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
|
@@ -2,24 +2,33 @@ import { execFileSync } from "child_process";
|
|
|
2
2
|
import { existsSync, readFileSync } from "fs";
|
|
3
3
|
import { mkdir, readFile, readdir, writeFile } from "fs/promises";
|
|
4
4
|
import { join, resolve } from "path";
|
|
5
|
-
import { readModeState, updateModeState } from "../modes/base.js";
|
|
5
|
+
import { readModeState, readModeStateForSession, updateModeState } from "../modes/base.js";
|
|
6
6
|
import { listActiveSkills, readVisibleSkillActiveState, } from "../state/skill-active.js";
|
|
7
7
|
import { readSubagentSessionSummary } from "../subagents/tracker.js";
|
|
8
8
|
import { resolveCanonicalTeamStateRoot } from "../team/state-root.js";
|
|
9
|
+
import { readUsableSessionState, reconcileNativeSessionStart } from "../hooks/session.js";
|
|
9
10
|
import { appendTeamEvent, readTeamLeaderAttention, readTeamManifestV2, readTeamPhase, writeTeamLeaderAttention, writeTeamPhase, } from "../team/state.js";
|
|
10
|
-
import { omxNotepadPath, omxProjectMemoryPath
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { omxNotepadPath, omxProjectMemoryPath } from "../utils/paths.js";
|
|
12
|
+
import { getStateFilePath } from "../mcp/state-paths.js";
|
|
13
|
+
import { detectKeywords, detectPrimaryKeyword, recordSkillActivation, } from "../hooks/keyword-detector.js";
|
|
14
|
+
import { detectStallPattern, loadAutoNudgeConfig, normalizeAutoNudgeSignatureText, resolveEffectiveAutoNudgeResponse, } from "./notify-hook/auto-nudge.js";
|
|
13
15
|
import { buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, } from "./codex-native-pre-post.js";
|
|
14
16
|
import { buildNativeHookEvent, } from "../hooks/extensibility/events.js";
|
|
15
17
|
import { dispatchHookEvent } from "../hooks/extensibility/dispatcher.js";
|
|
16
|
-
import { writeSessionStart } from "../hooks/session.js";
|
|
17
18
|
import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
|
|
19
|
+
import { onSessionStart as buildWikiSessionStartContext } from "../wiki/lifecycle.js";
|
|
18
20
|
const TERMINAL_RALPH_PHASES = new Set(["complete", "failed", "cancelled"]);
|
|
19
21
|
const TERMINAL_MODE_PHASES = new Set(["complete", "failed", "cancelled"]);
|
|
20
|
-
const SKILL_STOP_BLOCKERS = new Set(["ralplan"
|
|
22
|
+
const SKILL_STOP_BLOCKERS = new Set(["ralplan"]);
|
|
21
23
|
const TEAM_TERMINAL_TASK_STATUSES = new Set(["completed", "failed"]);
|
|
22
24
|
const NATIVE_STOP_STATE_FILE = "native-stop-state.json";
|
|
25
|
+
const STABLE_FINAL_RECOMMENDATION_PATTERNS = [
|
|
26
|
+
/^\s*(?:launch|release|ship)-?ready\s*:\s*(?:yes|no)\b[^\n\r]*/im,
|
|
27
|
+
/^\s*ready to release\s*:\s*(?:yes|no)\b[^\n\r]*/im,
|
|
28
|
+
/^\s*(?:final\s+)?recommendation\s*:\s*(?:yes|no|ship|hold|release|do not release|proceed|do not proceed)\b[^\n\r]*/im,
|
|
29
|
+
/^\s*decision\s*:\s*(?:yes|no|ship|hold|release|do not release|proceed|do not proceed)\b[^\n\r]*/im,
|
|
30
|
+
];
|
|
31
|
+
const RELEASE_READINESS_FINALIZE_SYSTEM_MESSAGE = "OMX release-readiness detected a stable final recommendation with no active worker tasks; emit one concise final decision summary and finalize.";
|
|
23
32
|
function safeString(value) {
|
|
24
33
|
return typeof value === "string" ? value : "";
|
|
25
34
|
}
|
|
@@ -81,16 +90,24 @@ function readPromptText(payload) {
|
|
|
81
90
|
}
|
|
82
91
|
return "";
|
|
83
92
|
}
|
|
93
|
+
function sanitizePayloadForHookContext(payload, hookEventName) {
|
|
94
|
+
if (hookEventName !== "UserPromptSubmit")
|
|
95
|
+
return payload;
|
|
96
|
+
const sanitized = { ...payload };
|
|
97
|
+
delete sanitized.prompt;
|
|
98
|
+
delete sanitized.input;
|
|
99
|
+
delete sanitized.user_prompt;
|
|
100
|
+
delete sanitized.userPrompt;
|
|
101
|
+
delete sanitized.text;
|
|
102
|
+
return sanitized;
|
|
103
|
+
}
|
|
84
104
|
function buildBaseContext(cwd, payload, hookEventName) {
|
|
85
105
|
return {
|
|
86
106
|
cwd,
|
|
87
107
|
project_path: cwd,
|
|
88
108
|
transcript_path: safeString(payload.transcript_path ?? payload.transcriptPath) || null,
|
|
89
109
|
source: safeString(payload.source),
|
|
90
|
-
payload,
|
|
91
|
-
...(hookEventName === "UserPromptSubmit"
|
|
92
|
-
? { prompt: readPromptText(payload) }
|
|
93
|
-
: {}),
|
|
110
|
+
payload: sanitizePayloadForHookContext(payload, hookEventName),
|
|
94
111
|
};
|
|
95
112
|
}
|
|
96
113
|
async function readJsonIfExists(path) {
|
|
@@ -111,22 +128,26 @@ function formatPhase(value, fallback = "active") {
|
|
|
111
128
|
const phase = safeString(value).trim();
|
|
112
129
|
return phase || fallback;
|
|
113
130
|
}
|
|
114
|
-
async function readActiveRalphState(stateDir) {
|
|
115
|
-
const sessionInfo = await
|
|
131
|
+
async function readActiveRalphState(stateDir, preferredSessionId) {
|
|
132
|
+
const sessionInfo = await readUsableSessionState(resolve(stateDir, "..", ".."));
|
|
116
133
|
const currentOmxSessionId = safeString(sessionInfo?.session_id).trim();
|
|
117
|
-
|
|
118
|
-
|
|
134
|
+
const sessionCandidates = [...new Set([
|
|
135
|
+
safeString(preferredSessionId).trim(),
|
|
136
|
+
currentOmxSessionId,
|
|
137
|
+
].filter(Boolean))];
|
|
138
|
+
for (const sessionId of sessionCandidates) {
|
|
139
|
+
const sessionScoped = await readJsonIfExists(join(stateDir, "sessions", sessionId, "ralph-state.json"));
|
|
119
140
|
if (sessionScoped?.active === true
|
|
120
141
|
&& !TERMINAL_RALPH_PHASES.has(safeString(sessionScoped.current_phase).trim().toLowerCase())) {
|
|
121
142
|
return sessionScoped;
|
|
122
143
|
}
|
|
123
144
|
}
|
|
145
|
+
if (sessionCandidates.length > 0)
|
|
146
|
+
return null;
|
|
124
147
|
const direct = await readJsonIfExists(join(stateDir, "ralph-state.json"));
|
|
125
148
|
if (direct?.active === true && !TERMINAL_RALPH_PHASES.has(safeString(direct.current_phase).trim().toLowerCase())) {
|
|
126
149
|
return direct;
|
|
127
150
|
}
|
|
128
|
-
if (currentOmxSessionId)
|
|
129
|
-
return null;
|
|
130
151
|
const sessionsRoot = join(stateDir, "sessions");
|
|
131
152
|
if (!existsSync(sessionsRoot))
|
|
132
153
|
return null;
|
|
@@ -328,6 +349,10 @@ async function buildSessionStartContext(cwd, sessionId) {
|
|
|
328
349
|
// best effort only
|
|
329
350
|
}
|
|
330
351
|
}
|
|
352
|
+
const wikiContext = buildWikiSessionStartContext({ cwd });
|
|
353
|
+
if (wikiContext.additionalContext) {
|
|
354
|
+
sections.push(wikiContext.additionalContext);
|
|
355
|
+
}
|
|
331
356
|
const subagentSummary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
|
|
332
357
|
if (subagentSummary && subagentSummary.activeSubagentThreadIds.length > 0) {
|
|
333
358
|
sections.push(`[Subagents]\n- active subagent threads: ${subagentSummary.activeSubagentThreadIds.length}`);
|
|
@@ -337,29 +362,83 @@ async function buildSessionStartContext(cwd, sessionId) {
|
|
|
337
362
|
function buildAdditionalContextMessage(prompt, skillState) {
|
|
338
363
|
if (!prompt)
|
|
339
364
|
return null;
|
|
365
|
+
const matches = detectKeywords(prompt);
|
|
340
366
|
const match = detectPrimaryKeyword(prompt);
|
|
341
367
|
if (!match)
|
|
342
368
|
return null;
|
|
343
|
-
|
|
369
|
+
const detectedKeywordMessage = matches.length > 1
|
|
370
|
+
? `OMX native UserPromptSubmit detected workflow keywords ${matches.map((entry) => `"${entry.keyword}" -> ${entry.skill}`).join(", ")}.`
|
|
371
|
+
: `OMX native UserPromptSubmit detected workflow keyword "${match.keyword}" -> ${match.skill}.`;
|
|
372
|
+
const activeSkills = Array.isArray(skillState?.active_skills)
|
|
373
|
+
? skillState.active_skills.map((entry) => entry.skill)
|
|
374
|
+
: [];
|
|
375
|
+
const deferredSkills = Array.isArray(skillState?.deferred_skills)
|
|
376
|
+
? skillState.deferred_skills
|
|
377
|
+
: [];
|
|
378
|
+
const teamDetected = activeSkills.includes("team");
|
|
379
|
+
const combinedTransitionMessage = (() => {
|
|
380
|
+
if (!skillState?.transition_message)
|
|
381
|
+
return null;
|
|
382
|
+
if (matches.length <= 1 || activeSkills.length <= 1)
|
|
383
|
+
return skillState.transition_message;
|
|
384
|
+
const source = skillState.transition_message.match(/^mode transiting: (.+?) -> /)?.[1];
|
|
385
|
+
if (!source)
|
|
386
|
+
return skillState.transition_message;
|
|
387
|
+
return `mode transiting: ${source} -> ${activeSkills.join(" + ")}`;
|
|
388
|
+
})();
|
|
389
|
+
if (skillState?.transition_error) {
|
|
390
|
+
return [
|
|
391
|
+
`OMX native UserPromptSubmit denied workflow keyword "${match.keyword}" -> ${match.skill}.`,
|
|
392
|
+
skillState.transition_error,
|
|
393
|
+
'Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.',
|
|
394
|
+
].join(' ');
|
|
395
|
+
}
|
|
396
|
+
if (skillState?.transition_message) {
|
|
397
|
+
return [
|
|
398
|
+
detectedKeywordMessage,
|
|
399
|
+
combinedTransitionMessage,
|
|
400
|
+
activeSkills.length > 1 ? `active skills: ${activeSkills.join(", ")}.` : null,
|
|
401
|
+
deferredSkills.length > 0
|
|
402
|
+
? `planning preserved over simultaneous execution follow-up; deferred skills: ${deferredSkills.join(", ")}.`
|
|
403
|
+
: null,
|
|
404
|
+
skillState.initialized_mode && skillState.initialized_state_path
|
|
405
|
+
? `skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`
|
|
406
|
+
: null,
|
|
407
|
+
teamDetected
|
|
408
|
+
? "Use the durable OMX team runtime via `omx team ...` for coordinated execution; do not replace it with in-process fanout."
|
|
409
|
+
: null,
|
|
410
|
+
teamDetected ? "If you need help, run `omx team --help`." : null,
|
|
411
|
+
'Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.',
|
|
412
|
+
].filter(Boolean).join(' ');
|
|
413
|
+
}
|
|
414
|
+
if (teamDetected) {
|
|
344
415
|
const initializedStateMessage = skillState?.initialized_mode && skillState.initialized_state_path
|
|
345
416
|
? `skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`
|
|
346
417
|
: null;
|
|
347
418
|
return [
|
|
348
|
-
|
|
419
|
+
detectedKeywordMessage,
|
|
420
|
+
activeSkills.length > 1 ? `active skills: ${activeSkills.join(", ")}.` : null,
|
|
421
|
+
deferredSkills.length > 0
|
|
422
|
+
? `planning preserved over simultaneous execution follow-up; deferred skills: ${deferredSkills.join(", ")}.`
|
|
423
|
+
: null,
|
|
349
424
|
initializedStateMessage,
|
|
350
425
|
"Use the durable OMX team runtime via `omx team ...` for coordinated execution; do not replace it with in-process fanout.",
|
|
351
426
|
"If you need help, run `omx team --help`.",
|
|
352
|
-
"Follow AGENTS.md routing and preserve
|
|
427
|
+
"Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
|
|
353
428
|
].filter(Boolean).join(" ");
|
|
354
429
|
}
|
|
355
430
|
if (skillState?.initialized_mode && skillState.initialized_state_path) {
|
|
356
431
|
return [
|
|
357
|
-
|
|
432
|
+
detectedKeywordMessage,
|
|
433
|
+
activeSkills.length > 1 ? `active skills: ${activeSkills.join(", ")}.` : null,
|
|
434
|
+
deferredSkills.length > 0
|
|
435
|
+
? `planning preserved over simultaneous execution follow-up; deferred skills: ${deferredSkills.join(", ")}.`
|
|
436
|
+
: null,
|
|
358
437
|
`skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`,
|
|
359
|
-
"Follow AGENTS.md routing and preserve
|
|
438
|
+
"Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
|
|
360
439
|
].join(" ");
|
|
361
440
|
}
|
|
362
|
-
return
|
|
441
|
+
return `${detectedKeywordMessage} Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.`;
|
|
363
442
|
}
|
|
364
443
|
function parseTeamWorkerEnv(rawValue) {
|
|
365
444
|
const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(rawValue.trim());
|
|
@@ -455,8 +534,10 @@ function isStopExempt(payload) {
|
|
|
455
534
|
|| value.includes("compact")
|
|
456
535
|
|| value.includes("limit"));
|
|
457
536
|
}
|
|
458
|
-
async function buildModeBasedStopOutput(mode, cwd) {
|
|
459
|
-
const state =
|
|
537
|
+
async function buildModeBasedStopOutput(mode, cwd, sessionId) {
|
|
538
|
+
const state = sessionId
|
|
539
|
+
? await readModeStateForSession(mode, sessionId, cwd)
|
|
540
|
+
: await readModeState(mode, cwd);
|
|
460
541
|
if (state?.active !== true || !isNonTerminalPhase(state.current_phase))
|
|
461
542
|
return null;
|
|
462
543
|
const phase = formatPhase(state.current_phase);
|
|
@@ -467,11 +548,34 @@ async function buildModeBasedStopOutput(mode, cwd) {
|
|
|
467
548
|
systemMessage: `OMX ${mode} is still active (phase: ${phase}).`,
|
|
468
549
|
};
|
|
469
550
|
}
|
|
470
|
-
async function
|
|
471
|
-
const
|
|
551
|
+
async function readTeamModeStateForStop(cwd, sessionId) {
|
|
552
|
+
const normalizedSessionId = safeString(sessionId).trim();
|
|
553
|
+
if (!normalizedSessionId) {
|
|
554
|
+
return await readModeState("team", cwd);
|
|
555
|
+
}
|
|
556
|
+
const scopedState = await readStopSessionPinnedState("team-state.json", cwd, normalizedSessionId);
|
|
557
|
+
if (scopedState)
|
|
558
|
+
return scopedState;
|
|
559
|
+
const rootState = await readJsonIfExists(join(cwd, ".omx", "state", "team-state.json"));
|
|
560
|
+
if (rootState?.active !== true)
|
|
561
|
+
return null;
|
|
562
|
+
const ownerSessionId = safeString(rootState.session_id).trim();
|
|
563
|
+
if (ownerSessionId && ownerSessionId !== normalizedSessionId) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
return rootState;
|
|
567
|
+
}
|
|
568
|
+
async function buildTeamStopOutput(cwd, sessionId) {
|
|
569
|
+
const teamState = await readTeamModeStateForStop(cwd, sessionId);
|
|
472
570
|
if (teamState?.active !== true)
|
|
473
571
|
return null;
|
|
474
572
|
const teamName = safeString(teamState.team_name).trim();
|
|
573
|
+
if (teamName) {
|
|
574
|
+
const canonicalTeamDir = join(resolveCanonicalTeamStateRoot(cwd), "team", teamName);
|
|
575
|
+
if (!existsSync(canonicalTeamDir)) {
|
|
576
|
+
return null;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
475
579
|
const coarsePhase = teamState.current_phase;
|
|
476
580
|
const canonicalPhase = teamName ? (await readTeamPhase(teamName, cwd))?.current_phase ?? coarsePhase : coarsePhase;
|
|
477
581
|
if (!isNonTerminalPhase(canonicalPhase))
|
|
@@ -490,6 +594,43 @@ function buildTeamStopOutputForPhase(teamName, phase) {
|
|
|
490
594
|
systemMessage: `OMX team pipeline is still active at phase ${phase}.`,
|
|
491
595
|
};
|
|
492
596
|
}
|
|
597
|
+
function extractStableFinalRecommendationSummary(message) {
|
|
598
|
+
for (const pattern of STABLE_FINAL_RECOMMENDATION_PATTERNS) {
|
|
599
|
+
const match = pattern.exec(message);
|
|
600
|
+
if (!match)
|
|
601
|
+
continue;
|
|
602
|
+
const summary = match[0]?.trim().replace(/\s+/g, " ");
|
|
603
|
+
if (!summary)
|
|
604
|
+
continue;
|
|
605
|
+
return /[.!?]$/.test(summary) ? summary : `${summary}.`;
|
|
606
|
+
}
|
|
607
|
+
return "";
|
|
608
|
+
}
|
|
609
|
+
function buildStableFinalRecommendationStopSignature(payload, teamName, summary) {
|
|
610
|
+
const sessionId = readPayloadSessionId(payload) || "no-session";
|
|
611
|
+
const threadId = readPayloadThreadId(payload) || "no-thread";
|
|
612
|
+
const normalizedSummary = normalizeAutoNudgeSignatureText(summary) || summary.toLowerCase();
|
|
613
|
+
return ["release-readiness-finalize", sessionId, threadId, teamName, normalizedSummary].join("|");
|
|
614
|
+
}
|
|
615
|
+
function hasReleaseReadinessMode(payload) {
|
|
616
|
+
const mode = safeString(payload.mode).trim().toLowerCase();
|
|
617
|
+
return mode === "release-readiness";
|
|
618
|
+
}
|
|
619
|
+
async function hasReleaseReadinessStopMarker(cwd, sessionId, teamName) {
|
|
620
|
+
if (!sessionId)
|
|
621
|
+
return false;
|
|
622
|
+
const markerState = await readStopSessionPinnedState("release-readiness-state.json", cwd, sessionId);
|
|
623
|
+
if (markerState?.active !== true || markerState.stable_final_recommendation_emitted !== true) {
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
const markerTeamName = safeString(markerState.team_name).trim();
|
|
627
|
+
if (markerTeamName && markerTeamName !== teamName)
|
|
628
|
+
return false;
|
|
629
|
+
const markerSessionId = safeString(markerState.session_id).trim();
|
|
630
|
+
if (markerSessionId && markerSessionId !== sessionId)
|
|
631
|
+
return false;
|
|
632
|
+
return true;
|
|
633
|
+
}
|
|
493
634
|
function readPayloadSessionId(payload) {
|
|
494
635
|
return safeString(payload.session_id ?? payload.sessionId).trim();
|
|
495
636
|
}
|
|
@@ -499,26 +640,22 @@ function readPayloadThreadId(payload) {
|
|
|
499
640
|
function readPayloadTurnId(payload) {
|
|
500
641
|
return safeString(payload.turn_id ?? payload.turnId).trim();
|
|
501
642
|
}
|
|
502
|
-
async function
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
return
|
|
514
|
-
|
|
515
|
-
return (await readBlockingSkillForStop(cwd, sessionId, threadId, "deep-interview")) !== null;
|
|
643
|
+
async function resolveInternalSessionIdForPayload(cwd, payloadSessionId) {
|
|
644
|
+
const currentSession = await readUsableSessionState(cwd);
|
|
645
|
+
const canonicalSessionId = safeString(currentSession?.session_id).trim();
|
|
646
|
+
if (!canonicalSessionId)
|
|
647
|
+
return payloadSessionId;
|
|
648
|
+
const nativeSessionId = safeString(currentSession?.native_session_id).trim();
|
|
649
|
+
if (!payloadSessionId)
|
|
650
|
+
return canonicalSessionId;
|
|
651
|
+
if (payloadSessionId === canonicalSessionId)
|
|
652
|
+
return canonicalSessionId;
|
|
653
|
+
if (nativeSessionId && payloadSessionId === nativeSessionId)
|
|
654
|
+
return canonicalSessionId;
|
|
655
|
+
return payloadSessionId;
|
|
516
656
|
}
|
|
517
657
|
async function readStopSessionPinnedState(fileName, cwd, sessionId) {
|
|
518
|
-
const
|
|
519
|
-
const statePath = sessionId
|
|
520
|
-
? join(stateDir, "sessions", sessionId, fileName)
|
|
521
|
-
: join(stateDir, fileName);
|
|
658
|
+
const statePath = getStateFilePath(fileName, cwd, sessionId || undefined);
|
|
522
659
|
return readJsonIfExists(statePath);
|
|
523
660
|
}
|
|
524
661
|
function matchesSkillStopContext(entry, state, sessionId, threadId) {
|
|
@@ -559,6 +696,21 @@ async function readBlockingSkillForStop(cwd, sessionId, threadId, requiredSkill)
|
|
|
559
696
|
}
|
|
560
697
|
return null;
|
|
561
698
|
}
|
|
699
|
+
async function readStopAutoNudgePhase(cwd, sessionId, threadId) {
|
|
700
|
+
if (!sessionId.trim())
|
|
701
|
+
return "";
|
|
702
|
+
const canonicalState = await readVisibleSkillActiveState(cwd, sessionId);
|
|
703
|
+
const visibleEntries = canonicalState ? listActiveSkills(canonicalState) : [];
|
|
704
|
+
const deepInterview = visibleEntries.find((entry) => (entry.skill === "deep-interview"
|
|
705
|
+
&& matchesSkillStopContext(entry, canonicalState ?? {}, sessionId, threadId)));
|
|
706
|
+
if (!deepInterview)
|
|
707
|
+
return "";
|
|
708
|
+
const modeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, sessionId);
|
|
709
|
+
if (!modeState || modeState.active !== true)
|
|
710
|
+
return "";
|
|
711
|
+
const modePhase = safeString(modeState.current_phase).trim().toLowerCase();
|
|
712
|
+
return modePhase === "intent-first" ? "planning" : "";
|
|
713
|
+
}
|
|
562
714
|
function buildRepeatableStopSignature(payload, kind, detail = "") {
|
|
563
715
|
const sessionId = readPayloadSessionId(payload) || "no-session";
|
|
564
716
|
const threadId = readPayloadThreadId(payload) || "no-thread";
|
|
@@ -586,9 +738,6 @@ function buildRepeatableStopSignature(payload, kind, detail = "") {
|
|
|
586
738
|
normalizedDetail || "no-detail",
|
|
587
739
|
].join("|");
|
|
588
740
|
}
|
|
589
|
-
async function readNativeStopState(stateDir) {
|
|
590
|
-
return await readJsonIfExists(join(stateDir, NATIVE_STOP_STATE_FILE)) ?? {};
|
|
591
|
-
}
|
|
592
741
|
function readNativeStopSessionKey(payload) {
|
|
593
742
|
return readPayloadSessionId(payload) || readPayloadThreadId(payload) || "global";
|
|
594
743
|
}
|
|
@@ -600,7 +749,8 @@ function readPreviousNativeStopSignature(state, sessionKey) {
|
|
|
600
749
|
async function persistNativeStopSignature(stateDir, payload, signature) {
|
|
601
750
|
if (!signature)
|
|
602
751
|
return;
|
|
603
|
-
const
|
|
752
|
+
const statePath = join(stateDir, NATIVE_STOP_STATE_FILE);
|
|
753
|
+
const state = await readJsonIfExists(statePath) ?? {};
|
|
604
754
|
const sessions = safeObject(state.sessions);
|
|
605
755
|
const sessionKey = readNativeStopSessionKey(payload);
|
|
606
756
|
sessions[sessionKey] = {
|
|
@@ -608,7 +758,8 @@ async function persistNativeStopSignature(stateDir, payload, signature) {
|
|
|
608
758
|
last_signature: signature,
|
|
609
759
|
updated_at: new Date().toISOString(),
|
|
610
760
|
};
|
|
611
|
-
await
|
|
761
|
+
await mkdir(stateDir, { recursive: true });
|
|
762
|
+
await writeFile(statePath, JSON.stringify({
|
|
612
763
|
...state,
|
|
613
764
|
sessions,
|
|
614
765
|
}, null, 2));
|
|
@@ -618,7 +769,7 @@ async function maybeReturnRepeatableStopOutput(payload, stateDir, signature, out
|
|
|
618
769
|
return null;
|
|
619
770
|
const stopHookActive = payload.stop_hook_active === true || payload.stopHookActive === true;
|
|
620
771
|
if (stopHookActive) {
|
|
621
|
-
const state = await
|
|
772
|
+
const state = await readJsonIfExists(join(stateDir, NATIVE_STOP_STATE_FILE)) ?? {};
|
|
622
773
|
const previousSignature = readPreviousNativeStopSignature(state, readNativeStopSessionKey(payload));
|
|
623
774
|
if (!signature || previousSignature === signature) {
|
|
624
775
|
return null;
|
|
@@ -658,6 +809,43 @@ async function findCanonicalActiveTeamForSession(cwd, sessionId) {
|
|
|
658
809
|
}
|
|
659
810
|
return null;
|
|
660
811
|
}
|
|
812
|
+
async function resolveActiveTeamNameForStop(cwd, sessionId) {
|
|
813
|
+
const directState = await readTeamModeStateForStop(cwd, sessionId);
|
|
814
|
+
const directTeamName = safeString(directState?.team_name).trim();
|
|
815
|
+
if (directState?.active === true && directTeamName)
|
|
816
|
+
return directTeamName;
|
|
817
|
+
const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, sessionId);
|
|
818
|
+
return canonicalTeam?.teamName ?? "";
|
|
819
|
+
}
|
|
820
|
+
async function maybeBuildReleaseReadinessFinalizeStopOutput(payload, cwd, stateDir, sessionId) {
|
|
821
|
+
if (!sessionId)
|
|
822
|
+
return { matched: false, output: null };
|
|
823
|
+
const teamName = await resolveActiveTeamNameForStop(cwd, sessionId);
|
|
824
|
+
if (!teamName)
|
|
825
|
+
return { matched: false, output: null };
|
|
826
|
+
const explicitReleaseReadinessContext = hasReleaseReadinessMode(payload)
|
|
827
|
+
|| await hasReleaseReadinessStopMarker(cwd, sessionId, teamName);
|
|
828
|
+
if (!explicitReleaseReadinessContext) {
|
|
829
|
+
return { matched: false, output: null };
|
|
830
|
+
}
|
|
831
|
+
const summary = extractStableFinalRecommendationSummary(safeString(payload.last_assistant_message ?? payload.lastAssistantMessage));
|
|
832
|
+
if (!summary)
|
|
833
|
+
return { matched: false, output: null };
|
|
834
|
+
const leaderAttention = await readTeamLeaderAttention(teamName, cwd);
|
|
835
|
+
if (!leaderAttention
|
|
836
|
+
|| leaderAttention.leader_decision_state !== "done_waiting_on_leader"
|
|
837
|
+
|| leaderAttention.work_remaining !== false) {
|
|
838
|
+
return { matched: false, output: null };
|
|
839
|
+
}
|
|
840
|
+
const signature = buildStableFinalRecommendationStopSignature(payload, teamName, summary);
|
|
841
|
+
const output = await maybeReturnRepeatableStopOutput(payload, stateDir, signature, {
|
|
842
|
+
decision: "block",
|
|
843
|
+
reason: `Stable final recommendation already reached with no active worker tasks. Emit exactly one concise final decision summary aligned to "${summary}" with no filler or residual acknowledgements (for example "yes"), then stop.`,
|
|
844
|
+
stopReason: "release_readiness_auto_finalize",
|
|
845
|
+
systemMessage: RELEASE_READINESS_FINALIZE_SYSTEM_MESSAGE,
|
|
846
|
+
});
|
|
847
|
+
return { matched: true, output };
|
|
848
|
+
}
|
|
661
849
|
async function buildSkillStopOutput(cwd, sessionId, threadId) {
|
|
662
850
|
const blocker = await readBlockingSkillForStop(cwd, sessionId, threadId);
|
|
663
851
|
if (!blocker)
|
|
@@ -674,7 +862,7 @@ async function buildSkillStopOutput(cwd, sessionId, threadId) {
|
|
|
674
862
|
};
|
|
675
863
|
}
|
|
676
864
|
async function findActiveTeamForTransportFailure(cwd, sessionId) {
|
|
677
|
-
const teamState = await
|
|
865
|
+
const teamState = await readModeStateForSession("team", sessionId, cwd);
|
|
678
866
|
if (teamState?.active === true) {
|
|
679
867
|
const teamName = safeString(teamState.team_name).trim();
|
|
680
868
|
const coarsePhase = formatPhase(teamState.current_phase);
|
|
@@ -688,8 +876,8 @@ async function findActiveTeamForTransportFailure(cwd, sessionId) {
|
|
|
688
876
|
return await findCanonicalActiveTeamForSession(cwd, sessionId);
|
|
689
877
|
}
|
|
690
878
|
async function markTeamTransportFailure(cwd, payload) {
|
|
691
|
-
const
|
|
692
|
-
const activeTeam = await findActiveTeamForTransportFailure(cwd,
|
|
879
|
+
const canonicalSessionId = await resolveInternalSessionIdForPayload(cwd, readPayloadSessionId(payload));
|
|
880
|
+
const activeTeam = await findActiveTeamForTransportFailure(cwd, canonicalSessionId);
|
|
693
881
|
if (!activeTeam)
|
|
694
882
|
return;
|
|
695
883
|
const nowIso = new Date().toISOString();
|
|
@@ -725,7 +913,7 @@ async function markTeamTransportFailure(cwd, payload) {
|
|
|
725
913
|
],
|
|
726
914
|
leader_stale: existingAttention?.leader_stale ?? false,
|
|
727
915
|
leader_session_active: existingAttention?.leader_session_active ?? true,
|
|
728
|
-
leader_session_id: existingAttention?.leader_session_id ?? (
|
|
916
|
+
leader_session_id: existingAttention?.leader_session_id ?? (canonicalSessionId || null),
|
|
729
917
|
leader_session_stopped_at: existingAttention?.leader_session_stopped_at ?? null,
|
|
730
918
|
unread_leader_message_count: existingAttention?.unread_leader_message_count ?? 0,
|
|
731
919
|
work_remaining: existingAttention?.work_remaining ?? true,
|
|
@@ -744,7 +932,7 @@ async function markTeamTransportFailure(cwd, payload) {
|
|
|
744
932
|
current_phase: "failed",
|
|
745
933
|
error: "mcp_transport_dead",
|
|
746
934
|
last_turn_at: nowIso,
|
|
747
|
-
}, cwd);
|
|
935
|
+
}, cwd, canonicalSessionId || undefined);
|
|
748
936
|
}
|
|
749
937
|
catch {
|
|
750
938
|
// Canonical team state already carries the preserved failure for coarse-state-missing sessions.
|
|
@@ -755,29 +943,33 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
755
943
|
return null;
|
|
756
944
|
}
|
|
757
945
|
const sessionId = readPayloadSessionId(payload);
|
|
946
|
+
const canonicalSessionId = await resolveInternalSessionIdForPayload(cwd, sessionId);
|
|
758
947
|
const threadId = readPayloadThreadId(payload);
|
|
759
|
-
const ralphState = await readActiveRalphState(stateDir);
|
|
948
|
+
const ralphState = await readActiveRalphState(stateDir, canonicalSessionId);
|
|
760
949
|
const stopHookActive = payload.stop_hook_active === true || payload.stopHookActive === true;
|
|
761
950
|
if (!ralphState) {
|
|
762
951
|
const teamWorkerOutput = await buildTeamWorkerStopOutput(cwd);
|
|
763
952
|
if (!stopHookActive && hasTeamWorkerContext())
|
|
764
953
|
return teamWorkerOutput;
|
|
765
|
-
const autopilotOutput = await buildModeBasedStopOutput("autopilot", cwd);
|
|
954
|
+
const autopilotOutput = await buildModeBasedStopOutput("autopilot", cwd, canonicalSessionId);
|
|
766
955
|
if (!stopHookActive && autopilotOutput)
|
|
767
956
|
return autopilotOutput;
|
|
768
|
-
const ultraworkOutput = await buildModeBasedStopOutput("ultrawork", cwd);
|
|
957
|
+
const ultraworkOutput = await buildModeBasedStopOutput("ultrawork", cwd, canonicalSessionId);
|
|
769
958
|
if (!stopHookActive && ultraworkOutput)
|
|
770
959
|
return ultraworkOutput;
|
|
771
|
-
const ultraqaOutput = await buildModeBasedStopOutput("ultraqa", cwd);
|
|
960
|
+
const ultraqaOutput = await buildModeBasedStopOutput("ultraqa", cwd, canonicalSessionId);
|
|
772
961
|
if (!stopHookActive && ultraqaOutput)
|
|
773
962
|
return ultraqaOutput;
|
|
774
|
-
const
|
|
963
|
+
const releaseReadinessFinalizeResult = await maybeBuildReleaseReadinessFinalizeStopOutput(payload, cwd, stateDir, canonicalSessionId);
|
|
964
|
+
if (releaseReadinessFinalizeResult.matched)
|
|
965
|
+
return releaseReadinessFinalizeResult.output;
|
|
966
|
+
const teamOutput = await buildTeamStopOutput(cwd, canonicalSessionId);
|
|
775
967
|
if (teamOutput) {
|
|
776
968
|
const teamSignature = buildRepeatableStopSignature(payload, "team-stop", safeString(teamOutput.stopReason));
|
|
777
969
|
return await maybeReturnRepeatableStopOutput(payload, stateDir, teamSignature, teamOutput);
|
|
778
970
|
}
|
|
779
|
-
if (
|
|
780
|
-
const canonicalTeam = await findCanonicalActiveTeamForSession(cwd,
|
|
971
|
+
if (canonicalSessionId) {
|
|
972
|
+
const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, canonicalSessionId);
|
|
781
973
|
if (canonicalTeam) {
|
|
782
974
|
const canonicalTeamOutput = buildTeamStopOutputForPhase(canonicalTeam.teamName, canonicalTeam.phase);
|
|
783
975
|
const canonicalTeamSignature = buildRepeatableStopSignature(payload, "team-stop", `${canonicalTeam.teamName}|${canonicalTeam.phase}`);
|
|
@@ -785,19 +977,19 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
785
977
|
if (repeatedCanonicalTeamOutput)
|
|
786
978
|
return repeatedCanonicalTeamOutput;
|
|
787
979
|
}
|
|
788
|
-
const skillOutput = await buildSkillStopOutput(cwd,
|
|
980
|
+
const skillOutput = await buildSkillStopOutput(cwd, canonicalSessionId, threadId);
|
|
789
981
|
if (!stopHookActive && skillOutput)
|
|
790
982
|
return skillOutput;
|
|
791
983
|
}
|
|
792
|
-
const deepInterviewActive = await isDeepInterviewSuppressedForStop(cwd, sessionId, threadId);
|
|
793
984
|
const lastAssistantMessage = safeString(payload.last_assistant_message ?? payload.lastAssistantMessage);
|
|
794
985
|
const autoNudgeConfig = await loadAutoNudgeConfig();
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
&& detectStallPattern(lastAssistantMessage, autoNudgeConfig.patterns)) {
|
|
986
|
+
const autoNudgePhase = await readStopAutoNudgePhase(cwd, canonicalSessionId, threadId);
|
|
987
|
+
if (autoNudgeConfig.enabled
|
|
988
|
+
&& detectStallPattern(lastAssistantMessage, autoNudgeConfig.patterns, autoNudgePhase)) {
|
|
989
|
+
const effectiveResponse = resolveEffectiveAutoNudgeResponse(autoNudgeConfig.response);
|
|
798
990
|
return await maybeReturnRepeatableStopOutput(payload, stateDir, buildRepeatableStopSignature(payload, "auto-nudge", lastAssistantMessage), {
|
|
799
991
|
decision: "block",
|
|
800
|
-
reason:
|
|
992
|
+
reason: effectiveResponse,
|
|
801
993
|
stopReason: "auto_nudge",
|
|
802
994
|
systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
|
|
803
995
|
});
|
|
@@ -824,21 +1016,28 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
824
1016
|
await mkdir(stateDir, { recursive: true });
|
|
825
1017
|
const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
|
|
826
1018
|
let skillState = null;
|
|
827
|
-
const
|
|
1019
|
+
const nativeSessionId = safeString(payload.session_id ?? payload.sessionId).trim();
|
|
828
1020
|
const threadId = safeString(payload.thread_id ?? payload.threadId).trim();
|
|
829
1021
|
const turnId = safeString(payload.turn_id ?? payload.turnId).trim();
|
|
830
|
-
|
|
831
|
-
|
|
1022
|
+
let canonicalSessionId = safeString((await readUsableSessionState(cwd))?.session_id).trim();
|
|
1023
|
+
if (hookEventName === "SessionStart" && nativeSessionId) {
|
|
1024
|
+
const sessionState = await reconcileNativeSessionStart(cwd, nativeSessionId, {
|
|
832
1025
|
pid: options.sessionOwnerPid ?? resolveSessionOwnerPid(payload),
|
|
833
1026
|
});
|
|
1027
|
+
canonicalSessionId = safeString(sessionState.session_id).trim();
|
|
1028
|
+
}
|
|
1029
|
+
else if (!canonicalSessionId) {
|
|
1030
|
+
canonicalSessionId = safeString((await readUsableSessionState(cwd))?.session_id).trim();
|
|
834
1031
|
}
|
|
1032
|
+
const eventSessionId = canonicalSessionId || nativeSessionId || undefined;
|
|
1033
|
+
const sessionIdForState = canonicalSessionId || nativeSessionId;
|
|
835
1034
|
if (hookEventName === "UserPromptSubmit") {
|
|
836
1035
|
const prompt = readPromptText(payload);
|
|
837
1036
|
if (prompt) {
|
|
838
1037
|
skillState = await recordSkillActivation({
|
|
839
1038
|
stateDir,
|
|
840
1039
|
text: prompt,
|
|
841
|
-
sessionId,
|
|
1040
|
+
sessionId: sessionIdForState,
|
|
842
1041
|
threadId,
|
|
843
1042
|
turnId,
|
|
844
1043
|
});
|
|
@@ -846,8 +1045,16 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
846
1045
|
await reconcileHudForPromptSubmit(cwd).catch(() => { });
|
|
847
1046
|
}
|
|
848
1047
|
if (omxEventName) {
|
|
849
|
-
const
|
|
850
|
-
|
|
1048
|
+
const baseContext = buildBaseContext(cwd, payload, hookEventName);
|
|
1049
|
+
if (nativeSessionId) {
|
|
1050
|
+
baseContext.native_session_id = nativeSessionId;
|
|
1051
|
+
baseContext.codex_session_id = nativeSessionId;
|
|
1052
|
+
}
|
|
1053
|
+
if (canonicalSessionId) {
|
|
1054
|
+
baseContext.omx_session_id = canonicalSessionId;
|
|
1055
|
+
}
|
|
1056
|
+
const event = buildNativeHookEvent(omxEventName, baseContext, {
|
|
1057
|
+
session_id: eventSessionId,
|
|
851
1058
|
thread_id: threadId || undefined,
|
|
852
1059
|
turn_id: turnId || undefined,
|
|
853
1060
|
mode: safeString(payload.mode).trim() || undefined,
|
|
@@ -857,7 +1064,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
857
1064
|
let outputJson = null;
|
|
858
1065
|
if (hookEventName === "SessionStart" || hookEventName === "UserPromptSubmit") {
|
|
859
1066
|
const additionalContext = hookEventName === "SessionStart"
|
|
860
|
-
? await buildSessionStartContext(cwd,
|
|
1067
|
+
? await buildSessionStartContext(cwd, canonicalSessionId || nativeSessionId)
|
|
861
1068
|
: buildAdditionalContextMessage(readPromptText(payload), skillState);
|
|
862
1069
|
if (additionalContext) {
|
|
863
1070
|
outputJson = {
|
|
@@ -893,10 +1100,35 @@ async function readStdinJson() {
|
|
|
893
1100
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
894
1101
|
}
|
|
895
1102
|
const raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
896
|
-
|
|
1103
|
+
if (!raw) {
|
|
1104
|
+
return { payload: {}, parseError: null };
|
|
1105
|
+
}
|
|
1106
|
+
try {
|
|
1107
|
+
return {
|
|
1108
|
+
payload: safeObject(JSON.parse(raw)),
|
|
1109
|
+
parseError: null,
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
catch (error) {
|
|
1113
|
+
return {
|
|
1114
|
+
payload: {},
|
|
1115
|
+
parseError: error instanceof Error ? error : new Error(String(error)),
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
897
1118
|
}
|
|
898
1119
|
export async function runCodexNativeHookCli() {
|
|
899
|
-
const payload = await readStdinJson();
|
|
1120
|
+
const { payload, parseError } = await readStdinJson();
|
|
1121
|
+
if (parseError) {
|
|
1122
|
+
process.stdout.write(`${JSON.stringify({
|
|
1123
|
+
decision: "block",
|
|
1124
|
+
reason: "OMX native hook received malformed JSON input. Preserve runtime state and inspect the emitting hook payload before retrying.",
|
|
1125
|
+
hookSpecificOutput: {
|
|
1126
|
+
hookEventName: "Unknown",
|
|
1127
|
+
additionalContext: `stdin JSON parsing failed inside codex-native-hook: ${parseError.message}. Emit valid JSON from the native hook caller before retrying.`,
|
|
1128
|
+
},
|
|
1129
|
+
})}\n`);
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
900
1132
|
const result = await dispatchCodexNativeHook(payload);
|
|
901
1133
|
if (result.outputJson) {
|
|
902
1134
|
process.stdout.write(`${JSON.stringify(result.outputJson)}\n`);
|