tooling: shepherd legacy chats toward ACP migration (closes the loop for #34)#36
Open
heavygee wants to merge 2 commits into
Open
tooling: shepherd legacy chats toward ACP migration (closes the loop for #34)#36heavygee wants to merge 2 commits into
heavygee wants to merge 2 commits into
Conversation
Operator hand-built this 361-line script on 2026-06-06 to recover a HAPI session whose `cursorSessionId` was set to NULL when the hub auto-archived on agent crash. The procedure (path-hash discovery against ~/.cursor/chats/<md5(path)>/, sqlite metadata patch, hapi-restart-hub, POST /api/sessions/<id>/resume) was used twice in the same session and works; committing before it gets clobbered by a `git clean` the way the attach scripts did last week. Why this matters for the ACP migration (PR #34 / upstream tiann#824): the migrator refuses sessions in `lifecycleState='running'` and is not designed to recover crashed sessions with `cursorSessionId=NULL`. A crashed legacy session has to be resurrected (back to `lifecycleState='inactive'` with `cursorSessionProtocol='stream-json'`) BEFORE `hapi cursor migrate <id>` becomes applicable. This script closes that gap. Surface: hapi-resurrect-session <hapi-session-id-or-prefix> [--cursor-uuid <uuid>] # skip auto-discovery [--symlink-old-path <old> --as <new>] # moved worktrees [--name '<friendly label>'] [--dry-run] [--no-restart-hub] Exit codes: 0 ok, 1 discovery failed, 2 sqlite patch failed, 3 resume call failed, 4 cursor-agent crashed within 8s of spawn. No new dependencies (Python 3 stdlib + sqlite3 + curl). Co-authored-by: Cursor <cursoragent@cursor.com>
…tach
Every legacy chat that lands via attach-agent-chat.sh comes in as
`cursorSessionProtocol = 'stream-json'` by definition (it came from
~/.cursor/chats/<wsh>/<uuid>/, the pre-ACP directory layout).
Without explicit shepherding, the operator burns 5-30K preamble
tokens on every subsequent resume.
This adds a non-fatal post-attach check that:
1. Reads the session's metadata.cursorSessionProtocol from sqlite
(after the hub spawn returns, so the row exists).
2. If it's anything other than 'acp', prints a one-block hint
pointing at #34's `hapi cursor migrate <id>` command.
3. Captures the resulting protocol in the JSON report
(`cursorSessionProtocol`) so wrapper scripts can act on it
programmatically.
The check is wrapped in try/catch and only fires for `agent=cursor`
attaches in non-dry-run mode. A protocol-check error never blocks
the attach (already-succeeded) and is surfaced as
`cursorProtocolCheckError` in the report instead.
Doesn't ship the `hapi cursor migrate` binary itself — that's #34's
lane. This just connects the find-attach-backfill pipeline to the
migration follow-up so the operator doesn't have to remember the
two-stage flow.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two-commit branch that aligns the find-attach-backfill pipeline with #34's ACP migrator so the end-to-end flow has no gaps.
tooling(resurrect): commitsscripts/tooling/hapi-resurrect-session.sh(361 lines, operator-authored 2026-06-06). Recovers HAPI sessions auto-archived on agent crash withcursorSessionId=NULL. Was untracked in the working tree - same disappearing-act risk asattach-agent-chat.shhad until last week.tooling(attach): adds a 28-line post-attach check that readsmetadata.cursorSessionProtocolfrom sqlite and prints ahapi cursor migrate <id>hint when the session lands asstream-json. Non-fatal, captures the protocol in the JSON report for wrapper scripts.Why this matters for #34
#34's migrator refuses sessions in
lifecycleState='running'and has no recovery path forcursorSessionId=NULL. A crashed legacy session has to be resurrected back tolifecycleState='inactive'BEFOREhapi cursor migrate <id>is applicable. The resurrect script closes that prerequisite gap.The post-attach hint closes the operator-UX gap on the other end: every freshly-attached cursor session is on legacy stream-json by definition (it came from
~/.cursor/chats/<wsh>/<uuid>/, the pre-ACP directory layout). Without an explicit nudge, operators leave sessions on the legacy path indefinitely and burn 5-30K preamble tokens on every resume.End-to-end flow (after #34 lands)
Refusal contract for
hapi-resurrect-session.sh/api/sessions/<id>/resumereturned non-2xxIdempotent: re-running on an already-resurrected session is safe. Dry-run prints the discovery + planned patch without writing.
Test plan
bash -n scripts/tooling/hapi-resurrect-session.shsyntax-checks--helpprints the documented usage blockattach-agent-chat.tsparses cleanly post-editscripts/backfill-agent-transcript.test.tsstill 8/8 passattach-agent-chat.tspost-attach hint code path against the spawn return path - confirmsessionToNameis the post-spawn HAPI session id, not the legacy chat UUIDhapi cursor migrateships on main, re-run the attach script and confirm the hint fires (it should, since attach lands as stream-json before migration)hapi-resurrect-session.sh --dry-run <known-archived-session>against a real archived row to confirm path-hash discovery still picks the right candidateWhat this does NOT do
hapi cursor migrate(that's feat(cursor): operator-driven legacy stream-json -> ACP session migrator (transplant) #34's lane).import --from-cursor-diskdiscovery for the 300+ Cursor IDE chats with no HAPI metadata row (feat(cursor): operator-driven legacy stream-json -> ACP session migrator (transplant) #34's explicit out-of-scope future work).attach-agent-chat.shis the manual equivalent today; can be wrapped into a discovery CLI later if friction warrants.Companion branch
tooling/backfill-truncation-warnings(commitaa223ee, pushed) — raises the backfillMAX_MESSAGEScap from 2000 to 50_000 and surfaces aBACKFILL TRUNCATEDwarning when transcripts exceed the cap. Should land first so attaches of large chats (jessica-story-class, 3k+ turns) aren't silently lossy before being migrated.Made with Cursor