Created
July 27, 2026 22:23
-
-
Save arikon/5a56d31b6cb8a695683299c9ac30754e to your computer and use it in GitHub Desktop.
oh-my-codex #3324: honor exact identity-indeterminate session binding
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
| From d1aeec6c78f7b2c9da23fb8e61a5c4481de72056 Mon Sep 17 00:00:00 2001 | |
| From: Sergey Belov <peimei@ya.ru> | |
| Date: Tue, 28 Jul 2026 00:22:36 +0200 | |
| Subject: [PATCH] fix(state): honor exact indeterminate session binding | |
| --- | |
| src/mcp/__tests__/state-paths.test.ts | 55 ++++++++++++++++++++++- | |
| src/mcp/state-paths.ts | 10 ++++- | |
| src/ultragoal/__tests__/artifacts.test.ts | 28 ++++++++++++ | |
| 3 files changed, 90 insertions(+), 3 deletions(-) | |
| diff --git a/src/mcp/__tests__/state-paths.test.ts b/src/mcp/__tests__/state-paths.test.ts | |
| index 90362c29..80170a61 100644 | |
| --- a/src/mcp/__tests__/state-paths.test.ts | |
| +++ b/src/mcp/__tests__/state-paths.test.ts | |
| @@ -1038,7 +1038,30 @@ describe('state paths', () => { | |
| await rm(wd, { recursive: true, force: true }); | |
| } | |
| }); | |
| - it('fails closed for an identity-indeterminate pointer even with an env binding', async () => { | |
| + it('binds an exact OMX_SESSION_ID when the authoritative pointer is identity-indeterminate', async () => { | |
| + const wd = await mkRealTemp('omx-writable-indeterminate-exact-env-'); | |
| + __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' }); | |
| + try { | |
| + const stateDir = getBaseStateDir(wd); | |
| + const sessionPath = join(stateDir, 'session.json'); | |
| + await mkdir(stateDir, { recursive: true }); | |
| + const pointerBody = JSON.stringify({ session_id: 'sess-current', cwd: wd, pid: 8388607 }); | |
| + await writeFile(sessionPath, pointerBody); | |
| + process.env.OMX_SESSION_ID = 'sess-current'; | |
| + | |
| + assert.deepEqual(await resolveWritableStateScope(wd), { | |
| + source: 'session', | |
| + sessionId: 'sess-current', | |
| + stateDir: join(stateDir, 'sessions', 'sess-current'), | |
| + }); | |
| + assert.equal(await readFile(sessionPath, 'utf-8'), pointerBody); | |
| + } finally { | |
| + __resetSessionPointerTransactionDependenciesForTests(); | |
| + await rm(wd, { recursive: true, force: true }); | |
| + } | |
| + }); | |
| + | |
| + it('fails closed for an identity-indeterminate pointer with a mismatched env binding', async () => { | |
| const wd = await mkRealTemp('omx-writable-indeterminate-env-'); | |
| __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' }); | |
| try { | |
| @@ -1162,6 +1185,36 @@ describe('writable state scope recovery and revalidation', () => { | |
| } | |
| }); | |
| + it('fails closed when the pointer bytes change during exact identity-indeterminate binding', async () => { | |
| + const wd = await mkRealTemp('omx-writable-unstable-indeterminate-binding-'); | |
| + __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' }); | |
| + try { | |
| + const stateDir = getBaseStateDir(wd); | |
| + const sessionPath = join(stateDir, 'session.json'); | |
| + await mkdir(stateDir, { recursive: true }); | |
| + await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-current', cwd: wd, pid: 8388607 })); | |
| + process.env.OMX_SESSION_ID = 'sess-current'; | |
| + __setWritableStateScopeTestHooksForTests({ | |
| + beforeRecoveryReread: async () => { | |
| + await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-replaced', cwd: wd })); | |
| + }, | |
| + }); | |
| + | |
| + await assert.rejects( | |
| + () => resolveWritableStateScope(wd), | |
| + (error: unknown) => { | |
| + assert.equal((error as Error).message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession); | |
| + return true; | |
| + }, | |
| + ); | |
| + assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false); | |
| + } finally { | |
| + __setWritableStateScopeTestHooksForTests({}); | |
| + __resetSessionPointerTransactionDependenciesForTests(); | |
| + await rm(wd, { recursive: true, force: true }); | |
| + } | |
| + }); | |
| + | |
| it('T12 leaves the stale-dead pointer and base state root entries unchanged during recovery', async () => { | |
| const wd = await mkRealTemp('omx-writable-pointer-immutable-'); | |
| __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' }); | |
| diff --git a/src/mcp/state-paths.ts b/src/mcp/state-paths.ts | |
| index 617a5108..7c0c3726 100644 | |
| --- a/src/mcp/state-paths.ts | |
| +++ b/src/mcp/state-paths.ts | |
| @@ -617,6 +617,8 @@ export function __setWritableStateScopeTestHooksForTests(hooks: WritableStateSco | |
| * - a stale-dead session.json yields to an explicit exact-current | |
| * OMX_SESSION_ID binding (the dead owner holds no authority; SessionStart | |
| * remains the only pointer writer); | |
| + * - an identity-indeterminate session.json accepts OMX_SESSION_ID only when it | |
| + * exactly matches the authoritative pointer's canonical session_id; | |
| * - root writes are allowed only when session.json is absent. | |
| */ | |
| export async function resolveWritableStateScope( | |
| @@ -647,6 +649,7 @@ export async function resolveWritableStateScope( | |
| const sessionPath = join(baseStateDir, 'session.json'); | |
| if (existsSync(sessionPath)) { | |
| const envSessionId = normalizeSessionId(process.env[OMX_SESSION_ID_ENV]); | |
| + const pointerSessionId = snapshot ? normalizeSessionId(snapshot.state.session_id) : undefined; | |
| if (snapshot && selectedDecisionSnapshotReadHookForTests) { | |
| selectedDecisionSnapshotReadHookForTests({ | |
| ordinal: ++selectedDecisionSnapshotReadOrdinalForTests, | |
| @@ -656,8 +659,11 @@ export async function resolveWritableStateScope( | |
| if ( | |
| envSessionId | |
| && snapshot | |
| - && normalizeSessionId(snapshot.state.session_id) | |
| - && liveness === 'stale-dead' | |
| + && pointerSessionId | |
| + && ( | |
| + liveness === 'stale-dead' | |
| + || (liveness === 'identity-indeterminate' && envSessionId === pointerSessionId) | |
| + ) | |
| ) { | |
| if (selectedPointerRecoveryHookForTests) await selectedPointerRecoveryHookForTests(); | |
| const reread = await readFile(sessionPath, 'utf-8').catch((error: NodeJS.ErrnoException) => { | |
| diff --git a/src/ultragoal/__tests__/artifacts.test.ts b/src/ultragoal/__tests__/artifacts.test.ts | |
| index c7240b48..77f13503 100644 | |
| --- a/src/ultragoal/__tests__/artifacts.test.ts | |
| +++ b/src/ultragoal/__tests__/artifacts.test.ts | |
| @@ -2833,6 +2833,34 @@ describe('ultragoal artifacts', () => { | |
| } | |
| }); | |
| }); | |
| + | |
| + it('allows complete-goals mutation when exact OMX_SESSION_ID binds an identity-indeterminate pointer', async () => { | |
| + await withTempRepo(async (cwd) => { | |
| + const previousEnv = process.env.OMX_SESSION_ID; | |
| + process.env.OMX_SESSION_ID = 'sess-current'; | |
| + __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' }); | |
| + try { | |
| + const stateDir = join(cwd, '.omx', 'state'); | |
| + await mkdir(stateDir, { recursive: true }); | |
| + await writeFile(join(stateDir, 'session.json'), JSON.stringify({ | |
| + session_id: 'sess-current', | |
| + cwd, | |
| + state_root: stateDir, | |
| + pid: 8388607, | |
| + })); | |
| + | |
| + await createUltragoalPlan(cwd, { brief: '- Ship the fix' }); | |
| + const result = await startNextUltragoal(cwd); | |
| + assert.equal(result.goal?.status, 'in_progress'); | |
| + assert.equal(result.goal?.id, 'G001-ship-the-fix'); | |
| + } finally { | |
| + if (typeof previousEnv === 'string') process.env.OMX_SESSION_ID = previousEnv; | |
| + else delete process.env.OMX_SESSION_ID; | |
| + __resetSessionPointerTransactionDependenciesForTests(); | |
| + } | |
| + }); | |
| + }); | |
| + | |
| it('gates every durable ultragoal mutator while the selected pointer is stale-dead and no exact session is bound', async () => { | |
| await withTempRepo(async (cwd) => { | |
| const previousEnv = process.env.OMX_SESSION_ID; | |
| -- | |
| 2.50.1 (Apple Git-155) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment