{"record":{"id":"3c9277d8cc9e77ce","repo":"Yeachan-Heo/oh-my-codex","slug":"refusing-a-durable-ultragoal-mutation-before-writa","errorCode":null,"errorMessage":"Refusing a durable ultragoal mutation before writable lifecycle authority is restored: ${error.message} Restore the authoritative session binding so OMX_SESSION_ID matches the current session.json before retrying; see docs/troubleshooting.md (stale session pointer recovery).","messagePattern":"Refusing a durable ultragoal mutation before writable lifecycle authority is restored: (.+?) Restore the authoritative session binding so OMX_SESSION_ID matches the current session\\.json before retrying; see docs/troubleshooting\\.md \\(stale session pointer recovery\\)\\.","errorType":"exception","errorClass":"UltragoalError","httpStatus":null,"severity":"critical","filePath":"src/ultragoal/artifacts.ts","lineNumber":909,"sourceCode":"    };\n  } catch (error) {\n    // Existing-plan mutators keep the documented unbound compatibility path.\n    // Bootstrap callers opt out so failed state activation cannot create a new durable plan.\n    if (\n      error instanceof Error\n      && error.message === WRITABLE_STATE_SCOPE_ERRORS.unboundEnvironment\n      && options.allowUnboundEnvironment !== false\n    ) {\n      return { kind: 'no-pointer-compat' };\n    }\n    if (\n      error instanceof Error\n      && (\n        error.message === WRITABLE_STATE_SCOPE_ERRORS.unusableSession\n        || error.message === WRITABLE_STATE_SCOPE_ERRORS.unboundEnvironment\n      )\n    ) {\n      throw new UltragoalError(\n        `Refusing a durable ultragoal mutation before writable lifecycle authority is restored: ${error.message} Restore the authoritative session binding so OMX_SESSION_ID matches the current session.json before retrying; see docs/troubleshooting.md (stale session pointer recovery).`,\n      );\n    }\n    throw error;\n  }\n}\n\nfunction writableAuthorityEquals(\n  beforeLock: UltragoalWritableAuthority,\n  afterLock: UltragoalWritableAuthority,\n): boolean {\n  if (beforeLock.kind !== afterLock.kind) return false;\n  if (beforeLock.kind === 'no-pointer-compat') return true;\n  const resolvedAfterLock = afterLock as Extract<UltragoalWritableAuthority, { kind: 'resolved' }>;\n  return beforeLock.source === resolvedAfterLock.source\n    && beforeLock.sessionId === resolvedAfterLock.sessionId\n    && beforeLock.stateDir === resolvedAfterLock.stateDir;\n}","sourceCodeStart":891,"sourceCodeEnd":927,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/ultragoal/artifacts.ts#L891-L927","documentation":"A durable ultragoal mutation was blocked because assertUltragoalWritableLifecycleAuthority failed with either WRITABLE_STATE_SCOPE_ERRORS.unusableSession or unboundEnvironment. The wrapper converts these into an UltragoalError that explicitly refuses writes until the session binding is healed — the environment's OMX_SESSION_ID no longer matches the authoritative session.json, so writing now would corrupt ownership of durable state.","triggerScenarios":"Any durable ultragoal mutation API wrapped by this guard when OMX_SESSION_ID in the environment disagrees with the current session.json (unusableSession), or when the writable state scope has no session bound at all (unboundEnvironment) — e.g. reusing a shell from a previous session, resuming after a session restart, or exporting a stale OMX_SESSION_ID in CI.","commonSituations":"Long-lived terminal tabs where the session was rotated underneath; CI jobs caching environment variables between runs; scripts sourcing an old .env containing OMX_SESSION_ID; session.json rewritten by a new SessionStart while an old process still runs.","solutions":["Refresh the session binding so OMX_SESSION_ID equals the id in the current session.json (re-source the session env or restart from the launching shell)","If the old session is the correct authority, restore session.json to point at it instead of exporting a new id","Unset OMX_SESSION_ID if this context should be unbound-but-authorized, if your scope supports that mode","See docs/troubleshooting.md, section 'stale session pointer recovery', as the message itself directs"],"exampleFix":"# before\nexport OMX_SESSION_ID=old-session-id # stale\nomx ultragoal append --goal 'Fix::Thing' # refuses\n\n# after\nexport OMX_SESSION_ID=$(jq -r .sessionId .omx/session.json)\nomx ultragoal append --goal 'Fix::Thing'","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs';\n\nfunction sessionBindingIsCurrent(repoRoot: string): boolean {\n  const envId = process.env.OMX_SESSION_ID;\n  if (!envId) return false; // unboundEnvironment\n  try {\n    const session = JSON.parse(readFileSync(`${repoRoot}/.omx/session.json`, 'utf8'));\n    return session.sessionId === envId;\n  } catch {\n    return false;\n  }\n}","typeGuard":"function isLifecycleAuthorityError(e: unknown): boolean {\n  return e instanceof UltragoalError && e.message.includes('writable lifecycle authority is restored');\n}","tryCatchPattern":"try {\n  await mutateUltragoalState(...);\n} catch (e) {\n  if (isLifecycleAuthorityError(e)) {\n    await refreshSessionBinding(); // re-export OMX_SESSION_ID from session.json, then retry once\n    return mutateUltragoalState(...);\n  }\n  throw e;\n}","preventionTips":["Never hardcode or cache OMX_SESSION_ID across restarts; source it fresh from session.json","Restart shells after session rotation instead of reusing old env","Follow docs/troubleshooting.md stale session pointer recovery before retrying"],"tags":["ultragoal","session","lifecycle","stale-pointer","state-integrity"],"backgroundTag":"stale-session-id-binding","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}