oh-my-codex 0.15.0 → 0.15.2
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 +5 -5
- package/Cargo.toml +1 -1
- package/README.md +36 -5
- package/crates/omx-explore/src/main.rs +222 -12
- package/dist/agents/__tests__/native-config.test.js +40 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/native-config.d.ts +1 -0
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +6 -1
- package/dist/agents/native-config.js.map +1 -1
- package/dist/agents/policy.d.ts +1 -0
- package/dist/agents/policy.d.ts.map +1 -1
- package/dist/agents/policy.js +4 -0
- package/dist/agents/policy.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-guided.test.js +37 -13
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-team.test.js +46 -1
- package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +225 -111
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +96 -1
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +15 -2
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +292 -3
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +223 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-parity.test.js +86 -0
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +23 -0
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +76 -11
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +140 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +310 -4
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js +78 -19
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +79 -2
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/sidecar.test.d.ts +2 -0
- package/dist/cli/__tests__/sidecar.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sidecar.test.js +24 -0
- package/dist/cli/__tests__/sidecar.test.js.map +1 -0
- package/dist/cli/__tests__/team.test.js +54 -7
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/autoresearch-guided.d.ts.map +1 -1
- package/dist/cli/autoresearch-guided.js +12 -4
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/codex-home.d.ts +4 -6
- package/dist/cli/codex-home.d.ts.map +1 -1
- package/dist/cli/codex-home.js +9 -41
- package/dist/cli/codex-home.js.map +1 -1
- package/dist/cli/doctor.d.ts +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +509 -279
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +6 -4
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +284 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/omx.js +3 -1
- package/dist/cli/omx.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +13 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -0
- package/dist/cli/plugin-marketplace.js +77 -0
- package/dist/cli/plugin-marketplace.js.map +1 -0
- package/dist/cli/question.d.ts +1 -1
- package/dist/cli/question.d.ts.map +1 -1
- package/dist/cli/question.js +26 -12
- package/dist/cli/question.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +20 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -0
- package/dist/cli/setup-preferences.js +71 -0
- package/dist/cli/setup-preferences.js.map +1 -0
- package/dist/cli/setup.d.ts +7 -5
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +271 -152
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts +1 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +70 -15
- package/dist/cli/team.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +100 -3
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +6 -5
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts +2 -0
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +1 -0
- package/dist/config/__tests__/generator-status-line-presets.test.js +203 -0
- package/dist/config/__tests__/generator-status-line-presets.test.js.map +1 -0
- package/dist/config/__tests__/models.test.js +23 -1
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/generator.d.ts +9 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +184 -16
- package/dist/config/generator.js.map +1 -1
- package/dist/config/models.d.ts +5 -1
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +12 -2
- package/dist/config/models.js.map +1 -1
- package/dist/exec/followup.d.ts +44 -0
- package/dist/exec/followup.d.ts.map +1 -0
- package/dist/exec/followup.js +349 -0
- package/dist/exec/followup.js.map +1 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +37 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/codebase-map.test.js +63 -1
- package/dist/hooks/__tests__/codebase-map.test.js.map +1 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +1 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js +5 -5
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +12 -9
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +25 -18
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +23 -2
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +45 -2
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +17 -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 +121 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +4 -4
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +103 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +2 -2
- 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 +27 -13
- 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.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +35 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +215 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +70 -3
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +5 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +3 -2
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +9 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js +22 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +1 -0
- package/dist/hooks/codebase-map.d.ts.map +1 -1
- package/dist/hooks/codebase-map.js +83 -6
- package/dist/hooks/codebase-map.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +35 -4
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts +6 -0
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +117 -13
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +2 -0
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +6 -0
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +4 -4
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +4 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/types.test.js +27 -0
- package/dist/hud/__tests__/types.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +8 -0
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/types.d.ts +9 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js +3 -0
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +23 -5
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +50 -7
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +70 -12
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +10 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +71 -26
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-server.d.ts +5 -11
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +16 -432
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/modes/__tests__/base-autoresearch-contract.test.js +1 -1
- package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +89 -5
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +98 -1
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/index.d.ts +5 -3
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +4 -3
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts +7 -6
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +90 -11
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/review-verdict.d.ts +3 -0
- package/dist/pipeline/review-verdict.d.ts.map +1 -0
- package/dist/pipeline/review-verdict.js +14 -0
- package/dist/pipeline/review-verdict.js.map +1 -0
- package/dist/pipeline/stages/code-review.d.ts +33 -0
- package/dist/pipeline/stages/code-review.d.ts.map +1 -0
- package/dist/pipeline/stages/code-review.js +51 -0
- package/dist/pipeline/stages/code-review.js.map +1 -0
- package/dist/pipeline/stages/ralph-verify.d.ts +12 -2
- package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -1
- package/dist/pipeline/stages/ralph-verify.js +24 -6
- package/dist/pipeline/stages/ralph-verify.js.map +1 -1
- package/dist/pipeline/stages/ralplan.d.ts +1 -1
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
- package/dist/pipeline/stages/ralplan.js +21 -1
- package/dist/pipeline/stages/ralplan.js.map +1 -1
- package/dist/pipeline/types.d.ts +14 -7
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +2 -2
- package/dist/planning/__tests__/artifacts.test.js +152 -1
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/artifacts.d.ts +9 -0
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +60 -1
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/question/__tests__/client.test.js +23 -3
- package/dist/question/__tests__/client.test.js.map +1 -1
- package/dist/question/__tests__/renderer.test.js +148 -37
- package/dist/question/__tests__/renderer.test.js.map +1 -1
- package/dist/question/__tests__/types.test.js +21 -0
- package/dist/question/__tests__/types.test.js.map +1 -1
- package/dist/question/__tests__/ui.test.js +155 -7
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/client.d.ts +14 -4
- package/dist/question/client.d.ts.map +1 -1
- package/dist/question/client.js.map +1 -1
- package/dist/question/renderer.d.ts +11 -1
- package/dist/question/renderer.d.ts.map +1 -1
- package/dist/question/renderer.js +102 -7
- package/dist/question/renderer.js.map +1 -1
- package/dist/question/state.d.ts +2 -2
- package/dist/question/state.d.ts.map +1 -1
- package/dist/question/state.js +26 -17
- package/dist/question/state.js.map +1 -1
- package/dist/question/types.d.ts +25 -1
- package/dist/question/types.d.ts.map +1 -1
- package/dist/question/types.js +48 -13
- package/dist/question/types.js.map +1 -1
- package/dist/question/ui.d.ts +15 -2
- package/dist/question/ui.d.ts.map +1 -1
- package/dist/question/ui.js +268 -162
- package/dist/question/ui.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +415 -94
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/generate-release-body.test.js +36 -0
- package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts +2 -0
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/prompt-inventory.test.js +56 -0
- package/dist/scripts/__tests__/prompt-inventory.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +232 -54
- 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 +12 -9
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/generate-release-body.d.ts.map +1 -1
- package/dist/scripts/generate-release-body.js +12 -3
- package/dist/scripts/generate-release-body.js.map +1 -1
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +153 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +1 -0
- package/dist/scripts/notify-hook/managed-tmux.d.ts +4 -2
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +188 -6
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
- package/dist/scripts/notify-hook/process-runner.js +7 -3
- package/dist/scripts/notify-hook/process-runner.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +96 -11
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +3 -3
- package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts +34 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.js +434 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker.d.ts +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +3 -43
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +25 -4
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +36 -5
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/prompt-inventory.d.ts +29 -0
- package/dist/scripts/prompt-inventory.d.ts.map +1 -0
- package/dist/scripts/prompt-inventory.js +178 -0
- package/dist/scripts/prompt-inventory.js.map +1 -0
- package/dist/scripts/run-test-files.js +1 -0
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/sidecar/__tests__/boundary.test.d.ts +2 -0
- package/dist/sidecar/__tests__/boundary.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/boundary.test.js +48 -0
- package/dist/sidecar/__tests__/boundary.test.js.map +1 -0
- package/dist/sidecar/__tests__/collector.test.d.ts +2 -0
- package/dist/sidecar/__tests__/collector.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/collector.test.js +162 -0
- package/dist/sidecar/__tests__/collector.test.js.map +1 -0
- package/dist/sidecar/__tests__/render.test.d.ts +2 -0
- package/dist/sidecar/__tests__/render.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/render.test.js +67 -0
- package/dist/sidecar/__tests__/render.test.js.map +1 -0
- package/dist/sidecar/__tests__/tmux.test.d.ts +2 -0
- package/dist/sidecar/__tests__/tmux.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/tmux.test.js +30 -0
- package/dist/sidecar/__tests__/tmux.test.js.map +1 -0
- package/dist/sidecar/__tests__/watch.test.d.ts +2 -0
- package/dist/sidecar/__tests__/watch.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/watch.test.js +42 -0
- package/dist/sidecar/__tests__/watch.test.js.map +1 -0
- package/dist/sidecar/collector.d.ts +4 -0
- package/dist/sidecar/collector.d.ts.map +1 -0
- package/dist/sidecar/collector.js +377 -0
- package/dist/sidecar/collector.js.map +1 -0
- package/dist/sidecar/index.d.ts +25 -0
- package/dist/sidecar/index.d.ts.map +1 -0
- package/dist/sidecar/index.js +165 -0
- package/dist/sidecar/index.js.map +1 -0
- package/dist/sidecar/render.d.ts +3 -0
- package/dist/sidecar/render.d.ts.map +1 -0
- package/dist/sidecar/render.js +72 -0
- package/dist/sidecar/render.js.map +1 -0
- package/dist/sidecar/tmux.d.ts +13 -0
- package/dist/sidecar/tmux.d.ts.map +1 -0
- package/dist/sidecar/tmux.js +44 -0
- package/dist/sidecar/tmux.js.map +1 -0
- package/dist/sidecar/types.d.ts +125 -0
- package/dist/sidecar/types.d.ts.map +1 -0
- package/dist/sidecar/types.js +2 -0
- package/dist/sidecar/types.js.map +1 -0
- package/dist/state/__tests__/operations.test.js +50 -22
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +9 -1
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +19 -7
- package/dist/state/operations.js.map +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +1 -0
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/commit-hygiene.test.d.ts +2 -0
- package/dist/team/__tests__/commit-hygiene.test.d.ts.map +1 -0
- package/dist/team/__tests__/commit-hygiene.test.js +93 -0
- package/dist/team/__tests__/commit-hygiene.test.js.map +1 -0
- package/dist/team/__tests__/delegation-policy.test.d.ts +2 -0
- package/dist/team/__tests__/delegation-policy.test.d.ts.map +1 -0
- package/dist/team/__tests__/delegation-policy.test.js +69 -0
- package/dist/team/__tests__/delegation-policy.test.js.map +1 -0
- package/dist/team/__tests__/events.test.js +54 -4
- package/dist/team/__tests__/events.test.js.map +1 -1
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +2 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js +78 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +1 -0
- package/dist/team/__tests__/model-contract.test.js +16 -0
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +2 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +1 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js +95 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +623 -14
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +177 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +110 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +399 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +94 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/commit-hygiene.d.ts +22 -3
- package/dist/team/commit-hygiene.d.ts.map +1 -1
- package/dist/team/commit-hygiene.js +134 -2
- package/dist/team/commit-hygiene.js.map +1 -1
- package/dist/team/contracts.d.ts +1 -1
- package/dist/team/contracts.d.ts.map +1 -1
- package/dist/team/contracts.js +2 -0
- package/dist/team/contracts.js.map +1 -1
- package/dist/team/dag-schema.d.ts +38 -0
- package/dist/team/dag-schema.d.ts.map +1 -0
- package/dist/team/dag-schema.js +221 -0
- package/dist/team/dag-schema.js.map +1 -0
- package/dist/team/delegation-policy.d.ts +3 -0
- package/dist/team/delegation-policy.d.ts.map +1 -0
- package/dist/team/delegation-policy.js +82 -0
- package/dist/team/delegation-policy.js.map +1 -0
- package/dist/team/model-contract.d.ts +3 -1
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +44 -5
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/repo-aware-decomposition.d.ts +60 -0
- package/dist/team/repo-aware-decomposition.d.ts.map +1 -0
- package/dist/team/repo-aware-decomposition.js +229 -0
- package/dist/team/repo-aware-decomposition.js.map +1 -0
- package/dist/team/runtime.d.ts +27 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +172 -52
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +33 -0
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state/types.d.ts +23 -1
- 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 +35 -0
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +281 -1
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts +27 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +6 -0
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts +1 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +105 -6
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +3 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +77 -4
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/utils/agents-md.d.ts +3 -0
- package/dist/utils/agents-md.d.ts.map +1 -1
- package/dist/utils/agents-md.js +25 -0
- package/dist/utils/agents-md.js.map +1 -1
- package/package.json +3 -2
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +2 -2
- package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +134 -205
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +4 -4
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +14 -7
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/help/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +41 -10
- package/plugins/oh-my-codex/skills/plan/SKILL.md +12 -14
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +2 -4
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +5 -9
- package/plugins/oh-my-codex/skills/security-review/SKILL.md +4 -4
- package/plugins/oh-my-codex/skills/team/SKILL.md +2 -5
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +2 -5
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +2 -3
- package/prompts/analyst.md +2 -2
- package/prompts/api-reviewer.md +2 -2
- package/prompts/architect.md +2 -2
- package/prompts/build-fixer.md +2 -2
- package/prompts/code-reviewer.md +15 -5
- package/prompts/code-simplifier.md +1 -1
- package/prompts/critic.md +35 -83
- package/prompts/debugger.md +2 -2
- package/prompts/dependency-expert.md +2 -2
- package/prompts/designer.md +2 -2
- package/prompts/executor.md +40 -114
- package/prompts/explore-harness.md +1 -1
- package/prompts/explore.md +37 -90
- package/prompts/git-master.md +2 -2
- package/prompts/information-architect.md +1 -1
- package/prompts/performance-reviewer.md +2 -2
- package/prompts/planner.md +35 -62
- package/prompts/product-analyst.md +2 -2
- package/prompts/product-manager.md +2 -2
- package/prompts/qa-tester.md +2 -2
- package/prompts/quality-reviewer.md +2 -2
- package/prompts/quality-strategist.md +2 -2
- package/prompts/researcher.md +46 -78
- package/prompts/security-reviewer.md +2 -2
- package/prompts/sisyphus-lite.md +2 -2
- package/prompts/style-reviewer.md +2 -2
- package/prompts/team-executor.md +1 -1
- package/prompts/test-engineer.md +2 -2
- package/prompts/ux-researcher.md +2 -2
- package/prompts/verifier.md +29 -34
- package/prompts/vision.md +2 -2
- package/prompts/writer.md +2 -2
- package/skills/ai-slop-cleaner/SKILL.md +1 -1
- package/skills/analyze/SKILL.md +1 -1
- package/skills/autopilot/SKILL.md +134 -205
- package/skills/build-fix/SKILL.md +4 -4
- package/skills/code-review/SKILL.md +4 -4
- package/skills/deep-interview/SKILL.md +14 -7
- package/skills/doctor/SKILL.md +1 -1
- package/skills/help/SKILL.md +1 -1
- package/skills/omx-setup/SKILL.md +41 -10
- package/skills/plan/SKILL.md +12 -14
- package/skills/ralph/SKILL.md +2 -4
- package/skills/ralplan/SKILL.md +5 -9
- package/skills/security-review/SKILL.md +4 -4
- package/skills/team/SKILL.md +2 -5
- package/skills/ultraqa/SKILL.md +2 -5
- package/skills/ultrawork/SKILL.md +2 -3
- package/src/scripts/__tests__/codex-native-hook.test.ts +502 -94
- package/src/scripts/__tests__/generate-release-body.test.ts +41 -0
- package/src/scripts/__tests__/prompt-inventory.test.ts +64 -0
- package/src/scripts/codex-native-hook.ts +293 -61
- package/src/scripts/codex-native-pre-post.ts +10 -8
- package/src/scripts/generate-release-body.ts +13 -2
- package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +180 -0
- package/src/scripts/notify-hook/managed-tmux.ts +196 -9
- package/src/scripts/notify-hook/process-runner.ts +7 -3
- package/src/scripts/notify-hook/team-dispatch.ts +103 -11
- package/src/scripts/notify-hook/team-tmux-guard.ts +3 -3
- package/src/scripts/notify-hook/team-worker-posttooluse.ts +536 -0
- package/src/scripts/notify-hook/team-worker.ts +4 -48
- package/src/scripts/notify-hook/tmux-injection.ts +24 -6
- package/src/scripts/notify-hook.ts +36 -5
- package/src/scripts/prompt-inventory.ts +218 -0
- package/src/scripts/run-test-files.ts +1 -0
- package/templates/AGENTS.md +34 -95
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
|
-
import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { chmod, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
@@ -12,6 +12,7 @@ import { initTeamState, readTeamLeaderAttention, readTeamPhase, writeTeamLeaderA
|
|
|
12
12
|
import { dispatchCodexNativeHook, isCodexNativeHookMainModule, mapCodexHookEventToOmxEvent, resolveSessionOwnerPidFromAncestry, } from "../codex-native-hook.js";
|
|
13
13
|
import { writeSessionStart } from "../../hooks/session.js";
|
|
14
14
|
import { resetTriageConfigCache } from "../../hooks/triage-config.js";
|
|
15
|
+
import { executeStateOperation } from "../../state/operations.js";
|
|
15
16
|
function nativeHookScriptPath() {
|
|
16
17
|
return join(process.cwd(), "dist", "scripts", "codex-native-hook.js");
|
|
17
18
|
}
|
|
@@ -163,6 +164,46 @@ describe("codex native hook dispatch", () => {
|
|
|
163
164
|
assert.equal(output.hookSpecificOutput?.hookEventName, "Unknown");
|
|
164
165
|
assert.match(String(output.hookSpecificOutput?.additionalContext ?? ""), /stdin JSON parsing failed inside codex-native-hook:/);
|
|
165
166
|
});
|
|
167
|
+
it("emits parseable no-op JSON stdout for inactive Stop CLI runs", async () => {
|
|
168
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-cli-stop-noop-json-"));
|
|
169
|
+
try {
|
|
170
|
+
const stdout = runNativeHookCli({
|
|
171
|
+
hook_event_name: "Stop",
|
|
172
|
+
cwd,
|
|
173
|
+
session_id: "sess-cli-stop-noop-json",
|
|
174
|
+
thread_id: "thread-cli-stop-noop-json",
|
|
175
|
+
turn_id: "turn-cli-stop-noop-json",
|
|
176
|
+
}, { cwd });
|
|
177
|
+
const output = parseSingleJsonStdout(stdout);
|
|
178
|
+
assert.deepEqual(output, {});
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
await rm(cwd, { recursive: true, force: true });
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
it("does not crash Stop hook dispatch when the exec follow-up queue is malformed", async () => {
|
|
185
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-stop-exec-followup-corrupt-"));
|
|
186
|
+
try {
|
|
187
|
+
const session = await writeSessionStart(cwd, "sess-exec-followup-corrupt");
|
|
188
|
+
const queuePath = join(cwd, ".omx", "state", "sessions", session.session_id, "exec-followups.json");
|
|
189
|
+
await mkdir(dirname(queuePath), { recursive: true });
|
|
190
|
+
await writeFile(queuePath, '{"version":1,"records":[', "utf-8");
|
|
191
|
+
const result = await dispatchCodexNativeHook({
|
|
192
|
+
hook_event_name: "Stop",
|
|
193
|
+
cwd,
|
|
194
|
+
session_id: session.session_id,
|
|
195
|
+
});
|
|
196
|
+
assert.equal(result.hookEventName, "Stop");
|
|
197
|
+
assert.equal(result.outputJson, null);
|
|
198
|
+
const queueDirEntries = await readdir(dirname(queuePath));
|
|
199
|
+
assert.ok(queueDirEntries.some((entry) => entry.startsWith("exec-followups.json.corrupt-")));
|
|
200
|
+
const auditPath = join(cwd, ".omx", "logs", `exec-followups-${new Date().toISOString().slice(0, 10)}.jsonl`);
|
|
201
|
+
assert.match(await readFile(auditPath, "utf-8"), /exec_followup_queue_corrupt_recovered/);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
await rm(cwd, { recursive: true, force: true });
|
|
205
|
+
}
|
|
206
|
+
});
|
|
166
207
|
it("emits exactly one parseable JSON object for active Stop CLI continuation", async () => {
|
|
167
208
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-cli-stop-json-"));
|
|
168
209
|
try {
|
|
@@ -309,6 +350,127 @@ describe("codex native hook dispatch", () => {
|
|
|
309
350
|
await rm(cwd, { recursive: true, force: true });
|
|
310
351
|
}
|
|
311
352
|
});
|
|
353
|
+
it("keeps subagent SessionStart from replacing the canonical leader session", async () => {
|
|
354
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-subagent-session-start-"));
|
|
355
|
+
try {
|
|
356
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
357
|
+
const canonicalSessionId = "omx-leader-session";
|
|
358
|
+
const leaderNativeSessionId = "codex-leader-thread";
|
|
359
|
+
const childNativeSessionId = "codex-child-thread";
|
|
360
|
+
await mkdir(join(stateDir, "sessions", canonicalSessionId), { recursive: true });
|
|
361
|
+
await writeSessionStart(cwd, canonicalSessionId, {
|
|
362
|
+
nativeSessionId: leaderNativeSessionId,
|
|
363
|
+
});
|
|
364
|
+
await writeJson(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), {
|
|
365
|
+
active: true,
|
|
366
|
+
mode: "ralph",
|
|
367
|
+
current_phase: "executing",
|
|
368
|
+
iteration: 1,
|
|
369
|
+
max_iterations: 5,
|
|
370
|
+
});
|
|
371
|
+
const transcriptPath = join(cwd, "subagent-rollout.jsonl");
|
|
372
|
+
await writeFile(transcriptPath, `${JSON.stringify({
|
|
373
|
+
type: "session_meta",
|
|
374
|
+
payload: {
|
|
375
|
+
id: childNativeSessionId,
|
|
376
|
+
source: {
|
|
377
|
+
subagent: {
|
|
378
|
+
thread_spawn: {
|
|
379
|
+
parent_thread_id: leaderNativeSessionId,
|
|
380
|
+
depth: 1,
|
|
381
|
+
agent_nickname: "Hegel",
|
|
382
|
+
agent_role: "critic",
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
agent_nickname: "Hegel",
|
|
387
|
+
agent_role: "critic",
|
|
388
|
+
},
|
|
389
|
+
})}\n`);
|
|
390
|
+
const result = await dispatchCodexNativeHook({
|
|
391
|
+
hook_event_name: "SessionStart",
|
|
392
|
+
cwd,
|
|
393
|
+
session_id: childNativeSessionId,
|
|
394
|
+
transcript_path: transcriptPath,
|
|
395
|
+
}, { cwd, sessionOwnerPid: process.pid });
|
|
396
|
+
const sessionState = JSON.parse(await readFile(join(stateDir, "session.json"), "utf-8"));
|
|
397
|
+
assert.equal(sessionState.session_id, canonicalSessionId);
|
|
398
|
+
assert.equal(sessionState.native_session_id, leaderNativeSessionId);
|
|
399
|
+
assert.equal(existsSync(join(stateDir, "sessions", childNativeSessionId, "ralph-state.json")), false);
|
|
400
|
+
assert.ok(result.outputJson);
|
|
401
|
+
const leaderRalph = JSON.parse(await readFile(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), "utf-8"));
|
|
402
|
+
assert.equal(leaderRalph.active, true);
|
|
403
|
+
assert.equal(leaderRalph.current_phase, "executing");
|
|
404
|
+
const tracking = JSON.parse(await readFile(join(stateDir, "subagent-tracking.json"), "utf-8"));
|
|
405
|
+
assert.equal(tracking.sessions?.[canonicalSessionId]?.leader_thread_id, leaderNativeSessionId);
|
|
406
|
+
assert.equal(tracking.sessions?.[canonicalSessionId]?.threads?.[childNativeSessionId]?.kind, "subagent");
|
|
407
|
+
assert.equal(tracking.sessions?.[canonicalSessionId]?.threads?.[childNativeSessionId]?.mode, "critic");
|
|
408
|
+
assert.equal(tracking.sessions?.[leaderNativeSessionId]?.leader_thread_id, leaderNativeSessionId);
|
|
409
|
+
assert.equal(tracking.sessions?.[leaderNativeSessionId]?.threads?.[childNativeSessionId]?.kind, "subagent");
|
|
410
|
+
assert.equal(tracking.sessions?.[leaderNativeSessionId]?.threads?.[childNativeSessionId]?.mode, "critic");
|
|
411
|
+
}
|
|
412
|
+
finally {
|
|
413
|
+
await rm(cwd, { recursive: true, force: true });
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
it("does not attach a subagent SessionStart to an unrelated canonical leader", async () => {
|
|
417
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-subagent-session-start-mismatch-"));
|
|
418
|
+
try {
|
|
419
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
420
|
+
const canonicalSessionId = "omx-leader-session-a";
|
|
421
|
+
const leaderNativeSessionId = "codex-leader-thread-a";
|
|
422
|
+
const unrelatedParentNativeSessionId = "codex-leader-thread-b";
|
|
423
|
+
const childNativeSessionId = "codex-child-thread-b";
|
|
424
|
+
await mkdir(join(stateDir, "sessions", canonicalSessionId), { recursive: true });
|
|
425
|
+
await writeSessionStart(cwd, canonicalSessionId, {
|
|
426
|
+
nativeSessionId: leaderNativeSessionId,
|
|
427
|
+
});
|
|
428
|
+
await writeJson(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), {
|
|
429
|
+
active: true,
|
|
430
|
+
mode: "ralph",
|
|
431
|
+
current_phase: "executing",
|
|
432
|
+
iteration: 1,
|
|
433
|
+
max_iterations: 5,
|
|
434
|
+
});
|
|
435
|
+
const transcriptPath = join(cwd, "unrelated-subagent-rollout.jsonl");
|
|
436
|
+
await writeFile(transcriptPath, `${JSON.stringify({
|
|
437
|
+
type: "session_meta",
|
|
438
|
+
payload: {
|
|
439
|
+
id: childNativeSessionId,
|
|
440
|
+
source: {
|
|
441
|
+
subagent: {
|
|
442
|
+
thread_spawn: {
|
|
443
|
+
parent_thread_id: unrelatedParentNativeSessionId,
|
|
444
|
+
depth: 1,
|
|
445
|
+
agent_nickname: "Spinoza",
|
|
446
|
+
agent_role: "critic",
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
agent_nickname: "Spinoza",
|
|
451
|
+
agent_role: "critic",
|
|
452
|
+
},
|
|
453
|
+
})}\n`);
|
|
454
|
+
const result = await dispatchCodexNativeHook({
|
|
455
|
+
hook_event_name: "SessionStart",
|
|
456
|
+
cwd,
|
|
457
|
+
session_id: childNativeSessionId,
|
|
458
|
+
transcript_path: transcriptPath,
|
|
459
|
+
}, { cwd, sessionOwnerPid: process.pid });
|
|
460
|
+
const sessionState = JSON.parse(await readFile(join(stateDir, "session.json"), "utf-8"));
|
|
461
|
+
assert.equal(sessionState.session_id, canonicalSessionId);
|
|
462
|
+
assert.equal(sessionState.native_session_id, leaderNativeSessionId);
|
|
463
|
+
assert.equal(existsSync(join(stateDir, "subagent-tracking.json")), false);
|
|
464
|
+
assert.equal(existsSync(join(stateDir, "sessions", childNativeSessionId)), false);
|
|
465
|
+
assert.equal(result.outputJson, null);
|
|
466
|
+
const leaderRalph = JSON.parse(await readFile(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), "utf-8"));
|
|
467
|
+
assert.equal(leaderRalph.active, true);
|
|
468
|
+
assert.equal(leaderRalph.current_phase, "executing");
|
|
469
|
+
}
|
|
470
|
+
finally {
|
|
471
|
+
await rm(cwd, { recursive: true, force: true });
|
|
472
|
+
}
|
|
473
|
+
});
|
|
312
474
|
it("describes attached tmux runtime in SessionStart context when TMUX is present", async () => {
|
|
313
475
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-start-tmux-"));
|
|
314
476
|
process.env.TMUX = "/tmp/tmux-attached";
|
|
@@ -326,7 +488,7 @@ describe("codex native hook dispatch", () => {
|
|
|
326
488
|
assert.match(additionalContext, /\[Execution environment\]/);
|
|
327
489
|
assert.match(additionalContext, /attached tmux runtime/);
|
|
328
490
|
assert.match(additionalContext, /omx team, omx hud, and omx quest(?:ion) are directly usable in this session/);
|
|
329
|
-
assert.match(additionalContext, /visible renderer available from the current pane/);
|
|
491
|
+
assert.match(additionalContext, /visible temporary renderer available from the current pane; primary success JSON is answers\[\]/);
|
|
330
492
|
}
|
|
331
493
|
finally {
|
|
332
494
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -1771,7 +1933,7 @@ esac
|
|
|
1771
1933
|
await rm(cwd, { recursive: true, force: true });
|
|
1772
1934
|
}
|
|
1773
1935
|
});
|
|
1774
|
-
it("blocks PreToolUse git commit when the inline message is not Lore-compliant", async () => {
|
|
1936
|
+
it("blocks PreToolUse git commit with supported response shape when the inline message is not Lore-compliant", async () => {
|
|
1775
1937
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-pretool-git-commit-invalid-"));
|
|
1776
1938
|
try {
|
|
1777
1939
|
const result = await dispatchCodexNativeHook({
|
|
@@ -1787,13 +1949,6 @@ esac
|
|
|
1787
1949
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
1788
1950
|
hookSpecificOutput: {
|
|
1789
1951
|
hookEventName: "PreToolUse",
|
|
1790
|
-
additionalContext: [
|
|
1791
|
-
"Lore-format git commit enforcement triggered.",
|
|
1792
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
1793
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
1794
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
1795
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
1796
|
-
].join("\n"),
|
|
1797
1952
|
},
|
|
1798
1953
|
systemMessage: [
|
|
1799
1954
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -1803,6 +1958,9 @@ esac
|
|
|
1803
1958
|
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
1804
1959
|
].join("\n"),
|
|
1805
1960
|
});
|
|
1961
|
+
const hookSpecificOutput = result.outputJson
|
|
1962
|
+
.hookSpecificOutput ?? {};
|
|
1963
|
+
assert.equal("additionalContext" in hookSpecificOutput, false);
|
|
1806
1964
|
}
|
|
1807
1965
|
finally {
|
|
1808
1966
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -1875,13 +2033,6 @@ esac
|
|
|
1875
2033
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
1876
2034
|
hookSpecificOutput: {
|
|
1877
2035
|
hookEventName: "PreToolUse",
|
|
1878
|
-
additionalContext: [
|
|
1879
|
-
"Lore-format git commit enforcement triggered.",
|
|
1880
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
1881
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
1882
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
1883
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
1884
|
-
].join("\n"),
|
|
1885
2036
|
},
|
|
1886
2037
|
systemMessage: [
|
|
1887
2038
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -1912,13 +2063,6 @@ esac
|
|
|
1912
2063
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
1913
2064
|
hookSpecificOutput: {
|
|
1914
2065
|
hookEventName: "PreToolUse",
|
|
1915
|
-
additionalContext: [
|
|
1916
|
-
"Lore-format git commit enforcement triggered.",
|
|
1917
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
1918
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
1919
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
1920
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
1921
|
-
].join("\n"),
|
|
1922
2066
|
},
|
|
1923
2067
|
systemMessage: [
|
|
1924
2068
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -1949,13 +2093,6 @@ esac
|
|
|
1949
2093
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
1950
2094
|
hookSpecificOutput: {
|
|
1951
2095
|
hookEventName: "PreToolUse",
|
|
1952
|
-
additionalContext: [
|
|
1953
|
-
"Lore-format git commit enforcement triggered.",
|
|
1954
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
1955
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
1956
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
1957
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
1958
|
-
].join("\n"),
|
|
1959
2096
|
},
|
|
1960
2097
|
systemMessage: [
|
|
1961
2098
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -1986,13 +2123,6 @@ esac
|
|
|
1986
2123
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
1987
2124
|
hookSpecificOutput: {
|
|
1988
2125
|
hookEventName: "PreToolUse",
|
|
1989
|
-
additionalContext: [
|
|
1990
|
-
"Lore-format git commit enforcement triggered.",
|
|
1991
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
1992
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
1993
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
1994
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
1995
|
-
].join("\n"),
|
|
1996
2126
|
},
|
|
1997
2127
|
systemMessage: [
|
|
1998
2128
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2023,13 +2153,6 @@ esac
|
|
|
2023
2153
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2024
2154
|
hookSpecificOutput: {
|
|
2025
2155
|
hookEventName: "PreToolUse",
|
|
2026
|
-
additionalContext: [
|
|
2027
|
-
"Lore-format git commit enforcement triggered.",
|
|
2028
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2029
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2030
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2031
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2032
|
-
].join("\n"),
|
|
2033
2156
|
},
|
|
2034
2157
|
systemMessage: [
|
|
2035
2158
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2060,13 +2183,6 @@ esac
|
|
|
2060
2183
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2061
2184
|
hookSpecificOutput: {
|
|
2062
2185
|
hookEventName: "PreToolUse",
|
|
2063
|
-
additionalContext: [
|
|
2064
|
-
"Lore-format git commit enforcement triggered.",
|
|
2065
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2066
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2067
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2068
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2069
|
-
].join("\n"),
|
|
2070
2186
|
},
|
|
2071
2187
|
systemMessage: [
|
|
2072
2188
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2097,13 +2213,6 @@ esac
|
|
|
2097
2213
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2098
2214
|
hookSpecificOutput: {
|
|
2099
2215
|
hookEventName: "PreToolUse",
|
|
2100
|
-
additionalContext: [
|
|
2101
|
-
"Lore-format git commit enforcement triggered.",
|
|
2102
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2103
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2104
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2105
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2106
|
-
].join("\n"),
|
|
2107
2216
|
},
|
|
2108
2217
|
systemMessage: [
|
|
2109
2218
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2134,13 +2243,6 @@ esac
|
|
|
2134
2243
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2135
2244
|
hookSpecificOutput: {
|
|
2136
2245
|
hookEventName: "PreToolUse",
|
|
2137
|
-
additionalContext: [
|
|
2138
|
-
"Lore-format git commit enforcement triggered.",
|
|
2139
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2140
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2141
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2142
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2143
|
-
].join("\n"),
|
|
2144
2246
|
},
|
|
2145
2247
|
systemMessage: [
|
|
2146
2248
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2171,13 +2273,6 @@ esac
|
|
|
2171
2273
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2172
2274
|
hookSpecificOutput: {
|
|
2173
2275
|
hookEventName: "PreToolUse",
|
|
2174
|
-
additionalContext: [
|
|
2175
|
-
"Lore-format git commit enforcement triggered.",
|
|
2176
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2177
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2178
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2179
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2180
|
-
].join("\n"),
|
|
2181
2276
|
},
|
|
2182
2277
|
systemMessage: [
|
|
2183
2278
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2208,10 +2303,6 @@ esac
|
|
|
2208
2303
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2209
2304
|
hookSpecificOutput: {
|
|
2210
2305
|
hookEventName: "PreToolUse",
|
|
2211
|
-
additionalContext: [
|
|
2212
|
-
"Lore-format git commit enforcement triggered.",
|
|
2213
|
-
"- Use inline `git commit -m ...` paragraphs for Lore-format commits in this path; file/editor/reuse/fixup message sources are not inspectable safely from pre-tool-use enforcement.",
|
|
2214
|
-
].join("\n"),
|
|
2215
2306
|
},
|
|
2216
2307
|
systemMessage: [
|
|
2217
2308
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2247,10 +2338,6 @@ esac
|
|
|
2247
2338
|
reason: "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2248
2339
|
hookSpecificOutput: {
|
|
2249
2340
|
hookEventName: "PreToolUse",
|
|
2250
|
-
additionalContext: [
|
|
2251
|
-
"Lore-format git commit enforcement triggered.",
|
|
2252
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2253
|
-
].join("\n"),
|
|
2254
2341
|
},
|
|
2255
2342
|
systemMessage: [
|
|
2256
2343
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2489,6 +2576,24 @@ esac
|
|
|
2489
2576
|
await rm(cwd, { recursive: true, force: true });
|
|
2490
2577
|
}
|
|
2491
2578
|
});
|
|
2579
|
+
it("stays silent when Bash stdout only contains failure-like source text", async () => {
|
|
2580
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-failure-source-text-"));
|
|
2581
|
+
try {
|
|
2582
|
+
const result = await dispatchCodexNativeHook({
|
|
2583
|
+
hook_event_name: "PostToolUse",
|
|
2584
|
+
cwd,
|
|
2585
|
+
tool_name: "Bash",
|
|
2586
|
+
tool_use_id: "tool-source-text",
|
|
2587
|
+
tool_input: { command: "sed -n '1,40p' hook-source.ts" },
|
|
2588
|
+
tool_response: "const text = 'bash: foo: command not found';\nconst detail = 'permission denied';",
|
|
2589
|
+
}, { cwd });
|
|
2590
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
2591
|
+
assert.equal(result.outputJson, null);
|
|
2592
|
+
}
|
|
2593
|
+
finally {
|
|
2594
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2595
|
+
}
|
|
2596
|
+
});
|
|
2492
2597
|
it("stays silent for rc-zero build logs that mention missing grep paths", async () => {
|
|
2493
2598
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-build-log-"));
|
|
2494
2599
|
try {
|
|
@@ -2511,6 +2616,28 @@ esac
|
|
|
2511
2616
|
await rm(cwd, { recursive: true, force: true });
|
|
2512
2617
|
}
|
|
2513
2618
|
});
|
|
2619
|
+
it("does not treat Bash output containing MCP transport text as MCP transport death", async () => {
|
|
2620
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-mcp-source-text-"));
|
|
2621
|
+
try {
|
|
2622
|
+
const result = await dispatchCodexNativeHook({
|
|
2623
|
+
hook_event_name: "PostToolUse",
|
|
2624
|
+
cwd,
|
|
2625
|
+
tool_name: "Bash",
|
|
2626
|
+
tool_use_id: "tool-mcp-source-text",
|
|
2627
|
+
tool_input: { command: "sed -n '580,620p' codex-native-pre-post.ts" },
|
|
2628
|
+
tool_response: JSON.stringify({
|
|
2629
|
+
exit_code: 0,
|
|
2630
|
+
stdout: "reason: 'MCP transport closed before response over stdio pipe closed'",
|
|
2631
|
+
stderr: "",
|
|
2632
|
+
}),
|
|
2633
|
+
}, { cwd });
|
|
2634
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
2635
|
+
assert.equal(result.outputJson, null);
|
|
2636
|
+
}
|
|
2637
|
+
finally {
|
|
2638
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2639
|
+
}
|
|
2640
|
+
});
|
|
2514
2641
|
it("stays silent when successful output includes prior hook context text", async () => {
|
|
2515
2642
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-recursive-context-"));
|
|
2516
2643
|
try {
|
|
@@ -2533,6 +2660,46 @@ esac
|
|
|
2533
2660
|
await rm(cwd, { recursive: true, force: true });
|
|
2534
2661
|
}
|
|
2535
2662
|
});
|
|
2663
|
+
it("stays silent when successful Bash output quotes MCP transport warnings", async () => {
|
|
2664
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-bash-mcp-quote-"));
|
|
2665
|
+
try {
|
|
2666
|
+
const result = await dispatchCodexNativeHook({
|
|
2667
|
+
hook_event_name: "PostToolUse",
|
|
2668
|
+
cwd,
|
|
2669
|
+
tool_name: "Bash",
|
|
2670
|
+
tool_use_id: "tool-bash-mcp-quote",
|
|
2671
|
+
tool_input: { command: "cat diagnostic-log.txt" },
|
|
2672
|
+
tool_response: JSON.stringify({
|
|
2673
|
+
exit_code: 0,
|
|
2674
|
+
stdout: "diagnostic log quoted: MCP transport closed; stdio pipe closed before response",
|
|
2675
|
+
stderr: "",
|
|
2676
|
+
}),
|
|
2677
|
+
}, { cwd });
|
|
2678
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
2679
|
+
assert.equal(result.outputJson, null);
|
|
2680
|
+
}
|
|
2681
|
+
finally {
|
|
2682
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2683
|
+
}
|
|
2684
|
+
});
|
|
2685
|
+
it("stays silent when Bash hard-failure text has no parsed exit code", async () => {
|
|
2686
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-bash-unparsed-failure-"));
|
|
2687
|
+
try {
|
|
2688
|
+
const result = await dispatchCodexNativeHook({
|
|
2689
|
+
hook_event_name: "PostToolUse",
|
|
2690
|
+
cwd,
|
|
2691
|
+
tool_name: "Bash",
|
|
2692
|
+
tool_use_id: "tool-bash-unparsed-failure",
|
|
2693
|
+
tool_input: { command: "cat captured-output.txt" },
|
|
2694
|
+
tool_response: "captured transcript says: bash: foo: command not found",
|
|
2695
|
+
}, { cwd });
|
|
2696
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
2697
|
+
assert.equal(result.outputJson, null);
|
|
2698
|
+
}
|
|
2699
|
+
finally {
|
|
2700
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2701
|
+
}
|
|
2702
|
+
});
|
|
2536
2703
|
it("returns PostToolUse MCP transport fallback guidance for clear MCP transport death", async () => {
|
|
2537
2704
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-mcp-transport-"));
|
|
2538
2705
|
try {
|
|
@@ -2979,7 +3146,17 @@ esac
|
|
|
2979
3146
|
const prevLeaderCwd = process.env.OMX_TEAM_LEADER_CWD;
|
|
2980
3147
|
try {
|
|
2981
3148
|
await initTeamState("worker-stop-team", "worker stop fallback", "executor", 1, cwd, undefined, { ...process.env, OMX_SESSION_ID: "sess-stop-team-worker" });
|
|
3149
|
+
const workerCwd = join(cwd, ".omx", "team", "worker-stop-team", "worktrees", "worker-1");
|
|
2982
3150
|
const workerDir = join(cwd, ".omx", "state", "team", "worker-stop-team", "workers", "worker-1");
|
|
3151
|
+
await mkdir(workerCwd, { recursive: true });
|
|
3152
|
+
await writeJson(join(workerDir, "identity.json"), {
|
|
3153
|
+
name: "worker-1",
|
|
3154
|
+
index: 1,
|
|
3155
|
+
role: "executor",
|
|
3156
|
+
assigned_tasks: ["1"],
|
|
3157
|
+
worktree_path: workerCwd,
|
|
3158
|
+
team_state_root: join(cwd, ".omx", "state"),
|
|
3159
|
+
});
|
|
2983
3160
|
await writeJson(join(workerDir, "status.json"), {
|
|
2984
3161
|
state: "idle",
|
|
2985
3162
|
current_task_id: "1",
|
|
@@ -2998,9 +3175,9 @@ esac
|
|
|
2998
3175
|
process.env.OMX_TEAM_LEADER_CWD = cwd;
|
|
2999
3176
|
const result = await dispatchCodexNativeHook({
|
|
3000
3177
|
hook_event_name: "Stop",
|
|
3001
|
-
cwd:
|
|
3178
|
+
cwd: workerCwd,
|
|
3002
3179
|
session_id: "sess-stop-team-worker",
|
|
3003
|
-
}, { cwd:
|
|
3180
|
+
}, { cwd: workerCwd });
|
|
3004
3181
|
assert.deepEqual(result.outputJson, {
|
|
3005
3182
|
decision: "block",
|
|
3006
3183
|
reason: "OMX team worker worker-1 is still assigned non-terminal task 1 (in_progress); continue the current assigned task or report a concrete blocker before stopping.",
|
|
@@ -3031,6 +3208,16 @@ esac
|
|
|
3031
3208
|
const stateDir = join(cwd, ".omx", "state");
|
|
3032
3209
|
const workerDir = join(stateDir, "team", "worker-repeat-team", "workers", "worker-1");
|
|
3033
3210
|
const taskPath = join(stateDir, "team", "worker-repeat-team", "tasks", "task-1.json");
|
|
3211
|
+
const workerCwd = join(cwd, ".omx", "team", "worker-repeat-team", "worktrees", "worker-1");
|
|
3212
|
+
await mkdir(workerCwd, { recursive: true });
|
|
3213
|
+
await writeJson(join(workerDir, "identity.json"), {
|
|
3214
|
+
name: "worker-1",
|
|
3215
|
+
index: 1,
|
|
3216
|
+
role: "executor",
|
|
3217
|
+
assigned_tasks: ["1"],
|
|
3218
|
+
worktree_path: workerCwd,
|
|
3219
|
+
team_state_root: stateDir,
|
|
3220
|
+
});
|
|
3034
3221
|
await writeJson(join(workerDir, "status.json"), {
|
|
3035
3222
|
state: "idle",
|
|
3036
3223
|
current_task_id: "1",
|
|
@@ -3047,7 +3234,6 @@ esac
|
|
|
3047
3234
|
process.env.OMX_TEAM_WORKER = "worker-repeat-team/worker-1";
|
|
3048
3235
|
process.env.OMX_TEAM_STATE_ROOT = stateDir;
|
|
3049
3236
|
process.env.OMX_TEAM_LEADER_CWD = cwd;
|
|
3050
|
-
const workerCwd = join(cwd, ".omx", "team", "worker-repeat-team", "worktrees", "worker-1");
|
|
3051
3237
|
const basePayload = {
|
|
3052
3238
|
hook_event_name: "Stop",
|
|
3053
3239
|
cwd: workerCwd,
|
|
@@ -3207,6 +3393,38 @@ esac
|
|
|
3207
3393
|
await rm(cwd, { recursive: true, force: true });
|
|
3208
3394
|
}
|
|
3209
3395
|
});
|
|
3396
|
+
it("honors terminal team run-state before later canonical-team Stop fallback", async () => {
|
|
3397
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-terminal-run-state-canonical-"));
|
|
3398
|
+
try {
|
|
3399
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
3400
|
+
const sessionId = "sess-stop-team-terminal-run-state";
|
|
3401
|
+
await initTeamState("terminal-run-state-team", "terminal team stop canonical fallback regression", "executor", 1, cwd, undefined, { ...process.env, OMX_SESSION_ID: sessionId });
|
|
3402
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
3403
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId, cwd });
|
|
3404
|
+
await writeJson(join(stateDir, "sessions", sessionId, "run-state.json"), {
|
|
3405
|
+
version: 1,
|
|
3406
|
+
mode: "team",
|
|
3407
|
+
active: false,
|
|
3408
|
+
outcome: "finish",
|
|
3409
|
+
lifecycle_outcome: "finished",
|
|
3410
|
+
current_phase: "complete",
|
|
3411
|
+
completed_at: "2026-04-27T12:00:00.000Z",
|
|
3412
|
+
updated_at: "2026-04-27T12:00:00.000Z",
|
|
3413
|
+
});
|
|
3414
|
+
const result = await dispatchCodexNativeHook({
|
|
3415
|
+
hook_event_name: "Stop",
|
|
3416
|
+
cwd,
|
|
3417
|
+
session_id: sessionId,
|
|
3418
|
+
thread_id: "thread-stop-team-terminal-run-state",
|
|
3419
|
+
turn_id: "turn-stop-team-terminal-run-state-1",
|
|
3420
|
+
}, { cwd });
|
|
3421
|
+
assert.equal(result.omxEventName, "stop");
|
|
3422
|
+
assert.equal(result.outputJson, null);
|
|
3423
|
+
}
|
|
3424
|
+
finally {
|
|
3425
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3426
|
+
}
|
|
3427
|
+
});
|
|
3210
3428
|
it("re-fires canonical-team Stop output for a later fresh Stop reply when coarse mode state is missing", async () => {
|
|
3211
3429
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-canonical-refire-"));
|
|
3212
3430
|
try {
|
|
@@ -3679,7 +3897,7 @@ esac
|
|
|
3679
3897
|
decision: "block",
|
|
3680
3898
|
reason: "Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
3681
3899
|
stopReason: "deep_interview_question_required",
|
|
3682
|
-
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
3900
|
+
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping; read the returned answers[] JSON before continuing.",
|
|
3683
3901
|
});
|
|
3684
3902
|
}
|
|
3685
3903
|
finally {
|
|
@@ -3728,7 +3946,7 @@ esac
|
|
|
3728
3946
|
decision: "block",
|
|
3729
3947
|
reason: "Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
3730
3948
|
stopReason: "deep_interview_question_required",
|
|
3731
|
-
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
3949
|
+
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping; read the returned answers[] JSON before continuing.",
|
|
3732
3950
|
});
|
|
3733
3951
|
}
|
|
3734
3952
|
finally {
|
|
@@ -3841,7 +4059,7 @@ esac
|
|
|
3841
4059
|
decision: "block",
|
|
3842
4060
|
reason: "Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
3843
4061
|
stopReason: "deep_interview_question_required",
|
|
3844
|
-
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
4062
|
+
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping; read the returned answers[] JSON before continuing.",
|
|
3845
4063
|
};
|
|
3846
4064
|
const first = await dispatchCodexNativeHook(payload, { cwd });
|
|
3847
4065
|
const replay = await dispatchCodexNativeHook({ ...payload, stop_hook_active: true }, { cwd });
|
|
@@ -3968,7 +4186,7 @@ esac
|
|
|
3968
4186
|
decision: "block",
|
|
3969
4187
|
reason: "Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
3970
4188
|
stopReason: "deep_interview_question_required",
|
|
3971
|
-
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
4189
|
+
systemMessage: "OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping; read the returned answers[] JSON before continuing.",
|
|
3972
4190
|
});
|
|
3973
4191
|
}
|
|
3974
4192
|
finally {
|
|
@@ -4114,9 +4332,9 @@ esac
|
|
|
4114
4332
|
assert.equal(result.omxEventName, "stop");
|
|
4115
4333
|
assert.deepEqual(result.outputJson, {
|
|
4116
4334
|
decision: "block",
|
|
4117
|
-
reason: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
4335
|
+
reason: "OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4118
4336
|
stopReason: "ralph_executing",
|
|
4119
|
-
systemMessage: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
4337
|
+
systemMessage: "OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4120
4338
|
});
|
|
4121
4339
|
}
|
|
4122
4340
|
finally {
|
|
@@ -4142,9 +4360,9 @@ esac
|
|
|
4142
4360
|
assert.equal(result.omxEventName, "stop");
|
|
4143
4361
|
assert.deepEqual(result.outputJson, {
|
|
4144
4362
|
decision: "block",
|
|
4145
|
-
reason: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
4363
|
+
reason: "OMX Ralph is still active (phase: executing; state: .omx/state/sessions/sess-live-ralph/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4146
4364
|
stopReason: "ralph_executing",
|
|
4147
|
-
systemMessage: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
4365
|
+
systemMessage: "OMX Ralph is still active (phase: executing; state: .omx/state/sessions/sess-live-ralph/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4148
4366
|
});
|
|
4149
4367
|
}
|
|
4150
4368
|
finally {
|
|
@@ -4219,6 +4437,74 @@ esac
|
|
|
4219
4437
|
await rm(cwd, { recursive: true, force: true });
|
|
4220
4438
|
}
|
|
4221
4439
|
});
|
|
4440
|
+
it("does not hard-block Stop on stale session-scoped Ralph starting state after visible active modes are cleared", async () => {
|
|
4441
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-cleared-stale-ralph-"));
|
|
4442
|
+
try {
|
|
4443
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
4444
|
+
const sessionId = "sess-cleared-ralph";
|
|
4445
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
4446
|
+
await writeJson(join(stateDir, "sessions", sessionId, "ralph-state.json"), {
|
|
4447
|
+
active: true,
|
|
4448
|
+
mode: "ralph",
|
|
4449
|
+
current_phase: "starting",
|
|
4450
|
+
session_id: sessionId,
|
|
4451
|
+
});
|
|
4452
|
+
await writeJson(join(stateDir, "skill-active-state.json"), {
|
|
4453
|
+
active: false,
|
|
4454
|
+
skill: "ralph",
|
|
4455
|
+
active_skills: [],
|
|
4456
|
+
});
|
|
4457
|
+
const listActive = await executeStateOperation("state_list_active", {
|
|
4458
|
+
workingDirectory: cwd,
|
|
4459
|
+
});
|
|
4460
|
+
assert.deepEqual(listActive.payload, { active_modes: [] });
|
|
4461
|
+
const result = await dispatchCodexNativeHook({
|
|
4462
|
+
hook_event_name: "Stop",
|
|
4463
|
+
cwd,
|
|
4464
|
+
session_id: sessionId,
|
|
4465
|
+
}, { cwd });
|
|
4466
|
+
assert.equal(result.omxEventName, "stop");
|
|
4467
|
+
assert.equal(result.outputJson, null);
|
|
4468
|
+
}
|
|
4469
|
+
finally {
|
|
4470
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4471
|
+
}
|
|
4472
|
+
});
|
|
4473
|
+
it("blocks Stop on visible active session-scoped Ralph starting state and reports its path", async () => {
|
|
4474
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-visible-starting-ralph-"));
|
|
4475
|
+
try {
|
|
4476
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
4477
|
+
const sessionId = "sess-visible-ralph";
|
|
4478
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
4479
|
+
await writeJson(join(stateDir, "sessions", sessionId, "ralph-state.json"), {
|
|
4480
|
+
active: true,
|
|
4481
|
+
mode: "ralph",
|
|
4482
|
+
current_phase: "starting",
|
|
4483
|
+
session_id: sessionId,
|
|
4484
|
+
});
|
|
4485
|
+
await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
|
|
4486
|
+
active: true,
|
|
4487
|
+
skill: "ralph",
|
|
4488
|
+
phase: "starting",
|
|
4489
|
+
active_skills: [{ skill: "ralph", phase: "starting", active: true, session_id: sessionId }],
|
|
4490
|
+
});
|
|
4491
|
+
const result = await dispatchCodexNativeHook({
|
|
4492
|
+
hook_event_name: "Stop",
|
|
4493
|
+
cwd,
|
|
4494
|
+
session_id: sessionId,
|
|
4495
|
+
}, { cwd });
|
|
4496
|
+
assert.equal(result.omxEventName, "stop");
|
|
4497
|
+
assert.deepEqual(result.outputJson, {
|
|
4498
|
+
decision: "block",
|
|
4499
|
+
reason: "OMX Ralph is still active (phase: starting; state: .omx/state/sessions/sess-visible-ralph/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4500
|
+
stopReason: "ralph_starting",
|
|
4501
|
+
systemMessage: "OMX Ralph is still active (phase: starting; state: .omx/state/sessions/sess-visible-ralph/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4504
|
+
finally {
|
|
4505
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4506
|
+
}
|
|
4507
|
+
});
|
|
4222
4508
|
it("does not block Stop from another session-scoped Ralph state when an explicit session_id has no active Ralph state", async () => {
|
|
4223
4509
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-explicit-session-ralph-"));
|
|
4224
4510
|
try {
|
|
@@ -4241,6 +4527,41 @@ esac
|
|
|
4241
4527
|
await rm(cwd, { recursive: true, force: true });
|
|
4242
4528
|
}
|
|
4243
4529
|
});
|
|
4530
|
+
it("prefers canonical run-state terminal lifecycle before stale session Ralph state during Stop", async () => {
|
|
4531
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-canonical-run-state-ralph-"));
|
|
4532
|
+
try {
|
|
4533
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
4534
|
+
const sessionId = "sess-canonical-run-state-ralph";
|
|
4535
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
4536
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId, cwd });
|
|
4537
|
+
await writeJson(join(stateDir, "sessions", sessionId, "run-state.json"), {
|
|
4538
|
+
version: 1,
|
|
4539
|
+
mode: "ralph",
|
|
4540
|
+
active: false,
|
|
4541
|
+
outcome: "finish",
|
|
4542
|
+
lifecycle_outcome: "finished",
|
|
4543
|
+
current_phase: "complete",
|
|
4544
|
+
completed_at: "2026-04-27T12:00:00.000Z",
|
|
4545
|
+
updated_at: "2026-04-27T12:00:00.000Z",
|
|
4546
|
+
});
|
|
4547
|
+
await writeJson(join(stateDir, "sessions", sessionId, "ralph-state.json"), {
|
|
4548
|
+
active: true,
|
|
4549
|
+
mode: "ralph",
|
|
4550
|
+
current_phase: "verifying",
|
|
4551
|
+
session_id: sessionId,
|
|
4552
|
+
});
|
|
4553
|
+
const result = await dispatchCodexNativeHook({
|
|
4554
|
+
hook_event_name: "Stop",
|
|
4555
|
+
cwd,
|
|
4556
|
+
session_id: sessionId,
|
|
4557
|
+
}, { cwd });
|
|
4558
|
+
assert.equal(result.omxEventName, "stop");
|
|
4559
|
+
assert.equal(result.outputJson, null);
|
|
4560
|
+
}
|
|
4561
|
+
finally {
|
|
4562
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4563
|
+
}
|
|
4564
|
+
});
|
|
4244
4565
|
it("does not block Stop from root Ralph fallback when the current session has no scoped Ralph state", async () => {
|
|
4245
4566
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-root-fallback-ralph-"));
|
|
4246
4567
|
try {
|
|
@@ -4334,9 +4655,9 @@ esac
|
|
|
4334
4655
|
};
|
|
4335
4656
|
const expected = {
|
|
4336
4657
|
decision: "block",
|
|
4337
|
-
reason: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
4658
|
+
reason: "OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4338
4659
|
stopReason: "ralph_executing",
|
|
4339
|
-
systemMessage: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
4660
|
+
systemMessage: "OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
4340
4661
|
};
|
|
4341
4662
|
const first = await dispatchCodexNativeHook(payload, { cwd });
|
|
4342
4663
|
const replay = await dispatchCodexNativeHook({
|