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
|
@@ -6,8 +6,8 @@ import { join } from 'path';
|
|
|
6
6
|
import { tmpdir } from 'os';
|
|
7
7
|
import { existsSync } from 'fs';
|
|
8
8
|
import { HUD_TMUX_TEAM_HEIGHT_LINES } from '../../hud/constants.js';
|
|
9
|
-
import { initTeamState, createTask, readTeamConfig, saveTeamConfig, listMailboxMessages, listDispatchRequests, transitionDispatchRequest, updateWorkerHeartbeat, writeAtomic, readTask, readMonitorSnapshot, claimTask, transitionTaskStatus, readWorkerStatus, writeWorkerStatus, } from '../state.js';
|
|
10
|
-
import { monitorTeam, shutdownTeam, resumeTeam, startTeam, assignTask, sendWorkerMessage, applyCreatedInteractiveSessionToConfig, resolveWorkerLaunchArgsFromEnv, shouldPrekillInteractiveShutdownProcessTrees, waitForWorkerStartupEvidence, waitForClaudeStartupEvidence, cleanupTeamWorkerLaunchOrphanedMcpProcesses, } from '../runtime.js';
|
|
9
|
+
import { initTeamState, createTask, writeWorkerInbox, readTeamConfig, saveTeamConfig, listMailboxMessages, listDispatchRequests, transitionDispatchRequest, updateWorkerHeartbeat, writeAtomic, readTask, readMonitorSnapshot, claimTask, transitionTaskStatus, readWorkerStatus, writeWorkerStatus, } from '../state.js';
|
|
10
|
+
import { monitorTeam, shutdownTeam, resumeTeam, startTeam, assignTask, sendWorkerMessage, applyCreatedInteractiveSessionToConfig, resolveWorkerLaunchArgsFromEnv, shouldPrekillInteractiveShutdownProcessTrees, waitForWorkerStartupEvidence, waitForClaudeStartupEvidence, cleanupTeamWorkerLaunchOrphanedMcpProcesses, settleStartupAttemptResults, } from '../runtime.js';
|
|
11
11
|
import { resolveAgentReasoningEffort, resolveTeamLowComplexityDefaultModel } from '../model-contract.js';
|
|
12
12
|
import { readTeamEvents } from '../state/events.js';
|
|
13
13
|
import { sanitizeTeamName } from '../tmux-session.js';
|
|
@@ -56,6 +56,31 @@ async function readTeamDeliveryLog(cwd) {
|
|
|
56
56
|
.filter(Boolean)
|
|
57
57
|
.map((line) => JSON.parse(line));
|
|
58
58
|
}
|
|
59
|
+
async function markPendingInboxDispatchesDelivered(teamName, cwd, opts = {}) {
|
|
60
|
+
const requests = await listDispatchRequests(teamName, cwd, { kind: 'inbox' }).catch(() => []);
|
|
61
|
+
for (const request of requests) {
|
|
62
|
+
if (request.status !== 'pending')
|
|
63
|
+
continue;
|
|
64
|
+
if (opts.toWorker && request.to_worker !== opts.toWorker)
|
|
65
|
+
continue;
|
|
66
|
+
await opts.beforeDeliver?.();
|
|
67
|
+
const notified = await transitionDispatchRequest(teamName, request.request_id, 'pending', 'notified', { last_reason: opts.lastReason ?? 'test_delivered_receipt' }, cwd).catch(() => null);
|
|
68
|
+
if (!notified)
|
|
69
|
+
continue;
|
|
70
|
+
await transitionDispatchRequest(teamName, request.request_id, 'notified', 'delivered', { last_reason: opts.lastReason ?? 'test_delivered_receipt' }, cwd).catch(() => { });
|
|
71
|
+
await opts.afterDeliver?.();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function markPendingInboxDispatchesNotified(teamName, cwd, opts = {}) {
|
|
75
|
+
const requests = await listDispatchRequests(teamName, cwd, { kind: 'inbox' }).catch(() => []);
|
|
76
|
+
for (const request of requests) {
|
|
77
|
+
if (request.status !== 'pending')
|
|
78
|
+
continue;
|
|
79
|
+
if (opts.toWorker && request.to_worker !== opts.toWorker)
|
|
80
|
+
continue;
|
|
81
|
+
await transitionDispatchRequest(teamName, request.request_id, 'pending', 'notified', { last_reason: opts.lastReason ?? 'test_notified_receipt' }, cwd).catch(() => { });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
59
84
|
function withEmptyPath(fn) {
|
|
60
85
|
const prev = process.env.PATH;
|
|
61
86
|
process.env.PATH = '';
|
|
@@ -564,6 +589,161 @@ describe('runtime', () => {
|
|
|
564
589
|
await rm(cwd, { recursive: true, force: true });
|
|
565
590
|
}
|
|
566
591
|
});
|
|
592
|
+
it('uses a production startup evidence window that can tolerate slow Codex startup', async () => {
|
|
593
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-startup-window-'));
|
|
594
|
+
const prevTmux = process.env.TMUX;
|
|
595
|
+
const prevTmuxPane = process.env.TMUX_PANE;
|
|
596
|
+
const prevLaunchMode = process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
597
|
+
const prevWorkerCli = process.env.OMX_TEAM_WORKER_CLI;
|
|
598
|
+
const prevSkipReadyWait = process.env.OMX_TEAM_SKIP_READY_WAIT;
|
|
599
|
+
const prevStartupEvidenceTimeout = process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
600
|
+
const prevStartupDispatchRetries = process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES;
|
|
601
|
+
const prevStartupDispatchRetryDelay = process.env.OMX_TEAM_STARTUP_DISPATCH_RETRY_DELAY_MS;
|
|
602
|
+
let receiptNotifier = null;
|
|
603
|
+
let progressWriter = null;
|
|
604
|
+
try {
|
|
605
|
+
await withMockTmuxFixture({
|
|
606
|
+
dirPrefix: 'omx-runtime-startup-window-bin-',
|
|
607
|
+
tmuxScript: (tmuxLogPath) => `#!/bin/sh
|
|
608
|
+
set -eu
|
|
609
|
+
printf '%s\\n' "$*" >> "${tmuxLogPath}"
|
|
610
|
+
case "$1" in
|
|
611
|
+
-V)
|
|
612
|
+
echo "tmux 3.4"
|
|
613
|
+
exit 0
|
|
614
|
+
;;
|
|
615
|
+
display-message)
|
|
616
|
+
case "$*" in
|
|
617
|
+
*"#{window_width}"*)
|
|
618
|
+
echo "120"
|
|
619
|
+
;;
|
|
620
|
+
*)
|
|
621
|
+
echo "leader:0 %1"
|
|
622
|
+
;;
|
|
623
|
+
esac
|
|
624
|
+
exit 0
|
|
625
|
+
;;
|
|
626
|
+
list-panes)
|
|
627
|
+
case "$*" in
|
|
628
|
+
*"-F #{pane_id}"*"#{pane_current_command}"*)
|
|
629
|
+
printf "%%1\\tzsh\\tzsh\\n"
|
|
630
|
+
exit 0
|
|
631
|
+
;;
|
|
632
|
+
*"#{pane_pid}"*)
|
|
633
|
+
echo "4321"
|
|
634
|
+
exit 0
|
|
635
|
+
;;
|
|
636
|
+
*"#{pane_dead} #{pane_pid}"*)
|
|
637
|
+
echo "0 4321"
|
|
638
|
+
exit 0
|
|
639
|
+
;;
|
|
640
|
+
*)
|
|
641
|
+
exit 0
|
|
642
|
+
;;
|
|
643
|
+
esac
|
|
644
|
+
;;
|
|
645
|
+
split-window)
|
|
646
|
+
case "$*" in
|
|
647
|
+
*" -h "*)
|
|
648
|
+
echo "%2"
|
|
649
|
+
;;
|
|
650
|
+
*)
|
|
651
|
+
echo "%3"
|
|
652
|
+
;;
|
|
653
|
+
esac
|
|
654
|
+
exit 0
|
|
655
|
+
;;
|
|
656
|
+
capture-pane)
|
|
657
|
+
printf 'OpenAI Codex\\n> '
|
|
658
|
+
exit 0
|
|
659
|
+
;;
|
|
660
|
+
send-keys|resize-pane|select-layout|set-window-option|select-pane|set-hook|run-shell|kill-pane|kill-session)
|
|
661
|
+
exit 0
|
|
662
|
+
;;
|
|
663
|
+
*)
|
|
664
|
+
exit 0
|
|
665
|
+
;;
|
|
666
|
+
esac
|
|
667
|
+
`,
|
|
668
|
+
binaries: [
|
|
669
|
+
{
|
|
670
|
+
name: 'codex',
|
|
671
|
+
content: '#!/bin/sh\nsleep 30\n',
|
|
672
|
+
},
|
|
673
|
+
],
|
|
674
|
+
}, async () => {
|
|
675
|
+
process.env.TMUX = 'leader-session';
|
|
676
|
+
process.env.TMUX_PANE = '%1';
|
|
677
|
+
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = 'interactive';
|
|
678
|
+
process.env.OMX_TEAM_WORKER_CLI = 'codex';
|
|
679
|
+
process.env.OMX_TEAM_SKIP_READY_WAIT = '1';
|
|
680
|
+
delete process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
681
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES = '1';
|
|
682
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRY_DELAY_MS = '50';
|
|
683
|
+
receiptNotifier = setInterval(() => {
|
|
684
|
+
void markPendingInboxDispatchesNotified('team-startup-window', cwd, {
|
|
685
|
+
toWorker: 'worker-1',
|
|
686
|
+
lastReason: 'test_notified_receipt',
|
|
687
|
+
}).catch(() => { });
|
|
688
|
+
}, 20);
|
|
689
|
+
progressWriter = setTimeout(() => {
|
|
690
|
+
void writeWorkerStatus('team-startup-window', 'worker-1', {
|
|
691
|
+
state: 'working',
|
|
692
|
+
current_task_id: '1',
|
|
693
|
+
updated_at: new Date().toISOString(),
|
|
694
|
+
}, cwd).catch(() => { });
|
|
695
|
+
}, 6_000);
|
|
696
|
+
const runtime = await withoutTeamWorkerEnv(() => startTeam('team-startup-window', 'interactive startup should wait for slow Codex evidence', 'executor', 1, [{ subject: 's', description: 'd', owner: 'worker-1' }], cwd));
|
|
697
|
+
assert.equal(runtime.teamName, 'team-startup-window');
|
|
698
|
+
assert.ok(await readTeamConfig('team-startup-window', cwd));
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
finally {
|
|
702
|
+
if (receiptNotifier)
|
|
703
|
+
clearInterval(receiptNotifier);
|
|
704
|
+
if (progressWriter)
|
|
705
|
+
clearTimeout(progressWriter);
|
|
706
|
+
if (typeof prevTmux === 'string')
|
|
707
|
+
process.env.TMUX = prevTmux;
|
|
708
|
+
else
|
|
709
|
+
delete process.env.TMUX;
|
|
710
|
+
if (typeof prevTmuxPane === 'string')
|
|
711
|
+
process.env.TMUX_PANE = prevTmuxPane;
|
|
712
|
+
else
|
|
713
|
+
delete process.env.TMUX_PANE;
|
|
714
|
+
if (typeof prevLaunchMode === 'string')
|
|
715
|
+
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = prevLaunchMode;
|
|
716
|
+
else
|
|
717
|
+
delete process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
718
|
+
if (typeof prevWorkerCli === 'string')
|
|
719
|
+
process.env.OMX_TEAM_WORKER_CLI = prevWorkerCli;
|
|
720
|
+
else
|
|
721
|
+
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
722
|
+
if (typeof prevSkipReadyWait === 'string')
|
|
723
|
+
process.env.OMX_TEAM_SKIP_READY_WAIT = prevSkipReadyWait;
|
|
724
|
+
else
|
|
725
|
+
delete process.env.OMX_TEAM_SKIP_READY_WAIT;
|
|
726
|
+
if (typeof prevStartupEvidenceTimeout === 'string') {
|
|
727
|
+
process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS = prevStartupEvidenceTimeout;
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
delete process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
731
|
+
}
|
|
732
|
+
if (typeof prevStartupDispatchRetries === 'string') {
|
|
733
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES = prevStartupDispatchRetries;
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
delete process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES;
|
|
737
|
+
}
|
|
738
|
+
if (typeof prevStartupDispatchRetryDelay === 'string') {
|
|
739
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRY_DELAY_MS = prevStartupDispatchRetryDelay;
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
delete process.env.OMX_TEAM_STARTUP_DISPATCH_RETRY_DELAY_MS;
|
|
743
|
+
}
|
|
744
|
+
await rm(cwd, { recursive: true, force: true });
|
|
745
|
+
}
|
|
746
|
+
});
|
|
567
747
|
it('startTeam rejects interactive startup when tmux fallback never produces worker startup evidence', async () => {
|
|
568
748
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-startup-no-evidence-'));
|
|
569
749
|
const prevTmux = process.env.TMUX;
|
|
@@ -809,10 +989,6 @@ sleep 5
|
|
|
809
989
|
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = prevLaunchMode;
|
|
810
990
|
else
|
|
811
991
|
delete process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
812
|
-
if (typeof prevWorkerCli === 'string')
|
|
813
|
-
process.env.OMX_TEAM_WORKER_CLI = prevWorkerCli;
|
|
814
|
-
else
|
|
815
|
-
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
816
992
|
await rm(cwd, { recursive: true, force: true });
|
|
817
993
|
}
|
|
818
994
|
});
|
|
@@ -828,6 +1004,7 @@ sleep 5
|
|
|
828
1004
|
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = prevLaunchMode;
|
|
829
1005
|
else
|
|
830
1006
|
delete process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
1007
|
+
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
831
1008
|
await rm(cwd, { recursive: true, force: true });
|
|
832
1009
|
}
|
|
833
1010
|
});
|
|
@@ -956,7 +1133,7 @@ esac
|
|
|
956
1133
|
delete process.env.WSL_DISTRO_NAME;
|
|
957
1134
|
delete process.env.WSL_INTEROP;
|
|
958
1135
|
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
959
|
-
runtime = await withoutTeamWorkerEnv(() => startTeam('team-win32-no-env', 'native windows current-client detection', 'executor', 1, [{ subject: 's', description: 'd', owner: 'worker-1' }], cwd));
|
|
1136
|
+
const runtime = await withoutTeamWorkerEnv(() => startTeam('team-win32-no-env', 'native windows current-client detection', 'executor', 1, [{ subject: 's', description: 'd', owner: 'worker-1' }], cwd));
|
|
960
1137
|
teamNameForCleanup = runtime.teamName;
|
|
961
1138
|
assert.equal(runtime.config.tmux_session, 'leader:0');
|
|
962
1139
|
assert.equal(runtime.config.leader_pane_id, '%1');
|
|
@@ -967,7 +1144,6 @@ esac
|
|
|
967
1144
|
if (teamNameForCleanup) {
|
|
968
1145
|
await shutdownTeam(teamNameForCleanup, cwd, { force: true });
|
|
969
1146
|
}
|
|
970
|
-
runtime = null;
|
|
971
1147
|
});
|
|
972
1148
|
}
|
|
973
1149
|
finally {
|
|
@@ -1274,11 +1450,11 @@ esac
|
|
|
1274
1450
|
await rm(cwd, { recursive: true, force: true });
|
|
1275
1451
|
}
|
|
1276
1452
|
});
|
|
1277
|
-
it('startTeam saves interactive pane ids before readiness
|
|
1453
|
+
it('startTeam saves interactive pane ids before concurrent readiness attempts', async () => {
|
|
1278
1454
|
const source = await readFile(join(process.cwd(), 'src', 'team', 'runtime.ts'), 'utf-8');
|
|
1279
1455
|
const applyMatch = source.match(/applyCreatedInteractiveSessionToConfig\(\s*config,\s*createdSession,\s*workerPaneIds\s*\);/m);
|
|
1280
1456
|
const saveMatch = source.match(/await saveTeamConfig\(config, leaderCwd\);/m);
|
|
1281
|
-
const readyMatch = source.match(/
|
|
1457
|
+
const readyMatch = source.match(/waitForWorkerReadyAsync\(/m);
|
|
1282
1458
|
const applyIndex = applyMatch?.index ?? -1;
|
|
1283
1459
|
const saveIndex = saveMatch?.index ?? -1;
|
|
1284
1460
|
const readyIndex = readyMatch?.index ?? -1;
|
|
@@ -1288,6 +1464,148 @@ esac
|
|
|
1288
1464
|
assert.equal(applyIndex < saveIndex, true);
|
|
1289
1465
|
assert.equal(saveIndex < readyIndex, true);
|
|
1290
1466
|
});
|
|
1467
|
+
it('startTeam starts worker-2 readiness before delayed worker-1 readiness settles', async () => {
|
|
1468
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-parallel-ready-'));
|
|
1469
|
+
const previousTmux = process.env.TMUX;
|
|
1470
|
+
const previousTmuxPane = process.env.TMUX_PANE;
|
|
1471
|
+
const previousLaunchMode = process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
1472
|
+
const previousWorkerCli = process.env.OMX_TEAM_WORKER_CLI;
|
|
1473
|
+
const previousReadyTimeout = process.env.OMX_TEAM_READY_TIMEOUT_MS;
|
|
1474
|
+
const previousStartupEvidenceTimeout = process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
1475
|
+
const previousStartupDispatchRetries = process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES;
|
|
1476
|
+
let receiptDeliverer = null;
|
|
1477
|
+
let runtimeTeamName = null;
|
|
1478
|
+
try {
|
|
1479
|
+
await withMockTmuxFixture({
|
|
1480
|
+
dirPrefix: 'omx-runtime-parallel-ready-bin-',
|
|
1481
|
+
tmuxScript: () => `#!/bin/sh
|
|
1482
|
+
set -eu
|
|
1483
|
+
order_file="${cwd}/ready-order.log"
|
|
1484
|
+
case "$1" in
|
|
1485
|
+
-V)
|
|
1486
|
+
echo "tmux 3.4"
|
|
1487
|
+
exit 0
|
|
1488
|
+
;;
|
|
1489
|
+
display-message)
|
|
1490
|
+
case "$*" in
|
|
1491
|
+
*"#{window_width}"*) echo "120" ;;
|
|
1492
|
+
*) echo "leader:0 %1" ;;
|
|
1493
|
+
esac
|
|
1494
|
+
exit 0
|
|
1495
|
+
;;
|
|
1496
|
+
list-panes)
|
|
1497
|
+
case "$*" in
|
|
1498
|
+
*"pane_current_command"*) printf "%%1\tnode\t'codex'\n" ;;
|
|
1499
|
+
*"#{pane_dead} #{pane_pid}"*) echo "0 4242" ;;
|
|
1500
|
+
*"#{pane_dead}"*) echo "0" ;;
|
|
1501
|
+
*"-t %2"*"#{pane_pid}"*) echo "4242" ;;
|
|
1502
|
+
*"-t %3"*"#{pane_pid}"*) echo "4343" ;;
|
|
1503
|
+
*"#{pane_pid}"*) echo "4141" ;;
|
|
1504
|
+
*) exit 0 ;;
|
|
1505
|
+
esac
|
|
1506
|
+
exit 0
|
|
1507
|
+
;;
|
|
1508
|
+
capture-pane)
|
|
1509
|
+
case "$*" in
|
|
1510
|
+
*"-t %2"*)
|
|
1511
|
+
printf '%s\n' w1-ready-start >> "$order_file"
|
|
1512
|
+
sleep 0.4
|
|
1513
|
+
printf '%s\n' w1-ready-done >> "$order_file"
|
|
1514
|
+
printf 'OpenAI Codex\nmodel: test\n› \n'
|
|
1515
|
+
;;
|
|
1516
|
+
*"-t %3"*)
|
|
1517
|
+
printf '%s\n' w2-ready-start >> "$order_file"
|
|
1518
|
+
printf 'OpenAI Codex\nmodel: test\n› \n'
|
|
1519
|
+
;;
|
|
1520
|
+
*)
|
|
1521
|
+
printf 'OpenAI Codex\nmodel: test\n› \n'
|
|
1522
|
+
;;
|
|
1523
|
+
esac
|
|
1524
|
+
exit 0
|
|
1525
|
+
;;
|
|
1526
|
+
split-window)
|
|
1527
|
+
count_file="${cwd}/split-window-count"
|
|
1528
|
+
count=0
|
|
1529
|
+
if [ -f "$count_file" ]; then count=$(cat "$count_file"); fi
|
|
1530
|
+
count=$((count + 1))
|
|
1531
|
+
printf '%s' "$count" > "$count_file"
|
|
1532
|
+
case "$count" in
|
|
1533
|
+
1) echo "%2" ;;
|
|
1534
|
+
2) echo "%3" ;;
|
|
1535
|
+
*) echo "%4" ;;
|
|
1536
|
+
esac
|
|
1537
|
+
exit 0
|
|
1538
|
+
;;
|
|
1539
|
+
set-hook|run-shell|select-layout|set-window-option|select-pane|send-keys|kill-pane|kill-session|resize-pane)
|
|
1540
|
+
exit 0
|
|
1541
|
+
;;
|
|
1542
|
+
*)
|
|
1543
|
+
exit 0
|
|
1544
|
+
;;
|
|
1545
|
+
esac
|
|
1546
|
+
`,
|
|
1547
|
+
binaries: [{ name: 'codex', content: '#!/usr/bin/env node\nprocess.stdin.resume();\n' }],
|
|
1548
|
+
}, async () => {
|
|
1549
|
+
delete process.env.TMUX;
|
|
1550
|
+
process.env.TMUX_PANE = '%1';
|
|
1551
|
+
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = 'interactive';
|
|
1552
|
+
process.env.OMX_TEAM_WORKER_CLI = 'codex';
|
|
1553
|
+
process.env.OMX_TEAM_READY_TIMEOUT_MS = '2000';
|
|
1554
|
+
process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS = '50';
|
|
1555
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES = '1';
|
|
1556
|
+
receiptDeliverer = setInterval(() => {
|
|
1557
|
+
void (async () => {
|
|
1558
|
+
await markPendingInboxDispatchesDelivered('team-parallel-ready', cwd);
|
|
1559
|
+
})();
|
|
1560
|
+
}, 20);
|
|
1561
|
+
const runtime = await withoutTeamWorkerEnv(() => startTeam('team-parallel-ready', 'worker-2 readiness should not wait for worker-1 readiness settle', 'executor', 2, [
|
|
1562
|
+
{ subject: 'w1', description: 'worker one', owner: 'worker-1' },
|
|
1563
|
+
{ subject: 'w2', description: 'worker two', owner: 'worker-2' },
|
|
1564
|
+
], cwd));
|
|
1565
|
+
runtimeTeamName = runtime.teamName;
|
|
1566
|
+
const order = (await readFile(join(cwd, 'ready-order.log'), 'utf-8')).trim().split('\n');
|
|
1567
|
+
assert.ok(order.includes('w1-ready-start'));
|
|
1568
|
+
assert.ok(order.includes('w2-ready-start'));
|
|
1569
|
+
assert.ok(order.includes('w1-ready-done'));
|
|
1570
|
+
assert.equal(order.indexOf('w2-ready-start') < order.indexOf('w1-ready-done'), true, `expected worker-2 readiness attempt before worker-1 readiness settled, got ${order.join(',')}`);
|
|
1571
|
+
});
|
|
1572
|
+
}
|
|
1573
|
+
finally {
|
|
1574
|
+
if (receiptDeliverer)
|
|
1575
|
+
clearInterval(receiptDeliverer);
|
|
1576
|
+
if (runtimeTeamName)
|
|
1577
|
+
await shutdownTeam(runtimeTeamName, cwd, { force: true }).catch(() => { });
|
|
1578
|
+
if (typeof previousTmux === 'string')
|
|
1579
|
+
process.env.TMUX = previousTmux;
|
|
1580
|
+
else
|
|
1581
|
+
delete process.env.TMUX;
|
|
1582
|
+
if (typeof previousTmuxPane === 'string')
|
|
1583
|
+
process.env.TMUX_PANE = previousTmuxPane;
|
|
1584
|
+
else
|
|
1585
|
+
delete process.env.TMUX_PANE;
|
|
1586
|
+
if (typeof previousLaunchMode === 'string')
|
|
1587
|
+
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = previousLaunchMode;
|
|
1588
|
+
else
|
|
1589
|
+
delete process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
1590
|
+
if (typeof previousWorkerCli === 'string')
|
|
1591
|
+
process.env.OMX_TEAM_WORKER_CLI = previousWorkerCli;
|
|
1592
|
+
else
|
|
1593
|
+
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
1594
|
+
if (typeof previousReadyTimeout === 'string')
|
|
1595
|
+
process.env.OMX_TEAM_READY_TIMEOUT_MS = previousReadyTimeout;
|
|
1596
|
+
else
|
|
1597
|
+
delete process.env.OMX_TEAM_READY_TIMEOUT_MS;
|
|
1598
|
+
if (typeof previousStartupEvidenceTimeout === 'string')
|
|
1599
|
+
process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS = previousStartupEvidenceTimeout;
|
|
1600
|
+
else
|
|
1601
|
+
delete process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
1602
|
+
if (typeof previousStartupDispatchRetries === 'string')
|
|
1603
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES = previousStartupDispatchRetries;
|
|
1604
|
+
else
|
|
1605
|
+
delete process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES;
|
|
1606
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1291
1609
|
it('startTeam records recoverable startup issues per worker instead of failing launch early when panes stay alive', async () => {
|
|
1292
1610
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-no-startup-evidence-'));
|
|
1293
1611
|
const previousTmux = process.env.TMUX;
|
|
@@ -1457,6 +1775,164 @@ process.on('SIGTERM', () => process.exit(0));
|
|
|
1457
1775
|
await rm(cwd, { recursive: true, force: true });
|
|
1458
1776
|
}
|
|
1459
1777
|
});
|
|
1778
|
+
it('startTeam attempts worker-2 before rejecting lowest-index unrecoverable startup failure', async () => {
|
|
1779
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-parallel-dead-pane-'));
|
|
1780
|
+
const previousTmux = process.env.TMUX;
|
|
1781
|
+
const previousTmuxPane = process.env.TMUX_PANE;
|
|
1782
|
+
const previousLaunchMode = process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
1783
|
+
const previousWorkerCli = process.env.OMX_TEAM_WORKER_CLI;
|
|
1784
|
+
const previousReadyTimeout = process.env.OMX_TEAM_READY_TIMEOUT_MS;
|
|
1785
|
+
const previousStartupEvidenceTimeout = process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
1786
|
+
const previousStartupDispatchRetries = process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES;
|
|
1787
|
+
let receiptFailer = null;
|
|
1788
|
+
try {
|
|
1789
|
+
await withMockTmuxFixture({
|
|
1790
|
+
dirPrefix: 'omx-runtime-parallel-dead-pane-bin-',
|
|
1791
|
+
tmuxScript: () => `#!/bin/sh
|
|
1792
|
+
set -eu
|
|
1793
|
+
order_file="${cwd}/dead-pane-order.log"
|
|
1794
|
+
case "$1" in
|
|
1795
|
+
-V)
|
|
1796
|
+
echo "tmux 3.4"
|
|
1797
|
+
exit 0
|
|
1798
|
+
;;
|
|
1799
|
+
display-message)
|
|
1800
|
+
case "$*" in
|
|
1801
|
+
*"#{window_width}"*) echo "120" ;;
|
|
1802
|
+
*) echo "leader:0 %1" ;;
|
|
1803
|
+
esac
|
|
1804
|
+
exit 0
|
|
1805
|
+
;;
|
|
1806
|
+
list-panes)
|
|
1807
|
+
case "$*" in
|
|
1808
|
+
*"pane_current_command"*) printf "%%1\tnode\t'codex'\n" ;;
|
|
1809
|
+
*"-t %2"*"#{pane_dead} #{pane_pid}"*) echo "1 4242" ;;
|
|
1810
|
+
*"-t %3"*"#{pane_dead} #{pane_pid}"*) echo "0 4343" ;;
|
|
1811
|
+
*"#{pane_dead} #{pane_pid}"*) echo "0 4141" ;;
|
|
1812
|
+
*"-t %2"*"#{pane_pid}"*) echo "4242" ;;
|
|
1813
|
+
*"-t %3"*"#{pane_pid}"*) echo "4343" ;;
|
|
1814
|
+
*"#{pane_pid}"*) echo "4141" ;;
|
|
1815
|
+
*) exit 0 ;;
|
|
1816
|
+
esac
|
|
1817
|
+
exit 0
|
|
1818
|
+
;;
|
|
1819
|
+
capture-pane)
|
|
1820
|
+
case "$*" in
|
|
1821
|
+
*"-t %2"*) printf '%s\n' w1-ready-start >> "$order_file" ;;
|
|
1822
|
+
*"-t %3"*) printf '%s\n' w2-ready-start >> "$order_file"; printf 'OpenAI Codex\nmodel: test\n› \n' ;;
|
|
1823
|
+
*) printf 'OpenAI Codex\nmodel: test\n› \n' ;;
|
|
1824
|
+
esac
|
|
1825
|
+
exit 0
|
|
1826
|
+
;;
|
|
1827
|
+
split-window)
|
|
1828
|
+
count_file="${cwd}/split-window-count"
|
|
1829
|
+
count=0
|
|
1830
|
+
if [ -f "$count_file" ]; then count=$(cat "$count_file"); fi
|
|
1831
|
+
count=$((count + 1))
|
|
1832
|
+
printf '%s' "$count" > "$count_file"
|
|
1833
|
+
case "$count" in
|
|
1834
|
+
1) echo "%2" ;;
|
|
1835
|
+
2) echo "%3" ;;
|
|
1836
|
+
*) echo "%4" ;;
|
|
1837
|
+
esac
|
|
1838
|
+
exit 0
|
|
1839
|
+
;;
|
|
1840
|
+
set-hook|run-shell|select-layout|set-window-option|select-pane|send-keys|kill-pane|kill-session|resize-pane)
|
|
1841
|
+
exit 0
|
|
1842
|
+
;;
|
|
1843
|
+
*)
|
|
1844
|
+
exit 0
|
|
1845
|
+
;;
|
|
1846
|
+
esac
|
|
1847
|
+
`,
|
|
1848
|
+
binaries: [{ name: 'codex', content: '#!/usr/bin/env node\nprocess.stdin.resume();\n' }],
|
|
1849
|
+
}, async () => {
|
|
1850
|
+
delete process.env.TMUX;
|
|
1851
|
+
process.env.TMUX_PANE = '%1';
|
|
1852
|
+
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = 'interactive';
|
|
1853
|
+
process.env.OMX_TEAM_WORKER_CLI = 'codex';
|
|
1854
|
+
process.env.OMX_TEAM_READY_TIMEOUT_MS = '300';
|
|
1855
|
+
process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS = '50';
|
|
1856
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES = '1';
|
|
1857
|
+
receiptFailer = setInterval(() => {
|
|
1858
|
+
void (async () => {
|
|
1859
|
+
const requests = await listDispatchRequests('team-parallel-dead-pane', cwd, { kind: 'inbox' }).catch(() => []);
|
|
1860
|
+
for (const request of requests) {
|
|
1861
|
+
if (request.status !== 'pending')
|
|
1862
|
+
continue;
|
|
1863
|
+
await transitionDispatchRequest('team-parallel-dead-pane', request.request_id, 'pending', 'failed', { last_reason: 'test_failed_receipt' }, cwd).catch(() => { });
|
|
1864
|
+
}
|
|
1865
|
+
})();
|
|
1866
|
+
}, 20);
|
|
1867
|
+
await assert.rejects(() => withoutTeamWorkerEnv(() => startTeam('team-parallel-dead-pane', 'worker-2 should be attempted despite worker-1 fatal readiness failure', 'executor', 2, [
|
|
1868
|
+
{ subject: 'w1', description: 'worker one', owner: 'worker-1' },
|
|
1869
|
+
{ subject: 'w2', description: 'worker two', owner: 'worker-2' },
|
|
1870
|
+
], cwd)), /Worker worker-1 did not become ready/);
|
|
1871
|
+
const order = (await readFile(join(cwd, 'dead-pane-order.log'), 'utf-8')).trim().split('\n');
|
|
1872
|
+
assert.ok(order.includes('w1-ready-start'));
|
|
1873
|
+
assert.ok(order.includes('w2-ready-start'));
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
finally {
|
|
1877
|
+
if (receiptFailer)
|
|
1878
|
+
clearInterval(receiptFailer);
|
|
1879
|
+
if (typeof previousTmux === 'string')
|
|
1880
|
+
process.env.TMUX = previousTmux;
|
|
1881
|
+
else
|
|
1882
|
+
delete process.env.TMUX;
|
|
1883
|
+
if (typeof previousTmuxPane === 'string')
|
|
1884
|
+
process.env.TMUX_PANE = previousTmuxPane;
|
|
1885
|
+
else
|
|
1886
|
+
delete process.env.TMUX_PANE;
|
|
1887
|
+
if (typeof previousLaunchMode === 'string')
|
|
1888
|
+
process.env.OMX_TEAM_WORKER_LAUNCH_MODE = previousLaunchMode;
|
|
1889
|
+
else
|
|
1890
|
+
delete process.env.OMX_TEAM_WORKER_LAUNCH_MODE;
|
|
1891
|
+
if (typeof previousWorkerCli === 'string')
|
|
1892
|
+
process.env.OMX_TEAM_WORKER_CLI = previousWorkerCli;
|
|
1893
|
+
else
|
|
1894
|
+
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
1895
|
+
if (typeof previousReadyTimeout === 'string')
|
|
1896
|
+
process.env.OMX_TEAM_READY_TIMEOUT_MS = previousReadyTimeout;
|
|
1897
|
+
else
|
|
1898
|
+
delete process.env.OMX_TEAM_READY_TIMEOUT_MS;
|
|
1899
|
+
if (typeof previousStartupEvidenceTimeout === 'string')
|
|
1900
|
+
process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS = previousStartupEvidenceTimeout;
|
|
1901
|
+
else
|
|
1902
|
+
delete process.env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS;
|
|
1903
|
+
if (typeof previousStartupDispatchRetries === 'string')
|
|
1904
|
+
process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES = previousStartupDispatchRetries;
|
|
1905
|
+
else
|
|
1906
|
+
delete process.env.OMX_TEAM_STARTUP_DISPATCH_RETRIES;
|
|
1907
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
it('settleStartupAttemptResults waits for sibling startup attempt to settle after worker startup throw', async () => {
|
|
1911
|
+
let worker2Settled = false;
|
|
1912
|
+
const startupAttemptResults = await settleStartupAttemptResults([
|
|
1913
|
+
{
|
|
1914
|
+
workerIndex: 1,
|
|
1915
|
+
workerName: 'worker-1',
|
|
1916
|
+
attempt: Promise.reject(new Error('test_startup_attempt_throw:worker-1')),
|
|
1917
|
+
},
|
|
1918
|
+
{
|
|
1919
|
+
workerIndex: 2,
|
|
1920
|
+
workerName: 'worker-2',
|
|
1921
|
+
attempt: new Promise((resolve) => {
|
|
1922
|
+
setTimeout(() => {
|
|
1923
|
+
worker2Settled = true;
|
|
1924
|
+
resolve({ ok: true, workerIndex: 2, workerName: 'worker-2' });
|
|
1925
|
+
}, 100);
|
|
1926
|
+
}),
|
|
1927
|
+
},
|
|
1928
|
+
]);
|
|
1929
|
+
assert.equal(worker2Settled, true, 'worker-2 startup attempt should settle before results return');
|
|
1930
|
+
const firstStartupError = startupAttemptResults
|
|
1931
|
+
.filter((result) => !result.ok)
|
|
1932
|
+
.sort((a, b) => a.workerIndex - b.workerIndex)[0];
|
|
1933
|
+
assert.equal(firstStartupError?.workerName, 'worker-1');
|
|
1934
|
+
assert.match(String(firstStartupError?.error), /test_startup_attempt_throw:worker-1/);
|
|
1935
|
+
});
|
|
1460
1936
|
it('startTeam still fails startup when the worker pane is dead/unrecoverable', async () => {
|
|
1461
1937
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-dead-startup-pane-'));
|
|
1462
1938
|
const previousTmux = process.env.TMUX;
|
|
@@ -4263,8 +4739,19 @@ esac
|
|
|
4263
4739
|
config.workers[0].pid = sleeperPid;
|
|
4264
4740
|
config.workers[0].pane_id = null;
|
|
4265
4741
|
await writeFile(configPath, JSON.stringify(config, null, 2));
|
|
4742
|
+
const manifestPath = join(cwd, '.omx', 'state', 'team', 'team-prompt-resume', 'manifest.v2.json');
|
|
4743
|
+
const manifest = JSON.parse(await readFile(manifestPath, 'utf-8'));
|
|
4744
|
+
manifest.policy.worker_launch_mode = 'prompt';
|
|
4745
|
+
manifest.tmux_session = 'prompt-team-prompt-resume';
|
|
4746
|
+
manifest.leader_pane_id = null;
|
|
4747
|
+
manifest.hud_pane_id = null;
|
|
4748
|
+
manifest.workers[0].pid = sleeperPid;
|
|
4749
|
+
manifest.workers[0].pane_id = null;
|
|
4750
|
+
await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
4266
4751
|
const runtime = await resumeTeam('team-prompt-resume', cwd);
|
|
4267
4752
|
assert.equal(runtime, null);
|
|
4753
|
+
const events = await readTeamEvents('team-prompt-resume', cwd);
|
|
4754
|
+
assert.ok(events.some((event) => event.reason === `prompt_resume_unavailable:missing_handle:worker-1:${sleeperPid}`), 'resumeTeam should persist an explicit missing-handle diagnostic event');
|
|
4268
4755
|
}
|
|
4269
4756
|
finally {
|
|
4270
4757
|
if (sleeperPid > 0) {
|
|
@@ -4365,6 +4852,119 @@ esac
|
|
|
4365
4852
|
await rm(cwd, { recursive: true, force: true });
|
|
4366
4853
|
}
|
|
4367
4854
|
});
|
|
4855
|
+
it('startTeam persists synthesized delegation plans for broad tasks', async () => {
|
|
4856
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-'));
|
|
4857
|
+
const binDir = join(cwd, 'bin');
|
|
4858
|
+
const fakeCodexPath = join(binDir, 'codex');
|
|
4859
|
+
await mkdir(binDir, { recursive: true });
|
|
4860
|
+
await writeFakePromptWorkerBinary(fakeCodexPath, `setTimeout(() => {}, 5000);`);
|
|
4861
|
+
let runtime = null;
|
|
4862
|
+
try {
|
|
4863
|
+
runtime = await withPromptModeCodexEnv(binDir, {}, () => withoutTeamWorkerEnv(() => startTeam('team-delegation-persist', 'delegation persistence test', 'executor', 1, [{ subject: 'Investigate runtime assignment', description: 'Search runtime and debug assignTask behavior' }], cwd)));
|
|
4864
|
+
const task = await readTask('team-delegation-persist', '1', cwd);
|
|
4865
|
+
assert.equal(task?.delegation?.mode, 'auto');
|
|
4866
|
+
assert.equal(task?.delegation?.child_model, 'gpt-5.4-mini');
|
|
4867
|
+
assert.equal(task?.delegation?.required_parallel_probe, true);
|
|
4868
|
+
}
|
|
4869
|
+
finally {
|
|
4870
|
+
if (runtime) {
|
|
4871
|
+
await shutdownTeam(runtime.teamName, cwd, { force: true }).catch(() => { });
|
|
4872
|
+
}
|
|
4873
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4874
|
+
}
|
|
4875
|
+
});
|
|
4876
|
+
it('startTeam remaps repo-aware DAG dependencies after concrete task IDs are created', async () => {
|
|
4877
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-'));
|
|
4878
|
+
const binDir = join(cwd, 'bin');
|
|
4879
|
+
const fakeCodexPath = join(binDir, 'codex');
|
|
4880
|
+
await mkdir(binDir, { recursive: true });
|
|
4881
|
+
await writeFakePromptWorkerBinary(fakeCodexPath, `setTimeout(() => {}, 5000);`);
|
|
4882
|
+
let runtime = null;
|
|
4883
|
+
try {
|
|
4884
|
+
runtime = await withPromptModeCodexEnv(binDir, {}, () => withoutTeamWorkerEnv(() => startTeam('team-dag-remap', 'repo-aware DAG remap test', 'executor', 2, [
|
|
4885
|
+
{
|
|
4886
|
+
subject: 'Implement runtime',
|
|
4887
|
+
description: 'Change runtime',
|
|
4888
|
+
owner: 'worker-1',
|
|
4889
|
+
role: 'executor',
|
|
4890
|
+
symbolic_id: 'impl',
|
|
4891
|
+
symbolic_depends_on: [],
|
|
4892
|
+
lane: 'implementation',
|
|
4893
|
+
filePaths: ['src/team/runtime.ts'],
|
|
4894
|
+
allocation_reason: 'balances current load',
|
|
4895
|
+
},
|
|
4896
|
+
{
|
|
4897
|
+
subject: 'Verify runtime',
|
|
4898
|
+
description: 'Test runtime',
|
|
4899
|
+
owner: 'worker-2',
|
|
4900
|
+
role: 'test-engineer',
|
|
4901
|
+
symbolic_id: 'verify',
|
|
4902
|
+
symbolic_depends_on: ['impl'],
|
|
4903
|
+
lane: 'verification',
|
|
4904
|
+
allocation_reason: 'keeps blocked work on a lighter lane',
|
|
4905
|
+
},
|
|
4906
|
+
], cwd, {
|
|
4907
|
+
decompositionMetadata: {
|
|
4908
|
+
decomposition_source: 'dag_sidecar',
|
|
4909
|
+
worker_count_requested: 2,
|
|
4910
|
+
worker_count_effective: 2,
|
|
4911
|
+
worker_count_source: 'plan-suggested',
|
|
4912
|
+
ready_lane_count: 1,
|
|
4913
|
+
useful_lane_count: 2,
|
|
4914
|
+
allocation_reasons: {
|
|
4915
|
+
impl: 'balances current load',
|
|
4916
|
+
verify: 'keeps blocked work on a lighter lane',
|
|
4917
|
+
},
|
|
4918
|
+
node_dependencies: {
|
|
4919
|
+
impl: [],
|
|
4920
|
+
verify: ['impl'],
|
|
4921
|
+
},
|
|
4922
|
+
},
|
|
4923
|
+
})));
|
|
4924
|
+
const first = await readTask('team-dag-remap', '1', cwd);
|
|
4925
|
+
const second = await readTask('team-dag-remap', '2', cwd);
|
|
4926
|
+
assert.deepEqual(first?.depends_on, []);
|
|
4927
|
+
assert.deepEqual(first?.blocked_by, undefined);
|
|
4928
|
+
assert.deepEqual(second?.depends_on, ['1']);
|
|
4929
|
+
assert.deepEqual(second?.blocked_by, ['1']);
|
|
4930
|
+
const report = JSON.parse(await readFile(join(cwd, '.omx', 'state', 'team', 'team-dag-remap', 'decomposition-report.json'), 'utf-8'));
|
|
4931
|
+
assert.deepEqual(report.node_id_to_task_id, { impl: '1', verify: '2' });
|
|
4932
|
+
assert.deepEqual(report.task_hints?.['2']?.depends_on, ['1']);
|
|
4933
|
+
assert.deepEqual(report.task_hints?.['2']?.symbolic_depends_on, ['impl']);
|
|
4934
|
+
const inbox = await readFile(join(cwd, '.omx', 'state', 'team', 'team-dag-remap', 'workers', 'worker-2', 'inbox.md'), 'utf-8');
|
|
4935
|
+
assert.match(inbox, /Blocked by: 1/);
|
|
4936
|
+
assert.doesNotMatch(inbox, /Blocked by: impl/);
|
|
4937
|
+
assert.doesNotMatch(inbox, /Depends on: impl/);
|
|
4938
|
+
}
|
|
4939
|
+
finally {
|
|
4940
|
+
if (runtime) {
|
|
4941
|
+
await shutdownTeam(runtime.teamName, cwd, { force: true }).catch(() => { });
|
|
4942
|
+
}
|
|
4943
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4944
|
+
}
|
|
4945
|
+
});
|
|
4946
|
+
it('assignTask synthesizes delegation before follow-up dispatch rollback', async () => {
|
|
4947
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-'));
|
|
4948
|
+
try {
|
|
4949
|
+
await initTeamState('team-assign-delegation', 'assignment delegation test', 'executor', 1, cwd);
|
|
4950
|
+
const config = await readTeamConfig('team-assign-delegation', cwd);
|
|
4951
|
+
assert.ok(config);
|
|
4952
|
+
config.worker_launch_mode = 'prompt';
|
|
4953
|
+
await saveTeamConfig(config, cwd);
|
|
4954
|
+
const task = await createTask('team-assign-delegation', { subject: 'Investigate follow-up assignment', description: 'Search repo and debug follow-up assignment behavior', status: 'pending' }, cwd);
|
|
4955
|
+
await writeWorkerInbox('team-assign-delegation', 'worker-1', 'existing inbox', cwd);
|
|
4956
|
+
await assert.rejects(() => assignTask('team-assign-delegation', 'worker-1', task.id, cwd), /worker_notify_failed/);
|
|
4957
|
+
const reread = await readTask('team-assign-delegation', task.id, cwd);
|
|
4958
|
+
assert.equal(reread?.delegation?.mode, 'auto');
|
|
4959
|
+
assert.equal(reread?.delegation?.child_model, 'gpt-5.4-mini');
|
|
4960
|
+
const inbox = await readFile(join(cwd, '.omx', 'state', 'team', 'team-assign-delegation', 'workers', 'worker-1', 'inbox.md'), 'utf-8');
|
|
4961
|
+
assert.match(inbox, /Assignment Cancelled/);
|
|
4962
|
+
assert.match(inbox, /worker_notify_failed/);
|
|
4963
|
+
}
|
|
4964
|
+
finally {
|
|
4965
|
+
await rm(cwd, { recursive: true, force: true });
|
|
4966
|
+
}
|
|
4967
|
+
});
|
|
4368
4968
|
it('monitorTeam does not re-notify already-notified mailbox messages (issue #116)', async () => {
|
|
4369
4969
|
// Regression: deliverPendingMailboxMessages used to re-notify every 15 s via shouldRetry.
|
|
4370
4970
|
// After the fix it must NOT re-notify messages that already have notified_at set.
|
|
@@ -4715,7 +5315,7 @@ esac
|
|
|
4715
5315
|
await rm(cwd, { recursive: true, force: true });
|
|
4716
5316
|
}
|
|
4717
5317
|
});
|
|
4718
|
-
it('sendWorkerMessage transport_direct
|
|
5318
|
+
it('sendWorkerMessage transport_direct fails fast for leader-fixed when leader_pane_id missing', async () => {
|
|
4719
5319
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-runtime-leader-direct-'));
|
|
4720
5320
|
try {
|
|
4721
5321
|
await initTeamState('team-leader-direct', 'leader direct transport test', 'executor', 1, cwd);
|
|
@@ -4729,14 +5329,23 @@ esac
|
|
|
4729
5329
|
const manifest = JSON.parse(await readFile(manifestPath, 'utf-8'));
|
|
4730
5330
|
manifest.policy = { ...(manifest.policy || {}), dispatch_mode: 'transport_direct' };
|
|
4731
5331
|
await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
4732
|
-
await sendWorkerMessage('team-leader-direct', 'worker-1', 'leader-fixed', 'hello leader direct', cwd);
|
|
5332
|
+
await assert.rejects(sendWorkerMessage('team-leader-direct', 'worker-1', 'leader-fixed', 'hello leader direct', cwd), /mailbox_notify_failed:leader_pane_missing_transport_direct_failed/);
|
|
4733
5333
|
const mailbox = await listMailboxMessages('team-leader-direct', 'leader-fixed', cwd);
|
|
4734
5334
|
assert.ok(mailbox.length >= 1, `expected at least 1 mailbox message, got ${mailbox.length}`);
|
|
4735
5335
|
const requests = await listDispatchRequests('team-leader-direct', cwd, { kind: 'mailbox', to_worker: 'leader-fixed' });
|
|
4736
5336
|
assert.ok(requests.length >= 1, `expected at least 1 leader-fixed dispatch request, got ${requests.length}`);
|
|
4737
5337
|
const latest = requests[requests.length - 1];
|
|
4738
|
-
assert.equal(latest?.status, '
|
|
4739
|
-
assert.equal(latest?.last_reason, '
|
|
5338
|
+
assert.equal(latest?.status, 'failed');
|
|
5339
|
+
assert.equal(latest?.last_reason, 'leader_pane_missing_transport_direct_failed');
|
|
5340
|
+
assert.ok(latest?.failed_at, 'missing leader pane should fail fast with failed_at evidence');
|
|
5341
|
+
const deliveryLog = await readTeamDeliveryLog(cwd);
|
|
5342
|
+
const runtimeEntries = deliveryLog.filter((entry) => entry.event === 'dispatch_result'
|
|
5343
|
+
&& entry.source === 'team.runtime'
|
|
5344
|
+
&& entry.to_worker === 'leader-fixed'
|
|
5345
|
+
&& entry.transport === 'mailbox'
|
|
5346
|
+
&& entry.result === 'failed'
|
|
5347
|
+
&& entry.reason === 'leader_pane_missing_transport_direct_failed');
|
|
5348
|
+
assert.equal(runtimeEntries.length, 1, 'leader direct missing-pane failure should emit exactly one runtime dispatch_result entry');
|
|
4740
5349
|
}
|
|
4741
5350
|
finally {
|
|
4742
5351
|
await rm(cwd, { recursive: true, force: true });
|