oh-my-codex 0.18.0 → 0.18.2
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 +6 -6
- package/Cargo.toml +1 -1
- package/README.md +45 -19
- package/crates/omx-api/src/lib.rs +66 -9
- package/crates/omx-sparkshell/src/exec.rs +125 -3
- package/crates/omx-sparkshell/src/main.rs +126 -36
- package/crates/omx-sparkshell/tests/execution.rs +225 -1
- package/dist/agents/__tests__/definitions.test.js +14 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +19 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +30 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/native-config.d.ts +1 -0
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +4 -0
- package/dist/agents/native-config.js.map +1 -1
- package/dist/catalog/__tests__/generator.test.js +4 -0
- package/dist/catalog/__tests__/generator.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 +137 -8
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +203 -15
- 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 +163 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +29 -43
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +94 -35
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +20 -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/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 +297 -17
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +465 -110
- package/dist/cli/index.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 +13 -3
- 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 +22 -11
- 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.d.ts +1 -0
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +8 -10
- 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 +17 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +124 -11
- package/dist/config/generator.js.map +1 -1
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +21 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +4 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.js +50 -3
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -6
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- 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 +173 -17
- package/dist/hooks/__tests__/keyword-detector.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__/prometheus-strict-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js +320 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +12 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts +2 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.js +35 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.js.map +1 -0
- 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 +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +36 -9
- 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 +14 -2
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +36 -8
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +122 -11
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +84 -0
- package/dist/hud/__tests__/render.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__/state.test.js +51 -1
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +69 -23
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/index.d.ts +2 -2
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +17 -6
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +6 -3
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +26 -0
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts +2 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +62 -1
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.d.ts +10 -3
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +60 -11
- package/dist/hud/tmux.js.map +1 -1
- package/dist/hud/types.d.ts +22 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.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 +128 -4
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +460 -9
- 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 +85 -17
- 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/ralplan.d.ts.map +1 -1
- package/dist/pipeline/stages/ralplan.js +41 -6
- package/dist/pipeline/stages/ralplan.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/question/__tests__/ui.test.js +43 -10
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/ui.d.ts +12 -0
- package/dist/question/ui.d.ts.map +1 -1
- package/dist/question/ui.js +83 -46
- package/dist/question/ui.js.map +1 -1
- package/dist/ralplan/__tests__/runtime.test.js +200 -10
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts +23 -0
- package/dist/ralplan/consensus-gate.d.ts.map +1 -0
- package/dist/ralplan/consensus-gate.js +212 -0
- package/dist/ralplan/consensus-gate.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +25 -0
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +144 -8
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +1358 -79
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/docs-site-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/docs-site-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/docs-site-contract.test.js +42 -0
- package/dist/scripts/__tests__/docs-site-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js +115 -2
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
- package/dist/scripts/__tests__/run-test-files.test.js +57 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +23 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +18 -3
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- 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 +372 -44
- 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 +9 -1
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-dispatcher.js +188 -4
- 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 +9 -5
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +7 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/run-test-files.js +13 -0
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +3 -0
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +99 -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/__tests__/workflow-transition.test.js +6 -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 +11 -0
- package/dist/state/operations.js.map +1 -1
- package/dist/state/workflow-transition.d.ts +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +7 -0
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +4 -3
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +36 -44
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +163 -15
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +10 -20
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +51 -21
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +764 -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 +837 -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/package.json +2 -1
- 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 +92 -50
- package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +4 -0
- package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/best-practice-research/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/cancel/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +23 -12
- package/plugins/oh-my-codex/skills/plan/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/prometheus-strict/README.md +35 -0
- package/plugins/oh-my-codex/skills/prometheus-strict/SKILL.md +219 -0
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +7 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +22 -7
- 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/prometheus-strict-metis.md +274 -0
- package/prompts/prometheus-strict-momus.md +82 -0
- package/prompts/prometheus-strict-oracle.md +107 -0
- package/prompts/researcher.md +22 -3
- package/skills/autopilot/SKILL.md +92 -50
- package/skills/autoresearch/SKILL.md +4 -0
- package/skills/autoresearch-goal/SKILL.md +1 -1
- package/skills/best-practice-research/SKILL.md +1 -1
- package/skills/cancel/SKILL.md +2 -2
- package/skills/deep-interview/SKILL.md +8 -8
- package/skills/omx-setup/SKILL.md +1 -1
- package/skills/pipeline/SKILL.md +23 -12
- package/skills/plan/SKILL.md +8 -8
- package/skills/prometheus-strict/README.md +35 -0
- package/skills/prometheus-strict/SKILL.md +219 -0
- package/skills/ralph/SKILL.md +7 -0
- package/skills/ralplan/SKILL.md +22 -7
- 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 +1757 -210
- package/src/scripts/__tests__/docs-site-contract.test.ts +47 -0
- package/src/scripts/__tests__/notify-dispatcher.test.ts +132 -3
- package/src/scripts/__tests__/run-test-files.test.ts +67 -0
- package/src/scripts/__tests__/smoke-packed-install.test.ts +31 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +23 -3
- package/src/scripts/cleanup-explore-harness.ts +1 -0
- package/src/scripts/codex-native-hook.ts +393 -40
- package/src/scripts/codex-native-pre-post.ts +16 -1
- package/src/scripts/notify-dispatcher.ts +202 -4
- package/src/scripts/notify-hook/process-runner.ts +40 -16
- package/src/scripts/notify-hook/team-dispatch.ts +9 -5
- package/src/scripts/notify-hook/team-tmux-guard.ts +7 -0
- package/src/scripts/run-test-files.ts +13 -0
- package/src/scripts/smoke-packed-install.ts +105 -0
- package/src/scripts/sync-plugin-mirror.ts +3 -3
- package/src/scripts/verify-native-agents.ts +2 -2
- package/templates/catalog-manifest.json +22 -0
package/Cargo.lock
CHANGED
|
@@ -32,7 +32,7 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
|
32
32
|
|
|
33
33
|
[[package]]
|
|
34
34
|
name = "omx-api"
|
|
35
|
-
version = "0.18.
|
|
35
|
+
version = "0.18.2"
|
|
36
36
|
dependencies = [
|
|
37
37
|
"serde",
|
|
38
38
|
"serde_json",
|
|
@@ -40,14 +40,14 @@ dependencies = [
|
|
|
40
40
|
|
|
41
41
|
[[package]]
|
|
42
42
|
name = "omx-explore-harness"
|
|
43
|
-
version = "0.18.
|
|
43
|
+
version = "0.18.2"
|
|
44
44
|
dependencies = [
|
|
45
45
|
"libc",
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
[[package]]
|
|
49
49
|
name = "omx-mux"
|
|
50
|
-
version = "0.18.
|
|
50
|
+
version = "0.18.2"
|
|
51
51
|
dependencies = [
|
|
52
52
|
"serde",
|
|
53
53
|
"serde_json",
|
|
@@ -55,7 +55,7 @@ dependencies = [
|
|
|
55
55
|
|
|
56
56
|
[[package]]
|
|
57
57
|
name = "omx-runtime"
|
|
58
|
-
version = "0.18.
|
|
58
|
+
version = "0.18.2"
|
|
59
59
|
dependencies = [
|
|
60
60
|
"omx-mux",
|
|
61
61
|
"omx-runtime-core",
|
|
@@ -64,7 +64,7 @@ dependencies = [
|
|
|
64
64
|
|
|
65
65
|
[[package]]
|
|
66
66
|
name = "omx-runtime-core"
|
|
67
|
-
version = "0.18.
|
|
67
|
+
version = "0.18.2"
|
|
68
68
|
dependencies = [
|
|
69
69
|
"fs2",
|
|
70
70
|
"serde",
|
|
@@ -73,7 +73,7 @@ dependencies = [
|
|
|
73
73
|
|
|
74
74
|
[[package]]
|
|
75
75
|
name = "omx-sparkshell"
|
|
76
|
-
version = "0.18.
|
|
76
|
+
version = "0.18.2"
|
|
77
77
|
dependencies = [
|
|
78
78
|
"omx-mux",
|
|
79
79
|
]
|
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
**Community:** [Discord](https://discord.gg/PUwSMR9XNk) — shared OMX/community server for oh-my-codex and related tooling.
|
|
19
19
|
|
|
20
|
+
## Official project and package
|
|
21
|
+
|
|
22
|
+
The official/original OMX project is this repository, [`Yeachan-Heo/oh-my-codex`](https://github.com/Yeachan-Heo/oh-my-codex), and the official npm package for this project is [`oh-my-codex`](https://www.npmjs.com/package/oh-my-codex). Install this project with `npm install -g oh-my-codex` (or alongside Codex CLI as shown below).
|
|
23
|
+
|
|
24
|
+
Third-party projects or forks that use names such as “OMX v2” are not official continuations, replacements, or release lines for this repository unless this README or the docs explicitly say so. When in doubt, trust this repository and the `oh-my-codex` package as the official install target.
|
|
25
|
+
|
|
20
26
|
OMX is a workflow layer for [OpenAI Codex CLI](https://github.com/openai/codex).
|
|
21
27
|
|
|
22
28
|
<table>
|
|
@@ -28,7 +34,7 @@ OMX is a workflow layer for [OpenAI Codex CLI](https://github.com/openai/codex).
|
|
|
28
34
|
It keeps Codex as the execution engine and makes it easier to:
|
|
29
35
|
- start a stronger Codex session by default
|
|
30
36
|
- run one consistent workflow from clarification to completion
|
|
31
|
-
- invoke the canonical
|
|
37
|
+
- invoke the canonical default workflow with `$deep-interview`, `$ralplan`, and `$ultragoal`
|
|
32
38
|
- keep project guidance, plans, logs, and state in `.omx/`
|
|
33
39
|
|
|
34
40
|
## Core Maintainers
|
|
@@ -58,34 +64,50 @@ It keeps Codex as the execution engine and makes it easier to:
|
|
|
58
64
|
|
|
59
65
|
If you want the default OMX experience, start here:
|
|
60
66
|
|
|
67
|
+
Choose one install path. If Codex CLI is already installed (Homebrew, npm, or another supported method):
|
|
68
|
+
|
|
61
69
|
```bash
|
|
62
|
-
|
|
70
|
+
codex --version
|
|
71
|
+
npm install -g oh-my-codex
|
|
72
|
+
omx setup
|
|
63
73
|
omx --madmax --high
|
|
64
74
|
```
|
|
65
75
|
|
|
76
|
+
If you do not have Codex CLI yet and want npm to manage it:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm install -g @openai/codex
|
|
80
|
+
npm install -g oh-my-codex
|
|
81
|
+
omx setup
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Do not run a combined `npm install -g @openai/codex oh-my-codex` over an existing Homebrew-owned `codex` binary such as `/opt/homebrew/bin/codex`; npm may fail with `EEXIST` when `@openai/codex` tries to create the same binary. OMX only needs a working, authenticated `codex` command on `PATH`; it does not require Codex to be installed through npm.
|
|
85
|
+
|
|
66
86
|
On a real `oh-my-codex` version bump, the global npm install now prints an explicit reminder instead of launching `omx setup` automatically. When you're ready, run `omx setup` manually or use `omx update` to check npm and then run the same setup refresh path.
|
|
67
87
|
|
|
68
|
-
|
|
88
|
+
OMX also checks for npm updates at launch on a throttled cadence and prompts before scheduling the update after the current session exits. Set `OMX_AUTO_UPDATE=0` to disable the launch-time check, or set `OMX_AUTO_UPDATE=defer` to schedule the same deferred update without prompting.
|
|
89
|
+
|
|
90
|
+
**Codex plugin install note:** this repo also ships an official Codex plugin layout at `plugins/oh-my-codex` with marketplace metadata in `.agents/plugins/marketplace.json`. That plugin bundles the mirrored skill surface plus plugin-scoped companion metadata for official Codex lifecycle hooks, optional MCP compatibility servers, and apps. It is still **not** a replacement for `npm install -g oh-my-codex` plus `omx setup`: plugin-scoped hooks launch the installed `omx` CLI, legacy setup mode installs native agents and prompts, and plugin setup mode relies on plugin discovery for bundled skills while archiving/removing legacy OMX-managed prompts/native-agent TOMLs so stale role files cannot shadow plugin behavior.
|
|
69
91
|
|
|
70
92
|
Then work normally inside Codex:
|
|
71
93
|
|
|
72
94
|
```text
|
|
73
95
|
$deep-interview "clarify the authentication change"
|
|
74
96
|
$ralplan "approve the auth plan and review tradeoffs"
|
|
75
|
-
$
|
|
76
|
-
$
|
|
77
|
-
$ultragoal "turn this launch into durable Codex goals"
|
|
97
|
+
$prometheus-strict "stress-test the plan before durable execution"
|
|
98
|
+
$ultragoal "turn the approved plan into durable Codex goals"
|
|
78
99
|
```
|
|
79
100
|
|
|
80
101
|
That is the main path.
|
|
81
102
|
Before you treat the runtime as ready, run the quick-start smoke test below: `omx doctor` verifies the install shape, while `omx exec` proves the active Codex runtime can actually authenticate and complete a model call from the current environment.
|
|
82
|
-
Start OMX strongly, clarify first when needed, approve the plan, then
|
|
103
|
+
Start OMX strongly, clarify first when needed, approve the plan, optionally use `$prometheus-strict` for interview-driven plan hardening on high-risk work, then use `$ultragoal` as the default durable completion wrapper. Use `$team` inside that execution path only when a specific Ultragoal story needs coordinated parallel work; use `$ralph` when you intentionally want a single-owner completion loop instead of a durable multi-goal run.
|
|
83
104
|
|
|
84
105
|
## What OMX is for
|
|
85
106
|
|
|
86
107
|
Use OMX if you already like Codex and want a better day-to-day runtime around it:
|
|
87
|
-
- a standard workflow built around `$deep-interview
|
|
88
|
-
-
|
|
108
|
+
- a standard workflow built around `$deep-interview` -> `$ralplan` -> `$ultragoal`, with `$prometheus-strict` available when plans need stricter interview/critique/synthesis before execution and optional `.omx/plans/prometheus-strict/` artifacts
|
|
109
|
+
- research boundaries: use `$best-practice-research` for ordinary pre-planning official/upstream evidence, `$autoresearch` for bounded validator-gated research artifacts, `$autoresearch-goal` for goal-mode research missions, and feed any research findings into `$ralplan` for architecture synthesis
|
|
110
|
+
- durable multi-goal handoffs with `$ultragoal` and `.omx/ultragoal` artifacts as the default completion path after planning
|
|
89
111
|
- specialist roles and supporting skills when the task needs them
|
|
90
112
|
- project guidance through scoped `AGENTS.md`
|
|
91
113
|
- durable state under `.omx/` for plans, logs, memory, and mode tracking
|
|
@@ -97,7 +119,7 @@ If you want plain Codex with no extra workflow layer, you probably do not need O
|
|
|
97
119
|
### Requirements
|
|
98
120
|
|
|
99
121
|
- Node.js 20+
|
|
100
|
-
- Codex CLI installed
|
|
122
|
+
- Codex CLI installed, verified with `codex --version`, and authenticated (Homebrew or npm are both fine; do not reinstall `@openai/codex` with npm if Homebrew already owns `codex`)
|
|
101
123
|
- Codex auth configured and visible in the same shell/profile that will run OMX
|
|
102
124
|
- `tmux` on macOS/Linux if you want the recommended durable team runtime
|
|
103
125
|
- `psmux` on native Windows only if you intentionally want the less-supported Windows team path
|
|
@@ -160,11 +182,10 @@ Then try the canonical workflow:
|
|
|
160
182
|
```text
|
|
161
183
|
$deep-interview "clarify the authentication change"
|
|
162
184
|
$ralplan "approve the safest implementation path"
|
|
163
|
-
$
|
|
164
|
-
$team 3:executor "execute the approved plan in parallel"
|
|
185
|
+
$ultragoal "turn the approved path into durable Codex goals"
|
|
165
186
|
```
|
|
166
187
|
|
|
167
|
-
Use `$team` when
|
|
188
|
+
Use `$team` when an active Ultragoal story needs coordinated parallel work, or `$ralph` when one persistent owner should keep pushing to completion without a multi-goal ledger.
|
|
168
189
|
|
|
169
190
|
## A simple mental model
|
|
170
191
|
|
|
@@ -180,20 +201,22 @@ Most users should think of OMX as **better task routing + better workflow + bett
|
|
|
180
201
|
|
|
181
202
|
## Start here if you are new
|
|
182
203
|
|
|
183
|
-
1.
|
|
204
|
+
1. If Codex CLI already exists, verify it with `codex --version` and install or update OMX with `npm install -g oh-my-codex`; otherwise install `@openai/codex` separately first if you want npm to manage Codex
|
|
184
205
|
2. After install or real OMX version bumps, run `omx setup` yourself when you're ready, or use `omx update` when you also want npm to check for and install the latest build before refreshing setup
|
|
185
206
|
3. Run `omx doctor`
|
|
186
207
|
4. Run a real execution smoke test: `codex login status` and `omx exec --skip-git-repo-check -C . "Reply with exactly OMX-EXEC-OK"`
|
|
187
208
|
5. Launch with `omx --madmax --high`
|
|
188
209
|
6. Use `$deep-interview "..."` when the request or boundaries are still unclear
|
|
189
210
|
7. Use `$ralplan "..."` to approve the plan and review tradeoffs
|
|
190
|
-
8.
|
|
211
|
+
8. Use `$ultragoal "..."` to turn the approved plan into durable goals and ledger checkpoints
|
|
191
212
|
|
|
192
213
|
## Recommended workflow
|
|
193
214
|
|
|
194
215
|
1. `$deep-interview` — clarify scope when the request or boundaries are still vague.
|
|
195
216
|
2. `$ralplan` — turn that clarified scope into an approved architecture and implementation plan.
|
|
196
|
-
3. `$
|
|
217
|
+
3. `$ultragoal` — make the approved plan durable as sequential Codex goals with `.omx/ultragoal` ledger checkpoints.
|
|
218
|
+
|
|
219
|
+
Inside an Ultragoal story, use `$team` only when that story benefits from coordinated parallel execution. Use `$ralph` as an intentional alternate completion loop when you do not need a durable multi-goal ledger.
|
|
197
220
|
|
|
198
221
|
## Common in-session surfaces
|
|
199
222
|
|
|
@@ -201,6 +224,7 @@ Most users should think of OMX as **better task routing + better workflow + bett
|
|
|
201
224
|
| --- | --- |
|
|
202
225
|
| `$deep-interview "..."` | clarifying intent, boundaries, and non-goals |
|
|
203
226
|
| `$ralplan "..."` | approving the implementation plan and tradeoffs |
|
|
227
|
+
| `$ultragoal "..."` | durable multi-goal completion after the approved plan |
|
|
204
228
|
| `$ralph "..."` | persistent completion and verification loops |
|
|
205
229
|
| `$team "..."` | coordinated parallel execution when the work is big enough |
|
|
206
230
|
| `/skills` | browsing installed skills and supporting helpers |
|
|
@@ -223,19 +247,21 @@ omx team shutdown <team-name>
|
|
|
223
247
|
### Setup, doctor, and HUD
|
|
224
248
|
|
|
225
249
|
These are operator/support surfaces:
|
|
226
|
-
- Codex plugin marketplace install/discovery can cache the plugin under `${CODEX_HOME:-~/.codex}/plugins/cache/$MARKETPLACE_NAME/oh-my-codex/$VERSION/` (local installs may use `local` as the version identifier); that packaged plugin includes plugin-scoped companion metadata for optional MCP compatibility servers and apps (disabled by default),
|
|
227
|
-
- `omx setup` installs prompts, skills, AGENTS scaffolding, `.codex/config.toml`, and OMX-managed native Codex hooks in `.codex/hooks.json`
|
|
250
|
+
- Codex plugin marketplace install/discovery can cache the plugin under `${CODEX_HOME:-~/.codex}/plugins/cache/$MARKETPLACE_NAME/oh-my-codex/$VERSION/` (local installs may use `local` as the version identifier); that packaged plugin includes plugin-scoped companion metadata for official Codex lifecycle hooks, optional MCP compatibility servers, and apps (MCP/apps disabled by default), so it is still paired with the installed `omx` CLI for runtime execution
|
|
251
|
+
- `omx setup` installs prompts, skills, AGENTS scaffolding, `.codex/config.toml`, and (for legacy installs or older Codex without `plugin_hooks`) OMX-managed native Codex hooks in `.codex/hooks.json`
|
|
228
252
|
- setup refresh preserves non-OMX hook entries in `.codex/hooks.json` and only rewrites OMX-managed wrappers
|
|
229
253
|
- `omx setup --merge-agents` preserves existing `AGENTS.md` guidance while inserting or refreshing generated OMX sections between `<!-- OMX:AGENTS:START -->` / `<!-- OMX:AGENTS:END -->`; without `--merge-agents` or `--force`, non-interactive setup keeps skipping existing `AGENTS.md` files
|
|
230
254
|
- `omx uninstall` removes OMX-managed wrappers from `.codex/hooks.json` but keeps the file when user hooks remain
|
|
231
255
|
- `omx update` checks npm immediately, installs the newest global OMX build, then reruns the same interactive setup refresh path
|
|
256
|
+
- launch-time update checks are throttled and prompt by default; use `OMX_AUTO_UPDATE=0` to disable them or `OMX_AUTO_UPDATE=defer` to schedule deferred updates without a prompt
|
|
232
257
|
- fresh OMX-managed `gpt-5.5` config seeding now recommends `model_context_window = 250000` and `model_auto_compact_token_limit = 200000`, but only when those keys are missing
|
|
233
258
|
- `.omx-config.json` model/env routing is documented in [the model/env routing reference](./docs/reference/omx-config-schema-routing.md); only edit keys supported by your installed OMX version
|
|
234
259
|
- `omx doctor` verifies the install when something seems wrong; it does not prove that the active Codex profile can make an authenticated model call
|
|
235
260
|
- `omx hud --watch` is a monitoring/status surface, not the primary user workflow
|
|
236
261
|
|
|
237
262
|
For non-team sessions, native Codex hooks are now the canonical lifecycle surface:
|
|
238
|
-
-
|
|
263
|
+
- `plugins/oh-my-codex/hooks/hooks.json` = official plugin-scoped hook registrations for plugin installs
|
|
264
|
+
- `.codex/hooks.json` = legacy/fallback native Codex hook registrations preserved for legacy installs and older Codex versions
|
|
239
265
|
- `.omx/hooks/*.mjs` = OMX plugin hooks
|
|
240
266
|
- `omx tmux-hook` / notify-hook / derived watcher = tmux + runtime fallback paths
|
|
241
267
|
|
|
@@ -6,7 +6,7 @@ use std::fs;
|
|
|
6
6
|
use std::io::{self, BufRead, BufReader, Read, Write};
|
|
7
7
|
use std::net::{IpAddr, Shutdown, TcpListener, TcpStream};
|
|
8
8
|
use std::path::{Path, PathBuf};
|
|
9
|
-
use std::process::{Command, Stdio};
|
|
9
|
+
use std::process::{Child, Command, Stdio};
|
|
10
10
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
11
11
|
use std::sync::{Arc, Mutex};
|
|
12
12
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
@@ -1934,17 +1934,49 @@ fn spawn_daemon(config: &ServerConfig) -> Result<DaemonState> {
|
|
|
1934
1934
|
.stdout(Stdio::null())
|
|
1935
1935
|
.stderr(Stdio::null())
|
|
1936
1936
|
.spawn()?;
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1937
|
+
wait_for_daemon_state(
|
|
1938
|
+
&mut child,
|
|
1939
|
+
&config.state_file,
|
|
1940
|
+
100,
|
|
1941
|
+
Duration::from_millis(20),
|
|
1942
|
+
)
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
fn terminate_child(child: &mut Child) {
|
|
1946
|
+
let _ = child.kill();
|
|
1947
|
+
let _ = child.wait();
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
fn wait_for_daemon_state(
|
|
1951
|
+
child: &mut Child,
|
|
1952
|
+
state_file: &Path,
|
|
1953
|
+
attempts: usize,
|
|
1954
|
+
sleep: Duration,
|
|
1955
|
+
) -> Result<DaemonState> {
|
|
1956
|
+
for _ in 0..attempts {
|
|
1957
|
+
match read_daemon_state(state_file) {
|
|
1958
|
+
Ok(Some(state)) => return Ok(state),
|
|
1959
|
+
Ok(None) => {}
|
|
1960
|
+
Err(error) => {
|
|
1961
|
+
terminate_child(child);
|
|
1962
|
+
return Err(error);
|
|
1963
|
+
}
|
|
1940
1964
|
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1965
|
+
match child.try_wait() {
|
|
1966
|
+
Ok(Some(status)) => {
|
|
1967
|
+
return Err(OmxApiError::Message(format!(
|
|
1968
|
+
"daemon exited before writing state: {status}"
|
|
1969
|
+
)));
|
|
1970
|
+
}
|
|
1971
|
+
Ok(None) => {}
|
|
1972
|
+
Err(error) => {
|
|
1973
|
+
terminate_child(child);
|
|
1974
|
+
return Err(error.into());
|
|
1975
|
+
}
|
|
1945
1976
|
}
|
|
1946
|
-
std::thread::sleep(
|
|
1977
|
+
std::thread::sleep(sleep);
|
|
1947
1978
|
}
|
|
1979
|
+
terminate_child(child);
|
|
1948
1980
|
Err(OmxApiError::Message(
|
|
1949
1981
|
"daemon did not write state within timeout".to_string(),
|
|
1950
1982
|
))
|
|
@@ -2930,6 +2962,31 @@ mod tests {
|
|
|
2930
2962
|
assert!(read_daemon_state(&path).unwrap().is_none());
|
|
2931
2963
|
}
|
|
2932
2964
|
|
|
2965
|
+
#[test]
|
|
2966
|
+
fn daemon_startup_timeout_kills_child_process_to_avoid_process_leak() {
|
|
2967
|
+
let path = env::temp_dir().join(format!("omx-api-timeout-test-{}.json", now_unix()));
|
|
2968
|
+
let mut child = Command::new("sh")
|
|
2969
|
+
.arg("-c")
|
|
2970
|
+
.arg("sleep 60")
|
|
2971
|
+
.stdin(Stdio::null())
|
|
2972
|
+
.stdout(Stdio::null())
|
|
2973
|
+
.stderr(Stdio::null())
|
|
2974
|
+
.spawn()
|
|
2975
|
+
.expect("spawn sleep child");
|
|
2976
|
+
|
|
2977
|
+
let error = wait_for_daemon_state(&mut child, &path, 1, Duration::from_millis(1))
|
|
2978
|
+
.expect_err("missing state should time out");
|
|
2979
|
+
|
|
2980
|
+
assert!(error
|
|
2981
|
+
.to_string()
|
|
2982
|
+
.contains("daemon did not write state within timeout"));
|
|
2983
|
+
assert!(
|
|
2984
|
+
child.try_wait().unwrap().is_some(),
|
|
2985
|
+
"timeout path should reap the spawned daemon child"
|
|
2986
|
+
);
|
|
2987
|
+
let _ = fs::remove_file(path);
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2933
2990
|
#[test]
|
|
2934
2991
|
fn cli_system_dry_run_is_json() {
|
|
2935
2992
|
let mut out = Vec::new();
|
|
@@ -26,8 +26,82 @@ impl CommandOutput {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
pub fn
|
|
30
|
-
|
|
29
|
+
pub fn resolve_shell_argv(script: &str) -> Vec<String> {
|
|
30
|
+
resolve_shell_argv_for_platform(script, current_platform(), command_exists_on_path)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
34
|
+
enum ShellPlatform {
|
|
35
|
+
Windows,
|
|
36
|
+
Posix,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fn current_platform() -> ShellPlatform {
|
|
40
|
+
if cfg!(windows) {
|
|
41
|
+
ShellPlatform::Windows
|
|
42
|
+
} else {
|
|
43
|
+
ShellPlatform::Posix
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fn resolve_shell_argv_for_platform(
|
|
48
|
+
script: &str,
|
|
49
|
+
platform: ShellPlatform,
|
|
50
|
+
exists: impl Fn(&str) -> bool,
|
|
51
|
+
) -> Vec<String> {
|
|
52
|
+
match platform {
|
|
53
|
+
ShellPlatform::Posix => vec!["bash".to_string(), "-lc".to_string(), script.to_string()],
|
|
54
|
+
ShellPlatform::Windows => {
|
|
55
|
+
if exists("pwsh") {
|
|
56
|
+
return vec![
|
|
57
|
+
"pwsh".to_string(),
|
|
58
|
+
"-NoLogo".to_string(),
|
|
59
|
+
"-NoProfile".to_string(),
|
|
60
|
+
"-Command".to_string(),
|
|
61
|
+
script.to_string(),
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
if exists("powershell.exe") {
|
|
65
|
+
return vec![
|
|
66
|
+
"powershell.exe".to_string(),
|
|
67
|
+
"-NoLogo".to_string(),
|
|
68
|
+
"-NoProfile".to_string(),
|
|
69
|
+
"-Command".to_string(),
|
|
70
|
+
script.to_string(),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
vec![
|
|
74
|
+
std::env::var("ComSpec").unwrap_or_else(|_| "cmd.exe".to_string()),
|
|
75
|
+
"/d".to_string(),
|
|
76
|
+
"/s".to_string(),
|
|
77
|
+
"/c".to_string(),
|
|
78
|
+
script.to_string(),
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fn command_exists_on_path(command: &str) -> bool {
|
|
85
|
+
if command.contains(std::path::MAIN_SEPARATOR)
|
|
86
|
+
|| command.contains('/')
|
|
87
|
+
|| command.contains('\\')
|
|
88
|
+
{
|
|
89
|
+
return std::path::Path::new(command).is_file();
|
|
90
|
+
}
|
|
91
|
+
let Some(path) = std::env::var_os("PATH") else {
|
|
92
|
+
return false;
|
|
93
|
+
};
|
|
94
|
+
std::env::split_paths(&path).any(|dir| {
|
|
95
|
+
let candidate = dir.join(command);
|
|
96
|
+
candidate.is_file()
|
|
97
|
+
|| if cfg!(windows) && std::path::Path::new(command).extension().is_none() {
|
|
98
|
+
["exe", "cmd", "bat", "com"]
|
|
99
|
+
.iter()
|
|
100
|
+
.any(|ext| dir.join(format!("{command}.{ext}")).is_file())
|
|
101
|
+
} else {
|
|
102
|
+
false
|
|
103
|
+
}
|
|
104
|
+
})
|
|
31
105
|
}
|
|
32
106
|
|
|
33
107
|
pub fn execute_command(argv: &[String]) -> Result<CommandOutput, SparkshellError> {
|
|
@@ -106,7 +180,7 @@ fn build_windows_command(command_name: &str, args: &[String]) -> Command {
|
|
|
106
180
|
|
|
107
181
|
#[cfg(test)]
|
|
108
182
|
mod tests {
|
|
109
|
-
use super::execute_command;
|
|
183
|
+
use super::{execute_command, resolve_shell_argv_for_platform, ShellPlatform};
|
|
110
184
|
|
|
111
185
|
#[test]
|
|
112
186
|
fn rejects_missing_command() {
|
|
@@ -116,4 +190,52 @@ mod tests {
|
|
|
116
190
|
"usage: omx-sparkshell <command> [args...]"
|
|
117
191
|
);
|
|
118
192
|
}
|
|
193
|
+
|
|
194
|
+
#[test]
|
|
195
|
+
fn posix_shell_mode_uses_bash_lc() {
|
|
196
|
+
assert_eq!(
|
|
197
|
+
resolve_shell_argv_for_platform("printf ok", ShellPlatform::Posix, |_| false),
|
|
198
|
+
["bash", "-lc", "printf ok"]
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
#[test]
|
|
203
|
+
fn windows_shell_mode_prefers_pwsh() {
|
|
204
|
+
assert_eq!(
|
|
205
|
+
resolve_shell_argv_for_platform("Write-Output ok", ShellPlatform::Windows, |name| {
|
|
206
|
+
name == "pwsh"
|
|
207
|
+
}),
|
|
208
|
+
[
|
|
209
|
+
"pwsh",
|
|
210
|
+
"-NoLogo",
|
|
211
|
+
"-NoProfile",
|
|
212
|
+
"-Command",
|
|
213
|
+
"Write-Output ok"
|
|
214
|
+
]
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#[test]
|
|
219
|
+
fn windows_shell_mode_falls_back_to_windows_powershell() {
|
|
220
|
+
assert_eq!(
|
|
221
|
+
resolve_shell_argv_for_platform("Write-Output ok", ShellPlatform::Windows, |name| {
|
|
222
|
+
name == "powershell.exe"
|
|
223
|
+
}),
|
|
224
|
+
[
|
|
225
|
+
"powershell.exe",
|
|
226
|
+
"-NoLogo",
|
|
227
|
+
"-NoProfile",
|
|
228
|
+
"-Command",
|
|
229
|
+
"Write-Output ok"
|
|
230
|
+
]
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
#[test]
|
|
235
|
+
fn windows_shell_mode_uses_minimal_cmd_fallback() {
|
|
236
|
+
assert_eq!(
|
|
237
|
+
resolve_shell_argv_for_platform("echo ok", ShellPlatform::Windows, |_| false),
|
|
238
|
+
["cmd.exe", "/d", "/s", "/c", "echo ok"]
|
|
239
|
+
);
|
|
240
|
+
}
|
|
119
241
|
}
|