Skip to content

fix(reports): report writers merge into a stale teamai-reports worktree #561

Description

@jimpablo

Problem

Report writers read, merge, and write their own per-member file inside the teamai-reports worktree, but never sync that worktree with origin first:

  • sessions/<user>/<month>.md (session save --push) — still stale
  • votes/<user>.yaml (Stop hook) — still stale
  • members/<user>.yaml (init / bootstrap) — still stale
  • stats/<user>.yaml / votes from reportUsageToTeam — still stale when that function runs without a prior refresh

commitAndPushReports only fetches and rebases after a push is rejected. Its comment assumes rebase conflicts are effectively impossible because each member writes only their own file. That is false when the same member reports from two checkouts: both write sessions/alice/… (or stats/alice.yaml, votes/alice.yaml).

When that happens, the merge starts from a stale copy of the member's own file. The push is rejected, the rebase conflicts on that file, and the new entry never reaches origin.

#560 (merged as 1734c31) already:

Unstick ≠ recover: a later members / pull refresh will not bring the lost session/vote/stats entry back.

Independent git clones have been affected since #489 (before it, the git-kind auto-report ran resetToCleanMaster + pullRepo before merging). Single-repo mode has been affected since #292.

Reproduction and actual result

Setup: built CLI, a local bare remote, two isolated HOMEs configured as the same member alice (machines A and B), independent git clone, user scope. Each HOME needs a dashboard events.jsonl entry for the --session-id being saved.

Precondition (required): A already has a reports worktree. Run teamai members on A first so ensureReportsWorktree later returns the existing checkout without fetching. This is the usual "both machines have been used" case. If A is a brand-new clone with no reports worktree, its first ensure fetches origin and the loss shows up on B's next write (alice-b1) instead of on alice-a1.

  1. A: teamai members (materialize a local reports worktree; do not refresh after B publishes)
  2. B: teamai session save --push --force --session-id alice-b0 --scope user
  3. A: teamai session save --push --force --session-id alice-a1 --scope user
  4. B: teamai session save --push --force --session-id alice-b1 --scope user

Expected: sessions/alice/<month>.md on teamai-reports contains alice-b0, alice-a1, and alice-b1.

Actual on current main (1734c31, includes #560): A prints Nothing new to push. Origin contains alice-b0 and alice-b1; alice-a1 is missing. A appended to a stale month log that did not contain alice-b0. The push was rejected, the fetch + rebase retry conflicted on that file, and the entry never reached origin.

Suggested fix

Before a writer merges into a per-member reports file, sync the reports worktree with origin under the reports lock, then merge, commit, and push. Reuse commitAndPushReports unless a single helper that does sync + write + push is clearly simpler.

Idle Stop / auto-report with nothing pending should not fetch.

Relevant code at 1734c31: src/save-session.ts:141-151, src/hook-handlers.ts:337-341, src/init.ts / src/bootstrap.ts member registration, src/team-push.ts:404-405, src/utils/reports-branch.ts (ensureReportsWorktree, commitAndPushReports).

Out of scope

Verification

Reproduced on main 1734c31 (Node 22, macOS) with the built CLI, a local bare remote, and two isolated HOMEs. With the members precondition on A, origin's month log has alice-b0 and alice-b1 and not alice-a1. Without that precondition, alice-a1 can land and alice-b1 is the entry that is dropped instead.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions