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
|
@@ -4,10 +4,11 @@ import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises
|
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
5
|
import { dirname, join } from 'node:path';
|
|
6
6
|
import { tmpdir } from 'node:os';
|
|
7
|
-
import { executeStateOperation } from '../operations.js';
|
|
7
|
+
import { completeRalplanSession, executeStateOperation } from '../operations.js';
|
|
8
8
|
import { subagentTrackingPath } from '../../subagents/tracker.js';
|
|
9
|
-
import { updateModeState } from '../../modes/base.js';
|
|
10
|
-
import { WRITABLE_STATE_SCOPE_ERRORS } from '../../mcp/state-paths.js';
|
|
9
|
+
import { startMode, updateModeState } from '../../modes/base.js';
|
|
10
|
+
import { __setWritableStateScopeTestHooksForTests, getBaseStateDir, WRITABLE_STATE_SCOPE_ERRORS, } from '../../mcp/state-paths.js';
|
|
11
|
+
import { __resetSessionPointerTransactionDependenciesForTests, __setSessionPointerTransactionDependenciesForTests, } from '../../hooks/session.js';
|
|
11
12
|
async function withAmbientTmuxEnv(env, run) {
|
|
12
13
|
const previousTmux = process.env.TMUX;
|
|
13
14
|
const previousTmuxPane = process.env.TMUX_PANE;
|
|
@@ -172,6 +173,7 @@ function ralplanConsensusGate(sessionId, provenanceKind, threadOverrides = {}) {
|
|
|
172
173
|
ralplan_architect_review: {
|
|
173
174
|
agent_role: 'architect',
|
|
174
175
|
verdict: 'approve',
|
|
176
|
+
sequence_index: 1,
|
|
175
177
|
provenance_kind: provenanceKind,
|
|
176
178
|
session_id: sessionId,
|
|
177
179
|
thread_id: architectThread,
|
|
@@ -181,6 +183,7 @@ function ralplanConsensusGate(sessionId, provenanceKind, threadOverrides = {}) {
|
|
|
181
183
|
ralplan_critic_review: {
|
|
182
184
|
agent_role: 'critic',
|
|
183
185
|
verdict: 'approve',
|
|
186
|
+
sequence_index: 2,
|
|
184
187
|
provenance_kind: provenanceKind,
|
|
185
188
|
session_id: sessionId,
|
|
186
189
|
thread_id: criticThread,
|
|
@@ -793,7 +796,7 @@ describe('state operations directory initialization', () => {
|
|
|
793
796
|
const sessionId = 'sess-clear';
|
|
794
797
|
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
795
798
|
await mkdir(sessionDir, { recursive: true });
|
|
796
|
-
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
|
|
799
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: stateDir }, null, 2));
|
|
797
800
|
await writeFile(join(stateDir, 'deep-interview-state.json'), JSON.stringify({ active: true, mode: 'deep-interview', current_phase: 'legacy-root' }, null, 2));
|
|
798
801
|
await writeFile(join(sessionDir, 'deep-interview-state.json'), JSON.stringify({ active: true, mode: 'deep-interview', current_phase: 'session-active' }, null, 2));
|
|
799
802
|
await executeStateOperation('state_clear', {
|
|
@@ -854,6 +857,25 @@ describe('state operations directory initialization', () => {
|
|
|
854
857
|
await rm(wd, { recursive: true, force: true });
|
|
855
858
|
}
|
|
856
859
|
});
|
|
860
|
+
it('excludes derived run-state.json from active mode enumeration while preserving genuine mode state files', async () => {
|
|
861
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-derived-run-state-'));
|
|
862
|
+
try {
|
|
863
|
+
const sessionId = 'sess-derived-run-state';
|
|
864
|
+
const sessionDir = join(wd, '.omx', 'state', 'sessions', sessionId);
|
|
865
|
+
await mkdir(sessionDir, { recursive: true });
|
|
866
|
+
await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
|
|
867
|
+
await writeFile(join(sessionDir, 'run-state.json'), JSON.stringify({ active: true, mode: 'derived' }, null, 2));
|
|
868
|
+
await writeFile(join(sessionDir, 'autopilot-state.json'), JSON.stringify({ active: true, current_phase: 'executing' }, null, 2));
|
|
869
|
+
const response = await executeStateOperation('state_list_active', {
|
|
870
|
+
workingDirectory: wd,
|
|
871
|
+
session_id: sessionId,
|
|
872
|
+
});
|
|
873
|
+
assert.deepEqual(response.payload, { active_modes: ['autopilot'] });
|
|
874
|
+
}
|
|
875
|
+
finally {
|
|
876
|
+
await rm(wd, { recursive: true, force: true });
|
|
877
|
+
}
|
|
878
|
+
});
|
|
857
879
|
it('does not list a mode active when terminal canonical visibility contradicts an active detail state', async () => {
|
|
858
880
|
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-terminal-canonical-wins-'));
|
|
859
881
|
try {
|
|
@@ -893,7 +915,7 @@ describe('state operations directory initialization', () => {
|
|
|
893
915
|
const sessionId = 'sess-terminal-implicit';
|
|
894
916
|
const sessionDir = join(wd, '.omx', 'state', 'sessions', sessionId);
|
|
895
917
|
await mkdir(sessionDir, { recursive: true });
|
|
896
|
-
await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
|
|
918
|
+
await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: join(wd, '.omx', 'state') }, null, 2));
|
|
897
919
|
await writeFile(join(sessionDir, 'autopilot-state.json'), JSON.stringify({
|
|
898
920
|
active: true,
|
|
899
921
|
current_phase: 'deep-interview',
|
|
@@ -949,7 +971,7 @@ describe('state operations directory initialization', () => {
|
|
|
949
971
|
await rm(wd, { recursive: true, force: true });
|
|
950
972
|
}
|
|
951
973
|
});
|
|
952
|
-
it('
|
|
974
|
+
it('rejects a completed ralplan state transition when only local review lifecycle evidence is present', async () => {
|
|
953
975
|
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-complete-'));
|
|
954
976
|
try {
|
|
955
977
|
const sessionId = 'sess-ralplan-complete';
|
|
@@ -1005,36 +1027,38 @@ describe('state operations directory initialization', () => {
|
|
|
1005
1027
|
},
|
|
1006
1028
|
ralplan_consensus_gate: consensusGate,
|
|
1007
1029
|
});
|
|
1008
|
-
assert.equal(response.isError,
|
|
1030
|
+
assert.equal(response.isError, true);
|
|
1031
|
+
assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
|
|
1009
1032
|
const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
|
|
1010
1033
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1011
1034
|
for (const state of [rootRalplan, sessionRalplan]) {
|
|
1012
|
-
assert.equal(state.active,
|
|
1013
|
-
assert.equal(state.current_phase, '
|
|
1014
|
-
assert.equal(state.status,
|
|
1015
|
-
assert.equal(state.terminal_reason, 'consensus approved bounded no-op');
|
|
1016
|
-
assert.equal(state.ralplan_consensus_gate.complete, true);
|
|
1035
|
+
assert.equal(state.active, true);
|
|
1036
|
+
assert.equal(state.current_phase, 'planning');
|
|
1037
|
+
assert.equal(state.status, undefined);
|
|
1017
1038
|
assert.equal(state.session_id, sessionId);
|
|
1018
1039
|
}
|
|
1019
1040
|
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1020
1041
|
const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
|
|
1021
1042
|
for (const state of [rootSkill, sessionSkill]) {
|
|
1022
|
-
assert.equal(state.active,
|
|
1023
|
-
assert.equal(state.phase, '
|
|
1024
|
-
assert.
|
|
1025
|
-
|
|
1043
|
+
assert.equal(state.active, true);
|
|
1044
|
+
assert.equal(state.phase, 'planning');
|
|
1045
|
+
assert.deepEqual(state.active_skills, [{
|
|
1046
|
+
skill: 'ralplan',
|
|
1047
|
+
phase: 'planning',
|
|
1048
|
+
active: true,
|
|
1049
|
+
session_id: sessionId,
|
|
1050
|
+
}]);
|
|
1026
1051
|
}
|
|
1027
|
-
assert.equal(sessionSkill.session_id, sessionId);
|
|
1028
1052
|
const listed = await executeStateOperation('state_list_active', {
|
|
1029
1053
|
workingDirectory: wd,
|
|
1030
1054
|
});
|
|
1031
|
-
assert.deepEqual(listed.payload, { active_modes: [] });
|
|
1055
|
+
assert.deepEqual(listed.payload, { active_modes: ['ralplan'] });
|
|
1032
1056
|
}
|
|
1033
1057
|
finally {
|
|
1034
1058
|
await rm(wd, { recursive: true, force: true });
|
|
1035
1059
|
}
|
|
1036
1060
|
});
|
|
1037
|
-
it('
|
|
1061
|
+
it('rejects a ralplan release when runtime and workspace trackers only provide local review lifecycle evidence', async () => {
|
|
1038
1062
|
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-runtime-lag-complete-'));
|
|
1039
1063
|
const stateRoot = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-runtime-lag-root-'));
|
|
1040
1064
|
try {
|
|
@@ -1100,13 +1124,12 @@ describe('state operations directory initialization', () => {
|
|
|
1100
1124
|
terminal_reason: 'consensus approved despite runtime tracker lag',
|
|
1101
1125
|
ralplan_consensus_gate: consensusGate,
|
|
1102
1126
|
});
|
|
1103
|
-
assert.equal(response.isError,
|
|
1127
|
+
assert.equal(response.isError, true);
|
|
1128
|
+
assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
|
|
1104
1129
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1105
|
-
assert.equal(sessionRalplan.active,
|
|
1106
|
-
assert.equal(sessionRalplan.current_phase, '
|
|
1107
|
-
assert.equal(sessionRalplan.status,
|
|
1108
|
-
assert.equal(sessionRalplan.terminal_reason, 'consensus approved despite runtime tracker lag');
|
|
1109
|
-
assert.equal(sessionRalplan.ralplan_consensus_gate.complete, true);
|
|
1130
|
+
assert.equal(sessionRalplan.active, true);
|
|
1131
|
+
assert.equal(sessionRalplan.current_phase, 'planning');
|
|
1132
|
+
assert.equal(sessionRalplan.status, undefined);
|
|
1110
1133
|
});
|
|
1111
1134
|
}
|
|
1112
1135
|
finally {
|
|
@@ -1142,7 +1165,7 @@ describe('state operations directory initialization', () => {
|
|
|
1142
1165
|
},
|
|
1143
1166
|
});
|
|
1144
1167
|
assert.equal(response.isError, true);
|
|
1145
|
-
assert.match(String(response.payload.error ?? ''), /
|
|
1168
|
+
assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
|
|
1146
1169
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1147
1170
|
assert.equal(sessionRalplan.active, true);
|
|
1148
1171
|
assert.equal(sessionRalplan.current_phase, 'planning');
|
|
@@ -1455,7 +1478,7 @@ describe('state operations directory initialization', () => {
|
|
|
1455
1478
|
currentPhase: 'complete',
|
|
1456
1479
|
});
|
|
1457
1480
|
assert.equal(response.isError, true);
|
|
1458
|
-
assert.match(String(response.payload.error ?? ''), /
|
|
1481
|
+
assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
|
|
1459
1482
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1460
1483
|
assert.equal(sessionRalplan.active, true);
|
|
1461
1484
|
assert.equal(sessionRalplan.current_phase, 'planning');
|
|
@@ -1465,7 +1488,7 @@ describe('state operations directory initialization', () => {
|
|
|
1465
1488
|
await rm(wd, { recursive: true, force: true });
|
|
1466
1489
|
}
|
|
1467
1490
|
});
|
|
1468
|
-
it('
|
|
1491
|
+
it('rejects terminal writes that reuse existing local tracker review lifecycle evidence', async () => {
|
|
1469
1492
|
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-existing-consensus-'));
|
|
1470
1493
|
try {
|
|
1471
1494
|
const sessionId = 'sess-ralplan-existing-consensus';
|
|
@@ -1491,10 +1514,11 @@ describe('state operations directory initialization', () => {
|
|
|
1491
1514
|
current_phase: 'complete',
|
|
1492
1515
|
terminal_reason: 'existing tracker-backed consensus complete',
|
|
1493
1516
|
});
|
|
1494
|
-
assert.equal(response.isError,
|
|
1517
|
+
assert.equal(response.isError, true);
|
|
1518
|
+
assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
|
|
1495
1519
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1496
|
-
assert.equal(sessionRalplan.active,
|
|
1497
|
-
assert.equal(sessionRalplan.current_phase, '
|
|
1520
|
+
assert.equal(sessionRalplan.active, true);
|
|
1521
|
+
assert.equal(sessionRalplan.current_phase, 'planning');
|
|
1498
1522
|
const finalGate = sessionRalplan.ralplan_consensus_gate;
|
|
1499
1523
|
assert.equal(finalGate.complete, true);
|
|
1500
1524
|
assert.deepEqual(finalGate.required_review_roles, ['architect', 'critic']);
|
|
@@ -1505,7 +1529,7 @@ describe('state operations directory initialization', () => {
|
|
|
1505
1529
|
await rm(wd, { recursive: true, force: true });
|
|
1506
1530
|
}
|
|
1507
1531
|
});
|
|
1508
|
-
it('
|
|
1532
|
+
it('updateModeState rejects completed ralplan release without an official host receipt', async () => {
|
|
1509
1533
|
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-complete-update-mode-'));
|
|
1510
1534
|
try {
|
|
1511
1535
|
const sessionId = 'sess-ralplan-complete-update-mode';
|
|
@@ -1544,39 +1568,41 @@ describe('state operations directory initialization', () => {
|
|
|
1544
1568
|
};
|
|
1545
1569
|
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify(staleSkillState, null, 2));
|
|
1546
1570
|
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify(staleSkillState, null, 2));
|
|
1547
|
-
await updateModeState('ralplan', {
|
|
1571
|
+
await assert.rejects(() => updateModeState('ralplan', {
|
|
1548
1572
|
active: false,
|
|
1549
1573
|
current_phase: 'complete',
|
|
1550
1574
|
terminal_reason: 'runtime consensus complete',
|
|
1551
1575
|
ralplan_consensus_gate: consensusGate,
|
|
1552
|
-
}, wd);
|
|
1576
|
+
}, wd), /documented_host_consensus_receipt_unavailable/);
|
|
1553
1577
|
const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
|
|
1554
1578
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1555
1579
|
for (const state of [rootRalplan, sessionRalplan]) {
|
|
1556
|
-
assert.equal(state.active,
|
|
1557
|
-
assert.equal(state.current_phase, '
|
|
1558
|
-
assert.equal(state.status,
|
|
1559
|
-
assert.equal(state.terminal_reason, 'runtime consensus complete');
|
|
1560
|
-
assert.equal(state.ralplan_consensus_gate.complete, true);
|
|
1580
|
+
assert.equal(state.active, true);
|
|
1581
|
+
assert.equal(state.current_phase, 'planning');
|
|
1582
|
+
assert.equal(state.status, undefined);
|
|
1561
1583
|
assert.equal(state.session_id, sessionId);
|
|
1562
1584
|
}
|
|
1563
1585
|
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1564
1586
|
const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
|
|
1565
1587
|
for (const state of [rootSkill, sessionSkill]) {
|
|
1566
|
-
assert.equal(state.active,
|
|
1567
|
-
assert.equal(state.phase, '
|
|
1568
|
-
assert.
|
|
1569
|
-
|
|
1588
|
+
assert.equal(state.active, true);
|
|
1589
|
+
assert.equal(state.phase, 'planning');
|
|
1590
|
+
assert.deepEqual(state.active_skills, [{
|
|
1591
|
+
skill: 'ralplan',
|
|
1592
|
+
phase: 'planning',
|
|
1593
|
+
active: true,
|
|
1594
|
+
session_id: sessionId,
|
|
1595
|
+
}]);
|
|
1570
1596
|
}
|
|
1571
1597
|
const rootListed = await executeStateOperation('state_list_active', {
|
|
1572
1598
|
workingDirectory: wd,
|
|
1573
1599
|
});
|
|
1574
|
-
assert.deepEqual(rootListed.payload, { active_modes: [] });
|
|
1600
|
+
assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
|
|
1575
1601
|
const sessionListed = await executeStateOperation('state_list_active', {
|
|
1576
1602
|
workingDirectory: wd,
|
|
1577
1603
|
session_id: sessionId,
|
|
1578
1604
|
});
|
|
1579
|
-
assert.deepEqual(sessionListed.payload, { active_modes: [] });
|
|
1605
|
+
assert.deepEqual(sessionListed.payload, { active_modes: ['ralplan'] });
|
|
1580
1606
|
}
|
|
1581
1607
|
finally {
|
|
1582
1608
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -1606,7 +1632,7 @@ describe('state operations directory initialization', () => {
|
|
|
1606
1632
|
ralplan_consensus_gate: {
|
|
1607
1633
|
complete: true,
|
|
1608
1634
|
},
|
|
1609
|
-
}, wd), /
|
|
1635
|
+
}, wd), /documented_host_consensus_receipt_unavailable/);
|
|
1610
1636
|
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1611
1637
|
assert.equal(sessionRalplan.active, true);
|
|
1612
1638
|
assert.equal(sessionRalplan.current_phase, 'planning');
|
|
@@ -1637,7 +1663,7 @@ describe('state operations directory initialization', () => {
|
|
|
1637
1663
|
await writeFile(join(stateDir, 'run-state.json'), JSON.stringify(runState, null, 2));
|
|
1638
1664
|
const beforeList = await executeStateOperation('state_list_active', { workingDirectory: wd });
|
|
1639
1665
|
const beforeTeam = await executeStateOperation('state_read', { workingDirectory: wd, mode: 'team' });
|
|
1640
|
-
assert.deepEqual(beforeList.payload, { active_modes: [
|
|
1666
|
+
assert.deepEqual(beforeList.payload, { active_modes: [] });
|
|
1641
1667
|
assert.deepEqual(beforeTeam.payload, teamState);
|
|
1642
1668
|
const response = await executeStateOperation('state_write', {
|
|
1643
1669
|
workingDirectory: wd,
|
|
@@ -1645,844 +1671,125 @@ describe('state operations directory initialization', () => {
|
|
|
1645
1671
|
active: true,
|
|
1646
1672
|
current_phase: 'deep-interview',
|
|
1647
1673
|
state: { interview_id: 'fixture', profile: 'quick', type: 'brownfield' },
|
|
1648
|
-
});
|
|
1649
|
-
const payload = responsePayload(response);
|
|
1650
|
-
assert.equal(payload.success, true);
|
|
1651
|
-
assert.equal(payload.path, join(stateDir, 'deep-interview-state.json'));
|
|
1652
|
-
assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'team-state.json'), 'utf-8')), teamState);
|
|
1653
|
-
assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'run-state.json'), 'utf-8')), runState);
|
|
1654
|
-
assert.equal(existsSync(join(stateDir, 'sessions', 'foreign-team-session', 'deep-interview-state.json')), false);
|
|
1655
|
-
assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8')), foreignSkillState);
|
|
1656
|
-
const afterList = await executeStateOperation('state_list_active', { workingDirectory: wd });
|
|
1657
|
-
assert.deepEqual(afterList.payload, { active_modes: ['deep-interview'
|
|
1658
|
-
}
|
|
1659
|
-
finally {
|
|
1660
|
-
await rm(wd, { recursive: true, force: true });
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
});
|
|
1664
|
-
it('fails closed without mutating root state when ralplan terminalization sees a foreign session pointer', async () => {
|
|
1665
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-stale-session-'));
|
|
1666
|
-
try {
|
|
1667
|
-
const staleSessionId = 'sess-ralplan-stale';
|
|
1668
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, staleSessionId);
|
|
1669
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
1670
|
-
const sessionDir = join(stateDir, 'sessions', staleSessionId);
|
|
1671
|
-
await mkdir(stateDir, { recursive: true });
|
|
1672
|
-
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
1673
|
-
session_id: staleSessionId,
|
|
1674
|
-
cwd: join(wd, 'different-project'),
|
|
1675
|
-
}, null, 2));
|
|
1676
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
1677
|
-
mode: 'ralplan',
|
|
1678
|
-
active: true,
|
|
1679
|
-
current_phase: 'planning',
|
|
1680
|
-
session_id: staleSessionId,
|
|
1681
|
-
}, null, 2));
|
|
1682
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
1683
|
-
version: 1,
|
|
1684
|
-
active: true,
|
|
1685
|
-
skill: 'ralplan',
|
|
1686
|
-
phase: 'planning',
|
|
1687
|
-
session_id: staleSessionId,
|
|
1688
|
-
active_skills: [
|
|
1689
|
-
{
|
|
1690
|
-
skill: 'ralplan',
|
|
1691
|
-
phase: 'planning',
|
|
1692
|
-
active: true,
|
|
1693
|
-
},
|
|
1694
|
-
{
|
|
1695
|
-
skill: 'ralplan',
|
|
1696
|
-
phase: 'planning',
|
|
1697
|
-
active: true,
|
|
1698
|
-
session_id: staleSessionId,
|
|
1699
|
-
},
|
|
1700
|
-
],
|
|
1701
|
-
}, null, 2));
|
|
1702
|
-
const response = await executeStateOperation('state_write', {
|
|
1703
|
-
workingDirectory: wd,
|
|
1704
|
-
mode: 'ralplan',
|
|
1705
|
-
active: false,
|
|
1706
|
-
current_phase: 'complete',
|
|
1707
|
-
status: 'complete',
|
|
1708
|
-
terminal_reason: 'consensus approved bounded no-op',
|
|
1709
|
-
state: {
|
|
1710
|
-
session_id: staleSessionId,
|
|
1711
|
-
ralplan_consensus_gate: consensusGate,
|
|
1712
|
-
},
|
|
1713
|
-
});
|
|
1714
|
-
assert.equal(response.isError, true);
|
|
1715
|
-
assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.unusableSession });
|
|
1716
|
-
const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
|
|
1717
|
-
assert.equal(rootRalplan.active, true);
|
|
1718
|
-
assert.equal(rootRalplan.current_phase, 'planning');
|
|
1719
|
-
assert.equal(rootRalplan.session_id, staleSessionId);
|
|
1720
|
-
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1721
|
-
assert.equal(rootSkill.active, true);
|
|
1722
|
-
assert.equal(rootSkill.phase, 'planning');
|
|
1723
|
-
assert.equal(Array.isArray(rootSkill.active_skills), true);
|
|
1724
|
-
assert.equal(existsSync(join(sessionDir, 'ralplan-state.json')), false);
|
|
1725
|
-
assert.equal(existsSync(join(sessionDir, 'skill-active-state.json')), false);
|
|
1726
|
-
const listed = await executeStateOperation('state_list_active', {
|
|
1727
|
-
workingDirectory: wd,
|
|
1728
|
-
});
|
|
1729
|
-
assert.deepEqual(listed.payload, { active_modes: ['ralplan'] });
|
|
1730
|
-
}
|
|
1731
|
-
finally {
|
|
1732
|
-
await rm(wd, { recursive: true, force: true });
|
|
1733
|
-
}
|
|
1734
|
-
});
|
|
1735
|
-
it('does not hide unrelated root detail state when ralplan terminalizes without canonical state', async () => {
|
|
1736
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-root-detail-only-'));
|
|
1737
|
-
try {
|
|
1738
|
-
const sessionId = 'sess-ralplan-root-detail-only';
|
|
1739
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
1740
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
1741
|
-
await mkdir(stateDir, { recursive: true });
|
|
1742
|
-
await writeFile(join(stateDir, 'team-state.json'), JSON.stringify({
|
|
1743
|
-
mode: 'team',
|
|
1744
|
-
active: true,
|
|
1745
|
-
current_phase: 'running',
|
|
1746
|
-
}, null, 2));
|
|
1747
|
-
const response = await executeStateOperation('state_write', {
|
|
1748
|
-
workingDirectory: wd,
|
|
1749
|
-
mode: 'ralplan',
|
|
1750
|
-
active: false,
|
|
1751
|
-
current_phase: 'complete',
|
|
1752
|
-
state: {
|
|
1753
|
-
session_id: sessionId,
|
|
1754
|
-
ralplan_consensus_gate: consensusGate,
|
|
1755
|
-
},
|
|
1756
|
-
});
|
|
1757
|
-
assert.equal(response.isError, undefined);
|
|
1758
|
-
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
1759
|
-
const listed = await executeStateOperation('state_list_active', {
|
|
1760
|
-
workingDirectory: wd,
|
|
1761
|
-
});
|
|
1762
|
-
assert.deepEqual(listed.payload, { active_modes: ['team'] });
|
|
1763
|
-
}
|
|
1764
|
-
finally {
|
|
1765
|
-
await rm(wd, { recursive: true, force: true });
|
|
1766
|
-
}
|
|
1767
|
-
});
|
|
1768
|
-
it('preserves an unrelated active root ralplan when a session ralplan terminalizes', async () => {
|
|
1769
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-preserve-root-'));
|
|
1770
|
-
try {
|
|
1771
|
-
const sessionId = 'sess-ralplan-preserve-root';
|
|
1772
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
1773
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
1774
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
1775
|
-
await mkdir(sessionDir, { recursive: true });
|
|
1776
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
1777
|
-
mode: 'ralplan',
|
|
1778
|
-
active: true,
|
|
1779
|
-
current_phase: 'planning',
|
|
1780
|
-
}, null, 2));
|
|
1781
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
1782
|
-
mode: 'ralplan',
|
|
1783
|
-
active: true,
|
|
1784
|
-
current_phase: 'planning',
|
|
1785
|
-
session_id: sessionId,
|
|
1786
|
-
}, null, 2));
|
|
1787
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
1788
|
-
version: 1,
|
|
1789
|
-
active: true,
|
|
1790
|
-
skill: 'ralplan',
|
|
1791
|
-
phase: 'planning',
|
|
1792
|
-
active_skills: [
|
|
1793
|
-
{
|
|
1794
|
-
skill: 'ralplan',
|
|
1795
|
-
phase: 'planning',
|
|
1796
|
-
active: true,
|
|
1797
|
-
},
|
|
1798
|
-
{
|
|
1799
|
-
skill: 'ralplan',
|
|
1800
|
-
phase: 'planning',
|
|
1801
|
-
active: true,
|
|
1802
|
-
session_id: sessionId,
|
|
1803
|
-
},
|
|
1804
|
-
],
|
|
1805
|
-
}, null, 2));
|
|
1806
|
-
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
|
|
1807
|
-
version: 1,
|
|
1808
|
-
active: true,
|
|
1809
|
-
skill: 'ralplan',
|
|
1810
|
-
phase: 'planning',
|
|
1811
|
-
session_id: sessionId,
|
|
1812
|
-
active_skills: [{
|
|
1813
|
-
skill: 'ralplan',
|
|
1814
|
-
phase: 'planning',
|
|
1815
|
-
active: true,
|
|
1816
|
-
session_id: sessionId,
|
|
1817
|
-
}],
|
|
1818
|
-
}, null, 2));
|
|
1819
|
-
const response = await executeStateOperation('state_write', {
|
|
1820
|
-
workingDirectory: wd,
|
|
1821
|
-
session_id: sessionId,
|
|
1822
|
-
mode: 'ralplan',
|
|
1823
|
-
active: false,
|
|
1824
|
-
current_phase: 'complete',
|
|
1825
|
-
status: 'complete',
|
|
1826
|
-
terminal_reason: 'consensus approved bounded no-op',
|
|
1827
|
-
ralplan_consensus_gate: consensusGate,
|
|
1828
|
-
});
|
|
1829
|
-
assert.equal(response.isError, undefined);
|
|
1830
|
-
const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
|
|
1831
|
-
assert.equal(rootRalplan.active, true);
|
|
1832
|
-
assert.equal(rootRalplan.current_phase, 'planning');
|
|
1833
|
-
assert.equal(rootRalplan.session_id, undefined);
|
|
1834
|
-
const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
|
|
1835
|
-
assert.equal(sessionRalplan.active, false);
|
|
1836
|
-
assert.equal(sessionRalplan.current_phase, 'complete');
|
|
1837
|
-
assert.equal(sessionRalplan.session_id, sessionId);
|
|
1838
|
-
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1839
|
-
assert.equal(rootSkill.active, true);
|
|
1840
|
-
assert.equal(rootSkill.skill, 'ralplan');
|
|
1841
|
-
assert.deepEqual(rootSkill.active_skills, [{ skill: 'ralplan', phase: 'planning', active: true }]);
|
|
1842
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
1843
|
-
workingDirectory: wd,
|
|
1844
|
-
});
|
|
1845
|
-
assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
|
|
1846
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
1847
|
-
workingDirectory: wd,
|
|
1848
|
-
session_id: sessionId,
|
|
1849
|
-
});
|
|
1850
|
-
assert.deepEqual(sessionListed.payload, { active_modes: [] });
|
|
1851
|
-
}
|
|
1852
|
-
finally {
|
|
1853
|
-
await rm(wd, { recursive: true, force: true });
|
|
1854
|
-
}
|
|
1855
|
-
});
|
|
1856
|
-
it('does not hide a legacy active root ralplan detail state when a session ralplan terminalizes', async () => {
|
|
1857
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-legacy-root-detail-'));
|
|
1858
|
-
try {
|
|
1859
|
-
const sessionId = 'sess-ralplan-legacy-root-detail';
|
|
1860
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
1861
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
1862
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
1863
|
-
await mkdir(sessionDir, { recursive: true });
|
|
1864
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
1865
|
-
mode: 'ralplan',
|
|
1866
|
-
active: true,
|
|
1867
|
-
current_phase: 'planning',
|
|
1868
|
-
}, null, 2));
|
|
1869
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
1870
|
-
mode: 'ralplan',
|
|
1871
|
-
active: true,
|
|
1872
|
-
current_phase: 'planning',
|
|
1873
|
-
session_id: sessionId,
|
|
1874
|
-
}, null, 2));
|
|
1875
|
-
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
|
|
1876
|
-
version: 1,
|
|
1877
|
-
active: true,
|
|
1878
|
-
skill: 'ralplan',
|
|
1879
|
-
phase: 'planning',
|
|
1880
|
-
session_id: sessionId,
|
|
1881
|
-
active_skills: [{
|
|
1882
|
-
skill: 'ralplan',
|
|
1883
|
-
phase: 'planning',
|
|
1884
|
-
active: true,
|
|
1885
|
-
session_id: sessionId,
|
|
1886
|
-
}],
|
|
1887
|
-
}, null, 2));
|
|
1888
|
-
const response = await executeStateOperation('state_write', {
|
|
1889
|
-
workingDirectory: wd,
|
|
1890
|
-
session_id: sessionId,
|
|
1891
|
-
mode: 'ralplan',
|
|
1892
|
-
active: false,
|
|
1893
|
-
current_phase: 'complete',
|
|
1894
|
-
ralplan_consensus_gate: consensusGate,
|
|
1895
|
-
});
|
|
1896
|
-
assert.equal(response.isError, undefined);
|
|
1897
|
-
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
1898
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
1899
|
-
workingDirectory: wd,
|
|
1900
|
-
});
|
|
1901
|
-
assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
|
|
1902
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
1903
|
-
workingDirectory: wd,
|
|
1904
|
-
session_id: sessionId,
|
|
1905
|
-
});
|
|
1906
|
-
assert.deepEqual(sessionListed.payload, { active_modes: [] });
|
|
1907
|
-
}
|
|
1908
|
-
finally {
|
|
1909
|
-
await rm(wd, { recursive: true, force: true });
|
|
1910
|
-
}
|
|
1911
|
-
});
|
|
1912
|
-
it('removes an empty session-only root mirror when a session ralplan terminalizes', async () => {
|
|
1913
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-empty-root-mirror-'));
|
|
1914
|
-
try {
|
|
1915
|
-
const sessionId = 'sess-ralplan-empty-root-mirror';
|
|
1916
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
1917
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
1918
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
1919
|
-
await mkdir(sessionDir, { recursive: true });
|
|
1920
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
1921
|
-
mode: 'ralplan',
|
|
1922
|
-
active: true,
|
|
1923
|
-
current_phase: 'planning',
|
|
1924
|
-
}, null, 2));
|
|
1925
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
1926
|
-
mode: 'ralplan',
|
|
1927
|
-
active: true,
|
|
1928
|
-
current_phase: 'planning',
|
|
1929
|
-
session_id: sessionId,
|
|
1930
|
-
}, null, 2));
|
|
1931
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
1932
|
-
version: 1,
|
|
1933
|
-
active: true,
|
|
1934
|
-
skill: 'ralplan',
|
|
1935
|
-
phase: 'planning',
|
|
1936
|
-
session_id: sessionId,
|
|
1937
|
-
active_skills: [{
|
|
1938
|
-
skill: 'ralplan',
|
|
1939
|
-
phase: 'planning',
|
|
1940
|
-
active: true,
|
|
1941
|
-
session_id: sessionId,
|
|
1942
|
-
}],
|
|
1943
|
-
}, null, 2));
|
|
1944
|
-
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
|
|
1945
|
-
version: 1,
|
|
1946
|
-
active: true,
|
|
1947
|
-
skill: 'ralplan',
|
|
1948
|
-
phase: 'planning',
|
|
1949
|
-
session_id: sessionId,
|
|
1950
|
-
active_skills: [{
|
|
1951
|
-
skill: 'ralplan',
|
|
1952
|
-
phase: 'planning',
|
|
1953
|
-
active: true,
|
|
1954
|
-
session_id: sessionId,
|
|
1955
|
-
}],
|
|
1956
|
-
}, null, 2));
|
|
1957
|
-
const response = await executeStateOperation('state_write', {
|
|
1958
|
-
workingDirectory: wd,
|
|
1959
|
-
session_id: sessionId,
|
|
1960
|
-
mode: 'ralplan',
|
|
1961
|
-
active: false,
|
|
1962
|
-
current_phase: 'complete',
|
|
1963
|
-
ralplan_consensus_gate: consensusGate,
|
|
1964
|
-
});
|
|
1965
|
-
assert.equal(response.isError, undefined);
|
|
1966
|
-
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
1967
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
1968
|
-
workingDirectory: wd,
|
|
1969
|
-
});
|
|
1970
|
-
assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
|
|
1971
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
1972
|
-
workingDirectory: wd,
|
|
1973
|
-
session_id: sessionId,
|
|
1974
|
-
});
|
|
1975
|
-
assert.deepEqual(sessionListed.payload, { active_modes: [] });
|
|
1976
|
-
}
|
|
1977
|
-
finally {
|
|
1978
|
-
await rm(wd, { recursive: true, force: true });
|
|
1979
|
-
}
|
|
1980
|
-
});
|
|
1981
|
-
it('preserves run_outcome-only root canonical tombstones when a session ralplan terminalizes', async () => {
|
|
1982
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-preserve-root-tombstone-'));
|
|
1983
|
-
try {
|
|
1984
|
-
const sessionId = 'sess-ralplan-root-tombstone';
|
|
1985
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
1986
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
1987
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
1988
|
-
await mkdir(sessionDir, { recursive: true });
|
|
1989
|
-
await writeFile(join(stateDir, 'team-state.json'), JSON.stringify({
|
|
1990
|
-
mode: 'team',
|
|
1991
|
-
active: true,
|
|
1992
|
-
current_phase: 'running',
|
|
1993
|
-
}, null, 2));
|
|
1994
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
1995
|
-
mode: 'ralplan',
|
|
1996
|
-
active: true,
|
|
1997
|
-
current_phase: 'planning',
|
|
1998
|
-
}, null, 2));
|
|
1999
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2000
|
-
mode: 'ralplan',
|
|
2001
|
-
active: true,
|
|
2002
|
-
current_phase: 'planning',
|
|
2003
|
-
session_id: sessionId,
|
|
2004
|
-
}, null, 2));
|
|
2005
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
2006
|
-
version: 1,
|
|
2007
|
-
active: true,
|
|
2008
|
-
skill: 'team',
|
|
2009
|
-
run_outcome: 'finish',
|
|
2010
|
-
active_skills: [{
|
|
2011
|
-
skill: 'team',
|
|
2012
|
-
active: true,
|
|
2013
|
-
}],
|
|
2014
|
-
}, null, 2));
|
|
2015
|
-
const before = await executeStateOperation('state_list_active', {
|
|
2016
|
-
workingDirectory: wd,
|
|
2017
|
-
});
|
|
2018
|
-
assert.deepEqual(before.payload, { active_modes: [] });
|
|
2019
|
-
const response = await executeStateOperation('state_write', {
|
|
2020
|
-
workingDirectory: wd,
|
|
2021
|
-
session_id: sessionId,
|
|
2022
|
-
mode: 'ralplan',
|
|
2023
|
-
active: false,
|
|
2024
|
-
current_phase: 'complete',
|
|
2025
|
-
ralplan_consensus_gate: consensusGate,
|
|
2026
|
-
});
|
|
2027
|
-
assert.equal(response.isError, undefined);
|
|
2028
|
-
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2029
|
-
assert.equal(rootSkill.active, true);
|
|
2030
|
-
assert.equal(rootSkill.run_outcome, 'finish');
|
|
2031
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
2032
|
-
workingDirectory: wd,
|
|
2033
|
-
});
|
|
2034
|
-
assert.deepEqual(rootListed.payload, { active_modes: [] });
|
|
2035
|
-
}
|
|
2036
|
-
finally {
|
|
2037
|
-
await rm(wd, { recursive: true, force: true });
|
|
2038
|
-
}
|
|
2039
|
-
});
|
|
2040
|
-
it('removes terminal_reason-only active root canonical state when a session ralplan terminalizes', async () => {
|
|
2041
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-terminal-reason-only-'));
|
|
2042
|
-
try {
|
|
2043
|
-
const sessionId = 'sess-ralplan-terminal-reason-only';
|
|
2044
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
2045
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
2046
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2047
|
-
await mkdir(sessionDir, { recursive: true });
|
|
2048
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
2049
|
-
mode: 'ralplan',
|
|
2050
|
-
active: true,
|
|
2051
|
-
current_phase: 'planning',
|
|
2052
|
-
}, null, 2));
|
|
2053
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2054
|
-
mode: 'ralplan',
|
|
2055
|
-
active: true,
|
|
2056
|
-
current_phase: 'planning',
|
|
2057
|
-
session_id: sessionId,
|
|
2058
|
-
}, null, 2));
|
|
2059
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
2060
|
-
version: 1,
|
|
2061
|
-
active: true,
|
|
2062
|
-
skill: 'ralplan',
|
|
2063
|
-
terminal_reason: 'stale reason without terminal marker',
|
|
2064
|
-
active_skills: [{
|
|
2065
|
-
skill: 'ralplan',
|
|
2066
|
-
active: true,
|
|
2067
|
-
session_id: sessionId,
|
|
2068
|
-
}],
|
|
2069
|
-
}, null, 2));
|
|
2070
|
-
const before = await executeStateOperation('state_list_active', {
|
|
2071
|
-
workingDirectory: wd,
|
|
2072
|
-
session_id: sessionId,
|
|
2073
|
-
});
|
|
2074
|
-
assert.deepEqual(before.payload, { active_modes: ['ralplan'] });
|
|
2075
|
-
const response = await executeStateOperation('state_write', {
|
|
2076
|
-
workingDirectory: wd,
|
|
2077
|
-
session_id: sessionId,
|
|
2078
|
-
mode: 'ralplan',
|
|
2079
|
-
active: false,
|
|
2080
|
-
current_phase: 'complete',
|
|
2081
|
-
ralplan_consensus_gate: consensusGate,
|
|
2082
|
-
});
|
|
2083
|
-
assert.equal(response.isError, undefined);
|
|
2084
|
-
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
2085
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
2086
|
-
workingDirectory: wd,
|
|
2087
|
-
});
|
|
2088
|
-
assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
|
|
2089
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
2090
|
-
workingDirectory: wd,
|
|
2091
|
-
session_id: sessionId,
|
|
2092
|
-
});
|
|
2093
|
-
assert.deepEqual(sessionListed.payload, { active_modes: [] });
|
|
2094
|
-
}
|
|
2095
|
-
finally {
|
|
2096
|
-
await rm(wd, { recursive: true, force: true });
|
|
2097
|
-
}
|
|
2098
|
-
});
|
|
2099
|
-
it('removes non-terminal lifecycle_outcome root canonical state when a session ralplan terminalizes', async () => {
|
|
2100
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-lifecycle-nonterminal-'));
|
|
2101
|
-
try {
|
|
2102
|
-
const sessionId = 'sess-ralplan-lifecycle-nonterminal';
|
|
2103
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
2104
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
2105
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2106
|
-
await mkdir(sessionDir, { recursive: true });
|
|
2107
|
-
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
2108
|
-
mode: 'ralplan',
|
|
2109
|
-
active: true,
|
|
2110
|
-
current_phase: 'planning',
|
|
2111
|
-
}, null, 2));
|
|
2112
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2113
|
-
mode: 'ralplan',
|
|
2114
|
-
active: true,
|
|
2115
|
-
current_phase: 'planning',
|
|
2116
|
-
session_id: sessionId,
|
|
2117
|
-
}, null, 2));
|
|
2118
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
2119
|
-
version: 1,
|
|
2120
|
-
active: true,
|
|
2121
|
-
skill: 'ralplan',
|
|
2122
|
-
lifecycle_outcome: 'progress',
|
|
2123
|
-
active_skills: [{
|
|
2124
|
-
skill: 'ralplan',
|
|
2125
|
-
active: true,
|
|
2126
|
-
session_id: sessionId,
|
|
2127
|
-
}],
|
|
2128
|
-
}, null, 2));
|
|
2129
|
-
const before = await executeStateOperation('state_list_active', {
|
|
2130
|
-
workingDirectory: wd,
|
|
2131
|
-
session_id: sessionId,
|
|
2132
|
-
});
|
|
2133
|
-
assert.deepEqual(before.payload, { active_modes: ['ralplan'] });
|
|
2134
|
-
const response = await executeStateOperation('state_write', {
|
|
2135
|
-
workingDirectory: wd,
|
|
2136
|
-
session_id: sessionId,
|
|
2137
|
-
mode: 'ralplan',
|
|
2138
|
-
active: false,
|
|
2139
|
-
current_phase: 'complete',
|
|
2140
|
-
ralplan_consensus_gate: consensusGate,
|
|
2141
|
-
});
|
|
2142
|
-
assert.equal(response.isError, undefined);
|
|
2143
|
-
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
2144
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
2145
|
-
workingDirectory: wd,
|
|
2146
|
-
});
|
|
2147
|
-
assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
|
|
2148
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
2149
|
-
workingDirectory: wd,
|
|
2150
|
-
session_id: sessionId,
|
|
2151
|
-
});
|
|
2152
|
-
assert.deepEqual(sessionListed.payload, { active_modes: [] });
|
|
2153
|
-
}
|
|
2154
|
-
finally {
|
|
2155
|
-
await rm(wd, { recursive: true, force: true });
|
|
2156
|
-
}
|
|
2157
|
-
});
|
|
2158
|
-
it('preserves unrelated active session skills when ralplan terminalizes', async () => {
|
|
2159
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-preserve-'));
|
|
2160
|
-
try {
|
|
2161
|
-
const sessionId = 'sess-ralplan-preserve';
|
|
2162
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
2163
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
2164
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2165
|
-
await mkdir(sessionDir, { recursive: true });
|
|
2166
|
-
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
2167
|
-
session_id: sessionId,
|
|
2168
|
-
cwd: wd,
|
|
2169
|
-
}, null, 2));
|
|
2170
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2171
|
-
mode: 'ralplan',
|
|
2172
|
-
active: true,
|
|
2173
|
-
current_phase: 'planning',
|
|
2174
|
-
session_id: sessionId,
|
|
2175
|
-
}, null, 2));
|
|
2176
|
-
await writeFile(join(sessionDir, 'autoresearch-state.json'), JSON.stringify({
|
|
2177
|
-
mode: 'autoresearch',
|
|
2178
|
-
active: true,
|
|
2179
|
-
current_phase: 'running',
|
|
2180
|
-
session_id: sessionId,
|
|
2181
|
-
}, null, 2));
|
|
2182
|
-
const mixedSkillState = {
|
|
2183
|
-
version: 1,
|
|
2184
|
-
active: true,
|
|
2185
|
-
skill: 'ralplan',
|
|
2186
|
-
phase: 'planning',
|
|
2187
|
-
updated_at: '2026-06-30T00:00:00.000Z',
|
|
2188
|
-
session_id: sessionId,
|
|
2189
|
-
active_skills: [
|
|
2190
|
-
{
|
|
2191
|
-
skill: 'ralplan',
|
|
2192
|
-
phase: 'planning',
|
|
2193
|
-
active: true,
|
|
2194
|
-
session_id: sessionId,
|
|
2195
|
-
},
|
|
2196
|
-
{
|
|
2197
|
-
skill: 'autoresearch',
|
|
2198
|
-
phase: 'running',
|
|
2199
|
-
active: true,
|
|
2200
|
-
session_id: sessionId,
|
|
2201
|
-
},
|
|
2202
|
-
],
|
|
2203
|
-
};
|
|
2204
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify(mixedSkillState, null, 2));
|
|
2205
|
-
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify(mixedSkillState, null, 2));
|
|
2206
|
-
const response = await executeStateOperation('state_write', {
|
|
2207
|
-
workingDirectory: wd,
|
|
2208
|
-
mode: 'ralplan',
|
|
2209
|
-
active: false,
|
|
2210
|
-
current_phase: 'complete',
|
|
2211
|
-
status: 'complete',
|
|
2212
|
-
terminal_reason: 'consensus approved bounded no-op',
|
|
2213
|
-
ralplan_consensus_gate: consensusGate,
|
|
2214
|
-
});
|
|
2215
|
-
assert.equal(response.isError, undefined);
|
|
2216
|
-
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2217
|
-
const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
|
|
2218
|
-
for (const state of [rootSkill, sessionSkill]) {
|
|
2219
|
-
assert.equal(state.active, true);
|
|
2220
|
-
assert.equal(state.skill, 'autoresearch');
|
|
2221
|
-
assert.equal(state.phase, 'running');
|
|
2222
|
-
assert.deepEqual(state.active_skills?.map((entry) => entry.skill), ['autoresearch']);
|
|
2223
|
-
assert.deepEqual(state.active_skills?.map((entry) => entry.session_id), [sessionId]);
|
|
2224
|
-
}
|
|
2225
|
-
const listed = await executeStateOperation('state_list_active', {
|
|
2226
|
-
workingDirectory: wd,
|
|
2227
|
-
});
|
|
2228
|
-
assert.deepEqual(listed.payload, { active_modes: ['autoresearch'] });
|
|
2229
|
-
}
|
|
2230
|
-
finally {
|
|
2231
|
-
await rm(wd, { recursive: true, force: true });
|
|
2232
|
-
}
|
|
2233
|
-
});
|
|
2234
|
-
it('preserves same-session root mirror skills when session canonical state is partial', async () => {
|
|
2235
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-partial-session-skill-'));
|
|
2236
|
-
try {
|
|
2237
|
-
const sessionId = 'sess-ralplan-partial-session-skill';
|
|
2238
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
2239
|
-
const stateDir = join(wd, '.omx', 'state');
|
|
2240
|
-
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2241
|
-
await mkdir(sessionDir, { recursive: true });
|
|
2242
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2243
|
-
mode: 'ralplan',
|
|
2244
|
-
active: true,
|
|
2245
|
-
current_phase: 'planning',
|
|
2246
|
-
session_id: sessionId,
|
|
2247
|
-
}, null, 2));
|
|
2248
|
-
await writeFile(join(sessionDir, 'team-state.json'), JSON.stringify({
|
|
2249
|
-
mode: 'team',
|
|
2250
|
-
active: true,
|
|
2251
|
-
current_phase: 'running',
|
|
2252
|
-
session_id: sessionId,
|
|
2253
|
-
}, null, 2));
|
|
2254
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
2255
|
-
version: 1,
|
|
2256
|
-
active: true,
|
|
2257
|
-
skill: 'ralplan',
|
|
2258
|
-
phase: 'planning',
|
|
2259
|
-
session_id: sessionId,
|
|
2260
|
-
active_skills: [
|
|
2261
|
-
{
|
|
2262
|
-
skill: 'ralplan',
|
|
2263
|
-
phase: 'planning',
|
|
2264
|
-
active: true,
|
|
2265
|
-
session_id: sessionId,
|
|
2266
|
-
},
|
|
2267
|
-
{
|
|
2268
|
-
skill: 'team',
|
|
2269
|
-
phase: 'running',
|
|
2270
|
-
active: true,
|
|
2271
|
-
session_id: sessionId,
|
|
2272
|
-
},
|
|
2273
|
-
],
|
|
2274
|
-
}, null, 2));
|
|
2275
|
-
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
|
|
2276
|
-
version: 1,
|
|
2277
|
-
active: true,
|
|
2278
|
-
skill: 'ralplan',
|
|
2279
|
-
phase: 'planning',
|
|
2280
|
-
session_id: sessionId,
|
|
2281
|
-
active_skills: [{
|
|
2282
|
-
skill: 'ralplan',
|
|
2283
|
-
phase: 'planning',
|
|
2284
|
-
active: true,
|
|
2285
|
-
session_id: sessionId,
|
|
2286
|
-
}],
|
|
2287
|
-
}, null, 2));
|
|
2288
|
-
const response = await executeStateOperation('state_write', {
|
|
2289
|
-
workingDirectory: wd,
|
|
2290
|
-
session_id: sessionId,
|
|
2291
|
-
mode: 'ralplan',
|
|
2292
|
-
active: false,
|
|
2293
|
-
current_phase: 'complete',
|
|
2294
|
-
ralplan_consensus_gate: consensusGate,
|
|
2295
|
-
});
|
|
2296
|
-
assert.equal(response.isError, undefined);
|
|
2297
|
-
const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
|
|
2298
|
-
assert.equal(sessionSkill.active, true);
|
|
2299
|
-
assert.equal(sessionSkill.skill, 'team');
|
|
2300
|
-
assert.equal(sessionSkill.phase, 'running');
|
|
2301
|
-
assert.equal(sessionSkill.session_id, sessionId);
|
|
2302
|
-
assert.deepEqual(sessionSkill.active_skills?.map((entry) => entry.skill), ['team']);
|
|
2303
|
-
assert.deepEqual(sessionSkill.active_skills?.map((entry) => entry.session_id), [sessionId]);
|
|
2304
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
2305
|
-
workingDirectory: wd,
|
|
2306
|
-
session_id: sessionId,
|
|
2307
|
-
});
|
|
2308
|
-
assert.deepEqual(sessionListed.payload, { active_modes: ['team'] });
|
|
2309
|
-
}
|
|
2310
|
-
finally {
|
|
2311
|
-
await rm(wd, { recursive: true, force: true });
|
|
2312
|
-
}
|
|
1674
|
+
});
|
|
1675
|
+
const payload = responsePayload(response);
|
|
1676
|
+
assert.equal(payload.success, true);
|
|
1677
|
+
assert.equal(payload.path, join(stateDir, 'deep-interview-state.json'));
|
|
1678
|
+
assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'team-state.json'), 'utf-8')), teamState);
|
|
1679
|
+
assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'run-state.json'), 'utf-8')), runState);
|
|
1680
|
+
assert.equal(existsSync(join(stateDir, 'sessions', 'foreign-team-session', 'deep-interview-state.json')), false);
|
|
1681
|
+
assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8')), foreignSkillState);
|
|
1682
|
+
const afterList = await executeStateOperation('state_list_active', { workingDirectory: wd });
|
|
1683
|
+
assert.deepEqual(afterList.payload, { active_modes: ['deep-interview'] });
|
|
1684
|
+
}
|
|
1685
|
+
finally {
|
|
1686
|
+
await rm(wd, { recursive: true, force: true });
|
|
1687
|
+
}
|
|
1688
|
+
});
|
|
2313
1689
|
});
|
|
2314
|
-
it('
|
|
2315
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-
|
|
1690
|
+
it('fails closed without mutating root state when ralplan terminalization sees a foreign session pointer', async () => {
|
|
1691
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-stale-session-'));
|
|
2316
1692
|
try {
|
|
2317
|
-
const
|
|
2318
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd,
|
|
1693
|
+
const staleSessionId = 'sess-ralplan-stale';
|
|
1694
|
+
const consensusGate = await writeNativeRalplanConsensusGate(wd, staleSessionId);
|
|
2319
1695
|
const stateDir = join(wd, '.omx', 'state');
|
|
2320
|
-
const sessionDir = join(stateDir, 'sessions',
|
|
2321
|
-
await mkdir(
|
|
2322
|
-
await writeFile(join(
|
|
1696
|
+
const sessionDir = join(stateDir, 'sessions', staleSessionId);
|
|
1697
|
+
await mkdir(stateDir, { recursive: true });
|
|
1698
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({
|
|
1699
|
+
session_id: staleSessionId,
|
|
1700
|
+
cwd: join(wd, 'different-project'),
|
|
1701
|
+
}, null, 2));
|
|
1702
|
+
await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
|
|
2323
1703
|
mode: 'ralplan',
|
|
2324
1704
|
active: true,
|
|
2325
1705
|
current_phase: 'planning',
|
|
2326
|
-
session_id:
|
|
2327
|
-
}, null, 2));
|
|
2328
|
-
await writeFile(join(sessionDir, 'team-state.json'), JSON.stringify({
|
|
2329
|
-
mode: 'team',
|
|
2330
|
-
active: true,
|
|
2331
|
-
current_phase: 'running',
|
|
2332
|
-
session_id: sessionId,
|
|
1706
|
+
session_id: staleSessionId,
|
|
2333
1707
|
}, null, 2));
|
|
2334
1708
|
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
2335
1709
|
version: 1,
|
|
2336
1710
|
active: true,
|
|
2337
1711
|
skill: 'ralplan',
|
|
2338
1712
|
phase: 'planning',
|
|
2339
|
-
session_id:
|
|
1713
|
+
session_id: staleSessionId,
|
|
2340
1714
|
active_skills: [
|
|
2341
1715
|
{
|
|
2342
1716
|
skill: 'ralplan',
|
|
2343
1717
|
phase: 'planning',
|
|
2344
1718
|
active: true,
|
|
2345
|
-
session_id: sessionId,
|
|
2346
1719
|
},
|
|
2347
1720
|
{
|
|
2348
|
-
skill: '
|
|
1721
|
+
skill: 'ralplan',
|
|
1722
|
+
phase: 'planning',
|
|
2349
1723
|
active: true,
|
|
2350
|
-
session_id:
|
|
1724
|
+
session_id: staleSessionId,
|
|
2351
1725
|
},
|
|
2352
1726
|
],
|
|
2353
1727
|
}, null, 2));
|
|
2354
|
-
await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
|
|
2355
|
-
version: 1,
|
|
2356
|
-
active: false,
|
|
2357
|
-
skill: 'ralplan',
|
|
2358
|
-
phase: 'blocked',
|
|
2359
|
-
session_id: sessionId,
|
|
2360
|
-
completed_at: '2026-06-30T00:00:00.000Z',
|
|
2361
|
-
terminal_reason: 'stale terminal marker',
|
|
2362
|
-
active_skills: [],
|
|
2363
|
-
}, null, 2));
|
|
2364
|
-
const response = await executeStateOperation('state_write', {
|
|
2365
|
-
workingDirectory: wd,
|
|
2366
|
-
session_id: sessionId,
|
|
2367
|
-
mode: 'ralplan',
|
|
2368
|
-
active: false,
|
|
2369
|
-
current_phase: 'complete',
|
|
2370
|
-
ralplan_consensus_gate: consensusGate,
|
|
2371
|
-
});
|
|
2372
|
-
assert.equal(response.isError, undefined);
|
|
2373
|
-
const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
|
|
2374
|
-
assert.equal(sessionSkill.active, true);
|
|
2375
|
-
assert.equal(sessionSkill.skill, 'team');
|
|
2376
|
-
assert.equal(sessionSkill.phase, '');
|
|
2377
|
-
assert.equal(sessionSkill.completed_at, undefined);
|
|
2378
|
-
assert.equal(sessionSkill.terminal_reason, undefined);
|
|
2379
|
-
assert.deepEqual(sessionSkill.active_skills?.map((entry) => entry.skill), ['team']);
|
|
2380
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
2381
|
-
workingDirectory: wd,
|
|
2382
|
-
session_id: sessionId,
|
|
2383
|
-
});
|
|
2384
|
-
assert.deepEqual(sessionListed.payload, { active_modes: ['team'] });
|
|
2385
|
-
}
|
|
2386
|
-
finally {
|
|
2387
|
-
await rm(wd, { recursive: true, force: true });
|
|
2388
|
-
}
|
|
2389
|
-
});
|
|
2390
|
-
it('does not hide detail-only active session state when ralplan terminalizes', async () => {
|
|
2391
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-session-detail-only-'));
|
|
2392
|
-
try {
|
|
2393
|
-
const sessionId = 'sess-ralplan-session-detail-only';
|
|
2394
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
2395
|
-
const sessionDir = join(wd, '.omx', 'state', 'sessions', sessionId);
|
|
2396
|
-
await mkdir(sessionDir, { recursive: true });
|
|
2397
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2398
|
-
mode: 'ralplan',
|
|
2399
|
-
active: true,
|
|
2400
|
-
current_phase: 'planning',
|
|
2401
|
-
session_id: sessionId,
|
|
2402
|
-
}, null, 2));
|
|
2403
|
-
await writeFile(join(sessionDir, 'autoresearch-state.json'), JSON.stringify({
|
|
2404
|
-
mode: 'autoresearch',
|
|
2405
|
-
active: true,
|
|
2406
|
-
current_phase: 'running',
|
|
2407
|
-
session_id: sessionId,
|
|
2408
|
-
}, null, 2));
|
|
2409
1728
|
const response = await executeStateOperation('state_write', {
|
|
2410
1729
|
workingDirectory: wd,
|
|
2411
|
-
session_id: sessionId,
|
|
2412
1730
|
mode: 'ralplan',
|
|
2413
1731
|
active: false,
|
|
2414
1732
|
current_phase: 'complete',
|
|
2415
|
-
|
|
1733
|
+
status: 'complete',
|
|
1734
|
+
terminal_reason: 'consensus approved bounded no-op',
|
|
1735
|
+
state: {
|
|
1736
|
+
session_id: staleSessionId,
|
|
1737
|
+
ralplan_consensus_gate: consensusGate,
|
|
1738
|
+
},
|
|
2416
1739
|
});
|
|
2417
|
-
assert.equal(response.isError,
|
|
1740
|
+
assert.equal(response.isError, true);
|
|
1741
|
+
assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.unusableSession });
|
|
1742
|
+
const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
|
|
1743
|
+
assert.equal(rootRalplan.active, true);
|
|
1744
|
+
assert.equal(rootRalplan.current_phase, 'planning');
|
|
1745
|
+
assert.equal(rootRalplan.session_id, staleSessionId);
|
|
1746
|
+
const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1747
|
+
assert.equal(rootSkill.active, true);
|
|
1748
|
+
assert.equal(rootSkill.phase, 'planning');
|
|
1749
|
+
assert.equal(Array.isArray(rootSkill.active_skills), true);
|
|
1750
|
+
assert.equal(existsSync(join(sessionDir, 'ralplan-state.json')), false);
|
|
2418
1751
|
assert.equal(existsSync(join(sessionDir, 'skill-active-state.json')), false);
|
|
2419
1752
|
const listed = await executeStateOperation('state_list_active', {
|
|
2420
1753
|
workingDirectory: wd,
|
|
2421
|
-
session_id: sessionId,
|
|
2422
1754
|
});
|
|
2423
|
-
assert.deepEqual(listed.payload, { active_modes: ['
|
|
1755
|
+
assert.deepEqual(listed.payload, { active_modes: ['ralplan'] });
|
|
2424
1756
|
}
|
|
2425
1757
|
finally {
|
|
2426
1758
|
await rm(wd, { recursive: true, force: true });
|
|
2427
1759
|
}
|
|
2428
1760
|
});
|
|
2429
|
-
it('
|
|
2430
|
-
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-
|
|
1761
|
+
it('reconciles a stale-dead selected pointer with an explicit exact-current OMX_SESSION_ID (issue #3272)', async () => {
|
|
1762
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-stale-dead-repro-'));
|
|
1763
|
+
const previousEnv = process.env.OMX_SESSION_ID;
|
|
1764
|
+
__setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
|
|
2431
1765
|
try {
|
|
2432
|
-
const sessionId = 'sess-ralplan-root-only-skill';
|
|
2433
|
-
const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
|
|
2434
1766
|
const stateDir = join(wd, '.omx', 'state');
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
}, null, 2));
|
|
2442
|
-
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
|
|
2443
|
-
version: 1,
|
|
2444
|
-
active: true,
|
|
2445
|
-
skill: 'autoresearch',
|
|
2446
|
-
phase: 'running',
|
|
2447
|
-
active_skills: [{
|
|
2448
|
-
skill: 'autoresearch',
|
|
2449
|
-
phase: 'running',
|
|
2450
|
-
active: true,
|
|
2451
|
-
}],
|
|
2452
|
-
}, null, 2));
|
|
2453
|
-
await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
|
|
2454
|
-
mode: 'ralplan',
|
|
2455
|
-
active: true,
|
|
2456
|
-
current_phase: 'planning',
|
|
2457
|
-
session_id: sessionId,
|
|
2458
|
-
}, null, 2));
|
|
2459
|
-
await writeFile(join(sessionDir, 'team-state.json'), JSON.stringify({
|
|
2460
|
-
mode: 'team',
|
|
2461
|
-
active: true,
|
|
2462
|
-
current_phase: 'running',
|
|
2463
|
-
session_id: sessionId,
|
|
2464
|
-
}, null, 2));
|
|
1767
|
+
await mkdir(stateDir, { recursive: true });
|
|
1768
|
+
// Repro of comment 5069023665: the selected pointer names a session whose
|
|
1769
|
+
// PID is dead; the exact current session is bound through OMX_SESSION_ID.
|
|
1770
|
+
const pointerBody = JSON.stringify({ session_id: 'sess-stale-dead', cwd: wd, pid: 8388607 });
|
|
1771
|
+
await writeFile(join(stateDir, 'session.json'), pointerBody);
|
|
1772
|
+
process.env.OMX_SESSION_ID = 'sess-current';
|
|
2465
1773
|
const response = await executeStateOperation('state_write', {
|
|
2466
1774
|
workingDirectory: wd,
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
ralplan_consensus_gate: consensusGate,
|
|
2472
|
-
});
|
|
2473
|
-
assert.equal(response.isError, undefined);
|
|
2474
|
-
assert.equal(existsSync(join(sessionDir, 'skill-active-state.json')), false);
|
|
2475
|
-
const rootListed = await executeStateOperation('state_list_active', {
|
|
2476
|
-
workingDirectory: wd,
|
|
2477
|
-
});
|
|
2478
|
-
assert.deepEqual(rootListed.payload, { active_modes: ['autoresearch'] });
|
|
2479
|
-
const sessionListed = await executeStateOperation('state_list_active', {
|
|
2480
|
-
workingDirectory: wd,
|
|
2481
|
-
session_id: sessionId,
|
|
1775
|
+
mode: 'ultragoal',
|
|
1776
|
+
active: true,
|
|
1777
|
+
current_phase: 'reviewing',
|
|
1778
|
+
state: { goal_id: 'G001' },
|
|
2482
1779
|
});
|
|
2483
|
-
|
|
1780
|
+
const payload = responsePayload(response);
|
|
1781
|
+
assert.equal(payload.success, true);
|
|
1782
|
+
assert.equal(payload.path, join(stateDir, 'sessions', 'sess-current', 'ultragoal-state.json'));
|
|
1783
|
+
assert.equal(existsSync(payload.path), true);
|
|
1784
|
+
// The selected pointer is never rewritten by a scope-resolution read path.
|
|
1785
|
+
assert.equal(await readFile(join(stateDir, 'session.json'), 'utf-8'), pointerBody);
|
|
2484
1786
|
}
|
|
2485
1787
|
finally {
|
|
1788
|
+
if (typeof previousEnv === 'string')
|
|
1789
|
+
process.env.OMX_SESSION_ID = previousEnv;
|
|
1790
|
+
else
|
|
1791
|
+
delete process.env.OMX_SESSION_ID;
|
|
1792
|
+
__resetSessionPointerTransactionDependenciesForTests();
|
|
2486
1793
|
await rm(wd, { recursive: true, force: true });
|
|
2487
1794
|
}
|
|
2488
1795
|
});
|
|
@@ -3772,7 +3079,7 @@ describe('state operations directory initialization', () => {
|
|
|
3772
3079
|
current_phase: 'ultragoal',
|
|
3773
3080
|
});
|
|
3774
3081
|
assert.equal(response.isError, true);
|
|
3775
|
-
assert.match(String(response.payload.error || ''), /
|
|
3082
|
+
assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
|
|
3776
3083
|
const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
|
|
3777
3084
|
assert.equal(state.current_phase, 'ralplan');
|
|
3778
3085
|
});
|
|
@@ -3904,7 +3211,7 @@ describe('state operations directory initialization', () => {
|
|
|
3904
3211
|
});
|
|
3905
3212
|
assert.equal(response.isError, true);
|
|
3906
3213
|
const error = String(response.payload.error || '');
|
|
3907
|
-
assert.match(error,
|
|
3214
|
+
assert.match(error, /documented_host_consensus_receipt_unavailable/);
|
|
3908
3215
|
const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
|
|
3909
3216
|
assert.equal(state.current_phase, 'ralplan');
|
|
3910
3217
|
});
|
|
@@ -3944,8 +3251,8 @@ describe('state operations directory initialization', () => {
|
|
|
3944
3251
|
});
|
|
3945
3252
|
assert.equal(response.isError, true);
|
|
3946
3253
|
const error = String(response.payload.error || '');
|
|
3947
|
-
assert.match(error, /
|
|
3948
|
-
assert.match(error, /
|
|
3254
|
+
assert.match(error, /documented_host_consensus_receipt_unavailable/);
|
|
3255
|
+
assert.match(error, /official host consensus receipt verifier is unavailable/i);
|
|
3949
3256
|
});
|
|
3950
3257
|
}
|
|
3951
3258
|
finally {
|
|
@@ -3984,7 +3291,7 @@ describe('state operations directory initialization', () => {
|
|
|
3984
3291
|
current_phase: 'ultragoal',
|
|
3985
3292
|
});
|
|
3986
3293
|
assert.equal(response.isError, true);
|
|
3987
|
-
assert.match(String(response.payload.error || ''), /
|
|
3294
|
+
assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
|
|
3988
3295
|
const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
|
|
3989
3296
|
assert.equal(state.current_phase, 'ralplan');
|
|
3990
3297
|
});
|
|
@@ -4013,7 +3320,7 @@ describe('state operations directory initialization', () => {
|
|
|
4013
3320
|
current_phase: 'ultragoal',
|
|
4014
3321
|
});
|
|
4015
3322
|
assert.equal(response.isError, true);
|
|
4016
|
-
assert.match(String(response.payload.error || ''), /
|
|
3323
|
+
assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
|
|
4017
3324
|
const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
|
|
4018
3325
|
assert.equal(state.current_phase, 'planning');
|
|
4019
3326
|
});
|
|
@@ -4638,7 +3945,7 @@ describe('state operations directory initialization', () => {
|
|
|
4638
3945
|
await rm(wd, { recursive: true, force: true });
|
|
4639
3946
|
}
|
|
4640
3947
|
});
|
|
4641
|
-
it('
|
|
3948
|
+
it('denies Autopilot ralplan to ultragoal self-write with tracker-backed native lifecycle evidence', async () => {
|
|
4642
3949
|
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-autopilot-ralplan-native-allow-'));
|
|
4643
3950
|
try {
|
|
4644
3951
|
await withOmxRootEnv(wd, async () => {
|
|
@@ -4667,9 +3974,10 @@ describe('state operations directory initialization', () => {
|
|
|
4667
3974
|
active: true,
|
|
4668
3975
|
current_phase: 'ultragoal',
|
|
4669
3976
|
});
|
|
4670
|
-
assert.equal(response.isError,
|
|
3977
|
+
assert.equal(response.isError, true);
|
|
3978
|
+
assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
|
|
4671
3979
|
const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
|
|
4672
|
-
assert.equal(state.current_phase, '
|
|
3980
|
+
assert.equal(state.current_phase, 'ralplan');
|
|
4673
3981
|
});
|
|
4674
3982
|
}
|
|
4675
3983
|
finally {
|
|
@@ -4745,7 +4053,7 @@ describe('state operations directory initialization', () => {
|
|
|
4745
4053
|
const sessionId = 'sess-resume-root-fallback';
|
|
4746
4054
|
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
4747
4055
|
await mkdir(sessionDir, { recursive: true });
|
|
4748
|
-
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
|
|
4056
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: stateDir }, null, 2));
|
|
4749
4057
|
await writeFile(join(stateDir, 'ralph-state.json'), JSON.stringify({
|
|
4750
4058
|
active: true,
|
|
4751
4059
|
current_phase: 'executing',
|
|
@@ -4776,5 +4084,309 @@ describe('state operations directory initialization', () => {
|
|
|
4776
4084
|
await rm(wd, { recursive: true, force: true });
|
|
4777
4085
|
}
|
|
4778
4086
|
});
|
|
4087
|
+
function installScopeTakeover(stateDir, expected, replacementPointer) {
|
|
4088
|
+
const events = [];
|
|
4089
|
+
__setWritableStateScopeTestHooksForTests({
|
|
4090
|
+
beforeScopeRevalidation: async (event) => {
|
|
4091
|
+
const actual = [event.commitOrdinal, event.site, event.kind, event.path];
|
|
4092
|
+
events.push(actual);
|
|
4093
|
+
if (event.commitOrdinal === expected[0] && event.site === expected[1]) {
|
|
4094
|
+
await writeFile(join(stateDir, 'session.json'), replacementPointer);
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
if (event.commitOrdinal === expected[0] || event.site === expected[1]) {
|
|
4098
|
+
throw new Error(`takeover drift: expected (${expected[0]}, ${expected[1]}), got (${event.commitOrdinal}, ${event.site})`);
|
|
4099
|
+
}
|
|
4100
|
+
},
|
|
4101
|
+
});
|
|
4102
|
+
return events;
|
|
4103
|
+
}
|
|
4104
|
+
async function seedWritableScope(wd, sessionId = 'sess-current') {
|
|
4105
|
+
const stateDir = getBaseStateDir(wd);
|
|
4106
|
+
await mkdir(join(stateDir, 'sessions', sessionId), { recursive: true });
|
|
4107
|
+
await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: stateDir }));
|
|
4108
|
+
return { stateDir, sessionId };
|
|
4109
|
+
}
|
|
4110
|
+
function assertPrefix(events, expected) {
|
|
4111
|
+
assert.deepEqual(events.slice(0, expected.length), expected);
|
|
4112
|
+
}
|
|
4113
|
+
it('fails closed before primary session persistence on malformed root skill-active state', async () => {
|
|
4114
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-malformed-root-'));
|
|
4115
|
+
try {
|
|
4116
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4117
|
+
const rootPath = join(stateDir, 'skill-active-state.json');
|
|
4118
|
+
const sessionPath = join(stateDir, 'sessions', sessionId, 'skill-active-state.json');
|
|
4119
|
+
const rootBytes = '{"active":true,\n';
|
|
4120
|
+
const sessionBytes = '{"active":true,"skill":"old"}\n';
|
|
4121
|
+
await writeFile(rootPath, rootBytes);
|
|
4122
|
+
await writeFile(sessionPath, sessionBytes);
|
|
4123
|
+
const response = await executeStateOperation('state_write', {
|
|
4124
|
+
workingDirectory: wd,
|
|
4125
|
+
session_id: sessionId,
|
|
4126
|
+
mode: 'skill-active',
|
|
4127
|
+
active: true,
|
|
4128
|
+
skill: 'new',
|
|
4129
|
+
phase: 'executing',
|
|
4130
|
+
active_skills: [{ skill: 'new', phase: 'executing', active: true, session_id: sessionId }],
|
|
4131
|
+
});
|
|
4132
|
+
assert.equal(response.isError, true);
|
|
4133
|
+
assert.match(String(response.payload.error || ''), /malformed root skill-active state/i);
|
|
4134
|
+
assert.equal(await readFile(rootPath, 'utf8'), rootBytes);
|
|
4135
|
+
assert.equal(await readFile(sessionPath, 'utf8'), sessionBytes);
|
|
4136
|
+
}
|
|
4137
|
+
finally {
|
|
4138
|
+
await rm(wd, { recursive: true, force: true });
|
|
4139
|
+
}
|
|
4140
|
+
});
|
|
4141
|
+
it('fails closed before primary session persistence on root lock timeout', async () => {
|
|
4142
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-lock-timeout-'));
|
|
4143
|
+
try {
|
|
4144
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4145
|
+
const rootPath = join(stateDir, 'skill-active-state.json');
|
|
4146
|
+
const sessionPath = join(stateDir, 'sessions', sessionId, 'skill-active-state.json');
|
|
4147
|
+
const rootBytes = `${JSON.stringify({ version: 1, active: true, skill: 'old', session_id: sessionId, active_skills: [] }, null, 2)}\n`;
|
|
4148
|
+
const sessionBytes = '{"active":true,"skill":"old"}\n';
|
|
4149
|
+
await writeFile(rootPath, rootBytes);
|
|
4150
|
+
await writeFile(sessionPath, sessionBytes);
|
|
4151
|
+
await mkdir(`${rootPath}.lock`);
|
|
4152
|
+
const response = await executeStateOperation('state_write', {
|
|
4153
|
+
workingDirectory: wd,
|
|
4154
|
+
session_id: sessionId,
|
|
4155
|
+
mode: 'skill-active',
|
|
4156
|
+
active: true,
|
|
4157
|
+
skill: 'new',
|
|
4158
|
+
phase: 'executing',
|
|
4159
|
+
active_skills: [{ skill: 'new', phase: 'executing', active: true, session_id: sessionId }],
|
|
4160
|
+
});
|
|
4161
|
+
assert.equal(response.isError, true);
|
|
4162
|
+
assert.match(String(response.payload.error || ''), /lock|timeout/i);
|
|
4163
|
+
assert.equal(await readFile(rootPath, 'utf8'), rootBytes);
|
|
4164
|
+
assert.equal(await readFile(sessionPath, 'utf8'), sessionBytes);
|
|
4165
|
+
}
|
|
4166
|
+
finally {
|
|
4167
|
+
await rm(wd, { recursive: true, force: true });
|
|
4168
|
+
}
|
|
4169
|
+
});
|
|
4170
|
+
it('T4 records the full pinned state_write commit prefix', async () => {
|
|
4171
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t4-'));
|
|
4172
|
+
try {
|
|
4173
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4174
|
+
const events = [];
|
|
4175
|
+
__setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: async (event) => { events.push([event.commitOrdinal, event.site, event.kind, event.path]); } });
|
|
4176
|
+
const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true, current_phase: 'running' });
|
|
4177
|
+
assert.equal(response.isError, undefined);
|
|
4178
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
4179
|
+
assertPrefix(events, [
|
|
4180
|
+
[1, 'mode.primary', 'write', join(sessionDir, 'autoresearch-state.json')],
|
|
4181
|
+
[2, 'skill-active.root-copy', 'write', join(stateDir, 'skill-active-state.json')],
|
|
4182
|
+
[3, 'skill-active.session-copy', 'write', join(sessionDir, 'skill-active-state.json')],
|
|
4183
|
+
]);
|
|
4184
|
+
}
|
|
4185
|
+
finally {
|
|
4186
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4187
|
+
await rm(wd, { recursive: true, force: true });
|
|
4188
|
+
}
|
|
4189
|
+
});
|
|
4190
|
+
it('T5 rejects a state_write takeover at its first commit', async () => {
|
|
4191
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t5-'));
|
|
4192
|
+
try {
|
|
4193
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4194
|
+
installScopeTakeover(stateDir, [1, 'mode.primary'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
|
|
4195
|
+
const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
|
|
4196
|
+
assert.equal(response.isError, true);
|
|
4197
|
+
assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
|
|
4198
|
+
assert.equal(existsSync(join(stateDir, 'sessions', sessionId, 'autoresearch-state.json')), false);
|
|
4199
|
+
}
|
|
4200
|
+
finally {
|
|
4201
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4202
|
+
await rm(wd, { recursive: true, force: true });
|
|
4203
|
+
}
|
|
4204
|
+
});
|
|
4205
|
+
it('T6 rejects a later state_write takeover after the non-atomic primary commit', async () => {
|
|
4206
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t6-'));
|
|
4207
|
+
try {
|
|
4208
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4209
|
+
installScopeTakeover(stateDir, [2, 'skill-active.root-copy'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
|
|
4210
|
+
const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
|
|
4211
|
+
assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
|
|
4212
|
+
// Earlier multi-file commits are not rolled back; each later site still performs its own point-in-time check, without closing the post-check race.
|
|
4213
|
+
assert.equal(existsSync(join(stateDir, 'sessions', sessionId, 'autoresearch-state.json')), true);
|
|
4214
|
+
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
4215
|
+
}
|
|
4216
|
+
finally {
|
|
4217
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4218
|
+
await rm(wd, { recursive: true, force: true });
|
|
4219
|
+
}
|
|
4220
|
+
});
|
|
4221
|
+
it('T7 records state_clear commits and rejects its native-stop takeover', async () => {
|
|
4222
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t7-'));
|
|
4223
|
+
try {
|
|
4224
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4225
|
+
await writeFile(join(stateDir, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
|
|
4226
|
+
await writeFile(join(stateDir, 'sessions', sessionId, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
|
|
4227
|
+
await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
|
|
4228
|
+
const events = [];
|
|
4229
|
+
__setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: async (event) => { events.push([event.commitOrdinal, event.site, event.kind, event.path]); } });
|
|
4230
|
+
await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
|
|
4231
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
4232
|
+
assertPrefix(events, [
|
|
4233
|
+
[1, 'state-clear.primary', 'unlink', join(sessionDir, 'autoresearch-state.json')],
|
|
4234
|
+
[2, 'native-stop.root', 'write', join(stateDir, 'native-stop-state.json')],
|
|
4235
|
+
[3, 'native-stop.session', 'write', join(sessionDir, 'native-stop-state.json')],
|
|
4236
|
+
[4, 'skill-active.root-copy', 'write', join(stateDir, 'skill-active-state.json')],
|
|
4237
|
+
[5, 'skill-active.session-copy', 'write', join(sessionDir, 'skill-active-state.json')],
|
|
4238
|
+
]);
|
|
4239
|
+
await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
|
|
4240
|
+
await writeFile(join(stateDir, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
|
|
4241
|
+
await writeFile(join(sessionDir, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
|
|
4242
|
+
installScopeTakeover(stateDir, [2, 'native-stop.root'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
|
|
4243
|
+
const rejected = await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
|
|
4244
|
+
assert.deepEqual(rejected.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
|
|
4245
|
+
}
|
|
4246
|
+
finally {
|
|
4247
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4248
|
+
await rm(wd, { recursive: true, force: true });
|
|
4249
|
+
}
|
|
4250
|
+
});
|
|
4251
|
+
it('T15 fails loudly when a takeover ordinal-site pair drifts', async () => {
|
|
4252
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t15-'));
|
|
4253
|
+
try {
|
|
4254
|
+
const { stateDir } = await seedWritableScope(wd);
|
|
4255
|
+
installScopeTakeover(stateDir, [2, 'mode.primary'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
|
|
4256
|
+
const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
|
|
4257
|
+
assert.equal(response.isError, true);
|
|
4258
|
+
const error = String(response.payload.error);
|
|
4259
|
+
assert.match(error, /takeover drift: expected \(2, mode.primary\), got \(1, mode.primary\)/);
|
|
4260
|
+
assert.notEqual(error, WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite);
|
|
4261
|
+
}
|
|
4262
|
+
finally {
|
|
4263
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4264
|
+
await rm(wd, { recursive: true, force: true });
|
|
4265
|
+
}
|
|
4266
|
+
});
|
|
4267
|
+
it('T14 revalidates the transition source-mode detail commit', async () => {
|
|
4268
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t14-'));
|
|
4269
|
+
try {
|
|
4270
|
+
const { stateDir, sessionId } = await seedWritableScope(wd);
|
|
4271
|
+
await startMode('deep-interview', 'clarify contract', 3, wd);
|
|
4272
|
+
await updateModeState('deep-interview', { deep_interview_gate: { status: 'complete', rationale: 'ready' } }, wd);
|
|
4273
|
+
const events = [];
|
|
4274
|
+
__setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: async (event) => { events.push([event.commitOrdinal, event.site, event.kind, event.path]); } });
|
|
4275
|
+
await startMode('ralplan', 'plan contract', 5, wd);
|
|
4276
|
+
assert.deepEqual(events[0], [1, 'transition.source-mode-detail', 'write', join(stateDir, 'sessions', sessionId, 'deep-interview-state.json')]);
|
|
4277
|
+
await rm(join(stateDir, 'ralplan-state.json'), { force: true });
|
|
4278
|
+
await writeFile(join(stateDir, 'sessions', sessionId, 'deep-interview-state.json'), JSON.stringify({ active: true, current_phase: 'starting', deep_interview_gate: { status: 'complete', rationale: 'ready' } }));
|
|
4279
|
+
await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({ active: true, active_skills: [{ skill: 'deep-interview', active: true, session_id: sessionId }] }));
|
|
4280
|
+
await writeFile(join(stateDir, 'sessions', sessionId, 'skill-active-state.json'), JSON.stringify({ active: true, active_skills: [{ skill: 'deep-interview', active: true, session_id: sessionId }] }));
|
|
4281
|
+
const detail = await readFile(join(stateDir, 'sessions', sessionId, 'deep-interview-state.json'), 'utf-8');
|
|
4282
|
+
const skill = await readFile(join(stateDir, 'sessions', sessionId, 'skill-active-state.json'), 'utf-8');
|
|
4283
|
+
installScopeTakeover(stateDir, [1, 'transition.source-mode-detail'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
|
|
4284
|
+
await assert.rejects(() => startMode('ralplan', 'plan again', 5, wd), new Error(WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite));
|
|
4285
|
+
assert.equal(await readFile(join(stateDir, 'sessions', sessionId, 'deep-interview-state.json'), 'utf-8'), detail);
|
|
4286
|
+
assert.equal(await readFile(join(stateDir, 'sessions', sessionId, 'skill-active-state.json'), 'utf-8'), skill);
|
|
4287
|
+
}
|
|
4288
|
+
finally {
|
|
4289
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4290
|
+
await rm(wd, { recursive: true, force: true });
|
|
4291
|
+
}
|
|
4292
|
+
});
|
|
4293
|
+
it('requires capturedScope before checking either terminal or non-terminal ralplan state', async () => {
|
|
4294
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-f14-guard-'));
|
|
4295
|
+
try {
|
|
4296
|
+
const { sessionId } = await seedWritableScope(wd);
|
|
4297
|
+
const terminal = { active: false, current_phase: 'complete', session_id: sessionId, ralplan_consensus_gate: { complete: true } };
|
|
4298
|
+
const beforeCommit = async () => { };
|
|
4299
|
+
await assert.rejects(() => completeRalplanSession({ cwd: wd, baseStateDir: getBaseStateDir(wd), state: terminal, beforeCommit }), new Error('completeRalplanSession requires capturedScope when beforeCommit is provided'));
|
|
4300
|
+
await assert.rejects(() => completeRalplanSession({ cwd: wd, baseStateDir: getBaseStateDir(wd), state: { active: true, current_phase: 'planning' }, beforeCommit }), new Error('completeRalplanSession requires capturedScope when beforeCommit is provided'));
|
|
4301
|
+
}
|
|
4302
|
+
finally {
|
|
4303
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4304
|
+
await rm(wd, { recursive: true, force: true });
|
|
4305
|
+
}
|
|
4306
|
+
});
|
|
4307
|
+
it('keeps mode and run-state writes pinned to session A across transient A-B-A pointer movement', async () => {
|
|
4308
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-f14-pinned-run-state-'));
|
|
4309
|
+
try {
|
|
4310
|
+
const { stateDir, sessionId } = await seedWritableScope(wd, 'sess-a');
|
|
4311
|
+
const sessionADir = join(stateDir, 'sessions', sessionId);
|
|
4312
|
+
const sessionBId = 'sess-b';
|
|
4313
|
+
const sessionBDir = join(stateDir, 'sessions', sessionBId);
|
|
4314
|
+
await mkdir(sessionBDir, { recursive: true });
|
|
4315
|
+
const pointerA = await readFile(join(stateDir, 'session.json'), 'utf-8');
|
|
4316
|
+
const pointerB = JSON.stringify({ session_id: sessionBId, cwd: wd, state_root: stateDir });
|
|
4317
|
+
const events = [];
|
|
4318
|
+
__setWritableStateScopeTestHooksForTests({
|
|
4319
|
+
beforeScopeRevalidation: async (event) => {
|
|
4320
|
+
events.push([event.commitOrdinal, event.site, event.kind, event.path]);
|
|
4321
|
+
if (event.site === 'mode.primary') {
|
|
4322
|
+
await writeFile(join(stateDir, 'session.json'), pointerB);
|
|
4323
|
+
await writeFile(join(stateDir, 'session.json'), pointerA);
|
|
4324
|
+
}
|
|
4325
|
+
},
|
|
4326
|
+
});
|
|
4327
|
+
await startMode('autoresearch', 'verify pinned run-state target', 3, wd);
|
|
4328
|
+
assert.deepEqual(events.find(([, site]) => site === 'run-state.mode-sync'), [2, 'run-state.mode-sync', 'write', join(sessionADir, 'run-state.json')]);
|
|
4329
|
+
assert.deepEqual(events.find(([, site]) => site === 'mode.primary'), [1, 'mode.primary', 'write', join(sessionADir, 'autoresearch-state.json')]);
|
|
4330
|
+
assert.equal(existsSync(join(sessionADir, 'run-state.json')), true);
|
|
4331
|
+
assert.equal(existsSync(join(sessionADir, 'autoresearch-state.json')), true);
|
|
4332
|
+
assert.equal(existsSync(join(sessionBDir, 'run-state.json')), false);
|
|
4333
|
+
assert.equal(existsSync(join(sessionBDir, 'autoresearch-state.json')), false);
|
|
4334
|
+
}
|
|
4335
|
+
finally {
|
|
4336
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4337
|
+
await rm(wd, { recursive: true, force: true });
|
|
4338
|
+
}
|
|
4339
|
+
});
|
|
4340
|
+
it('revalidates the root-scoped session skill-state unlink', async () => {
|
|
4341
|
+
const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-session-unlink-'));
|
|
4342
|
+
try {
|
|
4343
|
+
const stateDir = getBaseStateDir(wd);
|
|
4344
|
+
const sessionId = 'sess-current';
|
|
4345
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
4346
|
+
const sessionPath = join(sessionDir, 'skill-active-state.json');
|
|
4347
|
+
const writeFixture = async () => {
|
|
4348
|
+
const rootSkillState = JSON.stringify({
|
|
4349
|
+
active: true,
|
|
4350
|
+
skill: 'autoresearch',
|
|
4351
|
+
active_skills: [{ skill: 'autoresearch', active: true }],
|
|
4352
|
+
});
|
|
4353
|
+
const sessionSkillState = JSON.stringify({
|
|
4354
|
+
active: false,
|
|
4355
|
+
skill: 'autoresearch',
|
|
4356
|
+
session_id: sessionId,
|
|
4357
|
+
});
|
|
4358
|
+
await mkdir(sessionDir, { recursive: true });
|
|
4359
|
+
await writeFile(join(stateDir, 'autoresearch-state.json'), JSON.stringify({ active: true }));
|
|
4360
|
+
await writeFile(join(stateDir, 'skill-active-state.json'), rootSkillState);
|
|
4361
|
+
await writeFile(sessionPath, sessionSkillState);
|
|
4362
|
+
};
|
|
4363
|
+
await writeFixture();
|
|
4364
|
+
const events = [];
|
|
4365
|
+
__setWritableStateScopeTestHooksForTests({
|
|
4366
|
+
beforeScopeRevalidation: async (event) => {
|
|
4367
|
+
events.push([event.commitOrdinal, event.site, event.kind, event.path]);
|
|
4368
|
+
},
|
|
4369
|
+
});
|
|
4370
|
+
const response = await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
|
|
4371
|
+
assert.equal(response.isError, undefined);
|
|
4372
|
+
assertPrefix(events, [
|
|
4373
|
+
[1, 'state-clear.primary', 'unlink', join(stateDir, 'autoresearch-state.json')],
|
|
4374
|
+
[2, 'skill-active.root-copy', 'write', join(stateDir, 'skill-active-state.json')],
|
|
4375
|
+
[3, 'skill-active.session-unlink', 'unlink', sessionPath],
|
|
4376
|
+
]);
|
|
4377
|
+
assert.equal(existsSync(sessionPath), false);
|
|
4378
|
+
await writeFixture();
|
|
4379
|
+
installScopeTakeover(stateDir, [3, 'skill-active.session-unlink'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
|
|
4380
|
+
const rejected = await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
|
|
4381
|
+
assert.equal(rejected.isError, true);
|
|
4382
|
+
assert.deepEqual(rejected.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
|
|
4383
|
+
// Earlier commits in the sequence are not rolled back; each site performs its own point-in-time check.
|
|
4384
|
+
assert.equal(existsSync(sessionPath), true);
|
|
4385
|
+
}
|
|
4386
|
+
finally {
|
|
4387
|
+
__setWritableStateScopeTestHooksForTests({});
|
|
4388
|
+
await rm(wd, { recursive: true, force: true });
|
|
4389
|
+
}
|
|
4390
|
+
});
|
|
4779
4391
|
});
|
|
4780
4392
|
//# sourceMappingURL=operations.test.js.map
|