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";
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from "../codex-native-hook.js";
|
|
23
23
|
import { writeSessionStart } from "../../hooks/session.js";
|
|
24
24
|
import { resetTriageConfigCache } from "../../hooks/triage-config.js";
|
|
25
|
+
import { executeStateOperation } from "../../state/operations.js";
|
|
25
26
|
|
|
26
27
|
function nativeHookScriptPath(): string {
|
|
27
28
|
return join(process.cwd(), "dist", "scripts", "codex-native-hook.js");
|
|
@@ -264,6 +265,49 @@ describe("codex native hook dispatch", () => {
|
|
|
264
265
|
);
|
|
265
266
|
});
|
|
266
267
|
|
|
268
|
+
it("emits parseable no-op JSON stdout for inactive Stop CLI runs", async () => {
|
|
269
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-cli-stop-noop-json-"));
|
|
270
|
+
try {
|
|
271
|
+
const stdout = runNativeHookCli({
|
|
272
|
+
hook_event_name: "Stop",
|
|
273
|
+
cwd,
|
|
274
|
+
session_id: "sess-cli-stop-noop-json",
|
|
275
|
+
thread_id: "thread-cli-stop-noop-json",
|
|
276
|
+
turn_id: "turn-cli-stop-noop-json",
|
|
277
|
+
}, { cwd });
|
|
278
|
+
const output = parseSingleJsonStdout(stdout);
|
|
279
|
+
|
|
280
|
+
assert.deepEqual(output, {});
|
|
281
|
+
} finally {
|
|
282
|
+
await rm(cwd, { recursive: true, force: true });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it("does not crash Stop hook dispatch when the exec follow-up queue is malformed", async () => {
|
|
287
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-stop-exec-followup-corrupt-"));
|
|
288
|
+
try {
|
|
289
|
+
const session = await writeSessionStart(cwd, "sess-exec-followup-corrupt");
|
|
290
|
+
const queuePath = join(cwd, ".omx", "state", "sessions", session.session_id, "exec-followups.json");
|
|
291
|
+
await mkdir(dirname(queuePath), { recursive: true });
|
|
292
|
+
await writeFile(queuePath, '{"version":1,"records":[', "utf-8");
|
|
293
|
+
|
|
294
|
+
const result = await dispatchCodexNativeHook({
|
|
295
|
+
hook_event_name: "Stop",
|
|
296
|
+
cwd,
|
|
297
|
+
session_id: session.session_id,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
assert.equal(result.hookEventName, "Stop");
|
|
301
|
+
assert.equal(result.outputJson, null);
|
|
302
|
+
const queueDirEntries = await readdir(dirname(queuePath));
|
|
303
|
+
assert.ok(queueDirEntries.some((entry) => entry.startsWith("exec-followups.json.corrupt-")));
|
|
304
|
+
const auditPath = join(cwd, ".omx", "logs", `exec-followups-${new Date().toISOString().slice(0, 10)}.jsonl`);
|
|
305
|
+
assert.match(await readFile(auditPath, "utf-8"), /exec_followup_queue_corrupt_recovered/);
|
|
306
|
+
} finally {
|
|
307
|
+
await rm(cwd, { recursive: true, force: true });
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
267
311
|
it("emits exactly one parseable JSON object for active Stop CLI continuation", async () => {
|
|
268
312
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-cli-stop-json-"));
|
|
269
313
|
try {
|
|
@@ -440,6 +484,164 @@ describe("codex native hook dispatch", () => {
|
|
|
440
484
|
}
|
|
441
485
|
});
|
|
442
486
|
|
|
487
|
+
it("keeps subagent SessionStart from replacing the canonical leader session", async () => {
|
|
488
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-subagent-session-start-"));
|
|
489
|
+
try {
|
|
490
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
491
|
+
const canonicalSessionId = "omx-leader-session";
|
|
492
|
+
const leaderNativeSessionId = "codex-leader-thread";
|
|
493
|
+
const childNativeSessionId = "codex-child-thread";
|
|
494
|
+
await mkdir(join(stateDir, "sessions", canonicalSessionId), { recursive: true });
|
|
495
|
+
await writeSessionStart(cwd, canonicalSessionId, {
|
|
496
|
+
nativeSessionId: leaderNativeSessionId,
|
|
497
|
+
});
|
|
498
|
+
await writeJson(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), {
|
|
499
|
+
active: true,
|
|
500
|
+
mode: "ralph",
|
|
501
|
+
current_phase: "executing",
|
|
502
|
+
iteration: 1,
|
|
503
|
+
max_iterations: 5,
|
|
504
|
+
});
|
|
505
|
+
const transcriptPath = join(cwd, "subagent-rollout.jsonl");
|
|
506
|
+
await writeFile(
|
|
507
|
+
transcriptPath,
|
|
508
|
+
`${JSON.stringify({
|
|
509
|
+
type: "session_meta",
|
|
510
|
+
payload: {
|
|
511
|
+
id: childNativeSessionId,
|
|
512
|
+
source: {
|
|
513
|
+
subagent: {
|
|
514
|
+
thread_spawn: {
|
|
515
|
+
parent_thread_id: leaderNativeSessionId,
|
|
516
|
+
depth: 1,
|
|
517
|
+
agent_nickname: "Hegel",
|
|
518
|
+
agent_role: "critic",
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
agent_nickname: "Hegel",
|
|
523
|
+
agent_role: "critic",
|
|
524
|
+
},
|
|
525
|
+
})}\n`,
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
const result = await dispatchCodexNativeHook(
|
|
529
|
+
{
|
|
530
|
+
hook_event_name: "SessionStart",
|
|
531
|
+
cwd,
|
|
532
|
+
session_id: childNativeSessionId,
|
|
533
|
+
transcript_path: transcriptPath,
|
|
534
|
+
},
|
|
535
|
+
{ cwd, sessionOwnerPid: process.pid },
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
const sessionState = JSON.parse(
|
|
539
|
+
await readFile(join(stateDir, "session.json"), "utf-8"),
|
|
540
|
+
) as { session_id?: string; native_session_id?: string };
|
|
541
|
+
assert.equal(sessionState.session_id, canonicalSessionId);
|
|
542
|
+
assert.equal(sessionState.native_session_id, leaderNativeSessionId);
|
|
543
|
+
assert.equal(
|
|
544
|
+
existsSync(join(stateDir, "sessions", childNativeSessionId, "ralph-state.json")),
|
|
545
|
+
false,
|
|
546
|
+
);
|
|
547
|
+
assert.ok(result.outputJson);
|
|
548
|
+
|
|
549
|
+
const leaderRalph = JSON.parse(
|
|
550
|
+
await readFile(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), "utf-8"),
|
|
551
|
+
) as { active?: boolean; current_phase?: string };
|
|
552
|
+
assert.equal(leaderRalph.active, true);
|
|
553
|
+
assert.equal(leaderRalph.current_phase, "executing");
|
|
554
|
+
|
|
555
|
+
const tracking = JSON.parse(
|
|
556
|
+
await readFile(join(stateDir, "subagent-tracking.json"), "utf-8"),
|
|
557
|
+
) as {
|
|
558
|
+
sessions?: Record<string, {
|
|
559
|
+
leader_thread_id?: string;
|
|
560
|
+
threads?: Record<string, { kind?: string; mode?: string }>;
|
|
561
|
+
}>;
|
|
562
|
+
};
|
|
563
|
+
assert.equal(tracking.sessions?.[canonicalSessionId]?.leader_thread_id, leaderNativeSessionId);
|
|
564
|
+
assert.equal(tracking.sessions?.[canonicalSessionId]?.threads?.[childNativeSessionId]?.kind, "subagent");
|
|
565
|
+
assert.equal(tracking.sessions?.[canonicalSessionId]?.threads?.[childNativeSessionId]?.mode, "critic");
|
|
566
|
+
assert.equal(tracking.sessions?.[leaderNativeSessionId]?.leader_thread_id, leaderNativeSessionId);
|
|
567
|
+
assert.equal(tracking.sessions?.[leaderNativeSessionId]?.threads?.[childNativeSessionId]?.kind, "subagent");
|
|
568
|
+
assert.equal(tracking.sessions?.[leaderNativeSessionId]?.threads?.[childNativeSessionId]?.mode, "critic");
|
|
569
|
+
} finally {
|
|
570
|
+
await rm(cwd, { recursive: true, force: true });
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it("does not attach a subagent SessionStart to an unrelated canonical leader", async () => {
|
|
575
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-subagent-session-start-mismatch-"));
|
|
576
|
+
try {
|
|
577
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
578
|
+
const canonicalSessionId = "omx-leader-session-a";
|
|
579
|
+
const leaderNativeSessionId = "codex-leader-thread-a";
|
|
580
|
+
const unrelatedParentNativeSessionId = "codex-leader-thread-b";
|
|
581
|
+
const childNativeSessionId = "codex-child-thread-b";
|
|
582
|
+
await mkdir(join(stateDir, "sessions", canonicalSessionId), { recursive: true });
|
|
583
|
+
await writeSessionStart(cwd, canonicalSessionId, {
|
|
584
|
+
nativeSessionId: leaderNativeSessionId,
|
|
585
|
+
});
|
|
586
|
+
await writeJson(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), {
|
|
587
|
+
active: true,
|
|
588
|
+
mode: "ralph",
|
|
589
|
+
current_phase: "executing",
|
|
590
|
+
iteration: 1,
|
|
591
|
+
max_iterations: 5,
|
|
592
|
+
});
|
|
593
|
+
const transcriptPath = join(cwd, "unrelated-subagent-rollout.jsonl");
|
|
594
|
+
await writeFile(
|
|
595
|
+
transcriptPath,
|
|
596
|
+
`${JSON.stringify({
|
|
597
|
+
type: "session_meta",
|
|
598
|
+
payload: {
|
|
599
|
+
id: childNativeSessionId,
|
|
600
|
+
source: {
|
|
601
|
+
subagent: {
|
|
602
|
+
thread_spawn: {
|
|
603
|
+
parent_thread_id: unrelatedParentNativeSessionId,
|
|
604
|
+
depth: 1,
|
|
605
|
+
agent_nickname: "Spinoza",
|
|
606
|
+
agent_role: "critic",
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
agent_nickname: "Spinoza",
|
|
611
|
+
agent_role: "critic",
|
|
612
|
+
},
|
|
613
|
+
})}\n`,
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
const result = await dispatchCodexNativeHook(
|
|
617
|
+
{
|
|
618
|
+
hook_event_name: "SessionStart",
|
|
619
|
+
cwd,
|
|
620
|
+
session_id: childNativeSessionId,
|
|
621
|
+
transcript_path: transcriptPath,
|
|
622
|
+
},
|
|
623
|
+
{ cwd, sessionOwnerPid: process.pid },
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
const sessionState = JSON.parse(
|
|
627
|
+
await readFile(join(stateDir, "session.json"), "utf-8"),
|
|
628
|
+
) as { session_id?: string; native_session_id?: string };
|
|
629
|
+
assert.equal(sessionState.session_id, canonicalSessionId);
|
|
630
|
+
assert.equal(sessionState.native_session_id, leaderNativeSessionId);
|
|
631
|
+
assert.equal(existsSync(join(stateDir, "subagent-tracking.json")), false);
|
|
632
|
+
assert.equal(existsSync(join(stateDir, "sessions", childNativeSessionId)), false);
|
|
633
|
+
assert.equal(result.outputJson, null);
|
|
634
|
+
|
|
635
|
+
const leaderRalph = JSON.parse(
|
|
636
|
+
await readFile(join(stateDir, "sessions", canonicalSessionId, "ralph-state.json"), "utf-8"),
|
|
637
|
+
) as { active?: boolean; current_phase?: string };
|
|
638
|
+
assert.equal(leaderRalph.active, true);
|
|
639
|
+
assert.equal(leaderRalph.current_phase, "executing");
|
|
640
|
+
} finally {
|
|
641
|
+
await rm(cwd, { recursive: true, force: true });
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
|
|
443
645
|
it("describes attached tmux runtime in SessionStart context when TMUX is present", async () => {
|
|
444
646
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-start-tmux-"));
|
|
445
647
|
process.env.TMUX = "/tmp/tmux-attached";
|
|
@@ -463,7 +665,7 @@ describe("codex native hook dispatch", () => {
|
|
|
463
665
|
assert.match(additionalContext, /\[Execution environment\]/);
|
|
464
666
|
assert.match(additionalContext, /attached tmux runtime/);
|
|
465
667
|
assert.match(additionalContext, /omx team, omx hud, and omx quest(?:ion) are directly usable in this session/);
|
|
466
|
-
assert.match(additionalContext, /visible renderer available from the current pane/);
|
|
668
|
+
assert.match(additionalContext, /visible temporary renderer available from the current pane; primary success JSON is answers\[\]/);
|
|
467
669
|
} finally {
|
|
468
670
|
await rm(cwd, { recursive: true, force: true });
|
|
469
671
|
}
|
|
@@ -2218,7 +2420,7 @@ esac
|
|
|
2218
2420
|
}
|
|
2219
2421
|
});
|
|
2220
2422
|
|
|
2221
|
-
it("blocks PreToolUse git commit when the inline message is not Lore-compliant", async () => {
|
|
2423
|
+
it("blocks PreToolUse git commit with supported response shape when the inline message is not Lore-compliant", async () => {
|
|
2222
2424
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-pretool-git-commit-invalid-"));
|
|
2223
2425
|
try {
|
|
2224
2426
|
const result = await dispatchCodexNativeHook(
|
|
@@ -2239,13 +2441,6 @@ esac
|
|
|
2239
2441
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2240
2442
|
hookSpecificOutput: {
|
|
2241
2443
|
hookEventName: "PreToolUse",
|
|
2242
|
-
additionalContext: [
|
|
2243
|
-
"Lore-format git commit enforcement triggered.",
|
|
2244
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2245
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2246
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2247
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2248
|
-
].join("\n"),
|
|
2249
2444
|
},
|
|
2250
2445
|
systemMessage: [
|
|
2251
2446
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2255,6 +2450,9 @@ esac
|
|
|
2255
2450
|
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2256
2451
|
].join("\n"),
|
|
2257
2452
|
});
|
|
2453
|
+
const hookSpecificOutput = (result.outputJson as { hookSpecificOutput?: Record<string, unknown> })
|
|
2454
|
+
.hookSpecificOutput ?? {};
|
|
2455
|
+
assert.equal("additionalContext" in hookSpecificOutput, false);
|
|
2258
2456
|
} finally {
|
|
2259
2457
|
await rm(cwd, { recursive: true, force: true });
|
|
2260
2458
|
}
|
|
@@ -2344,13 +2542,6 @@ esac
|
|
|
2344
2542
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2345
2543
|
hookSpecificOutput: {
|
|
2346
2544
|
hookEventName: "PreToolUse",
|
|
2347
|
-
additionalContext: [
|
|
2348
|
-
"Lore-format git commit enforcement triggered.",
|
|
2349
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2350
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2351
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2352
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2353
|
-
].join("\n"),
|
|
2354
2545
|
},
|
|
2355
2546
|
systemMessage: [
|
|
2356
2547
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2386,13 +2577,6 @@ esac
|
|
|
2386
2577
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2387
2578
|
hookSpecificOutput: {
|
|
2388
2579
|
hookEventName: "PreToolUse",
|
|
2389
|
-
additionalContext: [
|
|
2390
|
-
"Lore-format git commit enforcement triggered.",
|
|
2391
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2392
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2393
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2394
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2395
|
-
].join("\n"),
|
|
2396
2580
|
},
|
|
2397
2581
|
systemMessage: [
|
|
2398
2582
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2428,13 +2612,6 @@ esac
|
|
|
2428
2612
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2429
2613
|
hookSpecificOutput: {
|
|
2430
2614
|
hookEventName: "PreToolUse",
|
|
2431
|
-
additionalContext: [
|
|
2432
|
-
"Lore-format git commit enforcement triggered.",
|
|
2433
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2434
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2435
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2436
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2437
|
-
].join("\n"),
|
|
2438
2615
|
},
|
|
2439
2616
|
systemMessage: [
|
|
2440
2617
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2470,13 +2647,6 @@ esac
|
|
|
2470
2647
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2471
2648
|
hookSpecificOutput: {
|
|
2472
2649
|
hookEventName: "PreToolUse",
|
|
2473
|
-
additionalContext: [
|
|
2474
|
-
"Lore-format git commit enforcement triggered.",
|
|
2475
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2476
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2477
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2478
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2479
|
-
].join("\n"),
|
|
2480
2650
|
},
|
|
2481
2651
|
systemMessage: [
|
|
2482
2652
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2512,13 +2682,6 @@ esac
|
|
|
2512
2682
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2513
2683
|
hookSpecificOutput: {
|
|
2514
2684
|
hookEventName: "PreToolUse",
|
|
2515
|
-
additionalContext: [
|
|
2516
|
-
"Lore-format git commit enforcement triggered.",
|
|
2517
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2518
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2519
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2520
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2521
|
-
].join("\n"),
|
|
2522
2685
|
},
|
|
2523
2686
|
systemMessage: [
|
|
2524
2687
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2554,13 +2717,6 @@ esac
|
|
|
2554
2717
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2555
2718
|
hookSpecificOutput: {
|
|
2556
2719
|
hookEventName: "PreToolUse",
|
|
2557
|
-
additionalContext: [
|
|
2558
|
-
"Lore-format git commit enforcement triggered.",
|
|
2559
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2560
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2561
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2562
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2563
|
-
].join("\n"),
|
|
2564
2720
|
},
|
|
2565
2721
|
systemMessage: [
|
|
2566
2722
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2596,13 +2752,6 @@ esac
|
|
|
2596
2752
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2597
2753
|
hookSpecificOutput: {
|
|
2598
2754
|
hookEventName: "PreToolUse",
|
|
2599
|
-
additionalContext: [
|
|
2600
|
-
"Lore-format git commit enforcement triggered.",
|
|
2601
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2602
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2603
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2604
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2605
|
-
].join("\n"),
|
|
2606
2755
|
},
|
|
2607
2756
|
systemMessage: [
|
|
2608
2757
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2638,13 +2787,6 @@ esac
|
|
|
2638
2787
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2639
2788
|
hookSpecificOutput: {
|
|
2640
2789
|
hookEventName: "PreToolUse",
|
|
2641
|
-
additionalContext: [
|
|
2642
|
-
"Lore-format git commit enforcement triggered.",
|
|
2643
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2644
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2645
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2646
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2647
|
-
].join("\n"),
|
|
2648
2790
|
},
|
|
2649
2791
|
systemMessage: [
|
|
2650
2792
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2680,13 +2822,6 @@ esac
|
|
|
2680
2822
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2681
2823
|
hookSpecificOutput: {
|
|
2682
2824
|
hookEventName: "PreToolUse",
|
|
2683
|
-
additionalContext: [
|
|
2684
|
-
"Lore-format git commit enforcement triggered.",
|
|
2685
|
-
"- Add a blank line after the subject before the narrative body.",
|
|
2686
|
-
"- Add a narrative body paragraph explaining the decision context.",
|
|
2687
|
-
"- Add at least one Lore trailer such as `Constraint:`, `Confidence:`, or `Tested:`.",
|
|
2688
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2689
|
-
].join("\n"),
|
|
2690
2825
|
},
|
|
2691
2826
|
systemMessage: [
|
|
2692
2827
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2722,10 +2857,6 @@ esac
|
|
|
2722
2857
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2723
2858
|
hookSpecificOutput: {
|
|
2724
2859
|
hookEventName: "PreToolUse",
|
|
2725
|
-
additionalContext: [
|
|
2726
|
-
"Lore-format git commit enforcement triggered.",
|
|
2727
|
-
"- 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.",
|
|
2728
|
-
].join("\n"),
|
|
2729
2860
|
},
|
|
2730
2861
|
systemMessage: [
|
|
2731
2862
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -2766,10 +2897,6 @@ esac
|
|
|
2766
2897
|
"git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
|
|
2767
2898
|
hookSpecificOutput: {
|
|
2768
2899
|
hookEventName: "PreToolUse",
|
|
2769
|
-
additionalContext: [
|
|
2770
|
-
"Lore-format git commit enforcement triggered.",
|
|
2771
|
-
"- Add the required co-author trailer: `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
2772
|
-
].join("\n"),
|
|
2773
2900
|
},
|
|
2774
2901
|
systemMessage: [
|
|
2775
2902
|
"git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
|
|
@@ -3042,6 +3169,28 @@ esac
|
|
|
3042
3169
|
}
|
|
3043
3170
|
});
|
|
3044
3171
|
|
|
3172
|
+
it("stays silent when Bash stdout only contains failure-like source text", async () => {
|
|
3173
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-failure-source-text-"));
|
|
3174
|
+
try {
|
|
3175
|
+
const result = await dispatchCodexNativeHook(
|
|
3176
|
+
{
|
|
3177
|
+
hook_event_name: "PostToolUse",
|
|
3178
|
+
cwd,
|
|
3179
|
+
tool_name: "Bash",
|
|
3180
|
+
tool_use_id: "tool-source-text",
|
|
3181
|
+
tool_input: { command: "sed -n '1,40p' hook-source.ts" },
|
|
3182
|
+
tool_response: "const text = 'bash: foo: command not found';\nconst detail = 'permission denied';",
|
|
3183
|
+
},
|
|
3184
|
+
{ cwd },
|
|
3185
|
+
);
|
|
3186
|
+
|
|
3187
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
3188
|
+
assert.equal(result.outputJson, null);
|
|
3189
|
+
} finally {
|
|
3190
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3191
|
+
}
|
|
3192
|
+
});
|
|
3193
|
+
|
|
3045
3194
|
it("stays silent for rc-zero build logs that mention missing grep paths", async () => {
|
|
3046
3195
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-build-log-"));
|
|
3047
3196
|
try {
|
|
@@ -3068,6 +3217,32 @@ esac
|
|
|
3068
3217
|
}
|
|
3069
3218
|
});
|
|
3070
3219
|
|
|
3220
|
+
it("does not treat Bash output containing MCP transport text as MCP transport death", async () => {
|
|
3221
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-mcp-source-text-"));
|
|
3222
|
+
try {
|
|
3223
|
+
const result = await dispatchCodexNativeHook(
|
|
3224
|
+
{
|
|
3225
|
+
hook_event_name: "PostToolUse",
|
|
3226
|
+
cwd,
|
|
3227
|
+
tool_name: "Bash",
|
|
3228
|
+
tool_use_id: "tool-mcp-source-text",
|
|
3229
|
+
tool_input: { command: "sed -n '580,620p' codex-native-pre-post.ts" },
|
|
3230
|
+
tool_response: JSON.stringify({
|
|
3231
|
+
exit_code: 0,
|
|
3232
|
+
stdout: "reason: 'MCP transport closed before response over stdio pipe closed'",
|
|
3233
|
+
stderr: "",
|
|
3234
|
+
}),
|
|
3235
|
+
},
|
|
3236
|
+
{ cwd },
|
|
3237
|
+
);
|
|
3238
|
+
|
|
3239
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
3240
|
+
assert.equal(result.outputJson, null);
|
|
3241
|
+
} finally {
|
|
3242
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3243
|
+
}
|
|
3244
|
+
});
|
|
3245
|
+
|
|
3071
3246
|
it("stays silent when successful output includes prior hook context text", async () => {
|
|
3072
3247
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-recursive-context-"));
|
|
3073
3248
|
try {
|
|
@@ -3095,6 +3270,54 @@ esac
|
|
|
3095
3270
|
}
|
|
3096
3271
|
});
|
|
3097
3272
|
|
|
3273
|
+
it("stays silent when successful Bash output quotes MCP transport warnings", async () => {
|
|
3274
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-bash-mcp-quote-"));
|
|
3275
|
+
try {
|
|
3276
|
+
const result = await dispatchCodexNativeHook(
|
|
3277
|
+
{
|
|
3278
|
+
hook_event_name: "PostToolUse",
|
|
3279
|
+
cwd,
|
|
3280
|
+
tool_name: "Bash",
|
|
3281
|
+
tool_use_id: "tool-bash-mcp-quote",
|
|
3282
|
+
tool_input: { command: "cat diagnostic-log.txt" },
|
|
3283
|
+
tool_response: JSON.stringify({
|
|
3284
|
+
exit_code: 0,
|
|
3285
|
+
stdout: "diagnostic log quoted: MCP transport closed; stdio pipe closed before response",
|
|
3286
|
+
stderr: "",
|
|
3287
|
+
}),
|
|
3288
|
+
},
|
|
3289
|
+
{ cwd },
|
|
3290
|
+
);
|
|
3291
|
+
|
|
3292
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
3293
|
+
assert.equal(result.outputJson, null);
|
|
3294
|
+
} finally {
|
|
3295
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3296
|
+
}
|
|
3297
|
+
});
|
|
3298
|
+
|
|
3299
|
+
it("stays silent when Bash hard-failure text has no parsed exit code", async () => {
|
|
3300
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-bash-unparsed-failure-"));
|
|
3301
|
+
try {
|
|
3302
|
+
const result = await dispatchCodexNativeHook(
|
|
3303
|
+
{
|
|
3304
|
+
hook_event_name: "PostToolUse",
|
|
3305
|
+
cwd,
|
|
3306
|
+
tool_name: "Bash",
|
|
3307
|
+
tool_use_id: "tool-bash-unparsed-failure",
|
|
3308
|
+
tool_input: { command: "cat captured-output.txt" },
|
|
3309
|
+
tool_response: "captured transcript says: bash: foo: command not found",
|
|
3310
|
+
},
|
|
3311
|
+
{ cwd },
|
|
3312
|
+
);
|
|
3313
|
+
|
|
3314
|
+
assert.equal(result.omxEventName, "post-tool-use");
|
|
3315
|
+
assert.equal(result.outputJson, null);
|
|
3316
|
+
} finally {
|
|
3317
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3318
|
+
}
|
|
3319
|
+
});
|
|
3320
|
+
|
|
3098
3321
|
it("returns PostToolUse MCP transport fallback guidance for clear MCP transport death", async () => {
|
|
3099
3322
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-mcp-transport-"));
|
|
3100
3323
|
try {
|
|
@@ -3711,7 +3934,17 @@ esac
|
|
|
3711
3934
|
undefined,
|
|
3712
3935
|
{ ...process.env, OMX_SESSION_ID: "sess-stop-team-worker" },
|
|
3713
3936
|
);
|
|
3937
|
+
const workerCwd = join(cwd, ".omx", "team", "worker-stop-team", "worktrees", "worker-1");
|
|
3714
3938
|
const workerDir = join(cwd, ".omx", "state", "team", "worker-stop-team", "workers", "worker-1");
|
|
3939
|
+
await mkdir(workerCwd, { recursive: true });
|
|
3940
|
+
await writeJson(join(workerDir, "identity.json"), {
|
|
3941
|
+
name: "worker-1",
|
|
3942
|
+
index: 1,
|
|
3943
|
+
role: "executor",
|
|
3944
|
+
assigned_tasks: ["1"],
|
|
3945
|
+
worktree_path: workerCwd,
|
|
3946
|
+
team_state_root: join(cwd, ".omx", "state"),
|
|
3947
|
+
});
|
|
3715
3948
|
await writeJson(join(workerDir, "status.json"), {
|
|
3716
3949
|
state: "idle",
|
|
3717
3950
|
current_task_id: "1",
|
|
@@ -3733,10 +3966,10 @@ esac
|
|
|
3733
3966
|
const result = await dispatchCodexNativeHook(
|
|
3734
3967
|
{
|
|
3735
3968
|
hook_event_name: "Stop",
|
|
3736
|
-
cwd:
|
|
3969
|
+
cwd: workerCwd,
|
|
3737
3970
|
session_id: "sess-stop-team-worker",
|
|
3738
3971
|
},
|
|
3739
|
-
{ cwd:
|
|
3972
|
+
{ cwd: workerCwd },
|
|
3740
3973
|
);
|
|
3741
3974
|
|
|
3742
3975
|
assert.deepEqual(result.outputJson, {
|
|
@@ -3772,6 +4005,16 @@ esac
|
|
|
3772
4005
|
const stateDir = join(cwd, ".omx", "state");
|
|
3773
4006
|
const workerDir = join(stateDir, "team", "worker-repeat-team", "workers", "worker-1");
|
|
3774
4007
|
const taskPath = join(stateDir, "team", "worker-repeat-team", "tasks", "task-1.json");
|
|
4008
|
+
const workerCwd = join(cwd, ".omx", "team", "worker-repeat-team", "worktrees", "worker-1");
|
|
4009
|
+
await mkdir(workerCwd, { recursive: true });
|
|
4010
|
+
await writeJson(join(workerDir, "identity.json"), {
|
|
4011
|
+
name: "worker-1",
|
|
4012
|
+
index: 1,
|
|
4013
|
+
role: "executor",
|
|
4014
|
+
assigned_tasks: ["1"],
|
|
4015
|
+
worktree_path: workerCwd,
|
|
4016
|
+
team_state_root: stateDir,
|
|
4017
|
+
});
|
|
3775
4018
|
await writeJson(join(workerDir, "status.json"), {
|
|
3776
4019
|
state: "idle",
|
|
3777
4020
|
current_task_id: "1",
|
|
@@ -3790,7 +4033,6 @@ esac
|
|
|
3790
4033
|
process.env.OMX_TEAM_STATE_ROOT = stateDir;
|
|
3791
4034
|
process.env.OMX_TEAM_LEADER_CWD = cwd;
|
|
3792
4035
|
|
|
3793
|
-
const workerCwd = join(cwd, ".omx", "team", "worker-repeat-team", "worktrees", "worker-1");
|
|
3794
4036
|
const basePayload = {
|
|
3795
4037
|
hook_event_name: "Stop",
|
|
3796
4038
|
cwd: workerCwd,
|
|
@@ -4032,6 +4274,51 @@ esac
|
|
|
4032
4274
|
}
|
|
4033
4275
|
});
|
|
4034
4276
|
|
|
4277
|
+
it("honors terminal team run-state before later canonical-team Stop fallback", async () => {
|
|
4278
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-terminal-run-state-canonical-"));
|
|
4279
|
+
try {
|
|
4280
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
4281
|
+
const sessionId = "sess-stop-team-terminal-run-state";
|
|
4282
|
+
await initTeamState(
|
|
4283
|
+
"terminal-run-state-team",
|
|
4284
|
+
"terminal team stop canonical fallback regression",
|
|
4285
|
+
"executor",
|
|
4286
|
+
1,
|
|
4287
|
+
cwd,
|
|
4288
|
+
undefined,
|
|
4289
|
+
{ ...process.env, OMX_SESSION_ID: sessionId },
|
|
4290
|
+
);
|
|
4291
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
4292
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId, cwd });
|
|
4293
|
+
await writeJson(join(stateDir, "sessions", sessionId, "run-state.json"), {
|
|
4294
|
+
version: 1,
|
|
4295
|
+
mode: "team",
|
|
4296
|
+
active: false,
|
|
4297
|
+
outcome: "finish",
|
|
4298
|
+
lifecycle_outcome: "finished",
|
|
4299
|
+
current_phase: "complete",
|
|
4300
|
+
completed_at: "2026-04-27T12:00:00.000Z",
|
|
4301
|
+
updated_at: "2026-04-27T12:00:00.000Z",
|
|
4302
|
+
});
|
|
4303
|
+
|
|
4304
|
+
const result = await dispatchCodexNativeHook(
|
|
4305
|
+
{
|
|
4306
|
+
hook_event_name: "Stop",
|
|
4307
|
+
cwd,
|
|
4308
|
+
session_id: sessionId,
|
|
4309
|
+
thread_id: "thread-stop-team-terminal-run-state",
|
|
4310
|
+
turn_id: "turn-stop-team-terminal-run-state-1",
|
|
4311
|
+
},
|
|
4312
|
+
{ cwd },
|
|
4313
|
+
);
|
|
4314
|
+
|
|
4315
|
+
assert.equal(result.omxEventName, "stop");
|
|
4316
|
+
assert.equal(result.outputJson, null);
|
|
4317
|
+
} finally {
|
|
4318
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4319
|
+
}
|
|
4320
|
+
});
|
|
4321
|
+
|
|
4035
4322
|
it("re-fires canonical-team Stop output for a later fresh Stop reply when coarse mode state is missing", async () => {
|
|
4036
4323
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-canonical-refire-"));
|
|
4037
4324
|
try {
|
|
@@ -4628,7 +4915,7 @@ esac
|
|
|
4628
4915
|
"Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
4629
4916
|
stopReason: "deep_interview_question_required",
|
|
4630
4917
|
systemMessage:
|
|
4631
|
-
"OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
4918
|
+
"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.",
|
|
4632
4919
|
});
|
|
4633
4920
|
} finally {
|
|
4634
4921
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -4684,7 +4971,7 @@ esac
|
|
|
4684
4971
|
"Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
4685
4972
|
stopReason: "deep_interview_question_required",
|
|
4686
4973
|
systemMessage:
|
|
4687
|
-
"OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
4974
|
+
"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.",
|
|
4688
4975
|
});
|
|
4689
4976
|
} finally {
|
|
4690
4977
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -4812,7 +5099,7 @@ esac
|
|
|
4812
5099
|
"Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
4813
5100
|
stopReason: "deep_interview_question_required",
|
|
4814
5101
|
systemMessage:
|
|
4815
|
-
"OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
5102
|
+
"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.",
|
|
4816
5103
|
};
|
|
4817
5104
|
|
|
4818
5105
|
const first = await dispatchCodexNativeHook(payload, { cwd });
|
|
@@ -4958,7 +5245,7 @@ esac
|
|
|
4958
5245
|
"Deep interview is still active (phase: intent-first) and has a pending structured question obligation; use `omx question` before stopping.",
|
|
4959
5246
|
stopReason: "deep_interview_question_required",
|
|
4960
5247
|
systemMessage:
|
|
4961
|
-
"OMX deep-interview is still active (phase: intent-first) and requires a structured question via omx question before stopping.",
|
|
5248
|
+
"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.",
|
|
4962
5249
|
});
|
|
4963
5250
|
} finally {
|
|
4964
5251
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -5136,10 +5423,10 @@ esac
|
|
|
5136
5423
|
assert.deepEqual(result.outputJson, {
|
|
5137
5424
|
decision: "block",
|
|
5138
5425
|
reason:
|
|
5139
|
-
"OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
5426
|
+
"OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
5140
5427
|
stopReason: "ralph_executing",
|
|
5141
5428
|
systemMessage:
|
|
5142
|
-
"OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
5429
|
+
"OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
5143
5430
|
});
|
|
5144
5431
|
} finally {
|
|
5145
5432
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -5171,10 +5458,10 @@ esac
|
|
|
5171
5458
|
assert.deepEqual(result.outputJson, {
|
|
5172
5459
|
decision: "block",
|
|
5173
5460
|
reason:
|
|
5174
|
-
"OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
5461
|
+
"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.",
|
|
5175
5462
|
stopReason: "ralph_executing",
|
|
5176
5463
|
systemMessage:
|
|
5177
|
-
"OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
5464
|
+
"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.",
|
|
5178
5465
|
});
|
|
5179
5466
|
} finally {
|
|
5180
5467
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -5259,6 +5546,87 @@ esac
|
|
|
5259
5546
|
}
|
|
5260
5547
|
});
|
|
5261
5548
|
|
|
5549
|
+
it("does not hard-block Stop on stale session-scoped Ralph starting state after visible active modes are cleared", async () => {
|
|
5550
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-cleared-stale-ralph-"));
|
|
5551
|
+
try {
|
|
5552
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
5553
|
+
const sessionId = "sess-cleared-ralph";
|
|
5554
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
5555
|
+
await writeJson(join(stateDir, "sessions", sessionId, "ralph-state.json"), {
|
|
5556
|
+
active: true,
|
|
5557
|
+
mode: "ralph",
|
|
5558
|
+
current_phase: "starting",
|
|
5559
|
+
session_id: sessionId,
|
|
5560
|
+
});
|
|
5561
|
+
await writeJson(join(stateDir, "skill-active-state.json"), {
|
|
5562
|
+
active: false,
|
|
5563
|
+
skill: "ralph",
|
|
5564
|
+
active_skills: [],
|
|
5565
|
+
});
|
|
5566
|
+
|
|
5567
|
+
const listActive = await executeStateOperation("state_list_active", {
|
|
5568
|
+
workingDirectory: cwd,
|
|
5569
|
+
});
|
|
5570
|
+
assert.deepEqual(listActive.payload, { active_modes: [] });
|
|
5571
|
+
|
|
5572
|
+
const result = await dispatchCodexNativeHook(
|
|
5573
|
+
{
|
|
5574
|
+
hook_event_name: "Stop",
|
|
5575
|
+
cwd,
|
|
5576
|
+
session_id: sessionId,
|
|
5577
|
+
},
|
|
5578
|
+
{ cwd },
|
|
5579
|
+
);
|
|
5580
|
+
|
|
5581
|
+
assert.equal(result.omxEventName, "stop");
|
|
5582
|
+
assert.equal(result.outputJson, null);
|
|
5583
|
+
} finally {
|
|
5584
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5585
|
+
}
|
|
5586
|
+
});
|
|
5587
|
+
|
|
5588
|
+
it("blocks Stop on visible active session-scoped Ralph starting state and reports its path", async () => {
|
|
5589
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-visible-starting-ralph-"));
|
|
5590
|
+
try {
|
|
5591
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
5592
|
+
const sessionId = "sess-visible-ralph";
|
|
5593
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
5594
|
+
await writeJson(join(stateDir, "sessions", sessionId, "ralph-state.json"), {
|
|
5595
|
+
active: true,
|
|
5596
|
+
mode: "ralph",
|
|
5597
|
+
current_phase: "starting",
|
|
5598
|
+
session_id: sessionId,
|
|
5599
|
+
});
|
|
5600
|
+
await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
|
|
5601
|
+
active: true,
|
|
5602
|
+
skill: "ralph",
|
|
5603
|
+
phase: "starting",
|
|
5604
|
+
active_skills: [{ skill: "ralph", phase: "starting", active: true, session_id: sessionId }],
|
|
5605
|
+
});
|
|
5606
|
+
|
|
5607
|
+
const result = await dispatchCodexNativeHook(
|
|
5608
|
+
{
|
|
5609
|
+
hook_event_name: "Stop",
|
|
5610
|
+
cwd,
|
|
5611
|
+
session_id: sessionId,
|
|
5612
|
+
},
|
|
5613
|
+
{ cwd },
|
|
5614
|
+
);
|
|
5615
|
+
|
|
5616
|
+
assert.equal(result.omxEventName, "stop");
|
|
5617
|
+
assert.deepEqual(result.outputJson, {
|
|
5618
|
+
decision: "block",
|
|
5619
|
+
reason:
|
|
5620
|
+
"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.",
|
|
5621
|
+
stopReason: "ralph_starting",
|
|
5622
|
+
systemMessage:
|
|
5623
|
+
"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.",
|
|
5624
|
+
});
|
|
5625
|
+
} finally {
|
|
5626
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5627
|
+
}
|
|
5628
|
+
});
|
|
5629
|
+
|
|
5262
5630
|
it("does not block Stop from another session-scoped Ralph state when an explicit session_id has no active Ralph state", async () => {
|
|
5263
5631
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-explicit-session-ralph-"));
|
|
5264
5632
|
try {
|
|
@@ -5286,6 +5654,46 @@ esac
|
|
|
5286
5654
|
}
|
|
5287
5655
|
});
|
|
5288
5656
|
|
|
5657
|
+
it("prefers canonical run-state terminal lifecycle before stale session Ralph state during Stop", async () => {
|
|
5658
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-canonical-run-state-ralph-"));
|
|
5659
|
+
try {
|
|
5660
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
5661
|
+
const sessionId = "sess-canonical-run-state-ralph";
|
|
5662
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
5663
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId, cwd });
|
|
5664
|
+
await writeJson(join(stateDir, "sessions", sessionId, "run-state.json"), {
|
|
5665
|
+
version: 1,
|
|
5666
|
+
mode: "ralph",
|
|
5667
|
+
active: false,
|
|
5668
|
+
outcome: "finish",
|
|
5669
|
+
lifecycle_outcome: "finished",
|
|
5670
|
+
current_phase: "complete",
|
|
5671
|
+
completed_at: "2026-04-27T12:00:00.000Z",
|
|
5672
|
+
updated_at: "2026-04-27T12:00:00.000Z",
|
|
5673
|
+
});
|
|
5674
|
+
await writeJson(join(stateDir, "sessions", sessionId, "ralph-state.json"), {
|
|
5675
|
+
active: true,
|
|
5676
|
+
mode: "ralph",
|
|
5677
|
+
current_phase: "verifying",
|
|
5678
|
+
session_id: sessionId,
|
|
5679
|
+
});
|
|
5680
|
+
|
|
5681
|
+
const result = await dispatchCodexNativeHook(
|
|
5682
|
+
{
|
|
5683
|
+
hook_event_name: "Stop",
|
|
5684
|
+
cwd,
|
|
5685
|
+
session_id: sessionId,
|
|
5686
|
+
},
|
|
5687
|
+
{ cwd },
|
|
5688
|
+
);
|
|
5689
|
+
|
|
5690
|
+
assert.equal(result.omxEventName, "stop");
|
|
5691
|
+
assert.equal(result.outputJson, null);
|
|
5692
|
+
} finally {
|
|
5693
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5694
|
+
}
|
|
5695
|
+
});
|
|
5696
|
+
|
|
5289
5697
|
it("does not block Stop from root Ralph fallback when the current session has no scoped Ralph state", async () => {
|
|
5290
5698
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-root-fallback-ralph-"));
|
|
5291
5699
|
try {
|
|
@@ -5399,10 +5807,10 @@ esac
|
|
|
5399
5807
|
const expected = {
|
|
5400
5808
|
decision: "block",
|
|
5401
5809
|
reason:
|
|
5402
|
-
"OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
5810
|
+
"OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
5403
5811
|
stopReason: "ralph_executing",
|
|
5404
5812
|
systemMessage:
|
|
5405
|
-
"OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
5813
|
+
"OMX Ralph is still active (phase: executing; state: .omx/state/ralph-state.json); continue the task and gather fresh verification evidence before stopping.",
|
|
5406
5814
|
};
|
|
5407
5815
|
|
|
5408
5816
|
const first = await dispatchCodexNativeHook(payload, { cwd });
|