feat(session-lock): identify Codex sessions by a root-bound thread-writer flock - #3469
Open
choppakatlakoushik001 wants to merge 6 commits into
Open
feat(session-lock): identify Codex sessions by a root-bound thread-writer flock#3469choppakatlakoushik001 wants to merge 6 commits into
choppakatlakoushik001 wants to merge 6 commits into
Conversation
…k verification docs
…-start and nudge docs
Confidence Score: 5/5The PR appears safe to merge within its explicitly stated scope, with no unacknowledged actionable defects identified. The changed consumers consistently treat the new Codex token as a validated opaque identity, ownership and contention preserve fail-closed semantics, and child launches clear inherited Codex markers; the relative-root limitation is explicitly deferred. Reviews (1): Last reviewed commit: "no-mistakes(document): align session-loc..." | Re-trigger Greptile |
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.
Intent
Ship only the core Codex session-lock identity capability on the updated firstmate baseline. Codex sandboxing can hide harness ancestry, so a confirmed-held Codex thread-writer flock is positive live-session evidence and must supply the home-lock identity. Bind both the verified thread id and the resolved Codex state root into a strict, unambiguous persisted identity; liveness and ownership of a recorded identity must use its bound root rather than re-resolving the checking process environment, and the same thread id under different roots must not collide. The settled three-state semantics are required: a missing or free writer lock is stale state 1, genuinely unevaluable state is uncertain state 2, and uncertainty remains live for contention so it cannot authorize lock theft. A confirmed-held Codex writer lock outranks inherited Claude, Pi, and Grok markers; uncertain Codex state does not win and falls back to the existing marker or ancestry path, with behavioral tests. Preserve the numeric non-Codex ancestry identity and liveness behavior. Keep direct consumers and dedicated behavioral tests needed for this core contract. This run explicitly defers rejecting relative Codex roots, macOS or no-flock portability work for the writer-lock test, the lease comment correction, and fm-lock identity-label deduplication; do not add those follow-ups here. The updated baseline has 15 documented pre-existing failing test scripts outside this core change; report but do not repair them. Keep park/codex-session-lock untouched, keep .no-mistakes untracked, keep bin scripts shellcheck-clean, add no agent co-author, ship a PR through no-mistakes, and never merge it.
What Changed
bin/fm-session-lock-lib.sh: resolve the Codex state root (CODEX_HOME, else$HOME/.codex), build/parse a strictcodex:<thread-id>:<state-root>lock record, and classify thethread-writer-locks/<thread-id>.lockflock into three states — held → live (stale-state 1 when absent/free, uncertain-state 2 when unevaluable, with uncertainty treated as live during contention). Newfm_session_identity,fm_session_identity_alive,fm_session_identity_valid, and thecodex:*branch offm_session_lock_owned_by_selfprefer a confirmed-held Codex writer lock over inherited Claude/Pi/Grok markers, bind liveness/ownership checks to the record's own root instead of re-resolving the current environment, and fall back to the unchanged numeric harness-ancestry path when Codex state is uncertain.bin/fm-harness.shnow detects a Codex session fromCODEX_THREAD_ID/CODEX_SESSION_IDplus a held writer flock;bin/fm-spawn.shstripsCODEX_THREAD_ID/CODEX_SESSION_IDfrom spawned child harnesses and the cursor launch template so a child cannot publish the parent's still-live identity.fm-lock.sh,fm-session-start.sh,fm-sessionstart-nudge.sh,fm-sessionstart-run.sh,fm-bootstrap.sh,fm-startup-network.sh, andfm-trace-context-lib.shthrough the shared session-identity helpers withcodex:*-aware status/error wording; tightenedfm-lease.shlock parsing to trim whitespace then require numeric. Updated architecture/scripts/nudge/verification docs and the Codex harness reference, and extended behavioral tests (fm-session-lock-ancestry,fm-session-start,fm-sessionstart-nudge,fm-spawn-dispatch-profile,fm-startup-network,fm-kimi-harness,fm-branch-supervision,fm-claude-stop-autoarm).Risk Assessment
✅ Low: Well-bounded, strictly additive Codex identity path gated on a flock proof with fail-closed uncertain handling; non-Codex path unchanged; consumers treat the token as opaque validated string; cross-root behavior is test-covered.
Testing
Baseline pipeline commands plus this phase: I ran the smallest relevant automated set — the dedicated fm-session-lock-ancestry suite and every modified session-identity consumer suite (claude-stop-autoarm, branch-supervision, kimi-harness, startup-network, spawn-dispatch-profile, trace-context-lib) — and all core-contract assertions pass, including the two new Codex tests. Automated pass alone is not sufficient, so I also drove the real bin/fm-lock.sh, bin/fm-harness.sh and bin/fm-session-lock-lib.sh end-to-end under a genuinely held flock and captured a CLI transcript showing a Codex session acquiring the home lock with hidden ancestry, the persisted codex:<thread>:<root> identity, live/stale status wording, codex harness detection, cross-root non-collision and lock-theft refusal, root-bound liveness from a foreign environment, and the unchanged non-Codex numeric identity. Two suites (fm-sessionstart-nudge, fm-session-start) each have one failing assertion; I traced both to host-environment causes (Node 22.22.1 cannot dynamically import a .ts file; a real /usr/bin/node defeats a fixture that deletes node from a fake PATH), confirmed both test functions are byte-identical at the base commit and touch no Codex session-lock code, so they are pre-existing baseline failures the intent says to report but not repair. This is a shell/CLI change with no rendered UI surface, so visual evidence does not apply; the CLI transcript is the reviewer-visible artifact. Overall result: the user intent is demonstrated working end-to-end with no regressions attributable to this change.Evidence: Codex session-lock identity — end-to-end CLI transcript
Source: Codex session-lock identity — end-to-end CLI transcript
# 2. fm-lock.sh: Codex session A acquires the per-home lock despite hidden ancestry lock acquired: session codex:thread-9f3a2b:/tmp/.../codex-state-A # 3. persisted identity binds thread id AND resolved Codex state root codex:thread-9f3a2b:/tmp/.../codex-state-A # 4. status -> lock: held by live session codex:thread-9f3a2b:/tmp/.../codex-state-A # 5. fm-harness.sh -> codex (ancestry hidden, verified by writer flock) # 6. same thread id under root B -> codex:thread-9f3a2b:/tmp/.../codex-state-B (distinct, no collision) # 7. session B (root B) -> error: another live firstmate session holds the lock (session codex:thread-9f3a2b:/tmp/.../codex-state-A) (exit 1) # 8. fm_session_identity_alive of A's identity, checked from root B env -> LIVE (uses bound root) # 9. after releasing A's writer flock -> lock: stale (session codex:thread-9f3a2b:/tmp/.../codex-state-A writer lock is free) # 10. non-Codex path -> numeric harness pid identity (unchanged)Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
tests/fm-sessionstart-nudge.test.sh:397- tests/fm-sessionstart-nudge.test.sh fails at 'Pi continuation classification' (expected exit 0, got 1). Pre-existing and unrelated to this change: the assertion runs node --input-type=module that dynamically import()s a .pi/extensions/*.ts file, and Node v22.22.1 on this host rejects it with 'Unknown file extension .ts'. The test function is byte-identical at base commit 355f46f and exercises no session-lock/Codex-identity code. Matches the intent's documented pre-existing baseline failures; report only, do not repair.tests/fm-session-start.test.sh:996- tests/fm-session-start.test.sh fails at test_output_ordering_diagnostics_lead ('MISSING diagnostic did not appear at all'). Pre-existing and unrelated to this change: the test does rm -f "$fakebin/node" to force a 'MISSING: node' bootstrap line, but this host has /usr/bin/node on the test's BASE_PATH, so command -v node still succeeds and the diagnostic is never emitted. This test function is byte-identical at base commit 355f46f (the branch only edited unrelated helper functions in this file) and does not touch Codex session-lock identity. Matches the intent's documented pre-existing baseline failures; report only, do not repair.bin/fm-test-run.sh tests/fm-session-lock-ancestry.test.sh — PASS (incl. new test_codex_writer_lock_supplies_identity_when_ancestry_is_hidden)bin/fm-test-run.sh tests/fm-claude-stop-autoarm.test.sh tests/fm-branch-supervision.test.sh tests/fm-kimi-harness.test.sh tests/fm-sessionstart-nudge.test.sh tests/fm-session-start.test.sh tests/fm-startup-network.test.sh tests/fm-spawn-dispatch-profile.test.sh tests/fm-trace-context-lib.test.sh — 6 PASS, 2 pre-existing env failures (fm-sessionstart-nudge 'Pi continuation classification', fm-session-start test_output_ordering_diagnostics_lead)Manual e2e against real bin/fm-lock.sh + bin/fm-harness.sh + bin/fm-session-lock-lib.sh with a real held flock: Codex acquire with hidden ancestry -> 'lock acquired: session codex:<thread>:<root>'; state/.lock content check; fm-lock.sh status live/stale wording; fm-harness.sh -> codex; same thread id under a second Codex root -> distinct identity; second root REFUSED the first root's home lock; fm_session_identity_alive resolves against the recorded root from a foreign env; writer-flock release -> stale; non-Codex fm_session_identity still returns a numeric pidVerified both failing test functions are byte-identical at base commit 355f46fe via git show 355f46fe:tests/... and reproduced their host-specific root causes (Node 22.22.1 rejects .ts dynamic import; /usr/bin/node present on BASE_PATH)Confirmed working tree clean, .no-mistakes/ untracked, no agent co-author trailers on the 5 branch commits✅ **Document** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.