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
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
import { readFile, writeFile, mkdir, appendFile, readdir } from 'fs/promises';
|
|
7
7
|
import { existsSync } from 'fs';
|
|
8
|
-
import { join } from 'path';
|
|
8
|
+
import { join, resolve } from 'path';
|
|
9
|
+
import { readUsableSessionState } from '../../hooks/session.js';
|
|
9
10
|
import { asNumber, safeString, isTerminalPhase } from './utils.js';
|
|
10
11
|
import { readJsonIfExists, getScopedStateDirsForCurrentSession } from './state-io.js';
|
|
11
12
|
import { runProcess } from './process-runner.js';
|
|
12
13
|
import { logTmuxHookEvent } from './log.js';
|
|
13
14
|
import { evaluatePaneInjectionReadiness, sendPaneInput } from './team-tmux-guard.js';
|
|
14
15
|
import { resolvePaneTarget } from './tmux-injection.js';
|
|
16
|
+
import { listNotifyCanonicalActiveTeams } from './active-team.js';
|
|
15
17
|
import {
|
|
16
18
|
classifyLeaderActionState,
|
|
17
19
|
resolveLeaderNudgeIntent,
|
|
@@ -20,8 +22,10 @@ import { DEFAULT_MARKER } from '../tmux-hook-engine.js';
|
|
|
20
22
|
import { isLeaderRuntimeStale } from '../../team/leader-activity.js';
|
|
21
23
|
import { appendTeamDeliveryLog } from '../../team/delivery-log.js';
|
|
22
24
|
import { writeTeamLeaderAttention } from '../../team/state.js';
|
|
25
|
+
import { readLatestTeamProgressEvidenceMs } from '../../team/progress-evidence.js';
|
|
23
26
|
const LEADER_PANE_MISSING_NO_INJECTION_REASON = 'leader_pane_missing_no_injection';
|
|
24
27
|
const LEADER_PANE_SHELL_NO_INJECTION_REASON = 'leader_pane_shell_no_injection';
|
|
28
|
+
const LEADER_PANE_SAME_CLASSIFIED_STATE_SUPPRESSED_REASON = 'pane_already_shows_same_classified_state';
|
|
25
29
|
const LEADER_NOTIFICATION_DEFERRED_TYPE = 'leader_notification_deferred';
|
|
26
30
|
const ACK_WITHOUT_START_EVIDENCE_REASON = 'ack_without_start_evidence';
|
|
27
31
|
const ACK_LIKE_PATTERNS = [
|
|
@@ -248,16 +252,7 @@ async function resolveCurrentSessionId(stateDir) {
|
|
|
248
252
|
|| '',
|
|
249
253
|
).trim();
|
|
250
254
|
if (fromEnv) return fromEnv;
|
|
251
|
-
|
|
252
|
-
const sessionPath = join(stateDir, 'session.json');
|
|
253
|
-
try {
|
|
254
|
-
if (!existsSync(sessionPath)) return '';
|
|
255
|
-
const parsed = JSON.parse(await readFile(sessionPath, 'utf-8'));
|
|
256
|
-
const sessionId = safeString(parsed && parsed.session_id ? parsed.session_id : '').trim();
|
|
257
|
-
return sessionId;
|
|
258
|
-
} catch {
|
|
259
|
-
return '';
|
|
260
|
-
}
|
|
255
|
+
return safeString((await readUsableSessionState(resolve(stateDir, '..', '..')))?.session_id).trim();
|
|
261
256
|
}
|
|
262
257
|
|
|
263
258
|
async function readWorkerStatusSnapshot(stateDir, teamName, workerName) {
|
|
@@ -445,6 +440,27 @@ function formatMailboxBodyForLeader(body, maxLength = 40) {
|
|
|
445
440
|
return `${normalized.slice(0, maxLength - 1)}…`;
|
|
446
441
|
}
|
|
447
442
|
|
|
443
|
+
function normalizeVisibleLeaderStateText(text) {
|
|
444
|
+
return safeString(text)
|
|
445
|
+
.toLowerCase()
|
|
446
|
+
.replace(/\[omx_tmux_inject\]/g, ' ')
|
|
447
|
+
.replace(/\[omx_intent:[^\]]+\]/g, ' ')
|
|
448
|
+
.replace(/said\s+"[^"]*"/g, 'said "<content>"')
|
|
449
|
+
.replace(/said\s+'[^']*'/g, 'said "<content>"')
|
|
450
|
+
.replace(/\b\d+[smhd](?:\s+\d+[smhd])*\b/g, '<duration>')
|
|
451
|
+
.replace(/\b\d+\b/g, '<n>')
|
|
452
|
+
.replace(/\s+/g, ' ')
|
|
453
|
+
.trim();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function paneAlreadyShowsVisibleLeaderState(paneCapture, visibleText) {
|
|
457
|
+
const normalizedVisibleText = normalizeVisibleLeaderStateText(visibleText);
|
|
458
|
+
if (!normalizedVisibleText) return false;
|
|
459
|
+
const normalizedPaneCapture = normalizeVisibleLeaderStateText(paneCapture);
|
|
460
|
+
if (!normalizedPaneCapture) return false;
|
|
461
|
+
return normalizedPaneCapture.includes(normalizedVisibleText);
|
|
462
|
+
}
|
|
463
|
+
|
|
448
464
|
async function workerHasOwnedStartedTask(stateDir, teamName, workerName) {
|
|
449
465
|
const tasksDir = join(stateDir, 'team', teamName, 'tasks');
|
|
450
466
|
if (!existsSync(tasksDir)) return false;
|
|
@@ -601,6 +617,11 @@ export async function maybeNudgeTeamLeader({
|
|
|
601
617
|
// Non-critical
|
|
602
618
|
}
|
|
603
619
|
|
|
620
|
+
const canonicalFallbackTeams = await listNotifyCanonicalActiveTeams(cwd, currentSessionId).catch(() => []);
|
|
621
|
+
for (const team of canonicalFallbackTeams) {
|
|
622
|
+
candidateTeamNames.add(team.teamName);
|
|
623
|
+
}
|
|
624
|
+
|
|
604
625
|
// Use pre-computed staleness (captured before HUD state was updated this turn)
|
|
605
626
|
const leaderStale = typeof preComputedLeaderStale === 'boolean' ? preComputedLeaderStale : false;
|
|
606
627
|
|
|
@@ -676,11 +697,15 @@ export async function maybeNudgeTeamLeader({
|
|
|
676
697
|
const workerTurnProgress = hasWorkerTurnProgress(progressSnapshot.workerSnapshot, previousTurnCounts);
|
|
677
698
|
const hasTrackableTurnSignals = hasTrackableActiveWorkerTurns(progressSnapshot.workerSnapshot, previousTurnCounts);
|
|
678
699
|
const progressChanged = !previousSignature || previousSignature !== progressSnapshot.signature || workerTurnProgress;
|
|
700
|
+
const extraProgressEvidenceMs = await readLatestTeamProgressEvidenceMs(cwd, teamName).catch(() => Number.NaN);
|
|
679
701
|
const effectiveProgressAtMs = progressChanged || !Number.isFinite(previousProgressAtMs)
|
|
680
702
|
? nowMs
|
|
681
703
|
: previousProgressAtMs;
|
|
682
|
-
const
|
|
683
|
-
|
|
704
|
+
const latestProgressEvidenceMs = Number.isFinite(extraProgressEvidenceMs)
|
|
705
|
+
? Math.max(effectiveProgressAtMs, extraProgressEvidenceMs)
|
|
706
|
+
: effectiveProgressAtMs;
|
|
707
|
+
const effectiveProgressAtIso = new Date(latestProgressEvidenceMs).toISOString();
|
|
708
|
+
const stalledForMs = Math.max(0, nowMs - latestProgressEvidenceMs);
|
|
684
709
|
const stallThresholdMs = hasTrackableTurnSignals ? workerTurnStallThresholdMs : fallbackProgressStallThresholdMs;
|
|
685
710
|
const teamProgressStalled =
|
|
686
711
|
progressSnapshot.workRemaining
|
|
@@ -688,6 +713,9 @@ export async function maybeNudgeTeamLeader({
|
|
|
688
713
|
&& !allWorkersIdle
|
|
689
714
|
&& !progressChanged
|
|
690
715
|
&& stalledForMs >= stallThresholdMs;
|
|
716
|
+
const hasFreshProgressEvidence =
|
|
717
|
+
progressSnapshot.workRemaining
|
|
718
|
+
&& stalledForMs < stallThresholdMs;
|
|
691
719
|
const leaderActionState = classifyLeaderActionState({
|
|
692
720
|
allWorkersIdle,
|
|
693
721
|
workerPanesAlive: paneStatus.alive,
|
|
@@ -724,7 +752,7 @@ export async function maybeNudgeTeamLeader({
|
|
|
724
752
|
|
|
725
753
|
// Stale-leader follow-up is the only periodic visible nudge path.
|
|
726
754
|
// This keeps the leader pane quieter when the leader is not actually stale.
|
|
727
|
-
const stalePanesNudge = paneStatus.alive && leaderStale;
|
|
755
|
+
const stalePanesNudge = paneStatus.alive && leaderStale && !hasFreshProgressEvidence;
|
|
728
756
|
const previousStalledTeamNudge = prevReason === 'stuck_waiting_on_leader';
|
|
729
757
|
const stalledTeamNudge = teamProgressStalled && (dueByTime || !previousStalledTeamNudge);
|
|
730
758
|
const staleFollowupDue = stalePanesNudge && dueByTime;
|
|
@@ -925,6 +953,55 @@ export async function maybeNudgeTeamLeader({
|
|
|
925
953
|
continue;
|
|
926
954
|
}
|
|
927
955
|
|
|
956
|
+
if (paneAlreadyShowsVisibleLeaderState(paneGuard.paneCapture, capped)) {
|
|
957
|
+
nudgeState.last_nudged_by_team[teamName] = {
|
|
958
|
+
at: nowIso,
|
|
959
|
+
last_message_id: newestId || prevMsgId || '',
|
|
960
|
+
reason: nudgeReason,
|
|
961
|
+
orchestration_intent: orchestrationIntent,
|
|
962
|
+
};
|
|
963
|
+
if (shouldSendAllIdleNudge) {
|
|
964
|
+
nudgeState.last_idle_nudged_by_team[teamName] = {
|
|
965
|
+
at: nowIso,
|
|
966
|
+
worker_count: workerNames.length,
|
|
967
|
+
orchestration_intent: orchestrationIntent,
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
await emitTeamNudgeEvent(cwd, teamName, nudgeReason, orchestrationIntent, nowIso);
|
|
972
|
+
|
|
973
|
+
try {
|
|
974
|
+
await logTmuxHookEvent(logsDir, {
|
|
975
|
+
timestamp: nowIso,
|
|
976
|
+
type: 'team_leader_nudge',
|
|
977
|
+
team: teamName,
|
|
978
|
+
tmux_target: tmuxTarget,
|
|
979
|
+
reason: nudgeReason,
|
|
980
|
+
orchestration_intent: orchestrationIntent,
|
|
981
|
+
pane_count: paneStatus.paneCount,
|
|
982
|
+
leader_stale: leaderStale,
|
|
983
|
+
message_count: messages.length,
|
|
984
|
+
stalled_for_ms: teamProgressStalled ? stalledForMs : undefined,
|
|
985
|
+
missing_signal_workers: progressSnapshot.missingSignalWorkers,
|
|
986
|
+
visible_injection_suppressed: true,
|
|
987
|
+
suppression_reason: LEADER_PANE_SAME_CLASSIFIED_STATE_SUPPRESSED_REASON,
|
|
988
|
+
});
|
|
989
|
+
} catch { /* ignore */ }
|
|
990
|
+
await appendTeamDeliveryLog(logsDir, {
|
|
991
|
+
event: 'nudge_triggered',
|
|
992
|
+
source,
|
|
993
|
+
team: teamName,
|
|
994
|
+
to_worker: 'leader-fixed',
|
|
995
|
+
transport: 'send-keys',
|
|
996
|
+
result: 'suppressed',
|
|
997
|
+
reason: nudgeReason,
|
|
998
|
+
orchestration_intent: orchestrationIntent,
|
|
999
|
+
visible_injection_suppressed: true,
|
|
1000
|
+
suppression_reason: LEADER_PANE_SAME_CLASSIFIED_STATE_SUPPRESSED_REASON,
|
|
1001
|
+
}).catch(() => {});
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
928
1005
|
try {
|
|
929
1006
|
const sendResult = await sendPaneInput({
|
|
930
1007
|
paneTarget: tmuxTarget,
|
|
@@ -8,6 +8,7 @@ import { readFile, writeFile } from 'fs/promises';
|
|
|
8
8
|
import { existsSync } from 'fs';
|
|
9
9
|
import { join, resolve as resolvePath } from 'path';
|
|
10
10
|
import { safeString, asNumber } from './utils.js';
|
|
11
|
+
import { sameFilePath } from '../../utils/paths.js';
|
|
11
12
|
import {
|
|
12
13
|
readJsonIfExists,
|
|
13
14
|
normalizeTmuxState,
|
|
@@ -35,7 +36,7 @@ async function resolvePaneCwdMismatch(paneId: string, expectedCwd: any): Promise
|
|
|
35
36
|
try {
|
|
36
37
|
const paneCwdResult = await runProcess('tmux', ['display-message', '-p', '-t', paneId, '#{pane_current_path}']);
|
|
37
38
|
const paneCwd = safeString(paneCwdResult.stdout).trim();
|
|
38
|
-
if (paneCwd &&
|
|
39
|
+
if (paneCwd && !sameFilePath(paneCwd, expectedCwd)) {
|
|
39
40
|
return {
|
|
40
41
|
paneTarget: null,
|
|
41
42
|
reason: 'pane_cwd_mismatch',
|
|
@@ -210,7 +211,15 @@ export async function resolvePaneTarget(target: any, expectedCwd: any, modePane:
|
|
|
210
211
|
const expectedSessionTarget = safeString(managedContext.expectedTmuxSessionName).trim();
|
|
211
212
|
const sessionIdTarget = safeString(managedContext.invocationSessionId).trim();
|
|
212
213
|
const stateSessionTarget = safeString(managedContext.sessionState?.session_id).trim();
|
|
213
|
-
const
|
|
214
|
+
const nativeSessionTarget = safeString(managedContext.nativeSessionId).trim();
|
|
215
|
+
const canonicalSessionTarget = safeString(managedContext.canonicalSessionId).trim();
|
|
216
|
+
const allowedSessionTargets = new Set([
|
|
217
|
+
expectedSessionTarget,
|
|
218
|
+
sessionIdTarget,
|
|
219
|
+
stateSessionTarget,
|
|
220
|
+
nativeSessionTarget,
|
|
221
|
+
canonicalSessionTarget,
|
|
222
|
+
].filter(Boolean));
|
|
214
223
|
if (!allowedSessionTargets.has(explicitSessionTarget)) {
|
|
215
224
|
return { paneTarget: null, reason: 'target_session_not_managed' };
|
|
216
225
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { writeFile, appendFile, mkdir, readFile } from 'fs/promises';
|
|
22
22
|
import { existsSync } from 'fs';
|
|
23
|
-
import { join } from 'path';
|
|
23
|
+
import { dirname, join } from 'path';
|
|
24
24
|
|
|
25
25
|
import { safeString, asNumber } from './notify-hook/utils.js';
|
|
26
26
|
import {
|
|
@@ -29,7 +29,9 @@ import {
|
|
|
29
29
|
normalizeInputMessages,
|
|
30
30
|
} from './notify-hook/payload-parser.js';
|
|
31
31
|
import {
|
|
32
|
-
|
|
32
|
+
getScopedStatePath,
|
|
33
|
+
readCurrentSessionId,
|
|
34
|
+
readScopedJsonIfExists,
|
|
33
35
|
getScopedStateDirsForCurrentSession,
|
|
34
36
|
normalizeNotifyState,
|
|
35
37
|
pruneRecentTurns,
|
|
@@ -181,10 +183,12 @@ async function main() {
|
|
|
181
183
|
const logsDir = join(cwd, '.omx', 'logs');
|
|
182
184
|
const omxDir = join(cwd, '.omx');
|
|
183
185
|
let currentOmxSessionId = '';
|
|
186
|
+
const getEffectiveSessionId = () => currentOmxSessionId || payloadSessionId;
|
|
184
187
|
|
|
185
188
|
// Ensure directories exist
|
|
186
189
|
await mkdir(logsDir, { recursive: true }).catch(() => {});
|
|
187
190
|
await mkdir(stateDir, { recursive: true }).catch(() => {});
|
|
191
|
+
currentOmxSessionId = await readCurrentSessionId(stateDir).catch(() => '') || '';
|
|
188
192
|
|
|
189
193
|
// Turn-level dedupe prevents double-processing when native notify and fallback
|
|
190
194
|
// watcher both emit the same completed turn.
|
|
@@ -195,14 +199,18 @@ async function main() {
|
|
|
195
199
|
const threadId = safeString(payload['thread-id'] || payload.thread_id || '');
|
|
196
200
|
const eventType = safeString(payload.type || 'agent-turn-complete');
|
|
197
201
|
const key = `${threadId || 'no-thread'}|${turnId}|${eventType}`;
|
|
198
|
-
const
|
|
199
|
-
const
|
|
202
|
+
const dedupeSessionId = getEffectiveSessionId();
|
|
203
|
+
const dedupeStatePath = await getScopedStatePath(stateDir, 'notify-hook-state.json', dedupeSessionId);
|
|
204
|
+
const dedupeState = normalizeNotifyState(
|
|
205
|
+
await readScopedJsonIfExists(stateDir, 'notify-hook-state.json', dedupeSessionId, null),
|
|
206
|
+
);
|
|
200
207
|
dedupeState.recent_turns = pruneRecentTurns(dedupeState.recent_turns, now);
|
|
201
208
|
if (dedupeState.recent_turns[key]) {
|
|
202
209
|
process.exit(0);
|
|
203
210
|
}
|
|
204
211
|
dedupeState.recent_turns[key] = now;
|
|
205
212
|
dedupeState.last_event_at = new Date().toISOString();
|
|
213
|
+
await mkdir(dirname(dedupeStatePath), { recursive: true }).catch(() => {});
|
|
206
214
|
await writeFile(dedupeStatePath, JSON.stringify(dedupeState, null, 2)).catch(() => {});
|
|
207
215
|
}
|
|
208
216
|
} catch {
|
|
@@ -214,10 +222,10 @@ async function main() {
|
|
|
214
222
|
try {
|
|
215
223
|
const threadId = safeString(payload['thread-id'] || payload.thread_id || '');
|
|
216
224
|
const turnId = safeString(payload['turn-id'] || payload.turn_id || '');
|
|
217
|
-
if (
|
|
225
|
+
if (getEffectiveSessionId() && threadId) {
|
|
218
226
|
const { recordSubagentTurnForSession } = await import('../subagents/tracker.js');
|
|
219
227
|
await recordSubagentTurnForSession(cwd, {
|
|
220
|
-
sessionId:
|
|
228
|
+
sessionId: getEffectiveSessionId(),
|
|
221
229
|
threadId,
|
|
222
230
|
...(turnId ? { turnId } : {}),
|
|
223
231
|
timestamp: new Date().toISOString(),
|
|
@@ -417,18 +425,20 @@ async function main() {
|
|
|
417
425
|
|
|
418
426
|
// 4. Write HUD state summary for `omx hud` (lead session only)
|
|
419
427
|
if (!isTeamWorker) {
|
|
420
|
-
const hudStatePath = join(stateDir, 'hud-state.json');
|
|
421
428
|
try {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
429
|
+
const scopedSessionId = getEffectiveSessionId();
|
|
430
|
+
const hudStatePath = await getScopedStatePath(stateDir, 'hud-state.json', scopedSessionId);
|
|
431
|
+
let hudState = await readScopedJsonIfExists(stateDir, 'hud-state.json', scopedSessionId, {
|
|
432
|
+
last_turn_at: '',
|
|
433
|
+
turn_count: 0,
|
|
434
|
+
});
|
|
426
435
|
const nowIso = new Date().toISOString();
|
|
427
436
|
hudState.last_turn_at = nowIso;
|
|
428
437
|
(hudState as any).last_progress_at = nowIso;
|
|
429
438
|
hudState.turn_count = (hudState.turn_count || 0) + 1;
|
|
430
439
|
(hudState as any).last_agent_output = (payload['last-assistant-message'] || payload.last_assistant_message || '')
|
|
431
440
|
.slice(0, 100);
|
|
441
|
+
await mkdir(dirname(hudStatePath), { recursive: true }).catch(() => {});
|
|
432
442
|
await writeFile(hudStatePath, JSON.stringify(hudState, null, 2));
|
|
433
443
|
} catch {
|
|
434
444
|
// Non-critical
|
|
@@ -451,19 +461,19 @@ async function main() {
|
|
|
451
461
|
try {
|
|
452
462
|
const { recordSkillActivation } = await import('../hooks/keyword-detector.js');
|
|
453
463
|
if (latestUserInput) {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
464
|
+
await recordSkillActivation({
|
|
465
|
+
stateDir,
|
|
466
|
+
text: latestUserInput,
|
|
467
|
+
sessionId: getEffectiveSessionId(),
|
|
468
|
+
threadId: payloadThreadId,
|
|
469
|
+
turnId: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
470
|
+
});
|
|
461
471
|
}
|
|
462
472
|
} catch {
|
|
463
473
|
// Non-fatal: keyword detector module may not be built yet
|
|
464
474
|
}
|
|
465
475
|
|
|
466
|
-
const deepInterviewStateActive = await isDeepInterviewStateActive(stateDir);
|
|
476
|
+
const deepInterviewStateActive = await isDeepInterviewStateActive(stateDir, getEffectiveSessionId());
|
|
467
477
|
|
|
468
478
|
// 4.55. Notify leader when individual worker transitions to idle (worker session only)
|
|
469
479
|
if (isTeamWorker && parsedTeamWorker && !deepInterviewStateActive) {
|
|
@@ -515,7 +525,7 @@ async function main() {
|
|
|
515
525
|
try {
|
|
516
526
|
const { buildNativeHookEvent, buildDerivedHookEvent } = await import('../hooks/extensibility/events.js');
|
|
517
527
|
const { dispatchHookEvent } = await import('../hooks/extensibility/dispatcher.js');
|
|
518
|
-
const sessionIdForHooks =
|
|
528
|
+
const sessionIdForHooks = getEffectiveSessionId();
|
|
519
529
|
const threadIdForHooks = safeString(payload['thread-id'] || payload.thread_id || '');
|
|
520
530
|
const turnIdForHooks = safeString(payload['turn-id'] || payload.turn_id || '');
|
|
521
531
|
const modeForHooks = safeString(payload.mode || '');
|
|
@@ -525,6 +535,8 @@ async function main() {
|
|
|
525
535
|
type: safeString(payload.type || 'agent-turn-complete'),
|
|
526
536
|
input_messages: normalizeInputMessages(payload),
|
|
527
537
|
output_preview: outputPreview,
|
|
538
|
+
native_session_id: payloadSessionId || null,
|
|
539
|
+
omx_session_id: sessionIdForHooks || null,
|
|
528
540
|
...readRepositoryMetadata(cwd),
|
|
529
541
|
session_name: resolveOperationalSessionName(cwd, sessionIdForHooks),
|
|
530
542
|
project_path: cwd,
|
|
@@ -546,6 +558,8 @@ async function main() {
|
|
|
546
558
|
status: signal.normalized_event,
|
|
547
559
|
errorSummary: signal.error_summary,
|
|
548
560
|
extra: {
|
|
561
|
+
native_session_id: payloadSessionId || null,
|
|
562
|
+
omx_session_id: sessionIdForHooks || null,
|
|
549
563
|
source_event: safeString(payload.type || 'agent-turn-complete'),
|
|
550
564
|
},
|
|
551
565
|
}), {
|
|
@@ -650,7 +664,7 @@ async function main() {
|
|
|
650
664
|
payload,
|
|
651
665
|
stateDir,
|
|
652
666
|
logsDir,
|
|
653
|
-
sessionId:
|
|
667
|
+
sessionId: getEffectiveSessionId(),
|
|
654
668
|
turnId: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
655
669
|
});
|
|
656
670
|
} catch (err) {
|
|
@@ -660,7 +674,7 @@ async function main() {
|
|
|
660
674
|
level: 'warn',
|
|
661
675
|
type: 'visual_verdict_import_failure',
|
|
662
676
|
error: (err as any)?.message || String(err),
|
|
663
|
-
session_id:
|
|
677
|
+
session_id: getEffectiveSessionId(),
|
|
664
678
|
turn_id: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
665
679
|
});
|
|
666
680
|
const warnFile = join(logsDir, `notify-hook-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
@@ -3,12 +3,18 @@ import { mkdir, writeFile } from 'fs/promises';
|
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import process from 'process';
|
|
5
5
|
import { spawnSync } from 'child_process';
|
|
6
|
+
import { CLAUDE_SKIP_PERMISSIONS_FLAG } from '../cli/constants.js';
|
|
6
7
|
|
|
7
8
|
const PROVIDER_BINARIES: Record<string, string> = {
|
|
8
9
|
claude: 'claude',
|
|
9
10
|
gemini: 'gemini',
|
|
10
11
|
};
|
|
11
12
|
const ASK_ORIGINAL_TASK_ENV = 'OMX_ASK_ORIGINAL_TASK';
|
|
13
|
+
const ISSUE_WORK_PROMPT_PATTERNS = [
|
|
14
|
+
/\bgh\s+issue\b/i,
|
|
15
|
+
/\b(?:fix|work on|work|investigate|implement|triage|debug|review|handle)\s+issue\s*#?\d+\b/i,
|
|
16
|
+
/\bissue\s*#\d+\b/i,
|
|
17
|
+
];
|
|
12
18
|
|
|
13
19
|
function usage(): void {
|
|
14
20
|
console.error('Usage: omx ask <claude|gemini> "<prompt>"');
|
|
@@ -70,6 +76,13 @@ function ensureBinary(binary: string): void {
|
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
|
|
79
|
+
function shouldUseClaudeIssuePermissionsBypass(provider: string, prompt: string): boolean {
|
|
80
|
+
if (provider !== 'claude') return false;
|
|
81
|
+
const trimmed = prompt.trim();
|
|
82
|
+
if (trimmed === '') return false;
|
|
83
|
+
return ISSUE_WORK_PROMPT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
84
|
+
}
|
|
85
|
+
|
|
73
86
|
function buildSummary(exitCode: number, output: string): string {
|
|
74
87
|
if (exitCode === 0) {
|
|
75
88
|
return 'Provider completed successfully. Review the raw output for details.';
|
|
@@ -148,10 +161,15 @@ async function writeArtifact({ provider, originalTask, finalPrompt, rawOutput, e
|
|
|
148
161
|
async function main(): Promise<void> {
|
|
149
162
|
const { provider, prompt } = parseArgs(process.argv.slice(2));
|
|
150
163
|
const binary = PROVIDER_BINARIES[provider];
|
|
164
|
+
const originalTask = process.env[ASK_ORIGINAL_TASK_ENV] ?? prompt;
|
|
151
165
|
|
|
152
166
|
ensureBinary(binary);
|
|
153
167
|
|
|
154
|
-
const
|
|
168
|
+
const launchArgs = shouldUseClaudeIssuePermissionsBypass(provider, originalTask)
|
|
169
|
+
? [CLAUDE_SKIP_PERMISSIONS_FLAG, '-p', prompt]
|
|
170
|
+
: ['-p', prompt];
|
|
171
|
+
|
|
172
|
+
const run = spawnSync(binary, launchArgs, {
|
|
155
173
|
encoding: 'utf8',
|
|
156
174
|
maxBuffer: 10 * 1024 * 1024,
|
|
157
175
|
windowsHide: true,
|
|
@@ -164,7 +182,7 @@ async function main(): Promise<void> {
|
|
|
164
182
|
|
|
165
183
|
const artifactPath = await writeArtifact({
|
|
166
184
|
provider,
|
|
167
|
-
originalTask
|
|
185
|
+
originalTask,
|
|
168
186
|
finalPrompt: prompt,
|
|
169
187
|
rawOutput,
|
|
170
188
|
exitCode,
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
existsSync,
|
|
3
|
-
lstatSync,
|
|
4
2
|
mkdtempSync,
|
|
5
3
|
rmSync,
|
|
6
|
-
symlinkSync,
|
|
7
4
|
} from 'node:fs';
|
|
8
5
|
import { mkdirSync } from 'node:fs';
|
|
9
6
|
import { tmpdir } from 'node:os';
|
|
10
|
-
import {
|
|
7
|
+
import { join } from 'node:path';
|
|
11
8
|
import { spawnSync } from 'node:child_process';
|
|
12
9
|
import { pathToFileURL } from 'node:url';
|
|
10
|
+
import {
|
|
11
|
+
ensureReusableNodeModules,
|
|
12
|
+
} from '../utils/repo-deps.js';
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
];
|
|
14
|
+
export {
|
|
15
|
+
hasUsableNodeModules,
|
|
16
|
+
resolveGitCommonDir,
|
|
17
|
+
resolveReusableNodeModulesSource,
|
|
18
|
+
} from '../utils/repo-deps.js';
|
|
20
19
|
|
|
21
20
|
export const PACKED_INSTALL_SMOKE_CORE_COMMANDS = [
|
|
22
21
|
['--help'],
|
|
@@ -32,41 +31,10 @@ function usage(): string {
|
|
|
32
31
|
].join('\n');
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
function hasNodeModulesPath(nodeModulesPath: string): boolean {
|
|
36
|
-
try {
|
|
37
|
-
lstatSync(nodeModulesPath);
|
|
38
|
-
return true;
|
|
39
|
-
} catch {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function hasUsableNodeModules(repoRoot: string): boolean {
|
|
45
|
-
return REQUIRED_NODE_MODULE_MARKERS.every((marker) => existsSync(join(repoRoot, 'node_modules', marker)));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function resolveGitCommonDir(cwd: string, gitRunner = spawnSync): string | null {
|
|
49
|
-
const result = gitRunner('git', ['rev-parse', '--git-common-dir'], {
|
|
50
|
-
cwd,
|
|
51
|
-
encoding: 'utf-8',
|
|
52
|
-
});
|
|
53
|
-
if (result.status !== 0) {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
const value = (result.stdout || '').trim();
|
|
57
|
-
if (!value) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
return resolve(cwd, value);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
34
|
interface EnsureRepoDepsOptions {
|
|
64
35
|
gitRunner?: typeof spawnSync;
|
|
65
36
|
install?: (cwd: string) => void;
|
|
66
|
-
remove?: typeof rmSync;
|
|
67
|
-
symlink?: typeof symlinkSync;
|
|
68
37
|
log?: (message: string) => void;
|
|
69
|
-
platformName?: string;
|
|
70
38
|
}
|
|
71
39
|
|
|
72
40
|
interface EnsureRepoDepsResult {
|
|
@@ -75,24 +43,6 @@ interface EnsureRepoDepsResult {
|
|
|
75
43
|
sourceNodeModulesPath?: string;
|
|
76
44
|
}
|
|
77
45
|
|
|
78
|
-
export function resolveReusableNodeModulesSource(repoRoot: string, gitRunner = spawnSync): string | null {
|
|
79
|
-
const commonDir = resolveGitCommonDir(repoRoot, gitRunner);
|
|
80
|
-
if (!commonDir || basename(commonDir) !== '.git') {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const primaryRepoRoot = dirname(commonDir);
|
|
85
|
-
if (resolve(primaryRepoRoot) === resolve(repoRoot)) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!hasUsableNodeModules(primaryRepoRoot)) {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return join(primaryRepoRoot, 'node_modules');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
46
|
function formatCommandFailure(cmd: string, args: string[], result: { stdout?: string; stderr?: string }): string {
|
|
97
47
|
return [
|
|
98
48
|
`Command failed: ${cmd} ${args.join(' ')}`,
|
|
@@ -114,40 +64,23 @@ export function ensureRepoDependencies(repoRoot: string, options: EnsureRepoDeps
|
|
|
114
64
|
throw new Error(formatCommandFailure('npm', ['ci'], result));
|
|
115
65
|
}
|
|
116
66
|
},
|
|
117
|
-
remove = rmSync,
|
|
118
|
-
symlink = symlinkSync,
|
|
119
67
|
log = () => {},
|
|
120
|
-
platformName = process.platform,
|
|
121
68
|
} = options;
|
|
122
69
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
nodeModulesPath: join(repoRoot, 'node_modules'),
|
|
127
|
-
};
|
|
70
|
+
const reusable = ensureReusableNodeModules(repoRoot, { gitRunner });
|
|
71
|
+
if (reusable.strategy === 'existing') {
|
|
72
|
+
return reusable;
|
|
128
73
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
remove(targetNodeModules, { recursive: true, force: true });
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const reusableNodeModules = resolveReusableNodeModulesSource(repoRoot, gitRunner);
|
|
136
|
-
if (reusableNodeModules) {
|
|
137
|
-
symlink(reusableNodeModules, targetNodeModules, platformName === 'win32' ? 'junction' : 'dir');
|
|
138
|
-
log(`[smoke:packed-install] Reusing node_modules from ${reusableNodeModules}`);
|
|
139
|
-
return {
|
|
140
|
-
strategy: 'symlink',
|
|
141
|
-
nodeModulesPath: targetNodeModules,
|
|
142
|
-
sourceNodeModulesPath: reusableNodeModules,
|
|
143
|
-
};
|
|
74
|
+
if (reusable.strategy === 'symlink') {
|
|
75
|
+
log(`[smoke:packed-install] Reusing node_modules from ${reusable.sourceNodeModulesPath}`);
|
|
76
|
+
return reusable;
|
|
144
77
|
}
|
|
145
78
|
|
|
146
79
|
log('[smoke:packed-install] Installing repo dependencies with npm ci');
|
|
147
80
|
install(repoRoot);
|
|
148
81
|
return {
|
|
149
82
|
strategy: 'installed',
|
|
150
|
-
nodeModulesPath:
|
|
83
|
+
nodeModulesPath: join(repoRoot, 'node_modules'),
|
|
151
84
|
};
|
|
152
85
|
}
|
|
153
86
|
|
package/templates/AGENTS.md
CHANGED
|
@@ -168,7 +168,7 @@ Rules:
|
|
|
168
168
|
<invocation_conventions>
|
|
169
169
|
- `$name` — invoke a workflow skill
|
|
170
170
|
- `/skills` — browse available skills
|
|
171
|
-
-
|
|
171
|
+
- Prefer skill invocation and keyword routing as the primary user-facing workflow surface
|
|
172
172
|
</invocation_conventions>
|
|
173
173
|
|
|
174
174
|
<model_routing>
|
|
@@ -191,7 +191,7 @@ Key roles:
|
|
|
191
191
|
- `executor` — implementation and refactoring
|
|
192
192
|
- `verifier` — completion evidence and validation
|
|
193
193
|
|
|
194
|
-
Specialists remain available through
|
|
194
|
+
Specialists remain available through the role catalog and native child-agent surfaces when the task clearly benefits from them.
|
|
195
195
|
</agent_catalog>
|
|
196
196
|
|
|
197
197
|
---
|
|
@@ -208,7 +208,7 @@ The `deep-interview` skill is the Socratic deep interview workflow and includes
|
|
|
208
208
|
Runtime availability gate:
|
|
209
209
|
- Treat `autopilot`, `ralph`, `ultrawork`, `ultraqa`, `team`/`swarm`, and `ecomode` as **OMX runtime workflows**, not generic prompt aliases.
|
|
210
210
|
- Auto-activate those runtime workflows only when the current session is actually running under OMX CLI/runtime (for example, launched via `omx`, with OMX session overlay/runtime state available, or when the user explicitly asks to run `omx ...` in the shell).
|
|
211
|
-
- In Codex App or plain Codex sessions without OMX runtime, do **not** treat those keywords alone as activation. Explain that they require OMX CLI runtime support, and continue with the nearest App-safe surface (`deep-interview`, `ralplan`, `plan`,
|
|
211
|
+
- In Codex App or plain Codex sessions without OMX runtime, do **not** treat those keywords alone as activation. Explain that they require OMX CLI runtime support, and continue with the nearest App-safe surface (`deep-interview`, `ralplan`, `plan`, or native subagents) unless the user explicitly wants you to launch OMX from the shell.
|
|
212
212
|
|
|
213
213
|
| Keyword(s) | Skill | Action |
|
|
214
214
|
|-------------|-------|--------|
|
|
@@ -234,7 +234,6 @@ Detection rules:
|
|
|
234
234
|
- Explicit `$name` invocations run left-to-right and override non-explicit keyword resolution.
|
|
235
235
|
- If multiple non-explicit keywords match, use the most specific match.
|
|
236
236
|
- Runtime-only keywords must pass the runtime availability gate before activation.
|
|
237
|
-
- If the user explicitly invokes `/prompts:<name>`, do not auto-activate keyword skills unless explicit `$name` tokens are also present.
|
|
238
237
|
- The rest of the user message becomes the task description.
|
|
239
238
|
|
|
240
239
|
Ralph / Ralplan execution gate:
|