oh-my-codex 0.13.1 → 0.14.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 +5 -5
- package/Cargo.toml +1 -1
- package/README.md +2 -0
- package/crates/omx-explore/src/main.rs +221 -10
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/skill-validation.test.js +91 -0
- package/dist/autoresearch/__tests__/skill-validation.test.js.map +1 -0
- package/dist/autoresearch/skill-validation.d.ts +13 -0
- package/dist/autoresearch/skill-validation.d.ts.map +1 -0
- package/dist/autoresearch/skill-validation.js +165 -0
- package/dist/autoresearch/skill-validation.js.map +1 -0
- package/dist/catalog/__tests__/generator.test.js +2 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/catalog/__tests__/schema.test.js +6 -0
- package/dist/catalog/__tests__/schema.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-guided.test.js +236 -273
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch.test.js +64 -653
- package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +102 -1
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/nested-help-routing.test.js +2 -1
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.d.ts +2 -0
- package/dist/cli/__tests__/question.test.d.ts.map +1 -0
- package/dist/cli/__tests__/question.test.js +113 -0
- package/dist/cli/__tests__/question.test.js.map +1 -0
- package/dist/cli/__tests__/session-search-help.test.js +1 -1
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +43 -3
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +25 -1
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/autoresearch-guided.d.ts +24 -7
- package/dist/cli/autoresearch-guided.d.ts.map +1 -1
- package/dist/cli/autoresearch-guided.js +189 -130
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/autoresearch.d.ts +3 -2
- package/dist/cli/autoresearch.d.ts.map +1 -1
- package/dist/cli/autoresearch.js +29 -305
- package/dist/cli/autoresearch.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +43 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +78 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/question.d.ts +3 -0
- package/dist/cli/question.d.ts.map +1 -0
- package/dist/cli/question.js +182 -0
- package/dist/cli/question.js.map +1 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +15 -0
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/update.js +1 -1
- package/dist/cli/update.js.map +1 -1
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.js +45 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.js +48 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.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__/debugger-log-recency-contract.test.js +2 -2
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +22 -5
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js +2 -2
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +340 -17
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +830 -85
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +717 -16
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +25 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +894 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +34 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +26 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +44 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +126 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +132 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js +22 -4
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +4 -2
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts +1 -0
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js +4 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +28 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js +5 -4
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-team-routing.test.js +2 -2
- package/dist/hooks/__tests__/prompt-team-routing.test.js.map +1 -1
- package/dist/hooks/__tests__/triage-config.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-config.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-config.test.js +211 -0
- package/dist/hooks/__tests__/triage-config.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js +230 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-state.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-state.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-state.test.js +426 -0
- package/dist/hooks/__tests__/triage-state.test.js.map +1 -0
- package/dist/hooks/keyword-detector.d.ts +26 -7
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +104 -26
- 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 +16 -9
- 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 +28 -1
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/triage-config.d.ts +33 -0
- package/dist/hooks/triage-config.d.ts.map +1 -0
- package/dist/hooks/triage-config.js +87 -0
- package/dist/hooks/triage-config.js.map +1 -0
- package/dist/hooks/triage-heuristic.d.ts +20 -0
- package/dist/hooks/triage-heuristic.d.ts.map +1 -0
- package/dist/hooks/triage-heuristic.js +210 -0
- package/dist/hooks/triage-heuristic.js.map +1 -0
- package/dist/hooks/triage-state.d.ts +63 -0
- package/dist/hooks/triage-state.d.ts.map +1 -0
- package/dist/hooks/triage-state.js +138 -0
- package/dist/hooks/triage-state.js.map +1 -0
- package/dist/hud/__tests__/reconcile.test.js +20 -0
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +55 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/reconcile.d.ts +1 -0
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +2 -1
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +23 -4
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +38 -0
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +1 -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 +11 -3
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-server.d.ts +8 -0
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +4 -0
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/modes/__tests__/base-ralph-contract.test.js +15 -0
- package/dist/modes/__tests__/base-ralph-contract.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 +22 -6
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/index.test.js +78 -0
- package/dist/notifications/__tests__/index.test.js.map +1 -1
- package/dist/notifications/__tests__/reply-listener.test.js +34 -1
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +39 -22
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts +1 -0
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +14 -2
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/openclaw/index.d.ts +5 -3
- package/dist/openclaw/index.d.ts.map +1 -1
- package/dist/openclaw/index.js +5 -3
- package/dist/openclaw/index.js.map +1 -1
- package/dist/question/__tests__/client.test.d.ts +2 -0
- package/dist/question/__tests__/client.test.d.ts.map +1 -0
- package/dist/question/__tests__/client.test.js +70 -0
- package/dist/question/__tests__/client.test.js.map +1 -0
- package/dist/question/__tests__/deep-interview.test.d.ts +2 -0
- package/dist/question/__tests__/deep-interview.test.d.ts.map +1 -0
- package/dist/question/__tests__/deep-interview.test.js +108 -0
- package/dist/question/__tests__/deep-interview.test.js.map +1 -0
- package/dist/question/__tests__/policy.test.d.ts +2 -0
- package/dist/question/__tests__/policy.test.d.ts.map +1 -0
- package/dist/question/__tests__/policy.test.js +107 -0
- package/dist/question/__tests__/policy.test.js.map +1 -0
- package/dist/question/__tests__/renderer.test.d.ts +2 -0
- package/dist/question/__tests__/renderer.test.d.ts.map +1 -0
- package/dist/question/__tests__/renderer.test.js +88 -0
- package/dist/question/__tests__/renderer.test.js.map +1 -0
- package/dist/question/__tests__/state.test.d.ts +2 -0
- package/dist/question/__tests__/state.test.d.ts.map +1 -0
- package/dist/question/__tests__/state.test.js +55 -0
- package/dist/question/__tests__/state.test.js.map +1 -0
- package/dist/question/__tests__/types.test.d.ts +2 -0
- package/dist/question/__tests__/types.test.d.ts.map +1 -0
- package/dist/question/__tests__/types.test.js +44 -0
- package/dist/question/__tests__/types.test.js.map +1 -0
- package/dist/question/__tests__/ui.test.d.ts +2 -0
- package/dist/question/__tests__/ui.test.d.ts.map +1 -0
- package/dist/question/__tests__/ui.test.js +169 -0
- package/dist/question/__tests__/ui.test.js.map +1 -0
- package/dist/question/client.d.ts +54 -0
- package/dist/question/client.d.ts.map +1 -0
- package/dist/question/client.js +77 -0
- package/dist/question/client.js.map +1 -0
- package/dist/question/deep-interview.d.ts +27 -0
- package/dist/question/deep-interview.d.ts.map +1 -0
- package/dist/question/deep-interview.js +101 -0
- package/dist/question/deep-interview.js.map +1 -0
- package/dist/question/policy.d.ts +18 -0
- package/dist/question/policy.d.ts.map +1 -0
- package/dist/question/policy.js +77 -0
- package/dist/question/policy.js.map +1 -0
- package/dist/question/renderer.d.ts +18 -0
- package/dist/question/renderer.d.ts.map +1 -0
- package/dist/question/renderer.js +128 -0
- package/dist/question/renderer.js.map +1 -0
- package/dist/question/state.d.ts +19 -0
- package/dist/question/state.d.ts.map +1 -0
- package/dist/question/state.js +108 -0
- package/dist/question/state.js.map +1 -0
- package/dist/question/types.d.ts +66 -0
- package/dist/question/types.d.ts.map +1 -0
- package/dist/question/types.js +82 -0
- package/dist/question/types.js.map +1 -0
- package/dist/question/ui.d.ts +38 -0
- package/dist/question/ui.d.ts.map +1 -0
- package/dist/question/ui.js +321 -0
- package/dist/question/ui.js.map +1 -0
- package/dist/ralph/contract.d.ts +1 -1
- package/dist/ralph/contract.d.ts.map +1 -1
- package/dist/ralph/contract.js +4 -1
- package/dist/ralph/contract.js.map +1 -1
- package/dist/ralplan/runtime.js +1 -1
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/runtime/__tests__/run-loop.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-loop.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-loop.test.js +35 -0
- package/dist/runtime/__tests__/run-loop.test.js.map +1 -0
- package/dist/runtime/__tests__/run-outcome.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-outcome.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-outcome.test.js +64 -0
- package/dist/runtime/__tests__/run-outcome.test.js.map +1 -0
- package/dist/runtime/run-loop.d.ts +41 -0
- package/dist/runtime/run-loop.d.ts.map +1 -0
- package/dist/runtime/run-loop.js +46 -0
- package/dist/runtime/run-loop.js.map +1 -0
- package/dist/runtime/run-outcome.d.ts +28 -0
- package/dist/runtime/run-outcome.d.ts.map +1 -0
- package/dist/runtime/run-outcome.js +136 -0
- package/dist/runtime/run-outcome.js.map +1 -0
- package/dist/runtime/run-state.d.ts +36 -0
- package/dist/runtime/run-state.d.ts.map +1 -0
- package/dist/runtime/run-state.js +110 -0
- package/dist/runtime/run-state.js.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +1299 -93
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/generate-release-body.test.d.ts +2 -0
- package/dist/scripts/__tests__/generate-release-body.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/generate-release-body.test.js +144 -0
- package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts +2 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +222 -55
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/generate-release-body.d.ts +34 -0
- package/dist/scripts/generate-release-body.d.ts.map +1 -0
- package/dist/scripts/generate-release-body.js +249 -0
- package/dist/scripts/generate-release-body.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +124 -22
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/active-team.d.ts.map +1 -1
- package/dist/scripts/notify-hook/active-team.js +2 -1
- package/dist/scripts/notify-hook/active-team.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts +27 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +83 -20
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +64 -38
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +18 -3
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +16 -0
- package/dist/scripts/notify-hook/state-io.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 -5
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook.js +16 -12
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/sync-prompt-guidance-fragments.js +5 -0
- package/dist/scripts/sync-prompt-guidance-fragments.js.map +1 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js +21 -0
- package/dist/state/__tests__/operations-ralph-phase.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +11 -0
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +15 -0
- package/dist/state/operations.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +14 -1
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +3 -1
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/followup-planner.test.js +15 -0
- package/dist/team/__tests__/followup-planner.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +6 -0
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/role-router.test.js +41 -0
- package/dist/team/__tests__/role-router.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +1 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts +2 -0
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/worker-runtime-identity.test.js +250 -0
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -0
- package/dist/team/followup-planner.d.ts.map +1 -1
- package/dist/team/followup-planner.js +31 -9
- package/dist/team/followup-planner.js.map +1 -1
- package/dist/team/leader-activity.d.ts.map +1 -1
- package/dist/team/leader-activity.js +26 -15
- package/dist/team/leader-activity.js.map +1 -1
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/role-router.d.ts.map +1 -1
- package/dist/team/role-router.js +73 -0
- package/dist/team/role-router.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +9 -8
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +10 -9
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +3 -2
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js +3 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
- package/dist/wiki/__tests__/slug-nonascii.test.js +11 -5
- package/dist/wiki/__tests__/slug-nonascii.test.js.map +1 -1
- package/dist/wiki/storage.d.ts.map +1 -1
- package/dist/wiki/storage.js +2 -1
- package/dist/wiki/storage.js.map +1 -1
- package/package.json +5 -2
- package/prompts/dependency-expert.md +3 -0
- package/prompts/executor.md +5 -0
- package/prompts/explore.md +2 -0
- package/prompts/planner.md +5 -0
- package/prompts/product-analyst.md +8 -8
- package/prompts/researcher.md +78 -30
- package/prompts/verifier.md +4 -0
- package/skills/analyze/SKILL.md +101 -134
- package/skills/autoresearch/SKILL.md +68 -0
- package/skills/deep-interview/SKILL.md +10 -9
- package/skills/help/SKILL.md +3 -1
- package/skills/ralplan/SKILL.md +1 -0
- package/skills/team/SKILL.md +1 -0
- package/skills/ultrawork/SKILL.md +1 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +1577 -73
- package/src/scripts/__tests__/generate-release-body.test.ts +166 -0
- package/src/scripts/codex-native-hook.ts +316 -80
- package/src/scripts/generate-release-body.ts +295 -0
- package/src/scripts/notify-fallback-watcher.ts +136 -23
- package/src/scripts/notify-hook/active-team.ts +2 -1
- package/src/scripts/notify-hook/auto-nudge.ts +89 -20
- package/src/scripts/notify-hook/managed-tmux.ts +70 -31
- package/src/scripts/notify-hook/ralph-session-resume.ts +18 -3
- package/src/scripts/notify-hook/state-io.ts +16 -0
- package/src/scripts/notify-hook/team-leader-nudge.ts +24 -4
- package/src/scripts/notify-hook.ts +24 -11
- package/src/scripts/sync-prompt-guidance-fragments.ts +4 -0
- package/templates/AGENTS.md +48 -37
- package/templates/catalog-manifest.json +9 -4
package/Cargo.lock
CHANGED
|
@@ -32,11 +32,11 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
|
32
32
|
|
|
33
33
|
[[package]]
|
|
34
34
|
name = "omx-explore-harness"
|
|
35
|
-
version = "0.
|
|
35
|
+
version = "0.14.0"
|
|
36
36
|
|
|
37
37
|
[[package]]
|
|
38
38
|
name = "omx-mux"
|
|
39
|
-
version = "0.
|
|
39
|
+
version = "0.14.0"
|
|
40
40
|
dependencies = [
|
|
41
41
|
"serde",
|
|
42
42
|
"serde_json",
|
|
@@ -44,7 +44,7 @@ dependencies = [
|
|
|
44
44
|
|
|
45
45
|
[[package]]
|
|
46
46
|
name = "omx-runtime"
|
|
47
|
-
version = "0.
|
|
47
|
+
version = "0.14.0"
|
|
48
48
|
dependencies = [
|
|
49
49
|
"omx-mux",
|
|
50
50
|
"omx-runtime-core",
|
|
@@ -53,7 +53,7 @@ dependencies = [
|
|
|
53
53
|
|
|
54
54
|
[[package]]
|
|
55
55
|
name = "omx-runtime-core"
|
|
56
|
-
version = "0.
|
|
56
|
+
version = "0.14.0"
|
|
57
57
|
dependencies = [
|
|
58
58
|
"fs2",
|
|
59
59
|
"serde",
|
|
@@ -62,7 +62,7 @@ dependencies = [
|
|
|
62
62
|
|
|
63
63
|
[[package]]
|
|
64
64
|
name = "omx-sparkshell"
|
|
65
|
-
version = "0.
|
|
65
|
+
version = "0.14.0"
|
|
66
66
|
dependencies = [
|
|
67
67
|
"omx-mux",
|
|
68
68
|
]
|
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -218,6 +218,8 @@ omx doctor --team
|
|
|
218
218
|
|
|
219
219
|
Only use the forced team shutdown for a team you have confirmed is dead or intentionally abandoned.
|
|
220
220
|
|
|
221
|
+
If `Shift+Enter` still submits instead of inserting a newline inside an OMX-managed tmux session, see [Troubleshooting execution readiness](./docs/troubleshooting.md#shiftenter-submits-instead-of-inserting-a-newline-in-tmux-backed-omx-sessions). Current OMX already enables tmux extended-key forwarding around its own Codex launch paths, so a persistent failure is usually a tmux terminal-capability/discoverability problem rather than a net-new OMX feature gap.
|
|
222
|
+
|
|
221
223
|
### Explore and sparkshell
|
|
222
224
|
|
|
223
225
|
- `omx explore --prompt "..."` is for read-only repository lookup
|
|
@@ -12,6 +12,8 @@ const CODEX_BIN_ENV: &str = "OMX_EXPLORE_CODEX_BIN";
|
|
|
12
12
|
const HARNESS_ROOT_ENV: &str = "OMX_EXPLORE_ROOT";
|
|
13
13
|
const INTERNAL_DIRECT_WRAPPER_FLAG: &str = "--internal-allowlist-direct";
|
|
14
14
|
const INTERNAL_SHELL_WRAPPER_FLAG: &str = "--internal-allowlist-shell";
|
|
15
|
+
const TEMP_ALLOWLIST_DIR_PREFIX: &str = "omx-explore-allowlist-";
|
|
16
|
+
const SHELL_STARTUP_ENV_VARS: &[&str] = &["BASH_ENV", "ENV", "PROMPT_COMMAND"];
|
|
15
17
|
const WINDOWS_UNSUPPORTED_ALLOWLIST_MESSAGE: &str =
|
|
16
18
|
"omx explore built-in harness is not ready on Windows because its allowlist runtime relies on POSIX sh/bash wrappers. Set OMX_EXPLORE_BIN to a compatible custom harness, prefer `omx sparkshell` for shell-native read-only lookups, or run `omx doctor` for readiness details.";
|
|
17
19
|
|
|
@@ -226,6 +228,7 @@ fn invoke_codex(args: &Args, model: &str, prompt_contract: &str) -> io::Result<A
|
|
|
226
228
|
.env(HARNESS_ROOT_ENV, &args.cwd)
|
|
227
229
|
.env("PATH", &allowlist.bin_dir)
|
|
228
230
|
.env("SHELL", &allowlist.shell_path);
|
|
231
|
+
sanitize_explore_subprocess_env(&mut command);
|
|
229
232
|
let output = command.output()?;
|
|
230
233
|
|
|
231
234
|
let markdown = read_to_string(&output_path).ok();
|
|
@@ -580,20 +583,46 @@ fn build_direct_wrapper(self_exe: &Path, command: &str) -> Result<String, String
|
|
|
580
583
|
|
|
581
584
|
fn resolve_host_command(command: &str) -> Option<PathBuf> {
|
|
582
585
|
let candidate = Path::new(command);
|
|
583
|
-
if candidate.is_absolute()
|
|
586
|
+
if candidate.is_absolute()
|
|
587
|
+
&& is_usable_host_command(candidate)
|
|
588
|
+
&& !is_omx_explore_allowlist_path(candidate)
|
|
589
|
+
{
|
|
584
590
|
return Some(candidate.to_path_buf());
|
|
585
591
|
}
|
|
586
592
|
|
|
587
593
|
let path = env::var_os("PATH")?;
|
|
588
594
|
for entry in env::split_paths(&path) {
|
|
589
595
|
let resolved = entry.join(command);
|
|
590
|
-
if is_usable_host_command(&resolved) {
|
|
596
|
+
if is_usable_host_command(&resolved) && !is_omx_explore_allowlist_path(&resolved) {
|
|
591
597
|
return Some(resolved);
|
|
592
598
|
}
|
|
593
599
|
}
|
|
594
600
|
None
|
|
595
601
|
}
|
|
596
602
|
|
|
603
|
+
fn is_omx_explore_allowlist_path(path: &Path) -> bool {
|
|
604
|
+
fn is_under_allowlist_bin(path: &Path) -> bool {
|
|
605
|
+
path.ancestors().any(|ancestor| {
|
|
606
|
+
let is_allowlist_root = ancestor
|
|
607
|
+
.file_name()
|
|
608
|
+
.and_then(|name| name.to_str())
|
|
609
|
+
.is_some_and(|name| name.starts_with(TEMP_ALLOWLIST_DIR_PREFIX));
|
|
610
|
+
if !is_allowlist_root {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
path.strip_prefix(ancestor)
|
|
614
|
+
.ok()
|
|
615
|
+
.and_then(|relative| relative.components().next())
|
|
616
|
+
.is_some_and(|component| component.as_os_str() == "bin")
|
|
617
|
+
})
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
is_under_allowlist_bin(path)
|
|
621
|
+
|| canonicalize_existing_prefix(path)
|
|
622
|
+
.as_deref()
|
|
623
|
+
.is_some_and(is_under_allowlist_bin)
|
|
624
|
+
}
|
|
625
|
+
|
|
597
626
|
fn is_usable_host_command(path: &Path) -> bool {
|
|
598
627
|
let metadata = match path.metadata() {
|
|
599
628
|
Ok(metadata) => metadata,
|
|
@@ -617,6 +646,12 @@ fn shell_quote(value: &str) -> String {
|
|
|
617
646
|
format!("'{}'", value.replace('\'', "'\"'\"'"))
|
|
618
647
|
}
|
|
619
648
|
|
|
649
|
+
fn sanitize_explore_subprocess_env(command: &mut Command) {
|
|
650
|
+
for key in SHELL_STARTUP_ENV_VARS {
|
|
651
|
+
command.env_remove(key);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
620
655
|
fn run_internal_direct_wrapper<I>(mut args: I) -> Result<(), String>
|
|
621
656
|
where
|
|
622
657
|
I: Iterator<Item = OsString>,
|
|
@@ -653,6 +688,7 @@ where
|
|
|
653
688
|
if real_shell.ends_with("bash") {
|
|
654
689
|
child.arg("--noprofile").arg("--norc");
|
|
655
690
|
}
|
|
691
|
+
sanitize_explore_subprocess_env(&mut child);
|
|
656
692
|
let status = child
|
|
657
693
|
.arg("-lc")
|
|
658
694
|
.arg(&command)
|
|
@@ -735,7 +771,7 @@ fn validate_direct_command(command_name: &str, args: &[String]) -> Result<(), St
|
|
|
735
771
|
);
|
|
736
772
|
}
|
|
737
773
|
}
|
|
738
|
-
"find"
|
|
774
|
+
"find"
|
|
739
775
|
if args.iter().any(|arg| {
|
|
740
776
|
matches!(
|
|
741
777
|
arg.as_str(),
|
|
@@ -749,13 +785,14 @@ fn validate_direct_command(command_name: &str, args: &[String]) -> Result<(), St
|
|
|
749
785
|
| "-fprintf"
|
|
750
786
|
| "-fls"
|
|
751
787
|
)
|
|
752
|
-
})
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
788
|
+
}) =>
|
|
789
|
+
{
|
|
790
|
+
return Err(
|
|
791
|
+
"find actions that execute, delete, or write files are not allowed in omx explore"
|
|
792
|
+
.to_string(),
|
|
793
|
+
);
|
|
758
794
|
}
|
|
795
|
+
"find" => {}
|
|
759
796
|
"cat" => {
|
|
760
797
|
let operands = non_option_operands(args);
|
|
761
798
|
if operands.is_empty() {
|
|
@@ -987,7 +1024,17 @@ mod tests {
|
|
|
987
1024
|
#[test]
|
|
988
1025
|
fn resolve_codex_binary_resolves_bare_env_override_from_path() {
|
|
989
1026
|
let _guard = env_lock();
|
|
990
|
-
let root =
|
|
1027
|
+
let root = TempDirGuard {
|
|
1028
|
+
path: env::temp_dir().join(format!(
|
|
1029
|
+
"omx-explore-resolve-codex-binary-{}-{}",
|
|
1030
|
+
std::process::id(),
|
|
1031
|
+
SystemTime::now()
|
|
1032
|
+
.duration_since(UNIX_EPOCH)
|
|
1033
|
+
.unwrap_or_default()
|
|
1034
|
+
.as_nanos()
|
|
1035
|
+
)),
|
|
1036
|
+
};
|
|
1037
|
+
create_dir_all(&root.path).expect("create temp root");
|
|
991
1038
|
let bin_dir = root.path.join("bin");
|
|
992
1039
|
create_dir_all(&bin_dir).expect("create bin");
|
|
993
1040
|
let fake_codex = bin_dir.join("codex-custom");
|
|
@@ -1271,6 +1318,72 @@ exec node "$basedir/../@openai/codex/bin/codex.js" "$@"
|
|
|
1271
1318
|
assert!(!wrapper.contains("exit 127"));
|
|
1272
1319
|
}
|
|
1273
1320
|
|
|
1321
|
+
#[cfg(unix)]
|
|
1322
|
+
#[test]
|
|
1323
|
+
fn resolve_host_command_skips_omx_explore_allowlist_wrappers() {
|
|
1324
|
+
let _guard = env_lock();
|
|
1325
|
+
let allowlist_root = temp_allowlist_dir().expect("allowlist root");
|
|
1326
|
+
let real_root = TempDirGuard {
|
|
1327
|
+
path: env::temp_dir().join(format!(
|
|
1328
|
+
"omx-explore-host-resolution-{}-{}",
|
|
1329
|
+
std::process::id(),
|
|
1330
|
+
SystemTime::now()
|
|
1331
|
+
.duration_since(UNIX_EPOCH)
|
|
1332
|
+
.unwrap_or_default()
|
|
1333
|
+
.as_nanos()
|
|
1334
|
+
)),
|
|
1335
|
+
};
|
|
1336
|
+
create_dir_all(&real_root.path).expect("create real root");
|
|
1337
|
+
let real_bin = real_root.path.join("real-bin");
|
|
1338
|
+
let allowlist_bin = allowlist_root
|
|
1339
|
+
.path
|
|
1340
|
+
.join(format!("{TEMP_ALLOWLIST_DIR_PREFIX}fixture"))
|
|
1341
|
+
.join("bin");
|
|
1342
|
+
create_dir_all(&real_bin).expect("create real bin");
|
|
1343
|
+
create_dir_all(&allowlist_bin).expect("create allowlist bin");
|
|
1344
|
+
|
|
1345
|
+
let real_grep = real_bin.join("grep");
|
|
1346
|
+
write_executable(&real_grep, "#!/bin/sh\nexit 0\n").expect("write real grep");
|
|
1347
|
+
let wrapper_grep = allowlist_bin.join("grep");
|
|
1348
|
+
write_executable(&wrapper_grep, "#!/bin/sh\nexit 0\n").expect("write wrapper grep");
|
|
1349
|
+
|
|
1350
|
+
let original_path = env::var_os("PATH");
|
|
1351
|
+
unsafe {
|
|
1352
|
+
env::set_var(
|
|
1353
|
+
"PATH",
|
|
1354
|
+
env::join_paths([allowlist_bin.as_path(), real_bin.as_path()]).expect("join path"),
|
|
1355
|
+
);
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
let resolved = resolve_host_command("grep");
|
|
1359
|
+
|
|
1360
|
+
match original_path {
|
|
1361
|
+
Some(value) => unsafe { env::set_var("PATH", value) },
|
|
1362
|
+
None => unsafe { env::remove_var("PATH") },
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
assert_eq!(resolved, Some(real_grep));
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
#[cfg(unix)]
|
|
1369
|
+
#[test]
|
|
1370
|
+
fn resolve_host_command_rejects_absolute_allowlist_wrapper_paths() {
|
|
1371
|
+
let _guard = env_lock();
|
|
1372
|
+
let root = temp_allowlist_dir().expect("temp root");
|
|
1373
|
+
let wrapper_dir = root
|
|
1374
|
+
.path
|
|
1375
|
+
.join(format!("{TEMP_ALLOWLIST_DIR_PREFIX}fixture"))
|
|
1376
|
+
.join("bin");
|
|
1377
|
+
create_dir_all(&wrapper_dir).expect("create wrapper dir");
|
|
1378
|
+
let wrapper = wrapper_dir.join("grep");
|
|
1379
|
+
write_executable(&wrapper, "#!/bin/sh\nexit 0\n").expect("write wrapper");
|
|
1380
|
+
|
|
1381
|
+
assert_eq!(
|
|
1382
|
+
resolve_host_command(wrapper.to_str().expect("wrapper path")),
|
|
1383
|
+
None
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1274
1387
|
#[test]
|
|
1275
1388
|
fn discover_codex_support_dirs_includes_home_omx_and_codex_when_present() {
|
|
1276
1389
|
let _guard = env_lock();
|
|
@@ -1520,6 +1633,104 @@ exit 17
|
|
|
1520
1633
|
let _error = result.expect_err("both attempts should fail");
|
|
1521
1634
|
}
|
|
1522
1635
|
|
|
1636
|
+
#[test]
|
|
1637
|
+
fn invoke_codex_clears_shell_startup_env_before_launching_codex() {
|
|
1638
|
+
let _guard = env_lock();
|
|
1639
|
+
let root = temp_allowlist_dir().expect("temp root");
|
|
1640
|
+
let repo = root.path.join("repo");
|
|
1641
|
+
create_dir_all(&repo).expect("create repo");
|
|
1642
|
+
let prompt_file = root.path.join("prompt.md");
|
|
1643
|
+
write(&prompt_file, "contract").expect("write prompt");
|
|
1644
|
+
let capture_path = root.path.join("capture.txt");
|
|
1645
|
+
let fake_codex = root.path.join("codex-stub");
|
|
1646
|
+
write_executable(
|
|
1647
|
+
&fake_codex,
|
|
1648
|
+
&format!(
|
|
1649
|
+
r#"#!/bin/sh
|
|
1650
|
+
set -eu
|
|
1651
|
+
output_path=""
|
|
1652
|
+
while [ "$#" -gt 0 ]; do
|
|
1653
|
+
if [ "$1" = "-o" ]; then
|
|
1654
|
+
shift
|
|
1655
|
+
output_path="$1"
|
|
1656
|
+
fi
|
|
1657
|
+
shift
|
|
1658
|
+
done
|
|
1659
|
+
printf 'BASH_ENV=%s\nENV=%s\nPROMPT_COMMAND=%s\n' "${{BASH_ENV:-}}" "${{ENV:-}}" "${{PROMPT_COMMAND:-}}" > {}
|
|
1660
|
+
printf '# Answer\nok\n' > "$output_path"
|
|
1661
|
+
"#,
|
|
1662
|
+
shell_quote(&capture_path.display().to_string())
|
|
1663
|
+
),
|
|
1664
|
+
)
|
|
1665
|
+
.expect("write fake codex");
|
|
1666
|
+
|
|
1667
|
+
unsafe {
|
|
1668
|
+
env::set_var(CODEX_BIN_ENV, &fake_codex);
|
|
1669
|
+
env::set_var("BASH_ENV", "/tmp/bash-env-should-not-leak");
|
|
1670
|
+
env::set_var("ENV", "/tmp/env-should-not-leak");
|
|
1671
|
+
env::set_var("PROMPT_COMMAND", "printf should-not-run");
|
|
1672
|
+
}
|
|
1673
|
+
let attempt = invoke_codex(
|
|
1674
|
+
&Args {
|
|
1675
|
+
cwd: repo.clone(),
|
|
1676
|
+
prompt: "find tests".to_string(),
|
|
1677
|
+
prompt_file,
|
|
1678
|
+
spark_model: "spark-model".to_string(),
|
|
1679
|
+
fallback_model: "fallback-model".to_string(),
|
|
1680
|
+
},
|
|
1681
|
+
"spark-model",
|
|
1682
|
+
"contract",
|
|
1683
|
+
)
|
|
1684
|
+
.expect("invoke codex");
|
|
1685
|
+
unsafe {
|
|
1686
|
+
env::remove_var(CODEX_BIN_ENV);
|
|
1687
|
+
env::remove_var("BASH_ENV");
|
|
1688
|
+
env::remove_var("ENV");
|
|
1689
|
+
env::remove_var("PROMPT_COMMAND");
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
assert_eq!(attempt.status_code, 0);
|
|
1693
|
+
assert_eq!(
|
|
1694
|
+
read_to_string(&capture_path).expect("read capture"),
|
|
1695
|
+
"BASH_ENV=\nENV=\nPROMPT_COMMAND=\n"
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
#[test]
|
|
1700
|
+
fn sanitize_explore_subprocess_env_blocks_bash_env_startup_hooks() {
|
|
1701
|
+
let _guard = env_lock();
|
|
1702
|
+
let root = temp_allowlist_dir().expect("temp root");
|
|
1703
|
+
let bash_env_log = root.path.join("bash-env.log");
|
|
1704
|
+
let bash_env = root.path.join("bash-env.sh");
|
|
1705
|
+
write(
|
|
1706
|
+
&bash_env,
|
|
1707
|
+
format!(
|
|
1708
|
+
"printf 'startup:%s\\n' \"$BASH_ENV\" >> {}\n",
|
|
1709
|
+
shell_quote(&bash_env_log.display().to_string())
|
|
1710
|
+
),
|
|
1711
|
+
)
|
|
1712
|
+
.expect("write bash env");
|
|
1713
|
+
let bash_path = resolve_host_command("bash").expect("host bash path");
|
|
1714
|
+
|
|
1715
|
+
unsafe {
|
|
1716
|
+
env::set_var("BASH_ENV", &bash_env);
|
|
1717
|
+
}
|
|
1718
|
+
let mut child = Command::new(&bash_path);
|
|
1719
|
+
child
|
|
1720
|
+
.arg("--noprofile")
|
|
1721
|
+
.arg("--norc")
|
|
1722
|
+
.arg("-lc")
|
|
1723
|
+
.arg("true");
|
|
1724
|
+
sanitize_explore_subprocess_env(&mut child);
|
|
1725
|
+
let status = child.status().expect("run bash");
|
|
1726
|
+
unsafe {
|
|
1727
|
+
env::remove_var("BASH_ENV");
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
assert!(status.success());
|
|
1731
|
+
assert_eq!(read_to_string(&bash_env_log).unwrap_or_default(), "");
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1523
1734
|
#[test]
|
|
1524
1735
|
fn print_attempt_output_requires_markdown_artifact() {
|
|
1525
1736
|
let result = print_attempt_output(AttemptResult {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-validation.test.d.ts","sourceRoot":"","sources":["../../../src/autoresearch/__tests__/skill-validation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { assessAutoresearchCompletionState, normalizeAutoresearchValidationMode, } from '../skill-validation.js';
|
|
7
|
+
describe('autoresearch skill validation', () => {
|
|
8
|
+
it('normalizes the supported validation modes', () => {
|
|
9
|
+
assert.equal(normalizeAutoresearchValidationMode('mission-validator-script'), 'mission-validator-script');
|
|
10
|
+
assert.equal(normalizeAutoresearchValidationMode('prompt-architect-artifact'), 'prompt-architect-artifact');
|
|
11
|
+
assert.equal(normalizeAutoresearchValidationMode('unknown-mode'), null);
|
|
12
|
+
});
|
|
13
|
+
it('treats missing validation mode as incomplete', async () => {
|
|
14
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-autoresearch-skill-validation-'));
|
|
15
|
+
try {
|
|
16
|
+
const result = await assessAutoresearchCompletionState({ active: true }, cwd);
|
|
17
|
+
assert.equal(result.complete, false);
|
|
18
|
+
assert.equal(result.reason, 'missing_validation_mode');
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
await rm(cwd, { recursive: true, force: true });
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
it('requires a validator pass artifact for mission-validator-script mode', async () => {
|
|
25
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-autoresearch-validator-script-'));
|
|
26
|
+
try {
|
|
27
|
+
const artifactPath = join(cwd, '.omx', 'specs', 'autoresearch-demo', 'completion.json');
|
|
28
|
+
await mkdir(join(cwd, '.omx', 'specs', 'autoresearch-demo'), { recursive: true });
|
|
29
|
+
await writeFile(artifactPath, JSON.stringify({ status: 'running' }, null, 2));
|
|
30
|
+
const incomplete = await assessAutoresearchCompletionState({
|
|
31
|
+
active: true,
|
|
32
|
+
validation_mode: 'mission-validator-script',
|
|
33
|
+
mission_validator_command: 'node scripts/validate.js',
|
|
34
|
+
completion_artifact_path: artifactPath,
|
|
35
|
+
}, cwd);
|
|
36
|
+
assert.equal(incomplete.complete, false);
|
|
37
|
+
assert.equal(incomplete.reason, 'validator_not_passed');
|
|
38
|
+
await writeFile(artifactPath, JSON.stringify({ status: 'passed', passed: true }, null, 2));
|
|
39
|
+
const complete = await assessAutoresearchCompletionState({
|
|
40
|
+
active: true,
|
|
41
|
+
validation_mode: 'mission-validator-script',
|
|
42
|
+
mission_validator_command: 'node scripts/validate.js',
|
|
43
|
+
completion_artifact_path: artifactPath,
|
|
44
|
+
}, cwd);
|
|
45
|
+
assert.equal(complete.complete, true);
|
|
46
|
+
assert.equal(complete.reason, 'validator_passed');
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await rm(cwd, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
it('requires prompt, architect approval, and output artifact for prompt-architect-artifact mode', async () => {
|
|
53
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-autoresearch-architect-validation-'));
|
|
54
|
+
try {
|
|
55
|
+
const artifactDir = join(cwd, '.omx', 'specs', 'autoresearch-demo');
|
|
56
|
+
const completionPath = join(artifactDir, 'completion.json');
|
|
57
|
+
const outputPath = join(artifactDir, 'report.md');
|
|
58
|
+
await mkdir(artifactDir, { recursive: true });
|
|
59
|
+
await writeFile(outputPath, '# Report\n', 'utf-8');
|
|
60
|
+
await writeFile(completionPath, JSON.stringify({
|
|
61
|
+
architect_review: { verdict: 'reject' },
|
|
62
|
+
output_artifact_path: outputPath,
|
|
63
|
+
}, null, 2));
|
|
64
|
+
const rejected = await assessAutoresearchCompletionState({
|
|
65
|
+
active: true,
|
|
66
|
+
validation_mode: 'prompt-architect-artifact',
|
|
67
|
+
validator_prompt: 'Review the research output.',
|
|
68
|
+
completion_artifact_path: completionPath,
|
|
69
|
+
}, cwd);
|
|
70
|
+
assert.equal(rejected.complete, false);
|
|
71
|
+
assert.equal(rejected.reason, 'missing_architect_approval');
|
|
72
|
+
await writeFile(completionPath, JSON.stringify({
|
|
73
|
+
validator_prompt: 'Review the research output.',
|
|
74
|
+
architect_review: { verdict: 'approved' },
|
|
75
|
+
output_artifact_path: outputPath,
|
|
76
|
+
}, null, 2));
|
|
77
|
+
const approved = await assessAutoresearchCompletionState({
|
|
78
|
+
active: true,
|
|
79
|
+
validation_mode: 'prompt-architect-artifact',
|
|
80
|
+
validator_prompt: 'Review the research output.',
|
|
81
|
+
completion_artifact_path: completionPath,
|
|
82
|
+
}, cwd);
|
|
83
|
+
assert.equal(approved.complete, true);
|
|
84
|
+
assert.equal(approved.reason, 'architect_approved');
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
await rm(cwd, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=skill-validation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-validation.test.js","sourceRoot":"","sources":["../../../src/autoresearch/__tests__/skill-validation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type AutoresearchValidationMode = 'mission-validator-script' | 'prompt-architect-artifact';
|
|
2
|
+
export interface AutoresearchCompletionStatus {
|
|
3
|
+
complete: boolean;
|
|
4
|
+
reason: string;
|
|
5
|
+
validationMode: AutoresearchValidationMode | null;
|
|
6
|
+
artifactPath: string | null;
|
|
7
|
+
outputArtifactPath?: string | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function normalizeAutoresearchValidationMode(value: unknown): AutoresearchValidationMode | null;
|
|
10
|
+
export declare function assessAutoresearchCompletionState(rawState: Record<string, unknown> | null, cwd: string): Promise<AutoresearchCompletionStatus>;
|
|
11
|
+
export declare function readAutoresearchModeState(cwd: string, sessionId?: string): Promise<Record<string, unknown> | null>;
|
|
12
|
+
export declare function readAutoresearchCompletionStatus(cwd: string, sessionId?: string): Promise<AutoresearchCompletionStatus>;
|
|
13
|
+
//# sourceMappingURL=skill-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-validation.d.ts","sourceRoot":"","sources":["../../src/autoresearch/skill-validation.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,0BAA0B,GAAG,0BAA0B,GAAG,2BAA2B,CAAC;AAElG,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AA8CD,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,GAAG,IAAI,CAKrG;AA2DD,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACxC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,4BAA4B,CAAC,CA6CvC;AAED,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAWzC;AAED,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,4BAA4B,CAAC,CAGvC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { readFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { getReadScopedStatePaths } from '../mcp/state-paths.js';
|
|
5
|
+
function safeString(value) {
|
|
6
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
7
|
+
}
|
|
8
|
+
function safeObject(value) {
|
|
9
|
+
return value && typeof value === 'object' ? value : null;
|
|
10
|
+
}
|
|
11
|
+
function safeBoolean(value) {
|
|
12
|
+
return typeof value === 'boolean' ? value : null;
|
|
13
|
+
}
|
|
14
|
+
function lookupString(raw, ...keys) {
|
|
15
|
+
if (!raw)
|
|
16
|
+
return '';
|
|
17
|
+
for (const key of keys) {
|
|
18
|
+
const direct = safeString(raw[key]);
|
|
19
|
+
if (direct)
|
|
20
|
+
return direct;
|
|
21
|
+
}
|
|
22
|
+
const nestedState = safeObject(raw.state);
|
|
23
|
+
if (nestedState) {
|
|
24
|
+
for (const key of keys) {
|
|
25
|
+
const nested = safeString(nestedState[key]);
|
|
26
|
+
if (nested)
|
|
27
|
+
return nested;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
function lookupBoolean(raw, ...keys) {
|
|
33
|
+
if (!raw)
|
|
34
|
+
return null;
|
|
35
|
+
for (const key of keys) {
|
|
36
|
+
const direct = safeBoolean(raw[key]);
|
|
37
|
+
if (direct !== null)
|
|
38
|
+
return direct;
|
|
39
|
+
}
|
|
40
|
+
const nestedState = safeObject(raw.state);
|
|
41
|
+
if (nestedState) {
|
|
42
|
+
for (const key of keys) {
|
|
43
|
+
const nested = safeBoolean(nestedState[key]);
|
|
44
|
+
if (nested !== null)
|
|
45
|
+
return nested;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
export function normalizeAutoresearchValidationMode(value) {
|
|
51
|
+
const normalized = safeString(value).toLowerCase();
|
|
52
|
+
if (normalized === 'mission-validator-script')
|
|
53
|
+
return 'mission-validator-script';
|
|
54
|
+
if (normalized === 'prompt-architect-artifact')
|
|
55
|
+
return 'prompt-architect-artifact';
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function resolveMaybeRelativePath(cwd, rawPath) {
|
|
59
|
+
if (!rawPath)
|
|
60
|
+
return rawPath;
|
|
61
|
+
return rawPath.startsWith('/') ? rawPath : join(cwd, rawPath);
|
|
62
|
+
}
|
|
63
|
+
function deriveDefaultArtifactPath(cwd, rawState) {
|
|
64
|
+
const slug = lookupString(rawState, 'slug', 'mission_slug', 'missionSlug');
|
|
65
|
+
if (!slug)
|
|
66
|
+
return null;
|
|
67
|
+
return join(cwd, '.omx', 'specs', `autoresearch-${slug}`, 'completion.json');
|
|
68
|
+
}
|
|
69
|
+
function resolveArtifactPath(cwd, rawState) {
|
|
70
|
+
const explicit = lookupString(rawState, 'completion_artifact_path', 'completionArtifactPath', 'validator_artifact_path', 'validatorArtifactPath');
|
|
71
|
+
if (explicit)
|
|
72
|
+
return resolveMaybeRelativePath(cwd, explicit);
|
|
73
|
+
return deriveDefaultArtifactPath(cwd, rawState);
|
|
74
|
+
}
|
|
75
|
+
async function readJsonIfExists(path) {
|
|
76
|
+
if (!path || !existsSync(path))
|
|
77
|
+
return null;
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(await readFile(path, 'utf-8'));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function isPassingStatus(value) {
|
|
86
|
+
const normalized = safeString(value).toLowerCase();
|
|
87
|
+
return ['pass', 'passed', 'complete', 'completed', 'success', 'succeeded', 'approved'].includes(normalized);
|
|
88
|
+
}
|
|
89
|
+
function hasArchitectApproval(artifact) {
|
|
90
|
+
if (!artifact)
|
|
91
|
+
return false;
|
|
92
|
+
const direct = lookupBoolean(artifact, 'architect_approved', 'architectApproved', 'approved');
|
|
93
|
+
if (direct === true)
|
|
94
|
+
return true;
|
|
95
|
+
const architectReview = safeObject(artifact.architect_review) ?? safeObject(artifact.architectReview);
|
|
96
|
+
const architectValidation = safeObject(artifact.architect_validation) ?? safeObject(artifact.architectValidation);
|
|
97
|
+
return isPassingStatus(architectReview?.verdict) || isPassingStatus(architectValidation?.verdict);
|
|
98
|
+
}
|
|
99
|
+
function resolveOutputArtifactPath(cwd, rawState, artifact) {
|
|
100
|
+
const explicit = lookupString(rawState, 'output_artifact_path', 'outputArtifactPath')
|
|
101
|
+
|| lookupString(artifact, 'output_artifact_path', 'outputArtifactPath');
|
|
102
|
+
if (!explicit)
|
|
103
|
+
return null;
|
|
104
|
+
return resolveMaybeRelativePath(cwd, explicit);
|
|
105
|
+
}
|
|
106
|
+
export async function assessAutoresearchCompletionState(rawState, cwd) {
|
|
107
|
+
const validationMode = normalizeAutoresearchValidationMode(lookupString(rawState, 'validation_mode', 'validationMode'));
|
|
108
|
+
if (!rawState) {
|
|
109
|
+
return { complete: false, reason: 'missing_mode_state', validationMode: null, artifactPath: null };
|
|
110
|
+
}
|
|
111
|
+
if (!validationMode) {
|
|
112
|
+
return { complete: false, reason: 'missing_validation_mode', validationMode: null, artifactPath: resolveArtifactPath(cwd, rawState) };
|
|
113
|
+
}
|
|
114
|
+
const artifactPath = resolveArtifactPath(cwd, rawState);
|
|
115
|
+
const artifact = await readJsonIfExists(artifactPath);
|
|
116
|
+
if (!artifactPath) {
|
|
117
|
+
return { complete: false, reason: 'missing_completion_artifact_path', validationMode, artifactPath: null };
|
|
118
|
+
}
|
|
119
|
+
if (!artifact) {
|
|
120
|
+
return { complete: false, reason: 'missing_or_invalid_completion_artifact', validationMode, artifactPath };
|
|
121
|
+
}
|
|
122
|
+
if (validationMode === 'mission-validator-script') {
|
|
123
|
+
const validatorCommand = lookupString(rawState, 'mission_validator_command', 'missionValidatorCommand')
|
|
124
|
+
|| lookupString(safeObject(rawState.mission_validator), 'command');
|
|
125
|
+
if (!validatorCommand) {
|
|
126
|
+
return { complete: false, reason: 'missing_mission_validator_command', validationMode, artifactPath };
|
|
127
|
+
}
|
|
128
|
+
if (lookupBoolean(artifact, 'passed', 'complete', 'completed', 'valid') === true || isPassingStatus(artifact.status)) {
|
|
129
|
+
return { complete: true, reason: 'validator_passed', validationMode, artifactPath };
|
|
130
|
+
}
|
|
131
|
+
return { complete: false, reason: 'validator_not_passed', validationMode, artifactPath };
|
|
132
|
+
}
|
|
133
|
+
const validatorPrompt = lookupString(rawState, 'validator_prompt', 'validatorPrompt')
|
|
134
|
+
|| lookupString(artifact, 'validator_prompt', 'validatorPrompt');
|
|
135
|
+
if (!validatorPrompt) {
|
|
136
|
+
return { complete: false, reason: 'missing_validator_prompt', validationMode, artifactPath };
|
|
137
|
+
}
|
|
138
|
+
const outputArtifactPath = resolveOutputArtifactPath(cwd, rawState, artifact);
|
|
139
|
+
if (!outputArtifactPath || !existsSync(outputArtifactPath)) {
|
|
140
|
+
return { complete: false, reason: 'missing_output_artifact', validationMode, artifactPath, outputArtifactPath };
|
|
141
|
+
}
|
|
142
|
+
if (!hasArchitectApproval(artifact)) {
|
|
143
|
+
return { complete: false, reason: 'missing_architect_approval', validationMode, artifactPath, outputArtifactPath };
|
|
144
|
+
}
|
|
145
|
+
return { complete: true, reason: 'architect_approved', validationMode, artifactPath, outputArtifactPath };
|
|
146
|
+
}
|
|
147
|
+
export async function readAutoresearchModeState(cwd, sessionId) {
|
|
148
|
+
const candidates = await getReadScopedStatePaths('autoresearch', cwd, sessionId);
|
|
149
|
+
for (const candidatePath of candidates) {
|
|
150
|
+
if (!existsSync(candidatePath))
|
|
151
|
+
continue;
|
|
152
|
+
try {
|
|
153
|
+
return JSON.parse(await readFile(candidatePath, 'utf-8'));
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
export async function readAutoresearchCompletionStatus(cwd, sessionId) {
|
|
162
|
+
const state = await readAutoresearchModeState(cwd, sessionId);
|
|
163
|
+
return assessAutoresearchCompletionState(state, cwd);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=skill-validation.js.map
|