fix: move-codex-session should handle Codex 0.160.1 and large native homes #132
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/move-codex-session-codex-0160"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The
move-codex-sessionscript refused every move on Codex 0.160.1 and could not run against a large native home. It now moves the per-thread tables 0.160.1 added (attachments, realtime items, queue revisions, stage-1 memory jobs), streams its unmoved-row check so a 1.6 GB history database works, and tolerates the legacy rollouts Codex records as skipped.It also fixes four ways a move could end half-done: a concurrent destination write misread as a trigger side effect, a masked disk-full error, history stranded around reverts and forks, and a destination change between copy and source deletion.
Moving a 32-thread tree out of a clone of a real native home and back left every row and rollout intact, apart from regenerated log row IDs.
move-codex-sessionshould handle Codex 0.160.1 and large native homesReview
01M4H2GP9Y7V9GND1K25M4P77M— head170aee6a7ac2affb4b5cef2699a6192ba8abac65Review — j4k-oss/agent-skills @
40154724b6Scope: diff against base tree
21b532de61b1Status: dispatched — coverage complete (5/5 slots terminal)
Facts: current review-wide projection
Computed under:
Findings (6)
critical — Rollback deletes destination history even when the history copy failed
01M4H2MB9PP48NTKF5J0NPDZ7Vskills/move-codex-session/scripts/move-codex-session.ts(snippet)01M4H2QF754GRV534VQE42HTMF· valid: The exact-grounded cleanup arguments gate state IDs but pass history IDs unconditionally. The reviewer's concrete trace explains that a history INSERT conflict rolls back the copy before historyCopied becomes true, while stateCopied still enables cleanup and ownership checking is skipped for history. Its reported probe shows the independently inserted conflicting row survives the failed copy and is then deleted by cleanup. The related process-boundary claim still permits ancestor-process activity, so its narrower allowance does not refute this interleaving. Gate history deletion on historyCopied. This supports high severity for conditional data loss; critical overstates the demonstrated scope and reach. The probe is reviewer-reported, not independently reproduced.high — SKILL.md's list of refusals omits the new project-membership refusal and other refusals the script enforces
01M4H2KA4PZDF580K9XHQD4C3Tskills/move-codex-session/SKILL.md(snippet)01M4H2QF754GRV534VQE42HTMF· valid: The exact-grounded passage enumerates the script's refusals. The reviewer names the defining script and compares its conditions with the copy, including the project-membership refusal and three other omitted conditions. This satisfies the required set comparison and establishes an already inaccurate inventory, warranting high severity. Reported error messages supply the cause when a move fails, so a full refusal inventory adds no distinct operational value. Preserve the actionable source-idleness and destination-activity prerequisites, using the precise ancestry boundary established by the related claim; replace the remaining enumeration with a purpose statement and a precise script pointer. The proposed rewrite's possible loss of those prerequisites does not negate the established inventory defect.high — Source deletion guards state and history but can discard the only remaining auxiliary rows
01M4H2P36D6VPE1K504TAQ5E05skills/move-codex-session/scripts/move-codex-session.ts(snippet)01M4H2QF754GRV534VQE42HTMF· valid: The exact-grounded commit guard locks and compares destination state and history. The reviewer's trace establishes that auxiliary destination copies are verified earlier, before an await, but their source rows are subsequently deleted without retaining equivalent destination locks or rechecking their transferred contents. The reported probe deletes a copied goal before source deletion and finds the goal absent from both homes after a successful return. Auxiliary snapshots protecting unrelated source rows do not protect that destination recovery copy. Permitted ancestor-process activity leaves the interleaving possible; its unknown frequency does not refute the mechanism. Extend the commit guard to transferred auxiliary contents with appropriate key normalization and locks held through source commit. High severity is supported.medium — “Invoking process tree” overstates which active destination processes are allowed
01M4H2NJXVF1HPQ2QPTEEQYXWXskills/move-codex-session/SKILL.md(snippet)01M4H2QF754GRV534VQE42HTMF· valid: The exact-grounded phrase describes an invoking process tree, whereas the reported implementation walks only the script PID and its ancestors, with a separate allowance for its lock helpers. The reviewer supplies a concrete test comparison: a sibling destination holder is rejected while the invoking parent holding a descriptor is permitted. That establishes a plausible preparation mistake under the broader wording, rather than a merely missing definition. Describe permitted user-controlled activity as the script and its ancestors, retaining the active-source restriction; internal lock-helper allowances need not become another inventory for the reader. No supplied requirement establishes that the broader process-tree policy was an intentional decision overriding this implementation.medium — The rollback test name claims completeness over the script’s database set
01M4H2PTSH7WV19VM9FTPN47GFskills/move-codex-session/scripts/move-codex-session.test.ts(snippet)01M4H2QF754GRV534VQE42HTMF· valid: The exact-grounded test name promises rollback of every destination database. The reviewer names the defining script and lists state, thread_history, logs, goals, memories, and queue, explaining that the manually asserted copy currently matches with no differing member. The rubric expressly excludes completeness claims about a production-defined set from the test-name exception, even when the current body checks each member. This is therefore a medium maintenance-copy defect, not a demand for more test coverage or a naming preference. The proposed failure-trigger and rollback-outcome name preserves useful test-output meaning while leaving all regression assertions intact.low — The precision-loss test decrements twice and misses lossy snapshot encoding
01M4H2NZSQ64ECWNP23YVXHTDSskills/move-codex-session/scripts/move-codex-session.test.ts(snippet)01M4H2QF754GRV534VQE42HTMF· valid: The exact-grounded AFTER INSERT trigger has no single-thread condition. The reported fixture and copy trace insert two threads, decrementing 9007199254740993 twice to 9007199254740991. These endpoints remain distinguishable after Number conversion, so the stated lossy BigInt encoding regression still triggers refusal and leaves the test green. The reported mutation probe corroborates that mechanism; its lsof shim does not affect this arithmetic comparison. Restricting the trigger to one inserted thread makes both endpoints round to 9007199254740992, restoring the promised precision check while retaining refusal and rollback assertions. This is a concrete ineffective-test defect under the supplied test guidelines.Other claims
Coverage
Coverage pass: 01M4H2H5DR4BZ93RFR6BM1D6ND
Accounting: complete
Slot health: healthy
@ -8,3 +8,3 @@Move one top-level session and its descendant agent sessions without losing rollout, state, history, or index data. User instructions override this skill's defaults.The bundled script supports macOS and Linux and requires Node.js 24+, `lsof`, and Perl. Run it with the session ID and explicit source and destination Codex homes. It holds Codex-compatible thread-writer and rollout-maintenance locks, and refuses incompatible schemas, destination conflicts, child-only moves, an active source home, or a destination home active outside the invoking process tree; resolve the reported blocker instead of editing the databases by hand.The bundled script supports macOS and Linux and requires Node.js 24+, `lsof`, and Perl. Run it with the session ID and explicit source and destination Codex homes. It holds Codex-compatible thread-writer and rollout-maintenance locks, write-locks each destination database while copying into it (seconds on a large home, so a Codex writing there from the invoking process tree can see `database is locked`), and refuses incompatible schemas, destination conflicts, child-only moves, an active source home, or a destination home active outside the invoking process tree; resolve the reported blocker instead of editing the databases by hand.high — SKILL.md's list of refusals omits the new project-membership refusal and other refusals the script enforces
lens
restated-sets· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4H2KA4PZDF580K9XHQD4C3Tof review01M4H2GP9Y7V9GND1K25M4P77Mmedium — “Invoking process tree” overstates which active destination processes are allowed
lens
writing-quality· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4H2NJXVF1HPQ2QPTEEQYXWXof review01M4H2GP9Y7V9GND1K25M4P77M@ -751,0 +1327,8 @@`INSERT INTO rollout_migration_skipped_rollouts (migration_id, rollout_path, rollout_modified_at_ns)VALUES ('big', 'beyond-safe-integer.jsonl', 9007199254740993);CREATE TRIGGER nudge_timestampAFTER INSERT ON threadsBEGINUPDATE rollout_migration_skipped_rollouts SET rollout_modified_at_ns = rollout_modified_at_ns - 1;END;low — The precision-loss test decrements twice and misses lossy snapshot encoding
lens
test-trimming· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4H2NZSQ64ECWNP23YVXHTDSof review01M4H2GP9Y7V9GND1K25M4P77M@ -751,0 +1671,4 @@}});test("rolls back every destination database when a step after the queue copy fails", () => {medium — The rollback test name claims completeness over the script’s database set
lens
writing-quality· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4H2PTSH7WV19VM9FTPN47GFof review01M4H2GP9Y7V9GND1K25M4P77M@ -1535,0 +1819,9 @@// The compared destination rows must still be the ones the source commit stands behind: a writer that changed// or deleted them since the comparison would leave the session in neither home.try {destinationState.exec("BEGIN IMMEDIATE");destinationHistory.exec("BEGIN IMMEDIATE");const currentDigests: Array<[string, Record<string, string>, Record<string, string>]> = [["state", comparedStateDigests, movedRowDigests(destinationState, STATE_TABLES, threadIds, removableSectionIds)],["history", comparedHistoryDigests, movedRowDigests(destinationHistory, HISTORY_TABLES, historyIds.copy, [])],];high — Source deletion guards state and history but can discard the only remaining auxiliary rows
lens
general-bug· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4H2P36D6VPE1K504TAQ5E05of review01M4H2GP9Y7V9GND1K25M4P77M@ -1645,0 +1924,6 @@deleteDestinationDatabases(statePath,historyPath,stateCopied ? threadIds : [],historyIds,stateCopied ? newSectionIds : [],critical — Rollback deletes destination history even when the history copy failed
lens
general-bug· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4H2MB9PP48NTKF5J0NPDZ7Vof review01M4H2GP9Y7V9GND1K25M4P77Mmove-codex-sessionrollback should keep destination history rows it never copied #133move-codex-sessionskill should state which processes block a move #134move-codex-sessionrollback test for its trigger and outcome #135move-codex-sessionprecision test fire its trigger once #136Confirmed, and it predates this PR:
mainalso passes the moved thread IDs to the destination history rollback whenever the state copy committed. Tracked in #133, which deletes destination history only after the history copy commits. Its regression test has a destination writer commit a history row between the two copies; on this PR's head the rollback deletes that row.Confirmed: the script also refuses project-bound threads, unrecorded legacy rollouts, rollout paths outside the home and checksum mismatches, and the incomplete list predates this PR. Tracked in #134, which replaces the list with the two home-activity requirements a caller can act on and points to the script's error for every other refusal.
Confirmed:
ancestorProcessIdsallows only the script and its ancestors, so a process the invoking Codex started still blocks the move. The process-tree wording predates this PR. Tracked in #134, which states the ancestor rule in the skill.Agreed. Tracked in #135, which renames the test to "rolls back copied rows when index publication fails" and leaves its setup and assertions unchanged.
Confirmed with the mutation you described: with
encodeSqliteValuereturningNumber(value).toString(), the current test passes, and with the trigger limited to the root thread it fails because the move exits 0. Tracked in #136.move-codex-sessionrollback should keep destination history rows it never copied #133jercik referenced this pull request2026-10-09 20:07:59 +00:00
move-codex-sessiontable in the index-publication rollback test #137move-codex-sessionshould re-check goals, memories, queue and logs before deleting the source #138Confirmed, and it predates this PR:
main'sdeleteSourceDatabasesalso compares and write-locks only the destination state and history databases before committing the source deletion. Tracked in #138, which compares the goals, memories, queue and logs copies too and holds write locks on all six destination databases through the source commit. Its regression test deletes a destination goal after the comparison; on this PR's head the move exits 0 and deletes the source rows.move-codex-sessionleaks database connections when a later open throws #139move-codex-sessioncannot finish a move that fails after the source commit #142