Skip to content

fix(session): merge a diverged session index on pull and retry push once (#1133) - #1139

Merged
jeff-r2026 merged 7 commits into
Tencent:mainfrom
SaulMoro:fix/resolve-issue-1133
Oct 15, 2026
Merged

jeff-r2026 merged 7 commits into
Tencent:mainfrom
SaulMoro:fix/resolve-issue-1133

Conversation

@SaulMoro

@SaulMoro SaulMoro commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

When two machines archived sessions for the same repo, both changed sessions/repos/<repo>/_index.json, and teamai session pull stopped with a misleading "configured remote" error, depending on each member's pull.rebase. The pull is now an explicit merge, a conflict on session indexes alone is rebuilt from the session files, and session push pulls once and retries when the remote moved ahead.

 session pull
-  git pull                          -> conflict on _index.json, "configured remote" error
+  gitPull (git pull --no-rebase --ff, autostash off)
+    rebase / merge / unmerged files already there -> stop, print the step that finishes it
+      except a merge stopped only on session indexes -> finish it, then pull
+    only session indexes conflict  -> rebuild + commit the merge, under withSessionIndexLock
+    any other conflict             -> git merge --abort, name the files
 session push
-  git push rejected                 -> commit kept local, exit 1
+  rejected and behind remote        -> gitPull as above, push once more
+  any other rejection               -> unchanged
 failed git step
-  "Command failed: git pull ..."
+  git's own fatal:/error: line

Every _index.json write still goes through writeIndex, which leaves an unchanged index byte-identical, so a merged checkout stays clean on the next pull. A conflicted index takes its repoIdentity from the first side that recorded one, then from the directory name.

Closes #1133

Evidence

  • Before (main, 450be2aa, same script):
    (d) teamai session pull --all   Error: git pull failed in …/d: Command failed: git pull origin main
                                    Check that …/d is a git repository with a configured remote, then retry.   exit 1
        index lists only d's session; a second pull fails the same way
    
    After (8d8c66b5, built CLI, isolated HOME and git config, local bare remote, pull.rebase unset):
    (a) teamai session push --source claude-code --all -y        ✓ Pushed 1 session(s)            exit 0
    (d, remote unreachable) teamai session push ...              ✗ Remote push failed (local commit kept)  exit 1
    d vs origin/main: behind 1, ahead 1
    (d) teamai session pull --all   ✓ Merged remote sessions and rebuilt 1 conflicted session index(es)
                                    ✓ Pulled and indexed 2 session(s) across 1 repo(s)   exit 0
        no MERGE_HEAD, git status clean, index lists both sessions
    (d) teamai session pull --all   ✓ Pulled and indexed 2 session(s)                    exit 0
        _index.json sha256 identical across both pulls, git status clean
    
  • src/__tests__/session-sync-pull.test.ts (real git, local bare remote) fails on main and passes here. It covers a diverged index under pull.rebase unset/false/true and pull.ff=only; another file conflicting, with and without an index conflict; an earlier stopped merge, also when the remote moved on again; a stopped rebase; autostash config over local edits; a legacy _-folded repo directory; a conflicted side without a usable identity; the push retry (success, real conflict, hook rejection); and push --all skipping an unreadable session while merging a diverged index.
  • At 8d8c66b5: npx tsc --noEmit, npm run lint, npm run build pass; session unit files 468/468; E2E suite: 1259 passed, 1 failed (source-freshness-recall, which fails the same way on main on macOS: /private/var vs /var).
  • Not run locally: the gitlab/github providers and the Codex, CodeBuddy and OpenCode agents (left to CI), and git older than 2.27. Autostash is disabled with -c config rather than --no-autostash, which git pull before 2.27 rejects outside a rebase.

Merge Danger

Door: two-way

Revert restores the old pull and push. Merge commits the new pull created stay in team repos, which is ordinary git history.

Blast Radius: sessions

Only teamai session pull and teamai session push change. A member whose checkout holds a rebase, merge or unmerged files gets an explicit stop with the next step instead of a pull attempt. runGit now sets LANGUAGE=en so the quoted git reason is in English.

@SaulMoro
SaulMoro force-pushed the fix/resolve-issue-1133 branch from 8ef3259 to 13a15d1 Compare October 14, 2026 21:03
@SaulMoro SaulMoro changed the title fix(session): merge a diverged session index on pull and retry push once (#1133) [after #1135] fix(session): merge a diverged session index on pull and retry push once (#1133) Oct 14, 2026
@SaulMoro
SaulMoro marked this pull request as draft October 14, 2026 21:03
@SaulMoro
SaulMoro force-pushed the fix/resolve-issue-1133 branch 3 times, most recently from 2669d2e to a833eb8 Compare October 14, 2026 21:45
@github-actions

Copy link
Copy Markdown
  • [P2 non-blocking] Fetch after finishing a previously stopped merge — src/session-flow/sync.ts:1147. If a pull leaves an index merge pending while the lock is busy, and another machine pushes before the rerun, this early return only finishes the old merge. The command reports success without fetching the newer sessions. Finish the pending merge, then perform the requested pull.

  • [P3 nit] Try the other stage when repoIdentity is missing — src/session-flow/sync.ts:1195. If stage 2 contains valid JSON without repoIdentity, this returns undefined, ignoring stage 3’s identity and the directory fallback. The rebuilt index then omits its identity, so listAllRepoIdentities() skips it. Validate the field before returning.

The PR description documents sufficient testing, including representative built-CLI runs against a local bare remote. Deferred provider/agent coverage is not blocking. I did not run, build, or install anything.

@SaulMoro
SaulMoro force-pushed the fix/resolve-issue-1133 branch 3 times, most recently from 2430cd5 to 82a2151 Compare October 15, 2026 04:09
…nce (Tencent#1133)

gitPull ran a bare `git pull`, so the user's pull.rebase decided the
outcome: unset refused any divergence, false stopped mid-merge, true
stopped mid-rebase. It now merges explicitly, without rebase or
autostash. Conflicts only in `_index.json` are rebuilt from the session
files, keeping the identity the index recorded, and the merge is
committed. Any other conflict aborts the merge, and an unfinished
rebase, merge, or other git operation stops the pull untouched. Both
come back as a `stopped` result that names the next step.

gitPush pulls and pushes again once when the remote moved ahead, so a
second machine's push no longer leaves its commit stranded locally.
Git runs untranslated, so errors quote git's own reason line.
…ncent#1133)

A pull that stops on conflicted session indexes now returns them instead of rebuilding them. session pull and the push retry rebuild them and commit the merge inside withSessionIndexLock, while the network pull and push stay outside it. When the lock stays busy the merge is left in progress and the member is told to rerun `teamai session pull`, which finishes it.
@SaulMoro SaulMoro changed the title [after #1135] fix(session): merge a diverged session index on pull and retry push once (#1133) fix(session): merge a diverged session index on pull and retry push once (#1133) Oct 15, 2026
@SaulMoro
SaulMoro force-pushed the fix/resolve-issue-1133 branch from 82a2151 to 8d8c66b Compare October 15, 2026 10:02
@SaulMoro
SaulMoro marked this pull request as ready for review October 15, 2026 10:02
@github-actions

Copy link
Copy Markdown

No new confident findings in the available PR commit diff.

  • Both earlier findings are resolved: pending index merges are followed by the requested pull, and identity recovery tries the other stage before falling back to the directory name.
  • The PR description documents sufficient testing, including representative built-CLI runs. Deferred provider/agent coverage is not blocking.
  • Review limitation: the shallow checkout cannot resolve the specified three-dot diff (no merge base), and network access failed. I inspected the six PR commits after 450be2aa, but cannot certify that this exactly matches the requested scope.

I did not run, build, or install anything from the PR.

@github-actions

Copy link
Copy Markdown

No new confident findings in the specified three-dot diff.

  • Both earlier findings are resolved: finishing a pending index merge is followed by the requested pull, and identity recovery checks the other stage before falling back to the directory name.
  • The PR description documents sufficient testing, including representative built-CLI runs against a local bare remote. The record names an older commit than the head; this is a note, not blocking. Deferred provider/agent coverage is not blocking.
  • The exact requested diff resolved successfully. I did not run, build, or install anything from the PR.

@jeff-r2026
jeff-r2026 merged commit 762a888 into Tencent:main Oct 15, 2026
23 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

session pull stops on an _index.json conflict when two machines push the same repo

2 participants