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
|
@@ -4,11 +4,18 @@
|
|
|
4
4
|
* automatically send a continuation prompt so the agent keeps working.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { readFile, writeFile } from 'fs/promises';
|
|
8
|
-
import { join } from 'path';
|
|
7
|
+
import { mkdir, readFile, writeFile } from 'fs/promises';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
9
|
import { homedir } from 'os';
|
|
10
10
|
import { asNumber, safeString } from './utils.js';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
getScopedStateDirsForCurrentSession,
|
|
13
|
+
getScopedStatePath,
|
|
14
|
+
readJsonIfExists,
|
|
15
|
+
readScopedJsonIfExists,
|
|
16
|
+
readdir,
|
|
17
|
+
writeScopedJson,
|
|
18
|
+
} from './state-io.js';
|
|
12
19
|
import { runProcess } from './process-runner.js';
|
|
13
20
|
import { logTmuxHookEvent } from './log.js';
|
|
14
21
|
import { evaluatePaneInjectionReadiness, mapPaneInjectionReadinessReason, sendPaneInput } from './team-tmux-guard.js';
|
|
@@ -26,6 +33,7 @@ import {
|
|
|
26
33
|
export const SKILL_ACTIVE_STATE_FILE = 'skill-active-state.json';
|
|
27
34
|
export const DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS = ['yes', 'y', 'proceed', 'continue', 'ok', 'sure', 'go ahead', 'next i should'];
|
|
28
35
|
export const DEEP_INTERVIEW_INPUT_LOCK_MESSAGE = 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.';
|
|
36
|
+
export const DEFAULT_AUTO_NUDGE_RESPONSE = 'continue with the current task only if it is already authorized';
|
|
29
37
|
const DEEP_INTERVIEW_ERROR_PATTERNS = [' error', ' failed', ' failure', ' exception', 'unable to continue', 'cannot continue', 'could not continue'];
|
|
30
38
|
const DEEP_INTERVIEW_ABORT_PATTERNS = ['aborted', 'cancelled', 'canceled'];
|
|
31
39
|
const DEEP_INTERVIEW_ABORT_INPUTS = new Set(['abort', 'cancel', 'stop']);
|
|
@@ -171,29 +179,30 @@ export function inferSkillPhaseFromText(text, currentPhase = 'planning') {
|
|
|
171
179
|
return normalizeSkillPhase(currentPhase);
|
|
172
180
|
}
|
|
173
181
|
|
|
174
|
-
async function loadSkillActiveState(stateDir) {
|
|
175
|
-
const raw = await
|
|
182
|
+
async function loadSkillActiveState(stateDir, sessionId) {
|
|
183
|
+
const raw = await readScopedJsonIfExists(stateDir, SKILL_ACTIVE_STATE_FILE, sessionId, null);
|
|
176
184
|
return normalizeSkillActiveState(raw);
|
|
177
185
|
}
|
|
178
186
|
|
|
179
|
-
async function persistSkillActiveState(stateDir, state) {
|
|
180
|
-
await
|
|
187
|
+
async function persistSkillActiveState(stateDir, sessionId, state) {
|
|
188
|
+
await writeScopedJson(stateDir, SKILL_ACTIVE_STATE_FILE, sessionId, state).catch(() => {});
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
|
|
184
|
-
export async function isDeepInterviewStateActive(stateDir) {
|
|
185
|
-
const modeState = await
|
|
192
|
+
export async function isDeepInterviewStateActive(stateDir, sessionId) {
|
|
193
|
+
const modeState = await readScopedJsonIfExists(stateDir, 'deep-interview-state.json', sessionId, null);
|
|
186
194
|
return Boolean(modeState && modeState.active === true);
|
|
187
195
|
}
|
|
188
196
|
|
|
189
|
-
export async function isDeepInterviewInputLockActive(stateDir) {
|
|
190
|
-
const skillState = await loadSkillActiveState(stateDir);
|
|
197
|
+
export async function isDeepInterviewInputLockActive(stateDir, sessionId) {
|
|
198
|
+
const skillState = await loadSkillActiveState(stateDir, sessionId);
|
|
191
199
|
return isDeepInterviewAutoApprovalLocked(skillState);
|
|
192
200
|
}
|
|
193
201
|
|
|
194
202
|
export async function resolveAutoNudgeSignature(stateDir, payload, lastMessage = '') {
|
|
195
203
|
const normalizedMessage = normalizeAutoNudgeSignatureText(lastMessage);
|
|
196
|
-
const
|
|
204
|
+
const invocationSessionId = resolveInvocationSessionId(payload);
|
|
205
|
+
const hudState = await readScopedJsonIfExists(stateDir, 'hud-state.json', invocationSessionId, null);
|
|
197
206
|
const hudTurnAt = safeString(hudState?.last_turn_at).trim();
|
|
198
207
|
const hudTurnCount = Number.isFinite(hudState?.turn_count) ? hudState.turn_count : null;
|
|
199
208
|
const hudMessage = normalizeAutoNudgeSignatureText(hudState?.last_agent_output || hudState?.last_agent_message || '');
|
|
@@ -218,70 +227,65 @@ function latestUserInputFromPayload(payload) {
|
|
|
218
227
|
}
|
|
219
228
|
|
|
220
229
|
export const DEFAULT_STALL_PATTERNS = [
|
|
221
|
-
'if you want',
|
|
222
|
-
'would you like',
|
|
223
|
-
'shall i',
|
|
224
|
-
'next i can',
|
|
225
230
|
'continue with',
|
|
226
231
|
'continue on',
|
|
227
|
-
'do you want me to',
|
|
228
|
-
'let me know if',
|
|
229
|
-
'do you want',
|
|
230
|
-
'want me to',
|
|
231
|
-
'let me know',
|
|
232
|
-
'just let me know',
|
|
233
|
-
'i can also',
|
|
234
|
-
'i could also',
|
|
235
232
|
'pick up with',
|
|
236
|
-
'next step',
|
|
237
|
-
'next steps',
|
|
238
|
-
'ready to proceed',
|
|
239
|
-
'i\'m ready to',
|
|
240
233
|
'keep going',
|
|
241
|
-
'should i',
|
|
242
|
-
'whenever you',
|
|
243
|
-
'say go',
|
|
244
|
-
'say yes',
|
|
245
|
-
'type continue',
|
|
246
234
|
'and i\'ll continue',
|
|
247
|
-
'and i\'ll proceed',
|
|
248
235
|
'keep driving',
|
|
249
236
|
'keep pushing',
|
|
250
237
|
'move forward',
|
|
251
238
|
'drive forward',
|
|
252
|
-
'proceed from here',
|
|
253
239
|
'i\'ll continue from',
|
|
254
240
|
];
|
|
255
241
|
|
|
256
242
|
const SEMANTIC_STALL_PROMPT_PATTERNS = [
|
|
257
|
-
/\bif you want\b/g,
|
|
258
|
-
/\bwould you like\b/g,
|
|
259
|
-
/\bshall i\b/g,
|
|
260
|
-
/\bshould i\b/g,
|
|
261
|
-
/\bdo you want(?: me)? to\b/g,
|
|
262
|
-
/\bwant me to\b/g,
|
|
263
|
-
/\blet me know(?: if)?\b/g,
|
|
264
|
-
/\bjust let me know\b/g,
|
|
265
|
-
/\bi can also\b/g,
|
|
266
|
-
/\bi could also\b/g,
|
|
267
|
-
/\bnext i can\b/g,
|
|
268
243
|
/\bcontinue (?:with|on)\b/g,
|
|
269
244
|
/\bpick up with\b/g,
|
|
270
|
-
/\bnext steps?\b/g,
|
|
271
|
-
/\bready to proceed\b/g,
|
|
272
|
-
/\bi'?m ready to\b/g,
|
|
273
245
|
/\bkeep going\b/g,
|
|
274
|
-
/\
|
|
275
|
-
/\bsay (?:go|yes)\b/g,
|
|
276
|
-
/\btype continue\b/g,
|
|
277
|
-
/\band i'?ll (?:continue|proceed)\b/g,
|
|
246
|
+
/\band i'?ll continue\b/g,
|
|
278
247
|
/\bkeep (?:driving|pushing)\b/g,
|
|
279
248
|
/\bmove forward\b/g,
|
|
280
249
|
/\bdrive forward\b/g,
|
|
281
|
-
/\bproceed from here\b/g,
|
|
282
250
|
/\bi'?ll continue from\b/g,
|
|
283
251
|
];
|
|
284
252
|
|
|
253
|
+
const PLANNING_ONLY_STALL_PATTERNS = [
|
|
254
|
+
'plan',
|
|
255
|
+
'planning',
|
|
256
|
+
'approach',
|
|
257
|
+
'proposal',
|
|
258
|
+
'options',
|
|
259
|
+
'review',
|
|
260
|
+
'feedback',
|
|
261
|
+
'spec',
|
|
262
|
+
'design',
|
|
263
|
+
'next step',
|
|
264
|
+
'next steps',
|
|
265
|
+
'ready to proceed',
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
const PERMISSION_SEEKING_STALL_PATTERNS = [
|
|
269
|
+
'if you want',
|
|
270
|
+
'would you like',
|
|
271
|
+
'shall i',
|
|
272
|
+
'should i',
|
|
273
|
+
'do you want me to',
|
|
274
|
+
'do you want',
|
|
275
|
+
'want me to',
|
|
276
|
+
'let me know if',
|
|
277
|
+
'let me know',
|
|
278
|
+
'just let me know',
|
|
279
|
+
'i can also',
|
|
280
|
+
'i could also',
|
|
281
|
+
'next i can',
|
|
282
|
+
'whenever you',
|
|
283
|
+
'say go',
|
|
284
|
+
'say yes',
|
|
285
|
+
'type continue',
|
|
286
|
+
'proceed from here',
|
|
287
|
+
];
|
|
288
|
+
|
|
285
289
|
function normalizeStallDetectionText(text) {
|
|
286
290
|
return stripOrchestrationIntentTags(safeString(text))
|
|
287
291
|
.replace(/\r\n?/g, '\n')
|
|
@@ -315,6 +319,52 @@ export function normalizeAutoNudgeSignatureText(text) {
|
|
|
315
319
|
return normalized;
|
|
316
320
|
}
|
|
317
321
|
|
|
322
|
+
function normalizePatternList(patterns) {
|
|
323
|
+
return patterns.map((pattern) => normalizeStallDetectionText(pattern)).filter(Boolean);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function usesDefaultStallPatterns(patterns) {
|
|
327
|
+
const normalizedPatterns = normalizePatternList(patterns);
|
|
328
|
+
const normalizedDefaults = normalizePatternList(DEFAULT_STALL_PATTERNS);
|
|
329
|
+
return normalizedPatterns.length === normalizedDefaults.length
|
|
330
|
+
&& normalizedPatterns.every((pattern, index) => pattern === normalizedDefaults[index]);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function matchesNormalizedPatterns(normalizedText, normalizedPatterns) {
|
|
334
|
+
if (!normalizedText || normalizedPatterns.length === 0) return false;
|
|
335
|
+
const tail = normalizedText.slice(-800);
|
|
336
|
+
const lines = tail.split('\n').filter((line) => line.trim());
|
|
337
|
+
const hotZone = lines.slice(-3).join('\n');
|
|
338
|
+
if (normalizedPatterns.some((pattern) => hotZone.includes(pattern))) return true;
|
|
339
|
+
return normalizedPatterns.some((pattern) => tail.includes(pattern));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function looksLikePlanningOnlyContinuation(normalizedText) {
|
|
343
|
+
return matchesNormalizedPatterns(normalizedText, normalizePatternList(PLANNING_ONLY_STALL_PATTERNS));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function looksLikePermissionSeekingContinuation(normalizedText) {
|
|
347
|
+
return matchesNormalizedPatterns(normalizedText, normalizePatternList(PERMISSION_SEEKING_STALL_PATTERNS));
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Pattern to identify test-runner output lines (status symbols, PASS/FAIL prefixes).
|
|
352
|
+
* These lines may incidentally contain stall-pattern words inside test names and
|
|
353
|
+
* should be excluded before running stall detection on pane captures.
|
|
354
|
+
*/
|
|
355
|
+
const CAPTURE_TEST_LINE_RE = /^\s*(?:[✓✗✕×●✔✘▶◆○]|(?:PASS|FAIL|SKIP|ERROR)\s)/u;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Strip lines that look like test-runner output so stall patterns inside test
|
|
359
|
+
* names (e.g. "✓ should continue with the next step") do not trigger a nudge.
|
|
360
|
+
*/
|
|
361
|
+
function filterCapturedTestLines(text) {
|
|
362
|
+
return safeString(text)
|
|
363
|
+
.split('\n')
|
|
364
|
+
.filter((line) => !CAPTURE_TEST_LINE_RE.test(line))
|
|
365
|
+
.join('\n');
|
|
366
|
+
}
|
|
367
|
+
|
|
318
368
|
function summarizePaneCaptureForLog(captured, maxLines = 6) {
|
|
319
369
|
const lines = safeString(captured)
|
|
320
370
|
.replace(/\r\n?/g, '\n')
|
|
@@ -358,6 +408,12 @@ export function normalizeAutoNudgeConfig(raw) {
|
|
|
358
408
|
};
|
|
359
409
|
}
|
|
360
410
|
|
|
411
|
+
export function resolveEffectiveAutoNudgeResponse(response) {
|
|
412
|
+
const normalized = safeString(response).trim();
|
|
413
|
+
if (!normalized) return DEFAULT_AUTO_NUDGE_RESPONSE;
|
|
414
|
+
return isBlockedAutoApprovalInput(normalized) ? DEFAULT_AUTO_NUDGE_RESPONSE : normalized;
|
|
415
|
+
}
|
|
416
|
+
|
|
361
417
|
export async function loadAutoNudgeConfig() {
|
|
362
418
|
const codexHomePath = process.env.CODEX_HOME || join(homedir(), '.codex');
|
|
363
419
|
const configPath = join(codexHomePath, '.omx-config.json');
|
|
@@ -373,16 +429,16 @@ async function localTmuxInjectionDisabled(cwd) {
|
|
|
373
429
|
return tmuxHookExplicitlyDisablesInjection(raw);
|
|
374
430
|
}
|
|
375
431
|
|
|
376
|
-
export function detectStallPattern(text, patterns) {
|
|
432
|
+
export function detectStallPattern(text, patterns, currentPhase = '') {
|
|
377
433
|
if (!text || typeof text !== 'string') return false;
|
|
378
434
|
const normalized = normalizeStallDetectionText(text);
|
|
379
435
|
if (!normalized) return false;
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if (
|
|
385
|
-
return
|
|
436
|
+
const normalizedPatterns = normalizePatternList(patterns);
|
|
437
|
+
if (!matchesNormalizedPatterns(normalized, normalizedPatterns)) return false;
|
|
438
|
+
if (!usesDefaultStallPatterns(patterns)) return true;
|
|
439
|
+
if (looksLikePermissionSeekingContinuation(normalized)) return false;
|
|
440
|
+
if (safeString(currentPhase).trim().toLowerCase() === 'planning') return false;
|
|
441
|
+
return !looksLikePlanningOnlyContinuation(normalized);
|
|
386
442
|
}
|
|
387
443
|
|
|
388
444
|
export async function capturePane(paneId, lines = 10) {
|
|
@@ -426,6 +482,7 @@ export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: a
|
|
|
426
482
|
|
|
427
483
|
export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
428
484
|
const config = await loadAutoNudgeConfig();
|
|
485
|
+
const effectiveResponse = resolveEffectiveAutoNudgeResponse(config.response);
|
|
429
486
|
if (!config.enabled) return;
|
|
430
487
|
if (await localTmuxInjectionDisabled(cwd)) {
|
|
431
488
|
await logTmuxHookEvent(logsDir, {
|
|
@@ -450,7 +507,8 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
450
507
|
|
|
451
508
|
const lastMessage = safeString(payload['last-assistant-message'] || payload.last_assistant_message || '');
|
|
452
509
|
const latestUserInput = latestUserInputFromPayload(payload);
|
|
453
|
-
|
|
510
|
+
const invocationSessionId = resolveInvocationSessionId(payload);
|
|
511
|
+
let skillState = await loadSkillActiveState(stateDir, invocationSessionId);
|
|
454
512
|
let releaseReason = null;
|
|
455
513
|
|
|
456
514
|
try {
|
|
@@ -460,23 +518,23 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
460
518
|
skillState.active = inferredPhase !== 'completing';
|
|
461
519
|
skillState.updated_at = new Date().toISOString();
|
|
462
520
|
releaseReason = inferDeepInterviewReleaseReason({ skillState, latestUserInput, lastMessage });
|
|
463
|
-
await persistSkillActiveState(stateDir, skillState);
|
|
521
|
+
await persistSkillActiveState(stateDir, invocationSessionId, skillState);
|
|
464
522
|
}
|
|
465
523
|
|
|
466
|
-
const nudgeStatePath =
|
|
467
|
-
let nudgeState = await
|
|
524
|
+
const nudgeStatePath = await getScopedStatePath(stateDir, 'auto-nudge-state.json', invocationSessionId);
|
|
525
|
+
let nudgeState = await readScopedJsonIfExists(stateDir, 'auto-nudge-state.json', invocationSessionId, null);
|
|
468
526
|
if (!nudgeState || typeof nudgeState !== 'object') {
|
|
469
527
|
nudgeState = { nudgeCount: 0, lastNudgeAt: '', lastSignature: '', lastSemanticSignature: '' };
|
|
470
528
|
}
|
|
471
529
|
const paneId = await resolveNudgePaneTarget(stateDir, cwd, payload);
|
|
472
530
|
|
|
473
|
-
let detected = detectStallPattern(lastMessage, config.patterns);
|
|
531
|
+
let detected = detectStallPattern(lastMessage, config.patterns, skillState?.phase);
|
|
474
532
|
let source = 'payload';
|
|
475
533
|
let captured = '';
|
|
476
534
|
|
|
477
535
|
if (!detected && paneId) {
|
|
478
536
|
captured = await capturePane(paneId);
|
|
479
|
-
detected = detectStallPattern(captured, config.patterns);
|
|
537
|
+
detected = detectStallPattern(filterCapturedTestLines(captured), config.patterns, skillState?.phase);
|
|
480
538
|
source = 'capture-pane';
|
|
481
539
|
}
|
|
482
540
|
|
|
@@ -523,6 +581,7 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
523
581
|
if (!isFallbackWatcherSource && config.stallMs > 0) {
|
|
524
582
|
nudgeState.pendingSignature = signature;
|
|
525
583
|
nudgeState.pendingSince = new Date().toISOString();
|
|
584
|
+
await mkdir(dirname(nudgeStatePath), { recursive: true }).catch(() => {});
|
|
526
585
|
await writeFile(nudgeStatePath, JSON.stringify(nudgeState, null, 2)).catch(() => {});
|
|
527
586
|
await logTmuxHookEvent(logsDir, {
|
|
528
587
|
timestamp: new Date().toISOString(),
|
|
@@ -556,10 +615,10 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
556
615
|
timestamp: new Date().toISOString(),
|
|
557
616
|
type: 'auto_nudge_blocked',
|
|
558
617
|
pane_id: paneId,
|
|
559
|
-
response:
|
|
618
|
+
response: effectiveResponse,
|
|
560
619
|
source,
|
|
561
620
|
blocked_by: 'deep-interview-lock',
|
|
562
|
-
block_kind: isBlockedAutoApprovalInput(
|
|
621
|
+
block_kind: isBlockedAutoApprovalInput(effectiveResponse, skillState.input_lock?.blocked_inputs)
|
|
563
622
|
? 'blocked-auto-approval'
|
|
564
623
|
: 'input-lock-active',
|
|
565
624
|
message: blockedMessage,
|
|
@@ -576,7 +635,7 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
576
635
|
try {
|
|
577
636
|
const sendResult = await sendPaneInput({
|
|
578
637
|
paneTarget: paneId,
|
|
579
|
-
prompt: `${
|
|
638
|
+
prompt: `${effectiveResponse} ${DEFAULT_MARKER}`,
|
|
580
639
|
submitKeyPresses: 2,
|
|
581
640
|
submitDelayMs: 100,
|
|
582
641
|
});
|
|
@@ -590,20 +649,14 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
590
649
|
nudgeState.lastSemanticSignature = semanticSignature;
|
|
591
650
|
nudgeState.pendingSignature = '';
|
|
592
651
|
nudgeState.pendingSince = '';
|
|
652
|
+
await mkdir(dirname(nudgeStatePath), { recursive: true }).catch(() => {});
|
|
593
653
|
await writeFile(nudgeStatePath, JSON.stringify(nudgeState, null, 2)).catch(() => {});
|
|
594
654
|
|
|
595
|
-
if (skillState && skillState.phase === 'planning') {
|
|
596
|
-
skillState.phase = 'executing';
|
|
597
|
-
skillState.active = true;
|
|
598
|
-
skillState.updated_at = nowIso;
|
|
599
|
-
await persistSkillActiveState(stateDir, skillState);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
655
|
await logTmuxHookEvent(logsDir, {
|
|
603
656
|
timestamp: nowIso,
|
|
604
657
|
type: 'auto_nudge',
|
|
605
658
|
pane_id: paneId,
|
|
606
|
-
response:
|
|
659
|
+
response: effectiveResponse,
|
|
607
660
|
source,
|
|
608
661
|
nudge_count: nudgeState.nudgeCount,
|
|
609
662
|
});
|
|
@@ -618,7 +671,7 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
618
671
|
} finally {
|
|
619
672
|
if (releaseReason && skillState && isDeepInterviewAutoApprovalLocked(skillState)) {
|
|
620
673
|
releaseDeepInterviewInputLock(skillState, releaseReason, new Date().toISOString());
|
|
621
|
-
await persistSkillActiveState(stateDir, skillState).catch(() => {});
|
|
674
|
+
await persistSkillActiveState(stateDir, invocationSessionId, skillState).catch(() => {});
|
|
622
675
|
}
|
|
623
676
|
}
|
|
624
677
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { execFileSync } from 'child_process';
|
|
2
2
|
import { readFileSync } from 'fs';
|
|
3
|
-
import { basename, dirname
|
|
3
|
+
import { basename, dirname } from 'path';
|
|
4
4
|
import { readSessionState, isSessionStale } from '../../hooks/session.js';
|
|
5
5
|
import { runProcess } from './process-runner.js';
|
|
6
6
|
import { safeString } from './utils.js';
|
|
7
|
+
import { sameFilePath } from '../../utils/paths.js';
|
|
7
8
|
|
|
8
9
|
function sanitizeTmuxToken(value: string): string {
|
|
9
10
|
const cleaned = safeString(value)
|
|
@@ -56,6 +57,10 @@ export function resolveInvocationSessionId(payload: any): string {
|
|
|
56
57
|
).trim();
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
function readNativeSessionId(sessionState: { native_session_id?: unknown; codex_session_id?: unknown }): string {
|
|
61
|
+
return safeString(sessionState.native_session_id || sessionState.codex_session_id || '').trim();
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
function readCurrentTmuxSessionName(): string {
|
|
60
65
|
if (!process.env.TMUX) return '';
|
|
61
66
|
try {
|
|
@@ -135,23 +140,32 @@ export async function resolveManagedSessionContext(cwd: string, payload: any, {
|
|
|
135
140
|
if (!sessionState) {
|
|
136
141
|
return { managed: false, reason: 'missing_session_state', invocationSessionId, sessionState: null, expectedTmuxSessionName: '', currentTmuxSessionName: '' };
|
|
137
142
|
}
|
|
138
|
-
if (
|
|
143
|
+
if (!sameFilePath(safeString(sessionState.cwd || cwd), cwd)) {
|
|
139
144
|
return { managed: false, reason: 'cwd_mismatch', invocationSessionId, sessionState, expectedTmuxSessionName: '', currentTmuxSessionName: '' };
|
|
140
145
|
}
|
|
141
|
-
|
|
146
|
+
const canonicalSessionId = safeString(sessionState.session_id).trim();
|
|
147
|
+
const nativeSessionId = readNativeSessionId(sessionState);
|
|
148
|
+
const allowedInvocationIds = new Set([canonicalSessionId, nativeSessionId].filter(Boolean));
|
|
149
|
+
if (!allowedInvocationIds.has(invocationSessionId)) {
|
|
142
150
|
return { managed: false, reason: 'session_id_mismatch', invocationSessionId, sessionState, expectedTmuxSessionName: '', currentTmuxSessionName: '' };
|
|
143
151
|
}
|
|
144
152
|
if (isSessionStale(sessionState)) {
|
|
145
153
|
return { managed: false, reason: 'stale_session', invocationSessionId, sessionState, expectedTmuxSessionName: '', currentTmuxSessionName: '' };
|
|
146
154
|
}
|
|
147
155
|
|
|
148
|
-
const
|
|
156
|
+
const authoritativeSessionCwd = safeString(sessionState.cwd || cwd).trim() || cwd;
|
|
157
|
+
const expectedTmuxSessionName = buildExpectedManagedTmuxSessionName(
|
|
158
|
+
authoritativeSessionCwd,
|
|
159
|
+
canonicalSessionId || invocationSessionId,
|
|
160
|
+
);
|
|
149
161
|
const currentTmuxSessionName = readCurrentTmuxSessionName();
|
|
150
162
|
if (currentTmuxSessionName && currentTmuxSessionName === expectedTmuxSessionName) {
|
|
151
163
|
return {
|
|
152
164
|
managed: true,
|
|
153
165
|
reason: 'tmux_session_match',
|
|
154
166
|
invocationSessionId,
|
|
167
|
+
canonicalSessionId,
|
|
168
|
+
nativeSessionId,
|
|
155
169
|
sessionState,
|
|
156
170
|
expectedTmuxSessionName,
|
|
157
171
|
currentTmuxSessionName,
|
|
@@ -163,6 +177,8 @@ export async function resolveManagedSessionContext(cwd: string, payload: any, {
|
|
|
163
177
|
managed: true,
|
|
164
178
|
reason: currentTmuxSessionName ? 'pid_ancestry_match_tmux_mismatch' : 'pid_ancestry_match',
|
|
165
179
|
invocationSessionId,
|
|
180
|
+
canonicalSessionId,
|
|
181
|
+
nativeSessionId,
|
|
166
182
|
sessionState,
|
|
167
183
|
expectedTmuxSessionName,
|
|
168
184
|
currentTmuxSessionName: '',
|
|
@@ -173,6 +189,8 @@ export async function resolveManagedSessionContext(cwd: string, payload: any, {
|
|
|
173
189
|
managed: false,
|
|
174
190
|
reason: currentTmuxSessionName ? 'tmux_session_mismatch' : 'pid_ancestry_mismatch',
|
|
175
191
|
invocationSessionId,
|
|
192
|
+
canonicalSessionId,
|
|
193
|
+
nativeSessionId,
|
|
176
194
|
sessionState,
|
|
177
195
|
expectedTmuxSessionName,
|
|
178
196
|
currentTmuxSessionName,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execFileSync } from 'child_process';
|
|
2
2
|
import { basename, dirname } from 'path';
|
|
3
3
|
import { safeString } from './utils.js';
|
|
4
|
+
import { upsertCurrentTaskBaseline } from '../../team/current-task-baseline.js';
|
|
4
5
|
|
|
5
6
|
const TEST_SEGMENT_PATTERNS = [
|
|
6
7
|
/^npm\s+(?:run\s+)?test\b/i,
|
|
@@ -216,6 +217,26 @@ export function buildOperationalContext({
|
|
|
216
217
|
};
|
|
217
218
|
const resolvedSessionName = resolveOperationalSessionName(cwd, sessionId, sessionName);
|
|
218
219
|
|
|
220
|
+
if (repoMeta.repo_path && repoMeta.branch) {
|
|
221
|
+
try {
|
|
222
|
+
const lifecycleStatus = normalizedEvent === 'pr-merged'
|
|
223
|
+
? 'merged'
|
|
224
|
+
: normalizedEvent === 'pr-closed'
|
|
225
|
+
? 'closed'
|
|
226
|
+
: undefined;
|
|
227
|
+
upsertCurrentTaskBaseline(repoMeta.repo_path, {
|
|
228
|
+
branch_name: repoMeta.branch,
|
|
229
|
+
worktree_path: repoMeta.worktree_path,
|
|
230
|
+
issue_number: detectedIssue,
|
|
231
|
+
pr_number: detectedPrInfo.pr_number,
|
|
232
|
+
pr_url: detectedPrInfo.pr_url,
|
|
233
|
+
...(lifecycleStatus ? { status: lifecycleStatus } : {}),
|
|
234
|
+
});
|
|
235
|
+
} catch {
|
|
236
|
+
// best effort only; operational context building must stay non-fatal
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
219
240
|
return {
|
|
220
241
|
normalized_event: normalizedEvent,
|
|
221
242
|
...(resolvedSessionName ? { session_name: resolvedSessionName } : {}),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { existsSync } from 'fs';
|
|
2
2
|
import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from 'fs/promises';
|
|
3
|
-
import { dirname, join } from 'path';
|
|
3
|
+
import { dirname, join, resolve } from 'path';
|
|
4
4
|
import { captureTmuxPaneFromEnv } from '../../state/mode-state-context.js';
|
|
5
|
+
import { readUsableSessionState } from '../../hooks/session.js';
|
|
5
6
|
import { resolveCodexPane } from '../tmux-hook-engine.js';
|
|
6
7
|
import { safeString } from './utils.js';
|
|
7
8
|
|
|
@@ -128,7 +129,7 @@ function isActiveRalphCandidate(state: Record<string, unknown> | null): state is
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
async function readCurrentOmxSessionId(stateDir: string): Promise<string> {
|
|
131
|
-
const session = await
|
|
132
|
+
const session = await readUsableSessionState(resolve(stateDir, '..', '..'));
|
|
132
133
|
const sessionId = safeString(session?.session_id).trim();
|
|
133
134
|
return SESSION_ID_PATTERN.test(sessionId) ? sessionId : '';
|
|
134
135
|
}
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* State file I/O helpers for notify-hook modules.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { readFile, readdir } from 'fs/promises';
|
|
6
|
-
import { join } from 'path';
|
|
5
|
+
import { mkdir, readFile, readdir, writeFile } from 'fs/promises';
|
|
6
|
+
import { dirname, join, resolve } from 'path';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { readUsableSessionState } from '../../hooks/session.js';
|
|
7
9
|
import { asNumber, safeString } from './utils.js';
|
|
8
10
|
|
|
9
11
|
const SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
@@ -16,18 +18,93 @@ export function readJsonIfExists(path: string, fallback: any): Promise<any> {
|
|
|
16
18
|
.catch(() => fallback);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
function isSafeStateFileName(fileName: string): boolean {
|
|
22
|
+
return fileName.length > 0
|
|
23
|
+
&& !fileName.includes('..')
|
|
24
|
+
&& !fileName.includes('/')
|
|
25
|
+
&& !fileName.includes('\\');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function readCurrentSessionId(baseStateDir: string): Promise<string | undefined> {
|
|
29
|
+
const cwd = resolve(baseStateDir, '..', '..');
|
|
30
|
+
const session = await readUsableSessionState(cwd);
|
|
31
|
+
const sessionId = safeString(session?.session_id);
|
|
32
|
+
return SESSION_ID_PATTERN.test(sessionId) ? sessionId : undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function resolveScopedStateDir(
|
|
36
|
+
baseStateDir: string,
|
|
37
|
+
explicitSessionId?: string,
|
|
38
|
+
): Promise<string> {
|
|
39
|
+
const currentSessionId = await readCurrentSessionId(baseStateDir);
|
|
40
|
+
if (currentSessionId) {
|
|
41
|
+
return join(baseStateDir, 'sessions', currentSessionId);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const normalizedExplicit = safeString(explicitSessionId).trim();
|
|
45
|
+
if (SESSION_ID_PATTERN.test(normalizedExplicit)) {
|
|
46
|
+
const explicitDir = join(baseStateDir, 'sessions', normalizedExplicit);
|
|
47
|
+
if (existsSync(explicitDir)) {
|
|
48
|
+
return explicitDir;
|
|
26
49
|
}
|
|
27
|
-
} catch {
|
|
28
|
-
// No session file or malformed - fall back to global only
|
|
29
50
|
}
|
|
30
|
-
return
|
|
51
|
+
return baseStateDir;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function getScopedStateDirsForCurrentSession(
|
|
55
|
+
baseStateDir: string,
|
|
56
|
+
explicitSessionId?: string,
|
|
57
|
+
options: { includeRootFallback?: boolean } = {},
|
|
58
|
+
): Promise<string[]> {
|
|
59
|
+
const scopedDir = await resolveScopedStateDir(baseStateDir, explicitSessionId);
|
|
60
|
+
if (scopedDir === baseStateDir || options.includeRootFallback !== true) {
|
|
61
|
+
return [scopedDir];
|
|
62
|
+
}
|
|
63
|
+
return [scopedDir, baseStateDir];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function getScopedStatePath(
|
|
67
|
+
baseStateDir: string,
|
|
68
|
+
fileName: string,
|
|
69
|
+
explicitSessionId?: string,
|
|
70
|
+
): Promise<string> {
|
|
71
|
+
if (!isSafeStateFileName(fileName)) {
|
|
72
|
+
throw new Error(`unsafe state file name: ${fileName}`);
|
|
73
|
+
}
|
|
74
|
+
return join(await resolveScopedStateDir(baseStateDir, explicitSessionId), fileName);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function readScopedJsonIfExists(
|
|
78
|
+
baseStateDir: string,
|
|
79
|
+
fileName: string,
|
|
80
|
+
explicitSessionId: string | undefined,
|
|
81
|
+
fallback: any,
|
|
82
|
+
options: { includeRootFallback?: boolean } = {},
|
|
83
|
+
): Promise<any> {
|
|
84
|
+
if (!isSafeStateFileName(fileName)) {
|
|
85
|
+
throw new Error(`unsafe state file name: ${fileName}`);
|
|
86
|
+
}
|
|
87
|
+
const candidateDirs = await getScopedStateDirsForCurrentSession(
|
|
88
|
+
baseStateDir,
|
|
89
|
+
explicitSessionId,
|
|
90
|
+
options,
|
|
91
|
+
);
|
|
92
|
+
for (const dir of candidateDirs) {
|
|
93
|
+
const value = await readJsonIfExists(join(dir, fileName), fallback);
|
|
94
|
+
if (value !== fallback) return value;
|
|
95
|
+
}
|
|
96
|
+
return fallback;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function writeScopedJson(
|
|
100
|
+
baseStateDir: string,
|
|
101
|
+
fileName: string,
|
|
102
|
+
explicitSessionId: string | undefined,
|
|
103
|
+
value: unknown,
|
|
104
|
+
): Promise<void> {
|
|
105
|
+
const targetPath = await getScopedStatePath(baseStateDir, fileName, explicitSessionId);
|
|
106
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
107
|
+
await writeFile(targetPath, JSON.stringify(value, null, 2));
|
|
31
108
|
}
|
|
32
109
|
|
|
33
110
|
export function normalizeTmuxState(raw: any): any {
|