oh-my-codex 0.15.2 → 0.16.0
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 +10 -7
- package/Cargo.toml +1 -1
- package/README.md +3 -0
- package/crates/omx-explore/Cargo.toml +3 -0
- package/crates/omx-explore/src/main.rs +517 -16
- package/dist/agents/__tests__/native-config.test.js +33 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/autoresearch/goal.d.ts +90 -0
- package/dist/autoresearch/goal.d.ts.map +1 -0
- package/dist/autoresearch/goal.js +237 -0
- package/dist/autoresearch/goal.js.map +1 -0
- package/dist/autoresearch/skill-validation.d.ts +1 -0
- package/dist/autoresearch/skill-validation.d.ts.map +1 -1
- package/dist/autoresearch/skill-validation.js +10 -3
- package/dist/autoresearch/skill-validation.js.map +1 -1
- package/dist/catalog/__tests__/generator.test.js +9 -4
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +29 -2
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/catalog/__tests__/schema.test.js +14 -3
- package/dist/catalog/__tests__/schema.test.js.map +1 -1
- package/dist/catalog/schema.js +1 -1
- package/dist/catalog/schema.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-goal.test.d.ts +2 -0
- package/dist/cli/__tests__/autoresearch-goal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/autoresearch-goal.test.js +194 -0
- package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -0
- package/dist/cli/__tests__/cleanup.test.js +82 -1
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -4
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js +122 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +25 -2
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +1 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +48 -18
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +222 -10
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +58 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-serve.test.js +27 -1
- package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
- package/dist/cli/__tests__/native-assets.test.js +26 -1
- package/dist/cli/__tests__/native-assets.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +2 -2
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/performance-goal.test.d.ts +2 -0
- package/dist/cli/__tests__/performance-goal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/performance-goal.test.js +144 -0
- package/dist/cli/__tests__/performance-goal.test.js.map +1 -0
- package/dist/cli/__tests__/question.test.js +8 -0
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +31 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +5 -4
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-prd-smoke.test.js +7 -0
- package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +59 -1
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +57 -21
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +27 -8
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +20 -10
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skill-validation.test.js +11 -11
- package/dist/cli/__tests__/setup-skill-validation.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +12 -12
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +242 -10
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.d.ts +2 -0
- package/dist/cli/__tests__/ultragoal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ultragoal.test.js +106 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -0
- package/dist/cli/__tests__/uninstall.test.js +11 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/autoresearch-goal.d.ts +3 -0
- package/dist/cli/autoresearch-goal.d.ts.map +1 -0
- package/dist/cli/autoresearch-goal.js +175 -0
- package/dist/cli/autoresearch-goal.js.map +1 -0
- package/dist/cli/cleanup.d.ts +3 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +42 -2
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +95 -3
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +10 -2
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +21 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +268 -30
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-serve.d.ts +1 -0
- package/dist/cli/mcp-serve.d.ts.map +1 -1
- package/dist/cli/mcp-serve.js +8 -0
- package/dist/cli/mcp-serve.js.map +1 -1
- package/dist/cli/native-assets.js +1 -1
- package/dist/cli/native-assets.js.map +1 -1
- package/dist/cli/performance-goal.d.ts +3 -0
- package/dist/cli/performance-goal.d.ts.map +1 -0
- package/dist/cli/performance-goal.js +186 -0
- package/dist/cli/performance-goal.js.map +1 -0
- package/dist/cli/ralph.d.ts +2 -0
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +25 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +13 -6
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts +6 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +113 -33
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +2 -1
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +3 -0
- package/dist/cli/ultragoal.d.ts.map +1 -0
- package/dist/cli/ultragoal.js +191 -0
- package/dist/cli/ultragoal.js.map +1 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +4 -2
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +39 -6
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +5 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/commit-lore-guard.d.ts +3 -0
- package/dist/config/commit-lore-guard.d.ts.map +1 -0
- package/dist/config/commit-lore-guard.js +9 -0
- package/dist/config/commit-lore-guard.js.map +1 -0
- package/dist/config/generator.d.ts +14 -4
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +166 -66
- package/dist/config/generator.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +1 -0
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
- package/dist/config/omx-first-party-mcp.js +4 -1
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/goal-workflows/__tests__/artifacts.test.d.ts +2 -0
- package/dist/goal-workflows/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/goal-workflows/__tests__/artifacts.test.js +96 -0
- package/dist/goal-workflows/__tests__/artifacts.test.js.map +1 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts +2 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts.map +1 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +54 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -0
- package/dist/goal-workflows/artifacts.d.ts +62 -0
- package/dist/goal-workflows/artifacts.d.ts.map +1 -0
- package/dist/goal-workflows/artifacts.js +132 -0
- package/dist/goal-workflows/artifacts.js.map +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +28 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.js +110 -0
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -0
- package/dist/goal-workflows/handoff.d.ts +10 -0
- package/dist/goal-workflows/handoff.d.ts.map +1 -0
- package/dist/goal-workflows/handoff.js +31 -0
- package/dist/goal-workflows/handoff.js.map +1 -0
- package/dist/goal-workflows/validation.d.ts +13 -0
- package/dist/goal-workflows/validation.d.ts.map +1 -0
- package/dist/goal-workflows/validation.js +36 -0
- package/dist/goal-workflows/validation.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +59 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.js +109 -18
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +45 -32
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +3 -3
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +2 -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 +17 -24
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +3 -3
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/task-size-detector.test.js +1 -1
- package/dist/hooks/__tests__/task-size-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-ralph-skill.test.js +3 -3
- package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.js +7 -11
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +23 -2
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +12 -13
- 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 +2 -10
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +0 -4
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.js +2 -2
- package/dist/hooks/session.js.map +1 -1
- package/dist/hooks/task-size-detector.d.ts.map +1 -1
- package/dist/hooks/task-size-detector.js +1 -0
- package/dist/hooks/task-size-detector.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +30 -14
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +29 -7
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/reconcile.d.ts +2 -1
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +12 -0
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +15 -2
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +54 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +36 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +9 -7
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +17 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +36 -2
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +26 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/base.d.ts +1 -0
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +35 -5
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/http-client.test.d.ts +2 -0
- package/dist/notifications/__tests__/http-client.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/http-client.test.js +90 -0
- package/dist/notifications/__tests__/http-client.test.js.map +1 -0
- package/dist/notifications/__tests__/notifier.test.js +22 -60
- package/dist/notifications/__tests__/notifier.test.js.map +1 -1
- package/dist/notifications/dispatcher.d.ts.map +1 -1
- package/dist/notifications/dispatcher.js +35 -60
- package/dist/notifications/dispatcher.js.map +1 -1
- package/dist/notifications/http-client.d.ts +22 -0
- package/dist/notifications/http-client.d.ts.map +1 -0
- package/dist/notifications/http-client.js +298 -0
- package/dist/notifications/http-client.js.map +1 -0
- package/dist/notifications/notifier.d.ts +3 -2
- package/dist/notifications/notifier.d.ts.map +1 -1
- package/dist/notifications/notifier.js +17 -22
- package/dist/notifications/notifier.js.map +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +63 -2
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +3 -2
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/performance-goal/artifacts.d.ts +76 -0
- package/dist/performance-goal/artifacts.d.ts.map +1 -0
- package/dist/performance-goal/artifacts.js +221 -0
- package/dist/performance-goal/artifacts.js.map +1 -0
- package/dist/pipeline/__tests__/stages.test.js +423 -14
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/stages/team-exec.d.ts +8 -4
- package/dist/pipeline/stages/team-exec.d.ts.map +1 -1
- package/dist/pipeline/stages/team-exec.js +181 -13
- package/dist/pipeline/stages/team-exec.js.map +1 -1
- package/dist/planning/__tests__/artifacts.test.js +261 -1
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/artifact-names.d.ts +13 -0
- package/dist/planning/artifact-names.d.ts.map +1 -0
- package/dist/planning/artifact-names.js +108 -0
- package/dist/planning/artifact-names.js.map +1 -0
- package/dist/planning/artifacts.d.ts +23 -1
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +171 -59
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/ralph/__tests__/persistence.test.js +21 -1
- package/dist/ralph/__tests__/persistence.test.js.map +1 -1
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +6 -4
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/ralplan/__tests__/runtime.test.js +2 -0
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +6 -0
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +1749 -88
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js +33 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
- package/dist/scripts/__tests__/run-test-files.test.js +36 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +570 -45
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts +7 -0
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +341 -15
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/hook-derived-watcher.js +2 -1
- package/dist/scripts/hook-derived-watcher.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +2 -1
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/orchestration-intent.d.ts +1 -2
- package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
- package/dist/scripts/notify-hook/orchestration-intent.js +2 -3
- package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts +0 -2
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +8 -60
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts +15 -0
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker-stop.js +224 -0
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +26 -18
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook.js +1 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-test-files.js +17 -1
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts +1 -0
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +10 -4
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +26 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +76 -0
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/operations.d.ts +3 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +8 -4
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +1 -0
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +54 -13
- package/dist/state/skill-active.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +279 -0
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.d.ts +2 -0
- package/dist/team/__tests__/approved-execution.test.d.ts.map +1 -0
- package/dist/team/__tests__/approved-execution.test.js +124 -0
- package/dist/team/__tests__/approved-execution.test.js.map +1 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +2 -4
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
- package/dist/team/__tests__/delivery-log.test.d.ts +2 -0
- package/dist/team/__tests__/delivery-log.test.d.ts.map +1 -0
- package/dist/team/__tests__/delivery-log.test.js +44 -0
- package/dist/team/__tests__/delivery-log.test.js.map +1 -0
- package/dist/team/__tests__/model-contract.test.js +40 -9
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.js +41 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -1
- package/dist/team/__tests__/role-router.test.js +4 -4
- package/dist/team/__tests__/role-router.test.js.map +1 -1
- package/dist/team/__tests__/runtime-boxed-state.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-boxed-state.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-boxed-state.test.js +39 -0
- package/dist/team/__tests__/runtime-boxed-state.test.js.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.js +24 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +563 -72
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +13 -0
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +13 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-identity.test.d.ts +2 -0
- package/dist/team/__tests__/team-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-identity.test.js +166 -0
- package/dist/team/__tests__/team-identity.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session.test.js +58 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +62 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/api-interop.d.ts +1 -0
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +163 -132
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/approved-execution.d.ts +37 -0
- package/dist/team/approved-execution.d.ts.map +1 -0
- package/dist/team/approved-execution.js +136 -0
- package/dist/team/approved-execution.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 +2 -1
- package/dist/team/delivery-log.js.map +1 -1
- package/dist/team/followup-planner.js +2 -2
- package/dist/team/followup-planner.js.map +1 -1
- package/dist/team/goal-workflow.d.ts +20 -0
- package/dist/team/goal-workflow.d.ts.map +1 -0
- package/dist/team/goal-workflow.js +57 -0
- package/dist/team/goal-workflow.js.map +1 -0
- package/dist/team/orchestrator.js +2 -2
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/repo-aware-decomposition.d.ts +3 -0
- package/dist/team/repo-aware-decomposition.d.ts.map +1 -1
- package/dist/team/repo-aware-decomposition.js +2 -0
- package/dist/team/repo-aware-decomposition.js.map +1 -1
- package/dist/team/role-router.js +5 -5
- package/dist/team/role-router.js.map +1 -1
- package/dist/team/runtime-cli.d.ts +32 -2
- package/dist/team/runtime-cli.d.ts.map +1 -1
- package/dist/team/runtime-cli.js +78 -26
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime.d.ts +7 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +383 -40
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +2 -0
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state.d.ts +9 -0
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +21 -0
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-identity.d.ts +26 -0
- package/dist/team/team-identity.d.ts.map +1 -0
- package/dist/team/team-identity.js +169 -0
- package/dist/team/team-identity.js.map +1 -0
- package/dist/team/tmux-session.d.ts +18 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +65 -3
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +4 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +28 -2
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/artifacts.test.js +93 -0
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -0
- package/dist/ultragoal/artifacts.d.ts +89 -0
- package/dist/ultragoal/artifacts.d.ts.map +1 -0
- package/dist/ultragoal/artifacts.js +233 -0
- package/dist/ultragoal/artifacts.js.map +1 -0
- package/dist/utils/__tests__/agents-model-table.test.js +3 -1
- package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +31 -1
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/agents-model-table.d.ts.map +1 -1
- package/dist/utils/agents-model-table.js +12 -1
- package/dist/utils/agents-model-table.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +23 -7
- package/dist/utils/paths.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +30 -19
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +5 -5
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +30 -5
- package/plugins/oh-my-codex/skills/ask/SKILL.md +58 -0
- package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +36 -0
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/performance-goal/SKILL.md +65 -0
- package/plugins/oh-my-codex/skills/plan/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -3
- package/plugins/oh-my-codex/skills/team/SKILL.md +6 -2
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +49 -0
- package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +9 -9
- package/prompts/api-reviewer.md +1 -1
- package/prompts/code-reviewer.md +2 -0
- package/prompts/performance-reviewer.md +1 -1
- package/prompts/quality-reviewer.md +1 -1
- package/prompts/quality-strategist.md +2 -2
- package/prompts/style-reviewer.md +1 -1
- package/prompts/test-engineer.md +1 -1
- package/skills/ai-slop-cleaner/SKILL.md +30 -5
- package/skills/ask/SKILL.md +58 -0
- package/skills/ask-claude/SKILL.md +3 -54
- package/skills/ask-gemini/SKILL.md +3 -54
- package/skills/autoresearch-goal/SKILL.md +36 -0
- package/skills/build-fix/SKILL.md +4 -139
- package/skills/deepsearch/SKILL.md +4 -32
- package/skills/ecomode/SKILL.md +4 -108
- package/skills/help/SKILL.md +4 -196
- package/skills/note/SKILL.md +4 -56
- package/skills/omx-setup/SKILL.md +2 -2
- package/skills/performance-goal/SKILL.md +65 -0
- package/skills/plan/SKILL.md +1 -1
- package/skills/ralph/SKILL.md +22 -3
- package/skills/ralph-init/SKILL.md +4 -40
- package/skills/review/SKILL.md +4 -32
- package/skills/security-review/SKILL.md +4 -294
- package/skills/swarm/SKILL.md +4 -19
- package/skills/tdd/SKILL.md +4 -100
- package/skills/team/SKILL.md +6 -2
- package/skills/trace/SKILL.md +4 -27
- package/skills/ultragoal/SKILL.md +49 -0
- package/skills/visual-ralph/SKILL.md +9 -9
- package/skills/visual-verdict/SKILL.md +4 -70
- package/skills/web-clone/SKILL.md +4 -18
- package/src/scripts/__tests__/codex-native-hook.test.ts +2923 -1030
- package/src/scripts/__tests__/hook-derived-watcher.test.ts +45 -1
- package/src/scripts/__tests__/run-test-files.test.ts +46 -0
- package/src/scripts/codex-native-hook.ts +696 -46
- package/src/scripts/codex-native-pre-post.ts +369 -16
- package/src/scripts/hook-derived-watcher.ts +2 -1
- package/src/scripts/notify-fallback-watcher.ts +2 -1
- package/src/scripts/notify-hook/orchestration-intent.ts +1 -3
- package/src/scripts/notify-hook/team-leader-nudge.ts +7 -63
- package/src/scripts/notify-hook/team-worker-posttooluse.ts +1 -1
- package/src/scripts/notify-hook/team-worker-stop.ts +246 -0
- package/src/scripts/notify-hook/team-worker.ts +23 -14
- package/src/scripts/notify-hook.ts +1 -1
- package/src/scripts/run-test-files.ts +20 -1
- package/src/scripts/sync-plugin-mirror.ts +13 -4
- package/templates/catalog-manifest.json +45 -27
- package/plugins/oh-my-codex/skills/ask-claude/SKILL.md +0 -61
- package/plugins/oh-my-codex/skills/ask-gemini/SKILL.md +0 -61
- package/plugins/oh-my-codex/skills/help/SKILL.md +0 -202
- package/plugins/oh-my-codex/skills/note/SKILL.md +0 -62
- package/plugins/oh-my-codex/skills/security-review/SKILL.md +0 -300
- package/plugins/oh-my-codex/skills/trace/SKILL.md +0 -33
- package/plugins/oh-my-codex/skills/visual-verdict/SKILL.md +0 -76
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { execFileSync } from "child_process";
|
|
2
2
|
import { closeSync, existsSync, openSync, readFileSync, readSync } from "fs";
|
|
3
3
|
import { mkdir, readFile, readdir, writeFile } from "fs/promises";
|
|
4
|
-
import { join, relative, resolve } from "path";
|
|
4
|
+
import { extname, join, relative, resolve } from "path";
|
|
5
5
|
import { pathToFileURL } from "url";
|
|
6
|
-
import { readModeState, readModeStateForSession, updateModeState } from "../modes/base.js";
|
|
7
|
-
import { listActiveSkills, readVisibleSkillActiveState, } from "../state/skill-active.js";
|
|
6
|
+
import { readModeState, readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
|
|
7
|
+
import { extractSessionIdFromInitializedStatePath, listActiveSkills, readVisibleSkillActiveState, } from "../state/skill-active.js";
|
|
8
8
|
import { readSubagentSessionSummary, recordSubagentTurnForSession, } from "../subagents/tracker.js";
|
|
9
9
|
import { resolveCanonicalTeamStateRoot, resolveWorkerNotifyTeamStateRootPath } from "../team/state-root.js";
|
|
10
10
|
import { appendToLog, isSessionStateUsable, readSessionState, readUsableSessionState, reconcileNativeSessionStart, } from "../hooks/session.js";
|
|
@@ -14,14 +14,15 @@ import { findGitLayout } from "../utils/git-layout.js";
|
|
|
14
14
|
import { getStateFilePath, getStatePath } from "../mcp/state-paths.js";
|
|
15
15
|
import { detectKeywords, detectPrimaryKeyword, recordSkillActivation, } from "../hooks/keyword-detector.js";
|
|
16
16
|
import { detectNativeStopStallPattern, loadAutoNudgeConfig, normalizeAutoNudgeSignatureText, resolveEffectiveAutoNudgeResponse, } from "./notify-hook/auto-nudge.js";
|
|
17
|
-
import { buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, } from "./codex-native-pre-post.js";
|
|
17
|
+
import { SLOPPY_FALLBACK_GROUNDING_PATTERNS, SLOPPY_FALLBACK_IMPLEMENTATION_CONTEXT_PATTERNS, SLOPPY_FALLBACK_PHRASE_PATTERNS, buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, hasAnyPattern, } from "./codex-native-pre-post.js";
|
|
18
18
|
import { handleTeamWorkerPostToolUseSuccess } from "./notify-hook/team-worker-posttooluse.js";
|
|
19
|
+
import { maybeNudgeLeaderForAllowedWorkerStop } from "./notify-hook/team-worker-stop.js";
|
|
19
20
|
import { resolveCodexExecutionSurface, } from "./codex-execution-surface.js";
|
|
20
21
|
import { buildNativeHookEvent, } from "../hooks/extensibility/events.js";
|
|
21
|
-
import {
|
|
22
|
+
import { dispatchHookEventRuntime } from "../hooks/extensibility/runtime.js";
|
|
22
23
|
import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
|
|
23
24
|
import { onSessionStart as buildWikiSessionStartContext } from "../wiki/lifecycle.js";
|
|
24
|
-
import { readAutoresearchCompletionStatus,
|
|
25
|
+
import { readAutoresearchCompletionStatus, readAutoresearchModeStateForActiveDecision } from "../autoresearch/skill-validation.js";
|
|
25
26
|
import { readRunState } from "../runtime/run-state.js";
|
|
26
27
|
import { getRunContinuationSnapshot, shouldContinueRun } from "../runtime/run-loop.js";
|
|
27
28
|
import { triagePrompt } from "../hooks/triage-heuristic.js";
|
|
@@ -30,9 +31,10 @@ import { readTriageState, writeTriageState, shouldSuppressFollowup, promptSignat
|
|
|
30
31
|
import { isPendingDeepInterviewQuestionEnforcement, reconcileDeepInterviewQuestionEnforcementFromAnsweredRecords, } from "../question/deep-interview.js";
|
|
31
32
|
import { buildDocumentRefreshAdvisoryOutput, evaluateFinalHandoffDocumentRefresh, isFinalHandoffDocumentRefreshCandidate, } from "../document-refresh/enforcer.js";
|
|
32
33
|
import { buildExecFollowupStopOutput } from "../exec/followup.js";
|
|
33
|
-
const TERMINAL_MODE_PHASES = new Set(["complete", "failed", "cancelled"]);
|
|
34
|
+
const TERMINAL_MODE_PHASES = new Set(["complete", "completed", "failed", "cancelled"]);
|
|
34
35
|
const SKILL_STOP_BLOCKERS = new Set(["ralplan"]);
|
|
35
|
-
const
|
|
36
|
+
const TEAM_STOP_BLOCKING_TASK_STATUSES = new Set(["pending", "in_progress", "blocked"]);
|
|
37
|
+
const TEAM_WORKER_TERMINAL_RUN_STATES = new Set(["done", "complete", "completed", "failed", "stopped", "cancelled"]);
|
|
36
38
|
const NATIVE_STOP_STATE_FILE = "native-stop-state.json";
|
|
37
39
|
const STABLE_FINAL_RECOMMENDATION_PATTERNS = [
|
|
38
40
|
/^\s*(?:launch|release|ship)-?ready\s*:\s*(?:yes|no)\b[^\n\r]*/im,
|
|
@@ -159,6 +161,20 @@ async function nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonica
|
|
|
159
161
|
return true;
|
|
160
162
|
return summary.allThreadIds.includes(parentThreadId);
|
|
161
163
|
}
|
|
164
|
+
async function isNativeSubagentHook(cwd, canonicalSessionId, nativeSessionId, threadId) {
|
|
165
|
+
const sessionId = canonicalSessionId.trim();
|
|
166
|
+
if (!sessionId)
|
|
167
|
+
return false;
|
|
168
|
+
const summary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
|
|
169
|
+
if (!summary)
|
|
170
|
+
return false;
|
|
171
|
+
const candidateIds = [nativeSessionId, threadId]
|
|
172
|
+
.map((value) => value.trim())
|
|
173
|
+
.filter(Boolean);
|
|
174
|
+
if (candidateIds.length === 0)
|
|
175
|
+
return false;
|
|
176
|
+
return candidateIds.some((id) => summary.allSubagentThreadIds.includes(id));
|
|
177
|
+
}
|
|
162
178
|
async function recordIgnoredNativeSubagentSessionStart(cwd, canonicalSessionId, childSessionId, metadata, transcriptPath) {
|
|
163
179
|
await appendToLog(cwd, {
|
|
164
180
|
event: "subagent_session_start_ignored",
|
|
@@ -302,7 +318,7 @@ async function readActiveAutoresearchState(cwd, sessionId) {
|
|
|
302
318
|
const normalizedSessionId = sessionId?.trim() || undefined;
|
|
303
319
|
if (!normalizedSessionId)
|
|
304
320
|
return null;
|
|
305
|
-
const state = await
|
|
321
|
+
const state = await readAutoresearchModeStateForActiveDecision(cwd, normalizedSessionId);
|
|
306
322
|
if (state?.active !== true)
|
|
307
323
|
return null;
|
|
308
324
|
if (!isNonTerminalPhase(state.current_phase ?? state.currentPhase ?? 'executing'))
|
|
@@ -312,6 +328,38 @@ async function readActiveAutoresearchState(cwd, sessionId) {
|
|
|
312
328
|
function isRalphStartingPhase(state) {
|
|
313
329
|
return safeString(state.current_phase ?? state.currentPhase).trim().toLowerCase() === "starting";
|
|
314
330
|
}
|
|
331
|
+
function hasValue(values, value) {
|
|
332
|
+
return value !== "" && values.some((candidate) => candidate === value);
|
|
333
|
+
}
|
|
334
|
+
function activeRalphStateMatchesStopOwner(state, context) {
|
|
335
|
+
const ownerOmxSessionId = safeString(state.owner_omx_session_id).trim();
|
|
336
|
+
if (ownerOmxSessionId && ownerOmxSessionId !== context.sessionId) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
const stateSessionId = safeString(state.session_id).trim();
|
|
340
|
+
if (!ownerOmxSessionId && stateSessionId && stateSessionId !== context.sessionId) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
const codexOwnerSessionId = safeString(state.owner_codex_session_id).trim();
|
|
344
|
+
if (codexOwnerSessionId) {
|
|
345
|
+
const stopCodexSessionIds = [
|
|
346
|
+
context.payloadSessionId,
|
|
347
|
+
context.currentNativeSessionId,
|
|
348
|
+
context.sessionId,
|
|
349
|
+
].filter(Boolean);
|
|
350
|
+
if (!hasValue(stopCodexSessionIds, codexOwnerSessionId))
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
const stateThreadId = safeString(state.owner_codex_thread_id ?? state.thread_id).trim();
|
|
354
|
+
if (stateThreadId && context.threadId && stateThreadId !== context.threadId) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
const statePaneId = safeString(state.tmux_pane_id).trim();
|
|
358
|
+
if (statePaneId && context.tmuxPaneId && statePaneId !== context.tmuxPaneId) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
315
363
|
function shouldHonorCanonicalTerminalRunState(runState, mode) {
|
|
316
364
|
if (!runState)
|
|
317
365
|
return false;
|
|
@@ -334,13 +382,26 @@ async function isVisibleRalphActiveForSession(cwd, sessionId) {
|
|
|
334
382
|
return listActiveSkills(canonicalState).some((entry) => (entry.skill === "ralph"
|
|
335
383
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, "")));
|
|
336
384
|
}
|
|
337
|
-
async function
|
|
385
|
+
async function hasConsistentRalphSkillActivation(cwd, sessionId) {
|
|
386
|
+
const canonicalState = await readVisibleSkillActiveState(cwd, sessionId);
|
|
387
|
+
if (!canonicalState)
|
|
388
|
+
return true;
|
|
389
|
+
const initializedMode = safeString(canonicalState.initialized_mode).trim();
|
|
390
|
+
if (initializedMode && initializedMode !== "ralph")
|
|
391
|
+
return true;
|
|
392
|
+
const initializedPathSessionId = extractSessionIdFromInitializedStatePath(canonicalState.initialized_state_path);
|
|
393
|
+
if (initializedPathSessionId && initializedPathSessionId !== sessionId)
|
|
394
|
+
return false;
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
async function readActiveRalphState(stateDir, preferredSessionId, ownerContext) {
|
|
338
398
|
const cwd = resolve(stateDir, "..", "..");
|
|
339
399
|
const [rawSessionInfo, usableSessionInfo] = await Promise.all([
|
|
340
400
|
readSessionState(cwd),
|
|
341
401
|
readUsableSessionState(cwd),
|
|
342
402
|
]);
|
|
343
403
|
const currentOmxSessionId = safeString(usableSessionInfo?.session_id).trim();
|
|
404
|
+
const currentNativeSessionId = safeString(usableSessionInfo?.native_session_id).trim();
|
|
344
405
|
const staleCurrentSessionId = rawSessionInfo && !isSessionStateUsable(rawSessionInfo, cwd)
|
|
345
406
|
? safeString(rawSessionInfo.session_id).trim()
|
|
346
407
|
: "";
|
|
@@ -365,7 +426,16 @@ async function readActiveRalphState(stateDir, preferredSessionId) {
|
|
|
365
426
|
&& !(await isVisibleRalphActiveForSession(cwd, sessionId))) {
|
|
366
427
|
continue;
|
|
367
428
|
}
|
|
368
|
-
if (sessionScoped?.active === true
|
|
429
|
+
if (sessionScoped?.active === true
|
|
430
|
+
&& shouldContinueRun(sessionScoped)
|
|
431
|
+
&& activeRalphStateMatchesStopOwner(sessionScoped, {
|
|
432
|
+
sessionId,
|
|
433
|
+
payloadSessionId: safeString(ownerContext?.payloadSessionId).trim(),
|
|
434
|
+
threadId: safeString(ownerContext?.threadId).trim(),
|
|
435
|
+
currentNativeSessionId,
|
|
436
|
+
tmuxPaneId: safeString(ownerContext?.tmuxPaneId).trim(),
|
|
437
|
+
})
|
|
438
|
+
&& await hasConsistentRalphSkillActivation(cwd, sessionId)) {
|
|
369
439
|
return { state: sessionScoped, path: sessionScopedPath };
|
|
370
440
|
}
|
|
371
441
|
}
|
|
@@ -480,6 +550,182 @@ function tryReadGitValue(cwd, args) {
|
|
|
480
550
|
return null;
|
|
481
551
|
}
|
|
482
552
|
}
|
|
553
|
+
const SOURCE_DIFF_EXTENSIONS = new Set([
|
|
554
|
+
".c",
|
|
555
|
+
".cc",
|
|
556
|
+
".cjs",
|
|
557
|
+
".cpp",
|
|
558
|
+
".cs",
|
|
559
|
+
".cts",
|
|
560
|
+
".go",
|
|
561
|
+
".h",
|
|
562
|
+
".hpp",
|
|
563
|
+
".java",
|
|
564
|
+
".js",
|
|
565
|
+
".jsx",
|
|
566
|
+
".kt",
|
|
567
|
+
".mjs",
|
|
568
|
+
".mts",
|
|
569
|
+
".php",
|
|
570
|
+
".py",
|
|
571
|
+
".rb",
|
|
572
|
+
".rs",
|
|
573
|
+
".sh",
|
|
574
|
+
".swift",
|
|
575
|
+
".ts",
|
|
576
|
+
".tsx",
|
|
577
|
+
]);
|
|
578
|
+
function gitOutput(cwd, args) {
|
|
579
|
+
try {
|
|
580
|
+
return execFileSync("git", args, {
|
|
581
|
+
cwd,
|
|
582
|
+
encoding: "utf-8",
|
|
583
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
584
|
+
windowsHide: true,
|
|
585
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
return "";
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function normalizeGitPath(path) {
|
|
593
|
+
return path.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
594
|
+
}
|
|
595
|
+
function isDiffAuditableSourcePath(path) {
|
|
596
|
+
const normalized = normalizeGitPath(path).toLowerCase();
|
|
597
|
+
if (!normalized || normalized.startsWith(".git/") || normalized.startsWith(".omx/"))
|
|
598
|
+
return false;
|
|
599
|
+
if (/(^|\/)(?:docs?|documentation|changelog|changeset|\.github)(?:\/|$)/i.test(normalized))
|
|
600
|
+
return false;
|
|
601
|
+
if (/(^|\/)(?:__tests__|__test__|test|tests|spec|specs|fixtures?|mocks?)(?:\/|$)/i.test(normalized))
|
|
602
|
+
return false;
|
|
603
|
+
if (/(?:^|\/)[^\/]+\.(?:test|spec)\.[^.\/]+$/i.test(normalized))
|
|
604
|
+
return false;
|
|
605
|
+
if (/(?:^|\/)(?:readme|changelog|changes|license|notice)(?:\.[^\/]*)?$/i.test(normalized))
|
|
606
|
+
return false;
|
|
607
|
+
if (/\.(?:md|mdx|markdown|txt|rst|adoc|ya?ml|json|lock)$/i.test(normalized))
|
|
608
|
+
return false;
|
|
609
|
+
return SOURCE_DIFF_EXTENSIONS.has(extname(normalized));
|
|
610
|
+
}
|
|
611
|
+
function isDiffHeaderLine(line) {
|
|
612
|
+
return line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@") || line.startsWith("diff --git ");
|
|
613
|
+
}
|
|
614
|
+
function isSuspiciousSloppyFallbackAddedLine(line, nearbyContext) {
|
|
615
|
+
const trimmed = line.trim();
|
|
616
|
+
if (!trimmed)
|
|
617
|
+
return false;
|
|
618
|
+
if (!hasAnyPattern(trimmed, SLOPPY_FALLBACK_PHRASE_PATTERNS))
|
|
619
|
+
return false;
|
|
620
|
+
if (!hasAnyPattern(trimmed, SLOPPY_FALLBACK_IMPLEMENTATION_CONTEXT_PATTERNS))
|
|
621
|
+
return false;
|
|
622
|
+
if (hasAnyPattern(nearbyContext, SLOPPY_FALLBACK_GROUNDING_PATTERNS))
|
|
623
|
+
return false;
|
|
624
|
+
if (/compatib(?:le|ility)|fail-?safe|tested|regression|coverage|because|issue|PR\s*#?\d|#\d/i.test(nearbyContext))
|
|
625
|
+
return false;
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
function collectFindingsFromCandidateLines(path, lines, source) {
|
|
629
|
+
if (!path || !isDiffAuditableSourcePath(path))
|
|
630
|
+
return [];
|
|
631
|
+
const findings = [];
|
|
632
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
633
|
+
const candidate = lines[index];
|
|
634
|
+
if (!candidate?.added)
|
|
635
|
+
continue;
|
|
636
|
+
const nearbyContext = lines
|
|
637
|
+
.slice(Math.max(0, index - 2), Math.min(lines.length, index + 3))
|
|
638
|
+
.map((line) => line.text)
|
|
639
|
+
.join("\n");
|
|
640
|
+
if (isSuspiciousSloppyFallbackAddedLine(candidate.text, nearbyContext)) {
|
|
641
|
+
findings.push({ path, line: candidate.text.trim(), source });
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return findings;
|
|
645
|
+
}
|
|
646
|
+
function collectSloppyFallbackFindingsFromPatch(patch, source) {
|
|
647
|
+
const findings = [];
|
|
648
|
+
let currentPath = "";
|
|
649
|
+
let hunkLines = [];
|
|
650
|
+
const flushHunk = () => {
|
|
651
|
+
findings.push(...collectFindingsFromCandidateLines(currentPath, hunkLines, source));
|
|
652
|
+
hunkLines = [];
|
|
653
|
+
};
|
|
654
|
+
for (const rawLine of patch.split(/\r?\n/)) {
|
|
655
|
+
const fileMatch = rawLine.match(/^diff --git a\/(.*?) b\/(.*)$/);
|
|
656
|
+
if (fileMatch) {
|
|
657
|
+
flushHunk();
|
|
658
|
+
currentPath = normalizeGitPath(fileMatch[2] || fileMatch[1] || "");
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
const renameMatch = rawLine.match(/^\+\+\+ b\/(.*)$/);
|
|
662
|
+
if (renameMatch) {
|
|
663
|
+
currentPath = normalizeGitPath(renameMatch[1] || currentPath);
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
if (rawLine.startsWith("@@")) {
|
|
667
|
+
flushHunk();
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
if (!currentPath || !isDiffAuditableSourcePath(currentPath) || isDiffHeaderLine(rawLine))
|
|
671
|
+
continue;
|
|
672
|
+
if (rawLine.startsWith("+")) {
|
|
673
|
+
hunkLines.push({ text: rawLine.slice(1), added: true });
|
|
674
|
+
}
|
|
675
|
+
else if (rawLine.startsWith(" ")) {
|
|
676
|
+
hunkLines.push({ text: rawLine.slice(1), added: false });
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
flushHunk();
|
|
680
|
+
return findings;
|
|
681
|
+
}
|
|
682
|
+
function collectSloppyFallbackFindingsFromUntracked(cwd) {
|
|
683
|
+
const output = gitOutput(cwd, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
684
|
+
if (!output)
|
|
685
|
+
return [];
|
|
686
|
+
const findings = [];
|
|
687
|
+
for (const rawPath of output.split("\0")) {
|
|
688
|
+
const path = normalizeGitPath(rawPath.trim());
|
|
689
|
+
if (!path || !isDiffAuditableSourcePath(path))
|
|
690
|
+
continue;
|
|
691
|
+
let content = "";
|
|
692
|
+
try {
|
|
693
|
+
content = readFileSync(join(cwd, path), "utf-8");
|
|
694
|
+
}
|
|
695
|
+
catch {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
findings.push(...collectFindingsFromCandidateLines(path, content.split(/\r?\n/).map((text) => ({ text, added: true })), "untracked"));
|
|
699
|
+
}
|
|
700
|
+
return findings;
|
|
701
|
+
}
|
|
702
|
+
function findSloppyFallbackDiffFindings(cwd) {
|
|
703
|
+
const layout = findGitLayout(cwd);
|
|
704
|
+
if (!layout)
|
|
705
|
+
return [];
|
|
706
|
+
const auditRoot = layout.worktreeRoot;
|
|
707
|
+
return [
|
|
708
|
+
...collectSloppyFallbackFindingsFromPatch(gitOutput(auditRoot, ["diff", "--cached", "--no-ext-diff", "--unified=3"]), "staged"),
|
|
709
|
+
...collectSloppyFallbackFindingsFromPatch(gitOutput(auditRoot, ["diff", "--no-ext-diff", "--unified=3"]), "unstaged"),
|
|
710
|
+
...collectSloppyFallbackFindingsFromUntracked(auditRoot),
|
|
711
|
+
];
|
|
712
|
+
}
|
|
713
|
+
function buildSloppyFallbackDiffStopOutput(findings) {
|
|
714
|
+
if (findings.length === 0)
|
|
715
|
+
return null;
|
|
716
|
+
const preview = findings
|
|
717
|
+
.slice(0, 3)
|
|
718
|
+
.map((finding) => `${finding.path} (${finding.source}): ${finding.line}`)
|
|
719
|
+
.join("; ");
|
|
720
|
+
const systemMessage = `Sloppy fallback/workaround diff audit detected ungrounded fallback code in added source lines: ${preview}. `
|
|
721
|
+
+ "Continue by replacing the bypass/workaround with a grounded design, or add explicit compatibility/fail-safe/tested/issue rationale near the code if the fallback is intentional.";
|
|
722
|
+
return {
|
|
723
|
+
decision: "block",
|
|
724
|
+
reason: systemMessage,
|
|
725
|
+
stopReason: "sloppy_fallback_diff_audit",
|
|
726
|
+
systemMessage,
|
|
727
|
+
};
|
|
728
|
+
}
|
|
483
729
|
function localExcludeAlreadyIgnoresOmx(cwd) {
|
|
484
730
|
const layout = findGitLayout(cwd);
|
|
485
731
|
if (!layout)
|
|
@@ -803,6 +1049,9 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
803
1049
|
const ultraworkPromptActivationNote = skillState?.initialized_mode === "ultrawork"
|
|
804
1050
|
? "Ultrawork protocol: ground the task before editing, define pass/fail acceptance criteria, keep shared-file work local, and use direct-tool plus background evidence lanes only for truly independent work. Direct ultrawork provides lightweight verification only; Ralph owns persistence and the full verified-completion promise."
|
|
805
1051
|
: null;
|
|
1052
|
+
const ultragoalPromptActivationNote = match.skill === "ultragoal"
|
|
1053
|
+
? "Ultragoal protocol: use `omx ultragoal create-goals` / `complete-goals` / `checkpoint` for `.omx/ultragoal` artifacts, then use Codex goal model tools only from the active agent handoff (`get_goal`, `create_goal`, `update_goal`) and never overwrite a different active Codex goal."
|
|
1054
|
+
: null;
|
|
806
1055
|
const combinedTransitionMessage = (() => {
|
|
807
1056
|
if (!skillState?.transition_message)
|
|
808
1057
|
return null;
|
|
@@ -830,6 +1079,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
830
1079
|
? `planning preserved over simultaneous execution follow-up; deferred skills: ${deferredSkills.join(", ")}.`
|
|
831
1080
|
: null,
|
|
832
1081
|
promptPriorityMessage,
|
|
1082
|
+
ultragoalPromptActivationNote,
|
|
833
1083
|
skillState.initialized_mode && skillState.initialized_state_path
|
|
834
1084
|
? `skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`
|
|
835
1085
|
: null,
|
|
@@ -854,6 +1104,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
854
1104
|
initializedStateMessage,
|
|
855
1105
|
deepInterviewPromptActivationNote,
|
|
856
1106
|
ultraworkPromptActivationNote,
|
|
1107
|
+
ultragoalPromptActivationNote,
|
|
857
1108
|
buildTeamRuntimeInstruction(cwd, payload),
|
|
858
1109
|
buildTeamHelpInstruction(cwd, payload),
|
|
859
1110
|
"Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
|
|
@@ -870,11 +1121,12 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
870
1121
|
`skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`,
|
|
871
1122
|
deepInterviewPromptActivationNote,
|
|
872
1123
|
ultraworkPromptActivationNote,
|
|
1124
|
+
ultragoalPromptActivationNote,
|
|
873
1125
|
ralphPromptActivationNote,
|
|
874
1126
|
"Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
|
|
875
1127
|
].join(" ");
|
|
876
1128
|
}
|
|
877
|
-
return [detectedKeywordMessage, promptPriorityMessage, "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules."].filter(Boolean).join(" ");
|
|
1129
|
+
return [detectedKeywordMessage, promptPriorityMessage, ultragoalPromptActivationNote, "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules."].filter(Boolean).join(" ");
|
|
878
1130
|
}
|
|
879
1131
|
function parseTeamWorkerEnv(rawValue) {
|
|
880
1132
|
const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(rawValue.trim());
|
|
@@ -886,20 +1138,51 @@ function parseTeamWorkerEnv(rawValue) {
|
|
|
886
1138
|
};
|
|
887
1139
|
}
|
|
888
1140
|
async function resolveTeamStateDirForWorkerContext(cwd, workerContext) {
|
|
889
|
-
|
|
1141
|
+
const resolved = await resolveWorkerNotifyTeamStateRootPath(cwd, workerContext, process.env).catch(() => null);
|
|
1142
|
+
if (resolved)
|
|
1143
|
+
return resolved;
|
|
1144
|
+
const explicit = safeString(process.env.OMX_TEAM_STATE_ROOT).trim();
|
|
1145
|
+
if (explicit) {
|
|
1146
|
+
const candidate = resolve(cwd, explicit);
|
|
1147
|
+
const workerRoot = join(candidate, "team", workerContext.teamName, "workers", workerContext.workerName);
|
|
1148
|
+
if (existsSync(workerRoot))
|
|
1149
|
+
return candidate;
|
|
1150
|
+
return candidate;
|
|
1151
|
+
}
|
|
1152
|
+
return null;
|
|
890
1153
|
}
|
|
891
|
-
async function
|
|
892
|
-
const workerContext = parseTeamWorkerEnv(safeString(process.env.
|
|
1154
|
+
async function resolveTeamWorkerStopDecision(cwd) {
|
|
1155
|
+
const workerContext = parseTeamWorkerEnv(safeString(process.env.OMX_TEAM_INTERNAL_WORKER))
|
|
1156
|
+
|| parseTeamWorkerEnv(safeString(process.env.OMX_TEAM_WORKER));
|
|
893
1157
|
if (!workerContext)
|
|
894
|
-
return
|
|
1158
|
+
return { kind: "unresolved", reason: "missing_worker_context" };
|
|
1159
|
+
const blockWorkerStop = (reasonCode, detail, stateDirForDecision = join(cwd, ".omx", "state")) => ({
|
|
1160
|
+
kind: "blocked",
|
|
1161
|
+
stateDir: stateDirForDecision,
|
|
1162
|
+
workerContext,
|
|
1163
|
+
allowRepeatDuringStopHook: false,
|
|
1164
|
+
output: {
|
|
1165
|
+
decision: "block",
|
|
1166
|
+
reason: `OMX team worker ${workerContext.workerName} Stop cannot be allowed for ${reasonCode}: ${detail}. ` +
|
|
1167
|
+
"Continue the assigned task, repair worker state, or report a concrete blocker before stopping.",
|
|
1168
|
+
stopReason: `team_worker_${workerContext.workerName}_${reasonCode}`,
|
|
1169
|
+
systemMessage: `OMX team worker ${workerContext.workerName} Stop lacks completed task evidence (${reasonCode}).`,
|
|
1170
|
+
},
|
|
1171
|
+
});
|
|
895
1172
|
const stateDir = await resolveTeamStateDirForWorkerContext(cwd, workerContext);
|
|
896
|
-
if (!stateDir)
|
|
897
|
-
return
|
|
1173
|
+
if (!stateDir) {
|
|
1174
|
+
return blockWorkerStop("missing_state_dir", "team state root could not be resolved");
|
|
1175
|
+
}
|
|
898
1176
|
const workerRoot = join(stateDir, "team", workerContext.teamName, "workers", workerContext.workerName);
|
|
899
1177
|
const [identity, status] = await Promise.all([
|
|
900
1178
|
readJsonIfExists(join(workerRoot, "identity.json")),
|
|
901
1179
|
readJsonIfExists(join(workerRoot, "status.json")),
|
|
902
1180
|
]);
|
|
1181
|
+
const workerRunState = safeString(status?.state).trim().toLowerCase();
|
|
1182
|
+
const workerRunStateIsTerminal = TEAM_WORKER_TERMINAL_RUN_STATES.has(workerRunState);
|
|
1183
|
+
if (!identity && !status && !existsSync(workerRoot)) {
|
|
1184
|
+
return blockWorkerStop("missing_worker_state", "worker identity/status state is missing", stateDir);
|
|
1185
|
+
}
|
|
903
1186
|
const candidateTaskIds = new Set();
|
|
904
1187
|
const currentTaskId = safeString(status?.current_task_id).trim();
|
|
905
1188
|
if (currentTaskId)
|
|
@@ -910,22 +1193,57 @@ async function buildTeamWorkerStopOutput(cwd) {
|
|
|
910
1193
|
if (normalized)
|
|
911
1194
|
candidateTaskIds.add(normalized);
|
|
912
1195
|
}
|
|
1196
|
+
const tasksDir = join(stateDir, "team", workerContext.teamName, "tasks");
|
|
1197
|
+
if (existsSync(tasksDir)) {
|
|
1198
|
+
const taskFiles = await readdir(tasksDir).catch(() => []);
|
|
1199
|
+
for (const entry of taskFiles) {
|
|
1200
|
+
if (!/^task-\d+\.json$/.test(entry))
|
|
1201
|
+
continue;
|
|
1202
|
+
const task = await readJsonIfExists(join(tasksDir, entry));
|
|
1203
|
+
const taskOwner = safeString(task?.owner).trim();
|
|
1204
|
+
const taskClaimOwner = safeString(safeObject(task?.claim).owner).trim();
|
|
1205
|
+
if (taskOwner !== workerContext.workerName && taskClaimOwner !== workerContext.workerName)
|
|
1206
|
+
continue;
|
|
1207
|
+
const idFromFile = /^task-(\d+)\.json$/.exec(entry)?.[1] ?? "";
|
|
1208
|
+
const taskId = safeString(task?.id).trim() || idFromFile;
|
|
1209
|
+
if (taskId)
|
|
1210
|
+
candidateTaskIds.add(taskId);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
if (candidateTaskIds.size === 0) {
|
|
1214
|
+
return blockWorkerStop("missing_task_assignment", "no current_task_id or assigned_tasks are recorded", stateDir);
|
|
1215
|
+
}
|
|
1216
|
+
let completedTaskCount = 0;
|
|
913
1217
|
for (const taskId of candidateTaskIds) {
|
|
914
1218
|
const task = await readJsonIfExists(join(stateDir, "team", workerContext.teamName, "tasks", `task-${taskId}.json`));
|
|
915
1219
|
const statusValue = safeString(task?.status).trim().toLowerCase();
|
|
916
|
-
if (!statusValue
|
|
1220
|
+
if (!statusValue) {
|
|
1221
|
+
return blockWorkerStop(`missing_task_state_${taskId}`, `task ${taskId} has no readable status`, stateDir);
|
|
1222
|
+
}
|
|
1223
|
+
if (statusValue === "completed") {
|
|
1224
|
+
completedTaskCount += 1;
|
|
917
1225
|
continue;
|
|
1226
|
+
}
|
|
1227
|
+
if (!TEAM_STOP_BLOCKING_TASK_STATUSES.has(statusValue)) {
|
|
1228
|
+
return blockWorkerStop(`non_completed_task_${taskId}_${statusValue}`, `task ${taskId} is ${statusValue}, not completed`, stateDir);
|
|
1229
|
+
}
|
|
918
1230
|
return {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1231
|
+
kind: "blocked",
|
|
1232
|
+
stateDir,
|
|
1233
|
+
workerContext,
|
|
1234
|
+
allowRepeatDuringStopHook: !workerRunStateIsTerminal,
|
|
1235
|
+
output: {
|
|
1236
|
+
decision: "block",
|
|
1237
|
+
reason: `OMX team worker ${workerContext.workerName} is still assigned non-terminal task ${taskId} (${statusValue}); continue the current assigned task or report a concrete blocker before stopping.`,
|
|
1238
|
+
stopReason: `team_worker_${workerContext.workerName}_${taskId}_${statusValue}`,
|
|
1239
|
+
systemMessage: `OMX team worker ${workerContext.workerName} is still assigned task ${taskId} (${statusValue}).`,
|
|
1240
|
+
},
|
|
923
1241
|
};
|
|
924
1242
|
}
|
|
925
|
-
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
return
|
|
1243
|
+
if (completedTaskCount === candidateTaskIds.size) {
|
|
1244
|
+
return { kind: "allowed", stateDir, workerContext };
|
|
1245
|
+
}
|
|
1246
|
+
return blockWorkerStop("missing_completed_task_evidence", "no referenced worker task is completed", stateDir);
|
|
929
1247
|
}
|
|
930
1248
|
function isStopExempt(payload) {
|
|
931
1249
|
const candidates = [
|
|
@@ -944,9 +1262,7 @@ function isStopExempt(payload) {
|
|
|
944
1262
|
|| value.includes("limit"));
|
|
945
1263
|
}
|
|
946
1264
|
async function buildModeBasedStopOutput(mode, cwd, sessionId) {
|
|
947
|
-
const state = sessionId
|
|
948
|
-
? await readModeStateForSession(mode, sessionId, cwd)
|
|
949
|
-
: await readModeState(mode, cwd);
|
|
1265
|
+
const state = await readModeStateForActiveDecision(mode, sessionId?.trim() || undefined, cwd);
|
|
950
1266
|
if (!state || !shouldContinueRun(state))
|
|
951
1267
|
return null;
|
|
952
1268
|
const phase = formatPhase(state.current_phase);
|
|
@@ -957,6 +1273,76 @@ async function buildModeBasedStopOutput(mode, cwd, sessionId) {
|
|
|
957
1273
|
systemMessage: `OMX ${mode} is still active (phase: ${phase}).`,
|
|
958
1274
|
};
|
|
959
1275
|
}
|
|
1276
|
+
function looksLikeGoalCompletionPrompt(text) {
|
|
1277
|
+
return /\b(?:complete|checkpoint|finish|close|mark)\b.{0,80}\b(?:goal|ultragoal|performance-goal|autoresearch-goal)\b/i.test(text)
|
|
1278
|
+
|| /\bupdate_goal\s*\(/i.test(text)
|
|
1279
|
+
|| /\bomx\s+(?:ultragoal|performance-goal|autoresearch-goal)\s+(?:checkpoint|complete)\b/i.test(text);
|
|
1280
|
+
}
|
|
1281
|
+
async function findActiveGoalWorkflowReconciliationRequirement(cwd) {
|
|
1282
|
+
const ultragoal = await readJsonIfExists(join(cwd, ".omx", "ultragoal", "goals.json"));
|
|
1283
|
+
const ultragoals = Array.isArray(ultragoal?.goals) ? ultragoal.goals.map(safeObject) : [];
|
|
1284
|
+
const activeUltragoal = ultragoals.find((goal) => safeString(goal.status) === "in_progress" || safeString(goal.id) === safeString(ultragoal?.activeGoalId));
|
|
1285
|
+
if (activeUltragoal) {
|
|
1286
|
+
return {
|
|
1287
|
+
workflow: "ultragoal",
|
|
1288
|
+
command: `omx ultragoal checkpoint --goal-id ${safeString(activeUltragoal.id) || "<goal-id>"} --status complete --codex-goal-json '<get_goal JSON or path>' --evidence '<evidence>'`,
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const performanceRoot = join(cwd, ".omx", "goals", "performance");
|
|
1292
|
+
for (const entry of await readdir(performanceRoot, { withFileTypes: true }).catch(() => [])) {
|
|
1293
|
+
if (!entry.isDirectory())
|
|
1294
|
+
continue;
|
|
1295
|
+
const state = await readJsonIfExists(join(performanceRoot, entry.name, "state.json"));
|
|
1296
|
+
const status = safeString(state?.status);
|
|
1297
|
+
if (state?.workflow === "performance-goal" && status && status !== "complete") {
|
|
1298
|
+
return {
|
|
1299
|
+
workflow: "performance-goal",
|
|
1300
|
+
command: `omx performance-goal complete --slug ${safeString(state.slug) || entry.name} --codex-goal-json '<get_goal JSON or path>' --evidence '<evidence>'`,
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
const autoresearchRoot = join(cwd, ".omx", "goals", "autoresearch");
|
|
1305
|
+
for (const entry of await readdir(autoresearchRoot, { withFileTypes: true }).catch(() => [])) {
|
|
1306
|
+
if (!entry.isDirectory())
|
|
1307
|
+
continue;
|
|
1308
|
+
const mission = await readJsonIfExists(join(autoresearchRoot, entry.name, "mission.json"));
|
|
1309
|
+
const status = safeString(mission?.status);
|
|
1310
|
+
if (mission?.workflow === "autoresearch-goal" && status && status !== "complete") {
|
|
1311
|
+
return {
|
|
1312
|
+
workflow: "autoresearch-goal",
|
|
1313
|
+
command: `omx autoresearch-goal complete --slug ${safeString(mission.slug) || entry.name} --codex-goal-json '<get_goal JSON or path>'`,
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return null;
|
|
1318
|
+
}
|
|
1319
|
+
async function buildGoalWorkflowReconciliationPromptWarning(cwd, prompt) {
|
|
1320
|
+
if (!looksLikeGoalCompletionPrompt(prompt))
|
|
1321
|
+
return null;
|
|
1322
|
+
const requirement = await findActiveGoalWorkflowReconciliationRequirement(cwd);
|
|
1323
|
+
if (!requirement)
|
|
1324
|
+
return null;
|
|
1325
|
+
return [
|
|
1326
|
+
`OMX ${requirement.workflow} goal workflow requires Codex goal snapshot reconciliation before completion.`,
|
|
1327
|
+
"Call get_goal, pass the resulting JSON or a path with --codex-goal-json, and do not rely on hooks or shell commands to mutate Codex-owned goal state.",
|
|
1328
|
+
`Required command shape: ${requirement.command}.`,
|
|
1329
|
+
].join(" ");
|
|
1330
|
+
}
|
|
1331
|
+
async function buildGoalWorkflowReconciliationStopOutput(payload, cwd) {
|
|
1332
|
+
const lastAssistantMessage = safeString(payload.last_assistant_message ?? payload.lastAssistantMessage);
|
|
1333
|
+
if (!looksLikeGoalCompletionPrompt(lastAssistantMessage))
|
|
1334
|
+
return null;
|
|
1335
|
+
const requirement = await findActiveGoalWorkflowReconciliationRequirement(cwd);
|
|
1336
|
+
if (!requirement)
|
|
1337
|
+
return null;
|
|
1338
|
+
const systemMessage = `OMX ${requirement.workflow} requires get_goal snapshot reconciliation before completion; call get_goal and pass --codex-goal-json to ${requirement.command}. Hooks must not mutate Codex goal state.`;
|
|
1339
|
+
return {
|
|
1340
|
+
decision: "block",
|
|
1341
|
+
reason: systemMessage,
|
|
1342
|
+
stopReason: `${requirement.workflow}_codex_goal_snapshot_required`,
|
|
1343
|
+
systemMessage,
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
960
1346
|
async function readTeamModeStateForStop(cwd, sessionId) {
|
|
961
1347
|
const normalizedSessionId = safeString(sessionId).trim();
|
|
962
1348
|
if (!normalizedSessionId) {
|
|
@@ -1080,6 +1466,28 @@ function matchesSkillStopContext(entry, state, sessionId, threadId) {
|
|
|
1080
1466
|
}
|
|
1081
1467
|
return true;
|
|
1082
1468
|
}
|
|
1469
|
+
function modeStateMatchesSkillStopContext(state, cwd, sessionId) {
|
|
1470
|
+
const stateSessionId = safeString(state.owner_omx_session_id
|
|
1471
|
+
?? state.session_id
|
|
1472
|
+
?? state.codex_session_id
|
|
1473
|
+
?? state.owner_codex_session_id).trim();
|
|
1474
|
+
if (sessionId && stateSessionId && stateSessionId !== sessionId)
|
|
1475
|
+
return false;
|
|
1476
|
+
const stateCwd = safeString(state.cwd
|
|
1477
|
+
?? state.workingDirectory
|
|
1478
|
+
?? state.working_directory
|
|
1479
|
+
?? state.project_path).trim();
|
|
1480
|
+
if (stateCwd) {
|
|
1481
|
+
try {
|
|
1482
|
+
if (resolve(stateCwd) !== resolve(cwd))
|
|
1483
|
+
return false;
|
|
1484
|
+
}
|
|
1485
|
+
catch {
|
|
1486
|
+
return false;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
return true;
|
|
1490
|
+
}
|
|
1083
1491
|
async function readBlockingSkillForStop(cwd, sessionId, threadId, requiredSkill) {
|
|
1084
1492
|
const canonicalState = await readVisibleSkillActiveState(cwd, sessionId);
|
|
1085
1493
|
const visibleEntries = canonicalState ? listActiveSkills(canonicalState) : [];
|
|
@@ -1087,15 +1495,29 @@ async function readBlockingSkillForStop(cwd, sessionId, threadId, requiredSkill)
|
|
|
1087
1495
|
? [requiredSkill]
|
|
1088
1496
|
: [...SKILL_STOP_BLOCKERS];
|
|
1089
1497
|
for (const skill of candidateSkills) {
|
|
1498
|
+
const terminalRunState = await readCanonicalTerminalRunStateForStop(cwd, sessionId, skill);
|
|
1499
|
+
if (terminalRunState)
|
|
1500
|
+
continue;
|
|
1090
1501
|
const modeState = await readStopSessionPinnedState(`${skill}-state.json`, cwd, sessionId);
|
|
1091
1502
|
if (!modeState || modeState.active !== true)
|
|
1092
1503
|
continue;
|
|
1504
|
+
if (!modeStateMatchesSkillStopContext(modeState, cwd, sessionId))
|
|
1505
|
+
continue;
|
|
1506
|
+
const modeSnapshot = getRunContinuationSnapshot(modeState);
|
|
1507
|
+
if (modeSnapshot?.terminal === true)
|
|
1508
|
+
continue;
|
|
1093
1509
|
const phase = formatPhase(modeState.current_phase, formatPhase(visibleEntries.find((entry) => entry.skill === skill)?.phase, "planning"));
|
|
1094
1510
|
if (TERMINAL_MODE_PHASES.has(phase.toLowerCase()) || phase === "completing") {
|
|
1095
1511
|
continue;
|
|
1096
1512
|
}
|
|
1097
1513
|
if (!canonicalState) {
|
|
1098
|
-
return {
|
|
1514
|
+
return {
|
|
1515
|
+
skill,
|
|
1516
|
+
phase,
|
|
1517
|
+
latestPlanPath: safeString(modeState.latest_plan_path ?? modeState.latestPlanPath).trim() || undefined,
|
|
1518
|
+
planningComplete: modeState.planning_complete === true || modeState.planningComplete === true,
|
|
1519
|
+
runOutcome: safeString(modeState.run_outcome ?? modeState.outcome).trim() || undefined,
|
|
1520
|
+
};
|
|
1099
1521
|
}
|
|
1100
1522
|
const blocker = visibleEntries.find((entry) => (entry.skill === skill
|
|
1101
1523
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
|
|
@@ -1104,10 +1526,47 @@ async function readBlockingSkillForStop(cwd, sessionId, threadId, requiredSkill)
|
|
|
1104
1526
|
return {
|
|
1105
1527
|
skill,
|
|
1106
1528
|
phase: formatPhase(modeState.current_phase ?? blocker.phase ?? canonicalState.phase, "planning"),
|
|
1529
|
+
latestPlanPath: safeString(modeState.latest_plan_path ?? modeState.latestPlanPath).trim() || undefined,
|
|
1530
|
+
planningComplete: modeState.planning_complete === true || modeState.planningComplete === true,
|
|
1531
|
+
runOutcome: safeString(modeState.run_outcome ?? modeState.outcome).trim() || undefined,
|
|
1107
1532
|
};
|
|
1108
1533
|
}
|
|
1109
1534
|
return null;
|
|
1110
1535
|
}
|
|
1536
|
+
function buildRalplanContinuationStatus(blocker, activeSubagentCount) {
|
|
1537
|
+
const phase = blocker.phase || "planning";
|
|
1538
|
+
const artifact = blocker.latestPlanPath
|
|
1539
|
+
? ` Artifact: ${blocker.latestPlanPath}.`
|
|
1540
|
+
: " Artifact: use the latest `.omx/plans/` ralplan artifact if present.";
|
|
1541
|
+
if (activeSubagentCount > 0) {
|
|
1542
|
+
return {
|
|
1543
|
+
reason: `Status: waiting — ralplan is waiting for ${activeSubagentCount} active native subagent thread(s) to finish (phase: ${phase}). Do not stop silently; wait for the subagent result, then continue from the current ralplan artifact and proceed to the next planning/review step.${artifact}`,
|
|
1544
|
+
stopReasonSuffix: "waiting_subagent",
|
|
1545
|
+
systemMessage: `OMX ralplan status: waiting for ${activeSubagentCount} active native subagent thread(s) at phase ${phase}; after they finish, continue from the current ralplan artifact and state the next status explicitly.`,
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
const normalizedPhase = phase.toLowerCase();
|
|
1549
|
+
const normalizedOutcome = (blocker.runOutcome ?? "").toLowerCase();
|
|
1550
|
+
const waitingForInput = normalizedOutcome === "blocked_on_user"
|
|
1551
|
+
|| normalizedPhase.includes("blocked")
|
|
1552
|
+
|| normalizedPhase.includes("input")
|
|
1553
|
+
|| normalizedPhase.includes("question");
|
|
1554
|
+
if (waitingForInput) {
|
|
1555
|
+
return {
|
|
1556
|
+
reason: `Status: waiting_for_input — ralplan is paused for required user/operator input (phase: ${phase}). Ask the missing question or present the review choice explicitly before stopping.${artifact}`,
|
|
1557
|
+
stopReasonSuffix: "waiting_input",
|
|
1558
|
+
systemMessage: `OMX ralplan status: waiting for input at phase ${phase}; ask the required question or present the explicit review choice before stopping.`,
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1561
|
+
const completeHint = blocker.planningComplete
|
|
1562
|
+
? " The planning artifacts are present; if consensus is approved, emit the final complete/approved handoff instead of stopping here."
|
|
1563
|
+
: "";
|
|
1564
|
+
return {
|
|
1565
|
+
reason: `Status: continue_from_artifact — ralplan is still active (phase: ${phase}) and has not emitted a terminal complete/paused/waiting status. Continue from the current ralplan artifact, resolve any review ambiguity conservatively or ask the user if needed, and proceed to the next planning/review step before stopping.${artifact}${completeHint}`,
|
|
1566
|
+
stopReasonSuffix: "continue_artifact",
|
|
1567
|
+
systemMessage: `OMX ralplan status: continue_from_artifact at phase ${phase}; continue from the current ralplan artifact and finish by stating whether ralplan is complete, paused for review, waiting for input, or still continuing.`,
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1111
1570
|
async function readStopAutoNudgePhase(cwd, sessionId, threadId) {
|
|
1112
1571
|
const normalizedSessionId = sessionId.trim();
|
|
1113
1572
|
if (normalizedSessionId) {
|
|
@@ -1176,13 +1635,20 @@ async function buildDeepInterviewQuestionStopOutput(cwd, sessionId, threadId) {
|
|
|
1176
1635
|
};
|
|
1177
1636
|
}
|
|
1178
1637
|
function resolveRepeatableStopSessionId(payload, canonicalSessionId) {
|
|
1179
|
-
|
|
1638
|
+
const inheritedSessionId = safeString(process.env.OMX_SESSION_ID || process.env.CODEX_SESSION_ID).trim();
|
|
1639
|
+
return canonicalSessionId?.trim() || readPayloadSessionId(payload) || inheritedSessionId || "";
|
|
1640
|
+
}
|
|
1641
|
+
function isStateLevelStopSignatureKind(kind) {
|
|
1642
|
+
return kind === "team-worker-stop" || kind === "team-stop";
|
|
1180
1643
|
}
|
|
1181
1644
|
function buildRepeatableStopSignature(payload, kind, detail = "", canonicalSessionId) {
|
|
1182
1645
|
const sessionId = resolveRepeatableStopSessionId(payload, canonicalSessionId) || "no-session";
|
|
1183
1646
|
const threadId = readPayloadThreadId(payload) || "no-thread";
|
|
1184
|
-
const turnId = readPayloadTurnId(payload);
|
|
1185
1647
|
const normalizedDetail = normalizeAutoNudgeSignatureText(detail) || safeString(detail).trim().toLowerCase();
|
|
1648
|
+
if (isStateLevelStopSignatureKind(kind)) {
|
|
1649
|
+
return [kind, sessionId, threadId, normalizedDetail || "no-detail"].join("|");
|
|
1650
|
+
}
|
|
1651
|
+
const turnId = readPayloadTurnId(payload);
|
|
1186
1652
|
const transcriptPath = safeString(payload.transcript_path ?? payload.transcriptPath).trim() || "no-transcript";
|
|
1187
1653
|
const lastAssistantMessage = normalizeAutoNudgeSignatureText(payload.last_assistant_message ?? payload.lastAssistantMessage) || "no-message";
|
|
1188
1654
|
if (turnId) {
|
|
@@ -1327,7 +1793,17 @@ async function buildSkillStopOutput(cwd, sessionId, threadId) {
|
|
|
1327
1793
|
if (!blocker)
|
|
1328
1794
|
return null;
|
|
1329
1795
|
const subagentSummary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
|
|
1330
|
-
|
|
1796
|
+
const activeSubagentCount = subagentSummary?.activeSubagentThreadIds.length ?? 0;
|
|
1797
|
+
if (blocker.skill === "ralplan") {
|
|
1798
|
+
const status = buildRalplanContinuationStatus(blocker, activeSubagentCount);
|
|
1799
|
+
return {
|
|
1800
|
+
decision: "block",
|
|
1801
|
+
reason: status.reason,
|
|
1802
|
+
stopReason: `skill_${blocker.skill}_${blocker.phase}_${status.stopReasonSuffix}`,
|
|
1803
|
+
systemMessage: status.systemMessage,
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
if (activeSubagentCount > 0) {
|
|
1331
1807
|
return null;
|
|
1332
1808
|
}
|
|
1333
1809
|
return {
|
|
@@ -1414,7 +1890,7 @@ async function markTeamTransportFailure(cwd, payload) {
|
|
|
1414
1890
|
// Canonical team state already carries the preserved failure for coarse-state-missing sessions.
|
|
1415
1891
|
}
|
|
1416
1892
|
}
|
|
1417
|
-
async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
1893
|
+
async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
|
|
1418
1894
|
if (isStopExempt(payload)) {
|
|
1419
1895
|
return null;
|
|
1420
1896
|
}
|
|
@@ -1424,7 +1900,13 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1424
1900
|
const execFollowupOutput = await buildExecFollowupStopOutput(cwd, canonicalSessionId);
|
|
1425
1901
|
if (execFollowupOutput)
|
|
1426
1902
|
return execFollowupOutput;
|
|
1427
|
-
const ralphState =
|
|
1903
|
+
const ralphState = options.skipRalphStopBlock === true
|
|
1904
|
+
? null
|
|
1905
|
+
: await readActiveRalphState(stateDir, canonicalSessionId, {
|
|
1906
|
+
payloadSessionId: sessionId,
|
|
1907
|
+
threadId,
|
|
1908
|
+
tmuxPaneId: safeString(process.env.TMUX_PANE).trim(),
|
|
1909
|
+
});
|
|
1428
1910
|
if (!ralphState) {
|
|
1429
1911
|
const autoresearchState = await readActiveAutoresearchState(cwd, canonicalSessionId);
|
|
1430
1912
|
if (autoresearchState) {
|
|
@@ -1440,9 +1922,22 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1440
1922
|
}, canonicalSessionId, { allowRepeatDuringStopHook: true });
|
|
1441
1923
|
}
|
|
1442
1924
|
}
|
|
1443
|
-
const
|
|
1444
|
-
if (
|
|
1445
|
-
return await returnPersistentStopBlock(payload, stateDir, "team-worker-stop", safeString(
|
|
1925
|
+
const teamWorkerDecision = await resolveTeamWorkerStopDecision(cwd);
|
|
1926
|
+
if (teamWorkerDecision.kind === "blocked") {
|
|
1927
|
+
return await returnPersistentStopBlock(payload, stateDir, "team-worker-stop", safeString(teamWorkerDecision.output.stopReason), teamWorkerDecision.output, canonicalSessionId, { allowRepeatDuringStopHook: teamWorkerDecision.allowRepeatDuringStopHook });
|
|
1928
|
+
}
|
|
1929
|
+
if (teamWorkerDecision.kind === "allowed") {
|
|
1930
|
+
try {
|
|
1931
|
+
await maybeNudgeLeaderForAllowedWorkerStop({
|
|
1932
|
+
stateDir: teamWorkerDecision.stateDir,
|
|
1933
|
+
logsDir: join(cwd, ".omx", "logs"),
|
|
1934
|
+
workerContext: teamWorkerDecision.workerContext,
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
catch (err) {
|
|
1938
|
+
void err;
|
|
1939
|
+
}
|
|
1940
|
+
return null;
|
|
1446
1941
|
}
|
|
1447
1942
|
const autopilotOutput = await buildModeBasedStopOutput("autopilot", cwd, canonicalSessionId);
|
|
1448
1943
|
if (autopilotOutput) {
|
|
@@ -1483,6 +1978,10 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1483
1978
|
}
|
|
1484
1979
|
}
|
|
1485
1980
|
const lastAssistantMessage = safeString(payload.last_assistant_message ?? payload.lastAssistantMessage);
|
|
1981
|
+
const goalWorkflowStopOutput = await buildGoalWorkflowReconciliationStopOutput(payload, cwd);
|
|
1982
|
+
if (goalWorkflowStopOutput) {
|
|
1983
|
+
return await returnPersistentStopBlock(payload, stateDir, "goal-workflow-reconciliation-stop", safeString(goalWorkflowStopOutput.stopReason), goalWorkflowStopOutput, canonicalSessionId, { allowRepeatDuringStopHook: true });
|
|
1984
|
+
}
|
|
1486
1985
|
const autoNudgeConfig = await loadAutoNudgeConfig();
|
|
1487
1986
|
const autoNudgePhase = await readStopAutoNudgePhase(cwd, canonicalSessionId, threadId);
|
|
1488
1987
|
if (autoNudgeConfig.enabled
|
|
@@ -1495,6 +1994,11 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1495
1994
|
systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
|
|
1496
1995
|
}, canonicalSessionId);
|
|
1497
1996
|
}
|
|
1997
|
+
const sloppyFallbackDiffFindings = findSloppyFallbackDiffFindings(cwd);
|
|
1998
|
+
const sloppyFallbackDiffOutput = buildSloppyFallbackDiffStopOutput(sloppyFallbackDiffFindings);
|
|
1999
|
+
if (sloppyFallbackDiffOutput) {
|
|
2000
|
+
return await returnPersistentStopBlock(payload, stateDir, "sloppy-fallback-diff-stop", JSON.stringify(sloppyFallbackDiffFindings), sloppyFallbackDiffOutput, canonicalSessionId, { allowRepeatDuringStopHook: true });
|
|
2001
|
+
}
|
|
1498
2002
|
if (isFinalHandoffDocumentRefreshCandidate(lastAssistantMessage)) {
|
|
1499
2003
|
const documentRefreshWarning = evaluateFinalHandoffDocumentRefresh(cwd, lastAssistantMessage);
|
|
1500
2004
|
if (documentRefreshWarning) {
|
|
@@ -1522,6 +2026,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1522
2026
|
const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
|
|
1523
2027
|
let skillState = null;
|
|
1524
2028
|
let triageAdditionalContext = null;
|
|
2029
|
+
let goalWorkflowAdditionalContext = null;
|
|
1525
2030
|
const nativeSessionId = safeString(payload.session_id ?? payload.sessionId).trim();
|
|
1526
2031
|
const threadId = safeString(payload.thread_id ?? payload.threadId).trim();
|
|
1527
2032
|
const turnId = safeString(payload.turn_id ?? payload.turnId).trim();
|
|
@@ -1557,7 +2062,8 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1557
2062
|
canonicalSessionId = safeString(currentSessionState?.session_id).trim();
|
|
1558
2063
|
}
|
|
1559
2064
|
if (hookEventName === "Stop") {
|
|
1560
|
-
const
|
|
2065
|
+
const inheritedSessionId = safeString(process.env.OMX_SESSION_ID || process.env.CODEX_SESSION_ID).trim();
|
|
2066
|
+
const stopCanonicalSessionId = await resolveInternalSessionIdForPayload(cwd, readPayloadSessionId(payload) || inheritedSessionId);
|
|
1561
2067
|
if (stopCanonicalSessionId) {
|
|
1562
2068
|
canonicalSessionId = stopCanonicalSessionId;
|
|
1563
2069
|
}
|
|
@@ -1569,9 +2075,20 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1569
2075
|
const eventSessionId = canonicalSessionId || nativeSessionId || undefined;
|
|
1570
2076
|
const sessionIdForState = canonicalSessionId || nativeSessionId;
|
|
1571
2077
|
let outputJson = null;
|
|
2078
|
+
const isSubagentPromptSubmit = hookEventName === "UserPromptSubmit"
|
|
2079
|
+
? await isNativeSubagentHook(cwd, canonicalSessionId, nativeSessionId, threadId)
|
|
2080
|
+
: false;
|
|
2081
|
+
const isSubagentStop = hookEventName === "Stop"
|
|
2082
|
+
? (await Promise.all([...new Set([
|
|
2083
|
+
canonicalSessionId,
|
|
2084
|
+
safeString(currentSessionState?.session_id).trim(),
|
|
2085
|
+
].filter(Boolean))]
|
|
2086
|
+
.map((candidateSessionId) => isNativeSubagentHook(cwd, candidateSessionId, nativeSessionId, threadId)))).some(Boolean)
|
|
2087
|
+
: false;
|
|
1572
2088
|
if (hookEventName === "UserPromptSubmit") {
|
|
1573
2089
|
const prompt = readPromptText(payload);
|
|
1574
|
-
|
|
2090
|
+
goalWorkflowAdditionalContext = await buildGoalWorkflowReconciliationPromptWarning(cwd, prompt).catch(() => null);
|
|
2091
|
+
if (prompt && !isSubagentPromptSubmit) {
|
|
1575
2092
|
skillState = buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionIdForState, threadId || undefined, turnId || undefined) ?? await recordSkillActivation({
|
|
1576
2093
|
stateDir,
|
|
1577
2094
|
text: prompt,
|
|
@@ -1581,7 +2098,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1581
2098
|
});
|
|
1582
2099
|
}
|
|
1583
2100
|
// --- Triage classifier (advisory-only, non-keyword prompts) ---
|
|
1584
|
-
if (prompt && skillState === null) {
|
|
2101
|
+
if (prompt && skillState === null && !isSubagentPromptSubmit) {
|
|
1585
2102
|
try {
|
|
1586
2103
|
if (readTriageConfig().enabled) {
|
|
1587
2104
|
const normalized = prompt.trim().toLowerCase();
|
|
@@ -1673,7 +2190,11 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1673
2190
|
turn_id: turnId || undefined,
|
|
1674
2191
|
mode: safeString(payload.mode).trim() || undefined,
|
|
1675
2192
|
});
|
|
1676
|
-
await
|
|
2193
|
+
await dispatchHookEventRuntime({
|
|
2194
|
+
event,
|
|
2195
|
+
cwd,
|
|
2196
|
+
allowTeamWorkerSideEffects: false,
|
|
2197
|
+
});
|
|
1677
2198
|
}
|
|
1678
2199
|
if ((hookEventName === "SessionStart" && !skipCanonicalSessionStartContext) || hookEventName === "UserPromptSubmit") {
|
|
1679
2200
|
const additionalContext = hookEventName === "SessionStart"
|
|
@@ -1683,7 +2204,9 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1683
2204
|
canonicalSessionId,
|
|
1684
2205
|
nativeSessionId: resolvedNativeSessionId || nativeSessionId,
|
|
1685
2206
|
})
|
|
1686
|
-
:
|
|
2207
|
+
: isSubagentPromptSubmit
|
|
2208
|
+
? null
|
|
2209
|
+
: (buildAdditionalContextMessage(readPromptText(payload), skillState, cwd, payload) ?? goalWorkflowAdditionalContext ?? triageAdditionalContext);
|
|
1687
2210
|
if (additionalContext) {
|
|
1688
2211
|
outputJson = {
|
|
1689
2212
|
hookSpecificOutput: {
|
|
@@ -1704,7 +2227,9 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1704
2227
|
await handleTeamWorkerPostToolUseSuccess(payload, cwd);
|
|
1705
2228
|
}
|
|
1706
2229
|
else if (hookEventName === "Stop") {
|
|
1707
|
-
outputJson = await buildStopHookOutput(payload, cwd, stateDir
|
|
2230
|
+
outputJson = await buildStopHookOutput(payload, cwd, stateDir, {
|
|
2231
|
+
skipRalphStopBlock: isSubagentStop,
|
|
2232
|
+
});
|
|
1708
2233
|
}
|
|
1709
2234
|
return {
|
|
1710
2235
|
hookEventName,
|