oh-my-codex 0.18.6 → 0.18.8
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 +6 -6
- package/Cargo.toml +1 -1
- package/README.md +59 -10
- package/crates/omx-sparkshell/tests/execution.rs +1 -1
- package/dist/agents/__tests__/definitions.test.js +11 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +56 -6
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts +10 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +5 -1
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/native-config.d.ts +5 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +19 -4
- package/dist/agents/native-config.js.map +1 -1
- package/dist/autopilot/__tests__/fsm.test.d.ts +2 -0
- package/dist/autopilot/__tests__/fsm.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/fsm.test.js +75 -0
- package/dist/autopilot/__tests__/fsm.test.js.map +1 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.d.ts +2 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.js +79 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -0
- package/dist/autopilot/deep-interview-gate.d.ts +18 -0
- package/dist/autopilot/deep-interview-gate.d.ts.map +1 -0
- package/dist/autopilot/deep-interview-gate.js +256 -0
- package/dist/autopilot/deep-interview-gate.js.map +1 -0
- package/dist/autopilot/fsm.d.ts +13 -0
- package/dist/autopilot/fsm.d.ts.map +1 -0
- package/dist/autopilot/fsm.js +70 -0
- package/dist/autopilot/fsm.js.map +1 -0
- package/dist/autopilot/ralplan-gate.d.ts +17 -0
- package/dist/autopilot/ralplan-gate.d.ts.map +1 -0
- package/dist/autopilot/ralplan-gate.js +61 -0
- package/dist/autopilot/ralplan-gate.js.map +1 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js +512 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +39 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +83 -7
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +175 -6
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +8 -4
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +100 -0
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +13 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +14 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +89 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +83 -0
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/state.test.js +21 -0
- package/dist/cli/__tests__/state.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +2 -2
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +110 -2
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +8 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +14 -3
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +298 -50
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +14 -2
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +62 -15
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/question.d.ts.map +1 -1
- package/dist/cli/question.js +36 -5
- package/dist/cli/question.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +3 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +2 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +4 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +166 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/state.d.ts.map +1 -1
- package/dist/cli/state.js +8 -1
- package/dist/cli/state.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +16 -0
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +47 -3
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/deep-interview.test.js +7 -6
- package/dist/config/__tests__/deep-interview.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +1 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/deep-interview.d.ts.map +1 -1
- package/dist/config/deep-interview.js +14 -4
- package/dist/config/deep-interview.js.map +1 -1
- package/dist/config/generator.d.ts +2 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +2 -2
- package/dist/config/generator.js.map +1 -1
- package/dist/config/team-mode.d.ts +12 -0
- package/dist/config/team-mode.d.ts.map +1 -0
- package/dist/config/team-mode.js +91 -0
- package/dist/config/team-mode.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +88 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +8 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +8 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +10 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +1072 -14
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +64 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +189 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +35 -2
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +3 -3
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/session.test.js +25 -0
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-guidance-contract.test.js +21 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +36 -50
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/deep-interview-config-instruction.js +1 -1
- package/dist/hooks/deep-interview-config-instruction.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +31 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +1 -1
- package/dist/hooks/extensibility/plugin-runner.js +17 -21
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +428 -32
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +1 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +6 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +3 -0
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +13 -5
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/authority.test.js +469 -31
- package/dist/hud/__tests__/authority.test.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +2 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +210 -2
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +588 -28
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +61 -0
- package/dist/hud/__tests__/render.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +208 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +314 -22
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/authority.d.ts +5 -0
- package/dist/hud/authority.d.ts.map +1 -1
- package/dist/hud/authority.js +337 -30
- package/dist/hud/authority.js.map +1 -1
- package/dist/hud/index.d.ts +20 -2
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +103 -26
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.d.ts +3 -3
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +129 -20
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +35 -0
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +64 -50
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.d.ts +26 -6
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +173 -38
- package/dist/hud/tmux.js.map +1 -1
- package/dist/hud/types.d.ts +11 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/hermes-bridge.test.js +203 -7
- package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +71 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +13 -1
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/hermes-bridge.d.ts +12 -2
- package/dist/mcp/hermes-bridge.d.ts.map +1 -1
- package/dist/mcp/hermes-bridge.js +83 -9
- package/dist/mcp/hermes-bridge.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +32 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +113 -17
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/modes/__tests__/base-autoresearch-contract.test.js +7 -1
- package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +130 -0
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/orchestrator.js +1 -1
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/stages/ralplan.d.ts +1 -0
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
- package/dist/pipeline/stages/ralplan.js +14 -5
- package/dist/pipeline/stages/ralplan.js.map +1 -1
- package/dist/question/__tests__/deep-interview.test.js +160 -2
- package/dist/question/__tests__/deep-interview.test.js.map +1 -1
- package/dist/question/__tests__/policy.test.js +63 -3
- package/dist/question/__tests__/policy.test.js.map +1 -1
- package/dist/question/__tests__/renderer.test.js +191 -2
- package/dist/question/__tests__/renderer.test.js.map +1 -1
- package/dist/question/__tests__/state.test.js +94 -3
- package/dist/question/__tests__/state.test.js.map +1 -1
- package/dist/question/__tests__/ui.test.js +4 -0
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/autopilot-wait.d.ts +12 -2
- package/dist/question/autopilot-wait.d.ts.map +1 -1
- package/dist/question/autopilot-wait.js +158 -47
- package/dist/question/autopilot-wait.js.map +1 -1
- package/dist/question/deep-interview.d.ts.map +1 -1
- package/dist/question/deep-interview.js +22 -6
- package/dist/question/deep-interview.js.map +1 -1
- package/dist/question/policy.d.ts.map +1 -1
- package/dist/question/policy.js +2 -5
- package/dist/question/policy.js.map +1 -1
- package/dist/question/renderer.d.ts +12 -0
- package/dist/question/renderer.d.ts.map +1 -1
- package/dist/question/renderer.js +87 -3
- package/dist/question/renderer.js.map +1 -1
- package/dist/question/state.d.ts +8 -1
- package/dist/question/state.d.ts.map +1 -1
- package/dist/question/state.js +54 -14
- package/dist/question/state.js.map +1 -1
- package/dist/question/types.d.ts +1 -1
- package/dist/question/types.d.ts.map +1 -1
- package/dist/question/ui.d.ts +1 -0
- package/dist/question/ui.d.ts.map +1 -1
- package/dist/question/ui.js +1 -0
- package/dist/question/ui.js.map +1 -1
- package/dist/ralplan/__tests__/runtime.test.js +191 -0
- 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 +84 -2
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/ralplan/runtime.d.ts +9 -0
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +32 -11
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +2315 -280
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-state-io.test.js +72 -1
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js +57 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js +74 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +65 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +431 -56
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +79 -1
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js.map +1 -1
- package/dist/scripts/hook-payload-guard.d.ts +9 -0
- package/dist/scripts/hook-payload-guard.d.ts.map +1 -0
- package/dist/scripts/hook-payload-guard.js +111 -0
- package/dist/scripts/hook-payload-guard.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +8 -1
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.js +39 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.js.map +1 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +3 -1
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +3 -10
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +62 -38
- package/dist/scripts/notify-hook/state-io.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 +7 -0
- package/dist/scripts/notify-hook/team-leader-nudge.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 +234 -86
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +7 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +24 -18
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +86 -13
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-test-files.js +193 -22
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +61 -3
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/verify-native-agents.d.ts.map +1 -1
- package/dist/scripts/verify-native-agents.js +58 -1
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +1125 -1
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +46 -1
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +98 -7
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +159 -2
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.js +6 -8
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +6 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +38 -15
- 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 +10 -3
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/subagents/__tests__/tracker.test.js +139 -0
- package/dist/subagents/__tests__/tracker.test.js.map +1 -1
- package/dist/subagents/tracker.d.ts +3 -0
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +41 -4
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/coordination-protocol.test.d.ts +2 -0
- package/dist/team/__tests__/coordination-protocol.test.d.ts.map +1 -0
- package/dist/team/__tests__/coordination-protocol.test.js +173 -0
- package/dist/team/__tests__/coordination-protocol.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +52 -3
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +9 -4
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +83 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +240 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +84 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +4 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/coordination-protocol.d.ts +14 -0
- package/dist/team/coordination-protocol.d.ts.map +1 -0
- package/dist/team/coordination-protocol.js +244 -0
- package/dist/team/coordination-protocol.js.map +1 -0
- package/dist/team/runtime.d.ts +1 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +19 -3
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +3 -2
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +24 -0
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state/types.d.ts +21 -1
- package/dist/team/state/types.d.ts.map +1 -1
- package/dist/team/state/types.js.map +1 -1
- package/dist/team/state.d.ts +17 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +12 -5
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +1 -1
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +2 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +161 -13
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +63 -0
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/utils/__tests__/agents-model-table.test.js +4 -2
- package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
- package/dist/utils/agents-model-table.d.ts.map +1 -1
- package/dist/utils/agents-model-table.js +3 -0
- package/dist/utils/agents-model-table.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +81 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +8 -8
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +334 -21
- package/plugins/oh-my-codex/hooks/hooks.json +1 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +13 -6
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +7 -7
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +9 -4
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -22
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +12 -0
- package/plugins/oh-my-codex/skills/team/SKILL.md +16 -0
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +9 -0
- package/plugins/oh-my-codex/skills/worker/SKILL.md +14 -0
- package/skills/autopilot/SKILL.md +13 -6
- package/skills/code-review/SKILL.md +7 -7
- package/skills/deep-interview/SKILL.md +9 -4
- package/skills/ralph/SKILL.md +22 -22
- package/skills/ralplan/SKILL.md +12 -0
- package/skills/team/SKILL.md +16 -0
- package/skills/ultraqa/SKILL.md +9 -0
- package/skills/worker/SKILL.md +14 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +4435 -2083
- package/src/scripts/__tests__/notify-state-io.test.ts +95 -0
- package/src/scripts/__tests__/notify-tmux-injection.test.ts +82 -0
- package/src/scripts/__tests__/run-test-files.test.ts +102 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +75 -0
- package/src/scripts/codex-native-hook.ts +536 -51
- package/src/scripts/codex-native-pre-post.ts +80 -0
- package/src/scripts/demo-team-e2e.sh +10 -7
- package/src/scripts/eval/eval-parity-smoke.ts +1 -1
- package/src/scripts/hook-payload-guard.ts +113 -0
- package/src/scripts/notify-fallback-watcher.ts +8 -1
- package/src/scripts/notify-hook/__tests__/payload-guard.test.ts +41 -0
- package/src/scripts/notify-hook/auto-nudge.ts +3 -1
- package/src/scripts/notify-hook/ralph-session-resume.ts +2 -8
- package/src/scripts/notify-hook/state-io.ts +75 -37
- package/src/scripts/notify-hook/team-leader-nudge.ts +7 -0
- package/src/scripts/notify-hook/team-worker-stop.ts +193 -52
- package/src/scripts/notify-hook/tmux-injection.ts +35 -19
- package/src/scripts/notify-hook.ts +105 -6
- package/src/scripts/run-test-files.ts +192 -22
- package/src/scripts/sync-plugin-mirror.ts +98 -9
- package/src/scripts/verify-native-agents.ts +65 -1
|
@@ -9,19 +9,22 @@
|
|
|
9
9
|
* skill/workflow state. AGENTS.md now carries the behavioral fallback contract
|
|
10
10
|
* rather than the full keyword/state table.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import { constants as fsConstants } from 'node:fs';
|
|
13
|
+
import { access, lstat, mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
|
|
13
14
|
import { withModeRuntimeContext } from '../state/mode-state-context.js';
|
|
14
|
-
import { dirname, join } from 'node:path';
|
|
15
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
15
16
|
import { classifyTaskSize, isHeavyMode } from './task-size-detector.js';
|
|
16
17
|
import { isApprovedExecutionFollowupShortcut } from '../team/followup-planner.js';
|
|
17
18
|
import { isPlanningComplete, readPlanningArtifacts } from '../planning/artifacts.js';
|
|
18
19
|
import { hasDurableRalplanConsensusEvidenceForCwd } from '../ralplan/consensus-gate.js';
|
|
19
20
|
import { KEYWORD_TRIGGER_DEFINITIONS, compareKeywordMatches } from './keyword-registry.js';
|
|
21
|
+
import { readTeamModeConfig } from '../config/team-mode.js';
|
|
20
22
|
import { SKILL_ACTIVE_STATE_FILE, listActiveSkills, writeSkillActiveStateCopiesForStateDir, } from '../state/skill-active.js';
|
|
21
23
|
import { buildWorkflowTransitionError, evaluateWorkflowTransition, isTrackedWorkflowMode, } from '../state/workflow-transition.js';
|
|
22
24
|
import { reconcileWorkflowTransition } from '../state/workflow-transition-reconcile.js';
|
|
23
25
|
import { clearDeepInterviewQuestionObligation, } from '../question/deep-interview.js';
|
|
24
26
|
import { buildDeepInterviewConfigStateFields, resolveDeepInterviewRuntimeConfig, } from '../config/deep-interview.js';
|
|
27
|
+
import { inferTerminalLifecycleOutcome } from '../runtime/run-outcome.js';
|
|
25
28
|
const ACTIVE_SKILL_CONTINUATION_PATTERNS = [
|
|
26
29
|
/^[\\/]?\s*keep going(?:\s+now)?[.!]?\s*$/i,
|
|
27
30
|
/^[\\/]?\s*continue(?:\s+now)?[.!]?\s*$/i,
|
|
@@ -57,6 +60,198 @@ const STATEFUL_SKILL_SEED_CONFIG = {
|
|
|
57
60
|
ultrawork: { mode: 'ultrawork', initialPhase: 'planning' },
|
|
58
61
|
ultraqa: { mode: 'ultraqa', initialPhase: 'planning' },
|
|
59
62
|
};
|
|
63
|
+
function slugifyAutopilotTask(text) {
|
|
64
|
+
const slug = text
|
|
65
|
+
.replace(/(?:^|\s)\$?(?:oh-my-codex:)?autopilot\b/gi, ' ')
|
|
66
|
+
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
67
|
+
.replace(/^-+|-+$/g, '')
|
|
68
|
+
.toLowerCase()
|
|
69
|
+
.slice(0, 48)
|
|
70
|
+
.replace(/-+$/g, '');
|
|
71
|
+
return slug || 'autopilot-task';
|
|
72
|
+
}
|
|
73
|
+
function utcCompactTimestamp(nowIso) {
|
|
74
|
+
const parsed = new Date(nowIso);
|
|
75
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
76
|
+
throw new Error(`Invalid Autopilot context timestamp: ${nowIso}`);
|
|
77
|
+
}
|
|
78
|
+
return parsed.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z');
|
|
79
|
+
}
|
|
80
|
+
function isSafeAutopilotContextSnapshotPath(value) {
|
|
81
|
+
const path = safeString(value).trim();
|
|
82
|
+
const contextPrefix = '.omx/context/';
|
|
83
|
+
const snapshotName = path.startsWith(contextPrefix) ? path.slice(contextPrefix.length) : '';
|
|
84
|
+
return path.startsWith('.omx/context/')
|
|
85
|
+
&& path.endsWith('.md')
|
|
86
|
+
&& !isAbsolute(path)
|
|
87
|
+
&& !path.split('/').includes('..')
|
|
88
|
+
&& !path.includes('\\')
|
|
89
|
+
&& snapshotName !== ''
|
|
90
|
+
&& !snapshotName.includes('/');
|
|
91
|
+
}
|
|
92
|
+
function isAutopilotRecoverySnapshotPath(path) {
|
|
93
|
+
return path.startsWith('.omx/context/autopilot-recovery-');
|
|
94
|
+
}
|
|
95
|
+
const MAX_REUSABLE_AUTOPILOT_CONTEXT_SNAPSHOT_BYTES = 1024 * 1024;
|
|
96
|
+
async function isReadableAutopilotContextSnapshotPath(sourceCwd, value) {
|
|
97
|
+
if (!isSafeAutopilotContextSnapshotPath(value))
|
|
98
|
+
return false;
|
|
99
|
+
const contextDir = await ensureSafeAutopilotContextDir(sourceCwd);
|
|
100
|
+
const absolutePath = join(sourceCwd, value);
|
|
101
|
+
try {
|
|
102
|
+
const snapshotStat = await lstat(absolutePath);
|
|
103
|
+
if (!snapshotStat.isFile() || snapshotStat.isSymbolicLink())
|
|
104
|
+
return false;
|
|
105
|
+
if (snapshotStat.size > MAX_REUSABLE_AUTOPILOT_CONTEXT_SNAPSHOT_BYTES)
|
|
106
|
+
return false;
|
|
107
|
+
const contextRealPath = await realpath(contextDir);
|
|
108
|
+
const snapshotRealPath = await realpath(absolutePath);
|
|
109
|
+
const relativeToContext = relative(contextRealPath, snapshotRealPath);
|
|
110
|
+
if (relativeToContext === '' || relativeToContext.startsWith('..') || isAbsolute(relativeToContext))
|
|
111
|
+
return false;
|
|
112
|
+
await access(absolutePath, fsConstants.R_OK);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function isRecord(value) {
|
|
120
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
121
|
+
}
|
|
122
|
+
function normalizeAutopilotContextSnapshotCandidate(candidate) {
|
|
123
|
+
if (isRecord(candidate.value)) {
|
|
124
|
+
const path = safeString(candidate.value.path).trim();
|
|
125
|
+
const kind = safeString(candidate.value.kind).trim();
|
|
126
|
+
if (!path || !['canonical', 'legacy', 'recovery'].includes(kind))
|
|
127
|
+
return null;
|
|
128
|
+
if (kind === 'recovery' || isAutopilotRecoverySnapshotPath(path))
|
|
129
|
+
return null;
|
|
130
|
+
return { path, kind };
|
|
131
|
+
}
|
|
132
|
+
const path = safeString(candidate.value).trim();
|
|
133
|
+
if (!path)
|
|
134
|
+
return null;
|
|
135
|
+
if (isAutopilotRecoverySnapshotPath(path))
|
|
136
|
+
return null;
|
|
137
|
+
return { path, kind: candidate.kind ?? 'legacy' };
|
|
138
|
+
}
|
|
139
|
+
async function findReusableAutopilotContextSnapshotPath(sourceCwd, candidates) {
|
|
140
|
+
for (const candidate of candidates) {
|
|
141
|
+
const normalized = normalizeAutopilotContextSnapshotCandidate(candidate);
|
|
142
|
+
if (!normalized || isAutopilotRecoverySnapshotPath(normalized.path) || !isSafeAutopilotContextSnapshotPath(normalized.path))
|
|
143
|
+
continue;
|
|
144
|
+
if (await isReadableAutopilotContextSnapshotPath(sourceCwd, normalized.path))
|
|
145
|
+
return normalized;
|
|
146
|
+
}
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
const AUTOPILOT_CONTEXT_RECOVERY_REASON_MESSAGES = {
|
|
150
|
+
'missing-or-unsafe-legacy-context-snapshot': 'no safe legacy Autopilot context snapshot path was available during continuation.',
|
|
151
|
+
'missing-autopilot-mode-state': 'active Autopilot skill state existed but no matching Autopilot mode state was available during continuation.',
|
|
152
|
+
'malformed-autopilot-mode-state': 'active Autopilot mode state could not be parsed during continuation.',
|
|
153
|
+
'nonpreservable-autopilot-mode-state-missing-current-phase': 'active Autopilot mode state was missing current_phase during continuation.',
|
|
154
|
+
};
|
|
155
|
+
async function ensureSafeAutopilotContextDir(sourceCwd) {
|
|
156
|
+
const rootRealPath = await realpath(sourceCwd);
|
|
157
|
+
const omxDir = join(sourceCwd, '.omx');
|
|
158
|
+
await mkdir(omxDir, { recursive: true });
|
|
159
|
+
if ((await lstat(omxDir)).isSymbolicLink()) {
|
|
160
|
+
throw new Error('Unsafe Autopilot context directory: .omx is a symbolic link');
|
|
161
|
+
}
|
|
162
|
+
const contextDir = join(omxDir, 'context');
|
|
163
|
+
await mkdir(contextDir, { recursive: true });
|
|
164
|
+
if ((await lstat(contextDir)).isSymbolicLink()) {
|
|
165
|
+
throw new Error('Unsafe Autopilot context directory: .omx/context is a symbolic link');
|
|
166
|
+
}
|
|
167
|
+
const contextRealPath = await realpath(contextDir);
|
|
168
|
+
const relativeToRoot = relative(rootRealPath, contextRealPath);
|
|
169
|
+
if (relativeToRoot === '' || relativeToRoot.startsWith('..') || isAbsolute(relativeToRoot)) {
|
|
170
|
+
throw new Error('Unsafe Autopilot context directory: resolved path escapes repository root');
|
|
171
|
+
}
|
|
172
|
+
return contextDir;
|
|
173
|
+
}
|
|
174
|
+
async function writeUniqueAutopilotContextSnapshot(sourceCwd, slug, nowIso, body) {
|
|
175
|
+
const contextDir = await ensureSafeAutopilotContextDir(sourceCwd);
|
|
176
|
+
const timestamp = utcCompactTimestamp(nowIso);
|
|
177
|
+
for (let attempt = 0; attempt < 100; attempt += 1) {
|
|
178
|
+
const suffix = attempt === 0 ? '' : `-${attempt + 1}`;
|
|
179
|
+
const filename = `${slug}-${timestamp}${suffix}.md`;
|
|
180
|
+
const relativePath = `.omx/context/${filename}`;
|
|
181
|
+
const absolutePath = resolve(contextDir, filename);
|
|
182
|
+
try {
|
|
183
|
+
await writeFile(absolutePath, body, { encoding: 'utf-8', flag: 'wx' });
|
|
184
|
+
return relativePath;
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
if (error.code === 'EEXIST')
|
|
188
|
+
continue;
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
throw new Error(`Unable to allocate unique Autopilot context snapshot for ${slug}`);
|
|
193
|
+
}
|
|
194
|
+
async function ensureAutopilotContextSnapshot(sourceCwd, nowIso, activationText, existingSnapshot, options = {}) {
|
|
195
|
+
if (existingSnapshot) {
|
|
196
|
+
if (isSafeAutopilotContextSnapshotPath(existingSnapshot.path)) {
|
|
197
|
+
return {
|
|
198
|
+
path: existingSnapshot.path,
|
|
199
|
+
kind: existingSnapshot.kind,
|
|
200
|
+
original_task_status: existingSnapshot.kind === 'legacy' ? 'legacy-unverified' : 'activation-prompt',
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
throw new Error(`Unsafe Autopilot context snapshot path: ${existingSnapshot.path}`);
|
|
204
|
+
}
|
|
205
|
+
if (options.allowTaskSnapshotCreation === false) {
|
|
206
|
+
const slug = 'autopilot-recovery';
|
|
207
|
+
const continuationInput = activationText.trim() || '<empty>';
|
|
208
|
+
const reason = options.recoveryReason ?? 'missing-or-unsafe-legacy-context-snapshot';
|
|
209
|
+
const body = [
|
|
210
|
+
'# Autopilot context recovery',
|
|
211
|
+
'',
|
|
212
|
+
'- recovery status: degraded',
|
|
213
|
+
`- recovery reason: ${reason}`,
|
|
214
|
+
`- reason detail: ${AUTOPILOT_CONTEXT_RECOVERY_REASON_MESSAGES[reason]}`,
|
|
215
|
+
`- continuation input: ${continuationInput}`,
|
|
216
|
+
'- original task status: unavailable',
|
|
217
|
+
'- original task seed: unavailable; do not treat the continuation input as the task seed.',
|
|
218
|
+
'- required follow-up: re-establish or confirm the intended task context before downstream handoff.',
|
|
219
|
+
'',
|
|
220
|
+
].join('\n');
|
|
221
|
+
const path = await writeUniqueAutopilotContextSnapshot(sourceCwd, slug, nowIso, body);
|
|
222
|
+
return {
|
|
223
|
+
path,
|
|
224
|
+
kind: 'recovery',
|
|
225
|
+
original_task_status: 'unavailable',
|
|
226
|
+
recovery: {
|
|
227
|
+
status: 'degraded',
|
|
228
|
+
reason,
|
|
229
|
+
recovered_at: nowIso,
|
|
230
|
+
source: 'keyword-detector',
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const slug = slugifyAutopilotTask(activationText);
|
|
235
|
+
const taskSeed = activationText.trim() || '$autopilot';
|
|
236
|
+
const body = [
|
|
237
|
+
`# Autopilot task seed: ${slug}`,
|
|
238
|
+
'',
|
|
239
|
+
`- activation prompt / task seed: ${taskSeed}`,
|
|
240
|
+
'- original task status: activation-prompt',
|
|
241
|
+
'- scope note: this seed captures the Autopilot activation prompt and is not guaranteed to include prior conversation context.',
|
|
242
|
+
'- desired outcome: complete the requested Autopilot workflow correctly with durable gate evidence.',
|
|
243
|
+
'- known facts/evidence: Autopilot was activated from a UserPromptSubmit keyword.',
|
|
244
|
+
'- constraints: follow deep-interview -> ralplan -> ultragoal -> code-review -> ultraqa; do not skip gates without persisted evidence.',
|
|
245
|
+
'- unknowns/open questions: to be resolved by the deep-interview gate.',
|
|
246
|
+
'- likely codebase touchpoints: to be discovered during pre-context intake and planning.',
|
|
247
|
+
'',
|
|
248
|
+
].join('\n');
|
|
249
|
+
return {
|
|
250
|
+
path: await writeUniqueAutopilotContextSnapshot(sourceCwd, slug, nowIso, body),
|
|
251
|
+
kind: 'canonical',
|
|
252
|
+
original_task_status: 'activation-prompt',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
60
255
|
function createDeepInterviewInputLock(nowIso, previous) {
|
|
61
256
|
return {
|
|
62
257
|
active: true,
|
|
@@ -117,12 +312,21 @@ async function readExistingDeepInterviewState(statePath) {
|
|
|
117
312
|
}
|
|
118
313
|
}
|
|
119
314
|
async function readJsonStateIfExists(path) {
|
|
315
|
+
return (await readJsonStateWithStatus(path)).state;
|
|
316
|
+
}
|
|
317
|
+
async function readJsonStateWithStatus(path) {
|
|
120
318
|
try {
|
|
121
319
|
const raw = await readFile(path, 'utf-8');
|
|
122
|
-
|
|
320
|
+
const parsed = JSON.parse(raw);
|
|
321
|
+
if (!isRecord(parsed))
|
|
322
|
+
return { state: null, status: 'malformed' };
|
|
323
|
+
return { state: parsed, status: 'ok' };
|
|
123
324
|
}
|
|
124
|
-
catch {
|
|
125
|
-
|
|
325
|
+
catch (error) {
|
|
326
|
+
if (error.code === 'ENOENT') {
|
|
327
|
+
return { state: null, status: 'missing' };
|
|
328
|
+
}
|
|
329
|
+
return { state: null, status: 'malformed' };
|
|
126
330
|
}
|
|
127
331
|
}
|
|
128
332
|
export async function persistDeepInterviewModeState(stateDir, nextSkill, nowIso, previousSkill, input) {
|
|
@@ -192,20 +396,39 @@ function resolveSeedStateFilePath(stateDir, mode, sessionId, scope = 'session')
|
|
|
192
396
|
relativePath: `.omx/state/${mode}-state.json`,
|
|
193
397
|
};
|
|
194
398
|
}
|
|
195
|
-
|
|
399
|
+
function isResettableTerminalModeState(state, expectedMode) {
|
|
400
|
+
if (!state || safeString(state.mode).trim() !== expectedMode)
|
|
401
|
+
return false;
|
|
402
|
+
const phase = safeString(state.current_phase).trim().toLowerCase().replace(/_/g, '-');
|
|
403
|
+
const terminalPhases = expectedMode === 'ralph'
|
|
404
|
+
? ['blocked-on-user', 'complete', 'completed', 'failed', 'cancelled', 'canceled', 'stopped', 'user-stopped']
|
|
405
|
+
: ['complete', 'completed', 'failed', 'cancelled', 'canceled', 'stopped', 'user-stopped'];
|
|
406
|
+
if (terminalPhases.includes(phase))
|
|
407
|
+
return true;
|
|
408
|
+
const lifecycleOutcome = inferTerminalLifecycleOutcome(state, { includeQuestionEnforcement: false });
|
|
409
|
+
return lifecycleOutcome === 'finished'
|
|
410
|
+
|| lifecycleOutcome === 'failed'
|
|
411
|
+
|| lifecycleOutcome === 'userinterlude'
|
|
412
|
+
|| (expectedMode === 'ralph' && lifecycleOutcome === 'blocked');
|
|
413
|
+
}
|
|
414
|
+
async function persistStatefulSkillSeedState(stateDir, nextSkill, nowIso, previousSkill, activationText, sourceCwd, options = {}) {
|
|
196
415
|
const config = STATEFUL_SKILL_SEED_CONFIG[nextSkill.skill];
|
|
197
416
|
if (!config)
|
|
198
417
|
return nextSkill;
|
|
199
418
|
const { absolutePath, relativePath } = resolveSeedStateFilePath(stateDir, config.mode, nextSkill.session_id, config.scope);
|
|
200
|
-
const
|
|
419
|
+
const existingModeStateResult = await readJsonStateWithStatus(absolutePath);
|
|
420
|
+
const existingModeState = existingModeStateResult.state;
|
|
201
421
|
const sameActiveSkill = previousSkill?.skill === nextSkill.skill && previousSkill.active;
|
|
202
422
|
const existingModeMatches = safeString(existingModeState?.mode).trim() === config.mode;
|
|
203
423
|
const existingPhase = safeString(existingModeState?.current_phase).trim();
|
|
424
|
+
const existingModeTerminal = existingModeMatches
|
|
425
|
+
&& isResettableTerminalModeState(existingModeState, config.mode);
|
|
204
426
|
const preserveExistingModeState = existingModeMatches
|
|
205
427
|
&& existingPhase !== ''
|
|
428
|
+
&& !existingModeTerminal
|
|
206
429
|
&& (sameActiveSkill
|
|
207
430
|
|| (config.mode === 'team' && existingModeState?.active === true));
|
|
208
|
-
const startedAt = previousSkill?.skill === nextSkill.skill && previousSkill.active
|
|
431
|
+
const startedAt = previousSkill?.skill === nextSkill.skill && previousSkill.active && !existingModeTerminal
|
|
209
432
|
? safeString(existingModeState?.started_at).trim() || previousSkill.activated_at || nowIso
|
|
210
433
|
: preserveExistingModeState
|
|
211
434
|
? safeString(existingModeState?.started_at).trim() || nowIso
|
|
@@ -228,20 +451,47 @@ async function persistStatefulSkillSeedState(stateDir, nextSkill, nowIso, previo
|
|
|
228
451
|
if (config.includeIteration) {
|
|
229
452
|
const defaultIteration = config.mode === 'autopilot' ? 1 : 0;
|
|
230
453
|
const defaultMaxIterations = config.mode === 'autopilot' ? 10 : 50;
|
|
231
|
-
|
|
232
|
-
baseState.
|
|
454
|
+
const reusableModeState = preserveExistingModeState ? existingModeState : null;
|
|
455
|
+
baseState.iteration = typeof reusableModeState?.iteration === 'number' ? reusableModeState.iteration : defaultIteration;
|
|
456
|
+
baseState.max_iterations = typeof reusableModeState?.max_iterations === 'number' ? reusableModeState.max_iterations : defaultMaxIterations;
|
|
233
457
|
}
|
|
234
458
|
if (config.mode === 'deep-interview') {
|
|
235
459
|
Object.assign(baseState, buildDeepInterviewConfigStateFields(nextSkill.deep_interview_config));
|
|
236
460
|
}
|
|
237
461
|
if (config.mode === 'autopilot') {
|
|
238
|
-
const
|
|
239
|
-
|
|
462
|
+
const reusableModeState = preserveExistingModeState ? existingModeState : null;
|
|
463
|
+
const existingStateRaw = (reusableModeState?.state && typeof reusableModeState.state === 'object')
|
|
464
|
+
? reusableModeState.state
|
|
240
465
|
: {};
|
|
466
|
+
const { context_snapshot_path: legacyStateContextSnapshotPath, context_snapshot_recovery: _legacyContextSnapshotRecovery, ...existingState } = existingStateRaw;
|
|
241
467
|
const existingHandoffs = (existingState.handoff_artifacts && typeof existingState.handoff_artifacts === 'object')
|
|
242
468
|
? existingState.handoff_artifacts
|
|
243
469
|
: {};
|
|
244
|
-
|
|
470
|
+
let recoveryReason = 'missing-or-unsafe-legacy-context-snapshot';
|
|
471
|
+
if (options.activeContinuation === true && !preserveExistingModeState) {
|
|
472
|
+
if (existingModeStateResult.status === 'missing') {
|
|
473
|
+
recoveryReason = 'missing-autopilot-mode-state';
|
|
474
|
+
}
|
|
475
|
+
else if (existingModeStateResult.status === 'malformed') {
|
|
476
|
+
recoveryReason = 'malformed-autopilot-mode-state';
|
|
477
|
+
}
|
|
478
|
+
else if (existingModeMatches && existingPhase === '') {
|
|
479
|
+
recoveryReason = 'nonpreservable-autopilot-mode-state-missing-current-phase';
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
const existingContextSnapshotPath = await findReusableAutopilotContextSnapshotPath(sourceCwd, [
|
|
483
|
+
{ value: existingHandoffs.context_snapshot },
|
|
484
|
+
{ value: existingHandoffs.context_snapshot_path, kind: 'legacy' },
|
|
485
|
+
{ value: legacyStateContextSnapshotPath, kind: 'legacy' },
|
|
486
|
+
{ value: reusableModeState?.context_snapshot_path, kind: 'legacy' },
|
|
487
|
+
]);
|
|
488
|
+
const contextSnapshot = await ensureAutopilotContextSnapshot(sourceCwd, nowIso, activationText || safeString(nextSkill.keyword) || '$autopilot', existingContextSnapshotPath, {
|
|
489
|
+
allowTaskSnapshotCreation: !(preserveExistingModeState || options.activeContinuation === true),
|
|
490
|
+
recoveryReason,
|
|
491
|
+
});
|
|
492
|
+
const contextSnapshotPath = contextSnapshot.path;
|
|
493
|
+
baseState.review_cycle = typeof reusableModeState?.review_cycle === 'number' ? reusableModeState.review_cycle : 0;
|
|
494
|
+
delete baseState.context_snapshot_path;
|
|
245
495
|
baseState.state = {
|
|
246
496
|
...existingState,
|
|
247
497
|
phase_cycle: Array.isArray(existingState.phase_cycle) ? existingState.phase_cycle : ['deep-interview', 'ralplan', 'ultragoal', 'code-review', 'ultraqa'],
|
|
@@ -261,6 +511,13 @@ async function persistStatefulSkillSeedState(stateDir, nextSkill, nowIso, previo
|
|
|
261
511
|
code_review: null,
|
|
262
512
|
ultraqa: null,
|
|
263
513
|
...existingHandoffs,
|
|
514
|
+
context_snapshot_path: contextSnapshotPath,
|
|
515
|
+
context_snapshot: {
|
|
516
|
+
path: contextSnapshotPath,
|
|
517
|
+
kind: contextSnapshot.kind,
|
|
518
|
+
...(contextSnapshot.original_task_status ? { original_task_status: contextSnapshot.original_task_status } : {}),
|
|
519
|
+
...(contextSnapshot.recovery ? { recovery: contextSnapshot.recovery } : {}),
|
|
520
|
+
},
|
|
264
521
|
},
|
|
265
522
|
review_verdict: Object.prototype.hasOwnProperty.call(existingState, 'review_verdict')
|
|
266
523
|
? existingState.review_verdict
|
|
@@ -271,6 +528,7 @@ async function persistStatefulSkillSeedState(stateDir, nextSkill, nowIso, previo
|
|
|
271
528
|
return_to_ralplan_reason: Object.prototype.hasOwnProperty.call(existingState, 'return_to_ralplan_reason')
|
|
272
529
|
? existingState.return_to_ralplan_reason
|
|
273
530
|
: null,
|
|
531
|
+
...(contextSnapshot.recovery ? { context_snapshot_recovery: contextSnapshot.recovery } : {}),
|
|
274
532
|
deep_interview_gate: (existingState.deep_interview_gate && typeof existingState.deep_interview_gate === 'object')
|
|
275
533
|
? existingState.deep_interview_gate
|
|
276
534
|
: {
|
|
@@ -307,7 +565,7 @@ const KEYWORD_MAP = KEYWORD_TRIGGER_DEFINITIONS.map((entry) => ({
|
|
|
307
565
|
skill: entry.skill,
|
|
308
566
|
priority: entry.priority,
|
|
309
567
|
}));
|
|
310
|
-
const KEYWORDS_REQUIRING_INTENT = new Set(['ralph', 'team', 'stop', 'abort', 'parallel', 'autoresearch', 'ultragoal']);
|
|
568
|
+
const KEYWORDS_REQUIRING_INTENT = new Set(['ralph', 'team', 'stop', 'abort', 'parallel', 'autoresearch', 'ultragoal', 'autopilot']);
|
|
311
569
|
const DEEP_INTERVIEW_ACTIVATION_PATTERNS = [
|
|
312
570
|
/(?:^|[^\w])\$(?:deep-interview)\b/i,
|
|
313
571
|
/\/prompts:deep-interview\b/i,
|
|
@@ -379,6 +637,13 @@ const KEYWORD_INTENT_PATTERNS = {
|
|
|
379
637
|
/\b(?:use|run|start|enable|launch|invoke|activate|resume|continue)\s+(?:the\s+)?ultragoal\b/i,
|
|
380
638
|
/\bultragoal\s+(?:mode|workflow|skill|loop|plan|goals?)\b/i,
|
|
381
639
|
],
|
|
640
|
+
autopilot: [
|
|
641
|
+
/(?:^|[^\w])\$(?:autopilot)\b/i,
|
|
642
|
+
/^\s*\/autopilot\b/i,
|
|
643
|
+
/^\s*(?:please\s+)?autopilot(?:\s+(?:this|mode|workflow|skill|loop|now))?\s*[.!]?\s*$/i,
|
|
644
|
+
/\b(?:use|run|start|enable|launch|invoke|activate|resume|continue)\s+(?:the\s+)?autopilot(?:\s+(?:mode|workflow|skill|loop|now))?\s*[.!]?\s*$/i,
|
|
645
|
+
/\bautopilot\s+(?:mode|workflow|skill|loop)\b/i,
|
|
646
|
+
],
|
|
382
647
|
};
|
|
383
648
|
function hasExplicitPromptsInvocation(text) {
|
|
384
649
|
return /(?:^|\s)\/prompts:[\w.-]+(?=[\s.,!?;:]|$)/i.test(text);
|
|
@@ -497,6 +762,13 @@ export function detectPrimaryKeyword(text) {
|
|
|
497
762
|
const matches = detectKeywords(text);
|
|
498
763
|
return matches.length > 0 ? matches[0] : null;
|
|
499
764
|
}
|
|
765
|
+
function filterMatchesForTeamMode(matches, teamEnabled) {
|
|
766
|
+
return teamEnabled ? matches : matches.filter((entry) => entry.skill !== 'team');
|
|
767
|
+
}
|
|
768
|
+
function detectPrimaryKeywordForTeamMode(text, teamEnabled) {
|
|
769
|
+
const matches = filterMatchesForTeamMode(detectKeywords(text), teamEnabled);
|
|
770
|
+
return matches[0] ?? null;
|
|
771
|
+
}
|
|
500
772
|
function isActiveSkillContinuationPrompt(text) {
|
|
501
773
|
const normalized = text.trim();
|
|
502
774
|
if (!normalized)
|
|
@@ -509,13 +781,56 @@ function isNamedActiveSkillContinuationPrompt(text, skill) {
|
|
|
509
781
|
return false;
|
|
510
782
|
return new RegExp(`^[\\\\/]?\\s*${normalizedSkill}\\b(?:\\s+(?:keep\\s+going|continue|resume))(?:\\s+now)?[.!]?\\s*$`, 'i').test(text.trim());
|
|
511
783
|
}
|
|
784
|
+
function isOmxQuestionAnsweredPrompt(text) {
|
|
785
|
+
return /^\s*\[omx question answered\]/i.test(text.trim());
|
|
786
|
+
}
|
|
512
787
|
function shouldReusePreviousSkillForContinuation(text, previous) {
|
|
513
788
|
const previousSkill = safeString(previous?.skill).trim();
|
|
514
789
|
if (!previousSkill || previous?.active !== true || !isTrackedWorkflowMode(previousSkill)) {
|
|
515
790
|
return false;
|
|
516
791
|
}
|
|
517
792
|
return isActiveSkillContinuationPrompt(text)
|
|
518
|
-
|| isNamedActiveSkillContinuationPrompt(text, previousSkill)
|
|
793
|
+
|| isNamedActiveSkillContinuationPrompt(text, previousSkill)
|
|
794
|
+
|| ((previousSkill === 'autopilot' || previousSkill === 'deep-interview') && isOmxQuestionAnsweredPrompt(text));
|
|
795
|
+
}
|
|
796
|
+
function isAutopilotSupervisedChildSkill(skill) {
|
|
797
|
+
return skill === 'code-review'
|
|
798
|
+
|| skill === 'ultraqa'
|
|
799
|
+
|| skill === 'ralplan'
|
|
800
|
+
|| skill === 'ultragoal'
|
|
801
|
+
|| skill === 'deep-interview';
|
|
802
|
+
}
|
|
803
|
+
const AUTOPILOT_SUPERVISED_TRACKED_CHILD_SKILLS = [
|
|
804
|
+
'deep-interview',
|
|
805
|
+
'ralplan',
|
|
806
|
+
'ultragoal',
|
|
807
|
+
'ultraqa',
|
|
808
|
+
];
|
|
809
|
+
async function reconcileAutopilotSupervisedChildModeStates(cwd, stateDir, sessionId, childSkill, nowIso) {
|
|
810
|
+
if (!isTrackedWorkflowMode(childSkill))
|
|
811
|
+
return [];
|
|
812
|
+
const activeChildModes = [];
|
|
813
|
+
for (const mode of AUTOPILOT_SUPERVISED_TRACKED_CHILD_SKILLS) {
|
|
814
|
+
const candidatePaths = [
|
|
815
|
+
resolveSeedStateFilePath(stateDir, mode, sessionId).absolutePath,
|
|
816
|
+
];
|
|
817
|
+
for (const candidatePath of candidatePaths) {
|
|
818
|
+
const existing = await readJsonStateIfExists(candidatePath);
|
|
819
|
+
if (!existing || existing.active !== true || safeString(existing.mode).trim() !== mode)
|
|
820
|
+
continue;
|
|
821
|
+
activeChildModes.push(mode);
|
|
822
|
+
break;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const transition = await reconcileWorkflowTransition(cwd, childSkill, {
|
|
826
|
+
action: 'activate',
|
|
827
|
+
baseStateDir: stateDir,
|
|
828
|
+
currentModes: activeChildModes,
|
|
829
|
+
nowIso,
|
|
830
|
+
sessionId,
|
|
831
|
+
source: 'autopilot-supervised-child',
|
|
832
|
+
});
|
|
833
|
+
return transition.completedPaths;
|
|
519
834
|
}
|
|
520
835
|
function isDeepInterviewRuntimeConfig(value) {
|
|
521
836
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
@@ -535,10 +850,12 @@ function resolveContinuationKeywordMatch(text, previous, fallbackMatch) {
|
|
|
535
850
|
if (!previousSkill || previous?.active !== true || !isTrackedWorkflowMode(previousSkill)) {
|
|
536
851
|
return fallbackMatch;
|
|
537
852
|
}
|
|
538
|
-
|
|
853
|
+
const markedQuestionAnswerContinuation = (previousSkill === 'autopilot' || previousSkill === 'deep-interview')
|
|
854
|
+
&& isOmxQuestionAnsweredPrompt(text);
|
|
855
|
+
if (!markedQuestionAnswerContinuation && parseExplicitSkillInvocations(normalizeWorkflowKeyboardTypos(text)).sawExplicitLikeInvocation) {
|
|
539
856
|
return fallbackMatch;
|
|
540
857
|
}
|
|
541
|
-
if (!shouldReusePreviousSkillForContinuation(text, previous) && !safeString(fallbackMatch?.keyword).trim().startsWith('$')) {
|
|
858
|
+
if (!markedQuestionAnswerContinuation && !shouldReusePreviousSkillForContinuation(text, previous) && !safeString(fallbackMatch?.keyword).trim().startsWith('$')) {
|
|
542
859
|
return fallbackMatch;
|
|
543
860
|
}
|
|
544
861
|
return {
|
|
@@ -584,12 +901,13 @@ export async function recordSkillActivation(input) {
|
|
|
584
901
|
const previousRoot = await readExistingSkillState(rootStatePath);
|
|
585
902
|
const previousSession = sessionStatePath ? await readExistingSkillState(sessionStatePath) : null;
|
|
586
903
|
const previous = input.sessionId ? previousSession : previousRoot;
|
|
587
|
-
const
|
|
904
|
+
const teamMode = readTeamModeConfig(sourceCwd);
|
|
905
|
+
const match = resolveContinuationKeywordMatch(input.text, previous, detectPrimaryKeywordForTeamMode(input.text, teamMode.enabled));
|
|
588
906
|
if (!match)
|
|
589
907
|
return null;
|
|
590
908
|
const nowIso = input.nowIso ?? new Date().toISOString();
|
|
591
909
|
const hadDeepInterviewLock = previous?.skill === 'deep-interview' && previous?.input_lock?.active === true;
|
|
592
|
-
const matches = detectKeywords(input.text);
|
|
910
|
+
const matches = filterMatchesForTeamMode(detectKeywords(input.text), teamMode.enabled);
|
|
593
911
|
const hasCancelIntent = matches.some((entry) => entry.skill === 'cancel');
|
|
594
912
|
if (hasCancelIntent && hadDeepInterviewLock) {
|
|
595
913
|
const state = {
|
|
@@ -619,7 +937,14 @@ export async function recordSkillActivation(input) {
|
|
|
619
937
|
const sameSkill = previous?.active === true && previous.skill === match.skill;
|
|
620
938
|
const sameKeyword = previous?.keyword?.toLowerCase() === match.keyword.toLowerCase();
|
|
621
939
|
const sameSkillContinuation = sameSkill && shouldReusePreviousSkillForContinuation(input.text, previous);
|
|
622
|
-
const
|
|
940
|
+
const matchedSeedConfig = STATEFUL_SKILL_SEED_CONFIG[match.skill];
|
|
941
|
+
const matchedModeState = matchedSeedConfig
|
|
942
|
+
? await readJsonStateIfExists(resolveSeedStateFilePath(input.stateDir, matchedSeedConfig.mode, input.sessionId, matchedSeedConfig.scope).absolutePath)
|
|
943
|
+
: null;
|
|
944
|
+
const matchedModeTerminal = matchedSeedConfig
|
|
945
|
+
? isResettableTerminalModeState(matchedModeState, matchedSeedConfig.mode)
|
|
946
|
+
: false;
|
|
947
|
+
const preserveActivatedAt = sameSkill && !matchedModeTerminal && (sameKeyword || sameSkillContinuation);
|
|
623
948
|
const previousEntries = listActiveSkills(previous ?? {});
|
|
624
949
|
const previousWorkflowEntries = previousEntries.filter((entry) => (isTrackedWorkflowMode(entry.skill)
|
|
625
950
|
&& (!input.sessionId
|
|
@@ -627,12 +952,16 @@ export async function recordSkillActivation(input) {
|
|
|
627
952
|
|| safeString(entry.session_id).trim() === safeString(input.sessionId).trim())));
|
|
628
953
|
const isTrackedWorkflowMatch = isTrackedWorkflowMode(match.skill);
|
|
629
954
|
const trackedMatchSkill = isTrackedWorkflowMatch ? match.skill : null;
|
|
955
|
+
const markedQuestionAnswerContinuation = sameSkill
|
|
956
|
+
&& (match.skill === 'autopilot' || match.skill === 'deep-interview')
|
|
957
|
+
&& isOmxQuestionAnsweredPrompt(input.text);
|
|
630
958
|
const normalizedInputText = isTrackedWorkflowMatch
|
|
631
959
|
? normalizeWorkflowKeyboardTypos(input.text)
|
|
632
960
|
: input.text;
|
|
633
|
-
const workflowMatches = isTrackedWorkflowMatch
|
|
961
|
+
const workflowMatches = isTrackedWorkflowMatch && !markedQuestionAnswerContinuation
|
|
634
962
|
? parseExplicitSkillInvocations(normalizedInputText).matches
|
|
635
963
|
.map((entry) => entry.skill)
|
|
964
|
+
.filter((skill) => teamMode.enabled || skill !== 'team')
|
|
636
965
|
.filter(isTrackedWorkflowMode)
|
|
637
966
|
: [];
|
|
638
967
|
const resolvedWorkflowRequest = isTrackedWorkflowMatch
|
|
@@ -651,6 +980,49 @@ export async function recordSkillActivation(input) {
|
|
|
651
980
|
const deepInterviewConfig = willActivateDeepInterview
|
|
652
981
|
? reusableDeepInterviewConfig ?? resolveDeepInterviewRuntimeConfig({ cwd: sourceCwd, text: input.text })
|
|
653
982
|
: null;
|
|
983
|
+
if (previous?.active === true && previous.skill === 'autopilot' && isAutopilotSupervisedChildSkill(match.skill)) {
|
|
984
|
+
const nextState = {
|
|
985
|
+
...previous,
|
|
986
|
+
version: 1,
|
|
987
|
+
active: true,
|
|
988
|
+
updated_at: nowIso,
|
|
989
|
+
source: 'keyword-detector',
|
|
990
|
+
session_id: input.sessionId ?? previous.session_id,
|
|
991
|
+
thread_id: input.threadId ?? previous.thread_id,
|
|
992
|
+
turn_id: input.turnId ?? previous.turn_id,
|
|
993
|
+
active_skills: listActiveSkills(previous).map((entry) => (entry.skill === 'autopilot'
|
|
994
|
+
? {
|
|
995
|
+
...entry,
|
|
996
|
+
active: true,
|
|
997
|
+
updated_at: nowIso,
|
|
998
|
+
session_id: input.sessionId ?? entry.session_id,
|
|
999
|
+
thread_id: input.threadId ?? entry.thread_id,
|
|
1000
|
+
turn_id: input.turnId ?? entry.turn_id,
|
|
1001
|
+
}
|
|
1002
|
+
: entry)),
|
|
1003
|
+
supervised_child_keyword: match.keyword,
|
|
1004
|
+
supervised_child_skill: match.skill,
|
|
1005
|
+
};
|
|
1006
|
+
try {
|
|
1007
|
+
await reconcileAutopilotSupervisedChildModeStates(sourceCwd, input.stateDir, input.sessionId ?? previous.session_id, match.skill, nowIso);
|
|
1008
|
+
await writeSkillActiveStateCopiesForStateDir(input.stateDir, nextState, input.sessionId, selectRootSkillStateCopy(previousRoot, nextState, input.sessionId));
|
|
1009
|
+
}
|
|
1010
|
+
catch (error) {
|
|
1011
|
+
return {
|
|
1012
|
+
...previous,
|
|
1013
|
+
version: 1,
|
|
1014
|
+
active: true,
|
|
1015
|
+
updated_at: nowIso,
|
|
1016
|
+
source: 'keyword-detector',
|
|
1017
|
+
session_id: input.sessionId ?? previous.session_id,
|
|
1018
|
+
thread_id: input.threadId ?? previous.thread_id,
|
|
1019
|
+
turn_id: input.turnId ?? previous.turn_id,
|
|
1020
|
+
active_skills: listActiveSkills(previous),
|
|
1021
|
+
transition_error: error instanceof Error ? error.message : String(error),
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
return nextState;
|
|
1025
|
+
}
|
|
654
1026
|
if (isTrackedWorkflowMatch) {
|
|
655
1027
|
let nextWorkflowEntries = previousWorkflowEntries.map((entry) => ({ ...entry }));
|
|
656
1028
|
const transitionMessages = [];
|
|
@@ -676,13 +1048,35 @@ export async function recordSkillActivation(input) {
|
|
|
676
1048
|
};
|
|
677
1049
|
}
|
|
678
1050
|
if (decision.autoCompleteModes.length > 0) {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1051
|
+
let transition;
|
|
1052
|
+
try {
|
|
1053
|
+
transition = await reconcileWorkflowTransition(sourceCwd, requestedMode, {
|
|
1054
|
+
action: 'activate',
|
|
1055
|
+
sessionId: input.sessionId,
|
|
1056
|
+
source: 'keyword-detector',
|
|
1057
|
+
baseStateDir: input.stateDir,
|
|
1058
|
+
currentModes: nextWorkflowEntries.map((entry) => entry.skill),
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
catch (error) {
|
|
1062
|
+
return {
|
|
1063
|
+
...(previous ?? {}),
|
|
1064
|
+
version: 1,
|
|
1065
|
+
active: previous?.active ?? nextWorkflowEntries.length > 0,
|
|
1066
|
+
skill: previous?.skill || match.skill,
|
|
1067
|
+
keyword: previous?.keyword || match.keyword,
|
|
1068
|
+
phase: previous?.phase || initialWorkflowPhaseForMode(trackedMatchSkill),
|
|
1069
|
+
activated_at: previous?.activated_at || nowIso,
|
|
1070
|
+
updated_at: nowIso,
|
|
1071
|
+
source: 'keyword-detector',
|
|
1072
|
+
session_id: input.sessionId ?? previous?.session_id,
|
|
1073
|
+
thread_id: input.threadId ?? previous?.thread_id,
|
|
1074
|
+
turn_id: input.turnId ?? previous?.turn_id,
|
|
1075
|
+
active_skills: previousEntries,
|
|
1076
|
+
...(previous?.input_lock ? { input_lock: previous.input_lock } : {}),
|
|
1077
|
+
transition_error: error instanceof Error ? error.message : String(error),
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
686
1080
|
if (transition.transitionMessage) {
|
|
687
1081
|
transitionMessages.push(transition.transitionMessage);
|
|
688
1082
|
}
|
|
@@ -691,7 +1085,7 @@ export async function recordSkillActivation(input) {
|
|
|
691
1085
|
nextWorkflowEntries = nextWorkflowEntries.filter((entry) => (isTrackedWorkflowMode(entry.skill) && survivingSkills.has(entry.skill)));
|
|
692
1086
|
const existingEntry = nextWorkflowEntries.find((entry) => entry.skill === requestedMode);
|
|
693
1087
|
if (existingEntry) {
|
|
694
|
-
existingEntry.phase = requestedMode === match.skill && !sameSkill
|
|
1088
|
+
existingEntry.phase = requestedMode === match.skill && (!sameSkill || matchedModeTerminal)
|
|
695
1089
|
? initialWorkflowPhaseForMode(requestedMode)
|
|
696
1090
|
: existingEntry.phase;
|
|
697
1091
|
existingEntry.active = true;
|
|
@@ -753,7 +1147,7 @@ export async function recordSkillActivation(input) {
|
|
|
753
1147
|
activated_at: requestedEntry.activated_at || workflowState.activated_at,
|
|
754
1148
|
updated_at: requestedEntry.updated_at || workflowState.updated_at,
|
|
755
1149
|
...(requestedEntry.skill === 'deep-interview' && deepInterviewConfig ? { deep_interview_config: deepInterviewConfig } : {}),
|
|
756
|
-
}, nowIso, previous);
|
|
1150
|
+
}, nowIso, previous, input.text, sourceCwd, { activeContinuation: requestedEntry.skill === 'autopilot' && sameSkillContinuation });
|
|
757
1151
|
if (requestedEntry.skill === workflowState.skill) {
|
|
758
1152
|
nextState = {
|
|
759
1153
|
...workflowState,
|
|
@@ -798,7 +1192,7 @@ export async function recordSkillActivation(input) {
|
|
|
798
1192
|
...(match.skill === 'deep-interview' && deepInterviewConfig ? { deep_interview_config: deepInterviewConfig } : {}),
|
|
799
1193
|
};
|
|
800
1194
|
try {
|
|
801
|
-
const nextState = await persistStatefulSkillSeedState(input.stateDir, state, nowIso, previous);
|
|
1195
|
+
const nextState = await persistStatefulSkillSeedState(input.stateDir, state, nowIso, previous, input.text, sourceCwd, { activeContinuation: match.skill === 'autopilot' && sameSkillContinuation });
|
|
802
1196
|
nextState.active_skills = buildActiveSkills(nextState);
|
|
803
1197
|
await writeSkillActiveStateCopiesForStateDir(input.stateDir, nextState, input.sessionId, selectRootSkillStateCopy(previousRoot, nextState, input.sessionId));
|
|
804
1198
|
await persistDeepInterviewModeState(input.stateDir, nextState, nowIso, previous, input);
|
|
@@ -914,7 +1308,9 @@ export function applyRalplanGate(keywords, text, options = {}) {
|
|
|
914
1308
|
return { keywords, gateApplied: false, gatedKeywords: [] };
|
|
915
1309
|
}
|
|
916
1310
|
const planningComplete = isPlanningComplete(readPlanningArtifacts(options.cwd ?? process.cwd()));
|
|
917
|
-
const consensusComplete = hasDurableRalplanConsensusEvidenceForCwd(options.cwd ?? process.cwd()
|
|
1311
|
+
const consensusComplete = hasDurableRalplanConsensusEvidenceForCwd(options.cwd ?? process.cwd(), {
|
|
1312
|
+
requireNativeSubagents: options.requireNativeSubagents,
|
|
1313
|
+
});
|
|
918
1314
|
const shortFollowupBypasses = executionKeywords.filter((keyword) => {
|
|
919
1315
|
if (keyword !== 'team' && keyword !== 'ralph')
|
|
920
1316
|
return false;
|