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
|
@@ -91,6 +91,7 @@ async function writeJsonAtomic(path, value) {
|
|
|
91
91
|
}
|
|
92
92
|
// Keep stale-timeout semantics aligned with src/team/state.ts LOCK_STALE_MS.
|
|
93
93
|
const DISPATCH_LOCK_STALE_MS = 5 * 60 * 1000;
|
|
94
|
+
const DISPATCH_REQUEST_LEASE_STALE_MS = 30 * 1000;
|
|
94
95
|
const DEFAULT_ISSUE_DISPATCH_COOLDOWN_MS = 15 * 60 * 1000;
|
|
95
96
|
const ISSUE_DISPATCH_COOLDOWN_ENV = 'OMX_TEAM_DISPATCH_ISSUE_COOLDOWN_MS';
|
|
96
97
|
const DEFAULT_DISPATCH_TRIGGER_COOLDOWN_MS = 30 * 1000;
|
|
@@ -171,6 +172,21 @@ function parseTriggerCooldownEntry(entry) {
|
|
|
171
172
|
lastRequestId: safeString(entry.last_request_id).trim(),
|
|
172
173
|
};
|
|
173
174
|
}
|
|
175
|
+
function reserveDispatchCooldowns({ issueCooldownMs, triggerCooldownMs, issueCooldownByIssue, triggerCooldownByKey, issueKey, triggerKey, requestId, reservedAt = Date.now(), }) {
|
|
176
|
+
let mutated = false;
|
|
177
|
+
if (issueKey && issueCooldownMs > 0) {
|
|
178
|
+
issueCooldownByIssue[issueKey] = reservedAt;
|
|
179
|
+
mutated = true;
|
|
180
|
+
}
|
|
181
|
+
if (triggerKey && triggerCooldownMs > 0) {
|
|
182
|
+
triggerCooldownByKey[triggerKey] = {
|
|
183
|
+
at: reservedAt,
|
|
184
|
+
last_request_id: safeString(requestId).trim(),
|
|
185
|
+
};
|
|
186
|
+
mutated = true;
|
|
187
|
+
}
|
|
188
|
+
return mutated;
|
|
189
|
+
}
|
|
174
190
|
async function withLockDirectory(lockDir, timeoutError, fn) {
|
|
175
191
|
const ownerPath = join(lockDir, 'owner');
|
|
176
192
|
const ownerToken = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
|
|
@@ -227,6 +243,50 @@ async function withDispatchLock(teamDirPath, fn) {
|
|
|
227
243
|
async function withMailboxLock(teamDirPath, workerName, fn) {
|
|
228
244
|
return await withLockDirectory(join(teamDirPath, 'mailbox', `.lock-${workerName}`), `Timed out acquiring mailbox lock for ${teamDirPath}/${workerName}`, fn);
|
|
229
245
|
}
|
|
246
|
+
function dispatchRequestLeaseDir(teamDirPath, requestId) {
|
|
247
|
+
return join(teamDirPath, 'dispatch', `.processing-${safeString(requestId).trim()}`);
|
|
248
|
+
}
|
|
249
|
+
async function tryAcquireDispatchRequestLease(teamDirPath, requestId) {
|
|
250
|
+
const lockDir = dispatchRequestLeaseDir(teamDirPath, requestId);
|
|
251
|
+
const ownerPath = join(lockDir, 'owner');
|
|
252
|
+
const ownerToken = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
|
|
253
|
+
await mkdir(dirname(lockDir), { recursive: true });
|
|
254
|
+
while (true) {
|
|
255
|
+
try {
|
|
256
|
+
await mkdir(lockDir, { recursive: false });
|
|
257
|
+
await writeFile(ownerPath, ownerToken, 'utf8');
|
|
258
|
+
return { lockDir, ownerPath, ownerToken, requestId };
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
if (error?.code !== 'EEXIST')
|
|
262
|
+
throw error;
|
|
263
|
+
try {
|
|
264
|
+
const info = await stat(lockDir);
|
|
265
|
+
if (Date.now() - info.mtimeMs > DISPATCH_REQUEST_LEASE_STALE_MS) {
|
|
266
|
+
await rm(lockDir, { recursive: true, force: true });
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
// best effort
|
|
272
|
+
}
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async function releaseDispatchRequestLease(lease) {
|
|
278
|
+
if (!lease?.lockDir || !lease?.ownerPath || !lease?.ownerToken)
|
|
279
|
+
return;
|
|
280
|
+
try {
|
|
281
|
+
const currentOwner = await readFile(lease.ownerPath, 'utf8');
|
|
282
|
+
if (currentOwner.trim() === lease.ownerToken) {
|
|
283
|
+
await rm(lease.lockDir, { recursive: true, force: true });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// best effort
|
|
288
|
+
}
|
|
289
|
+
}
|
|
230
290
|
function resolveLeaderPaneId(config) {
|
|
231
291
|
return safeString(config?.leader_pane_id).trim();
|
|
232
292
|
}
|
|
@@ -307,6 +367,199 @@ async function appendLeaderNotificationDeferredEvent({ stateDir, teamName, reque
|
|
|
307
367
|
await mkdir(eventsDir, { recursive: true }).catch(() => { });
|
|
308
368
|
await appendFile(eventsPath, JSON.stringify(event) + '\n').catch(() => { });
|
|
309
369
|
}
|
|
370
|
+
async function finalizeClaimedDispatchRequest({ claim, result, teamName, teamDirPath, config, cwd, stateDir, logsDir, issueCooldownMs, triggerCooldownMs, }) {
|
|
371
|
+
const requestsPath = join(teamDirPath, 'dispatch', 'requests.json');
|
|
372
|
+
const issueKey = extractIssueKey(claim.request.trigger_message);
|
|
373
|
+
const triggerKey = normalizeTriggerKey(claim.request.trigger_message);
|
|
374
|
+
let summary = { processed: 0, skipped: 0, failed: 0 };
|
|
375
|
+
await withDispatchLock(teamDirPath, async () => {
|
|
376
|
+
const bridgeRequests = await readBridgeDispatchRequests(stateDir, teamName);
|
|
377
|
+
const usingLegacyRequests = bridgeRequests === null;
|
|
378
|
+
const requests = usingLegacyRequests ? await readJson(requestsPath, []) : bridgeRequests;
|
|
379
|
+
if (!Array.isArray(requests))
|
|
380
|
+
return;
|
|
381
|
+
const index = requests.findIndex((entry) => safeString(entry?.request_id).trim() === claim.request.request_id);
|
|
382
|
+
if (index < 0)
|
|
383
|
+
return;
|
|
384
|
+
const request = requests[index];
|
|
385
|
+
if (!request || typeof request !== 'object' || shouldSkipRequest(request) || request.status !== 'pending')
|
|
386
|
+
return;
|
|
387
|
+
const issueCooldownState = await readIssueCooldownState(teamDirPath);
|
|
388
|
+
const triggerCooldownState = await readTriggerCooldownState(teamDirPath);
|
|
389
|
+
const issueCooldownByIssue = issueCooldownState.by_issue || {};
|
|
390
|
+
const triggerCooldownByKey = triggerCooldownState.by_trigger || {};
|
|
391
|
+
const nowIso = new Date().toISOString();
|
|
392
|
+
let mutated = false;
|
|
393
|
+
mutated = reserveDispatchCooldowns({
|
|
394
|
+
issueCooldownMs,
|
|
395
|
+
triggerCooldownMs,
|
|
396
|
+
issueCooldownByIssue,
|
|
397
|
+
triggerCooldownByKey,
|
|
398
|
+
issueKey,
|
|
399
|
+
triggerKey,
|
|
400
|
+
requestId: request.request_id,
|
|
401
|
+
}) || mutated;
|
|
402
|
+
request.attempt_count = Number.isFinite(request.attempt_count) ? Math.max(0, request.attempt_count + 1) : 1;
|
|
403
|
+
request.updated_at = nowIso;
|
|
404
|
+
if (result.ok) {
|
|
405
|
+
const MAX_UNCONFIRMED_ATTEMPTS = 3;
|
|
406
|
+
if (result.reason === 'tmux_send_keys_unconfirmed' && request.attempt_count < MAX_UNCONFIRMED_ATTEMPTS) {
|
|
407
|
+
request.last_reason = result.reason;
|
|
408
|
+
summary.skipped += 1;
|
|
409
|
+
mutated = true;
|
|
410
|
+
await appendDispatchLog(logsDir, {
|
|
411
|
+
type: 'dispatch_unconfirmed_retry',
|
|
412
|
+
team: teamName,
|
|
413
|
+
request_id: request.request_id,
|
|
414
|
+
worker: request.to_worker,
|
|
415
|
+
attempt: request.attempt_count,
|
|
416
|
+
reason: result.reason,
|
|
417
|
+
...buildDispatchAttemptEvidence(result),
|
|
418
|
+
});
|
|
419
|
+
await appendDeliveryTelemetry(logsDir, {
|
|
420
|
+
event: 'dispatch_result',
|
|
421
|
+
team: teamName,
|
|
422
|
+
request_id: request.request_id,
|
|
423
|
+
message_id: request.message_id || null,
|
|
424
|
+
to_worker: request.to_worker,
|
|
425
|
+
transport: 'send-keys',
|
|
426
|
+
result: 'retry',
|
|
427
|
+
reason: result.reason,
|
|
428
|
+
});
|
|
429
|
+
await emitOperationalHookEvent(cwd, 'retry-needed', {
|
|
430
|
+
team: teamName,
|
|
431
|
+
worker: request.to_worker,
|
|
432
|
+
request_id: request.request_id,
|
|
433
|
+
attempt: request.attempt_count,
|
|
434
|
+
command: request.trigger_message,
|
|
435
|
+
reason: result.reason,
|
|
436
|
+
status: 'retry-needed',
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
else if (result.reason === 'tmux_send_keys_unconfirmed') {
|
|
440
|
+
request.status = 'failed';
|
|
441
|
+
request.failed_at = nowIso;
|
|
442
|
+
request.last_reason = 'unconfirmed_after_max_retries';
|
|
443
|
+
runtimeExec({ command: 'MarkFailed', request_id: request.request_id, reason: 'unconfirmed_after_max_retries' }, stateDir);
|
|
444
|
+
summary.processed += 1;
|
|
445
|
+
summary.failed += 1;
|
|
446
|
+
mutated = true;
|
|
447
|
+
await appendDispatchLog(logsDir, {
|
|
448
|
+
type: 'dispatch_failed',
|
|
449
|
+
team: teamName,
|
|
450
|
+
request_id: request.request_id,
|
|
451
|
+
worker: request.to_worker,
|
|
452
|
+
message_id: request.message_id || null,
|
|
453
|
+
reason: request.last_reason,
|
|
454
|
+
...buildDispatchAttemptEvidence(result),
|
|
455
|
+
});
|
|
456
|
+
await appendDeliveryTelemetry(logsDir, {
|
|
457
|
+
event: 'dispatch_result',
|
|
458
|
+
team: teamName,
|
|
459
|
+
request_id: request.request_id,
|
|
460
|
+
message_id: request.message_id || null,
|
|
461
|
+
to_worker: request.to_worker,
|
|
462
|
+
transport: 'send-keys',
|
|
463
|
+
result: 'failed',
|
|
464
|
+
reason: request.last_reason,
|
|
465
|
+
});
|
|
466
|
+
await emitOperationalHookEvent(cwd, 'failed', {
|
|
467
|
+
team: teamName,
|
|
468
|
+
worker: request.to_worker,
|
|
469
|
+
request_id: request.request_id,
|
|
470
|
+
message_id: request.message_id || null,
|
|
471
|
+
command: request.trigger_message,
|
|
472
|
+
reason: request.last_reason,
|
|
473
|
+
error_summary: request.last_reason,
|
|
474
|
+
status: 'failed',
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
request.status = 'notified';
|
|
479
|
+
request.notified_at = nowIso;
|
|
480
|
+
request.last_reason = result.reason;
|
|
481
|
+
runtimeExec({ command: 'MarkNotified', request_id: request.request_id, channel: 'tmux' }, stateDir);
|
|
482
|
+
if (request.kind === 'mailbox' && request.message_id) {
|
|
483
|
+
runtimeExec({ command: 'MarkMailboxNotified', message_id: request.message_id }, stateDir);
|
|
484
|
+
if (usingLegacyRequests) {
|
|
485
|
+
await updateMailboxNotified(stateDir, teamName, request.to_worker, request.message_id).catch(() => { });
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
summary.processed += 1;
|
|
489
|
+
mutated = true;
|
|
490
|
+
await appendDispatchLog(logsDir, {
|
|
491
|
+
type: 'dispatch_notified',
|
|
492
|
+
team: teamName,
|
|
493
|
+
request_id: request.request_id,
|
|
494
|
+
worker: request.to_worker,
|
|
495
|
+
message_id: request.message_id || null,
|
|
496
|
+
reason: result.reason,
|
|
497
|
+
...buildDispatchAttemptEvidence(result),
|
|
498
|
+
});
|
|
499
|
+
await appendDeliveryTelemetry(logsDir, {
|
|
500
|
+
event: 'dispatch_result',
|
|
501
|
+
team: teamName,
|
|
502
|
+
request_id: request.request_id,
|
|
503
|
+
message_id: request.message_id || null,
|
|
504
|
+
to_worker: request.to_worker,
|
|
505
|
+
transport: 'send-keys',
|
|
506
|
+
result: 'notified',
|
|
507
|
+
reason: result.reason,
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
request.status = 'failed';
|
|
513
|
+
request.failed_at = nowIso;
|
|
514
|
+
request.last_reason = result.reason;
|
|
515
|
+
runtimeExec({ command: 'MarkFailed', request_id: request.request_id, reason: result.reason }, stateDir);
|
|
516
|
+
summary.processed += 1;
|
|
517
|
+
summary.failed += 1;
|
|
518
|
+
mutated = true;
|
|
519
|
+
await appendDispatchLog(logsDir, {
|
|
520
|
+
type: 'dispatch_failed',
|
|
521
|
+
team: teamName,
|
|
522
|
+
request_id: request.request_id,
|
|
523
|
+
worker: request.to_worker,
|
|
524
|
+
message_id: request.message_id || null,
|
|
525
|
+
reason: result.reason,
|
|
526
|
+
...buildDispatchAttemptEvidence(result),
|
|
527
|
+
});
|
|
528
|
+
await appendDeliveryTelemetry(logsDir, {
|
|
529
|
+
event: 'dispatch_result',
|
|
530
|
+
team: teamName,
|
|
531
|
+
request_id: request.request_id,
|
|
532
|
+
message_id: request.message_id || null,
|
|
533
|
+
to_worker: request.to_worker,
|
|
534
|
+
transport: 'send-keys',
|
|
535
|
+
result: 'failed',
|
|
536
|
+
reason: result.reason,
|
|
537
|
+
});
|
|
538
|
+
await emitOperationalHookEvent(cwd, result.reason === LEADER_PANE_MISSING_DEFERRED_REASON ? 'handoff-needed' : 'failed', {
|
|
539
|
+
team: teamName,
|
|
540
|
+
worker: request.to_worker,
|
|
541
|
+
request_id: request.request_id,
|
|
542
|
+
message_id: request.message_id || null,
|
|
543
|
+
command: request.trigger_message,
|
|
544
|
+
reason: result.reason,
|
|
545
|
+
...(result.reason === LEADER_PANE_MISSING_DEFERRED_REASON
|
|
546
|
+
? { status: 'handoff-needed' }
|
|
547
|
+
: { status: 'failed', error_summary: result.reason }),
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
if (!mutated)
|
|
551
|
+
return;
|
|
552
|
+
issueCooldownState.by_issue = issueCooldownByIssue;
|
|
553
|
+
await writeJsonAtomic(issueCooldownStatePath(teamDirPath), issueCooldownState);
|
|
554
|
+
triggerCooldownState.by_trigger = triggerCooldownByKey;
|
|
555
|
+
await writeJsonAtomic(triggerCooldownStatePath(teamDirPath), triggerCooldownState);
|
|
556
|
+
await writeJsonAtomic(requestsPath, requests);
|
|
557
|
+
if (!usingLegacyRequests) {
|
|
558
|
+
await writeBridgeDispatchCompat(stateDir, teamName, requests);
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
return summary;
|
|
562
|
+
}
|
|
310
563
|
function resolveWorkerCliForRequest(request, config) {
|
|
311
564
|
const workers = Array.isArray(config?.workers) ? config.workers : [];
|
|
312
565
|
const idx = Number.isFinite(request?.worker_index) ? Number(request.worker_index) : null;
|
|
@@ -557,6 +810,7 @@ export async function drainPendingTeamDispatch({ cwd, stateDir = resolveBridgeSt
|
|
|
557
810
|
const configPath = join(teamDirPath, 'config.json');
|
|
558
811
|
const requestsPath = join(teamDirPath, 'dispatch', 'requests.json');
|
|
559
812
|
const config = await readJson(existsSync(manifestPath) ? manifestPath : configPath, {});
|
|
813
|
+
const claims = [];
|
|
560
814
|
await withDispatchLock(teamDirPath, async () => {
|
|
561
815
|
const bridgeRequests = await readBridgeDispatchRequests(stateDir, teamName);
|
|
562
816
|
const usingLegacyRequests = bridgeRequests === null;
|
|
@@ -570,7 +824,7 @@ export async function drainPendingTeamDispatch({ cwd, stateDir = resolveBridgeSt
|
|
|
570
824
|
const nowMs = Date.now();
|
|
571
825
|
let mutated = false;
|
|
572
826
|
for (const request of requests) {
|
|
573
|
-
if (processed >= maxPerTick)
|
|
827
|
+
if (processed + claims.length >= maxPerTick)
|
|
574
828
|
break;
|
|
575
829
|
if (!request || typeof request !== 'object')
|
|
576
830
|
continue;
|
|
@@ -614,9 +868,6 @@ export async function drainPendingTeamDispatch({ cwd, stateDir = resolveBridgeSt
|
|
|
614
868
|
result: 'deferred',
|
|
615
869
|
reason: LEADER_PANE_MISSING_DEFERRED_REASON,
|
|
616
870
|
});
|
|
617
|
-
// On the legacy fallback lane, requests.json still carries the queue
|
|
618
|
-
// state for this deferred request; this event stays a progress
|
|
619
|
-
// artifact for hook/watcher readers.
|
|
620
871
|
await appendLeaderNotificationDeferredEvent({
|
|
621
872
|
stateDir,
|
|
622
873
|
teamName,
|
|
@@ -648,170 +899,24 @@ export async function drainPendingTeamDispatch({ cwd, stateDir = resolveBridgeSt
|
|
|
648
899
|
continue;
|
|
649
900
|
}
|
|
650
901
|
}
|
|
651
|
-
const
|
|
652
|
-
if (
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
}
|
|
656
|
-
if (triggerKey && triggerCooldownMs > 0) {
|
|
657
|
-
triggerCooldownByKey[triggerKey] = {
|
|
658
|
-
at: Date.now(),
|
|
659
|
-
last_request_id: safeString(request.request_id).trim(),
|
|
660
|
-
};
|
|
661
|
-
mutated = true;
|
|
662
|
-
}
|
|
663
|
-
const nowIso = new Date().toISOString();
|
|
664
|
-
request.attempt_count = Number.isFinite(request.attempt_count) ? Math.max(0, request.attempt_count + 1) : 1;
|
|
665
|
-
request.updated_at = nowIso;
|
|
666
|
-
if (result.ok) {
|
|
667
|
-
// Unconfirmed sends: trigger text was still visible after retry
|
|
668
|
-
// rounds. Leave as pending for the next tick to retry (up to 3
|
|
669
|
-
// total attempts) rather than marking notified. Fixes #391.
|
|
670
|
-
const MAX_UNCONFIRMED_ATTEMPTS = 3;
|
|
671
|
-
if (result.reason === 'tmux_send_keys_unconfirmed' && request.attempt_count < MAX_UNCONFIRMED_ATTEMPTS) {
|
|
672
|
-
request.last_reason = result.reason;
|
|
673
|
-
mutated = true;
|
|
674
|
-
skipped += 1;
|
|
675
|
-
await appendDispatchLog(logsDir, {
|
|
676
|
-
type: 'dispatch_unconfirmed_retry',
|
|
677
|
-
team: teamName,
|
|
678
|
-
request_id: request.request_id,
|
|
679
|
-
worker: request.to_worker,
|
|
680
|
-
attempt: request.attempt_count,
|
|
681
|
-
reason: result.reason,
|
|
682
|
-
...buildDispatchAttemptEvidence(result),
|
|
683
|
-
});
|
|
684
|
-
await appendDeliveryTelemetry(logsDir, {
|
|
685
|
-
event: 'dispatch_result',
|
|
686
|
-
team: teamName,
|
|
687
|
-
request_id: request.request_id,
|
|
688
|
-
message_id: request.message_id || null,
|
|
689
|
-
to_worker: request.to_worker,
|
|
690
|
-
transport: 'send-keys',
|
|
691
|
-
result: 'retry',
|
|
692
|
-
reason: result.reason,
|
|
693
|
-
});
|
|
694
|
-
await emitOperationalHookEvent(cwd, 'retry-needed', {
|
|
695
|
-
team: teamName,
|
|
696
|
-
worker: request.to_worker,
|
|
697
|
-
request_id: request.request_id,
|
|
698
|
-
attempt: request.attempt_count,
|
|
699
|
-
command: request.trigger_message,
|
|
700
|
-
reason: result.reason,
|
|
701
|
-
status: 'retry-needed',
|
|
702
|
-
});
|
|
703
|
-
continue;
|
|
704
|
-
}
|
|
705
|
-
if (result.reason === 'tmux_send_keys_unconfirmed') {
|
|
706
|
-
request.status = 'failed';
|
|
707
|
-
request.failed_at = nowIso;
|
|
708
|
-
request.last_reason = 'unconfirmed_after_max_retries';
|
|
709
|
-
runtimeExec({ command: 'MarkFailed', request_id: request.request_id, reason: 'unconfirmed_after_max_retries' }, stateDir);
|
|
710
|
-
processed += 1;
|
|
711
|
-
failed += 1;
|
|
712
|
-
mutated = true;
|
|
713
|
-
await appendDispatchLog(logsDir, {
|
|
714
|
-
type: 'dispatch_failed',
|
|
715
|
-
team: teamName,
|
|
716
|
-
request_id: request.request_id,
|
|
717
|
-
worker: request.to_worker,
|
|
718
|
-
message_id: request.message_id || null,
|
|
719
|
-
reason: request.last_reason,
|
|
720
|
-
...buildDispatchAttemptEvidence(result),
|
|
721
|
-
});
|
|
722
|
-
await appendDeliveryTelemetry(logsDir, {
|
|
723
|
-
event: 'dispatch_result',
|
|
724
|
-
team: teamName,
|
|
725
|
-
request_id: request.request_id,
|
|
726
|
-
message_id: request.message_id || null,
|
|
727
|
-
to_worker: request.to_worker,
|
|
728
|
-
transport: 'send-keys',
|
|
729
|
-
result: 'failed',
|
|
730
|
-
reason: request.last_reason,
|
|
731
|
-
});
|
|
732
|
-
await emitOperationalHookEvent(cwd, 'failed', {
|
|
733
|
-
team: teamName,
|
|
734
|
-
worker: request.to_worker,
|
|
735
|
-
request_id: request.request_id,
|
|
736
|
-
message_id: request.message_id || null,
|
|
737
|
-
command: request.trigger_message,
|
|
738
|
-
reason: request.last_reason,
|
|
739
|
-
error_summary: request.last_reason,
|
|
740
|
-
status: 'failed',
|
|
741
|
-
});
|
|
742
|
-
continue;
|
|
743
|
-
}
|
|
744
|
-
request.status = 'notified';
|
|
745
|
-
request.notified_at = nowIso;
|
|
746
|
-
request.last_reason = result.reason;
|
|
747
|
-
runtimeExec({ command: 'MarkNotified', request_id: request.request_id, channel: 'tmux' }, stateDir);
|
|
748
|
-
if (request.kind === 'mailbox' && request.message_id) {
|
|
749
|
-
runtimeExec({ command: 'MarkMailboxNotified', message_id: request.message_id }, stateDir);
|
|
750
|
-
if (usingLegacyRequests) {
|
|
751
|
-
await updateMailboxNotified(stateDir, teamName, request.to_worker, request.message_id).catch(() => { });
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
processed += 1;
|
|
755
|
-
mutated = true;
|
|
756
|
-
await appendDispatchLog(logsDir, {
|
|
757
|
-
type: 'dispatch_notified',
|
|
758
|
-
team: teamName,
|
|
759
|
-
request_id: request.request_id,
|
|
760
|
-
worker: request.to_worker,
|
|
761
|
-
message_id: request.message_id || null,
|
|
762
|
-
reason: result.reason,
|
|
763
|
-
...buildDispatchAttemptEvidence(result),
|
|
764
|
-
});
|
|
765
|
-
await appendDeliveryTelemetry(logsDir, {
|
|
766
|
-
event: 'dispatch_result',
|
|
767
|
-
team: teamName,
|
|
768
|
-
request_id: request.request_id,
|
|
769
|
-
message_id: request.message_id || null,
|
|
770
|
-
to_worker: request.to_worker,
|
|
771
|
-
transport: 'send-keys',
|
|
772
|
-
result: 'notified',
|
|
773
|
-
reason: result.reason,
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
else {
|
|
777
|
-
request.status = 'failed';
|
|
778
|
-
request.failed_at = nowIso;
|
|
779
|
-
request.last_reason = result.reason;
|
|
780
|
-
runtimeExec({ command: 'MarkFailed', request_id: request.request_id, reason: result.reason }, stateDir);
|
|
781
|
-
processed += 1;
|
|
782
|
-
failed += 1;
|
|
783
|
-
mutated = true;
|
|
784
|
-
await appendDispatchLog(logsDir, {
|
|
785
|
-
type: 'dispatch_failed',
|
|
786
|
-
team: teamName,
|
|
787
|
-
request_id: request.request_id,
|
|
788
|
-
worker: request.to_worker,
|
|
789
|
-
message_id: request.message_id || null,
|
|
790
|
-
reason: result.reason,
|
|
791
|
-
...buildDispatchAttemptEvidence(result),
|
|
792
|
-
});
|
|
793
|
-
await appendDeliveryTelemetry(logsDir, {
|
|
794
|
-
event: 'dispatch_result',
|
|
795
|
-
team: teamName,
|
|
796
|
-
request_id: request.request_id,
|
|
797
|
-
message_id: request.message_id || null,
|
|
798
|
-
to_worker: request.to_worker,
|
|
799
|
-
transport: 'send-keys',
|
|
800
|
-
result: 'failed',
|
|
801
|
-
reason: result.reason,
|
|
802
|
-
});
|
|
803
|
-
await emitOperationalHookEvent(cwd, result.reason === LEADER_PANE_MISSING_DEFERRED_REASON ? 'handoff-needed' : 'failed', {
|
|
804
|
-
team: teamName,
|
|
805
|
-
worker: request.to_worker,
|
|
806
|
-
request_id: request.request_id,
|
|
807
|
-
message_id: request.message_id || null,
|
|
808
|
-
command: request.trigger_message,
|
|
809
|
-
reason: result.reason,
|
|
810
|
-
...(result.reason === LEADER_PANE_MISSING_DEFERRED_REASON
|
|
811
|
-
? { status: 'handoff-needed' }
|
|
812
|
-
: { status: 'failed', error_summary: result.reason }),
|
|
813
|
-
});
|
|
902
|
+
const lease = await tryAcquireDispatchRequestLease(teamDirPath, request.request_id);
|
|
903
|
+
if (!lease) {
|
|
904
|
+
skipped += 1;
|
|
905
|
+
continue;
|
|
814
906
|
}
|
|
907
|
+
mutated = reserveDispatchCooldowns({
|
|
908
|
+
issueCooldownMs,
|
|
909
|
+
triggerCooldownMs,
|
|
910
|
+
issueCooldownByIssue,
|
|
911
|
+
triggerCooldownByKey,
|
|
912
|
+
issueKey,
|
|
913
|
+
triggerKey,
|
|
914
|
+
requestId: request.request_id,
|
|
915
|
+
}) || mutated;
|
|
916
|
+
claims.push({
|
|
917
|
+
request: { ...request },
|
|
918
|
+
lease,
|
|
919
|
+
});
|
|
815
920
|
}
|
|
816
921
|
if (mutated) {
|
|
817
922
|
issueCooldownState.by_issue = issueCooldownByIssue;
|
|
@@ -824,6 +929,39 @@ export async function drainPendingTeamDispatch({ cwd, stateDir = resolveBridgeSt
|
|
|
824
929
|
}
|
|
825
930
|
}
|
|
826
931
|
});
|
|
932
|
+
try {
|
|
933
|
+
for (const claim of claims) {
|
|
934
|
+
try {
|
|
935
|
+
const result = await injector(claim.request, config, resolve(cwd), stateDir);
|
|
936
|
+
const delta = await finalizeClaimedDispatchRequest({
|
|
937
|
+
claim,
|
|
938
|
+
result,
|
|
939
|
+
teamName,
|
|
940
|
+
teamDirPath,
|
|
941
|
+
config,
|
|
942
|
+
cwd,
|
|
943
|
+
stateDir,
|
|
944
|
+
logsDir,
|
|
945
|
+
issueCooldownMs,
|
|
946
|
+
triggerCooldownMs,
|
|
947
|
+
});
|
|
948
|
+
processed += delta.processed;
|
|
949
|
+
skipped += delta.skipped;
|
|
950
|
+
failed += delta.failed;
|
|
951
|
+
}
|
|
952
|
+
finally {
|
|
953
|
+
claim.released = true;
|
|
954
|
+
await releaseDispatchRequestLease(claim.lease);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
finally {
|
|
959
|
+
for (const claim of claims) {
|
|
960
|
+
if (claim.released)
|
|
961
|
+
continue;
|
|
962
|
+
await releaseDispatchRequestLease(claim.lease);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
827
965
|
}
|
|
828
966
|
return { processed, skipped, failed };
|
|
829
967
|
}
|