oh-my-codex 0.15.2 → 0.16.0
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 +10 -7
- package/Cargo.toml +1 -1
- package/README.md +3 -0
- package/crates/omx-explore/Cargo.toml +3 -0
- package/crates/omx-explore/src/main.rs +517 -16
- package/dist/agents/__tests__/native-config.test.js +33 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/autoresearch/goal.d.ts +90 -0
- package/dist/autoresearch/goal.d.ts.map +1 -0
- package/dist/autoresearch/goal.js +237 -0
- package/dist/autoresearch/goal.js.map +1 -0
- package/dist/autoresearch/skill-validation.d.ts +1 -0
- package/dist/autoresearch/skill-validation.d.ts.map +1 -1
- package/dist/autoresearch/skill-validation.js +10 -3
- package/dist/autoresearch/skill-validation.js.map +1 -1
- package/dist/catalog/__tests__/generator.test.js +9 -4
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +29 -2
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/catalog/__tests__/schema.test.js +14 -3
- package/dist/catalog/__tests__/schema.test.js.map +1 -1
- package/dist/catalog/schema.js +1 -1
- package/dist/catalog/schema.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-goal.test.d.ts +2 -0
- package/dist/cli/__tests__/autoresearch-goal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/autoresearch-goal.test.js +194 -0
- package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -0
- package/dist/cli/__tests__/cleanup.test.js +82 -1
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -4
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js +122 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +25 -2
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +1 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +48 -18
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +222 -10
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +58 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-serve.test.js +27 -1
- package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
- package/dist/cli/__tests__/native-assets.test.js +26 -1
- package/dist/cli/__tests__/native-assets.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +2 -2
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/performance-goal.test.d.ts +2 -0
- package/dist/cli/__tests__/performance-goal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/performance-goal.test.js +144 -0
- package/dist/cli/__tests__/performance-goal.test.js.map +1 -0
- package/dist/cli/__tests__/question.test.js +8 -0
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +31 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +5 -4
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-prd-smoke.test.js +7 -0
- package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +59 -1
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +57 -21
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +27 -8
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +20 -10
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skill-validation.test.js +11 -11
- package/dist/cli/__tests__/setup-skill-validation.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +12 -12
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +242 -10
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.d.ts +2 -0
- package/dist/cli/__tests__/ultragoal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ultragoal.test.js +106 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -0
- package/dist/cli/__tests__/uninstall.test.js +11 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/autoresearch-goal.d.ts +3 -0
- package/dist/cli/autoresearch-goal.d.ts.map +1 -0
- package/dist/cli/autoresearch-goal.js +175 -0
- package/dist/cli/autoresearch-goal.js.map +1 -0
- package/dist/cli/cleanup.d.ts +3 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +42 -2
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +95 -3
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +10 -2
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +21 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +268 -30
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-serve.d.ts +1 -0
- package/dist/cli/mcp-serve.d.ts.map +1 -1
- package/dist/cli/mcp-serve.js +8 -0
- package/dist/cli/mcp-serve.js.map +1 -1
- package/dist/cli/native-assets.js +1 -1
- package/dist/cli/native-assets.js.map +1 -1
- package/dist/cli/performance-goal.d.ts +3 -0
- package/dist/cli/performance-goal.d.ts.map +1 -0
- package/dist/cli/performance-goal.js +186 -0
- package/dist/cli/performance-goal.js.map +1 -0
- package/dist/cli/ralph.d.ts +2 -0
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +25 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +13 -6
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts +6 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +113 -33
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +2 -1
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +3 -0
- package/dist/cli/ultragoal.d.ts.map +1 -0
- package/dist/cli/ultragoal.js +191 -0
- package/dist/cli/ultragoal.js.map +1 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +4 -2
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +39 -6
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +5 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/commit-lore-guard.d.ts +3 -0
- package/dist/config/commit-lore-guard.d.ts.map +1 -0
- package/dist/config/commit-lore-guard.js +9 -0
- package/dist/config/commit-lore-guard.js.map +1 -0
- package/dist/config/generator.d.ts +14 -4
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +166 -66
- package/dist/config/generator.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +1 -0
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
- package/dist/config/omx-first-party-mcp.js +4 -1
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/goal-workflows/__tests__/artifacts.test.d.ts +2 -0
- package/dist/goal-workflows/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/goal-workflows/__tests__/artifacts.test.js +96 -0
- package/dist/goal-workflows/__tests__/artifacts.test.js.map +1 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts +2 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts.map +1 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +54 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -0
- package/dist/goal-workflows/artifacts.d.ts +62 -0
- package/dist/goal-workflows/artifacts.d.ts.map +1 -0
- package/dist/goal-workflows/artifacts.js +132 -0
- package/dist/goal-workflows/artifacts.js.map +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +28 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.js +110 -0
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -0
- package/dist/goal-workflows/handoff.d.ts +10 -0
- package/dist/goal-workflows/handoff.d.ts.map +1 -0
- package/dist/goal-workflows/handoff.js +31 -0
- package/dist/goal-workflows/handoff.js.map +1 -0
- package/dist/goal-workflows/validation.d.ts +13 -0
- package/dist/goal-workflows/validation.d.ts.map +1 -0
- package/dist/goal-workflows/validation.js +36 -0
- package/dist/goal-workflows/validation.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +59 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.js +109 -18
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +45 -32
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +3 -3
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +2 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +17 -24
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +3 -3
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/task-size-detector.test.js +1 -1
- package/dist/hooks/__tests__/task-size-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-ralph-skill.test.js +3 -3
- package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.js +7 -11
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +23 -2
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +12 -13
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +2 -10
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +0 -4
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.js +2 -2
- package/dist/hooks/session.js.map +1 -1
- package/dist/hooks/task-size-detector.d.ts.map +1 -1
- package/dist/hooks/task-size-detector.js +1 -0
- package/dist/hooks/task-size-detector.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +30 -14
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +29 -7
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/reconcile.d.ts +2 -1
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +12 -0
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +15 -2
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +54 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +36 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +9 -7
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +17 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +36 -2
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +26 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/base.d.ts +1 -0
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +35 -5
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/http-client.test.d.ts +2 -0
- package/dist/notifications/__tests__/http-client.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/http-client.test.js +90 -0
- package/dist/notifications/__tests__/http-client.test.js.map +1 -0
- package/dist/notifications/__tests__/notifier.test.js +22 -60
- package/dist/notifications/__tests__/notifier.test.js.map +1 -1
- package/dist/notifications/dispatcher.d.ts.map +1 -1
- package/dist/notifications/dispatcher.js +35 -60
- package/dist/notifications/dispatcher.js.map +1 -1
- package/dist/notifications/http-client.d.ts +22 -0
- package/dist/notifications/http-client.d.ts.map +1 -0
- package/dist/notifications/http-client.js +298 -0
- package/dist/notifications/http-client.js.map +1 -0
- package/dist/notifications/notifier.d.ts +3 -2
- package/dist/notifications/notifier.d.ts.map +1 -1
- package/dist/notifications/notifier.js +17 -22
- package/dist/notifications/notifier.js.map +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +63 -2
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +3 -2
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/performance-goal/artifacts.d.ts +76 -0
- package/dist/performance-goal/artifacts.d.ts.map +1 -0
- package/dist/performance-goal/artifacts.js +221 -0
- package/dist/performance-goal/artifacts.js.map +1 -0
- package/dist/pipeline/__tests__/stages.test.js +423 -14
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/stages/team-exec.d.ts +8 -4
- package/dist/pipeline/stages/team-exec.d.ts.map +1 -1
- package/dist/pipeline/stages/team-exec.js +181 -13
- package/dist/pipeline/stages/team-exec.js.map +1 -1
- package/dist/planning/__tests__/artifacts.test.js +261 -1
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/artifact-names.d.ts +13 -0
- package/dist/planning/artifact-names.d.ts.map +1 -0
- package/dist/planning/artifact-names.js +108 -0
- package/dist/planning/artifact-names.js.map +1 -0
- package/dist/planning/artifacts.d.ts +23 -1
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +171 -59
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/ralph/__tests__/persistence.test.js +21 -1
- package/dist/ralph/__tests__/persistence.test.js.map +1 -1
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +6 -4
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/ralplan/__tests__/runtime.test.js +2 -0
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +6 -0
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +1749 -88
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js +33 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
- package/dist/scripts/__tests__/run-test-files.test.js +36 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +570 -45
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts +7 -0
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +341 -15
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/hook-derived-watcher.js +2 -1
- package/dist/scripts/hook-derived-watcher.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +2 -1
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/orchestration-intent.d.ts +1 -2
- package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
- package/dist/scripts/notify-hook/orchestration-intent.js +2 -3
- package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts +0 -2
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +8 -60
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts +15 -0
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker-stop.js +224 -0
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +26 -18
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook.js +1 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-test-files.js +17 -1
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts +1 -0
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +10 -4
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +26 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +76 -0
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/operations.d.ts +3 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +8 -4
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +1 -0
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +54 -13
- package/dist/state/skill-active.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +279 -0
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.d.ts +2 -0
- package/dist/team/__tests__/approved-execution.test.d.ts.map +1 -0
- package/dist/team/__tests__/approved-execution.test.js +124 -0
- package/dist/team/__tests__/approved-execution.test.js.map +1 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +2 -4
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
- package/dist/team/__tests__/delivery-log.test.d.ts +2 -0
- package/dist/team/__tests__/delivery-log.test.d.ts.map +1 -0
- package/dist/team/__tests__/delivery-log.test.js +44 -0
- package/dist/team/__tests__/delivery-log.test.js.map +1 -0
- package/dist/team/__tests__/model-contract.test.js +40 -9
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.js +41 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -1
- package/dist/team/__tests__/role-router.test.js +4 -4
- package/dist/team/__tests__/role-router.test.js.map +1 -1
- package/dist/team/__tests__/runtime-boxed-state.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-boxed-state.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-boxed-state.test.js +39 -0
- package/dist/team/__tests__/runtime-boxed-state.test.js.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.js +24 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +563 -72
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +13 -0
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +13 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-identity.test.d.ts +2 -0
- package/dist/team/__tests__/team-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-identity.test.js +166 -0
- package/dist/team/__tests__/team-identity.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session.test.js +58 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +62 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/api-interop.d.ts +1 -0
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +163 -132
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/approved-execution.d.ts +37 -0
- package/dist/team/approved-execution.d.ts.map +1 -0
- package/dist/team/approved-execution.js +136 -0
- package/dist/team/approved-execution.js.map +1 -0
- package/dist/team/delivery-log.d.ts +1 -1
- package/dist/team/delivery-log.d.ts.map +1 -1
- package/dist/team/delivery-log.js +2 -1
- package/dist/team/delivery-log.js.map +1 -1
- package/dist/team/followup-planner.js +2 -2
- package/dist/team/followup-planner.js.map +1 -1
- package/dist/team/goal-workflow.d.ts +20 -0
- package/dist/team/goal-workflow.d.ts.map +1 -0
- package/dist/team/goal-workflow.js +57 -0
- package/dist/team/goal-workflow.js.map +1 -0
- package/dist/team/orchestrator.js +2 -2
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/repo-aware-decomposition.d.ts +3 -0
- package/dist/team/repo-aware-decomposition.d.ts.map +1 -1
- package/dist/team/repo-aware-decomposition.js +2 -0
- package/dist/team/repo-aware-decomposition.js.map +1 -1
- package/dist/team/role-router.js +5 -5
- package/dist/team/role-router.js.map +1 -1
- package/dist/team/runtime-cli.d.ts +32 -2
- package/dist/team/runtime-cli.d.ts.map +1 -1
- package/dist/team/runtime-cli.js +78 -26
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime.d.ts +7 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +383 -40
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +2 -0
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state.d.ts +9 -0
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +21 -0
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-identity.d.ts +26 -0
- package/dist/team/team-identity.d.ts.map +1 -0
- package/dist/team/team-identity.js +169 -0
- package/dist/team/team-identity.js.map +1 -0
- package/dist/team/tmux-session.d.ts +18 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +65 -3
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +4 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +28 -2
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/artifacts.test.js +93 -0
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -0
- package/dist/ultragoal/artifacts.d.ts +89 -0
- package/dist/ultragoal/artifacts.d.ts.map +1 -0
- package/dist/ultragoal/artifacts.js +233 -0
- package/dist/ultragoal/artifacts.js.map +1 -0
- package/dist/utils/__tests__/agents-model-table.test.js +3 -1
- package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +31 -1
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/agents-model-table.d.ts.map +1 -1
- package/dist/utils/agents-model-table.js +12 -1
- package/dist/utils/agents-model-table.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +23 -7
- package/dist/utils/paths.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +30 -19
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +5 -5
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +30 -5
- package/plugins/oh-my-codex/skills/ask/SKILL.md +58 -0
- package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +36 -0
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/performance-goal/SKILL.md +65 -0
- package/plugins/oh-my-codex/skills/plan/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -3
- package/plugins/oh-my-codex/skills/team/SKILL.md +6 -2
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +49 -0
- package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +9 -9
- package/prompts/api-reviewer.md +1 -1
- package/prompts/code-reviewer.md +2 -0
- package/prompts/performance-reviewer.md +1 -1
- package/prompts/quality-reviewer.md +1 -1
- package/prompts/quality-strategist.md +2 -2
- package/prompts/style-reviewer.md +1 -1
- package/prompts/test-engineer.md +1 -1
- package/skills/ai-slop-cleaner/SKILL.md +30 -5
- package/skills/ask/SKILL.md +58 -0
- package/skills/ask-claude/SKILL.md +3 -54
- package/skills/ask-gemini/SKILL.md +3 -54
- package/skills/autoresearch-goal/SKILL.md +36 -0
- package/skills/build-fix/SKILL.md +4 -139
- package/skills/deepsearch/SKILL.md +4 -32
- package/skills/ecomode/SKILL.md +4 -108
- package/skills/help/SKILL.md +4 -196
- package/skills/note/SKILL.md +4 -56
- package/skills/omx-setup/SKILL.md +2 -2
- package/skills/performance-goal/SKILL.md +65 -0
- package/skills/plan/SKILL.md +1 -1
- package/skills/ralph/SKILL.md +22 -3
- package/skills/ralph-init/SKILL.md +4 -40
- package/skills/review/SKILL.md +4 -32
- package/skills/security-review/SKILL.md +4 -294
- package/skills/swarm/SKILL.md +4 -19
- package/skills/tdd/SKILL.md +4 -100
- package/skills/team/SKILL.md +6 -2
- package/skills/trace/SKILL.md +4 -27
- package/skills/ultragoal/SKILL.md +49 -0
- package/skills/visual-ralph/SKILL.md +9 -9
- package/skills/visual-verdict/SKILL.md +4 -70
- package/skills/web-clone/SKILL.md +4 -18
- package/src/scripts/__tests__/codex-native-hook.test.ts +2923 -1030
- package/src/scripts/__tests__/hook-derived-watcher.test.ts +45 -1
- package/src/scripts/__tests__/run-test-files.test.ts +46 -0
- package/src/scripts/codex-native-hook.ts +696 -46
- package/src/scripts/codex-native-pre-post.ts +369 -16
- package/src/scripts/hook-derived-watcher.ts +2 -1
- package/src/scripts/notify-fallback-watcher.ts +2 -1
- package/src/scripts/notify-hook/orchestration-intent.ts +1 -3
- package/src/scripts/notify-hook/team-leader-nudge.ts +7 -63
- package/src/scripts/notify-hook/team-worker-posttooluse.ts +1 -1
- package/src/scripts/notify-hook/team-worker-stop.ts +246 -0
- package/src/scripts/notify-hook/team-worker.ts +23 -14
- package/src/scripts/notify-hook.ts +1 -1
- package/src/scripts/run-test-files.ts +20 -1
- package/src/scripts/sync-plugin-mirror.ts +13 -4
- package/templates/catalog-manifest.json +45 -27
- package/plugins/oh-my-codex/skills/ask-claude/SKILL.md +0 -61
- package/plugins/oh-my-codex/skills/ask-gemini/SKILL.md +0 -61
- package/plugins/oh-my-codex/skills/help/SKILL.md +0 -202
- package/plugins/oh-my-codex/skills/note/SKILL.md +0 -62
- package/plugins/oh-my-codex/skills/security-review/SKILL.md +0 -300
- package/plugins/oh-my-codex/skills/trace/SKILL.md +0 -33
- package/plugins/oh-my-codex/skills/visual-verdict/SKILL.md +0 -76
package/dist/team/runtime.js
CHANGED
|
@@ -3,25 +3,28 @@ import { existsSync, appendFileSync, mkdirSync } from 'fs';
|
|
|
3
3
|
import { mkdir, readdir, readFile, writeFile } from 'fs/promises';
|
|
4
4
|
import { performance } from 'perf_hooks';
|
|
5
5
|
import { spawn, spawnSync } from 'child_process';
|
|
6
|
-
import { sanitizeTeamName, isTmuxAvailable, hasCurrentTmuxClientContext, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, waitForWorkerReadyAsync, dismissTrustPromptIfPresent, sendToWorker, sendToWorkerStdin, isWorkerAlive, isWorkerPaneOpen, getWorkerPanePid, killWorkerByPaneIdAsync, restoreStandaloneHudPane, teardownWorkerPanes, unregisterResizeHook, destroyTeamSession, listPaneIds, listTeamSessions, resolveSharedSessionShutdownTopology, } from './tmux-session.js';
|
|
7
|
-
import { teamInit as initTeamState, DEFAULT_MAX_WORKERS, teamReadConfig as readTeamConfig, teamWriteWorkerIdentity as writeWorkerIdentity, teamReadWorkerHeartbeat as readWorkerHeartbeat, teamReadWorkerStatus as readWorkerStatus, teamWriteWorkerInbox as writeWorkerInbox, teamCreateTask as createStateTask, teamReadTask as readTask, teamListTasks as listTasks, teamUpdateTask as updateTask, teamReadManifest as readTeamManifestV2, teamNormalizeGovernance as normalizeTeamGovernance, teamNormalizePolicy as normalizeTeamPolicy, teamClaimTask as claimTask, teamReleaseTaskClaim as releaseTaskClaim, teamReclaimExpiredTaskClaim as reclaimExpiredTaskClaim, teamAppendEvent as appendTeamEvent, teamReadTaskApproval as readTaskApproval, teamListMailbox as listMailboxMessages, teamMarkMessageDelivered as markMessageDelivered, teamMarkMessageNotified as markMessageNotified, teamEnqueueDispatchRequest as enqueueDispatchRequest, teamMarkDispatchRequestNotified as markDispatchRequestNotified, teamTransitionDispatchRequest as transitionDispatchRequest, teamReadDispatchRequest as readDispatchRequest, teamCleanup as cleanupTeamState, teamSaveConfig as saveTeamConfig, teamWriteShutdownRequest as writeShutdownRequest, teamReadShutdownAck as readShutdownAck, teamReadMonitorSnapshot as readMonitorSnapshot, teamWriteMonitorSnapshot as writeMonitorSnapshot, teamReadPhase as readTeamPhaseState, teamWritePhase as writeTeamPhaseState, teamWriteWorkerStatus as writeWorkerStatus, } from './team-ops.js';
|
|
6
|
+
import { sanitizeTeamName, isTmuxAvailable, hasCurrentTmuxClientContext, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, waitForWorkerReadyAsync, dismissTrustPromptIfPresent, evaluateStartupDirectTriggerSafety, sendToWorker, sendToWorkerStdin, isWorkerAlive, isWorkerPaneOpen, getWorkerPanePid, killWorkerByPaneIdAsync, restoreStandaloneHudPane, teardownWorkerPanes, unregisterResizeHook, destroyTeamSession, listPaneIds, listTeamSessions, resolveSharedSessionShutdownTopology, } from './tmux-session.js';
|
|
7
|
+
import { teamInit as initTeamState, DEFAULT_MAX_WORKERS, teamReadConfig as readTeamConfig, teamWriteWorkerIdentity as writeWorkerIdentity, teamReadWorkerHeartbeat as readWorkerHeartbeat, teamReadWorkerStatus as readWorkerStatus, teamWriteWorkerInbox as writeWorkerInbox, teamCreateTask as createStateTask, teamReadTask as readTask, teamListTasks as listTasks, teamUpdateTask as updateTask, teamReadManifest as readTeamManifestV2, teamNormalizeGovernance as normalizeTeamGovernance, teamNormalizePolicy as normalizeTeamPolicy, teamClaimTask as claimTask, teamReleaseTaskClaim as releaseTaskClaim, teamReclaimExpiredTaskClaim as reclaimExpiredTaskClaim, teamAppendEvent as appendTeamEvent, teamReadTaskApproval as readTaskApproval, teamListMailbox as listMailboxMessages, teamMarkMessageDelivered as markMessageDelivered, teamMarkMessageNotified as markMessageNotified, teamEnqueueDispatchRequest as enqueueDispatchRequest, teamMarkDispatchRequestNotified as markDispatchRequestNotified, teamTransitionDispatchRequest as transitionDispatchRequest, teamReadDispatchRequest as readDispatchRequest, teamCleanup as cleanupTeamState, teamSaveConfig as saveTeamConfig, teamWriteShutdownRequest as writeShutdownRequest, teamReadShutdownAck as readShutdownAck, teamReadMonitorSnapshot as readMonitorSnapshot, teamWriteMonitorSnapshot as writeMonitorSnapshot, teamReadPhase as readTeamPhaseState, teamWritePhase as writeTeamPhaseState, teamWriteWorkerStatus as writeWorkerStatus, writeAtomic, } from './team-ops.js';
|
|
8
8
|
import { queueInboxInstruction, queueDirectMailboxMessage, queueBroadcastMailboxMessage, waitForDispatchReceipt, } from './mcp-comm.js';
|
|
9
9
|
import { appendTeamDeliveryLogForCwd } from './delivery-log.js';
|
|
10
10
|
import { remapRepoAwareDecompositionMetadataToCreatedTasks, } from './repo-aware-decomposition.js';
|
|
11
11
|
import { generateWorkerOverlay, writeTeamWorkerInstructionsFile, removeTeamWorkerInstructionsFile, writeWorkerWorktreeRootAgentsFile, removeWorkerWorktreeRootAgentsFile, generateInitialInbox, generateTaskAssignmentInbox, generateShutdownInbox, buildTriggerDirective, buildMailboxTriggerDirective, buildLeaderMailboxTriggerDirective, writeWorkerRoleInstructionsFile, } from './worker-bootstrap.js';
|
|
12
|
+
import { buildTeamWorkerGoalInstruction } from './goal-workflow.js';
|
|
12
13
|
import { synthesizeDelegationPlan } from './delegation-policy.js';
|
|
13
14
|
import { loadRolePrompt } from './role-router.js';
|
|
14
15
|
import { composeRoleInstructionsForRole } from '../agents/native-config.js';
|
|
15
|
-
import { codexPromptsDir } from '../utils/paths.js';
|
|
16
|
+
import { codexPromptsDir, omxStateDir } from '../utils/paths.js';
|
|
16
17
|
import { isTerminalPhase } from './orchestrator.js';
|
|
17
18
|
import { resolveTeamWorkerLaunchArgs, TEAM_LOW_COMPLEXITY_DEFAULT_MODEL, parseTeamWorkerLaunchArgs, splitWorkerLaunchArgs, resolveAgentDefaultModel, resolveAgentReasoningEffort, } from './model-contract.js';
|
|
18
19
|
import { resolveCanonicalTeamStateRoot } from './state-root.js';
|
|
20
|
+
import { buildInternalTeamName, resolveTeamIdentityScope, resolveTeamNameForCurrentContext } from './team-identity.js';
|
|
19
21
|
import { inferPhaseTargetFromTaskCounts, reconcilePhaseStateForMonitor } from './phase-controller.js';
|
|
20
22
|
import { getTeamTmuxSessions } from '../notifications/tmux.js';
|
|
21
23
|
import { hasStructuredVerificationEvidence } from '../verification/verifier.js';
|
|
22
24
|
import { buildRebalanceDecisions } from './rebalance-policy.js';
|
|
23
25
|
import { getStatePath } from '../mcp/state-paths.js';
|
|
24
26
|
import { readModeState, updateModeState } from '../modes/base.js';
|
|
27
|
+
import { buildApprovedTeamExecutionBinding, normalizeApprovedTeamExecutionBinding, readApprovedTeamExecutionHintFromBinding, resolvePersistedApprovedTeamExecutionContinuityState, writePersistedApprovedTeamExecutionBinding, } from './approved-execution.js';
|
|
25
28
|
import { appendTeamCommitHygieneEntries, buildTeamCommitHygieneContext, resolveTeamCommitHygieneArtifactCwd, writeTeamCommitHygieneContext, } from './commit-hygiene.js';
|
|
26
29
|
import { assertCleanLeaderWorkspaceForWorkerWorktrees, ensureWorktree, isGitRepository, isWorktreeDirty, planWorktreeTarget, removeWorktreeForce, rollbackProvisionedWorktrees, } from './worktree.js';
|
|
27
30
|
import { cleanupOmxMcpProcesses, findLaunchSafeCleanupCandidates, } from '../cli/cleanup.js';
|
|
@@ -188,6 +191,21 @@ async function logRuntimeDispatchOutcome(params) {
|
|
|
188
191
|
reason: outcome.reason,
|
|
189
192
|
});
|
|
190
193
|
}
|
|
194
|
+
async function logStartupTiming(params) {
|
|
195
|
+
const { cwd, teamName, workerName, event, paneId, elapsedMs, reason, requestId, transport } = params;
|
|
196
|
+
await appendTeamDeliveryLogForCwd(cwd, {
|
|
197
|
+
event: 'startup_timing',
|
|
198
|
+
source: 'team.runtime',
|
|
199
|
+
team: teamName,
|
|
200
|
+
to_worker: workerName,
|
|
201
|
+
startup_event: event,
|
|
202
|
+
pane_id: paneId,
|
|
203
|
+
elapsed_ms: typeof elapsedMs === 'number' ? Math.round(elapsedMs) : undefined,
|
|
204
|
+
reason,
|
|
205
|
+
request_id: requestId,
|
|
206
|
+
transport,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
191
209
|
function collectProvisionedShutdownWorktrees(config) {
|
|
192
210
|
const seenWorktreePaths = new Set();
|
|
193
211
|
const worktrees = [];
|
|
@@ -932,6 +950,52 @@ const WORKTREE_TRIGGER_STATE_ROOT = '$OMX_TEAM_STATE_ROOT';
|
|
|
932
950
|
const STARTUP_EVIDENCE_TIMEOUT_MS = 15_000;
|
|
933
951
|
const STARTUP_EVIDENCE_POLL_MS = 100;
|
|
934
952
|
const STARTUP_EVIDENCE_LAUNCH_TIMEOUT_MS = 45_000;
|
|
953
|
+
const STARTUP_TIMING_LOG_VERSION = 1;
|
|
954
|
+
export function teamStartupTimingPath(teamName, cwd) {
|
|
955
|
+
return join(resolveCanonicalTeamStateRoot(cwd), 'team', teamName, 'startup-timing.json');
|
|
956
|
+
}
|
|
957
|
+
export function teamRuntimeTeamsRoot(cwd) {
|
|
958
|
+
return join(resolveCanonicalTeamStateRoot(cwd), 'team');
|
|
959
|
+
}
|
|
960
|
+
export function teamRuntimeTeamRoot(teamName, cwd) {
|
|
961
|
+
return join(teamRuntimeTeamsRoot(cwd), teamName);
|
|
962
|
+
}
|
|
963
|
+
export function teamRuntimeSessionPath(cwd) {
|
|
964
|
+
return join(omxStateDir(cwd), 'session.json');
|
|
965
|
+
}
|
|
966
|
+
function createStartupTimingRecorder(teamName, cwd) {
|
|
967
|
+
const startedAt = performance.now();
|
|
968
|
+
const events = [];
|
|
969
|
+
return {
|
|
970
|
+
mark: (phase, details = {}) => {
|
|
971
|
+
events.push({
|
|
972
|
+
phase,
|
|
973
|
+
at: new Date().toISOString(),
|
|
974
|
+
elapsed_ms: Math.round((performance.now() - startedAt) * 1000) / 1000,
|
|
975
|
+
...details,
|
|
976
|
+
});
|
|
977
|
+
},
|
|
978
|
+
flush: async () => {
|
|
979
|
+
const timingPath = teamStartupTimingPath(teamName, cwd);
|
|
980
|
+
await writeAtomic(timingPath, JSON.stringify({ schema_version: STARTUP_TIMING_LOG_VERSION, team_name: teamName, events }, null, 2)).catch(() => { });
|
|
981
|
+
for (const event of events) {
|
|
982
|
+
await appendTeamDeliveryLogForCwd(cwd, {
|
|
983
|
+
event: 'dispatch_result',
|
|
984
|
+
source: 'team.runtime.startup-timing',
|
|
985
|
+
team: teamName,
|
|
986
|
+
result: event.ok === false ? 'failed' : 'ok',
|
|
987
|
+
phase: event.phase,
|
|
988
|
+
elapsed_ms: event.elapsed_ms,
|
|
989
|
+
to_worker: event.worker,
|
|
990
|
+
pane_id: event.pane_id,
|
|
991
|
+
reason: event.reason,
|
|
992
|
+
transport: event.transport,
|
|
993
|
+
request_id: event.request_id,
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
};
|
|
998
|
+
}
|
|
935
999
|
const promptWorkerRegistry = new Map();
|
|
936
1000
|
const previousModelInstructionsFileByTeam = new Map();
|
|
937
1001
|
const PROMPT_WORKER_SIGTERM_WAIT_MS = 3_000;
|
|
@@ -1000,7 +1064,7 @@ function resolveGovernancePolicy(governance, legacyPolicy) {
|
|
|
1000
1064
|
return normalizeTeamGovernance(governance, legacyPolicy);
|
|
1001
1065
|
}
|
|
1002
1066
|
async function assertNestedTeamAllowed(cwd) {
|
|
1003
|
-
const workerContext = parseTeamWorkerContext(process.env.OMX_TEAM_WORKER);
|
|
1067
|
+
const workerContext = parseTeamWorkerContext(process.env.OMX_TEAM_INTERNAL_WORKER || process.env.OMX_TEAM_WORKER);
|
|
1004
1068
|
if (!workerContext)
|
|
1005
1069
|
return;
|
|
1006
1070
|
for (const candidateCwd of resolveManifestLookupCwds(cwd)) {
|
|
@@ -1077,6 +1141,22 @@ async function recordRecoverableStartupIssue(params) {
|
|
|
1077
1141
|
reason,
|
|
1078
1142
|
}, cwd).catch(() => { });
|
|
1079
1143
|
}
|
|
1144
|
+
async function recordPromptStartupWorkerStopped(params) {
|
|
1145
|
+
const { teamName, workerName, taskIds, reason, cwd } = params;
|
|
1146
|
+
const updatedAt = new Date().toISOString();
|
|
1147
|
+
await writeWorkerStatus(teamName, workerName, {
|
|
1148
|
+
state: 'failed',
|
|
1149
|
+
current_task_id: taskIds[0],
|
|
1150
|
+
reason,
|
|
1151
|
+
updated_at: updatedAt,
|
|
1152
|
+
}, cwd).catch(() => { });
|
|
1153
|
+
await appendTeamEvent(teamName, {
|
|
1154
|
+
type: 'worker_stopped',
|
|
1155
|
+
worker: workerName,
|
|
1156
|
+
task_id: taskIds[0],
|
|
1157
|
+
reason,
|
|
1158
|
+
}, cwd).catch(() => { });
|
|
1159
|
+
}
|
|
1080
1160
|
function setTeamModelInstructionsFile(teamName, filePath) {
|
|
1081
1161
|
if (!previousModelInstructionsFileByTeam.has(teamName)) {
|
|
1082
1162
|
previousModelInstructionsFileByTeam.set(teamName, process.env[MODEL_INSTRUCTIONS_FILE_ENV]);
|
|
@@ -1383,10 +1463,16 @@ export { TEAM_LOW_COMPLEXITY_DEFAULT_MODEL };
|
|
|
1383
1463
|
export { resolveCanonicalTeamStateRoot };
|
|
1384
1464
|
function spawnPromptWorker(teamName, workerName, workerIndex, workerCwd, launchArgs, workerEnv, workerCli, initialPrompt, workerRole) {
|
|
1385
1465
|
const processSpec = buildWorkerProcessLaunchSpec(teamName, workerIndex, launchArgs, workerCwd, workerEnv, workerCli, initialPrompt, workerRole);
|
|
1466
|
+
const childEnv = { ...process.env, ...processSpec.env };
|
|
1467
|
+
// Prompt workers are external CLI processes, not in-process runtime code.
|
|
1468
|
+
// Keeping c8's NODE_V8_COVERAGE in their environment makes coverage runs
|
|
1469
|
+
// track long-lived fake worker descendants and can keep node --test alive
|
|
1470
|
+
// after the runtime test itself has completed.
|
|
1471
|
+
delete childEnv.NODE_V8_COVERAGE;
|
|
1386
1472
|
const child = spawn(processSpec.command, processSpec.args, {
|
|
1387
1473
|
cwd: workerCwd,
|
|
1388
1474
|
detached: process.platform !== 'win32',
|
|
1389
|
-
env:
|
|
1475
|
+
env: childEnv,
|
|
1390
1476
|
stdio: ['pipe', 'ignore', 'ignore'],
|
|
1391
1477
|
});
|
|
1392
1478
|
registerPromptWorkerHandle(teamName, workerName, child);
|
|
@@ -1481,11 +1567,28 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1481
1567
|
const leaderCwd = resolve(cwd);
|
|
1482
1568
|
await assertNestedTeamAllowed(leaderCwd);
|
|
1483
1569
|
const effectiveWorktreeMode = resolveEffectiveTeamWorktreeMode(leaderCwd, options.worktreeMode);
|
|
1484
|
-
const
|
|
1485
|
-
const leaderSessionId = await resolveLeaderSessionId(leaderCwd);
|
|
1486
|
-
await assertTeamStartupIsNonDestructive(sanitized, leaderCwd, leaderSessionId);
|
|
1570
|
+
const displayName = sanitizeTeamName(teamName);
|
|
1487
1571
|
const workerLaunchMode = resolveTeamWorkerLaunchMode(process.env);
|
|
1488
1572
|
const displayMode = workerLaunchMode === 'interactive' ? 'split_pane' : 'auto';
|
|
1573
|
+
const rawIdentityScope = resolveTeamIdentityScope(process.env);
|
|
1574
|
+
const resolvedLeaderSessionId = await resolveLeaderSessionId(leaderCwd);
|
|
1575
|
+
const identityScope = rawIdentityScope.source === 'run-id'
|
|
1576
|
+
? (resolvedLeaderSessionId
|
|
1577
|
+
? { ...rawIdentityScope, sessionId: resolvedLeaderSessionId, runId: '' }
|
|
1578
|
+
: {
|
|
1579
|
+
...rawIdentityScope,
|
|
1580
|
+
// Prompt-mode starts can run outside tmux/native session metadata. A fresh
|
|
1581
|
+
// random run id would give every start a new leader identity and bypass
|
|
1582
|
+
// one-active-team protection, so scope that fallback to the leader cwd.
|
|
1583
|
+
runId: `cwd:${leaderCwd}`,
|
|
1584
|
+
})
|
|
1585
|
+
: rawIdentityScope;
|
|
1586
|
+
const sanitized = buildInternalTeamName(displayName, identityScope);
|
|
1587
|
+
const leaderSessionId = identityScope.sessionId || identityScope.paneId || identityScope.tmuxTarget || identityScope.runId;
|
|
1588
|
+
await assertTeamStartupIsNonDestructive(sanitized, leaderCwd, leaderSessionId);
|
|
1589
|
+
if (displayName !== sanitized) {
|
|
1590
|
+
await assertTeamStartupIsNonDestructive(displayName, leaderCwd, leaderSessionId);
|
|
1591
|
+
}
|
|
1489
1592
|
if (workerLaunchMode === 'interactive') {
|
|
1490
1593
|
if (!isTmuxAvailable()) {
|
|
1491
1594
|
throw new Error('Team mode requires tmux. Install with: apt install tmux / brew install tmux');
|
|
@@ -1495,6 +1598,16 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1495
1598
|
}
|
|
1496
1599
|
}
|
|
1497
1600
|
const teamStateRoot = resolveCanonicalTeamStateRoot(leaderCwd);
|
|
1601
|
+
const requestedApprovedExecution = normalizeApprovedTeamExecutionBinding(options.approvedExecution);
|
|
1602
|
+
const selectedApprovedExecutionHint = requestedApprovedExecution
|
|
1603
|
+
? readApprovedTeamExecutionHintFromBinding(leaderCwd, requestedApprovedExecution)
|
|
1604
|
+
: null;
|
|
1605
|
+
if (requestedApprovedExecution && !selectedApprovedExecutionHint) {
|
|
1606
|
+
throw new Error(`approved_execution_binding_stale:${requestedApprovedExecution.prd_path}:${requestedApprovedExecution.task}`);
|
|
1607
|
+
}
|
|
1608
|
+
const approvedExecution = selectedApprovedExecutionHint
|
|
1609
|
+
? buildApprovedTeamExecutionBinding(selectedApprovedExecutionHint)
|
|
1610
|
+
: null;
|
|
1498
1611
|
const activeWorktreeMode = effectiveWorktreeMode.enabled
|
|
1499
1612
|
? (effectiveWorktreeMode.detached ? 'detached' : 'named')
|
|
1500
1613
|
: null;
|
|
@@ -1553,10 +1666,18 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1553
1666
|
const skipWorkerReadyWait = shouldSkipWorkerReadyWait(process.env);
|
|
1554
1667
|
try {
|
|
1555
1668
|
// 3. Init state directory + config
|
|
1556
|
-
config = await initTeamState(sanitized, task, agentType, workerCount, leaderCwd, DEFAULT_MAX_WORKERS, {
|
|
1669
|
+
config = await initTeamState(sanitized, task, agentType, workerCount, leaderCwd, DEFAULT_MAX_WORKERS, {
|
|
1670
|
+
...process.env,
|
|
1671
|
+
OMX_SESSION_ID: leaderSessionId,
|
|
1672
|
+
OMX_TEAM_DISPLAY_MODE: displayMode,
|
|
1673
|
+
OMX_TEAM_WORKER_LAUNCH_MODE: workerLaunchMode,
|
|
1674
|
+
}, {
|
|
1557
1675
|
leader_cwd: leaderCwd,
|
|
1558
1676
|
team_state_root: teamStateRoot,
|
|
1559
1677
|
workspace_mode: workspaceMode,
|
|
1678
|
+
display_name: displayName,
|
|
1679
|
+
requested_name: displayName,
|
|
1680
|
+
identity_source: identityScope.source,
|
|
1560
1681
|
worktree_mode: effectiveWorktreeMode,
|
|
1561
1682
|
}, 'default');
|
|
1562
1683
|
if (!config) {
|
|
@@ -1565,7 +1686,11 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1565
1686
|
config.leader_cwd = leaderCwd;
|
|
1566
1687
|
config.team_state_root = teamStateRoot;
|
|
1567
1688
|
config.workspace_mode = workspaceMode;
|
|
1689
|
+
config.display_name = displayName;
|
|
1690
|
+
config.requested_name = displayName;
|
|
1691
|
+
config.identity_source = identityScope.source;
|
|
1568
1692
|
config.worktree_mode = effectiveWorktreeMode;
|
|
1693
|
+
await writePersistedApprovedTeamExecutionBinding(sanitized, leaderCwd, approvedExecution, teamStateRoot);
|
|
1569
1694
|
// 4. Create tasks. Repo-aware DAG dependencies are symbolic until the
|
|
1570
1695
|
// state layer returns concrete task IDs, so create those tasks dependency
|
|
1571
1696
|
// free and patch runtime dependency fields after ID assignment.
|
|
@@ -1661,6 +1786,8 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1661
1786
|
rolePromptContent: rawRolePromptContent ?? undefined,
|
|
1662
1787
|
worktreeRootAgentsCanonical: Boolean(workerWorkspace.worktreePath),
|
|
1663
1788
|
taskHints: effectiveDecompositionMetadata?.task_hints,
|
|
1789
|
+
approvedContextSummary: effectiveDecompositionMetadata?.approved_context_summary,
|
|
1790
|
+
workerGoalInstruction: buildTeamWorkerGoalInstruction(sanitized, workerName, workerTasks, { teamStateRoot }),
|
|
1664
1791
|
});
|
|
1665
1792
|
const triggerDirective = buildTriggerDirective(workerName, sanitized, resolveInstructionStateRoot(workerWorkspace.worktreePath));
|
|
1666
1793
|
const trigger = triggerDirective.text;
|
|
@@ -1688,6 +1815,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1688
1815
|
[TEAM_STATE_ROOT_ENV]: teamStateRoot,
|
|
1689
1816
|
[TEAM_LEADER_CWD_ENV]: leaderCwd,
|
|
1690
1817
|
[MODEL_INSTRUCTIONS_FILE_ENV]: plan.instructionsFilePath,
|
|
1818
|
+
OMX_TEAM_DISPLAY_NAME: displayName,
|
|
1691
1819
|
};
|
|
1692
1820
|
if (plan.workerWorkspace.worktreePath) {
|
|
1693
1821
|
env.OMX_TEAM_WORKTREE_PATH = plan.workerWorkspace.worktreePath;
|
|
@@ -1756,6 +1884,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1756
1884
|
cleanup: options.cleanupLaunchOrphanedMcpProcesses,
|
|
1757
1885
|
writeWarning: options.writeCleanupWarning,
|
|
1758
1886
|
});
|
|
1887
|
+
const startupTiming = createStartupTimingRecorder(sanitized, leaderCwd);
|
|
1759
1888
|
if (workerLaunchMode === 'interactive') {
|
|
1760
1889
|
const createdSession = createTeamSession(sanitized, workerCount, leaderCwd, sharedWorkerLaunchArgs, workerStartups);
|
|
1761
1890
|
sessionName = createdSession.name;
|
|
@@ -1763,6 +1892,9 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1763
1892
|
createdWorkerPaneIds.push(...createdSession.workerPaneIds);
|
|
1764
1893
|
createdLeaderPaneId = createdSession.leaderPaneId;
|
|
1765
1894
|
applyCreatedInteractiveSessionToConfig(config, createdSession, workerPaneIds);
|
|
1895
|
+
for (const [index, paneId] of createdSession.workerPaneIds.entries()) {
|
|
1896
|
+
startupTiming.mark('split_returned', { worker: `worker-${index + 1}`, pane_id: paneId });
|
|
1897
|
+
}
|
|
1766
1898
|
}
|
|
1767
1899
|
else {
|
|
1768
1900
|
config.tmux_session = `prompt-${sanitized}`;
|
|
@@ -1787,6 +1919,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1787
1919
|
throw new Error(`missing bootstrap plan for worker-${i}`);
|
|
1788
1920
|
}
|
|
1789
1921
|
await materializeWorkerStartupState(bootstrapPlan, i, workerPaneIds[i - 1]);
|
|
1922
|
+
startupTiming.mark('identity_inbox_written', { worker: bootstrapPlan.workerName, pane_id: workerPaneIds[i - 1] });
|
|
1790
1923
|
}
|
|
1791
1924
|
await saveTeamConfig(config, leaderCwd);
|
|
1792
1925
|
// 7. Start all safe per-worker readiness/dispatch attempts concurrently.
|
|
@@ -1812,6 +1945,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1812
1945
|
const trigger = bootstrapPlan.trigger;
|
|
1813
1946
|
const triggerIntent = bootstrapPlan.triggerIntent;
|
|
1814
1947
|
const initialPrompt = bootstrapPlan.initialPrompt;
|
|
1948
|
+
const startupStartedAt = performance.now();
|
|
1815
1949
|
const taskRoles = workerTasks
|
|
1816
1950
|
.map((task) => task.role)
|
|
1817
1951
|
.filter((role) => Boolean(role));
|
|
@@ -1819,8 +1953,26 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1819
1953
|
if (uniqueTaskRoles.length > 1) {
|
|
1820
1954
|
console.log(`[omx:team] ${workerName}: mixed task roles [${uniqueTaskRoles.join(', ')}], falling back to ${agentType}`);
|
|
1821
1955
|
}
|
|
1822
|
-
|
|
1956
|
+
const startupDirectOutcome = workerLaunchMode === 'interactive' && !initialPrompt
|
|
1957
|
+
? await attemptStartupDirectTrigger({
|
|
1958
|
+
teamName: sanitized,
|
|
1959
|
+
config: config,
|
|
1960
|
+
workerName,
|
|
1961
|
+
workerIndex,
|
|
1962
|
+
paneId,
|
|
1963
|
+
workerCli: workerCliPlan[workerIndex - 1],
|
|
1964
|
+
inbox,
|
|
1965
|
+
triggerMessage: trigger,
|
|
1966
|
+
intent: triggerIntent,
|
|
1967
|
+
taskIds: workerTasks.map((task) => task.id),
|
|
1968
|
+
cwd: leaderCwd,
|
|
1969
|
+
timing: startupTiming,
|
|
1970
|
+
})
|
|
1971
|
+
: null;
|
|
1972
|
+
if (workerLaunchMode === 'interactive' && !skipWorkerReadyWait && !initialPrompt && !startupDirectOutcome?.ok) {
|
|
1973
|
+
startupTiming.mark('ready_wait_start', { worker: workerName, pane_id: paneId });
|
|
1823
1974
|
const ready = await waitForWorkerReadyAsync(sessionName, workerIndex, workerReadyTimeoutMs, paneId);
|
|
1975
|
+
startupTiming.mark('ready_wait_end', { worker: workerName, pane_id: paneId, ok: ready });
|
|
1824
1976
|
if (!ready) {
|
|
1825
1977
|
const workerAlive = isWorkerPaneOpen(sessionName, workerIndex, paneId);
|
|
1826
1978
|
if (workerAlive) {
|
|
@@ -1841,10 +1993,11 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1841
1993
|
};
|
|
1842
1994
|
}
|
|
1843
1995
|
}
|
|
1996
|
+
const startupReadyPromptObserved = workerLaunchMode === 'interactive' && !skipWorkerReadyWait && !initialPrompt;
|
|
1844
1997
|
let dispatchOutcome = initialPrompt
|
|
1845
1998
|
? { ok: true, transport: 'none', reason: 'startup_prompt_delivered_at_launch' }
|
|
1846
|
-
: { ok: false, transport: 'none', reason: 'not_attempted' };
|
|
1847
|
-
if (!initialPrompt) {
|
|
1999
|
+
: (startupDirectOutcome ?? { ok: false, transport: 'none', reason: 'not_attempted' });
|
|
2000
|
+
if (!initialPrompt && !startupDirectOutcome?.ok) {
|
|
1848
2001
|
for (let attempt = 1; attempt <= startupDispatchRetries; attempt++) {
|
|
1849
2002
|
dispatchOutcome = await dispatchCriticalInboxInstruction({
|
|
1850
2003
|
teamName: sanitized,
|
|
@@ -1861,7 +2014,20 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1861
2014
|
inboxCorrelationKey: `startup:${workerName}`,
|
|
1862
2015
|
requireWorkerStartupEvidence: true,
|
|
1863
2016
|
startupEvidenceTimeoutMs: workerStartupEvidenceTimeoutMs,
|
|
2017
|
+
startupReadyPromptObserved,
|
|
2018
|
+
startupTiming,
|
|
1864
2019
|
});
|
|
2020
|
+
await logStartupTiming({
|
|
2021
|
+
cwd: leaderCwd,
|
|
2022
|
+
teamName: sanitized,
|
|
2023
|
+
workerName,
|
|
2024
|
+
event: dispatchOutcome.ok ? 'startup_evidence' : 'startup_attempt_failed',
|
|
2025
|
+
paneId,
|
|
2026
|
+
elapsedMs: performance.now() - startupStartedAt,
|
|
2027
|
+
reason: dispatchOutcome.reason,
|
|
2028
|
+
requestId: dispatchOutcome.request_id,
|
|
2029
|
+
transport: dispatchOutcome.transport,
|
|
2030
|
+
}).catch(() => { });
|
|
1865
2031
|
if (dispatchOutcome.ok)
|
|
1866
2032
|
break;
|
|
1867
2033
|
if (attempt < startupDispatchRetries) {
|
|
@@ -1895,6 +2061,16 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1895
2061
|
});
|
|
1896
2062
|
return { ok: true, workerIndex, workerName };
|
|
1897
2063
|
}
|
|
2064
|
+
if (workerLaunchMode === 'prompt' && !workerAlive) {
|
|
2065
|
+
await recordPromptStartupWorkerStopped({
|
|
2066
|
+
teamName: sanitized,
|
|
2067
|
+
workerName,
|
|
2068
|
+
taskIds: workerTasks.map((task) => task.id),
|
|
2069
|
+
reason: dispatchOutcome.reason,
|
|
2070
|
+
cwd: leaderCwd,
|
|
2071
|
+
});
|
|
2072
|
+
return { ok: true, workerIndex, workerName };
|
|
2073
|
+
}
|
|
1898
2074
|
return {
|
|
1899
2075
|
ok: false,
|
|
1900
2076
|
workerIndex,
|
|
@@ -1921,6 +2097,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1921
2097
|
throw firstStartupError.error;
|
|
1922
2098
|
}
|
|
1923
2099
|
await saveTeamConfig(config, leaderCwd);
|
|
2100
|
+
await startupTiming.flush();
|
|
1924
2101
|
return {
|
|
1925
2102
|
teamName: sanitized,
|
|
1926
2103
|
sanitizedName: sanitized,
|
|
@@ -2046,7 +2223,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
2046
2223
|
*/
|
|
2047
2224
|
export async function monitorTeam(teamName, cwd) {
|
|
2048
2225
|
const monitorStartMs = performance.now();
|
|
2049
|
-
const sanitized =
|
|
2226
|
+
const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);
|
|
2050
2227
|
const config = await readTeamConfig(sanitized, cwd);
|
|
2051
2228
|
if (!config)
|
|
2052
2229
|
return null;
|
|
@@ -2361,6 +2538,25 @@ export async function assignTask(teamName, workerName, taskId, cwd) {
|
|
|
2361
2538
|
export async function reassignTask(teamName, taskId, _fromWorker, toWorker, cwd) {
|
|
2362
2539
|
await assignTask(teamName, toWorker, taskId, cwd);
|
|
2363
2540
|
}
|
|
2541
|
+
function resolveCommitHygieneArtifactTeamNames(config, internalTeamName) {
|
|
2542
|
+
const names = [];
|
|
2543
|
+
for (const value of [config.requested_name, config.display_name, internalTeamName]) {
|
|
2544
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
2545
|
+
continue;
|
|
2546
|
+
try {
|
|
2547
|
+
const sanitized = sanitizeTeamName(value);
|
|
2548
|
+
if (!names.includes(sanitized))
|
|
2549
|
+
names.push(sanitized);
|
|
2550
|
+
}
|
|
2551
|
+
catch {
|
|
2552
|
+
// Persisted display/request names are best-effort aliases. If an older
|
|
2553
|
+
// state file contains an invalid value, fall back to the internal name.
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
if (!names.includes(internalTeamName))
|
|
2557
|
+
names.push(internalTeamName);
|
|
2558
|
+
return names;
|
|
2559
|
+
}
|
|
2364
2560
|
/**
|
|
2365
2561
|
* Graceful shutdown: send shutdown inbox to all workers, wait, force kill, cleanup.
|
|
2366
2562
|
*/
|
|
@@ -2368,7 +2564,7 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2368
2564
|
const force = options.force === true;
|
|
2369
2565
|
const confirmIssues = options.confirmIssues === true;
|
|
2370
2566
|
let skipWorkerAcks = false;
|
|
2371
|
-
const sanitized =
|
|
2567
|
+
const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);
|
|
2372
2568
|
const config = await readTeamConfig(sanitized, cwd);
|
|
2373
2569
|
if (!config) {
|
|
2374
2570
|
// No config -- just try to kill tmux session and clean up
|
|
@@ -2616,14 +2812,22 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2616
2812
|
}
|
|
2617
2813
|
}
|
|
2618
2814
|
const artifactCwd = resolveTeamCommitHygieneArtifactCwd(config, cwd);
|
|
2619
|
-
const ledger = await appendTeamCommitHygieneEntries(sanitized, commitHygieneEntries, artifactCwd);
|
|
2620
2815
|
const taskView = await listTasks(sanitized, cwd).catch(() => []);
|
|
2621
|
-
const
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2816
|
+
const internalLedger = await appendTeamCommitHygieneEntries(sanitized, commitHygieneEntries, artifactCwd);
|
|
2817
|
+
const commitHygieneArtifactTeamNames = resolveCommitHygieneArtifactTeamNames(config, sanitized);
|
|
2818
|
+
let commitHygieneArtifacts = null;
|
|
2819
|
+
for (const artifactTeamName of commitHygieneArtifactTeamNames) {
|
|
2820
|
+
const ledger = artifactTeamName === sanitized
|
|
2821
|
+
? internalLedger
|
|
2822
|
+
: await appendTeamCommitHygieneEntries(artifactTeamName, internalLedger.entries, artifactCwd);
|
|
2823
|
+
const commitHygieneContext = buildTeamCommitHygieneContext({
|
|
2824
|
+
teamName: artifactTeamName,
|
|
2825
|
+
tasks: taskView,
|
|
2826
|
+
ledger,
|
|
2827
|
+
});
|
|
2828
|
+
const writtenArtifacts = await writeTeamCommitHygieneContext(artifactTeamName, commitHygieneContext, artifactCwd);
|
|
2829
|
+
commitHygieneArtifacts ??= writtenArtifacts;
|
|
2830
|
+
}
|
|
2627
2831
|
// 5. Remove worker worktree-root instructions and team-scoped fallback instructions.
|
|
2628
2832
|
for (const worker of config.workers) {
|
|
2629
2833
|
if (!worker.worktree_path || !worker.team_state_root)
|
|
@@ -2675,11 +2879,19 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2675
2879
|
* Resume monitoring an existing team.
|
|
2676
2880
|
*/
|
|
2677
2881
|
export async function resumeTeam(teamName, cwd) {
|
|
2678
|
-
const sanitized =
|
|
2882
|
+
const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);
|
|
2679
2883
|
const config = await readTeamConfig(sanitized, cwd);
|
|
2680
2884
|
if (!config)
|
|
2681
2885
|
return null;
|
|
2682
2886
|
config.lifecycle_profile = 'default';
|
|
2887
|
+
const leaderCwd = config.leader_cwd ?? cwd;
|
|
2888
|
+
const approvedExecutionState = await resolvePersistedApprovedTeamExecutionContinuityState(sanitized, leaderCwd, config.team_state_root ?? resolveCanonicalTeamStateRoot(leaderCwd));
|
|
2889
|
+
if (approvedExecutionState.status === 'malformed') {
|
|
2890
|
+
throw new Error(`approved_execution_binding_malformed:${sanitized}`);
|
|
2891
|
+
}
|
|
2892
|
+
if (approvedExecutionState.status === 'stale') {
|
|
2893
|
+
throw new Error(`approved_execution_binding_stale:${approvedExecutionState.binding.prd_path}:${approvedExecutionState.binding.task}`);
|
|
2894
|
+
}
|
|
2683
2895
|
if (config.worker_launch_mode === 'prompt') {
|
|
2684
2896
|
const handleTeamConfig = { ...config, name: sanitized };
|
|
2685
2897
|
const hasLivePromptWorker = config.workers.some((worker) => isPromptWorkerAlive(handleTeamConfig, worker));
|
|
@@ -2718,7 +2930,7 @@ export async function resumeTeam(teamName, cwd) {
|
|
|
2718
2930
|
};
|
|
2719
2931
|
}
|
|
2720
2932
|
async function findActiveTeams(cwd, leaderSessionId) {
|
|
2721
|
-
const root =
|
|
2933
|
+
const root = teamRuntimeTeamsRoot(cwd);
|
|
2722
2934
|
if (!existsSync(root))
|
|
2723
2935
|
return [];
|
|
2724
2936
|
const sessions = new Set(listTeamSessions());
|
|
@@ -2754,7 +2966,7 @@ async function findActiveTeams(cwd, leaderSessionId) {
|
|
|
2754
2966
|
return active;
|
|
2755
2967
|
}
|
|
2756
2968
|
async function detectAndCleanStaleTeam(teamName, leaderCwd, workerCount, confirmFn) {
|
|
2757
|
-
const stateDir =
|
|
2969
|
+
const stateDir = teamRuntimeTeamRoot(teamName, leaderCwd);
|
|
2758
2970
|
if (!existsSync(stateDir))
|
|
2759
2971
|
return;
|
|
2760
2972
|
const sessions = new Set(listTeamSessions());
|
|
@@ -2803,7 +3015,7 @@ async function resolveLeaderSessionId(cwd) {
|
|
|
2803
3015
|
const fromEnv = process.env.OMX_SESSION_ID || process.env.CODEX_SESSION_ID || process.env.SESSION_ID;
|
|
2804
3016
|
if (fromEnv && fromEnv.trim() !== '')
|
|
2805
3017
|
return fromEnv.trim();
|
|
2806
|
-
const p =
|
|
3018
|
+
const p = teamRuntimeSessionPath(cwd);
|
|
2807
3019
|
if (!existsSync(p))
|
|
2808
3020
|
return '';
|
|
2809
3021
|
try {
|
|
@@ -2951,8 +3163,89 @@ async function markDispatchRequestLeaderPaneMissingDeferred(params) {
|
|
|
2951
3163
|
last_reason: 'leader_pane_missing_deferred',
|
|
2952
3164
|
}, cwd).catch(() => { });
|
|
2953
3165
|
}
|
|
3166
|
+
async function attemptStartupDirectTrigger(params) {
|
|
3167
|
+
const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, taskIds, cwd, timing, } = params;
|
|
3168
|
+
const safety = await evaluateStartupDirectTriggerSafety(config.tmux_session, workerIndex, paneId, workerCli);
|
|
3169
|
+
if (!safety.safe) {
|
|
3170
|
+
timing.mark('startup_direct_bypass', {
|
|
3171
|
+
worker: workerName,
|
|
3172
|
+
pane_id: paneId,
|
|
3173
|
+
ok: false,
|
|
3174
|
+
reason: `startup_direct_unsafe:${safety.reason}`,
|
|
3175
|
+
});
|
|
3176
|
+
return null;
|
|
3177
|
+
}
|
|
3178
|
+
const queued = await queueInboxInstruction({
|
|
3179
|
+
teamName,
|
|
3180
|
+
workerName,
|
|
3181
|
+
workerIndex,
|
|
3182
|
+
paneId,
|
|
3183
|
+
inbox,
|
|
3184
|
+
triggerMessage,
|
|
3185
|
+
intent,
|
|
3186
|
+
cwd,
|
|
3187
|
+
transportPreference: 'transport_direct',
|
|
3188
|
+
fallbackAllowed: false,
|
|
3189
|
+
inboxCorrelationKey: `startup-direct:${workerName}`,
|
|
3190
|
+
notify: (_target, message) => notifyWorkerOutcome(config, workerIndex, message, paneId),
|
|
3191
|
+
});
|
|
3192
|
+
timing.mark('dispatch_queued', {
|
|
3193
|
+
worker: workerName,
|
|
3194
|
+
pane_id: paneId,
|
|
3195
|
+
ok: queued.ok,
|
|
3196
|
+
reason: queued.reason,
|
|
3197
|
+
transport: queued.transport,
|
|
3198
|
+
request_id: queued.request_id,
|
|
3199
|
+
});
|
|
3200
|
+
timing.mark('direct_fallback', {
|
|
3201
|
+
worker: workerName,
|
|
3202
|
+
pane_id: paneId,
|
|
3203
|
+
ok: queued.ok,
|
|
3204
|
+
reason: queued.ok ? `startup_direct_trigger_sent:${safety.reason}` : queued.reason,
|
|
3205
|
+
transport: queued.transport,
|
|
3206
|
+
request_id: queued.request_id,
|
|
3207
|
+
});
|
|
3208
|
+
if (!queued.ok)
|
|
3209
|
+
return queued;
|
|
3210
|
+
const effectiveWorkerCli = workerCli ?? 'codex';
|
|
3211
|
+
const workerStartupEvidence = await waitForWorkerStartupEvidence({
|
|
3212
|
+
teamName,
|
|
3213
|
+
workerName,
|
|
3214
|
+
workerCli: effectiveWorkerCli,
|
|
3215
|
+
cwd,
|
|
3216
|
+
timeoutMs: 0,
|
|
3217
|
+
pollMs: STARTUP_EVIDENCE_POLL_MS,
|
|
3218
|
+
});
|
|
3219
|
+
timing.mark('startup_evidence', {
|
|
3220
|
+
worker: workerName,
|
|
3221
|
+
pane_id: paneId,
|
|
3222
|
+
ok: workerStartupEvidence !== 'none',
|
|
3223
|
+
reason: workerStartupEvidence,
|
|
3224
|
+
transport: queued.transport,
|
|
3225
|
+
request_id: queued.request_id,
|
|
3226
|
+
});
|
|
3227
|
+
const reason = workerStartupEvidence === 'none'
|
|
3228
|
+
? `${effectiveWorkerCli}_startup_direct_no_evidence:${safety.reason}`
|
|
3229
|
+
: `startup_direct_trigger_sent:${safety.reason}`;
|
|
3230
|
+
if ((effectiveWorkerCli === 'codex' || effectiveWorkerCli === 'claude') && workerStartupEvidence === 'none') {
|
|
3231
|
+
await recordRecoverableStartupIssue({
|
|
3232
|
+
teamName,
|
|
3233
|
+
workerName,
|
|
3234
|
+
taskIds,
|
|
3235
|
+
reason,
|
|
3236
|
+
cwd,
|
|
3237
|
+
});
|
|
3238
|
+
}
|
|
3239
|
+
return {
|
|
3240
|
+
...queued,
|
|
3241
|
+
reason,
|
|
3242
|
+
};
|
|
3243
|
+
}
|
|
2954
3244
|
async function dispatchCriticalInboxInstruction(params) {
|
|
2955
|
-
const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, cwd, dispatchPolicy, inboxCorrelationKey, requireWorkerStartupEvidence, startupEvidenceTimeoutMs, } = params;
|
|
3245
|
+
const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, cwd, dispatchPolicy, inboxCorrelationKey, requireWorkerStartupEvidence, startupEvidenceTimeoutMs, startupReadyPromptObserved = false, startupTiming, } = params;
|
|
3246
|
+
const noteTiming = (phase, details) => {
|
|
3247
|
+
startupTiming?.mark(phase, { worker: workerName, pane_id: paneId, ...details });
|
|
3248
|
+
};
|
|
2956
3249
|
if (config.worker_launch_mode === 'prompt') {
|
|
2957
3250
|
return await queueInboxInstruction({
|
|
2958
3251
|
teamName,
|
|
@@ -2999,12 +3292,26 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
2999
3292
|
inboxCorrelationKey,
|
|
3000
3293
|
notify: () => ({ ok: true, transport: 'hook', reason: 'queued_for_hook_dispatch' }),
|
|
3001
3294
|
});
|
|
3295
|
+
noteTiming('dispatch_queued', {
|
|
3296
|
+
ok: queued.ok,
|
|
3297
|
+
reason: queued.reason,
|
|
3298
|
+
transport: queued.transport,
|
|
3299
|
+
request_id: queued.request_id,
|
|
3300
|
+
});
|
|
3002
3301
|
if (!queued.request_id)
|
|
3003
3302
|
return { ...queued, ok: false, reason: 'dispatch_request_missing_id' };
|
|
3004
3303
|
const receipt = await waitForDispatchReceipt(teamName, queued.request_id, cwd, {
|
|
3005
3304
|
timeoutMs: dispatchPolicy.dispatch_ack_timeout_ms,
|
|
3006
3305
|
pollMs: 50,
|
|
3007
3306
|
});
|
|
3307
|
+
if (receipt) {
|
|
3308
|
+
noteTiming('hook_receipt', {
|
|
3309
|
+
ok: receipt.status === 'delivered' || receipt.status === 'notified',
|
|
3310
|
+
reason: receipt.status,
|
|
3311
|
+
transport: 'hook',
|
|
3312
|
+
request_id: queued.request_id,
|
|
3313
|
+
});
|
|
3314
|
+
}
|
|
3008
3315
|
if (receipt?.status === 'delivered') {
|
|
3009
3316
|
return { ok: true, transport: 'hook', reason: 'hook_receipt_delivered', request_id: queued.request_id };
|
|
3010
3317
|
}
|
|
@@ -3015,6 +3322,14 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
3015
3322
|
if (!requiresObservedStartupEvidence) {
|
|
3016
3323
|
return { ok: true, transport: 'hook', reason: 'hook_receipt_notified', request_id: queued.request_id };
|
|
3017
3324
|
}
|
|
3325
|
+
if (startupReadyPromptObserved) {
|
|
3326
|
+
return {
|
|
3327
|
+
ok: true,
|
|
3328
|
+
transport: 'hook',
|
|
3329
|
+
reason: 'hook_receipt_notified_with_ready_prompt',
|
|
3330
|
+
request_id: queued.request_id,
|
|
3331
|
+
};
|
|
3332
|
+
}
|
|
3018
3333
|
startupEvidence = await waitForWorkerStartupEvidence({
|
|
3019
3334
|
teamName,
|
|
3020
3335
|
workerName,
|
|
@@ -3022,6 +3337,12 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
3022
3337
|
cwd,
|
|
3023
3338
|
timeoutMs: startupEvidenceTimeoutMs,
|
|
3024
3339
|
});
|
|
3340
|
+
noteTiming('startup_evidence', {
|
|
3341
|
+
ok: startupEvidence !== 'none',
|
|
3342
|
+
reason: startupEvidence,
|
|
3343
|
+
transport: 'hook',
|
|
3344
|
+
request_id: queued.request_id,
|
|
3345
|
+
});
|
|
3025
3346
|
if (startupEvidence !== 'none') {
|
|
3026
3347
|
return {
|
|
3027
3348
|
ok: true,
|
|
@@ -3034,13 +3355,21 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
3034
3355
|
if (receipt?.status === 'failed') {
|
|
3035
3356
|
const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
3036
3357
|
if (fallback.ok) {
|
|
3037
|
-
const fallbackStartupEvidence =
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3358
|
+
const fallbackStartupEvidence = startupReadyPromptObserved
|
|
3359
|
+
? 'ready_prompt'
|
|
3360
|
+
: await waitForRequiredStartupEvidenceAfterDirectFallback({
|
|
3361
|
+
requireWorkerStartupEvidence,
|
|
3362
|
+
workerCli,
|
|
3363
|
+
teamName,
|
|
3364
|
+
workerName,
|
|
3365
|
+
cwd,
|
|
3366
|
+
timeoutMs: startupEvidenceTimeoutMs,
|
|
3367
|
+
});
|
|
3368
|
+
noteTiming('startup_evidence', {
|
|
3369
|
+
ok: fallbackStartupEvidence !== 'none',
|
|
3370
|
+
reason: fallbackStartupEvidence,
|
|
3371
|
+
transport: fallback.transport,
|
|
3372
|
+
request_id: queued.request_id,
|
|
3044
3373
|
});
|
|
3045
3374
|
if (requiresObservedStartupEvidence && fallbackStartupEvidence === 'none') {
|
|
3046
3375
|
await transitionDispatchRequest(teamName, queued.request_id, 'failed', 'failed', { last_reason: `${workerCli}_startup_no_evidence_after_fallback:${fallback.reason}` }, cwd).catch(() => { });
|
|
@@ -3071,6 +3400,12 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
3071
3400
|
};
|
|
3072
3401
|
}
|
|
3073
3402
|
const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
3403
|
+
noteTiming('direct_fallback', {
|
|
3404
|
+
ok: fallback.ok,
|
|
3405
|
+
reason: fallback.reason,
|
|
3406
|
+
transport: fallback.transport,
|
|
3407
|
+
request_id: queued.request_id,
|
|
3408
|
+
});
|
|
3074
3409
|
const startupFallbackLabel = receipt?.status === 'notified' && requiresObservedStartupEvidence
|
|
3075
3410
|
? `${workerCli}_startup_no_evidence`
|
|
3076
3411
|
: null;
|
|
@@ -3078,13 +3413,21 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
3078
3413
|
? `${startupFallbackLabel}_fallback_failed:${fallback.reason}`
|
|
3079
3414
|
: `fallback_attempted_but_unconfirmed:${fallback.reason}`;
|
|
3080
3415
|
if (fallback.ok) {
|
|
3081
|
-
const fallbackStartupEvidence =
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3416
|
+
const fallbackStartupEvidence = startupReadyPromptObserved
|
|
3417
|
+
? 'ready_prompt'
|
|
3418
|
+
: await waitForRequiredStartupEvidenceAfterDirectFallback({
|
|
3419
|
+
requireWorkerStartupEvidence,
|
|
3420
|
+
workerCli,
|
|
3421
|
+
teamName,
|
|
3422
|
+
workerName,
|
|
3423
|
+
cwd,
|
|
3424
|
+
timeoutMs: startupEvidenceTimeoutMs,
|
|
3425
|
+
});
|
|
3426
|
+
noteTiming('startup_evidence', {
|
|
3427
|
+
ok: fallbackStartupEvidence !== 'none',
|
|
3428
|
+
reason: fallbackStartupEvidence,
|
|
3429
|
+
transport: fallback.transport,
|
|
3430
|
+
request_id: queued.request_id,
|
|
3088
3431
|
});
|
|
3089
3432
|
if (requiresObservedStartupEvidence && fallbackStartupEvidence === 'none') {
|
|
3090
3433
|
const current = await readDispatchRequest(teamName, queued.request_id, cwd);
|