oh-my-codex 0.12.4 → 0.12.6
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 +27 -3
- package/dist/cli/__tests__/ask.test.js +26 -0
- package/dist/cli/__tests__/ask.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +28 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +95 -8
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +102 -4
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +169 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-parity.test.js +31 -0
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +66 -2
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +51 -1
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +148 -3
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +14 -1
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/cleanup.js +1 -1
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/constants.d.ts +1 -0
- package/dist/cli/constants.d.ts.map +1 -1
- package/dist/cli/constants.js +1 -0
- package/dist/cli/constants.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +15 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts +1 -0
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +49 -1
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +127 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.d.ts +1 -1
- package/dist/cli/mcp-parity.d.ts.map +1 -1
- package/dist/cli/mcp-parity.js +24 -0
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +17 -5
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +80 -6
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +1 -0
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +60 -0
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/mcp-registry.test.js +61 -0
- package/dist/config/__tests__/mcp-registry.test.js.map +1 -1
- package/dist/config/__tests__/wiki-config-contract.test.d.ts +2 -0
- package/dist/config/__tests__/wiki-config-contract.test.d.ts.map +1 -0
- package/dist/config/__tests__/wiki-config-contract.test.js +19 -0
- package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -0
- package/dist/config/generator.d.ts +1 -0
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +88 -3
- package/dist/config/generator.js.map +1 -1
- package/dist/config/mcp-registry.d.ts +2 -0
- package/dist/config/mcp-registry.d.ts.map +1 -1
- package/dist/config/mcp-registry.js +12 -0
- package/dist/config/mcp-registry.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +39 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +297 -4
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +392 -22
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +166 -67
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +112 -2
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-modules.test.js +52 -12
- package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts +2 -3
- package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts.map +1 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +18 -23
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +33 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +176 -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 +355 -7
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +90 -2
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/session.test.js +142 -2
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.js +34 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +1 -0
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +0 -1
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +32 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/runtime.test.js +31 -0
- package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/sdk.test.js +33 -3
- package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js +41 -0
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk/runtime-state.js +7 -1
- package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -1
- package/dist/hooks/extensibility/types.d.ts +1 -0
- package/dist/hooks/extensibility/types.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +6 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +207 -10
- 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 +3 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/session.d.ts +14 -2
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +120 -16
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +111 -2
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +18 -21
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +88 -1
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +3 -0
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +30 -2
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +415 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/__tests__/wiki-server.test.d.ts +2 -0
- package/dist/mcp/__tests__/wiki-server.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/wiki-server.test.js +30 -0
- package/dist/mcp/__tests__/wiki-server.test.js.map +1 -0
- package/dist/mcp/bootstrap.d.ts +19 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +185 -0
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +5 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +41 -11
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +49 -2
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/mcp/wiki-server.d.ts +181 -0
- package/dist/mcp/wiki-server.d.ts.map +1 -0
- package/dist/mcp/wiki-server.js +235 -0
- package/dist/mcp/wiki-server.js.map +1 -0
- package/dist/modes/__tests__/base-autoresearch-contract.test.js +74 -2
- package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -1
- package/dist/modes/__tests__/base-multi-state-compat.test.d.ts +2 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.js +38 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -0
- package/dist/modes/__tests__/base-tmux-pane.test.js +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts +2 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +55 -31
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/formatter.test.js +11 -0
- package/dist/notifications/__tests__/formatter.test.js.map +1 -1
- package/dist/notifications/__tests__/idle-cooldown.test.js +32 -1
- package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
- package/dist/notifications/__tests__/index.test.d.ts +2 -0
- package/dist/notifications/__tests__/index.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/index.test.js +113 -0
- package/dist/notifications/__tests__/index.test.js.map +1 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts +2 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js +86 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -0
- package/dist/notifications/__tests__/reply-listener.test.js +174 -0
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts +2 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +93 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -0
- package/dist/notifications/__tests__/session-registry.test.js +48 -1
- package/dist/notifications/__tests__/session-registry.test.js.map +1 -1
- package/dist/notifications/__tests__/session-status.test.d.ts +2 -0
- package/dist/notifications/__tests__/session-status.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/session-status.test.js +159 -0
- package/dist/notifications/__tests__/session-status.test.js.map +1 -0
- package/dist/notifications/__tests__/tmux.test.js +58 -1
- package/dist/notifications/__tests__/tmux.test.js.map +1 -1
- package/dist/notifications/idle-cooldown.d.ts +11 -0
- package/dist/notifications/idle-cooldown.d.ts.map +1 -1
- package/dist/notifications/idle-cooldown.js +42 -8
- package/dist/notifications/idle-cooldown.js.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +41 -8
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/lifecycle-dedupe.d.ts +8 -0
- package/dist/notifications/lifecycle-dedupe.d.ts.map +1 -0
- package/dist/notifications/lifecycle-dedupe.js +112 -0
- package/dist/notifications/lifecycle-dedupe.js.map +1 -0
- package/dist/notifications/reply-listener.d.ts +10 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +49 -11
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/session-registry.d.ts.map +1 -1
- package/dist/notifications/session-registry.js +7 -1
- package/dist/notifications/session-registry.js.map +1 -1
- package/dist/notifications/session-status.d.ts +23 -0
- package/dist/notifications/session-status.d.ts.map +1 -0
- package/dist/notifications/session-status.js +187 -0
- package/dist/notifications/session-status.js.map +1 -0
- package/dist/notifications/tmux.d.ts +10 -0
- package/dist/notifications/tmux.d.ts.map +1 -1
- package/dist/notifications/tmux.js +59 -5
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/notifications/types.d.ts +2 -0
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/openclaw/__tests__/index.test.js +84 -0
- package/dist/openclaw/__tests__/index.test.js.map +1 -1
- package/dist/openclaw/index.d.ts.map +1 -1
- package/dist/openclaw/index.js +7 -14
- package/dist/openclaw/index.js.map +1 -1
- package/dist/openclaw/types.d.ts +2 -2
- package/dist/openclaw/types.d.ts.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +692 -40
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts +2 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.js +87 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +309 -77
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/hook-derived-watcher.js +43 -1
- package/dist/scripts/hook-derived-watcher.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +95 -21
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/active-team.d.ts +9 -0
- package/dist/scripts/notify-hook/active-team.d.ts.map +1 -0
- package/dist/scripts/notify-hook/active-team.js +44 -0
- package/dist/scripts/notify-hook/active-team.js.map +1 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts +5 -3
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +121 -78
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +18 -4
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/operational-events.d.ts.map +1 -1
- package/dist/scripts/notify-hook/operational-events.js +21 -0
- package/dist/scripts/notify-hook/operational-events.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +3 -2
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts +10 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +56 -12
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +305 -167
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +87 -15
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +11 -2
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +26 -16
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-provider-advisor.js +20 -2
- package/dist/scripts/run-provider-advisor.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +1 -8
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +12 -68
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +113 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +35 -0
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.d.ts +2 -0
- package/dist/state/__tests__/workflow-transition.test.d.ts.map +1 -0
- package/dist/state/__tests__/workflow-transition.test.js +56 -0
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -0
- package/dist/state/operations.d.ts +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +88 -2
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +2 -2
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +119 -33
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +15 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -0
- package/dist/state/workflow-transition-reconcile.js +100 -0
- package/dist/state/workflow-transition-reconcile.js.map +1 -0
- package/dist/state/workflow-transition.d.ts +22 -0
- package/dist/state/workflow-transition.d.ts.map +1 -0
- package/dist/state/workflow-transition.js +188 -0
- package/dist/state/workflow-transition.js.map +1 -0
- package/dist/team/__tests__/api-interop.test.js +90 -0
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/current-task-baseline.test.d.ts +2 -0
- package/dist/team/__tests__/current-task-baseline.test.d.ts.map +1 -0
- package/dist/team/__tests__/current-task-baseline.test.js +87 -0
- package/dist/team/__tests__/current-task-baseline.test.js.map +1 -0
- package/dist/team/__tests__/hardening-e2e.test.js +17 -0
- package/dist/team/__tests__/hardening-e2e.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +673 -65
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/shutdown-fallback.test.js +11 -1
- package/dist/team/__tests__/shutdown-fallback.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +447 -4
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +10 -1
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/current-task-baseline.d.ts +32 -0
- package/dist/team/current-task-baseline.d.ts.map +1 -0
- package/dist/team/current-task-baseline.js +85 -0
- package/dist/team/current-task-baseline.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.map +1 -1
- package/dist/team/leader-activity.d.ts +1 -0
- package/dist/team/leader-activity.d.ts.map +1 -1
- package/dist/team/leader-activity.js +4 -2
- package/dist/team/leader-activity.js.map +1 -1
- package/dist/team/progress-evidence.d.ts +2 -0
- package/dist/team/progress-evidence.d.ts.map +1 -0
- package/dist/team/progress-evidence.js +77 -0
- package/dist/team/progress-evidence.js.map +1 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +269 -64
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +1 -1
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +2 -13
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts +12 -3
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +174 -20
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worktree.d.ts +6 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +28 -4
- package/dist/team/worktree.js.map +1 -1
- package/dist/utils/__tests__/agents-md.test.js +21 -1
- package/dist/utils/__tests__/agents-md.test.js.map +1 -1
- package/dist/utils/__tests__/repo-deps.test.d.ts +2 -0
- package/dist/utils/__tests__/repo-deps.test.d.ts.map +1 -0
- package/dist/utils/__tests__/repo-deps.test.js +71 -0
- package/dist/utils/__tests__/repo-deps.test.js.map +1 -0
- package/dist/utils/agents-md.d.ts +1 -0
- package/dist/utils/agents-md.d.ts.map +1 -1
- package/dist/utils/agents-md.js +7 -3
- package/dist/utils/agents-md.js.map +1 -1
- package/dist/utils/paths.d.ts +4 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +20 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/repo-deps.d.ts +20 -0
- package/dist/utils/repo-deps.d.ts.map +1 -0
- package/dist/utils/repo-deps.js +78 -0
- package/dist/utils/repo-deps.js.map +1 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts +2 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts.map +1 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +54 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.d.ts +12 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.js +139 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -0
- package/dist/wiki/__tests__/crlf-parse.test.d.ts +2 -0
- package/dist/wiki/__tests__/crlf-parse.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/crlf-parse.test.js +24 -0
- package/dist/wiki/__tests__/crlf-parse.test.js.map +1 -0
- package/dist/wiki/__tests__/escape-newline.test.d.ts +2 -0
- package/dist/wiki/__tests__/escape-newline.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/escape-newline.test.js +45 -0
- package/dist/wiki/__tests__/escape-newline.test.js.map +1 -0
- package/dist/wiki/__tests__/ingest.test.d.ts +5 -0
- package/dist/wiki/__tests__/ingest.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/ingest.test.js +181 -0
- package/dist/wiki/__tests__/ingest.test.js.map +1 -0
- package/dist/wiki/__tests__/lint.test.d.ts +5 -0
- package/dist/wiki/__tests__/lint.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/lint.test.js +163 -0
- package/dist/wiki/__tests__/lint.test.js.map +1 -0
- package/dist/wiki/__tests__/query.test.d.ts +5 -0
- package/dist/wiki/__tests__/query.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/query.test.js +141 -0
- package/dist/wiki/__tests__/query.test.js.map +1 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.d.ts +2 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.js +44 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.js.map +1 -0
- package/dist/wiki/__tests__/session-hooks.test.d.ts +5 -0
- package/dist/wiki/__tests__/session-hooks.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/session-hooks.test.js +36 -0
- package/dist/wiki/__tests__/session-hooks.test.js.map +1 -0
- package/dist/wiki/__tests__/slug-nonascii.test.d.ts +2 -0
- package/dist/wiki/__tests__/slug-nonascii.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/slug-nonascii.test.js +24 -0
- package/dist/wiki/__tests__/slug-nonascii.test.js.map +1 -0
- package/dist/wiki/__tests__/storage.test.d.ts +5 -0
- package/dist/wiki/__tests__/storage.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/storage.test.js +278 -0
- package/dist/wiki/__tests__/storage.test.js.map +1 -0
- package/dist/wiki/__tests__/test-helpers.d.ts +31 -0
- package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/wiki/__tests__/test-helpers.js +108 -0
- package/dist/wiki/__tests__/test-helpers.js.map +1 -0
- package/dist/wiki/index.d.ts +14 -0
- package/dist/wiki/index.d.ts.map +1 -0
- package/dist/wiki/index.js +17 -0
- package/dist/wiki/index.js.map +1 -0
- package/dist/wiki/ingest.d.ts +20 -0
- package/dist/wiki/ingest.d.ts.map +1 -0
- package/dist/wiki/ingest.js +115 -0
- package/dist/wiki/ingest.js.map +1 -0
- package/dist/wiki/lifecycle.d.ts +20 -0
- package/dist/wiki/lifecycle.d.ts.map +1 -0
- package/dist/wiki/lifecycle.js +212 -0
- package/dist/wiki/lifecycle.js.map +1 -0
- package/dist/wiki/lint.d.ts +25 -0
- package/dist/wiki/lint.d.ts.map +1 -0
- package/dist/wiki/lint.js +166 -0
- package/dist/wiki/lint.js.map +1 -0
- package/dist/wiki/query.d.ts +36 -0
- package/dist/wiki/query.d.ts.map +1 -0
- package/dist/wiki/query.js +138 -0
- package/dist/wiki/query.js.map +1 -0
- package/dist/wiki/storage.d.ts +33 -0
- package/dist/wiki/storage.d.ts.map +1 -0
- package/dist/wiki/storage.js +321 -0
- package/dist/wiki/storage.js.map +1 -0
- package/dist/wiki/types.d.ts +83 -0
- package/dist/wiki/types.d.ts.map +1 -0
- package/dist/wiki/types.js +15 -0
- package/dist/wiki/types.js.map +1 -0
- package/package.json +3 -1
- package/skills/configure-notifications/SKILL.md +1 -0
- package/skills/doctor/SKILL.md +11 -0
- package/skills/omx-setup/SKILL.md +1 -1
- package/skills/wiki/SKILL.md +57 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +920 -56
- package/src/scripts/__tests__/hook-derived-watcher.test.ts +111 -0
- package/src/scripts/codex-native-hook.ts +377 -83
- package/src/scripts/hook-derived-watcher.ts +43 -1
- package/src/scripts/notify-fallback-watcher.ts +99 -20
- package/src/scripts/notify-hook/active-team.ts +54 -0
- package/src/scripts/notify-hook/auto-nudge.ts +132 -79
- package/src/scripts/notify-hook/managed-tmux.ts +22 -4
- package/src/scripts/notify-hook/operational-events.ts +21 -0
- package/src/scripts/notify-hook/ralph-session-resume.ts +3 -2
- package/src/scripts/notify-hook/state-io.ts +89 -12
- package/src/scripts/notify-hook/team-dispatch.ts +326 -168
- package/src/scripts/notify-hook/team-leader-nudge.ts +91 -14
- package/src/scripts/notify-hook/tmux-injection.ts +11 -2
- package/src/scripts/notify-hook.ts +36 -22
- package/src/scripts/run-provider-advisor.ts +20 -2
- package/src/scripts/smoke-packed-install.ts +16 -83
- package/templates/AGENTS.md +3 -4
package/dist/team/runtime.js
CHANGED
|
@@ -3,8 +3,8 @@ 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, dismissTrustPromptIfPresent, sleepFractionalSeconds, sendToWorker, sendToWorkerStdin, isWorkerAlive, getWorkerPanePid, killWorkerByPaneIdAsync, restoreStandaloneHudPane, teardownWorkerPanes, unregisterResizeHook, destroyTeamSession, listPaneIds, listTeamSessions, } 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, 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, } from './team-ops.js';
|
|
6
|
+
import { sanitizeTeamName, isTmuxAvailable, hasCurrentTmuxClientContext, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, dismissTrustPromptIfPresent, sleepFractionalSeconds, 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, 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';
|
|
8
8
|
import { queueInboxInstruction, queueDirectMailboxMessage, queueBroadcastMailboxMessage, waitForDispatchReceipt, } from './mcp-comm.js';
|
|
9
9
|
import { appendTeamDeliveryLogForCwd } from './delivery-log.js';
|
|
10
10
|
import { generateWorkerOverlay, writeTeamWorkerInstructionsFile, removeTeamWorkerInstructionsFile, writeWorkerWorktreeRootAgentsFile, removeWorkerWorktreeRootAgentsFile, generateInitialInbox, generateTaskAssignmentInbox, generateShutdownInbox, buildTriggerDirective, buildMailboxTriggerDirective, buildLeaderMailboxTriggerDirective, writeWorkerRoleInstructionsFile, } from './worker-bootstrap.js';
|
|
@@ -18,6 +18,7 @@ import { inferPhaseTargetFromTaskCounts, reconcilePhaseStateForMonitor } from '.
|
|
|
18
18
|
import { getTeamTmuxSessions } from '../notifications/tmux.js';
|
|
19
19
|
import { hasStructuredVerificationEvidence } from '../verification/verifier.js';
|
|
20
20
|
import { buildRebalanceDecisions } from './rebalance-policy.js';
|
|
21
|
+
import { getStatePath } from '../mcp/state-paths.js';
|
|
21
22
|
import { readModeState, updateModeState } from '../modes/base.js';
|
|
22
23
|
import { appendTeamCommitHygieneEntries, buildTeamCommitHygieneContext, writeTeamCommitHygieneContext, } from './commit-hygiene.js';
|
|
23
24
|
import { assertCleanLeaderWorkspaceForWorkerWorktrees, ensureWorktree, isGitRepository, isWorktreeDirty, planWorktreeTarget, removeWorktreeForce, rollbackProvisionedWorktrees, } from './worktree.js';
|
|
@@ -51,6 +52,40 @@ async function syncRootTeamModeStateOnTerminalPhase(teamName, phase, cwd) {
|
|
|
51
52
|
// Best-effort compatibility sync only.
|
|
52
53
|
}
|
|
53
54
|
}
|
|
55
|
+
function matchesTeamModeStateForShutdown(state, teamName) {
|
|
56
|
+
const stateTeamName = typeof state?.team_name === 'string' ? state.team_name.trim() : '';
|
|
57
|
+
return !stateTeamName || stateTeamName === teamName;
|
|
58
|
+
}
|
|
59
|
+
async function syncExactTeamModeStateOnShutdown(teamName, cwd, sessionId) {
|
|
60
|
+
const path = getStatePath('team', cwd, sessionId);
|
|
61
|
+
if (!existsSync(path))
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
const parsed = JSON.parse(await readFile(path, 'utf-8'));
|
|
65
|
+
if (!matchesTeamModeStateForShutdown(parsed, teamName))
|
|
66
|
+
return;
|
|
67
|
+
const next = {
|
|
68
|
+
...parsed,
|
|
69
|
+
active: false,
|
|
70
|
+
current_phase: 'cancelled',
|
|
71
|
+
completed_at: typeof parsed.completed_at === 'string' && parsed.completed_at.trim().length > 0
|
|
72
|
+
? parsed.completed_at
|
|
73
|
+
: new Date().toISOString(),
|
|
74
|
+
team_name: teamName,
|
|
75
|
+
};
|
|
76
|
+
await writeFile(path, JSON.stringify(next, null, 2));
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Best-effort compatibility sync only.
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function syncTeamModeStateOnShutdown(teamName, cwd, leaderSessionId) {
|
|
83
|
+
await syncExactTeamModeStateOnShutdown(teamName, cwd);
|
|
84
|
+
const normalizedLeaderSessionId = typeof leaderSessionId === 'string' ? leaderSessionId.trim() : '';
|
|
85
|
+
if (normalizedLeaderSessionId) {
|
|
86
|
+
await syncExactTeamModeStateOnShutdown(teamName, cwd, normalizedLeaderSessionId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
54
89
|
async function assertTeamStartupIsNonDestructive(teamName, cwd, leaderSessionId) {
|
|
55
90
|
const activeTeams = await findActiveTeams(cwd, leaderSessionId);
|
|
56
91
|
if (activeTeams.length > 0) {
|
|
@@ -86,10 +121,10 @@ export function applyCreatedInteractiveSessionToConfig(config, createdSession, w
|
|
|
86
121
|
}
|
|
87
122
|
}
|
|
88
123
|
function collectShutdownPaneIds(params) {
|
|
89
|
-
const { config, livePaneIds = [], restoredStandaloneHudPaneId = null } = params;
|
|
124
|
+
const { config, livePaneIds = [], restoredStandaloneHudPaneId = null, leaderPaneId = config.leader_pane_id, hudPaneId = config.hud_pane_id, } = params;
|
|
90
125
|
const excludedPaneIds = new Set([
|
|
91
|
-
|
|
92
|
-
|
|
126
|
+
leaderPaneId,
|
|
127
|
+
hudPaneId,
|
|
93
128
|
restoredStandaloneHudPaneId,
|
|
94
129
|
].filter((paneId) => typeof paneId === 'string' && paneId.trim().startsWith('%')));
|
|
95
130
|
const paneIds = new Set();
|
|
@@ -862,14 +897,24 @@ const TEAM_LEADER_CWD_ENV = 'OMX_TEAM_LEADER_CWD';
|
|
|
862
897
|
const WORKTREE_TRIGGER_STATE_ROOT = '$OMX_TEAM_STATE_ROOT';
|
|
863
898
|
const STARTUP_EVIDENCE_TIMEOUT_MS = 2_000;
|
|
864
899
|
const STARTUP_EVIDENCE_POLL_MS = 100;
|
|
900
|
+
const STARTUP_EVIDENCE_LAUNCH_TIMEOUT_MS = 5_000;
|
|
865
901
|
const promptWorkerRegistry = new Map();
|
|
866
902
|
const previousModelInstructionsFileByTeam = new Map();
|
|
867
903
|
const PROMPT_WORKER_SIGTERM_WAIT_MS = 3_000;
|
|
868
904
|
const PROMPT_WORKER_SIGKILL_WAIT_MS = 2_000;
|
|
869
905
|
const PROMPT_WORKER_EXIT_POLL_MS = 100;
|
|
906
|
+
const PROMPT_MODE_CODEX_UNSUPPORTED_REASON = 'prompt_mode_codex_requires_tty';
|
|
907
|
+
// Test-only escape hatch for fake prompt workers that intentionally do not require a real TTY.
|
|
908
|
+
const PROMPT_MODE_CODEX_TEST_ALLOW_ENV = 'OMX_TEST_ALLOW_NONTTY_CODEX_PROMPT';
|
|
870
909
|
function resolveInstructionStateRoot(worktreePath) {
|
|
871
910
|
return worktreePath ? WORKTREE_TRIGGER_STATE_ROOT : undefined;
|
|
872
911
|
}
|
|
912
|
+
function assertPromptModeWorkerCliSupported(workerCliPlan) {
|
|
913
|
+
if (workerCliPlan.some((workerCli) => workerCli === 'codex')
|
|
914
|
+
&& process.env[PROMPT_MODE_CODEX_TEST_ALLOW_ENV] !== '1') {
|
|
915
|
+
throw new Error(`${PROMPT_MODE_CODEX_UNSUPPORTED_REASON}: Codex prompt workers require a terminal; use interactive team mode or set OMX_TEAM_WORKER_CLI=claude/gemini for prompt-mode teammates.`);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
873
918
|
function resolveWorkerReadyTimeoutMs(env) {
|
|
874
919
|
const raw = env.OMX_TEAM_READY_TIMEOUT_MS;
|
|
875
920
|
const parsed = Number.parseInt(String(raw ?? ''), 10);
|
|
@@ -877,6 +922,12 @@ function resolveWorkerReadyTimeoutMs(env) {
|
|
|
877
922
|
return parsed;
|
|
878
923
|
return 45_000;
|
|
879
924
|
}
|
|
925
|
+
function resolveWorkerStartupEvidenceTimeoutMs(env, workerReadyTimeoutMs) {
|
|
926
|
+
const raw = Number.parseInt(String(env.OMX_TEAM_STARTUP_EVIDENCE_TIMEOUT_MS ?? ''), 10);
|
|
927
|
+
if (Number.isFinite(raw) && raw >= 500)
|
|
928
|
+
return raw;
|
|
929
|
+
return Math.max(STARTUP_EVIDENCE_TIMEOUT_MS, Math.min(workerReadyTimeoutMs, STARTUP_EVIDENCE_LAUNCH_TIMEOUT_MS));
|
|
930
|
+
}
|
|
880
931
|
function parseTeamWorkerContext(raw) {
|
|
881
932
|
if (typeof raw !== 'string' || raw.trim() === '')
|
|
882
933
|
return null;
|
|
@@ -954,6 +1005,30 @@ export async function waitForClaudeStartupEvidence(params) {
|
|
|
954
1005
|
function shouldSkipWorkerReadyWait(env) {
|
|
955
1006
|
return env.OMX_TEAM_SKIP_READY_WAIT === '1';
|
|
956
1007
|
}
|
|
1008
|
+
function isRecoverableInteractiveStartupReason(reason) {
|
|
1009
|
+
const normalized = reason.trim().toLowerCase();
|
|
1010
|
+
return normalized.includes('startup_no_evidence')
|
|
1011
|
+
|| normalized.includes('fallback_attempted_but_unconfirmed')
|
|
1012
|
+
|| normalized.includes('ready_prompt_timeout');
|
|
1013
|
+
}
|
|
1014
|
+
async function recordRecoverableStartupIssue(params) {
|
|
1015
|
+
const { teamName, workerName, taskIds, reason, cwd } = params;
|
|
1016
|
+
const updatedAt = new Date().toISOString();
|
|
1017
|
+
await writeWorkerStatus(teamName, workerName, {
|
|
1018
|
+
state: 'unknown',
|
|
1019
|
+
current_task_id: taskIds[0],
|
|
1020
|
+
reason,
|
|
1021
|
+
updated_at: updatedAt,
|
|
1022
|
+
}, cwd).catch(() => { });
|
|
1023
|
+
await appendTeamEvent(teamName, {
|
|
1024
|
+
type: 'worker_state_changed',
|
|
1025
|
+
worker: workerName,
|
|
1026
|
+
state: 'unknown',
|
|
1027
|
+
prev_state: 'unknown',
|
|
1028
|
+
task_id: taskIds[0],
|
|
1029
|
+
reason,
|
|
1030
|
+
}, cwd).catch(() => { });
|
|
1031
|
+
}
|
|
957
1032
|
function setTeamModelInstructionsFile(teamName, filePath) {
|
|
958
1033
|
if (!previousModelInstructionsFileByTeam.has(teamName)) {
|
|
959
1034
|
previousModelInstructionsFileByTeam.set(teamName, process.env[MODEL_INSTRUCTIONS_FILE_ENV]);
|
|
@@ -1258,8 +1333,8 @@ function isPromptWorkerAlive(config, worker) {
|
|
|
1258
1333
|
}
|
|
1259
1334
|
export { TEAM_LOW_COMPLEXITY_DEFAULT_MODEL };
|
|
1260
1335
|
export { resolveCanonicalTeamStateRoot };
|
|
1261
|
-
function spawnPromptWorker(teamName, workerName, workerIndex, workerCwd, launchArgs, workerEnv, workerCli, initialPrompt) {
|
|
1262
|
-
const processSpec = buildWorkerProcessLaunchSpec(teamName, workerIndex, launchArgs, workerCwd, workerEnv, workerCli, initialPrompt);
|
|
1336
|
+
function spawnPromptWorker(teamName, workerName, workerIndex, workerCwd, launchArgs, workerEnv, workerCli, initialPrompt, workerRole) {
|
|
1337
|
+
const processSpec = buildWorkerProcessLaunchSpec(teamName, workerIndex, launchArgs, workerCwd, workerEnv, workerCli, initialPrompt, workerRole);
|
|
1263
1338
|
const child = spawn(processSpec.command, processSpec.args, {
|
|
1264
1339
|
cwd: workerCwd,
|
|
1265
1340
|
detached: process.platform !== 'win32',
|
|
@@ -1402,7 +1477,11 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1402
1477
|
fallbackModel: resolveAgentDefaultModel(agentType, process.env.CODEX_HOME),
|
|
1403
1478
|
});
|
|
1404
1479
|
const workerCliPlan = resolveTeamWorkerCliPlan(workerCount, sharedWorkerLaunchArgs, process.env);
|
|
1480
|
+
if (workerLaunchMode === 'prompt') {
|
|
1481
|
+
assertPromptModeWorkerCliSupported(workerCliPlan);
|
|
1482
|
+
}
|
|
1405
1483
|
const workerReadyTimeoutMs = resolveWorkerReadyTimeoutMs(process.env);
|
|
1484
|
+
const workerStartupEvidenceTimeoutMs = resolveWorkerStartupEvidenceTimeoutMs(process.env, workerReadyTimeoutMs);
|
|
1406
1485
|
const skipWorkerReadyWait = shouldSkipWorkerReadyWait(process.env);
|
|
1407
1486
|
try {
|
|
1408
1487
|
// 3. Init state directory + config
|
|
@@ -1518,9 +1597,53 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1518
1597
|
initialPrompt: plan.initialPrompt,
|
|
1519
1598
|
launchArgs: plan.workerLaunchArgs,
|
|
1520
1599
|
workerCli: plan.workerCli,
|
|
1600
|
+
workerRole: plan.workerRole,
|
|
1521
1601
|
};
|
|
1522
1602
|
});
|
|
1523
1603
|
const workerPaneIds = Array.from({ length: workerCount }, () => undefined);
|
|
1604
|
+
const materializeWorkerStartupState = async (bootstrapPlan, workerIndex, paneId) => {
|
|
1605
|
+
const workerWorkspace = bootstrapPlan.workerWorkspace;
|
|
1606
|
+
const identity = {
|
|
1607
|
+
name: bootstrapPlan.workerName,
|
|
1608
|
+
index: workerIndex,
|
|
1609
|
+
role: bootstrapPlan.workerRole,
|
|
1610
|
+
worker_cli: bootstrapPlan.workerCli,
|
|
1611
|
+
assigned_tasks: bootstrapPlan.workerTasks.map((task) => task.id),
|
|
1612
|
+
working_dir: workerWorkspace.cwd,
|
|
1613
|
+
worktree_repo_root: workerWorkspace.worktreeRepoRoot,
|
|
1614
|
+
worktree_path: workerWorkspace.worktreePath,
|
|
1615
|
+
worktree_branch: workerWorkspace.worktreeBranch,
|
|
1616
|
+
worktree_detached: workerWorkspace.worktreeDetached,
|
|
1617
|
+
worktree_created: workerWorkspace.worktreeCreated,
|
|
1618
|
+
team_state_root: teamStateRoot,
|
|
1619
|
+
};
|
|
1620
|
+
if (workerLaunchMode === 'interactive') {
|
|
1621
|
+
const panePid = getWorkerPanePid(sessionName, workerIndex, paneId);
|
|
1622
|
+
if (panePid)
|
|
1623
|
+
identity.pid = panePid;
|
|
1624
|
+
}
|
|
1625
|
+
else if (config?.workers[workerIndex - 1]?.pid) {
|
|
1626
|
+
identity.pid = config.workers[workerIndex - 1].pid;
|
|
1627
|
+
}
|
|
1628
|
+
if (paneId)
|
|
1629
|
+
identity.pane_id = paneId;
|
|
1630
|
+
if (config?.workers[workerIndex - 1]) {
|
|
1631
|
+
config.workers[workerIndex - 1].pid = identity.pid;
|
|
1632
|
+
config.workers[workerIndex - 1].pane_id = paneId;
|
|
1633
|
+
config.workers[workerIndex - 1].role = bootstrapPlan.workerRole;
|
|
1634
|
+
config.workers[workerIndex - 1].worker_cli = bootstrapPlan.workerCli;
|
|
1635
|
+
config.workers[workerIndex - 1].assigned_tasks = bootstrapPlan.workerTasks.map((task) => task.id);
|
|
1636
|
+
config.workers[workerIndex - 1].working_dir = workerWorkspace.cwd;
|
|
1637
|
+
config.workers[workerIndex - 1].worktree_repo_root = workerWorkspace.worktreeRepoRoot;
|
|
1638
|
+
config.workers[workerIndex - 1].worktree_path = workerWorkspace.worktreePath;
|
|
1639
|
+
config.workers[workerIndex - 1].worktree_branch = workerWorkspace.worktreeBranch;
|
|
1640
|
+
config.workers[workerIndex - 1].worktree_detached = workerWorkspace.worktreeDetached;
|
|
1641
|
+
config.workers[workerIndex - 1].worktree_created = workerWorkspace.worktreeCreated;
|
|
1642
|
+
config.workers[workerIndex - 1].team_state_root = teamStateRoot;
|
|
1643
|
+
}
|
|
1644
|
+
await writeWorkerIdentity(sanitized, bootstrapPlan.workerName, identity, leaderCwd);
|
|
1645
|
+
await writeWorkerInbox(sanitized, bootstrapPlan.workerName, bootstrapPlan.inbox, leaderCwd);
|
|
1646
|
+
};
|
|
1524
1647
|
// 6. Create worker runtime (interactive tmux panes or prompt-mode child processes)
|
|
1525
1648
|
if (workerLaunchMode === 'interactive') {
|
|
1526
1649
|
const createdSession = createTeamSession(sanitized, workerCount, leaderCwd, sharedWorkerLaunchArgs, workerStartups);
|
|
@@ -1539,12 +1662,21 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1539
1662
|
for (let i = 1; i <= workerCount; i++) {
|
|
1540
1663
|
const startup = workerStartups[i - 1] || {};
|
|
1541
1664
|
const workerName = `worker-${i}`;
|
|
1542
|
-
const child = spawnPromptWorker(sanitized, workerName, i, startup.cwd || leaderCwd, startup.launchArgs || sharedWorkerLaunchArgs, startup.env || {}, startup.workerCli || workerCliPlan[i - 1], startup.initialPrompt);
|
|
1665
|
+
const child = spawnPromptWorker(sanitized, workerName, i, startup.cwd || leaderCwd, startup.launchArgs || sharedWorkerLaunchArgs, startup.env || {}, startup.workerCli || workerCliPlan[i - 1], startup.initialPrompt, startup.workerRole);
|
|
1543
1666
|
if (config.workers[i - 1]) {
|
|
1544
1667
|
config.workers[i - 1].pid = child.pid;
|
|
1545
1668
|
}
|
|
1546
1669
|
}
|
|
1547
1670
|
}
|
|
1671
|
+
// Materialize durable startup state for every worker before any per-worker
|
|
1672
|
+
// readiness wait or startup-evidence gate can block later workers.
|
|
1673
|
+
for (let i = 1; i <= workerCount; i++) {
|
|
1674
|
+
const bootstrapPlan = workerBootstrapPlans[i - 1];
|
|
1675
|
+
if (!bootstrapPlan) {
|
|
1676
|
+
throw new Error(`missing bootstrap plan for worker-${i}`);
|
|
1677
|
+
}
|
|
1678
|
+
await materializeWorkerStartupState(bootstrapPlan, i, workerPaneIds[i - 1]);
|
|
1679
|
+
}
|
|
1548
1680
|
await saveTeamConfig(config, leaderCwd);
|
|
1549
1681
|
// 7. Wait for all workers to be ready (interactive mode), then bootstrap them
|
|
1550
1682
|
const manifest = await readTeamManifestV2(sanitized, leaderCwd);
|
|
@@ -1554,64 +1686,33 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1554
1686
|
if (!bootstrapPlan) {
|
|
1555
1687
|
throw new Error(`missing bootstrap plan for worker-${i}`);
|
|
1556
1688
|
}
|
|
1557
|
-
const { workerName, paneId, workerTasks,
|
|
1689
|
+
const { workerName, paneId, workerTasks, inbox, trigger, triggerIntent, initialPrompt } = {
|
|
1558
1690
|
workerName: bootstrapPlan.workerName,
|
|
1559
1691
|
paneId: workerPaneIds[i - 1],
|
|
1560
1692
|
workerTasks: bootstrapPlan.workerTasks,
|
|
1561
|
-
workerRole: bootstrapPlan.workerRole,
|
|
1562
1693
|
inbox: bootstrapPlan.inbox,
|
|
1563
1694
|
trigger: bootstrapPlan.trigger,
|
|
1564
1695
|
triggerIntent: bootstrapPlan.triggerIntent,
|
|
1565
1696
|
initialPrompt: bootstrapPlan.initialPrompt,
|
|
1566
1697
|
};
|
|
1567
|
-
const workerWorkspace = bootstrapPlan.workerWorkspace;
|
|
1568
1698
|
if (workerTasks.map(t => t.role).filter(Boolean).length > 0 && new Set(workerTasks.map(t => t.role).filter(Boolean)).size > 1) {
|
|
1569
1699
|
console.log(`[omx:team] ${workerName}: mixed task roles [${[...new Set(workerTasks.map(t => t.role).filter(Boolean))].join(', ')}], falling back to ${agentType}`);
|
|
1570
1700
|
}
|
|
1571
|
-
// Write worker identity
|
|
1572
|
-
const identity = {
|
|
1573
|
-
name: workerName,
|
|
1574
|
-
index: i,
|
|
1575
|
-
role: workerRole,
|
|
1576
|
-
worker_cli: workerCliPlan[i - 1],
|
|
1577
|
-
assigned_tasks: workerTasks.map(t => t.id),
|
|
1578
|
-
working_dir: workerWorkspace.cwd,
|
|
1579
|
-
worktree_repo_root: workerWorkspace.worktreeRepoRoot,
|
|
1580
|
-
worktree_path: workerWorkspace.worktreePath,
|
|
1581
|
-
worktree_branch: workerWorkspace.worktreeBranch,
|
|
1582
|
-
worktree_detached: workerWorkspace.worktreeDetached,
|
|
1583
|
-
worktree_created: workerWorkspace.worktreeCreated,
|
|
1584
|
-
team_state_root: teamStateRoot,
|
|
1585
|
-
};
|
|
1586
|
-
// Get pane PID and store it (interactive mode) or process PID (prompt mode)
|
|
1587
|
-
if (workerLaunchMode === 'interactive') {
|
|
1588
|
-
const panePid = getWorkerPanePid(sessionName, i, paneId);
|
|
1589
|
-
if (panePid)
|
|
1590
|
-
identity.pid = panePid;
|
|
1591
|
-
}
|
|
1592
|
-
else if (config.workers[i - 1]?.pid) {
|
|
1593
|
-
identity.pid = config.workers[i - 1].pid;
|
|
1594
|
-
}
|
|
1595
|
-
if (paneId)
|
|
1596
|
-
identity.pane_id = paneId;
|
|
1597
|
-
if (config.workers[i - 1]) {
|
|
1598
|
-
config.workers[i - 1].pid = identity.pid;
|
|
1599
|
-
config.workers[i - 1].pane_id = paneId;
|
|
1600
|
-
config.workers[i - 1].role = workerRole;
|
|
1601
|
-
config.workers[i - 1].worker_cli = workerCliPlan[i - 1];
|
|
1602
|
-
config.workers[i - 1].working_dir = workerWorkspace.cwd;
|
|
1603
|
-
config.workers[i - 1].worktree_repo_root = workerWorkspace.worktreeRepoRoot;
|
|
1604
|
-
config.workers[i - 1].worktree_path = workerWorkspace.worktreePath;
|
|
1605
|
-
config.workers[i - 1].worktree_branch = workerWorkspace.worktreeBranch;
|
|
1606
|
-
config.workers[i - 1].worktree_detached = workerWorkspace.worktreeDetached;
|
|
1607
|
-
config.workers[i - 1].worktree_created = workerWorkspace.worktreeCreated;
|
|
1608
|
-
config.workers[i - 1].team_state_root = teamStateRoot;
|
|
1609
|
-
}
|
|
1610
|
-
await writeWorkerIdentity(sanitized, workerName, identity, leaderCwd);
|
|
1611
1701
|
// Wait for worker readiness
|
|
1612
1702
|
if (workerLaunchMode === 'interactive' && !skipWorkerReadyWait && !initialPrompt) {
|
|
1613
1703
|
const ready = waitForWorkerReady(sessionName, i, workerReadyTimeoutMs, paneId);
|
|
1614
1704
|
if (!ready) {
|
|
1705
|
+
const workerAlive = isWorkerPaneOpen(sessionName, i, paneId);
|
|
1706
|
+
if (workerAlive) {
|
|
1707
|
+
await recordRecoverableStartupIssue({
|
|
1708
|
+
teamName: sanitized,
|
|
1709
|
+
workerName,
|
|
1710
|
+
taskIds: workerTasks.map((task) => task.id),
|
|
1711
|
+
reason: 'ready_prompt_timeout',
|
|
1712
|
+
cwd: leaderCwd,
|
|
1713
|
+
});
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1615
1716
|
throw new Error(`Worker ${workerName} did not become ready in tmux session ${sessionName}`);
|
|
1616
1717
|
}
|
|
1617
1718
|
}
|
|
@@ -1639,6 +1740,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1639
1740
|
dispatchPolicy,
|
|
1640
1741
|
inboxCorrelationKey: `startup:${workerName}`,
|
|
1641
1742
|
requireWorkerStartupEvidence: true,
|
|
1743
|
+
startupEvidenceTimeoutMs: workerStartupEvidenceTimeoutMs,
|
|
1642
1744
|
});
|
|
1643
1745
|
if (dispatchOutcome.ok)
|
|
1644
1746
|
break;
|
|
@@ -1659,7 +1761,22 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
1659
1761
|
}
|
|
1660
1762
|
}
|
|
1661
1763
|
if (!dispatchOutcome.ok) {
|
|
1662
|
-
|
|
1764
|
+
const workerAlive = workerLaunchMode === 'prompt'
|
|
1765
|
+
? isPromptWorkerAlive(config, config.workers[i - 1])
|
|
1766
|
+
: isWorkerPaneOpen(sessionName, i, paneId);
|
|
1767
|
+
if (workerLaunchMode === 'interactive'
|
|
1768
|
+
&& workerAlive
|
|
1769
|
+
&& isRecoverableInteractiveStartupReason(dispatchOutcome.reason)) {
|
|
1770
|
+
await recordRecoverableStartupIssue({
|
|
1771
|
+
teamName: sanitized,
|
|
1772
|
+
workerName,
|
|
1773
|
+
taskIds: workerTasks.map((task) => task.id),
|
|
1774
|
+
reason: dispatchOutcome.reason,
|
|
1775
|
+
cwd: leaderCwd,
|
|
1776
|
+
});
|
|
1777
|
+
continue;
|
|
1778
|
+
}
|
|
1779
|
+
throw new Error(`worker_notify_failed:${workerName}:${dispatchOutcome.reason}`);
|
|
1663
1780
|
}
|
|
1664
1781
|
}
|
|
1665
1782
|
await saveTeamConfig(config, leaderCwd);
|
|
@@ -2118,10 +2235,14 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2118
2235
|
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
2119
2236
|
}
|
|
2120
2237
|
await cleanupTeamState(sanitized, cwd);
|
|
2238
|
+
await syncTeamModeStateOnShutdown(sanitized, cwd);
|
|
2121
2239
|
restoreTeamModelInstructionsFile(sanitized);
|
|
2122
2240
|
return { commitHygieneArtifacts: null };
|
|
2123
2241
|
}
|
|
2124
2242
|
const manifest = await readTeamManifestV2(sanitized, cwd);
|
|
2243
|
+
const leaderSessionId = typeof manifest?.leader?.session_id === 'string'
|
|
2244
|
+
? manifest.leader.session_id.trim()
|
|
2245
|
+
: '';
|
|
2125
2246
|
const governance = resolveGovernancePolicy(manifest?.governance, manifest?.policy);
|
|
2126
2247
|
if (!force) {
|
|
2127
2248
|
const classification = await classifyShutdown({
|
|
@@ -2232,8 +2353,20 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2232
2353
|
const leaderPaneId = config.leader_pane_id;
|
|
2233
2354
|
const hudPaneId = config.hud_pane_id;
|
|
2234
2355
|
if (config.worker_launch_mode === 'interactive') {
|
|
2235
|
-
const
|
|
2236
|
-
|
|
2356
|
+
const sharedSessionTopology = sessionName.includes(':')
|
|
2357
|
+
? resolveSharedSessionShutdownTopology(sessionName, leaderPaneId)
|
|
2358
|
+
: null;
|
|
2359
|
+
const effectiveLeaderPaneId = sharedSessionTopology?.leaderPaneId ?? leaderPaneId;
|
|
2360
|
+
const effectiveHudPaneId = sharedSessionTopology?.hudPaneIds.find((paneId) => paneId === hudPaneId)
|
|
2361
|
+
?? sharedSessionTopology?.hudPaneIds[0]
|
|
2362
|
+
?? hudPaneId;
|
|
2363
|
+
const livePaneIds = sharedSessionTopology?.livePaneIds ?? listPaneIds(sessionName);
|
|
2364
|
+
let shutdownPaneIds = collectShutdownPaneIds({
|
|
2365
|
+
config,
|
|
2366
|
+
livePaneIds,
|
|
2367
|
+
leaderPaneId: effectiveLeaderPaneId,
|
|
2368
|
+
hudPaneId: effectiveHudPaneId,
|
|
2369
|
+
});
|
|
2237
2370
|
if (shouldPrekillInteractiveShutdownProcessTrees(sessionName)) {
|
|
2238
2371
|
const workerPanePids = shutdownPaneIds
|
|
2239
2372
|
.map((paneId) => getWorkerPanePid(sessionName, 1, paneId))
|
|
@@ -2261,10 +2394,10 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2261
2394
|
console.warn(`[team shutdown] ${sanitized}: ${resizeHookWarning}; continuing teardown`);
|
|
2262
2395
|
}
|
|
2263
2396
|
let restoredHudPaneId = null;
|
|
2264
|
-
if (
|
|
2265
|
-
await killWorkerByPaneIdAsync(
|
|
2397
|
+
if (effectiveHudPaneId) {
|
|
2398
|
+
await killWorkerByPaneIdAsync(effectiveHudPaneId, effectiveLeaderPaneId ?? undefined);
|
|
2266
2399
|
if (sessionName.includes(':')) {
|
|
2267
|
-
restoredHudPaneId = restoreStandaloneHudPane(
|
|
2400
|
+
restoredHudPaneId = restoreStandaloneHudPane(effectiveLeaderPaneId, cwd);
|
|
2268
2401
|
if (!restoredHudPaneId) {
|
|
2269
2402
|
console.warn(`[team shutdown] ${sanitized}: failed to restore standalone HUD pane`);
|
|
2270
2403
|
}
|
|
@@ -2274,10 +2407,12 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2274
2407
|
config,
|
|
2275
2408
|
livePaneIds: listPaneIds(sessionName),
|
|
2276
2409
|
restoredStandaloneHudPaneId: restoredHudPaneId,
|
|
2410
|
+
leaderPaneId: effectiveLeaderPaneId,
|
|
2411
|
+
hudPaneId: effectiveHudPaneId,
|
|
2277
2412
|
});
|
|
2278
2413
|
await teardownWorkerPanes(shutdownPaneIds, {
|
|
2279
|
-
leaderPaneId,
|
|
2280
|
-
hudPaneId: restoredHudPaneId ??
|
|
2414
|
+
leaderPaneId: effectiveLeaderPaneId,
|
|
2415
|
+
hudPaneId: restoredHudPaneId ?? effectiveHudPaneId,
|
|
2281
2416
|
});
|
|
2282
2417
|
// 4. Destroy tmux session
|
|
2283
2418
|
if (!sessionName.includes(':')) {
|
|
@@ -2376,12 +2511,17 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
2376
2511
|
}
|
|
2377
2512
|
}
|
|
2378
2513
|
// 7. Cleanup state
|
|
2514
|
+
let teamStateCleaned = false;
|
|
2379
2515
|
try {
|
|
2380
2516
|
await cleanupTeamState(sanitized, cwd);
|
|
2517
|
+
teamStateCleaned = true;
|
|
2381
2518
|
}
|
|
2382
2519
|
catch (err) {
|
|
2383
2520
|
cleanupErrors.push(`cleanupTeamState: ${String(err)}`);
|
|
2384
2521
|
}
|
|
2522
|
+
if (teamStateCleaned) {
|
|
2523
|
+
await syncTeamModeStateOnShutdown(sanitized, cwd, leaderSessionId);
|
|
2524
|
+
}
|
|
2385
2525
|
if (cleanupErrors.length > 0) {
|
|
2386
2526
|
throw new Error(cleanupErrors.join(' | '));
|
|
2387
2527
|
}
|
|
@@ -2652,7 +2792,7 @@ async function markDispatchRequestLeaderPaneMissingDeferred(params) {
|
|
|
2652
2792
|
}, cwd).catch(() => { });
|
|
2653
2793
|
}
|
|
2654
2794
|
async function dispatchCriticalInboxInstruction(params) {
|
|
2655
|
-
const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, cwd, dispatchPolicy, inboxCorrelationKey, requireWorkerStartupEvidence, } = params;
|
|
2795
|
+
const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, cwd, dispatchPolicy, inboxCorrelationKey, requireWorkerStartupEvidence, startupEvidenceTimeoutMs, } = params;
|
|
2656
2796
|
if (config.worker_launch_mode === 'prompt') {
|
|
2657
2797
|
return await queueInboxInstruction({
|
|
2658
2798
|
teamName,
|
|
@@ -2720,6 +2860,7 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
2720
2860
|
workerName,
|
|
2721
2861
|
workerCli,
|
|
2722
2862
|
cwd,
|
|
2863
|
+
timeoutMs: startupEvidenceTimeoutMs,
|
|
2723
2864
|
});
|
|
2724
2865
|
if (startupEvidence !== 'none') {
|
|
2725
2866
|
return {
|
|
@@ -2733,7 +2874,27 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
2733
2874
|
if (receipt?.status === 'failed') {
|
|
2734
2875
|
const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
2735
2876
|
if (fallback.ok) {
|
|
2736
|
-
|
|
2877
|
+
const fallbackStartupEvidence = await waitForRequiredStartupEvidenceAfterDirectFallback({
|
|
2878
|
+
requireWorkerStartupEvidence,
|
|
2879
|
+
workerCli,
|
|
2880
|
+
teamName,
|
|
2881
|
+
workerName,
|
|
2882
|
+
cwd,
|
|
2883
|
+
timeoutMs: startupEvidenceTimeoutMs,
|
|
2884
|
+
});
|
|
2885
|
+
if (requiresObservedStartupEvidence && fallbackStartupEvidence === 'none') {
|
|
2886
|
+
await transitionDispatchRequest(teamName, queued.request_id, 'failed', 'failed', { last_reason: `${workerCli}_startup_no_evidence_after_fallback:${fallback.reason}` }, cwd).catch(() => { });
|
|
2887
|
+
return {
|
|
2888
|
+
ok: false,
|
|
2889
|
+
transport: fallback.transport,
|
|
2890
|
+
reason: `${workerCli}_startup_no_evidence_after_fallback:${fallback.reason}`,
|
|
2891
|
+
request_id: queued.request_id,
|
|
2892
|
+
};
|
|
2893
|
+
}
|
|
2894
|
+
const current = await readDispatchRequest(teamName, queued.request_id, cwd);
|
|
2895
|
+
if (current) {
|
|
2896
|
+
await transitionDispatchRequest(teamName, queued.request_id, current.status, 'failed', { last_reason: `fallback_confirmed_after_failed_receipt:${fallback.reason}` }, cwd).catch(() => { });
|
|
2897
|
+
}
|
|
2737
2898
|
return {
|
|
2738
2899
|
ok: true,
|
|
2739
2900
|
transport: fallback.transport,
|
|
@@ -2757,9 +2918,32 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
2757
2918
|
? `${startupFallbackLabel}_fallback_failed:${fallback.reason}`
|
|
2758
2919
|
: `fallback_attempted_but_unconfirmed:${fallback.reason}`;
|
|
2759
2920
|
if (fallback.ok) {
|
|
2921
|
+
const fallbackStartupEvidence = await waitForRequiredStartupEvidenceAfterDirectFallback({
|
|
2922
|
+
requireWorkerStartupEvidence,
|
|
2923
|
+
workerCli,
|
|
2924
|
+
teamName,
|
|
2925
|
+
workerName,
|
|
2926
|
+
cwd,
|
|
2927
|
+
timeoutMs: startupEvidenceTimeoutMs,
|
|
2928
|
+
});
|
|
2929
|
+
if (requiresObservedStartupEvidence && fallbackStartupEvidence === 'none') {
|
|
2930
|
+
const current = await readDispatchRequest(teamName, queued.request_id, cwd);
|
|
2931
|
+
if (current && current.status !== 'failed') {
|
|
2932
|
+
await transitionDispatchRequest(teamName, queued.request_id, current.status, 'failed', { last_reason: `${workerCli}_startup_no_evidence_after_fallback:${fallback.reason}` }, cwd).catch(() => { });
|
|
2933
|
+
}
|
|
2934
|
+
return {
|
|
2935
|
+
ok: false,
|
|
2936
|
+
transport: fallback.transport,
|
|
2937
|
+
reason: `${workerCli}_startup_no_evidence_after_fallback:${fallback.reason}`,
|
|
2938
|
+
request_id: queued.request_id,
|
|
2939
|
+
};
|
|
2940
|
+
}
|
|
2760
2941
|
const marked = await markDispatchRequestNotified(teamName, queued.request_id, { last_reason: `fallback_confirmed:${fallback.reason}` }, cwd);
|
|
2761
2942
|
if (!marked) {
|
|
2762
|
-
await
|
|
2943
|
+
const current = await readDispatchRequest(teamName, queued.request_id, cwd);
|
|
2944
|
+
if (current) {
|
|
2945
|
+
await transitionDispatchRequest(teamName, queued.request_id, current.status, 'failed', { last_reason: `fallback_confirmed_after_failed_receipt:${fallback.reason}` }, cwd).catch(() => { });
|
|
2946
|
+
}
|
|
2763
2947
|
}
|
|
2764
2948
|
return {
|
|
2765
2949
|
ok: true,
|
|
@@ -2781,6 +2965,21 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
2781
2965
|
request_id: queued.request_id,
|
|
2782
2966
|
};
|
|
2783
2967
|
}
|
|
2968
|
+
async function waitForRequiredStartupEvidenceAfterDirectFallback(params) {
|
|
2969
|
+
const { requireWorkerStartupEvidence, workerCli, teamName, workerName, cwd, timeoutMs, } = params;
|
|
2970
|
+
const requiresObservedStartupEvidence = requireWorkerStartupEvidence === true
|
|
2971
|
+
&& (workerCli === 'claude' || workerCli === 'codex');
|
|
2972
|
+
if (!requiresObservedStartupEvidence || !workerCli) {
|
|
2973
|
+
return 'none';
|
|
2974
|
+
}
|
|
2975
|
+
return await waitForWorkerStartupEvidence({
|
|
2976
|
+
teamName,
|
|
2977
|
+
workerName,
|
|
2978
|
+
workerCli,
|
|
2979
|
+
cwd,
|
|
2980
|
+
timeoutMs,
|
|
2981
|
+
});
|
|
2982
|
+
}
|
|
2784
2983
|
async function finalizeHookPreferredMailboxDispatch(params) {
|
|
2785
2984
|
const { teamName, requestId, workerName, workerIndex, paneId, messageId, triggerMessage, intent, config, dispatchPolicy, cwd, fallbackNotify, } = params;
|
|
2786
2985
|
const receipt = await waitForDispatchReceipt(teamName, requestId, cwd, {
|
|
@@ -2801,7 +3000,10 @@ async function finalizeHookPreferredMailboxDispatch(params) {
|
|
|
2801
3000
|
if (receipt?.status === 'failed') {
|
|
2802
3001
|
if (fallback.ok) {
|
|
2803
3002
|
await markMessageNotified(teamName, workerName, messageId, cwd).catch(() => false);
|
|
2804
|
-
await
|
|
3003
|
+
const current = await readDispatchRequest(teamName, requestId, cwd);
|
|
3004
|
+
if (current) {
|
|
3005
|
+
await transitionDispatchRequest(teamName, requestId, current.status, 'failed', { message_id: messageId, last_reason: `fallback_confirmed_after_failed_receipt:${fallback.reason}` }, cwd).catch(() => null);
|
|
3006
|
+
}
|
|
2805
3007
|
const outcome = {
|
|
2806
3008
|
ok: true,
|
|
2807
3009
|
transport: fallback.transport,
|
|
@@ -2844,7 +3046,10 @@ async function finalizeHookPreferredMailboxDispatch(params) {
|
|
|
2844
3046
|
await markMessageNotified(teamName, workerName, messageId, cwd).catch(() => false);
|
|
2845
3047
|
const marked = await markDispatchRequestNotified(teamName, requestId, { message_id: messageId, last_reason: `fallback_confirmed:${fallback.reason}` }, cwd);
|
|
2846
3048
|
if (!marked) {
|
|
2847
|
-
await
|
|
3049
|
+
const current = await readDispatchRequest(teamName, requestId, cwd);
|
|
3050
|
+
if (current) {
|
|
3051
|
+
await transitionDispatchRequest(teamName, requestId, current.status, 'failed', { message_id: messageId, last_reason: `fallback_confirmed_after_failed_receipt:${fallback.reason}` }, cwd).catch(() => { });
|
|
3052
|
+
}
|
|
2848
3053
|
}
|
|
2849
3054
|
const outcome = {
|
|
2850
3055
|
ok: true,
|