oh-my-codex 0.17.3 → 0.18.1
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 +13 -5
- package/Cargo.toml +2 -1
- package/README.md +44 -19
- package/crates/omx-api/Cargo.toml +19 -0
- package/crates/omx-api/src/lib.rs +2997 -0
- package/crates/omx-api/src/main.rs +10 -0
- package/crates/omx-api/tests/cli.rs +558 -0
- package/crates/omx-explore/src/main.rs +4 -0
- package/crates/omx-sparkshell/src/codex_bridge.rs +437 -123
- package/crates/omx-sparkshell/src/exec.rs +127 -1
- package/crates/omx-sparkshell/src/main.rs +829 -30
- package/crates/omx-sparkshell/src/prompt.rs +25 -3
- package/crates/omx-sparkshell/src/redaction.rs +241 -0
- package/crates/omx-sparkshell/tests/execution.rs +702 -237
- package/dist/cli/__tests__/api.test.d.ts +2 -0
- package/dist/cli/__tests__/api.test.d.ts.map +1 -0
- package/dist/cli/__tests__/api.test.js +175 -0
- package/dist/cli/__tests__/api.test.js.map +1 -0
- package/dist/cli/__tests__/ask.test.js +72 -5
- package/dist/cli/__tests__/ask.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-goal.test.js +14 -1
- package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +15 -7
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +76 -3
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +23 -0
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +171 -5
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/install-docs-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/install-docs-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/install-docs-contract.test.js +55 -0
- package/dist/cli/__tests__/install-docs-contract.test.js.map +1 -0
- package/dist/cli/__tests__/launch-fallback.test.js +191 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +4 -3
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +27 -41
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +232 -35
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +25 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-packaging.test.js +1 -0
- package/dist/cli/__tests__/sparkshell-packaging.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +227 -4
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +72 -1
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/__tests__/version-sync-contract.test.js +4 -0
- package/dist/cli/__tests__/version-sync-contract.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
- package/dist/cli/api.d.ts +26 -0
- package/dist/cli/api.d.ts.map +1 -0
- package/dist/cli/api.js +153 -0
- package/dist/cli/api.js.map +1 -0
- package/dist/cli/codex-feature-probe.d.ts +5 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -1
- package/dist/cli/codex-feature-probe.js +13 -7
- package/dist/cli/codex-feature-probe.js.map +1 -1
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +119 -10
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts +2 -0
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +43 -1
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +12 -4
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +460 -87
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/native-assets.d.ts +2 -1
- package/dist/cli/native-assets.d.ts.map +1 -1
- package/dist/cli/native-assets.js +1 -0
- package/dist/cli/native-assets.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +2 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +15 -1
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +71 -11
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/sparkshell.d.ts +7 -1
- package/dist/cli/sparkshell.d.ts.map +1 -1
- package/dist/cli/sparkshell.js +31 -4
- package/dist/cli/sparkshell.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +1 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +184 -10
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +14 -3
- package/dist/cli/update.js.map +1 -1
- package/dist/compat/__tests__/doctor-contract.test.js +3 -0
- package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
- package/dist/config/__tests__/codex-feature-flags.test.js +11 -1
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -1
- package/dist/config/__tests__/codex-hooks.test.js +19 -8
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/commit-lore-guard.test.d.ts +2 -0
- package/dist/config/__tests__/commit-lore-guard.test.d.ts.map +1 -0
- package/dist/config/__tests__/commit-lore-guard.test.js +20 -0
- package/dist/config/__tests__/commit-lore-guard.test.js.map +1 -0
- package/dist/config/codex-feature-flags.d.ts +4 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -1
- package/dist/config/codex-feature-flags.js +4 -0
- package/dist/config/codex-feature-flags.js.map +1 -1
- package/dist/config/codex-hooks.js +6 -6
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/commit-lore-guard.d.ts +1 -0
- package/dist/config/commit-lore-guard.d.ts.map +1 -1
- package/dist/config/commit-lore-guard.js +29 -3
- package/dist/config/commit-lore-guard.js.map +1 -1
- package/dist/config/generator.d.ts +3 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +114 -10
- package/dist/config/generator.js.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.js +5 -1
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +10 -6
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/best-practice-research-skill.test.d.ts +2 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.js +27 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.js.map +1 -0
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +1 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js +13 -11
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +4 -3
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +15 -3
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +6 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +33 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +4 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +26 -3
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js +29 -14
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +8 -3
- 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 +1 -0
- 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 +3 -2
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +14 -8
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +4 -4
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/resource-leak-watch.test.d.ts +2 -0
- package/dist/hud/__tests__/resource-leak-watch.test.d.ts.map +1 -0
- package/dist/hud/__tests__/resource-leak-watch.test.js +28 -0
- package/dist/hud/__tests__/resource-leak-watch.test.js.map +1 -0
- package/dist/hud/__tests__/tmux.test.js +23 -18
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/index.d.ts +1 -1
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +10 -4
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +9 -8
- package/dist/hud/tmux.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +75 -1
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +3 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +71 -2
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/notifications/__tests__/http-client-resource.test.d.ts +2 -0
- package/dist/notifications/__tests__/http-client-resource.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/http-client-resource.test.js +41 -0
- package/dist/notifications/__tests__/http-client-resource.test.js.map +1 -0
- package/dist/notifications/__tests__/verbosity.test.js +20 -0
- package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
- package/dist/notifications/config.d.ts.map +1 -1
- package/dist/notifications/config.js +6 -3
- package/dist/notifications/config.js.map +1 -1
- package/dist/notifications/http-client.d.ts.map +1 -1
- package/dist/notifications/http-client.js +78 -27
- package/dist/notifications/http-client.js.map +1 -1
- package/dist/notifications/types.d.ts +2 -0
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +49 -1
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts +7 -4
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +32 -69
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +65 -3
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +50 -5
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/index.d.ts +8 -2
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +5 -2
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts +5 -4
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +56 -15
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/stages/code-review.d.ts +2 -2
- package/dist/pipeline/stages/code-review.d.ts.map +1 -1
- package/dist/pipeline/stages/code-review.js +5 -3
- package/dist/pipeline/stages/code-review.js.map +1 -1
- package/dist/pipeline/stages/deep-interview.d.ts +15 -0
- package/dist/pipeline/stages/deep-interview.d.ts.map +1 -0
- package/dist/pipeline/stages/deep-interview.js +32 -0
- package/dist/pipeline/stages/deep-interview.js.map +1 -0
- package/dist/pipeline/stages/ralph-verify.d.ts +5 -5
- package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -1
- package/dist/pipeline/stages/ralph-verify.js +2 -2
- package/dist/pipeline/stages/ralph-verify.js.map +1 -1
- package/dist/pipeline/stages/ultragoal.d.ts +19 -0
- package/dist/pipeline/stages/ultragoal.d.ts.map +1 -0
- package/dist/pipeline/stages/ultragoal.js +38 -0
- package/dist/pipeline/stages/ultragoal.js.map +1 -0
- package/dist/pipeline/stages/ultraqa.d.ts +30 -0
- package/dist/pipeline/stages/ultraqa.d.ts.map +1 -0
- package/dist/pipeline/stages/ultraqa.js +46 -0
- package/dist/pipeline/stages/ultraqa.js.map +1 -0
- package/dist/pipeline/types.d.ts +8 -6
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +2 -2
- package/dist/scripts/__tests__/codex-native-hook.test.js +1488 -117
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-dispatcher.test.js +183 -1
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +27 -2
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +16 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- package/dist/scripts/build-api.d.ts +2 -0
- package/dist/scripts/build-api.d.ts.map +1 -0
- package/dist/scripts/build-api.js +44 -0
- package/dist/scripts/build-api.js.map +1 -0
- package/dist/scripts/cleanup-explore-harness.js +1 -0
- package/dist/scripts/cleanup-explore-harness.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +364 -16
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +98 -25
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-dispatcher.js +88 -0
- package/dist/scripts/notify-dispatcher.js.map +1 -1
- package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
- package/dist/scripts/notify-hook/process-runner.js +39 -17
- package/dist/scripts/notify-hook/process-runner.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +36 -14
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +26 -11
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +2 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +45 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.js +27 -14
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/run-provider-advisor.js +9 -3
- package/dist/scripts/run-provider-advisor.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +4 -1
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +101 -1
- package/dist/scripts/smoke-packed-install.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/scripts/verify-native-agents.js +2 -2
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts +2 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.js +38 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.js.map +1 -0
- package/dist/sidecar/index.d.ts +1 -1
- package/dist/sidecar/index.d.ts.map +1 -1
- package/dist/sidecar/index.js +29 -12
- package/dist/sidecar/index.js.map +1 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js +88 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +11 -0
- package/dist/state/operations.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +2 -2
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +207 -22
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/tmux-session.d.ts +1 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +73 -28
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +714 -10
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +57 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/__tests__/steering-fixtures.d.ts +68 -0
- package/dist/ultragoal/__tests__/steering-fixtures.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.js +259 -0
- package/dist/ultragoal/__tests__/steering-fixtures.js.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.js +65 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.js.map +1 -0
- package/dist/ultragoal/artifacts.d.ts +97 -2
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +811 -256
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/utils/__tests__/sleep-resource.test.d.ts +2 -0
- package/dist/utils/__tests__/sleep-resource.test.d.ts.map +1 -0
- package/dist/utils/__tests__/sleep-resource.test.js +39 -0
- package/dist/utils/__tests__/sleep-resource.test.js.map +1 -0
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js +17 -6
- package/dist/utils/sleep.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +85 -10
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js +1 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
- package/package.json +5 -3
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +4 -3
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +56 -0
- package/plugins/oh-my-codex/hooks/hooks.json +77 -0
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +77 -47
- package/plugins/oh-my-codex/skills/best-practice-research/SKILL.md +83 -0
- package/plugins/oh-my-codex/skills/cancel/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +9 -8
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +22 -11
- package/plugins/oh-my-codex/skills/plan/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +7 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +5 -5
- package/plugins/oh-my-codex/skills/team/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +38 -4
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +1 -1
- package/prompts/planner.md +1 -1
- package/prompts/researcher.md +15 -10
- package/skills/autopilot/SKILL.md +77 -47
- package/skills/best-practice-research/SKILL.md +83 -0
- package/skills/cancel/SKILL.md +2 -2
- package/skills/deep-interview/SKILL.md +9 -8
- package/skills/omx-setup/SKILL.md +1 -1
- package/skills/pipeline/SKILL.md +22 -11
- package/skills/plan/SKILL.md +8 -8
- package/skills/ralph/SKILL.md +7 -0
- package/skills/ralplan/SKILL.md +5 -5
- package/skills/team/SKILL.md +1 -1
- package/skills/ultragoal/SKILL.md +38 -4
- package/skills/ultrawork/SKILL.md +1 -1
- package/src/scripts/__tests__/codex-native-hook.test.ts +1758 -166
- package/src/scripts/__tests__/notify-dispatcher.test.ts +223 -1
- package/src/scripts/__tests__/smoke-packed-install.test.ts +39 -2
- package/src/scripts/__tests__/verify-native-agents.test.ts +21 -1
- package/src/scripts/build-api.ts +48 -0
- package/src/scripts/cleanup-explore-harness.ts +1 -0
- package/src/scripts/codex-native-hook.ts +416 -18
- package/src/scripts/codex-native-pre-post.ts +119 -25
- package/src/scripts/notify-dispatcher.ts +97 -0
- package/src/scripts/notify-hook/process-runner.ts +40 -16
- package/src/scripts/notify-hook/team-dispatch.ts +36 -13
- package/src/scripts/notify-hook/team-leader-nudge.ts +25 -11
- package/src/scripts/notify-hook/team-tmux-guard.ts +49 -0
- package/src/scripts/notify-hook/team-worker-stop.ts +24 -13
- package/src/scripts/run-provider-advisor.ts +11 -3
- package/src/scripts/smoke-packed-install.ts +107 -0
- package/src/scripts/sync-plugin-mirror.ts +3 -3
- package/src/scripts/verify-native-agents.ts +2 -2
- package/templates/catalog-manifest.json +7 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
|
-
import { addUltragoalGoal, buildCodexGoalInstruction, checkpointUltragoal, createUltragoalPlan, isUltragoalDone, readUltragoalPlan, recordFinalReviewBlockers, startNextUltragoal, } from '../artifacts.js';
|
|
6
|
+
import { addUltragoalGoal, buildCodexGoalInstruction, checkpointUltragoal, createUltragoalPlan, isFinalRunCompletionCandidate, isUltragoalDone, readUltragoalPlan, recordFinalReviewBlockers, steerUltragoal, startNextUltragoal, summarizeUltragoalPlan, ULTRAGOAL_AGGREGATE_CODEX_OBJECTIVE, validateUltragoalSteeringProposal, } from '../artifacts.js';
|
|
7
|
+
import { steeringFixtures } from './steering-fixtures.js';
|
|
7
8
|
async function withTempRepo(run) {
|
|
8
9
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-ultragoal-'));
|
|
9
10
|
try {
|
|
@@ -20,6 +21,61 @@ function cleanQualityGate() {
|
|
|
20
21
|
codeReview: { recommendation: 'APPROVE', architectStatus: 'CLEAR', evidence: '$code-review approved with CLEAR architecture' },
|
|
21
22
|
};
|
|
22
23
|
}
|
|
24
|
+
async function writeFixturePlan(cwd, plan) {
|
|
25
|
+
await mkdir(join(cwd, '.omx/ultragoal'), { recursive: true });
|
|
26
|
+
await writeFile(join(cwd, '.omx/ultragoal/brief.md'), 'G001-core-steering-model fixture for .omx/ultragoal steering behavior.\n');
|
|
27
|
+
await writeFile(join(cwd, '.omx/ultragoal/goals.json'), `${JSON.stringify(plan, null, 2)}\n`);
|
|
28
|
+
await writeFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), '');
|
|
29
|
+
}
|
|
30
|
+
function asChildGoals(after) {
|
|
31
|
+
if (!Array.isArray(after))
|
|
32
|
+
return undefined;
|
|
33
|
+
return after.map((item) => {
|
|
34
|
+
assert.equal(typeof item, 'object');
|
|
35
|
+
assert.notEqual(item, null);
|
|
36
|
+
const candidate = item;
|
|
37
|
+
assert.equal(typeof candidate.title, 'string');
|
|
38
|
+
assert.equal(typeof candidate.objective, 'string');
|
|
39
|
+
return { title: String(candidate.title), objective: String(candidate.objective) };
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function toSteeringProposal(proposal) {
|
|
43
|
+
const common = {
|
|
44
|
+
kind: proposal.kind,
|
|
45
|
+
source: proposal.source,
|
|
46
|
+
targetGoalIds: proposal.targetGoalIds,
|
|
47
|
+
evidence: proposal.evidence,
|
|
48
|
+
rationale: proposal.rationale,
|
|
49
|
+
idempotencyKey: proposal.idempotencyKey,
|
|
50
|
+
};
|
|
51
|
+
switch (proposal.kind) {
|
|
52
|
+
case 'add_subgoal':
|
|
53
|
+
return { ...common, title: proposal.title, objective: proposal.objective };
|
|
54
|
+
case 'split_subgoal':
|
|
55
|
+
return { ...common, childGoals: asChildGoals(proposal.after) };
|
|
56
|
+
case 'reorder_pending':
|
|
57
|
+
assert.ok(Array.isArray(proposal.after));
|
|
58
|
+
return { ...common, pendingOrder: proposal.after };
|
|
59
|
+
case 'revise_pending_wording':
|
|
60
|
+
return {
|
|
61
|
+
...common,
|
|
62
|
+
objective: proposal.objective,
|
|
63
|
+
directiveText: proposal.forbidden ? 'attempt to skip verification, weaken quality gates, and auto-complete protected aggregate state' : undefined,
|
|
64
|
+
revisedTitle: proposal.title,
|
|
65
|
+
revisedObjective: proposal.objective,
|
|
66
|
+
};
|
|
67
|
+
case 'annotate_ledger':
|
|
68
|
+
return common;
|
|
69
|
+
case 'mark_blocked_superseded': {
|
|
70
|
+
const childGoals = asChildGoals(proposal.after);
|
|
71
|
+
return {
|
|
72
|
+
...common,
|
|
73
|
+
childGoals,
|
|
74
|
+
blockedReason: childGoals ? undefined : 'Evidence-backed blocker has no safe replacement yet.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
23
79
|
describe('ultragoal artifacts', () => {
|
|
24
80
|
it('creates brief, goals, and ledger artifacts from a brief', async () => {
|
|
25
81
|
await withTempRepo(async (cwd) => {
|
|
@@ -29,8 +85,8 @@ describe('ultragoal artifacts', () => {
|
|
|
29
85
|
});
|
|
30
86
|
assert.equal(plan.goals.length, 3);
|
|
31
87
|
assert.equal(plan.codexGoalMode, 'aggregate');
|
|
32
|
-
assert.
|
|
33
|
-
assert.
|
|
88
|
+
assert.equal(plan.codexObjective, ULTRAGOAL_AGGREGATE_CODEX_OBJECTIVE);
|
|
89
|
+
assert.doesNotMatch(plan.codexObjective ?? '', /G001-build-the-cli/);
|
|
34
90
|
assert.equal(plan.goals[0]?.id, 'G001-build-the-cli');
|
|
35
91
|
assert.equal(plan.goals[0]?.status, 'pending');
|
|
36
92
|
assert.equal(await readFile(join(cwd, '.omx/ultragoal/brief.md'), 'utf-8'), '- Build the CLI\n- Add tests\n- Write docs\n');
|
|
@@ -60,11 +116,14 @@ describe('ultragoal artifacts', () => {
|
|
|
60
116
|
assert.match(instruction, /Codex goal = the whole ultragoal run/i);
|
|
61
117
|
assert.match(instruction, /same aggregate objective as active/i);
|
|
62
118
|
assert.match(instruction, /do not call update_goal yet/i);
|
|
63
|
-
assert.doesNotMatch(instruction, /fresh Codex thread/i);
|
|
64
119
|
assert.match(instruction, /--codex-goal-json/);
|
|
65
|
-
assert.match(instruction, /Complete
|
|
120
|
+
assert.match(instruction, /Complete the durable ultragoal plan/);
|
|
121
|
+
assert.match(instruction, /including later accepted\/appended stories/);
|
|
122
|
+
assert.match(instruction, /\.omx\/ultragoal\/ledger\.jsonl/);
|
|
66
123
|
assert.match(instruction, /Complete first milestone/);
|
|
67
|
-
assert.
|
|
124
|
+
assert.match(instruction, /does not call \/goal clear/);
|
|
125
|
+
assert.match(instruction, /manually run \/goal clear/);
|
|
126
|
+
assert.doesNotMatch(instruction, /fresh (?:Codex )?(?:thread|session)s?/i);
|
|
68
127
|
assert.doesNotMatch(instruction, /\.\.\/\.\.\/codex/);
|
|
69
128
|
assert.doesNotMatch(instruction, /`codex\s+goal\b/i);
|
|
70
129
|
});
|
|
@@ -259,7 +318,8 @@ describe('ultragoal artifacts', () => {
|
|
|
259
318
|
const first = await startNextUltragoal(cwd);
|
|
260
319
|
const instruction = buildCodexGoalInstruction(first.goal, first.plan);
|
|
261
320
|
assert.match(instruction, /Ultragoal active-goal handoff/);
|
|
262
|
-
assert.match(instruction, /
|
|
321
|
+
assert.match(instruction, /Codex goal context/);
|
|
322
|
+
assert.doesNotMatch(instruction, /fresh (?:Codex )?(?:thread|session)s?/i);
|
|
263
323
|
await checkpointUltragoal(cwd, {
|
|
264
324
|
goalId: first.goal.id,
|
|
265
325
|
status: 'complete',
|
|
@@ -278,6 +338,7 @@ describe('ultragoal artifacts', () => {
|
|
|
278
338
|
goals: [{ title: 'First', objective: 'Complete first milestone.' }],
|
|
279
339
|
});
|
|
280
340
|
const objective = plan.codexObjective;
|
|
341
|
+
assert.equal(objective, ULTRAGOAL_AGGREGATE_CODEX_OBJECTIVE);
|
|
281
342
|
const added = await addUltragoalGoal(cwd, {
|
|
282
343
|
title: 'Resolve final code-review blockers',
|
|
283
344
|
objective: 'Fix review blockers and rerun final gates.',
|
|
@@ -286,10 +347,121 @@ describe('ultragoal artifacts', () => {
|
|
|
286
347
|
assert.equal(added.goal.id, 'G002-resolve-final-code-review-blockers');
|
|
287
348
|
assert.equal(added.goal.status, 'pending');
|
|
288
349
|
assert.equal(added.plan.codexObjective, objective);
|
|
350
|
+
assert.doesNotMatch(added.plan.codexObjective ?? '', /G002-resolve-final-code-review-blockers/);
|
|
289
351
|
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
290
352
|
assert.match(ledger, /"event":"goal_added"/);
|
|
291
353
|
});
|
|
292
354
|
});
|
|
355
|
+
it('migrates legacy enumerated aggregate objectives to the pointer contract', async () => {
|
|
356
|
+
await withTempRepo(async (cwd) => {
|
|
357
|
+
await mkdir(join(cwd, '.omx/ultragoal'), { recursive: true });
|
|
358
|
+
const legacyObjective = 'Complete all ultragoal stories in .omx/ultragoal/goals.json: G001-first First; G002-second Second';
|
|
359
|
+
await writeFile(join(cwd, '.omx/ultragoal/goals.json'), `${JSON.stringify({
|
|
360
|
+
version: 1,
|
|
361
|
+
createdAt: '2026-05-04T10:00:00.000Z',
|
|
362
|
+
updatedAt: '2026-05-04T10:00:00.000Z',
|
|
363
|
+
briefPath: '.omx/ultragoal/brief.md',
|
|
364
|
+
goalsPath: '.omx/ultragoal/goals.json',
|
|
365
|
+
ledgerPath: '.omx/ultragoal/ledger.jsonl',
|
|
366
|
+
codexGoalMode: 'aggregate',
|
|
367
|
+
codexObjective: legacyObjective,
|
|
368
|
+
goals: [
|
|
369
|
+
{ id: 'G001-first', title: 'First', objective: 'Complete first.', status: 'pending', attempt: 0, createdAt: '2026-05-04T10:00:00.000Z', updatedAt: '2026-05-04T10:00:00.000Z' },
|
|
370
|
+
{ id: 'G002-second', title: 'Second', objective: 'Complete second.', status: 'pending', attempt: 0, createdAt: '2026-05-04T10:00:00.000Z', updatedAt: '2026-05-04T10:00:00.000Z' },
|
|
371
|
+
],
|
|
372
|
+
}, null, 2)}\n`);
|
|
373
|
+
await writeFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), '');
|
|
374
|
+
const plan = await readUltragoalPlan(cwd);
|
|
375
|
+
assert.equal(plan.codexObjective, ULTRAGOAL_AGGREGATE_CODEX_OBJECTIVE);
|
|
376
|
+
assert.deepEqual(plan.codexObjectiveAliases, [legacyObjective]);
|
|
377
|
+
assert.doesNotMatch(plan.codexObjective ?? '', /G001-first/);
|
|
378
|
+
const persisted = JSON.parse(await readFile(join(cwd, '.omx/ultragoal/goals.json'), 'utf-8'));
|
|
379
|
+
assert.equal(persisted.codexObjective, ULTRAGOAL_AGGREGATE_CODEX_OBJECTIVE);
|
|
380
|
+
assert.deepEqual(persisted.codexObjectiveAliases, [legacyObjective]);
|
|
381
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
382
|
+
assert.match(ledger, /"event":"aggregate_objective_migrated"/);
|
|
383
|
+
assert.match(ledger, /legacy enumerated aggregate Codex objective/);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
it('accepts migrated legacy aggregate objective aliases for active Codex snapshots', async () => {
|
|
387
|
+
await withTempRepo(async (cwd) => {
|
|
388
|
+
const legacyObjective = 'Complete all ultragoal stories in .omx/ultragoal/goals.json: G001-first First; G002-second Second';
|
|
389
|
+
await createUltragoalPlan(cwd, {
|
|
390
|
+
brief: 'brief',
|
|
391
|
+
goals: [
|
|
392
|
+
{ title: 'First', objective: 'Complete first.' },
|
|
393
|
+
{ title: 'Second', objective: 'Complete second.' },
|
|
394
|
+
],
|
|
395
|
+
});
|
|
396
|
+
const planPath = join(cwd, '.omx/ultragoal/goals.json');
|
|
397
|
+
const legacyPlan = JSON.parse(await readFile(planPath, 'utf-8'));
|
|
398
|
+
legacyPlan.codexObjective = legacyObjective;
|
|
399
|
+
await writeFile(planPath, `${JSON.stringify(legacyPlan, null, 2)}\n`);
|
|
400
|
+
const first = await startNextUltragoal(cwd);
|
|
401
|
+
const checkpointed = await checkpointUltragoal(cwd, {
|
|
402
|
+
goalId: first.goal.id,
|
|
403
|
+
status: 'complete',
|
|
404
|
+
evidence: 'legacy active Codex objective alias still represents the migrated aggregate run.',
|
|
405
|
+
codexGoal: { goal: { objective: legacyObjective, status: 'active' } },
|
|
406
|
+
});
|
|
407
|
+
assert.equal(checkpointed.goals[0]?.status, 'complete');
|
|
408
|
+
assert.equal(checkpointed.codexObjective, ULTRAGOAL_AGGREGATE_CODEX_OBJECTIVE);
|
|
409
|
+
assert.deepEqual(checkpointed.codexObjectiveAliases, [legacyObjective]);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
it('applies steering idempotently and keeps split replacements schedulable', async () => {
|
|
413
|
+
await withTempRepo(async (cwd) => {
|
|
414
|
+
await createUltragoalPlan(cwd, {
|
|
415
|
+
brief: 'brief',
|
|
416
|
+
goals: [
|
|
417
|
+
{ title: 'Core steering model', objective: 'Implement bounded dynamic steering.' },
|
|
418
|
+
{ title: 'CLI bridge', objective: 'Expose structured steering through the CLI.' },
|
|
419
|
+
{ title: 'Hook bridge', objective: 'Bridge explicit steering directives.' },
|
|
420
|
+
],
|
|
421
|
+
});
|
|
422
|
+
const firstSteer = await steerUltragoal(cwd, {
|
|
423
|
+
kind: 'split_subgoal',
|
|
424
|
+
source: 'finding',
|
|
425
|
+
targetGoalIds: ['G001-core-steering-model'],
|
|
426
|
+
childGoals: [
|
|
427
|
+
{ title: 'Core steering schema', objective: 'Add steering proposal and audit schema.' },
|
|
428
|
+
{ title: 'Core steering scheduler semantics', objective: 'Make superseded and blocked metadata affect scheduling and completion.' },
|
|
429
|
+
],
|
|
430
|
+
evidence: 'Implementation findings show schema and scheduler invariants should be isolated.',
|
|
431
|
+
rationale: 'Splitting reduces coupling without deleting or weakening the original goal.',
|
|
432
|
+
idempotencyKey: 'steering-idempotency-check',
|
|
433
|
+
});
|
|
434
|
+
assert.equal(firstSteer.accepted, true);
|
|
435
|
+
assert.equal(firstSteer.deduped, false);
|
|
436
|
+
assert.equal(firstSteer.plan.goals.find((goal) => goal.id === 'G001-core-steering-model')?.steeringStatus, 'superseded');
|
|
437
|
+
assert.equal(firstSteer.plan.goals.find((goal) => goal.id === 'G004-core-steering-schema')?.supersedes?.[0], 'G001-core-steering-model');
|
|
438
|
+
assert.equal(firstSteer.plan.goals.find((goal) => goal.id === 'G005-core-steering-scheduler-semantics')?.supersedes?.[0], 'G001-core-steering-model');
|
|
439
|
+
assert.equal(firstSteer.plan.goals.filter((goal) => goal.steeringStatus === 'superseded').length, 1);
|
|
440
|
+
assert.equal(isUltragoalDone(firstSteer.plan), false);
|
|
441
|
+
const started = await startNextUltragoal(cwd);
|
|
442
|
+
assert.equal(started.goal?.id, 'G004-core-steering-schema');
|
|
443
|
+
assert.equal(started.goal?.status, 'in_progress');
|
|
444
|
+
assert.equal(started.resumed, false);
|
|
445
|
+
const secondSteer = await steerUltragoal(cwd, {
|
|
446
|
+
kind: 'split_subgoal',
|
|
447
|
+
source: 'finding',
|
|
448
|
+
targetGoalIds: ['G001-core-steering-model'],
|
|
449
|
+
childGoals: [
|
|
450
|
+
{ title: 'Core steering schema', objective: 'Add steering proposal and audit schema.' },
|
|
451
|
+
{ title: 'Core steering scheduler semantics', objective: 'Make superseded and blocked metadata affect scheduling and completion.' },
|
|
452
|
+
],
|
|
453
|
+
evidence: 'Implementation findings show schema and scheduler invariants should be isolated.',
|
|
454
|
+
rationale: 'Splitting reduces coupling without deleting or weakening the original goal.',
|
|
455
|
+
idempotencyKey: 'steering-idempotency-check',
|
|
456
|
+
});
|
|
457
|
+
assert.equal(secondSteer.accepted, true);
|
|
458
|
+
assert.equal(secondSteer.deduped, true);
|
|
459
|
+
assert.equal(secondSteer.plan.goals.filter((goal) => goal.id === 'G004-core-steering-schema').length, 1);
|
|
460
|
+
assert.equal(secondSteer.plan.goals.filter((goal) => goal.id === 'G005-core-steering-scheduler-semantics').length, 1);
|
|
461
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
462
|
+
assert.equal((ledger.match(/"event":"steering_accepted"/g) ?? []).length, 1);
|
|
463
|
+
});
|
|
464
|
+
});
|
|
293
465
|
it('records final aggregate review blockers atomically and starts the blocker next', async () => {
|
|
294
466
|
await withTempRepo(async (cwd) => {
|
|
295
467
|
await createUltragoalPlan(cwd, {
|
|
@@ -411,7 +583,404 @@ describe('ultragoal artifacts', () => {
|
|
|
411
583
|
assert.match(ledger, /completed aggregate Codex goal blocks create_goal/);
|
|
412
584
|
});
|
|
413
585
|
});
|
|
414
|
-
it('
|
|
586
|
+
it('accepts core steering mutations and writes structured audit entries', async () => {
|
|
587
|
+
await withTempRepo(async (cwd) => {
|
|
588
|
+
await createUltragoalPlan(cwd, {
|
|
589
|
+
brief: 'brief',
|
|
590
|
+
goals: [
|
|
591
|
+
{ title: 'First', objective: 'Complete first milestone with tests.' },
|
|
592
|
+
{ title: 'Second', objective: 'Complete second milestone with tests.' },
|
|
593
|
+
],
|
|
594
|
+
});
|
|
595
|
+
const added = await steerUltragoal(cwd, {
|
|
596
|
+
kind: 'add_subgoal',
|
|
597
|
+
source: 'cli',
|
|
598
|
+
evidence: 'Code review found missing migration coverage.',
|
|
599
|
+
rationale: 'Add a bounded follow-up without weakening the aggregate objective.',
|
|
600
|
+
title: 'Add migration regression test',
|
|
601
|
+
objective: 'Add migration regression coverage and keep all existing quality gates.',
|
|
602
|
+
idempotencyKey: 'add-migration-test',
|
|
603
|
+
}, { now: new Date('2026-05-04T10:10:00Z') });
|
|
604
|
+
assert.equal(added.accepted, true);
|
|
605
|
+
assert.equal(added.plan.goals.at(-1)?.id, 'G003-add-migration-regression-test');
|
|
606
|
+
assert.equal(added.audit.before.goals.length, 2);
|
|
607
|
+
assert.equal(added.audit.after.id, 'G003-add-migration-regression-test');
|
|
608
|
+
const split = await steerUltragoal(cwd, {
|
|
609
|
+
kind: 'split_subgoal',
|
|
610
|
+
source: 'finding',
|
|
611
|
+
targetGoalIds: ['G002-second'],
|
|
612
|
+
evidence: 'Implementation evidence shows the second milestone has two independent safety checks.',
|
|
613
|
+
rationale: 'Split the pending work into narrower goals while preserving verification burden.',
|
|
614
|
+
childGoals: [
|
|
615
|
+
{ title: 'Second parser coverage', objective: 'Complete parser coverage for the second milestone with tests.' },
|
|
616
|
+
{ title: 'Second CLI coverage', objective: 'Complete CLI coverage for the second milestone with tests.' },
|
|
617
|
+
],
|
|
618
|
+
}, { now: new Date('2026-05-04T10:11:00Z') });
|
|
619
|
+
assert.equal(split.accepted, true);
|
|
620
|
+
const superseded = split.plan.goals.find((goal) => goal.id === 'G002-second');
|
|
621
|
+
assert.equal(superseded?.steeringStatus, 'superseded');
|
|
622
|
+
assert.deepEqual(superseded?.supersededBy, ['G004-second-parser-coverage', 'G005-second-cli-coverage']);
|
|
623
|
+
assert.equal(split.plan.goals.find((goal) => goal.id === 'G004-second-parser-coverage')?.supersedes?.[0], 'G002-second');
|
|
624
|
+
const revised = await steerUltragoal(cwd, {
|
|
625
|
+
kind: 'revise_pending_wording',
|
|
626
|
+
source: 'user_prompt_submit',
|
|
627
|
+
targetGoalIds: ['G003-add-migration-regression-test'],
|
|
628
|
+
evidence: 'Prompt-submit clarified the regression target after the goal was added.',
|
|
629
|
+
rationale: 'Clarify wording only; do not change acceptance or verification gates.',
|
|
630
|
+
revisedTitle: 'Add ledger migration regression test',
|
|
631
|
+
revisedObjective: 'Add ledger migration regression coverage and keep all existing quality gates.',
|
|
632
|
+
promptSignature: 'prompt-1',
|
|
633
|
+
}, { now: new Date('2026-05-04T10:12:00Z') });
|
|
634
|
+
assert.equal(revised.accepted, true);
|
|
635
|
+
assert.equal(revised.plan.goals.find((goal) => goal.id === 'G003-add-migration-regression-test')?.title, 'Add ledger migration regression test');
|
|
636
|
+
const reordered = await steerUltragoal(cwd, {
|
|
637
|
+
kind: 'reorder_pending',
|
|
638
|
+
source: 'cli',
|
|
639
|
+
evidence: 'Dependency analysis shows parser coverage should run before the original first milestone.',
|
|
640
|
+
rationale: 'Reorder pending stories only; status and quality gates are unchanged.',
|
|
641
|
+
pendingOrder: ['G004-second-parser-coverage', 'G001-first'],
|
|
642
|
+
}, { now: new Date('2026-05-04T10:13:00Z') });
|
|
643
|
+
assert.equal(reordered.accepted, true);
|
|
644
|
+
const next = await startNextUltragoal(cwd, { now: new Date('2026-05-04T10:14:00Z') });
|
|
645
|
+
assert.equal(next.goal?.id, 'G004-second-parser-coverage');
|
|
646
|
+
const annotated = await steerUltragoal(cwd, {
|
|
647
|
+
kind: 'annotate_ledger',
|
|
648
|
+
source: 'finding',
|
|
649
|
+
evidence: 'A reviewer recorded why parser coverage was scheduled first.',
|
|
650
|
+
rationale: 'Audit-only annotation; no plan fields should change.',
|
|
651
|
+
}, { now: new Date('2026-05-04T10:15:00Z') });
|
|
652
|
+
assert.equal(annotated.accepted, true);
|
|
653
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
654
|
+
assert.equal((ledger.match(/"event":"steering_accepted"/g) ?? []).length, 5);
|
|
655
|
+
assert.match(ledger, /"kind":"add_subgoal"/);
|
|
656
|
+
assert.match(ledger, /"kind":"split_subgoal"/);
|
|
657
|
+
assert.match(ledger, /"kind":"annotate_ledger"/);
|
|
658
|
+
assert.match(ledger, /"invariant":/);
|
|
659
|
+
});
|
|
660
|
+
});
|
|
661
|
+
it('rejects weakening steering and records rejected audit evidence', async () => {
|
|
662
|
+
await withTempRepo(async (cwd) => {
|
|
663
|
+
const plan = await createUltragoalPlan(cwd, {
|
|
664
|
+
brief: 'brief',
|
|
665
|
+
goals: [{ title: 'First', objective: 'Complete first milestone with tests.' }],
|
|
666
|
+
});
|
|
667
|
+
const invariant = validateUltragoalSteeringProposal(plan, {
|
|
668
|
+
kind: 'revise_pending_wording',
|
|
669
|
+
source: 'user_prompt_submit',
|
|
670
|
+
targetGoalIds: ['G001-first'],
|
|
671
|
+
evidence: 'User asked to skip tests.',
|
|
672
|
+
rationale: 'Skip verification and mark complete faster.',
|
|
673
|
+
revisedObjective: 'Complete first milestone but skip tests and review.',
|
|
674
|
+
});
|
|
675
|
+
assert.equal(invariant.accepted, false);
|
|
676
|
+
assert.equal(invariant.noEasierCompletion, false);
|
|
677
|
+
const rejected = await steerUltragoal(cwd, {
|
|
678
|
+
kind: 'revise_pending_wording',
|
|
679
|
+
source: 'user_prompt_submit',
|
|
680
|
+
targetGoalIds: ['G001-first'],
|
|
681
|
+
evidence: 'User asked to skip tests.',
|
|
682
|
+
rationale: 'Skip verification and mark complete faster.',
|
|
683
|
+
revisedObjective: 'Complete first milestone but skip tests and review.',
|
|
684
|
+
});
|
|
685
|
+
assert.equal(rejected.accepted, false);
|
|
686
|
+
assert.match(rejected.rejectedReasons.join('\n'), /weaken completion|quality gates|tests|reviews/);
|
|
687
|
+
const unchanged = await readUltragoalPlan(cwd);
|
|
688
|
+
assert.equal(unchanged.goals[0]?.objective, 'Complete first milestone with tests.');
|
|
689
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
690
|
+
assert.match(ledger, /"event":"steering_rejected"/);
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
it('rejects unknown steering mutation kinds before audit acceptance', async () => {
|
|
694
|
+
await withTempRepo(async (cwd) => {
|
|
695
|
+
const plan = await createUltragoalPlan(cwd, {
|
|
696
|
+
brief: 'brief',
|
|
697
|
+
goals: [{ title: 'First', objective: 'Complete first milestone with tests.' }],
|
|
698
|
+
});
|
|
699
|
+
const proposal = {
|
|
700
|
+
kind: 'make_goal_easier',
|
|
701
|
+
source: 'cli',
|
|
702
|
+
evidence: 'A stale proposal path supplied a non-allowlisted mutation kind.',
|
|
703
|
+
rationale: 'The core validator must fail closed even if the CLI parser is bypassed.',
|
|
704
|
+
};
|
|
705
|
+
const invariant = validateUltragoalSteeringProposal(plan, proposal);
|
|
706
|
+
assert.equal(invariant.accepted, false);
|
|
707
|
+
assert.match(invariant.rejectedReasons.join('\n'), /Invalid steering mutation kind/);
|
|
708
|
+
const rejected = await steerUltragoal(cwd, proposal);
|
|
709
|
+
assert.equal(rejected.accepted, false);
|
|
710
|
+
assert.match(rejected.rejectedReasons.join('\n'), /Invalid steering mutation kind/);
|
|
711
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
712
|
+
assert.match(ledger, /"event":"steering_rejected"/);
|
|
713
|
+
assert.doesNotMatch(ledger, /"event":"steering_accepted"/);
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
it('dedupes steering by ledger idempotency key without duplicating child goals', async () => {
|
|
717
|
+
await withTempRepo(async (cwd) => {
|
|
718
|
+
await createUltragoalPlan(cwd, {
|
|
719
|
+
brief: 'brief',
|
|
720
|
+
goals: [{ title: 'First', objective: 'Complete first milestone with tests.' }],
|
|
721
|
+
});
|
|
722
|
+
const proposal = {
|
|
723
|
+
kind: 'add_subgoal',
|
|
724
|
+
source: 'user_prompt_submit',
|
|
725
|
+
evidence: 'Prompt-submit requested a bounded regression goal.',
|
|
726
|
+
rationale: 'Add scoped regression work while preserving the end goal.',
|
|
727
|
+
title: 'Add regression',
|
|
728
|
+
objective: 'Add regression coverage with the same verification gates.',
|
|
729
|
+
idempotencyKey: 'same-prompt-signature',
|
|
730
|
+
};
|
|
731
|
+
const first = await steerUltragoal(cwd, proposal);
|
|
732
|
+
const firstPlan = await readUltragoalPlan(cwd);
|
|
733
|
+
const second = await steerUltragoal(cwd, proposal);
|
|
734
|
+
const secondPlan = await readUltragoalPlan(cwd);
|
|
735
|
+
assert.equal(first.accepted, true);
|
|
736
|
+
assert.equal(first.deduped, false);
|
|
737
|
+
assert.equal(second.accepted, true);
|
|
738
|
+
assert.equal(second.deduped, true);
|
|
739
|
+
assert.equal(second.plan.goals.filter((goal) => goal.title === 'Add regression').length, 1);
|
|
740
|
+
assert.deepEqual(secondPlan, firstPlan);
|
|
741
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
742
|
+
assert.equal((ledger.match(/"event":"steering_accepted"/g) ?? []).length, 1);
|
|
743
|
+
assert.equal((ledger.match(/"event":"steering_rejected"/g) ?? []).length, 0);
|
|
744
|
+
assert.equal((ledger.match(/same-prompt-signature/g) ?? []).length, 1);
|
|
745
|
+
});
|
|
746
|
+
});
|
|
747
|
+
it('skips superseded and blocked goals for scheduling while blocked goals prevent completion', async () => {
|
|
748
|
+
await withTempRepo(async (cwd) => {
|
|
749
|
+
await createUltragoalPlan(cwd, {
|
|
750
|
+
brief: 'brief',
|
|
751
|
+
goals: [
|
|
752
|
+
{ title: 'First', objective: 'Complete first milestone with tests.' },
|
|
753
|
+
{ title: 'Second', objective: 'Complete second milestone with tests.' },
|
|
754
|
+
{ title: 'Third', objective: 'Complete third milestone with tests.' },
|
|
755
|
+
],
|
|
756
|
+
});
|
|
757
|
+
await steerUltragoal(cwd, {
|
|
758
|
+
kind: 'mark_blocked_superseded',
|
|
759
|
+
source: 'finding',
|
|
760
|
+
targetGoalIds: ['G001-first'],
|
|
761
|
+
evidence: 'External API access is unavailable.',
|
|
762
|
+
rationale: 'Block unschedulable work without claiming completion.',
|
|
763
|
+
blockedReason: 'Waiting on external API access.',
|
|
764
|
+
});
|
|
765
|
+
await steerUltragoal(cwd, {
|
|
766
|
+
kind: 'mark_blocked_superseded',
|
|
767
|
+
source: 'finding',
|
|
768
|
+
targetGoalIds: ['G002-second'],
|
|
769
|
+
evidence: 'Second milestone is better represented as replacement child work.',
|
|
770
|
+
rationale: 'Supersede with a replacement goal that preserves the acceptance criteria.',
|
|
771
|
+
childGoals: [{ title: 'Replacement second', objective: 'Complete replacement second milestone with tests.' }],
|
|
772
|
+
});
|
|
773
|
+
const next = await startNextUltragoal(cwd);
|
|
774
|
+
assert.equal(next.goal?.id, 'G004-replacement-second');
|
|
775
|
+
const plan = await readUltragoalPlan(cwd);
|
|
776
|
+
assert.equal(isUltragoalDone(plan), false);
|
|
777
|
+
const summary = summarizeUltragoalPlan(plan);
|
|
778
|
+
assert.equal(summary.steeringBlocked, 1);
|
|
779
|
+
assert.equal(summary.superseded, 1);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
it('clears the active goal when mark_blocked_superseded supersedes the running goal', async () => {
|
|
783
|
+
await withTempRepo(async (cwd) => {
|
|
784
|
+
await createUltragoalPlan(cwd, {
|
|
785
|
+
brief: 'brief',
|
|
786
|
+
goals: [
|
|
787
|
+
{ title: 'First', objective: 'Complete first milestone with tests.' },
|
|
788
|
+
{ title: 'Second', objective: 'Complete second milestone with tests.' },
|
|
789
|
+
],
|
|
790
|
+
});
|
|
791
|
+
const started = await startNextUltragoal(cwd);
|
|
792
|
+
assert.equal(started.goal?.id, 'G001-first');
|
|
793
|
+
const result = await steerUltragoal(cwd, {
|
|
794
|
+
kind: 'mark_blocked_superseded',
|
|
795
|
+
source: 'finding',
|
|
796
|
+
targetGoalIds: ['G001-first'],
|
|
797
|
+
evidence: 'The active goal should be split into narrower replacement work.',
|
|
798
|
+
rationale: 'Supersede the active goal and keep the audit trail durable.',
|
|
799
|
+
childGoals: [
|
|
800
|
+
{ title: 'Replacement first part A', objective: 'Complete replacement first part A with tests.' },
|
|
801
|
+
{ title: 'Replacement first part B', objective: 'Complete replacement first part B with tests.' },
|
|
802
|
+
],
|
|
803
|
+
});
|
|
804
|
+
assert.equal(result.accepted, true);
|
|
805
|
+
assert.equal(result.plan.activeGoalId, undefined);
|
|
806
|
+
assert.equal(result.plan.goals.find((goal) => goal.id === 'G001-first')?.steeringStatus, 'superseded');
|
|
807
|
+
assert.deepEqual(result.plan.goals.filter((goal) => goal.supersedes?.includes('G001-first')).map((goal) => goal.status), ['pending', 'pending']);
|
|
808
|
+
const summary = summarizeUltragoalPlan(result.plan);
|
|
809
|
+
assert.equal(summary.superseded, 1);
|
|
810
|
+
assert.equal(summary.steeringBlocked, 0);
|
|
811
|
+
assert.equal(isUltragoalDone(result.plan), false);
|
|
812
|
+
});
|
|
813
|
+
});
|
|
814
|
+
it('rejects malformed steering invariants and records a single rejection audit', async () => {
|
|
815
|
+
await withTempRepo(async (cwd) => {
|
|
816
|
+
await createUltragoalPlan(cwd, {
|
|
817
|
+
brief: 'brief',
|
|
818
|
+
goals: [
|
|
819
|
+
{ title: 'First', objective: 'Complete first milestone with tests.' },
|
|
820
|
+
{ title: 'Second', objective: 'Complete second milestone with tests.' },
|
|
821
|
+
],
|
|
822
|
+
});
|
|
823
|
+
const plan = await readUltragoalPlan(cwd);
|
|
824
|
+
const invariant = validateUltragoalSteeringProposal(plan, {
|
|
825
|
+
kind: 'reorder_pending',
|
|
826
|
+
source: 'user_prompt_submit',
|
|
827
|
+
evidence: 'Order request from prompt submit.',
|
|
828
|
+
rationale: 'Exercise duplicate pending-order validation.',
|
|
829
|
+
pendingOrder: ['G001-first', 'G001-first'],
|
|
830
|
+
});
|
|
831
|
+
assert.equal(invariant.accepted, false);
|
|
832
|
+
assert.equal(invariant.structuralInvariantAccepted, false);
|
|
833
|
+
assert.match(invariant.rejectedReasons.join(' | '), /duplicate goal id/);
|
|
834
|
+
const rejected = await steerUltragoal(cwd, {
|
|
835
|
+
kind: 'reorder_pending',
|
|
836
|
+
source: 'user_prompt_submit',
|
|
837
|
+
evidence: 'Order request from prompt submit.',
|
|
838
|
+
rationale: 'Exercise duplicate pending-order validation.',
|
|
839
|
+
pendingOrder: ['G001-first', 'G001-first'],
|
|
840
|
+
});
|
|
841
|
+
assert.equal(rejected.accepted, false);
|
|
842
|
+
assert.equal(rejected.deduped, false);
|
|
843
|
+
assert.match(rejected.rejectedReasons.join(' | '), /duplicate goal id/);
|
|
844
|
+
assert.deepEqual(await readUltragoalPlan(cwd), plan);
|
|
845
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
846
|
+
assert.equal((ledger.match(/"event":"steering_rejected"/g) ?? []).length, 1);
|
|
847
|
+
assert.equal((ledger.match(/"event":"steering_accepted"/g) ?? []).length, 0);
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
it('rejects invalid steering source and malformed superseded replacement children with audit evidence', async () => {
|
|
851
|
+
await withTempRepo(async (cwd) => {
|
|
852
|
+
await createUltragoalPlan(cwd, {
|
|
853
|
+
brief: 'brief',
|
|
854
|
+
goals: [{ title: 'First', objective: 'Complete first milestone with tests.' }],
|
|
855
|
+
});
|
|
856
|
+
const invalidSource = await steerUltragoal(cwd, {
|
|
857
|
+
kind: 'annotate_ledger',
|
|
858
|
+
source: 'forged',
|
|
859
|
+
evidence: 'Invalid source must not be accepted.',
|
|
860
|
+
rationale: 'Runtime validation should protect JSON callers.',
|
|
861
|
+
});
|
|
862
|
+
assert.equal(invalidSource.accepted, false);
|
|
863
|
+
assert.match(invalidSource.rejectedReasons.join(' | '), /Invalid steering source/);
|
|
864
|
+
const malformedReplacement = await steerUltragoal(cwd, {
|
|
865
|
+
kind: 'mark_blocked_superseded',
|
|
866
|
+
source: 'finding',
|
|
867
|
+
targetGoalIds: ['G001-first'],
|
|
868
|
+
evidence: 'Replacement child is malformed.',
|
|
869
|
+
rationale: 'Malformed children should be rejected and audited instead of throwing.',
|
|
870
|
+
childGoals: [{ title: '', objective: 'Replacement objective.' }],
|
|
871
|
+
});
|
|
872
|
+
assert.equal(malformedReplacement.accepted, false);
|
|
873
|
+
assert.match(malformedReplacement.rejectedReasons.join(' | '), /replacement children require title and objective/);
|
|
874
|
+
const nullReplacement = await steerUltragoal(cwd, {
|
|
875
|
+
kind: 'mark_blocked_superseded',
|
|
876
|
+
source: 'finding',
|
|
877
|
+
targetGoalIds: ['G001-first'],
|
|
878
|
+
evidence: 'Replacement child is null.',
|
|
879
|
+
rationale: 'Malformed JSON children should reject without throwing.',
|
|
880
|
+
childGoals: [null],
|
|
881
|
+
});
|
|
882
|
+
assert.equal(nullReplacement.accepted, false);
|
|
883
|
+
assert.match(nullReplacement.rejectedReasons.join(' | '), /replacement children require title and objective/);
|
|
884
|
+
const weakenedSplitChild = await steerUltragoal(cwd, {
|
|
885
|
+
kind: 'split_subgoal',
|
|
886
|
+
source: 'finding',
|
|
887
|
+
targetGoalId: 'G001-first',
|
|
888
|
+
evidence: 'Split child attempted to weaken tests.',
|
|
889
|
+
rationale: 'Replacement objectives must preserve verification.',
|
|
890
|
+
childGoals: [
|
|
891
|
+
{ title: 'Shortcut child', objective: 'Skip tests and remove verification for faster completion.' },
|
|
892
|
+
],
|
|
893
|
+
});
|
|
894
|
+
assert.equal(weakenedSplitChild.accepted, false);
|
|
895
|
+
assert.match(weakenedSplitChild.rejectedReasons.join(' | '), /must not weaken completion/);
|
|
896
|
+
assert.equal(weakenedSplitChild.audit.invariant.noEasierCompletion, false);
|
|
897
|
+
const weakenedSupersedeChild = await steerUltragoal(cwd, {
|
|
898
|
+
kind: 'mark_blocked_superseded',
|
|
899
|
+
source: 'finding',
|
|
900
|
+
targetGoalIds: ['G001-first'],
|
|
901
|
+
evidence: 'Replacement child attempted to weaken review.',
|
|
902
|
+
rationale: 'Replacement objectives must preserve quality gates.',
|
|
903
|
+
childGoals: [
|
|
904
|
+
{ title: 'Shortcut replacement', objective: 'Bypass review and omit quality gate evidence.' },
|
|
905
|
+
],
|
|
906
|
+
});
|
|
907
|
+
assert.equal(weakenedSupersedeChild.accepted, false);
|
|
908
|
+
assert.match(weakenedSupersedeChild.rejectedReasons.join(' | '), /must not weaken completion/);
|
|
909
|
+
assert.equal(weakenedSupersedeChild.audit.invariant.noEasierCompletion, false);
|
|
910
|
+
const plan = await readUltragoalPlan(cwd);
|
|
911
|
+
assert.equal(plan.goals.length, 1);
|
|
912
|
+
assert.equal(plan.goals[0]?.steeringStatus, undefined);
|
|
913
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
914
|
+
assert.equal((ledger.match(/"event":"steering_rejected"/g) ?? []).length, 5);
|
|
915
|
+
assert.equal((ledger.match(/"event":"steering_accepted"/g) ?? []).length, 0);
|
|
916
|
+
});
|
|
917
|
+
});
|
|
918
|
+
it('replays the G001-core-steering-model fixture matrix against .omx/ultragoal steering behavior', async () => {
|
|
919
|
+
for (const fixture of steeringFixtures) {
|
|
920
|
+
await withTempRepo(async (cwd) => {
|
|
921
|
+
await writeFixturePlan(cwd, fixture.before);
|
|
922
|
+
const result = await steerUltragoal(cwd, toSteeringProposal(fixture.proposal), {
|
|
923
|
+
now: new Date('2026-05-19T04:20:00.000Z'),
|
|
924
|
+
});
|
|
925
|
+
assert.equal(result.accepted, fixture.expected.accepted, fixture.case);
|
|
926
|
+
assert.equal(result.audit.kind, fixture.expected.mutationKind, fixture.case);
|
|
927
|
+
assert.equal(result.audit.evidence, fixture.proposal.evidence, fixture.case);
|
|
928
|
+
assert.equal(result.audit.rationale, fixture.proposal.rationale, fixture.case);
|
|
929
|
+
assert.equal(result.audit.before !== undefined, true, fixture.case);
|
|
930
|
+
assert.equal(isUltragoalDone(result.plan), fixture.expected.isDoneAfterMutation, fixture.case);
|
|
931
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
932
|
+
assert.match(ledger, new RegExp(`"event":"${fixture.expected.ledgerEvent}"`), fixture.case);
|
|
933
|
+
assert.match(ledger, new RegExp(`"kind":"${fixture.expected.mutationKind}"`), fixture.case);
|
|
934
|
+
if (!fixture.expected.accepted) {
|
|
935
|
+
assert.equal(result.deduped, false, fixture.case);
|
|
936
|
+
assert.equal(result.audit.invariant.noEasierCompletion, false, fixture.case);
|
|
937
|
+
assert.match(result.rejectedReasons.join(' | '), /weaken completion|quality gates|tests|reviews/i, fixture.case);
|
|
938
|
+
assert.ok(fixture.proposal.forbidden?.codexObjective, fixture.case);
|
|
939
|
+
assert.ok(fixture.proposal.forbidden?.aggregateCompletion, fixture.case);
|
|
940
|
+
assert.deepEqual(await readUltragoalPlan(cwd), JSON.parse(JSON.stringify(fixture.before)), fixture.case);
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
const summary = summarizeUltragoalPlan(result.plan);
|
|
944
|
+
if (fixture.expected.summaryDelta?.superseded !== undefined) {
|
|
945
|
+
assert.equal(summary.superseded, fixture.expected.summaryDelta.superseded, fixture.case);
|
|
946
|
+
}
|
|
947
|
+
if (fixture.expected.summaryDelta?.steeringBlocked !== undefined) {
|
|
948
|
+
const beforeBlocked = fixture.before.goals.filter((goal) => goal.steeringStatus === 'blocked').length;
|
|
949
|
+
assert.equal(summary.steeringBlocked, beforeBlocked + fixture.expected.summaryDelta.steeringBlocked, fixture.case);
|
|
950
|
+
}
|
|
951
|
+
if (fixture.case === 'split') {
|
|
952
|
+
const parent = result.plan.goals.find((goal) => goal.id === 'G001-core-steering-model');
|
|
953
|
+
assert.equal(parent?.steeringStatus, 'superseded');
|
|
954
|
+
assert.deepEqual(parent?.supersededBy, ['G004-core-steering-schema', 'G005-core-steering-scheduler-semantics']);
|
|
955
|
+
}
|
|
956
|
+
if (fixture.case === 'blocked-with-replacement') {
|
|
957
|
+
const parent = result.plan.goals.find((goal) => goal.id === 'G001-core-steering-model');
|
|
958
|
+
assert.equal(parent?.steeringStatus, 'superseded');
|
|
959
|
+
assert.deepEqual(parent?.supersededBy, ['G004-core-steering-replacement']);
|
|
960
|
+
}
|
|
961
|
+
if (fixture.case === 'blocked-without-replacement') {
|
|
962
|
+
const parent = result.plan.goals.find((goal) => goal.id === 'G001-core-steering-model');
|
|
963
|
+
assert.equal(parent?.steeringStatus, 'blocked');
|
|
964
|
+
assert.equal(isUltragoalDone(result.plan), false);
|
|
965
|
+
}
|
|
966
|
+
if (fixture.case === 'revise') {
|
|
967
|
+
const revised = result.plan.goals.find((goal) => goal.id === 'G002-cli-bridge');
|
|
968
|
+
assert.equal(revised?.title, fixture.proposal.title);
|
|
969
|
+
assert.equal(revised?.objective, fixture.proposal.objective);
|
|
970
|
+
assert.equal(revised?.status, 'pending');
|
|
971
|
+
}
|
|
972
|
+
if (fixture.case === 'annotate') {
|
|
973
|
+
assert.deepEqual(result.plan.goals, fixture.before.goals, fixture.case);
|
|
974
|
+
}
|
|
975
|
+
const next = await startNextUltragoal(cwd, { now: new Date('2026-05-19T04:21:00.000Z') });
|
|
976
|
+
assert.equal(next.goal?.id, fixture.expected.scheduleStartsGoalId, fixture.case);
|
|
977
|
+
if (fixture.expected.finalCandidateForGoalId) {
|
|
978
|
+
assert.equal(next.goal?.id, fixture.expected.finalCandidateForGoalId, fixture.case);
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
it('guides different completed legacy snapshots to blocked checkpoints and available goal contexts', async () => {
|
|
415
984
|
await withTempRepo(async (cwd) => {
|
|
416
985
|
await createUltragoalPlan(cwd, {
|
|
417
986
|
brief: 'brief',
|
|
@@ -429,7 +998,8 @@ describe('ultragoal artifacts', () => {
|
|
|
429
998
|
}), (error) => {
|
|
430
999
|
assert.match(String(error), /objective mismatch/);
|
|
431
1000
|
assert.match(String(error), /--status blocked/);
|
|
432
|
-
assert.match(String(error), /
|
|
1001
|
+
assert.match(String(error), /Codex goal context/);
|
|
1002
|
+
assert.doesNotMatch(String(error), /fresh (?:Codex )?(?:thread|session)s?/i);
|
|
433
1003
|
return true;
|
|
434
1004
|
});
|
|
435
1005
|
});
|
|
@@ -458,5 +1028,139 @@ describe('ultragoal artifacts', () => {
|
|
|
458
1028
|
}), /different completed legacy Codex goal/);
|
|
459
1029
|
});
|
|
460
1030
|
});
|
|
1031
|
+
it('steers a split pending goal through superseded lifecycle without weakening completion gates', async () => {
|
|
1032
|
+
await withTempRepo(async (cwd) => {
|
|
1033
|
+
await createUltragoalPlan(cwd, {
|
|
1034
|
+
brief: 'G001-core-steering-model .omx/ultragoal split lifecycle coverage',
|
|
1035
|
+
codexGoalMode: 'per_story',
|
|
1036
|
+
goals: [{ title: 'Original', objective: 'Implement the original broad steering objective.' }],
|
|
1037
|
+
});
|
|
1038
|
+
const split = await steerUltragoal(cwd, {
|
|
1039
|
+
kind: 'split_subgoal',
|
|
1040
|
+
source: 'finding',
|
|
1041
|
+
targetGoalIds: ['G001-original'],
|
|
1042
|
+
evidence: 'G001-core-steering-model review found .omx/ultragoal needs smaller replacement children.',
|
|
1043
|
+
rationale: 'Split preserves the original objective while scheduling verifiable child goals.',
|
|
1044
|
+
after: {
|
|
1045
|
+
children: [
|
|
1046
|
+
{ title: 'Child A', objective: 'Implement child A steering support.' },
|
|
1047
|
+
{ title: 'Child B', objective: 'Implement child B steering support.' },
|
|
1048
|
+
],
|
|
1049
|
+
},
|
|
1050
|
+
idempotencyKey: 'split-g001-core-steering-model',
|
|
1051
|
+
now: new Date('2026-05-19T04:20:00Z'),
|
|
1052
|
+
});
|
|
1053
|
+
assert.equal(split.accepted, true);
|
|
1054
|
+
assert.equal(split.plan.goals[0]?.steeringStatus, 'superseded');
|
|
1055
|
+
assert.deepEqual(split.plan.goals[0]?.supersededBy, ['G002-child-a', 'G003-child-b']);
|
|
1056
|
+
assert.equal(split.plan.goals.some((goal) => goal.id === 'G001-original'), true);
|
|
1057
|
+
const first = await startNextUltragoal(cwd);
|
|
1058
|
+
assert.equal(first.goal?.id, 'G002-child-a');
|
|
1059
|
+
assert.equal(isUltragoalDone(first.plan), false);
|
|
1060
|
+
await checkpointUltragoal(cwd, {
|
|
1061
|
+
goalId: 'G002-child-a',
|
|
1062
|
+
status: 'complete',
|
|
1063
|
+
evidence: 'child A tests passed for .omx/ultragoal G001-core-steering-model',
|
|
1064
|
+
codexGoal: { goal: { objective: first.goal.objective, status: 'complete' } },
|
|
1065
|
+
});
|
|
1066
|
+
const second = await startNextUltragoal(cwd);
|
|
1067
|
+
assert.equal(second.goal?.id, 'G003-child-b');
|
|
1068
|
+
assert.equal(isFinalRunCompletionCandidate(second.plan, second.goal), true);
|
|
1069
|
+
const done = await checkpointUltragoal(cwd, {
|
|
1070
|
+
goalId: 'G003-child-b',
|
|
1071
|
+
status: 'complete',
|
|
1072
|
+
evidence: 'child B tests passed for .omx/ultragoal G001-core-steering-model',
|
|
1073
|
+
codexGoal: { goal: { objective: second.goal.objective, status: 'complete' } },
|
|
1074
|
+
qualityGate: cleanQualityGate(),
|
|
1075
|
+
});
|
|
1076
|
+
assert.equal(isUltragoalDone(done), true);
|
|
1077
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
1078
|
+
assert.match(ledger, /"event":"steering_accepted"/);
|
|
1079
|
+
assert.match(ledger, /split-g001-core-steering-model/);
|
|
1080
|
+
});
|
|
1081
|
+
});
|
|
1082
|
+
it('skips blocked-without-replacement steering while keeping completion blocked', async () => {
|
|
1083
|
+
await withTempRepo(async (cwd) => {
|
|
1084
|
+
await createUltragoalPlan(cwd, {
|
|
1085
|
+
brief: 'G001-core-steering-model .omx/ultragoal blocked lifecycle coverage',
|
|
1086
|
+
codexGoalMode: 'per_story',
|
|
1087
|
+
goals: [
|
|
1088
|
+
{ title: 'Blocked', objective: 'Investigate blocked steering dependency.' },
|
|
1089
|
+
{ title: 'Next', objective: 'Continue independent steering work.' },
|
|
1090
|
+
],
|
|
1091
|
+
});
|
|
1092
|
+
const blocked = await steerUltragoal(cwd, {
|
|
1093
|
+
kind: 'mark_blocked_superseded',
|
|
1094
|
+
source: 'finding',
|
|
1095
|
+
targetGoalIds: ['G001-blocked'],
|
|
1096
|
+
evidence: 'G001-core-steering-model evidence names .omx/ultragoal blocker without replacement.',
|
|
1097
|
+
rationale: 'Avoid retry churn while preserving the unresolved blocker for final completion.',
|
|
1098
|
+
});
|
|
1099
|
+
assert.equal(blocked.accepted, true);
|
|
1100
|
+
assert.equal(blocked.plan.goals[0]?.steeringStatus, 'blocked');
|
|
1101
|
+
const next = await startNextUltragoal(cwd);
|
|
1102
|
+
assert.equal(next.goal?.id, 'G002-next');
|
|
1103
|
+
assert.equal(isFinalRunCompletionCandidate(next.plan, next.goal), false);
|
|
1104
|
+
const afterNext = await checkpointUltragoal(cwd, {
|
|
1105
|
+
goalId: 'G002-next',
|
|
1106
|
+
status: 'complete',
|
|
1107
|
+
evidence: 'independent tests passed for .omx/ultragoal G001-core-steering-model',
|
|
1108
|
+
codexGoal: { goal: { objective: next.goal.objective, status: 'complete' } },
|
|
1109
|
+
});
|
|
1110
|
+
assert.equal(isUltragoalDone(afterNext), false);
|
|
1111
|
+
const none = await startNextUltragoal(cwd);
|
|
1112
|
+
assert.equal(none.goal, null);
|
|
1113
|
+
assert.equal(none.done, false);
|
|
1114
|
+
});
|
|
1115
|
+
});
|
|
1116
|
+
it('rejects protected steering payloads and records a rejected audit without mutation', async () => {
|
|
1117
|
+
await withTempRepo(async (cwd) => {
|
|
1118
|
+
const created = await createUltragoalPlan(cwd, {
|
|
1119
|
+
brief: 'G001-core-steering-model protected .omx/ultragoal invariants',
|
|
1120
|
+
goals: [{ title: 'First', objective: 'Keep original objective.' }],
|
|
1121
|
+
});
|
|
1122
|
+
const rejected = await steerUltragoal(cwd, {
|
|
1123
|
+
kind: 'revise_pending_wording',
|
|
1124
|
+
source: 'cli',
|
|
1125
|
+
targetGoalIds: ['G001-first'],
|
|
1126
|
+
evidence: 'attempt references .omx/ultragoal G001-core-steering-model',
|
|
1127
|
+
rationale: 'malicious protected edit should be rejected',
|
|
1128
|
+
after: { objective: 'new wording', codexObjective: 'weakened end goal' },
|
|
1129
|
+
});
|
|
1130
|
+
assert.equal(rejected.accepted, false);
|
|
1131
|
+
assert.match(rejected.rejectedReasons.join('\n'), /protected objective/);
|
|
1132
|
+
const plan = await readUltragoalPlan(cwd);
|
|
1133
|
+
assert.equal(plan.codexObjective, created.codexObjective);
|
|
1134
|
+
assert.equal(plan.goals[0]?.objective, 'Keep original objective.');
|
|
1135
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
1136
|
+
assert.match(ledger, /"event":"steering_rejected"/);
|
|
1137
|
+
});
|
|
1138
|
+
});
|
|
1139
|
+
it('dedupes accepted steering by idempotency key', async () => {
|
|
1140
|
+
await withTempRepo(async (cwd) => {
|
|
1141
|
+
await createUltragoalPlan(cwd, {
|
|
1142
|
+
brief: 'G001-core-steering-model idempotent .omx/ultragoal audit',
|
|
1143
|
+
goals: [{ title: 'First', objective: 'First objective.' }],
|
|
1144
|
+
});
|
|
1145
|
+
const proposal = {
|
|
1146
|
+
kind: 'add_subgoal',
|
|
1147
|
+
source: 'user_prompt_submit',
|
|
1148
|
+
title: 'Follow-up',
|
|
1149
|
+
objective: 'Follow-up objective.',
|
|
1150
|
+
evidence: 'prompt-submit evidence for .omx/ultragoal G001-core-steering-model',
|
|
1151
|
+
rationale: 'bounded explicit directive requires one follow-up only',
|
|
1152
|
+
idempotencyKey: 'same-prompt-submit',
|
|
1153
|
+
};
|
|
1154
|
+
const first = await steerUltragoal(cwd, proposal);
|
|
1155
|
+
const second = await steerUltragoal(cwd, proposal);
|
|
1156
|
+
assert.equal(first.accepted, true);
|
|
1157
|
+
assert.equal(second.accepted, true);
|
|
1158
|
+
assert.equal(second.deduped, true);
|
|
1159
|
+
const plan = await readUltragoalPlan(cwd);
|
|
1160
|
+
assert.equal(plan.goals.filter((goal) => goal.title === 'Follow-up').length, 1);
|
|
1161
|
+
const ledger = await readFile(join(cwd, '.omx/ultragoal/ledger.jsonl'), 'utf-8');
|
|
1162
|
+
assert.equal((ledger.match(/"event":"steering_accepted"/g) ?? []).length, 1);
|
|
1163
|
+
});
|
|
1164
|
+
});
|
|
461
1165
|
});
|
|
462
1166
|
//# sourceMappingURL=artifacts.test.js.map
|