oh-my-codex 0.20.2 → 0.20.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +36 -18
- package/Cargo.toml +1 -1
- package/README.md +28 -2
- package/crates/omx-runtime/Cargo.toml +4 -0
- package/crates/omx-runtime/src/main.rs +415 -2
- package/crates/omx-runtime/tests/execution.rs +483 -0
- package/crates/omx-runtime-core/src/dispatch.rs +96 -10
- package/crates/omx-runtime-core/src/engine.rs +839 -29
- package/crates/omx-runtime-core/src/lib.rs +8 -0
- package/dist/adapt/__tests__/herdr-target.test.d.ts +2 -0
- package/dist/adapt/__tests__/herdr-target.test.d.ts.map +1 -0
- package/dist/adapt/__tests__/herdr-target.test.js +72 -0
- package/dist/adapt/__tests__/herdr-target.test.js.map +1 -0
- package/dist/adapt/contracts.d.ts +1 -1
- package/dist/adapt/contracts.d.ts.map +1 -1
- package/dist/adapt/contracts.js +1 -1
- package/dist/adapt/contracts.js.map +1 -1
- package/dist/adapt/herdr/__tests__/authority.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/authority.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/authority.test.js +49 -0
- package/dist/adapt/herdr/__tests__/authority.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/bridge.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/bridge.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/bridge.test.js +176 -0
- package/dist/adapt/herdr/__tests__/bridge.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/sanitize.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/sanitize.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/sanitize.test.js +45 -0
- package/dist/adapt/herdr/__tests__/sanitize.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/semantic.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/semantic.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/semantic.test.js +130 -0
- package/dist/adapt/herdr/__tests__/semantic.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/seq-store.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/seq-store.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/seq-store.test.js +54 -0
- package/dist/adapt/herdr/__tests__/seq-store.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/socket-live.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/socket-live.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/socket-live.test.js +104 -0
- package/dist/adapt/herdr/__tests__/socket-live.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/team-map.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/team-map.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/team-map.test.js +46 -0
- package/dist/adapt/herdr/__tests__/team-map.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/transport.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/transport.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/transport.test.js +160 -0
- package/dist/adapt/herdr/__tests__/transport.test.js.map +1 -0
- package/dist/adapt/herdr/__tests__/wiring.test.d.ts +2 -0
- package/dist/adapt/herdr/__tests__/wiring.test.d.ts.map +1 -0
- package/dist/adapt/herdr/__tests__/wiring.test.js +118 -0
- package/dist/adapt/herdr/__tests__/wiring.test.js.map +1 -0
- package/dist/adapt/herdr/authority.d.ts +34 -0
- package/dist/adapt/herdr/authority.d.ts.map +1 -0
- package/dist/adapt/herdr/authority.js +71 -0
- package/dist/adapt/herdr/authority.js.map +1 -0
- package/dist/adapt/herdr/bridge.d.ts +84 -0
- package/dist/adapt/herdr/bridge.d.ts.map +1 -0
- package/dist/adapt/herdr/bridge.js +222 -0
- package/dist/adapt/herdr/bridge.js.map +1 -0
- package/dist/adapt/herdr/sanitize.d.ts +20 -0
- package/dist/adapt/herdr/sanitize.d.ts.map +1 -0
- package/dist/adapt/herdr/sanitize.js +70 -0
- package/dist/adapt/herdr/sanitize.js.map +1 -0
- package/dist/adapt/herdr/semantic.d.ts +67 -0
- package/dist/adapt/herdr/semantic.d.ts.map +1 -0
- package/dist/adapt/herdr/semantic.js +170 -0
- package/dist/adapt/herdr/semantic.js.map +1 -0
- package/dist/adapt/herdr/seq-store.d.ts +32 -0
- package/dist/adapt/herdr/seq-store.d.ts.map +1 -0
- package/dist/adapt/herdr/seq-store.js +126 -0
- package/dist/adapt/herdr/seq-store.js.map +1 -0
- package/dist/adapt/herdr/team-map.d.ts +30 -0
- package/dist/adapt/herdr/team-map.d.ts.map +1 -0
- package/dist/adapt/herdr/team-map.js +37 -0
- package/dist/adapt/herdr/team-map.js.map +1 -0
- package/dist/adapt/herdr/transport.d.ts +115 -0
- package/dist/adapt/herdr/transport.d.ts.map +1 -0
- package/dist/adapt/herdr/transport.js +260 -0
- package/dist/adapt/herdr/transport.js.map +1 -0
- package/dist/adapt/herdr/wiring.d.ts +24 -0
- package/dist/adapt/herdr/wiring.d.ts.map +1 -0
- package/dist/adapt/herdr/wiring.js +62 -0
- package/dist/adapt/herdr/wiring.js.map +1 -0
- package/dist/adapt/herdr.d.ts +19 -0
- package/dist/adapt/herdr.d.ts.map +1 -0
- package/dist/adapt/herdr.js +115 -0
- package/dist/adapt/herdr.js.map +1 -0
- package/dist/adapt/index.d.ts +4 -0
- package/dist/adapt/index.d.ts.map +1 -1
- package/dist/adapt/index.js +48 -0
- package/dist/adapt/index.js.map +1 -1
- package/dist/adapt/registry.d.ts.map +1 -1
- package/dist/adapt/registry.js +11 -0
- package/dist/adapt/registry.js.map +1 -1
- package/dist/agents/__tests__/definitions.test.js +81 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +25 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/native-config.d.ts +2 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js.map +1 -1
- package/dist/auth/__tests__/hotswap.test.js +60 -1
- package/dist/auth/__tests__/hotswap.test.js.map +1 -1
- package/dist/auth/__tests__/storage.test.js +33 -1
- package/dist/auth/__tests__/storage.test.js.map +1 -1
- package/dist/auth/hotswap.d.ts +22 -2
- package/dist/auth/hotswap.d.ts.map +1 -1
- package/dist/auth/hotswap.js +107 -22
- package/dist/auth/hotswap.js.map +1 -1
- package/dist/auth/storage.js +1 -1
- package/dist/auth/storage.js.map +1 -1
- package/dist/autopilot/__tests__/ralplan-gate.test.js +86 -1333
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
- package/dist/autopilot/ralplan-gate.d.ts.map +1 -1
- package/dist/autopilot/ralplan-gate.js +7 -6
- package/dist/autopilot/ralplan-gate.js.map +1 -1
- package/dist/cli/__tests__/agents-init.test.js +4 -23
- package/dist/cli/__tests__/agents-init.test.js.map +1 -1
- package/dist/cli/__tests__/api.test.js +61 -24
- package/dist/cli/__tests__/api.test.js.map +1 -1
- package/dist/cli/__tests__/auth.test.js +63 -7
- package/dist/cli/__tests__/auth.test.js.map +1 -1
- package/dist/cli/__tests__/codex-feature-probe.test.js +66 -1
- package/dist/cli/__tests__/codex-feature-probe.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +150 -2
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/detached-leader-teardown.test.d.ts +2 -0
- package/dist/cli/__tests__/detached-leader-teardown.test.d.ts.map +1 -0
- package/dist/cli/__tests__/detached-leader-teardown.test.js +473 -0
- package/dist/cli/__tests__/detached-leader-teardown.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-process-identity-readiness.test.js +103 -0
- package/dist/cli/__tests__/doctor-process-identity-readiness.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-state-root-binding.test.js +139 -0
- package/dist/cli/__tests__/doctor-state-root-binding.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +135 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +211 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +878 -463
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +1290 -127
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-parity.test.js +8 -4
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/native-assets.test.js +398 -16
- package/dist/cli/__tests__/native-assets.test.js.map +1 -1
- package/dist/cli/__tests__/native-hook-claim-journal.test.js +132 -6
- package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -3
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +3 -3
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +49 -164
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts +2 -0
- package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralplan-child-binding-3212.test.js +56 -0
- package/dist/cli/__tests__/ralplan-child-binding-3212.test.js.map +1 -0
- package/dist/cli/__tests__/ralplan.test.js +107 -109
- package/dist/cli/__tests__/ralplan.test.js.map +1 -1
- package/dist/cli/__tests__/resume.test.js +11 -10
- package/dist/cli/__tests__/resume.test.js.map +1 -1
- package/dist/cli/__tests__/session-scoped-runtime.test.js +1118 -43
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
- package/dist/cli/__tests__/session-search-help.test.js +25 -1
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +8 -55
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +224 -7
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +93 -41
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +150 -8
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +117 -2
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +95 -4
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +669 -177
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +33 -2
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
- package/dist/cli/api.d.ts.map +1 -1
- package/dist/cli/api.js +9 -10
- package/dist/cli/api.js.map +1 -1
- package/dist/cli/codex-feature-probe.d.ts +16 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -1
- package/dist/cli/codex-feature-probe.js +44 -0
- package/dist/cli/codex-feature-probe.js.map +1 -1
- package/dist/cli/codex-home.d.ts.map +1 -1
- package/dist/cli/codex-home.js +7 -4
- package/dist/cli/codex-home.js.map +1 -1
- package/dist/cli/doctor.d.ts +20 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +290 -3
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +234 -12
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2409 -746
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +2 -2
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/native-assets.d.ts +25 -0
- package/dist/cli/native-assets.d.ts.map +1 -1
- package/dist/cli/native-assets.js +448 -51
- package/dist/cli/native-assets.js.map +1 -1
- package/dist/cli/native-hook-claim-journal.d.ts +20 -5
- package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
- package/dist/cli/native-hook-claim-journal.js +67 -32
- package/dist/cli/native-hook-claim-journal.js.map +1 -1
- package/dist/cli/package-manager-ownership.d.ts +63 -0
- package/dist/cli/package-manager-ownership.d.ts.map +1 -0
- package/dist/cli/package-manager-ownership.js +323 -0
- package/dist/cli/package-manager-ownership.js.map +1 -0
- package/dist/cli/ralph.js +2 -2
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/ralplan.d.ts +5 -7
- package/dist/cli/ralplan.d.ts.map +1 -1
- package/dist/cli/ralplan.js +83 -134
- package/dist/cli/ralplan.js.map +1 -1
- package/dist/cli/session-search.d.ts +5 -0
- package/dist/cli/session-search.d.ts.map +1 -1
- package/dist/cli/session-search.js +87 -0
- package/dist/cli/session-search.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +15 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +27 -1
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +119 -47
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/sparkshell.d.ts.map +1 -1
- package/dist/cli/sparkshell.js +52 -9
- package/dist/cli/sparkshell.js.map +1 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +2 -2
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/uninstall.d.ts +9 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +71 -30
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update-worker.d.ts +2 -0
- package/dist/cli/update-worker.d.ts.map +1 -0
- package/dist/cli/update-worker.js +142 -0
- package/dist/cli/update-worker.js.map +1 -0
- package/dist/cli/update.d.ts +14 -22
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +192 -241
- package/dist/cli/update.js.map +1 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +503 -30
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +5 -3
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/models.test.js +67 -3
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/generator.d.ts +27 -21
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +610 -152
- package/dist/config/generator.js.map +1 -1
- package/dist/config/models.d.ts +12 -2
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +15 -1
- package/dist/config/models.js.map +1 -1
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +25 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.js +2 -0
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +5 -3
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -4
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts +2 -0
- package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js +172 -0
- package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js.map +1 -0
- package/dist/hooks/__tests__/keyword-detector.test.js +176 -37
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +402 -545
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +39 -4
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +161 -26
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +27 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +10 -118
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +7 -0
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +533 -14
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +159 -24
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +2 -1
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +44 -4
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js +9 -0
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/session.test.js +3130 -365
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/agents-overlay.js +1 -1
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +108 -2
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/sdk.test.js +151 -1
- package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js +20 -3
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/extensibility/plugin-runner.js +1 -0
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
- package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
- package/dist/hooks/extensibility/runtime.js.map +1 -1
- package/dist/hooks/extensibility/sdk/paths.d.ts +1 -1
- package/dist/hooks/extensibility/sdk/paths.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk/paths.js +2 -2
- package/dist/hooks/extensibility/sdk/paths.js.map +1 -1
- package/dist/hooks/extensibility/sdk/runtime-state.d.ts +1 -1
- package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk/runtime-state.js +55 -15
- package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -1
- package/dist/hooks/extensibility/sdk.d.ts +1 -0
- package/dist/hooks/extensibility/sdk.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk.js +1 -1
- package/dist/hooks/extensibility/sdk.js.map +1 -1
- package/dist/hooks/extensibility/types.d.ts +7 -0
- package/dist/hooks/extensibility/types.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +10 -3
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +116 -20
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/session.d.ts +204 -14
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +1500 -223
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +6 -6
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +26 -16
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +83 -78
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +36 -31
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +155 -198
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/tmux.d.ts +42 -4
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +1017 -139
- package/dist/hud/tmux.js.map +1 -1
- package/dist/leader/__tests__/contract.test.js +124 -37
- package/dist/leader/__tests__/contract.test.js.map +1 -1
- package/dist/leader/contract.d.ts +17 -6
- package/dist/leader/contract.d.ts.map +1 -1
- package/dist/leader/contract.js +102 -26
- package/dist/leader/contract.js.map +1 -1
- package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
- package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
- package/dist/mcp/__tests__/hermes-bridge.test.js +17 -0
- package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +4 -4
- package/dist/mcp/__tests__/state-paths.test.js +735 -4
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +1 -1
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/__tests__/trace-server.test.js +2 -2
- package/dist/mcp/__tests__/trace-server.test.js.map +1 -1
- package/dist/mcp/__tests__/wiki-server.test.js +18 -0
- package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +13 -3
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/mcp/hermes-bridge.d.ts.map +1 -1
- package/dist/mcp/hermes-bridge.js +2 -2
- package/dist/mcp/hermes-bridge.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +78 -4
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +543 -40
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/wiki-server.d.ts +11 -0
- package/dist/mcp/wiki-server.d.ts.map +1 -1
- package/dist/mcp/wiki-server.js +9 -2
- package/dist/mcp/wiki-server.js.map +1 -1
- package/dist/modes/__tests__/base-autopilot-gates.test.js +36 -7
- package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -1
- package/dist/modes/__tests__/base-multi-state-compat.test.js +1 -1
- package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +17 -8
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts +5 -5
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +76 -21
- package/dist/modes/base.js.map +1 -1
- package/dist/native-assets/archive.d.ts +17 -0
- package/dist/native-assets/archive.d.ts.map +1 -0
- package/dist/native-assets/archive.js +238 -0
- package/dist/native-assets/archive.js.map +1 -0
- package/dist/native-assets/policy.d.ts +42 -0
- package/dist/native-assets/policy.d.ts.map +1 -0
- package/dist/native-assets/policy.js +155 -0
- package/dist/native-assets/policy.js.map +1 -0
- package/dist/notifications/temp-contract.d.ts.map +1 -1
- package/dist/notifications/temp-contract.js +4 -0
- package/dist/notifications/temp-contract.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +164 -42
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +72 -155
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +124 -18
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
- package/dist/pipeline/stages/ralplan.js +36 -8
- package/dist/pipeline/stages/ralplan.js.map +1 -1
- package/dist/ralplan/__tests__/consensus-gate.test.js +73 -1316
- package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js +335 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
- package/dist/ralplan/__tests__/runtime.test.js +85 -101
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts +9 -1
- package/dist/ralplan/consensus-gate.d.ts.map +1 -1
- package/dist/ralplan/consensus-gate.js +82 -338
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/ralplan/documented-leader-preflight.d.ts +41 -0
- package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
- package/dist/ralplan/documented-leader-preflight.js +360 -0
- package/dist/ralplan/documented-leader-preflight.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +2 -1
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +67 -168
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/runtime/__tests__/bridge.test.js +42 -1
- package/dist/runtime/__tests__/bridge.test.js.map +1 -1
- package/dist/runtime/bridge.d.ts +12 -0
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +52 -1
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/runtime/run-state.d.ts +5 -1
- package/dist/runtime/run-state.d.ts.map +1 -1
- package/dist/runtime/run-state.js +15 -8
- package/dist/runtime/run-state.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +16323 -8978
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts +2 -0
- package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js +225 -0
- package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js.map +1 -0
- package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts +2 -0
- package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js +188 -0
- package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js.map +1 -0
- package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts +2 -0
- package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js +259 -0
- package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js.map +1 -0
- package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts +2 -0
- package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js +491 -0
- package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js.map +1 -0
- package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts +2 -0
- package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js +708 -0
- package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js.map +1 -0
- package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts +2 -0
- package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js +208 -0
- package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-state-io.test.js +26 -0
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-tmux-injection.test.js +23 -1
- package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -1
- package/dist/scripts/__tests__/postinstall.test.js +19 -1
- package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +63 -173
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +74 -159
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +404 -13
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts +2 -0
- package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/verify-native-release-assets.test.js +235 -0
- package/dist/scripts/__tests__/verify-native-release-assets.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts +53 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +14448 -1480
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts +9 -0
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +35 -12
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/generate-native-release-manifest.js +80 -51
- package/dist/scripts/generate-native-release-manifest.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +78 -115
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +74 -3
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +5 -0
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts +9 -0
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +234 -79
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +71 -16
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +12 -4
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.js +42 -21
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts +3 -0
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +82 -33
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +1 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +32 -3
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +79 -82
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/postinstall-advisory.d.ts +14 -0
- package/dist/scripts/postinstall-advisory.d.ts.map +1 -0
- package/dist/scripts/postinstall-advisory.js +49 -0
- package/dist/scripts/postinstall-advisory.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +1 -1
- package/dist/scripts/postinstall.d.ts.map +1 -1
- package/dist/scripts/postinstall.js +1 -1
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +80 -4
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +3162 -26
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +16 -1
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/verify-native-release-assets.js +37 -23
- package/dist/scripts/verify-native-release-assets.js.map +1 -1
- package/dist/state/__tests__/mode-state-context.test.js +61 -0
- package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +462 -850
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +400 -2
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/mode-state-context.d.ts +8 -0
- package/dist/state/mode-state-context.d.ts.map +1 -1
- package/dist/state/mode-state-context.js +73 -0
- package/dist/state/mode-state-context.js.map +1 -1
- package/dist/state/operations.d.ts +3 -0
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +144 -40
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +18 -1
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +420 -23
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +3 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +10 -4
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +3 -1
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +53 -247
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
- package/dist/subagents/__tests__/tracker.test.js +837 -1048
- package/dist/subagents/__tests__/tracker.test.js.map +1 -1
- package/dist/subagents/tracker.d.ts +58 -135
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +811 -632
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +91 -1
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +58 -17
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
- package/dist/team/__tests__/idle-nudge.test.js +45 -15
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
- package/dist/team/__tests__/mcp-comm.test.js +197 -30
- package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +110 -3
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/notice-ledger.test.d.ts +2 -0
- package/dist/team/__tests__/notice-ledger.test.d.ts.map +1 -0
- package/dist/team/__tests__/notice-ledger.test.js +131 -0
- package/dist/team/__tests__/notice-ledger.test.js.map +1 -0
- package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts +2 -0
- package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts.map +1 -0
- package/dist/team/__tests__/pane-teardown-residue-e2e.test.js +410 -0
- package/dist/team/__tests__/pane-teardown-residue-e2e.test.js.map +1 -0
- package/dist/team/__tests__/phase-controller.test.js +20 -0
- package/dist/team/__tests__/phase-controller.test.js.map +1 -1
- package/dist/team/__tests__/runtime-cli.test.js +9 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +3963 -428
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +2405 -203
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +117 -2
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +804 -36
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.js +6 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +4099 -1039
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-source-authority-realtmux.test.js +149 -0
- package/dist/team/__tests__/tmux-source-authority-realtmux.test.js.map +1 -0
- package/dist/team/__tests__/tmux-test-fixture.d.ts +69 -0
- package/dist/team/__tests__/tmux-test-fixture.d.ts.map +1 -1
- package/dist/team/__tests__/tmux-test-fixture.js +242 -15
- package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
- package/dist/team/__tests__/tmux-test-fixture.test.js +177 -1
- package/dist/team/__tests__/tmux-test-fixture.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +53 -44
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/__tests__/worktree.test.js +6 -0
- package/dist/team/__tests__/worktree.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +15 -9
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/exact-pane.d.ts +23 -0
- package/dist/team/exact-pane.d.ts.map +1 -0
- package/dist/team/exact-pane.js +133 -0
- package/dist/team/exact-pane.js.map +1 -0
- package/dist/team/idle-nudge.d.ts +12 -1
- package/dist/team/idle-nudge.d.ts.map +1 -1
- package/dist/team/idle-nudge.js +41 -14
- package/dist/team/idle-nudge.js.map +1 -1
- package/dist/team/model-contract.d.ts +2 -5
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +59 -17
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/notice-ledger.d.ts +54 -0
- package/dist/team/notice-ledger.d.ts.map +1 -0
- package/dist/team/notice-ledger.js +259 -0
- package/dist/team/notice-ledger.js.map +1 -0
- package/dist/team/phase-controller.d.ts.map +1 -1
- package/dist/team/phase-controller.js +2 -0
- package/dist/team/phase-controller.js.map +1 -1
- package/dist/team/runtime.d.ts +4 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +1527 -291
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts +13 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +1503 -387
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +26 -8
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/state/locks.d.ts.map +1 -1
- package/dist/team/state/locks.js +61 -13
- package/dist/team/state/locks.js.map +1 -1
- package/dist/team/state/monitor.d.ts +10 -0
- package/dist/team/state/monitor.d.ts.map +1 -1
- package/dist/team/state/monitor.js +13 -0
- package/dist/team/state/monitor.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +4 -3
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state/types.d.ts +15 -0
- package/dist/team/state/types.d.ts.map +1 -1
- package/dist/team/state/types.js.map +1 -1
- package/dist/team/state-root.d.ts +12 -0
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +177 -0
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts +85 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +672 -129
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +5 -0
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +4 -0
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +163 -27
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +1682 -376
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +4 -0
- package/dist/team/worktree.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +950 -2
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +1 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts +35 -1
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +232 -46
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
- package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
- package/dist/utils/__tests__/file-durability.test.js +114 -0
- package/dist/utils/__tests__/file-durability.test.js.map +1 -0
- package/dist/utils/__tests__/paths.test.js +21 -1
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/file-durability.d.ts +25 -0
- package/dist/utils/file-durability.d.ts.map +1 -0
- package/dist/utils/file-durability.js +67 -0
- package/dist/utils/file-durability.js.map +1 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +14 -6
- package/dist/utils/paths.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +49 -4
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js +60 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
- package/dist/verification/__tests__/native-release-manifest.test.js +157 -4
- package/dist/verification/__tests__/native-release-manifest.test.js.map +1 -1
- package/dist/wiki/lint.d.ts +4 -1
- package/dist/wiki/lint.d.ts.map +1 -1
- package/dist/wiki/lint.js +3 -2
- package/dist/wiki/lint.js.map +1 -1
- package/package.json +13 -5
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +105 -17
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +13 -5
- package/plugins/oh-my-codex/skills/cancel/SKILL.md +30 -85
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -4
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +16 -17
- package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +3 -2
- package/skills/autopilot/SKILL.md +13 -5
- package/skills/cancel/SKILL.md +30 -85
- package/skills/ralph/SKILL.md +6 -4
- package/skills/ralplan/SKILL.md +16 -17
- package/skills/team/SKILL.md +13 -9
- package/skills/ultragoal/SKILL.md +3 -2
- package/src/scripts/__tests__/codex-native-hook.test.ts +8831 -951
- package/src/scripts/__tests__/issue-3293-callsite-parity.test.ts +187 -0
- package/src/scripts/__tests__/issue-3293-cancel-transaction.test.ts +189 -0
- package/src/scripts/__tests__/issue-3293-hook-owned-cancel.test.ts +187 -0
- package/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts +591 -0
- package/src/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.ts +701 -0
- package/src/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.ts +211 -0
- package/src/scripts/__tests__/notify-state-io.test.ts +29 -0
- package/src/scripts/__tests__/notify-tmux-injection.test.ts +26 -1
- package/src/scripts/__tests__/postinstall.test.ts +23 -1
- package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
- package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +67 -185
- package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +79 -178
- package/src/scripts/__tests__/smoke-packed-install.test.ts +525 -16
- package/src/scripts/__tests__/verify-native-release-assets.test.ts +240 -0
- package/src/scripts/codex-native-hook.ts +14238 -1429
- package/src/scripts/codex-native-pre-post.ts +43 -12
- package/src/scripts/generate-native-release-manifest.ts +83 -79
- package/src/scripts/notify-fallback-watcher.ts +91 -122
- package/src/scripts/notify-hook/auto-nudge.ts +71 -3
- package/src/scripts/notify-hook/state-io.ts +11 -0
- package/src/scripts/notify-hook/team-dispatch.ts +242 -75
- package/src/scripts/notify-hook/team-leader-nudge.ts +72 -22
- package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
- package/src/scripts/notify-hook/team-worker-stop.ts +43 -20
- package/src/scripts/notify-hook/team-worker.ts +82 -31
- package/src/scripts/notify-hook/tmux-injection.ts +33 -3
- package/src/scripts/notify-hook.ts +84 -82
- package/src/scripts/postinstall-advisory.ts +67 -0
- package/src/scripts/postinstall.ts +1 -1
- package/src/scripts/smoke-packed-install.ts +3608 -39
- package/src/scripts/sync-plugin-mirror.ts +17 -1
- package/src/scripts/verify-native-release-assets.ts +39 -31
- package/templates/AGENTS.md +1 -0
- package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +0 -2
- package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +0 -1
- package/dist/subagents/__tests__/adapted-role-binding.test.js +0 -988
- package/dist/subagents/__tests__/adapted-role-binding.test.js.map +0 -1
- package/dist/subagents/adapted-role-binding.d.ts +0 -17
- package/dist/subagents/adapted-role-binding.d.ts.map +0 -1
- package/dist/subagents/adapted-role-binding.js +0 -75
- package/dist/subagents/adapted-role-binding.js.map +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { mkdir, mkdtemp, realpath, rm, symlink, writeFile } from 'fs/promises';
|
|
3
|
+
import { mkdir, mkdtemp, readFile, readdir, realpath, rm, symlink, writeFile } from 'fs/promises';
|
|
4
4
|
import { existsSync } from 'fs';
|
|
5
5
|
import { tmpdir } from 'os';
|
|
6
6
|
import { join, resolve as resolvePath } from 'path';
|
|
7
|
-
import { getAllScopedStateDirs, getAllScopedStatePaths, getBaseStateDir, getBaseStateDirWithSource, getAllSessionScopedStateDirs, getAllSessionScopedStatePaths, getReadScopedStateFilePaths, readCurrentSessionId, resolveRuntimeStateScope, resolveStateScope, resolveWritableStateScope, resolveWorkingDirectoryForState, getStateDir, getStateFilePath, getStatePath, normalizeSessionId, validateStateFileName, validateStateModeSegment, validateSessionId, WRITABLE_STATE_SCOPE_ERRORS, } from '../state-paths.js';
|
|
7
|
+
import { getAllScopedStateDirs, getAllScopedStatePaths, getBaseStateDir, getBaseStateDirWithSource, getAllSessionScopedStateDirs, getAllSessionScopedStatePaths, getReadScopedStateFilePaths, readCurrentSessionId, readSessionMetadataFromBaseStateDir, resolveRuntimeStateScope, resolveStateScope, resolveWritableStateScope, createWritableCommitRevalidator, __setWritableStateScopeTestHooksForTests, resolveWorkingDirectoryForState, getStateDir, getStateFilePath, getStatePath, normalizeSessionId, validateStateFileName, validateStateModeSegment, validateSessionId, WRITABLE_STATE_SCOPE_ERRORS, readCanonicalSessionBindingSnapshot, VERIFIED_SESSION_BINDING_FIELDS, } from '../state-paths.js';
|
|
8
|
+
import { __resetSessionPointerTransactionDependenciesForTests, __setSessionPointerTransactionDependenciesForTests, } from '../../hooks/session.js';
|
|
8
9
|
const isolatedEnvKeys = [
|
|
9
10
|
'OMX_MCP_WORKDIR_ROOTS',
|
|
10
11
|
'OMX_ROOT',
|
|
@@ -33,6 +34,26 @@ afterEach(() => {
|
|
|
33
34
|
async function mkRealTemp(prefix) {
|
|
34
35
|
return await realpath(await mkdtemp(join(await realpath(tmpdir()), prefix)));
|
|
35
36
|
}
|
|
37
|
+
function armPointerTakeover(options) {
|
|
38
|
+
const observed = [];
|
|
39
|
+
return {
|
|
40
|
+
observed,
|
|
41
|
+
hook: async (event) => {
|
|
42
|
+
const actual = { commitOrdinal: event.commitOrdinal, site: event.site, kind: event.kind, path: event.path };
|
|
43
|
+
observed.push(actual);
|
|
44
|
+
if (event.commitOrdinal === options.expectedOrdinal && event.site !== options.expectedSite) {
|
|
45
|
+
throw new Error(`Expected takeover at ordinal ${options.expectedOrdinal} site ${options.expectedSite}; received ordinal ${event.commitOrdinal} site ${event.site}.`);
|
|
46
|
+
}
|
|
47
|
+
if (event.site === options.expectedSite && event.commitOrdinal !== options.expectedOrdinal) {
|
|
48
|
+
throw new Error(`Expected takeover at ordinal ${options.expectedOrdinal} site ${options.expectedSite}; received ordinal ${event.commitOrdinal} site ${event.site}.`);
|
|
49
|
+
}
|
|
50
|
+
if (event.commitOrdinal === options.expectedOrdinal && event.site === options.expectedSite) {
|
|
51
|
+
options.beforePublish?.();
|
|
52
|
+
await writeFile(options.sessionPath, options.replacementPointer);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
36
57
|
describe('validateSessionId', () => {
|
|
37
58
|
it('accepts undefined and valid ids', () => {
|
|
38
59
|
assert.equal(validateSessionId(undefined), undefined);
|
|
@@ -51,6 +72,110 @@ describe('normalizeSessionId', () => {
|
|
|
51
72
|
assert.equal(normalizeSessionId(123), undefined);
|
|
52
73
|
});
|
|
53
74
|
});
|
|
75
|
+
describe('canonical session binding snapshot', () => {
|
|
76
|
+
it('accepts a descendant cwd through session authority and keeps the pointer bytes unchanged', async () => {
|
|
77
|
+
const root = await mkRealTemp('omx-binding-descendant-');
|
|
78
|
+
const nested = join(root, 'nested', 'child');
|
|
79
|
+
const env = { OMX_SESSION_ID: 'sess-descendant' };
|
|
80
|
+
try {
|
|
81
|
+
const stateDir = getBaseStateDir(root);
|
|
82
|
+
await mkdir(stateDir, { recursive: true });
|
|
83
|
+
await mkdir(nested, { recursive: true });
|
|
84
|
+
const pointer = JSON.stringify({ session_id: 'sess-descendant', cwd: root, state_root: stateDir });
|
|
85
|
+
await writeFile(join(stateDir, 'session.json'), pointer);
|
|
86
|
+
const snapshot = await readCanonicalSessionBindingSnapshot(nested, env);
|
|
87
|
+
assert.equal(snapshot.status, 'usable');
|
|
88
|
+
assert.equal(snapshot.rootSource, 'session-authority');
|
|
89
|
+
assert.equal(snapshot.recordedCwd, root);
|
|
90
|
+
assert.equal(snapshot.baseStateDir, stateDir);
|
|
91
|
+
assert.equal(await readFile(join(stateDir, 'session.json'), 'utf8'), pointer);
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
await rm(root, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
it('rejects a selected pointer whose explicit state root mismatches the selected root', async () => {
|
|
98
|
+
const root = await mkRealTemp('omx-binding-root-mismatch-');
|
|
99
|
+
const selectedRoot = join(root, 'selected');
|
|
100
|
+
const env = { OMX_ROOT: selectedRoot };
|
|
101
|
+
try {
|
|
102
|
+
const stateDir = getBaseStateDir(root, env);
|
|
103
|
+
await mkdir(stateDir, { recursive: true });
|
|
104
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
105
|
+
session_id: 'sess-mismatch', cwd: root, state_root: join(root, 'foreign-state'),
|
|
106
|
+
}));
|
|
107
|
+
const snapshot = await readCanonicalSessionBindingSnapshot(root, env);
|
|
108
|
+
assert.equal(snapshot.status, 'root-mismatch');
|
|
109
|
+
assert.equal(snapshot.rootSource, 'omx-root-env');
|
|
110
|
+
assert.equal(snapshot.baseStateDir, stateDir);
|
|
111
|
+
assert.equal(snapshot.selectedSessionJson, join(stateDir, 'session.json'));
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
await rm(root, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
it('uses the legacy cwd-derived root and only exposes the six verified aliases', async () => {
|
|
118
|
+
const root = await mkRealTemp('omx-binding-legacy-aliases-');
|
|
119
|
+
try {
|
|
120
|
+
const stateDir = getBaseStateDir(root);
|
|
121
|
+
await mkdir(stateDir, { recursive: true });
|
|
122
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
123
|
+
session_id: 'sess-canonical', native_session_id: 'native-id', codex_session_id: 'codex-id',
|
|
124
|
+
previous_native_session_id: 'previous-id', owner_omx_session_id: 'owner-omx', owner_codex_session_id: 'owner-codex',
|
|
125
|
+
owner_codex_thread_id: 'thread-must-not-bind', tmux_pane_id: '%9', tmux_session_name: 'foreign-tmux',
|
|
126
|
+
display_name: 'display-must-not-bind', owner_unknown_id: 'unknown-must-not-bind', cwd: root,
|
|
127
|
+
}));
|
|
128
|
+
const snapshot = await readCanonicalSessionBindingSnapshot(root, {});
|
|
129
|
+
assert.equal(snapshot.status, 'usable');
|
|
130
|
+
assert.equal(snapshot.baseStateDir, stateDir);
|
|
131
|
+
assert.deepEqual(Object.keys(snapshot.verifiedAliases), [...VERIFIED_SESSION_BINDING_FIELDS]);
|
|
132
|
+
assert.deepEqual(snapshot.verifiedAliases, {
|
|
133
|
+
session_id: 'sess-canonical', native_session_id: 'native-id', codex_session_id: 'codex-id',
|
|
134
|
+
previous_native_session_id: 'previous-id', owner_omx_session_id: 'owner-omx', owner_codex_session_id: 'owner-codex',
|
|
135
|
+
});
|
|
136
|
+
assert.equal(snapshot.verifiedAliases.owner_codex_thread_id, undefined);
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
await rm(root, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
it('fails closed when state_root is present but blank', async () => {
|
|
143
|
+
const root = await mkRealTemp('omx-binding-blank-state-root-');
|
|
144
|
+
try {
|
|
145
|
+
const stateDir = getBaseStateDir(root);
|
|
146
|
+
await mkdir(stateDir, { recursive: true });
|
|
147
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
148
|
+
session_id: 'sess-blank-root', cwd: root, state_root: ' ',
|
|
149
|
+
}));
|
|
150
|
+
const snapshot = await readCanonicalSessionBindingSnapshot(root, {});
|
|
151
|
+
assert.equal(snapshot.status, 'malformed');
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
await rm(root, { recursive: true, force: true });
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
it('compares selected and recorded roots by realpath', async () => {
|
|
158
|
+
const realRoot = await mkRealTemp('omx-binding-real-root-');
|
|
159
|
+
const linkParent = await mkRealTemp('omx-binding-link-parent-');
|
|
160
|
+
const linkedRoot = join(linkParent, 'workspace-link');
|
|
161
|
+
try {
|
|
162
|
+
await symlink(realRoot, linkedRoot, process.platform === 'win32' ? 'junction' : 'dir');
|
|
163
|
+
const stateDir = getBaseStateDir(realRoot);
|
|
164
|
+
await mkdir(stateDir, { recursive: true });
|
|
165
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
166
|
+
session_id: 'sess-realpath', cwd: realRoot, state_root: stateDir,
|
|
167
|
+
}));
|
|
168
|
+
const snapshot = await readCanonicalSessionBindingSnapshot(linkedRoot, { OMX_ROOT: linkedRoot });
|
|
169
|
+
assert.equal(snapshot.status, 'usable');
|
|
170
|
+
assert.ok(snapshot.baseStateDir);
|
|
171
|
+
assert.equal(await realpath(snapshot.baseStateDir), await realpath(stateDir));
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
await rm(realRoot, { recursive: true, force: true });
|
|
175
|
+
await rm(linkParent, { recursive: true, force: true });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
54
179
|
describe('validateStateModeSegment', () => {
|
|
55
180
|
it('accepts safe mode names', () => {
|
|
56
181
|
assert.equal(validateStateModeSegment('ralph'), 'ralph');
|
|
@@ -136,6 +261,159 @@ describe('state paths', () => {
|
|
|
136
261
|
delete process.env.OMX_TEAM_STATE_ROOT;
|
|
137
262
|
}
|
|
138
263
|
});
|
|
264
|
+
it('uses the ancestor session pointer matching OMX_SESSION_ID as the authoritative root', async () => {
|
|
265
|
+
const parent = await mkRealTemp('omx-state-authority-parent-');
|
|
266
|
+
const nested = join(parent, 'nested', 'project');
|
|
267
|
+
const parentState = join(parent, '.omx', 'state');
|
|
268
|
+
const nestedState = join(nested, '.omx', 'state');
|
|
269
|
+
try {
|
|
270
|
+
await mkdir(parentState, { recursive: true });
|
|
271
|
+
await mkdir(nestedState, { recursive: true });
|
|
272
|
+
await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-parent', cwd: parent, state_root: parentState }));
|
|
273
|
+
await writeFile(join(nestedState, 'session.json'), JSON.stringify({ session_id: 'sess-nested', cwd: nested }));
|
|
274
|
+
process.env.OMX_SESSION_ID = 'sess-parent';
|
|
275
|
+
assert.deepEqual(getBaseStateDirWithSource(nested), {
|
|
276
|
+
baseStateDir: parentState,
|
|
277
|
+
rootSource: 'session-authority',
|
|
278
|
+
});
|
|
279
|
+
const writable = await resolveWritableStateScope(nested);
|
|
280
|
+
assert.equal(writable.stateDir, join(parentState, 'sessions', 'sess-parent'));
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
await rm(parent, { recursive: true, force: true });
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
it('uses a live legacy ancestor pointer when its inferred root matches exactly', async () => {
|
|
287
|
+
const parent = await mkRealTemp('omx-state-authority-legacy-');
|
|
288
|
+
const nested = join(parent, 'nested');
|
|
289
|
+
const parentState = join(parent, '.omx', 'state');
|
|
290
|
+
try {
|
|
291
|
+
await mkdir(parentState, { recursive: true });
|
|
292
|
+
await mkdir(nested, { recursive: true });
|
|
293
|
+
await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-legacy', cwd: parent }));
|
|
294
|
+
process.env.OMX_SESSION_ID = 'sess-legacy';
|
|
295
|
+
assert.deepEqual(getBaseStateDirWithSource(nested), {
|
|
296
|
+
baseStateDir: parentState,
|
|
297
|
+
rootSource: 'session-authority',
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
finally {
|
|
301
|
+
await rm(parent, { recursive: true, force: true });
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
it('rejects pointers whose persisted or inferred root does not own the selected base', async () => {
|
|
305
|
+
const cwd = await mkRealTemp('omx-state-pointer-root-owner-');
|
|
306
|
+
const selectedState = join(cwd, 'selected-state');
|
|
307
|
+
const claimedState = join(cwd, 'claimed-state');
|
|
308
|
+
try {
|
|
309
|
+
await mkdir(selectedState, { recursive: true });
|
|
310
|
+
await writeFile(join(selectedState, 'session.json'), JSON.stringify({
|
|
311
|
+
session_id: 'sess-mismatch',
|
|
312
|
+
cwd,
|
|
313
|
+
state_root: claimedState,
|
|
314
|
+
}));
|
|
315
|
+
assert.equal(await readSessionMetadataFromBaseStateDir(cwd, selectedState), undefined);
|
|
316
|
+
await writeFile(join(selectedState, 'session.json'), JSON.stringify({ session_id: 'sess-legacy-explicit', cwd }));
|
|
317
|
+
assert.equal(await readSessionMetadataFromBaseStateDir(cwd, selectedState), undefined);
|
|
318
|
+
}
|
|
319
|
+
finally {
|
|
320
|
+
await rm(cwd, { recursive: true, force: true });
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
it('fails explicitly when multiple ancestor pointers claim the same session authority', async () => {
|
|
324
|
+
const parent = await mkRealTemp('omx-state-authority-conflict-');
|
|
325
|
+
const nested = join(parent, 'nested');
|
|
326
|
+
const parentState = join(parent, '.omx', 'state');
|
|
327
|
+
const nestedState = join(nested, '.omx', 'state');
|
|
328
|
+
try {
|
|
329
|
+
await mkdir(parentState, { recursive: true });
|
|
330
|
+
await mkdir(nestedState, { recursive: true });
|
|
331
|
+
await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-conflict', cwd: parent, state_root: parentState }));
|
|
332
|
+
await writeFile(join(nestedState, 'session.json'), JSON.stringify({ session_id: 'sess-conflict', cwd: nested, state_root: nestedState }));
|
|
333
|
+
process.env.OMX_SESSION_ID = 'sess-conflict';
|
|
334
|
+
assert.throws(() => getBaseStateDirWithSource(nested), new RegExp(`Conflicting authoritative state roots.*${parentState}.*${nestedState}|Conflicting authoritative state roots.*${nestedState}.*${parentState}`));
|
|
335
|
+
}
|
|
336
|
+
finally {
|
|
337
|
+
await rm(parent, { recursive: true, force: true });
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
it('ignores a dead matching ancestor session pointer', async () => {
|
|
341
|
+
const parent = await mkRealTemp('omx-state-authority-dead-');
|
|
342
|
+
const nested = join(parent, 'nested');
|
|
343
|
+
const parentState = join(parent, '.omx', 'state');
|
|
344
|
+
try {
|
|
345
|
+
await mkdir(parentState, { recursive: true });
|
|
346
|
+
await mkdir(nested, { recursive: true });
|
|
347
|
+
await writeFile(join(parentState, 'session.json'), JSON.stringify({
|
|
348
|
+
session_id: 'sess-dead',
|
|
349
|
+
cwd: parent,
|
|
350
|
+
pid: 2_147_483_647,
|
|
351
|
+
}));
|
|
352
|
+
process.env.OMX_SESSION_ID = 'sess-dead';
|
|
353
|
+
assert.deepEqual(getBaseStateDirWithSource(nested), {
|
|
354
|
+
baseStateDir: join(nested, '.omx', 'state'),
|
|
355
|
+
rootSource: 'cwd-default',
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
finally {
|
|
359
|
+
await rm(parent, { recursive: true, force: true });
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
it('does not discover ancestor authority outside OMX_MCP_WORKDIR_ROOTS', async () => {
|
|
363
|
+
const parent = await mkRealTemp('omx-state-authority-allowlist-');
|
|
364
|
+
const nested = join(parent, 'nested');
|
|
365
|
+
const parentState = join(parent, '.omx', 'state');
|
|
366
|
+
try {
|
|
367
|
+
await mkdir(parentState, { recursive: true });
|
|
368
|
+
await mkdir(nested, { recursive: true });
|
|
369
|
+
await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-outside', cwd: parent }));
|
|
370
|
+
process.env.OMX_SESSION_ID = 'sess-outside';
|
|
371
|
+
process.env.OMX_MCP_WORKDIR_ROOTS = nested;
|
|
372
|
+
assert.deepEqual(getBaseStateDirWithSource(nested), {
|
|
373
|
+
baseStateDir: join(nested, '.omx', 'state'),
|
|
374
|
+
rootSource: 'cwd-default',
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
finally {
|
|
378
|
+
await rm(parent, { recursive: true, force: true });
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
it('does not select an in-allowlist state symlink that escapes the allowed root', async () => {
|
|
382
|
+
const parent = await mkRealTemp('omx-state-authority-symlink-');
|
|
383
|
+
const nested = join(parent, 'nested');
|
|
384
|
+
const outsideState = join(parent, 'outside-state');
|
|
385
|
+
try {
|
|
386
|
+
await mkdir(join(nested, '.omx'), { recursive: true });
|
|
387
|
+
await mkdir(outsideState, { recursive: true });
|
|
388
|
+
await writeFile(join(outsideState, 'session.json'), JSON.stringify({ session_id: 'sess-symlink', cwd: nested }));
|
|
389
|
+
await symlink(outsideState, join(nested, '.omx', 'state'), process.platform === 'win32' ? 'junction' : 'dir');
|
|
390
|
+
process.env.OMX_SESSION_ID = 'sess-symlink';
|
|
391
|
+
process.env.OMX_MCP_WORKDIR_ROOTS = nested;
|
|
392
|
+
assert.throws(() => getBaseStateDirWithSource(nested), /State root .* is outside allowed roots \(OMX_MCP_WORKDIR_ROOTS\)/);
|
|
393
|
+
}
|
|
394
|
+
finally {
|
|
395
|
+
await rm(parent, { recursive: true, force: true });
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
it('rejects OMX_ROOT and OMX_STATE_ROOT whose appended state directory escapes the allowlist', async () => {
|
|
399
|
+
const parent = await mkRealTemp('omx-state-override-symlink-');
|
|
400
|
+
const allowed = join(parent, 'allowed');
|
|
401
|
+
const outsideState = join(parent, 'outside-state');
|
|
402
|
+
try {
|
|
403
|
+
await mkdir(join(allowed, '.omx'), { recursive: true });
|
|
404
|
+
await mkdir(outsideState, { recursive: true });
|
|
405
|
+
await symlink(outsideState, join(allowed, '.omx', 'state'), process.platform === 'win32' ? 'junction' : 'dir');
|
|
406
|
+
process.env.OMX_MCP_WORKDIR_ROOTS = allowed;
|
|
407
|
+
process.env.OMX_ROOT = allowed;
|
|
408
|
+
assert.throws(() => getBaseStateDirWithSource(allowed), /State root .* is outside allowed roots/);
|
|
409
|
+
delete process.env.OMX_ROOT;
|
|
410
|
+
process.env.OMX_STATE_ROOT = allowed;
|
|
411
|
+
assert.throws(() => getBaseStateDirWithSource(allowed), /State root .* is outside allowed roots/);
|
|
412
|
+
}
|
|
413
|
+
finally {
|
|
414
|
+
await rm(parent, { recursive: true, force: true });
|
|
415
|
+
}
|
|
416
|
+
});
|
|
139
417
|
it('fails closed when an explicit state root is outside the allowlist', async () => {
|
|
140
418
|
const allowedRoot = await mkRealTemp('omx-state-root-allowed-');
|
|
141
419
|
const disallowedRoot = await mkRealTemp('omx-state-root-disallowed-');
|
|
@@ -350,7 +628,11 @@ describe('state paths', () => {
|
|
|
350
628
|
const stateDir = getBaseStateDir(wd);
|
|
351
629
|
await mkdir(join(stateDir, 'sessions', 'sess-current'), { recursive: true });
|
|
352
630
|
await mkdir(stateDir, { recursive: true });
|
|
353
|
-
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
631
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
632
|
+
session_id: 'sess-current',
|
|
633
|
+
cwd: wd,
|
|
634
|
+
state_root: stateDir,
|
|
635
|
+
}));
|
|
354
636
|
const paths = await getReadScopedStateFilePaths('hud-state.json', wd, undefined, {
|
|
355
637
|
rootFallback: false,
|
|
356
638
|
});
|
|
@@ -427,6 +709,7 @@ describe('state paths', () => {
|
|
|
427
709
|
session_id: 'native-id',
|
|
428
710
|
native_session_id: 'native-id',
|
|
429
711
|
owner_omx_session_id: 'omx-owner-id',
|
|
712
|
+
owner_codex_session_id: 'codex-owner-id',
|
|
430
713
|
cwd: wd,
|
|
431
714
|
}));
|
|
432
715
|
process.env.OMX_SESSION_ID = 'omx-owner-id';
|
|
@@ -439,6 +722,14 @@ describe('state paths', () => {
|
|
|
439
722
|
assert.equal(runtimeScope.sessionId, 'native-id');
|
|
440
723
|
assert.equal(runtimeScope.stateDir, join(stateDir, 'sessions', 'native-id'));
|
|
441
724
|
assert.equal(runtimeScope.source, 'native-alias');
|
|
725
|
+
process.env.OMX_SESSION_ID = 'codex-owner-id';
|
|
726
|
+
assert.equal(await readCurrentSessionId(wd), 'native-id');
|
|
727
|
+
const codexScope = await resolveStateScope(wd);
|
|
728
|
+
assert.equal(codexScope.sessionId, 'native-id');
|
|
729
|
+
assert.equal(codexScope.stateDir, join(stateDir, 'sessions', 'native-id'));
|
|
730
|
+
const codexRuntimeScope = await resolveRuntimeStateScope(wd);
|
|
731
|
+
assert.equal(codexRuntimeScope.sessionId, 'native-id');
|
|
732
|
+
assert.equal(codexRuntimeScope.stateDir, join(stateDir, 'sessions', 'native-id'));
|
|
442
733
|
}
|
|
443
734
|
finally {
|
|
444
735
|
if (typeof previousOmxSessionId === 'string')
|
|
@@ -458,12 +749,16 @@ describe('state paths', () => {
|
|
|
458
749
|
session_id: 'native-id',
|
|
459
750
|
native_session_id: 'native-id',
|
|
460
751
|
owner_omx_session_id: 'omx-owner-id',
|
|
752
|
+
owner_codex_session_id: 'codex-owner-id',
|
|
461
753
|
cwd: wd,
|
|
462
754
|
}));
|
|
463
755
|
const scope = await resolveStateScope(wd, 'omx-owner-id');
|
|
464
756
|
assert.equal(scope.sessionId, 'native-id');
|
|
465
757
|
assert.equal(scope.stateDir, join(stateDir, 'sessions', 'native-id'));
|
|
466
758
|
assert.notEqual(scope.stateDir, join(stateDir, 'sessions', 'omx-owner-id'));
|
|
759
|
+
const codexScope = await resolveStateScope(wd, 'codex-owner-id');
|
|
760
|
+
assert.equal(codexScope.sessionId, 'native-id');
|
|
761
|
+
assert.equal(codexScope.stateDir, join(stateDir, 'sessions', 'native-id'));
|
|
467
762
|
}
|
|
468
763
|
finally {
|
|
469
764
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -517,6 +812,7 @@ describe('state paths', () => {
|
|
|
517
812
|
await writeFile(join(teamStateRoot, 'session.json'), JSON.stringify({
|
|
518
813
|
session_id: 'sess-team-current',
|
|
519
814
|
cwd: wd,
|
|
815
|
+
state_root: teamStateRoot,
|
|
520
816
|
}));
|
|
521
817
|
await mkdir(join(wd, '.omx', 'state'), { recursive: true });
|
|
522
818
|
await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({
|
|
@@ -617,7 +913,7 @@ describe('state paths', () => {
|
|
|
617
913
|
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-canonical', cwd: wd }));
|
|
618
914
|
process.env.OMX_SESSION_ID = 'sess-unmatched';
|
|
619
915
|
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
620
|
-
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.
|
|
916
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.sessionBindingMismatch);
|
|
621
917
|
return true;
|
|
622
918
|
});
|
|
623
919
|
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-unmatched')), false);
|
|
@@ -640,6 +936,7 @@ describe('state paths', () => {
|
|
|
640
936
|
session_id: 'sess-canonical',
|
|
641
937
|
native_session_id: 'native-alias',
|
|
642
938
|
owner_omx_session_id: 'omx-owner-alias',
|
|
939
|
+
owner_codex_session_id: 'codex-owner-alias',
|
|
643
940
|
cwd: wd,
|
|
644
941
|
}));
|
|
645
942
|
process.env.OMX_SESSION_ID = 'omx-owner-alias';
|
|
@@ -648,11 +945,445 @@ describe('state paths', () => {
|
|
|
648
945
|
sessionId: 'sess-canonical',
|
|
649
946
|
stateDir: join(stateDir, 'sessions', 'sess-canonical'),
|
|
650
947
|
});
|
|
948
|
+
process.env.OMX_SESSION_ID = 'codex-owner-alias';
|
|
949
|
+
assert.deepEqual(await resolveWritableStateScope(wd), {
|
|
950
|
+
source: 'session',
|
|
951
|
+
sessionId: 'sess-canonical',
|
|
952
|
+
stateDir: join(stateDir, 'sessions', 'sess-canonical'),
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
finally {
|
|
956
|
+
await rm(wd, { recursive: true, force: true });
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
it('binds an explicit exact-current OMX_SESSION_ID when the selected pointer is stale-dead', async () => {
|
|
960
|
+
const wd = await mkRealTemp('omx-writable-stale-dead-env-');
|
|
961
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
962
|
+
try {
|
|
963
|
+
const stateDir = getBaseStateDir(wd);
|
|
964
|
+
await mkdir(stateDir, { recursive: true });
|
|
965
|
+
const pointerBody = JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 });
|
|
966
|
+
await writeFile(join(stateDir, 'session.json'), pointerBody);
|
|
967
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
968
|
+
assert.deepEqual(await resolveWritableStateScope(wd), {
|
|
969
|
+
source: 'session',
|
|
970
|
+
sessionId: 'sess-current',
|
|
971
|
+
stateDir: join(stateDir, 'sessions', 'sess-current'),
|
|
972
|
+
});
|
|
973
|
+
// Scope resolution must never mutate the selected pointer; SessionStart
|
|
974
|
+
// remains the only session.json writer.
|
|
975
|
+
assert.equal(await readFile(join(stateDir, 'session.json'), 'utf-8'), pointerBody);
|
|
976
|
+
}
|
|
977
|
+
finally {
|
|
978
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
979
|
+
await rm(wd, { recursive: true, force: true });
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
it('still fails closed for a stale-dead pointer without an env binding', async () => {
|
|
983
|
+
const wd = await mkRealTemp('omx-writable-stale-dead-noenv-');
|
|
984
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
985
|
+
try {
|
|
986
|
+
const stateDir = getBaseStateDir(wd);
|
|
987
|
+
await mkdir(stateDir, { recursive: true });
|
|
988
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
|
|
989
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
990
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
991
|
+
return true;
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
finally {
|
|
995
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
996
|
+
await rm(wd, { recursive: true, force: true });
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
it('fails closed for malformed and foreign-cwd pointers even with an env binding', async () => {
|
|
1000
|
+
const wd = await mkRealTemp('omx-writable-ambiguous-env-');
|
|
1001
|
+
try {
|
|
1002
|
+
const stateDir = getBaseStateDir(wd);
|
|
1003
|
+
await mkdir(stateDir, { recursive: true });
|
|
1004
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1005
|
+
await writeFile(join(stateDir, 'session.json'), '{not json');
|
|
1006
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1007
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1008
|
+
return true;
|
|
1009
|
+
});
|
|
1010
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
1011
|
+
session_id: 'sess-foreign',
|
|
1012
|
+
cwd: join(wd, 'other-worktree'),
|
|
1013
|
+
}));
|
|
1014
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1015
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1016
|
+
return true;
|
|
1017
|
+
});
|
|
651
1018
|
}
|
|
652
1019
|
finally {
|
|
653
1020
|
await rm(wd, { recursive: true, force: true });
|
|
654
1021
|
}
|
|
655
1022
|
});
|
|
1023
|
+
it('fails closed for JSON-valid non-object pointers even with an env binding', async () => {
|
|
1024
|
+
const wd = await mkRealTemp('omx-writable-nonobject-env-');
|
|
1025
|
+
try {
|
|
1026
|
+
const stateDir = getBaseStateDir(wd);
|
|
1027
|
+
await mkdir(stateDir, { recursive: true });
|
|
1028
|
+
const sessionPath = join(stateDir, 'session.json');
|
|
1029
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1030
|
+
// JSON null, arrays, and scalars parse cleanly but are not pointer
|
|
1031
|
+
// objects. They must surface the same stable unusable-session error as
|
|
1032
|
+
// syntactically malformed bytes rather than throwing on property access.
|
|
1033
|
+
for (const body of ['null', '[]', '42', '"sess-current"']) {
|
|
1034
|
+
await writeFile(sessionPath, body);
|
|
1035
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1036
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1037
|
+
return true;
|
|
1038
|
+
});
|
|
1039
|
+
assert.equal(await readFile(sessionPath, 'utf-8'), body);
|
|
1040
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
finally {
|
|
1044
|
+
await rm(wd, { recursive: true, force: true });
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
it('recovers writable scope for an identity-indeterminate pointer with an exact-match OMX_SESSION_ID', async () => {
|
|
1048
|
+
const wd = await mkRealTemp('omx-writable-indeterminate-exact-');
|
|
1049
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
|
|
1050
|
+
try {
|
|
1051
|
+
const stateDir = getBaseStateDir(wd);
|
|
1052
|
+
const sessionPath = join(stateDir, 'session.json');
|
|
1053
|
+
await mkdir(stateDir, { recursive: true });
|
|
1054
|
+
const pointerBody = JSON.stringify({ session_id: 'sess-exact', cwd: wd, pid: 8388607 });
|
|
1055
|
+
await writeFile(sessionPath, pointerBody);
|
|
1056
|
+
const beforePointer = await readFile(sessionPath, 'utf-8');
|
|
1057
|
+
const beforeEntries = (await readdir(stateDir)).sort();
|
|
1058
|
+
process.env.OMX_SESSION_ID = 'sess-exact';
|
|
1059
|
+
assert.deepEqual(await resolveWritableStateScope(wd), {
|
|
1060
|
+
source: 'session',
|
|
1061
|
+
sessionId: 'sess-exact',
|
|
1062
|
+
stateDir: join(stateDir, 'sessions', 'sess-exact'),
|
|
1063
|
+
});
|
|
1064
|
+
assert.equal(await readFile(sessionPath, 'utf-8'), beforePointer);
|
|
1065
|
+
assert.deepEqual((await readdir(stateDir)).sort(), beforeEntries);
|
|
1066
|
+
}
|
|
1067
|
+
finally {
|
|
1068
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1069
|
+
await rm(wd, { recursive: true, force: true });
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
it('fails closed for an identity-indeterminate pointer even with an env binding', async () => {
|
|
1073
|
+
const wd = await mkRealTemp('omx-writable-indeterminate-env-');
|
|
1074
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
|
|
1075
|
+
try {
|
|
1076
|
+
const stateDir = getBaseStateDir(wd);
|
|
1077
|
+
await mkdir(stateDir, { recursive: true });
|
|
1078
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-unknown', cwd: wd, pid: 8388607 }));
|
|
1079
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1080
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1081
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1082
|
+
return true;
|
|
1083
|
+
});
|
|
1084
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
|
|
1085
|
+
}
|
|
1086
|
+
finally {
|
|
1087
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1088
|
+
await rm(wd, { recursive: true, force: true });
|
|
1089
|
+
}
|
|
1090
|
+
});
|
|
1091
|
+
it('fails closed for a stale-dead pointer without cwd or state_root authority even with an env binding', async () => {
|
|
1092
|
+
const wd = await mkRealTemp('omx-writable-stale-dead-noauthority-');
|
|
1093
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1094
|
+
try {
|
|
1095
|
+
const stateDir = getBaseStateDir(wd);
|
|
1096
|
+
await mkdir(stateDir, { recursive: true });
|
|
1097
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1098
|
+
// A dead PID does not cure a missing recorded cwd: the pointer holds
|
|
1099
|
+
// no selected-root authority, so recovery must stay fail-closed.
|
|
1100
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', pid: 8388607 }));
|
|
1101
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1102
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1103
|
+
return true;
|
|
1104
|
+
});
|
|
1105
|
+
// A recorded state_root naming another root is equally non-authoritative.
|
|
1106
|
+
const foreignRoot = join(wd, 'other-root');
|
|
1107
|
+
await mkdir(foreignRoot, { recursive: true });
|
|
1108
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
1109
|
+
session_id: 'sess-dead',
|
|
1110
|
+
cwd: wd,
|
|
1111
|
+
state_root: foreignRoot,
|
|
1112
|
+
pid: 8388607,
|
|
1113
|
+
}));
|
|
1114
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1115
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1116
|
+
return true;
|
|
1117
|
+
});
|
|
1118
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
|
|
1119
|
+
}
|
|
1120
|
+
finally {
|
|
1121
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1122
|
+
await rm(wd, { recursive: true, force: true });
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
describe('writable state scope recovery and revalidation', () => {
|
|
1128
|
+
it('T10 reads the selected decision snapshot and recovery stability snapshot once', async () => {
|
|
1129
|
+
const wd = await mkRealTemp('omx-writable-single-snapshot-');
|
|
1130
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1131
|
+
try {
|
|
1132
|
+
const stateDir = getBaseStateDir(wd);
|
|
1133
|
+
await mkdir(stateDir, { recursive: true });
|
|
1134
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
|
|
1135
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1136
|
+
const decisions = [];
|
|
1137
|
+
const stability = [];
|
|
1138
|
+
__setWritableStateScopeTestHooksForTests({
|
|
1139
|
+
onSelectedDecisionSnapshotRead: (event) => decisions.push({ ...event }),
|
|
1140
|
+
onRecoveryStabilityReread: (event) => stability.push({ ...event }),
|
|
1141
|
+
});
|
|
1142
|
+
await resolveWritableStateScope(wd);
|
|
1143
|
+
assert.deepEqual(decisions.map(({ ordinal }) => ordinal), [1]);
|
|
1144
|
+
assert.deepEqual(stability.map(({ ordinal }) => ordinal), [1]);
|
|
1145
|
+
assert.equal(stability[0]?.raw, decisions[0]?.raw);
|
|
1146
|
+
}
|
|
1147
|
+
finally {
|
|
1148
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1149
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1150
|
+
await rm(wd, { recursive: true, force: true });
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
it('T11 fails closed when the pointer bytes change during stale-dead recovery', async () => {
|
|
1154
|
+
const wd = await mkRealTemp('omx-writable-unstable-recovery-');
|
|
1155
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1156
|
+
try {
|
|
1157
|
+
const stateDir = getBaseStateDir(wd);
|
|
1158
|
+
const sessionPath = join(stateDir, 'session.json');
|
|
1159
|
+
await mkdir(stateDir, { recursive: true });
|
|
1160
|
+
await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
|
|
1161
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1162
|
+
__setWritableStateScopeTestHooksForTests({
|
|
1163
|
+
beforeRecoveryReread: async () => {
|
|
1164
|
+
await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-replaced', cwd: wd }));
|
|
1165
|
+
},
|
|
1166
|
+
});
|
|
1167
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1168
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1169
|
+
return true;
|
|
1170
|
+
});
|
|
1171
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
|
|
1172
|
+
}
|
|
1173
|
+
finally {
|
|
1174
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1175
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1176
|
+
await rm(wd, { recursive: true, force: true });
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
it('fails closed when the pointer bytes change during identity-indeterminate exact-match recovery', async () => {
|
|
1180
|
+
const wd = await mkRealTemp('omx-writable-indeterminate-unstable-');
|
|
1181
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
|
|
1182
|
+
try {
|
|
1183
|
+
const stateDir = getBaseStateDir(wd);
|
|
1184
|
+
const sessionPath = join(stateDir, 'session.json');
|
|
1185
|
+
await mkdir(stateDir, { recursive: true });
|
|
1186
|
+
await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-indeterminate', cwd: wd, pid: 8388607 }));
|
|
1187
|
+
process.env.OMX_SESSION_ID = 'sess-indeterminate';
|
|
1188
|
+
__setWritableStateScopeTestHooksForTests({
|
|
1189
|
+
beforeRecoveryReread: async () => {
|
|
1190
|
+
await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-indeterminate', cwd: wd, pid: 9999999 }));
|
|
1191
|
+
},
|
|
1192
|
+
});
|
|
1193
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1194
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
|
|
1195
|
+
return true;
|
|
1196
|
+
});
|
|
1197
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-indeterminate')), false);
|
|
1198
|
+
}
|
|
1199
|
+
finally {
|
|
1200
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1201
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1202
|
+
await rm(wd, { recursive: true, force: true });
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
it('T12 leaves the stale-dead pointer and base state root entries unchanged during recovery', async () => {
|
|
1206
|
+
const wd = await mkRealTemp('omx-writable-pointer-immutable-');
|
|
1207
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1208
|
+
try {
|
|
1209
|
+
const stateDir = getBaseStateDir(wd);
|
|
1210
|
+
const sessionPath = join(stateDir, 'session.json');
|
|
1211
|
+
await mkdir(stateDir, { recursive: true });
|
|
1212
|
+
await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
|
|
1213
|
+
const beforePointer = await readFile(sessionPath, 'utf-8');
|
|
1214
|
+
const beforeEntries = (await readdir(stateDir)).sort();
|
|
1215
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1216
|
+
await resolveWritableStateScope(wd);
|
|
1217
|
+
assert.equal(await readFile(sessionPath, 'utf-8'), beforePointer);
|
|
1218
|
+
assert.deepEqual((await readdir(stateDir)).sort(), beforeEntries);
|
|
1219
|
+
}
|
|
1220
|
+
finally {
|
|
1221
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1222
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1223
|
+
await rm(wd, { recursive: true, force: true });
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
it('T13 rejects stale-dead recovery without selected-root authority', async () => {
|
|
1227
|
+
const wd = await mkRealTemp('omx-writable-authority-matrix-');
|
|
1228
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1229
|
+
try {
|
|
1230
|
+
const stateDir = getBaseStateDir(wd);
|
|
1231
|
+
await mkdir(stateDir, { recursive: true });
|
|
1232
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1233
|
+
const cases = [
|
|
1234
|
+
{ name: 'missing recorded cwd', pointer: { session_id: 'sess-dead', pid: 8388607 } },
|
|
1235
|
+
{ name: 'different state root', pointer: { session_id: 'sess-dead', cwd: wd, state_root: join(wd, 'other-root'), pid: 8388607 } },
|
|
1236
|
+
{ name: 'recorded cwd does not contain the observed cwd', pointer: { session_id: 'sess-dead', cwd: join(wd, 'other-worktree'), pid: 8388607 } },
|
|
1237
|
+
];
|
|
1238
|
+
for (const testCase of cases) {
|
|
1239
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify(testCase.pointer));
|
|
1240
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1241
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession, testCase.name);
|
|
1242
|
+
return true;
|
|
1243
|
+
});
|
|
1244
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false, testCase.name);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
finally {
|
|
1248
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1249
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1250
|
+
await rm(wd, { recursive: true, force: true });
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
it('fails closed for identity-indeterminate pointer without selected-root authority even with an exact-match env binding', async () => {
|
|
1254
|
+
const wd = await mkRealTemp('omx-writable-indeterminate-noauthority-');
|
|
1255
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
|
|
1256
|
+
try {
|
|
1257
|
+
const stateDir = getBaseStateDir(wd);
|
|
1258
|
+
await mkdir(stateDir, { recursive: true });
|
|
1259
|
+
process.env.OMX_SESSION_ID = 'sess-indeterminate';
|
|
1260
|
+
const cases = [
|
|
1261
|
+
{ name: 'missing recorded cwd', pointer: { session_id: 'sess-indeterminate', pid: 8388607 } },
|
|
1262
|
+
{ name: 'different state root', pointer: { session_id: 'sess-indeterminate', cwd: wd, state_root: join(wd, 'other-root'), pid: 8388607 } },
|
|
1263
|
+
{ name: 'recorded cwd does not contain the observed cwd', pointer: { session_id: 'sess-indeterminate', cwd: join(wd, 'other-worktree'), pid: 8388607 } },
|
|
1264
|
+
];
|
|
1265
|
+
for (const testCase of cases) {
|
|
1266
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify(testCase.pointer));
|
|
1267
|
+
await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
|
|
1268
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession, testCase.name);
|
|
1269
|
+
return true;
|
|
1270
|
+
});
|
|
1271
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'sess-indeterminate')), false, testCase.name);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
finally {
|
|
1275
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1276
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1277
|
+
await rm(wd, { recursive: true, force: true });
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
it('T1 gives each writable commit revalidator a closure-local ordinal sequence', async () => {
|
|
1281
|
+
const wd = await mkRealTemp('omx-writable-revalidator-ordinals-');
|
|
1282
|
+
__setSessionPointerTransactionDependenciesForTests({});
|
|
1283
|
+
try {
|
|
1284
|
+
const stateDir = getBaseStateDir(wd);
|
|
1285
|
+
await mkdir(stateDir, { recursive: true });
|
|
1286
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-current', cwd: wd }));
|
|
1287
|
+
const capturedScope = await resolveWritableStateScope(wd);
|
|
1288
|
+
const events = [];
|
|
1289
|
+
__setWritableStateScopeTestHooksForTests({
|
|
1290
|
+
beforeScopeRevalidation: async (event) => { events.push({ ...event }); },
|
|
1291
|
+
});
|
|
1292
|
+
const options = { operation: 'state_write', cwd: wd, explicitSessionId: undefined, capturedScope, baseStateDir: stateDir };
|
|
1293
|
+
const revalidate = createWritableCommitRevalidator(options);
|
|
1294
|
+
const attempts = [
|
|
1295
|
+
{ site: 'mode.primary', kind: 'write', path: join(stateDir, 'mode-state.json') },
|
|
1296
|
+
{ site: 'skill-active.root-copy', kind: 'write', path: join(stateDir, 'skill-active.json') },
|
|
1297
|
+
{ site: 'skill-active.session-copy', kind: 'write', path: join(stateDir, 'sessions', 'sess-current', 'skill-active.json') },
|
|
1298
|
+
];
|
|
1299
|
+
for (const attempt of attempts)
|
|
1300
|
+
await revalidate(attempt);
|
|
1301
|
+
await createWritableCommitRevalidator(options)(attempts[0]);
|
|
1302
|
+
assert.deepEqual(events, [
|
|
1303
|
+
...attempts.map((attempt, index) => ({ operation: 'state_write', commitOrdinal: index + 1, ...attempt })),
|
|
1304
|
+
{ operation: 'state_write', commitOrdinal: 1, ...attempts[0] },
|
|
1305
|
+
]);
|
|
1306
|
+
}
|
|
1307
|
+
finally {
|
|
1308
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1309
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1310
|
+
await rm(wd, { recursive: true, force: true });
|
|
1311
|
+
}
|
|
1312
|
+
});
|
|
1313
|
+
it('T2 rejects a writable commit when revalidation observes a replacement scope', async () => {
|
|
1314
|
+
const wd = await mkRealTemp('omx-writable-revalidator-drift-');
|
|
1315
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1316
|
+
try {
|
|
1317
|
+
const stateDir = getBaseStateDir(wd);
|
|
1318
|
+
const sessionPath = join(stateDir, 'session.json');
|
|
1319
|
+
await mkdir(stateDir, { recursive: true });
|
|
1320
|
+
await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
|
|
1321
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1322
|
+
const capturedScope = await resolveWritableStateScope(wd);
|
|
1323
|
+
const takeover = armPointerTakeover({
|
|
1324
|
+
expectedOrdinal: 1,
|
|
1325
|
+
expectedSite: 'mode.primary',
|
|
1326
|
+
sessionPath,
|
|
1327
|
+
replacementPointer: JSON.stringify({ session_id: 'sess-replacement', cwd: wd }),
|
|
1328
|
+
beforePublish: () => { process.env.OMX_SESSION_ID = 'sess-replacement'; },
|
|
1329
|
+
});
|
|
1330
|
+
__setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: takeover.hook });
|
|
1331
|
+
const revalidate = createWritableCommitRevalidator({
|
|
1332
|
+
operation: 'state_write', cwd: wd, explicitSessionId: undefined, capturedScope, baseStateDir: stateDir,
|
|
1333
|
+
});
|
|
1334
|
+
await assert.rejects(() => revalidate({ site: 'mode.primary', kind: 'write', path: join(stateDir, 'mode-state.json') }), (error) => {
|
|
1335
|
+
assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite);
|
|
1336
|
+
return true;
|
|
1337
|
+
});
|
|
1338
|
+
assert.deepEqual(takeover.observed, [{
|
|
1339
|
+
commitOrdinal: 1,
|
|
1340
|
+
site: 'mode.primary',
|
|
1341
|
+
kind: 'write',
|
|
1342
|
+
path: join(stateDir, 'mode-state.json'),
|
|
1343
|
+
}]);
|
|
1344
|
+
}
|
|
1345
|
+
finally {
|
|
1346
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1347
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1348
|
+
await rm(wd, { recursive: true, force: true });
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
it('T3 clears recovery and revalidation hooks and resets snapshot ordinals', async () => {
|
|
1352
|
+
const wd = await mkRealTemp('omx-writable-hooks-clear-');
|
|
1353
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
1354
|
+
try {
|
|
1355
|
+
const stateDir = getBaseStateDir(wd);
|
|
1356
|
+
await mkdir(stateDir, { recursive: true });
|
|
1357
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
|
|
1358
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
1359
|
+
const oldCounters = { recovery: 0, revalidation: 0, decision: 0, stability: 0 };
|
|
1360
|
+
__setWritableStateScopeTestHooksForTests({
|
|
1361
|
+
beforeRecoveryReread: async () => { oldCounters.recovery += 1; },
|
|
1362
|
+
beforeScopeRevalidation: async () => { oldCounters.revalidation += 1; },
|
|
1363
|
+
onSelectedDecisionSnapshotRead: () => { oldCounters.decision += 1; },
|
|
1364
|
+
onRecoveryStabilityReread: () => { oldCounters.stability += 1; },
|
|
1365
|
+
});
|
|
1366
|
+
await resolveWritableStateScope(wd);
|
|
1367
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1368
|
+
await resolveWritableStateScope(wd);
|
|
1369
|
+
assert.deepEqual(oldCounters, { recovery: 1, revalidation: 0, decision: 1, stability: 1 });
|
|
1370
|
+
const restarted = [];
|
|
1371
|
+
__setWritableStateScopeTestHooksForTests({
|
|
1372
|
+
onSelectedDecisionSnapshotRead: ({ ordinal }) => restarted.push({ decision: ordinal, stability: 0 }),
|
|
1373
|
+
onRecoveryStabilityReread: ({ ordinal }) => {
|
|
1374
|
+
const event = restarted.at(-1);
|
|
1375
|
+
assert.ok(event);
|
|
1376
|
+
event.stability = ordinal;
|
|
1377
|
+
},
|
|
1378
|
+
});
|
|
1379
|
+
await resolveWritableStateScope(wd);
|
|
1380
|
+
assert.deepEqual(restarted, [{ decision: 1, stability: 1 }]);
|
|
1381
|
+
}
|
|
1382
|
+
finally {
|
|
1383
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
1384
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
1385
|
+
await rm(wd, { recursive: true, force: true });
|
|
1386
|
+
}
|
|
656
1387
|
});
|
|
657
1388
|
});
|
|
658
1389
|
//# sourceMappingURL=state-paths.test.js.map
|