oh-my-codex 0.15.3 → 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/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 +20 -1
- 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-warning-copy.test.js +23 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +8 -1
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +82 -3
- 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__/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__/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 +18 -9
- 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 +187 -0
- 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 +49 -0
- 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 +6 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +145 -18
- package/dist/cli/index.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.map +1 -1
- package/dist/cli/ralph.js +8 -0
- 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 +2 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +72 -17
- 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 +12 -1
- 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 +3 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +52 -8
- 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__/anti-slop-workflow.test.js +3 -3
- 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 +2 -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__/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 +62 -1
- 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 +30 -5
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/stages/team-exec.d.ts.map +1 -1
- package/dist/pipeline/stages/team-exec.js +2 -19
- package/dist/pipeline/stages/team-exec.js.map +1 -1
- package/dist/planning/__tests__/artifacts.test.js +16 -1
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/artifacts.d.ts +1 -0
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +9 -12
- package/dist/planning/artifacts.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 +1516 -205
- 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 +497 -51
- 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 +222 -19
- 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-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/run-test-files.js +17 -1
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +2 -2
- 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 +35 -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 +59 -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__/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.test.js +118 -6
- 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__/tmux-session.test.js +3 -0
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +50 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +4 -3
- 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.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/role-router.js +5 -5
- package/dist/team/role-router.js.map +1 -1
- package/dist/team/runtime.d.ts +6 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +46 -6
- 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/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +4 -2
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +2 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +19 -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/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/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 +1654 -157
- 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 +592 -52
- package/src/scripts/codex-native-pre-post.ts +252 -20
- 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-stop.ts +246 -0
- package/src/scripts/notify-hook/team-worker.ts +23 -14
- package/src/scripts/run-test-files.ts +20 -1
- package/src/scripts/sync-plugin-mirror.ts +2 -2
- 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";
|
|
@@ -32,8 +33,8 @@ import { buildDocumentRefreshAdvisoryOutput, evaluateFinalHandoffDocumentRefresh
|
|
|
32
33
|
import { buildExecFollowupStopOutput } from "../exec/followup.js";
|
|
33
34
|
const TERMINAL_MODE_PHASES = new Set(["complete", "completed", "failed", "cancelled"]);
|
|
34
35
|
const SKILL_STOP_BLOCKERS = new Set(["ralplan"]);
|
|
35
|
-
const
|
|
36
|
-
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"]);
|
|
37
38
|
const NATIVE_STOP_STATE_FILE = "native-stop-state.json";
|
|
38
39
|
const STABLE_FINAL_RECOMMENDATION_PATTERNS = [
|
|
39
40
|
/^\s*(?:launch|release|ship)-?ready\s*:\s*(?:yes|no)\b[^\n\r]*/im,
|
|
@@ -160,6 +161,20 @@ async function nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonica
|
|
|
160
161
|
return true;
|
|
161
162
|
return summary.allThreadIds.includes(parentThreadId);
|
|
162
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
|
+
}
|
|
163
178
|
async function recordIgnoredNativeSubagentSessionStart(cwd, canonicalSessionId, childSessionId, metadata, transcriptPath) {
|
|
164
179
|
await appendToLog(cwd, {
|
|
165
180
|
event: "subagent_session_start_ignored",
|
|
@@ -303,7 +318,7 @@ async function readActiveAutoresearchState(cwd, sessionId) {
|
|
|
303
318
|
const normalizedSessionId = sessionId?.trim() || undefined;
|
|
304
319
|
if (!normalizedSessionId)
|
|
305
320
|
return null;
|
|
306
|
-
const state = await
|
|
321
|
+
const state = await readAutoresearchModeStateForActiveDecision(cwd, normalizedSessionId);
|
|
307
322
|
if (state?.active !== true)
|
|
308
323
|
return null;
|
|
309
324
|
if (!isNonTerminalPhase(state.current_phase ?? state.currentPhase ?? 'executing'))
|
|
@@ -367,6 +382,18 @@ async function isVisibleRalphActiveForSession(cwd, sessionId) {
|
|
|
367
382
|
return listActiveSkills(canonicalState).some((entry) => (entry.skill === "ralph"
|
|
368
383
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, "")));
|
|
369
384
|
}
|
|
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
|
+
}
|
|
370
397
|
async function readActiveRalphState(stateDir, preferredSessionId, ownerContext) {
|
|
371
398
|
const cwd = resolve(stateDir, "..", "..");
|
|
372
399
|
const [rawSessionInfo, usableSessionInfo] = await Promise.all([
|
|
@@ -407,7 +434,8 @@ async function readActiveRalphState(stateDir, preferredSessionId, ownerContext)
|
|
|
407
434
|
threadId: safeString(ownerContext?.threadId).trim(),
|
|
408
435
|
currentNativeSessionId,
|
|
409
436
|
tmuxPaneId: safeString(ownerContext?.tmuxPaneId).trim(),
|
|
410
|
-
})
|
|
437
|
+
})
|
|
438
|
+
&& await hasConsistentRalphSkillActivation(cwd, sessionId)) {
|
|
411
439
|
return { state: sessionScoped, path: sessionScopedPath };
|
|
412
440
|
}
|
|
413
441
|
}
|
|
@@ -522,6 +550,182 @@ function tryReadGitValue(cwd, args) {
|
|
|
522
550
|
return null;
|
|
523
551
|
}
|
|
524
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
|
+
}
|
|
525
729
|
function localExcludeAlreadyIgnoresOmx(cwd) {
|
|
526
730
|
const layout = findGitLayout(cwd);
|
|
527
731
|
if (!layout)
|
|
@@ -845,6 +1049,9 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
845
1049
|
const ultraworkPromptActivationNote = skillState?.initialized_mode === "ultrawork"
|
|
846
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."
|
|
847
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;
|
|
848
1055
|
const combinedTransitionMessage = (() => {
|
|
849
1056
|
if (!skillState?.transition_message)
|
|
850
1057
|
return null;
|
|
@@ -872,6 +1079,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
872
1079
|
? `planning preserved over simultaneous execution follow-up; deferred skills: ${deferredSkills.join(", ")}.`
|
|
873
1080
|
: null,
|
|
874
1081
|
promptPriorityMessage,
|
|
1082
|
+
ultragoalPromptActivationNote,
|
|
875
1083
|
skillState.initialized_mode && skillState.initialized_state_path
|
|
876
1084
|
? `skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`
|
|
877
1085
|
: null,
|
|
@@ -896,6 +1104,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
896
1104
|
initializedStateMessage,
|
|
897
1105
|
deepInterviewPromptActivationNote,
|
|
898
1106
|
ultraworkPromptActivationNote,
|
|
1107
|
+
ultragoalPromptActivationNote,
|
|
899
1108
|
buildTeamRuntimeInstruction(cwd, payload),
|
|
900
1109
|
buildTeamHelpInstruction(cwd, payload),
|
|
901
1110
|
"Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
|
|
@@ -912,11 +1121,12 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
912
1121
|
`skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`,
|
|
913
1122
|
deepInterviewPromptActivationNote,
|
|
914
1123
|
ultraworkPromptActivationNote,
|
|
1124
|
+
ultragoalPromptActivationNote,
|
|
915
1125
|
ralphPromptActivationNote,
|
|
916
1126
|
"Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
|
|
917
1127
|
].join(" ");
|
|
918
1128
|
}
|
|
919
|
-
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(" ");
|
|
920
1130
|
}
|
|
921
1131
|
function parseTeamWorkerEnv(rawValue) {
|
|
922
1132
|
const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(rawValue.trim());
|
|
@@ -928,23 +1138,51 @@ function parseTeamWorkerEnv(rawValue) {
|
|
|
928
1138
|
};
|
|
929
1139
|
}
|
|
930
1140
|
async function resolveTeamStateDirForWorkerContext(cwd, workerContext) {
|
|
931
|
-
|
|
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;
|
|
932
1153
|
}
|
|
933
|
-
async function
|
|
934
|
-
const workerContext = parseTeamWorkerEnv(safeString(process.env.OMX_TEAM_INTERNAL_WORKER
|
|
1154
|
+
async function resolveTeamWorkerStopDecision(cwd) {
|
|
1155
|
+
const workerContext = parseTeamWorkerEnv(safeString(process.env.OMX_TEAM_INTERNAL_WORKER))
|
|
1156
|
+
|| parseTeamWorkerEnv(safeString(process.env.OMX_TEAM_WORKER));
|
|
935
1157
|
if (!workerContext)
|
|
936
|
-
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
|
+
});
|
|
937
1172
|
const stateDir = await resolveTeamStateDirForWorkerContext(cwd, workerContext);
|
|
938
|
-
if (!stateDir)
|
|
939
|
-
return
|
|
1173
|
+
if (!stateDir) {
|
|
1174
|
+
return blockWorkerStop("missing_state_dir", "team state root could not be resolved");
|
|
1175
|
+
}
|
|
940
1176
|
const workerRoot = join(stateDir, "team", workerContext.teamName, "workers", workerContext.workerName);
|
|
941
1177
|
const [identity, status] = await Promise.all([
|
|
942
1178
|
readJsonIfExists(join(workerRoot, "identity.json")),
|
|
943
1179
|
readJsonIfExists(join(workerRoot, "status.json")),
|
|
944
1180
|
]);
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
|
|
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
|
+
}
|
|
948
1186
|
const candidateTaskIds = new Set();
|
|
949
1187
|
const currentTaskId = safeString(status?.current_task_id).trim();
|
|
950
1188
|
if (currentTaskId)
|
|
@@ -955,22 +1193,57 @@ async function buildTeamWorkerStopOutput(cwd) {
|
|
|
955
1193
|
if (normalized)
|
|
956
1194
|
candidateTaskIds.add(normalized);
|
|
957
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;
|
|
958
1217
|
for (const taskId of candidateTaskIds) {
|
|
959
1218
|
const task = await readJsonIfExists(join(stateDir, "team", workerContext.teamName, "tasks", `task-${taskId}.json`));
|
|
960
1219
|
const statusValue = safeString(task?.status).trim().toLowerCase();
|
|
961
|
-
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;
|
|
962
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
|
+
}
|
|
963
1230
|
return {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
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
|
+
},
|
|
968
1241
|
};
|
|
969
1242
|
}
|
|
970
|
-
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
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);
|
|
974
1247
|
}
|
|
975
1248
|
function isStopExempt(payload) {
|
|
976
1249
|
const candidates = [
|
|
@@ -989,9 +1262,7 @@ function isStopExempt(payload) {
|
|
|
989
1262
|
|| value.includes("limit"));
|
|
990
1263
|
}
|
|
991
1264
|
async function buildModeBasedStopOutput(mode, cwd, sessionId) {
|
|
992
|
-
const state = sessionId
|
|
993
|
-
? await readModeStateForSession(mode, sessionId, cwd)
|
|
994
|
-
: await readModeState(mode, cwd);
|
|
1265
|
+
const state = await readModeStateForActiveDecision(mode, sessionId?.trim() || undefined, cwd);
|
|
995
1266
|
if (!state || !shouldContinueRun(state))
|
|
996
1267
|
return null;
|
|
997
1268
|
const phase = formatPhase(state.current_phase);
|
|
@@ -1002,6 +1273,76 @@ async function buildModeBasedStopOutput(mode, cwd, sessionId) {
|
|
|
1002
1273
|
systemMessage: `OMX ${mode} is still active (phase: ${phase}).`,
|
|
1003
1274
|
};
|
|
1004
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
|
+
}
|
|
1005
1346
|
async function readTeamModeStateForStop(cwd, sessionId) {
|
|
1006
1347
|
const normalizedSessionId = safeString(sessionId).trim();
|
|
1007
1348
|
if (!normalizedSessionId) {
|
|
@@ -1170,7 +1511,13 @@ async function readBlockingSkillForStop(cwd, sessionId, threadId, requiredSkill)
|
|
|
1170
1511
|
continue;
|
|
1171
1512
|
}
|
|
1172
1513
|
if (!canonicalState) {
|
|
1173
|
-
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
|
+
};
|
|
1174
1521
|
}
|
|
1175
1522
|
const blocker = visibleEntries.find((entry) => (entry.skill === skill
|
|
1176
1523
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
|
|
@@ -1179,10 +1526,47 @@ async function readBlockingSkillForStop(cwd, sessionId, threadId, requiredSkill)
|
|
|
1179
1526
|
return {
|
|
1180
1527
|
skill,
|
|
1181
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,
|
|
1182
1532
|
};
|
|
1183
1533
|
}
|
|
1184
1534
|
return null;
|
|
1185
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
|
+
}
|
|
1186
1570
|
async function readStopAutoNudgePhase(cwd, sessionId, threadId) {
|
|
1187
1571
|
const normalizedSessionId = sessionId.trim();
|
|
1188
1572
|
if (normalizedSessionId) {
|
|
@@ -1251,13 +1635,20 @@ async function buildDeepInterviewQuestionStopOutput(cwd, sessionId, threadId) {
|
|
|
1251
1635
|
};
|
|
1252
1636
|
}
|
|
1253
1637
|
function resolveRepeatableStopSessionId(payload, canonicalSessionId) {
|
|
1254
|
-
|
|
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";
|
|
1255
1643
|
}
|
|
1256
1644
|
function buildRepeatableStopSignature(payload, kind, detail = "", canonicalSessionId) {
|
|
1257
1645
|
const sessionId = resolveRepeatableStopSessionId(payload, canonicalSessionId) || "no-session";
|
|
1258
1646
|
const threadId = readPayloadThreadId(payload) || "no-thread";
|
|
1259
|
-
const turnId = readPayloadTurnId(payload);
|
|
1260
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);
|
|
1261
1652
|
const transcriptPath = safeString(payload.transcript_path ?? payload.transcriptPath).trim() || "no-transcript";
|
|
1262
1653
|
const lastAssistantMessage = normalizeAutoNudgeSignatureText(payload.last_assistant_message ?? payload.lastAssistantMessage) || "no-message";
|
|
1263
1654
|
if (turnId) {
|
|
@@ -1402,7 +1793,17 @@ async function buildSkillStopOutput(cwd, sessionId, threadId) {
|
|
|
1402
1793
|
if (!blocker)
|
|
1403
1794
|
return null;
|
|
1404
1795
|
const subagentSummary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
|
|
1405
|
-
|
|
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) {
|
|
1406
1807
|
return null;
|
|
1407
1808
|
}
|
|
1408
1809
|
return {
|
|
@@ -1489,7 +1890,7 @@ async function markTeamTransportFailure(cwd, payload) {
|
|
|
1489
1890
|
// Canonical team state already carries the preserved failure for coarse-state-missing sessions.
|
|
1490
1891
|
}
|
|
1491
1892
|
}
|
|
1492
|
-
async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
1893
|
+
async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
|
|
1493
1894
|
if (isStopExempt(payload)) {
|
|
1494
1895
|
return null;
|
|
1495
1896
|
}
|
|
@@ -1499,11 +1900,13 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1499
1900
|
const execFollowupOutput = await buildExecFollowupStopOutput(cwd, canonicalSessionId);
|
|
1500
1901
|
if (execFollowupOutput)
|
|
1501
1902
|
return execFollowupOutput;
|
|
1502
|
-
const ralphState =
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
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
|
+
});
|
|
1507
1910
|
if (!ralphState) {
|
|
1508
1911
|
const autoresearchState = await readActiveAutoresearchState(cwd, canonicalSessionId);
|
|
1509
1912
|
if (autoresearchState) {
|
|
@@ -1519,9 +1922,22 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1519
1922
|
}, canonicalSessionId, { allowRepeatDuringStopHook: true });
|
|
1520
1923
|
}
|
|
1521
1924
|
}
|
|
1522
|
-
const
|
|
1523
|
-
if (
|
|
1524
|
-
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;
|
|
1525
1941
|
}
|
|
1526
1942
|
const autopilotOutput = await buildModeBasedStopOutput("autopilot", cwd, canonicalSessionId);
|
|
1527
1943
|
if (autopilotOutput) {
|
|
@@ -1562,6 +1978,10 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1562
1978
|
}
|
|
1563
1979
|
}
|
|
1564
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
|
+
}
|
|
1565
1985
|
const autoNudgeConfig = await loadAutoNudgeConfig();
|
|
1566
1986
|
const autoNudgePhase = await readStopAutoNudgePhase(cwd, canonicalSessionId, threadId);
|
|
1567
1987
|
if (autoNudgeConfig.enabled
|
|
@@ -1574,6 +1994,11 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1574
1994
|
systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
|
|
1575
1995
|
}, canonicalSessionId);
|
|
1576
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
|
+
}
|
|
1577
2002
|
if (isFinalHandoffDocumentRefreshCandidate(lastAssistantMessage)) {
|
|
1578
2003
|
const documentRefreshWarning = evaluateFinalHandoffDocumentRefresh(cwd, lastAssistantMessage);
|
|
1579
2004
|
if (documentRefreshWarning) {
|
|
@@ -1601,6 +2026,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1601
2026
|
const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
|
|
1602
2027
|
let skillState = null;
|
|
1603
2028
|
let triageAdditionalContext = null;
|
|
2029
|
+
let goalWorkflowAdditionalContext = null;
|
|
1604
2030
|
const nativeSessionId = safeString(payload.session_id ?? payload.sessionId).trim();
|
|
1605
2031
|
const threadId = safeString(payload.thread_id ?? payload.threadId).trim();
|
|
1606
2032
|
const turnId = safeString(payload.turn_id ?? payload.turnId).trim();
|
|
@@ -1636,7 +2062,8 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1636
2062
|
canonicalSessionId = safeString(currentSessionState?.session_id).trim();
|
|
1637
2063
|
}
|
|
1638
2064
|
if (hookEventName === "Stop") {
|
|
1639
|
-
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);
|
|
1640
2067
|
if (stopCanonicalSessionId) {
|
|
1641
2068
|
canonicalSessionId = stopCanonicalSessionId;
|
|
1642
2069
|
}
|
|
@@ -1648,9 +2075,20 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1648
2075
|
const eventSessionId = canonicalSessionId || nativeSessionId || undefined;
|
|
1649
2076
|
const sessionIdForState = canonicalSessionId || nativeSessionId;
|
|
1650
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;
|
|
1651
2088
|
if (hookEventName === "UserPromptSubmit") {
|
|
1652
2089
|
const prompt = readPromptText(payload);
|
|
1653
|
-
|
|
2090
|
+
goalWorkflowAdditionalContext = await buildGoalWorkflowReconciliationPromptWarning(cwd, prompt).catch(() => null);
|
|
2091
|
+
if (prompt && !isSubagentPromptSubmit) {
|
|
1654
2092
|
skillState = buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionIdForState, threadId || undefined, turnId || undefined) ?? await recordSkillActivation({
|
|
1655
2093
|
stateDir,
|
|
1656
2094
|
text: prompt,
|
|
@@ -1660,7 +2098,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1660
2098
|
});
|
|
1661
2099
|
}
|
|
1662
2100
|
// --- Triage classifier (advisory-only, non-keyword prompts) ---
|
|
1663
|
-
if (prompt && skillState === null) {
|
|
2101
|
+
if (prompt && skillState === null && !isSubagentPromptSubmit) {
|
|
1664
2102
|
try {
|
|
1665
2103
|
if (readTriageConfig().enabled) {
|
|
1666
2104
|
const normalized = prompt.trim().toLowerCase();
|
|
@@ -1752,7 +2190,11 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1752
2190
|
turn_id: turnId || undefined,
|
|
1753
2191
|
mode: safeString(payload.mode).trim() || undefined,
|
|
1754
2192
|
});
|
|
1755
|
-
await
|
|
2193
|
+
await dispatchHookEventRuntime({
|
|
2194
|
+
event,
|
|
2195
|
+
cwd,
|
|
2196
|
+
allowTeamWorkerSideEffects: false,
|
|
2197
|
+
});
|
|
1756
2198
|
}
|
|
1757
2199
|
if ((hookEventName === "SessionStart" && !skipCanonicalSessionStartContext) || hookEventName === "UserPromptSubmit") {
|
|
1758
2200
|
const additionalContext = hookEventName === "SessionStart"
|
|
@@ -1762,7 +2204,9 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1762
2204
|
canonicalSessionId,
|
|
1763
2205
|
nativeSessionId: resolvedNativeSessionId || nativeSessionId,
|
|
1764
2206
|
})
|
|
1765
|
-
:
|
|
2207
|
+
: isSubagentPromptSubmit
|
|
2208
|
+
? null
|
|
2209
|
+
: (buildAdditionalContextMessage(readPromptText(payload), skillState, cwd, payload) ?? goalWorkflowAdditionalContext ?? triageAdditionalContext);
|
|
1766
2210
|
if (additionalContext) {
|
|
1767
2211
|
outputJson = {
|
|
1768
2212
|
hookSpecificOutput: {
|
|
@@ -1783,7 +2227,9 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1783
2227
|
await handleTeamWorkerPostToolUseSuccess(payload, cwd);
|
|
1784
2228
|
}
|
|
1785
2229
|
else if (hookEventName === "Stop") {
|
|
1786
|
-
outputJson = await buildStopHookOutput(payload, cwd, stateDir
|
|
2230
|
+
outputJson = await buildStopHookOutput(payload, cwd, stateDir, {
|
|
2231
|
+
skipRalphStopBlock: isSubagentStop,
|
|
2232
|
+
});
|
|
1787
2233
|
}
|
|
1788
2234
|
return {
|
|
1789
2235
|
hookEventName,
|