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
|
@@ -2,7 +2,11 @@ import {
|
|
|
2
2
|
buildDocumentRefreshAdvisoryOutput,
|
|
3
3
|
evaluateStagedDocumentRefresh,
|
|
4
4
|
} from "../document-refresh/enforcer.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
OMX_LORE_COMMIT_GUARD_ENV,
|
|
7
|
+
isLoreCommitGuardEnabled,
|
|
8
|
+
readConfiguredLoreCommitGuardValue,
|
|
9
|
+
} from "../config/commit-lore-guard.js";
|
|
6
10
|
import { resolveCodexExecutionSurface } from "./codex-execution-surface.js";
|
|
7
11
|
|
|
8
12
|
type CodexHookPayload = Record<string, unknown>;
|
|
@@ -747,6 +751,17 @@ function buildEffectiveLoreCommitGuardEnv(parsed: GitCommitCommandParseResult):
|
|
|
747
751
|
for (const [name, value] of Object.entries(parsed.inlineEnvironment)) {
|
|
748
752
|
if (typeof value === "string") effectiveEnvironment[name] = value;
|
|
749
753
|
}
|
|
754
|
+
|
|
755
|
+
if (
|
|
756
|
+
!parsed.environmentStartsClean
|
|
757
|
+
&& !parsed.unsetEnvironmentNames.includes(OMX_LORE_COMMIT_GUARD_ENV)
|
|
758
|
+
&& typeof effectiveEnvironment[OMX_LORE_COMMIT_GUARD_ENV] !== "string"
|
|
759
|
+
) {
|
|
760
|
+
const configuredValue = readConfiguredLoreCommitGuardValue(effectiveEnvironment);
|
|
761
|
+
if (typeof configuredValue === "string") {
|
|
762
|
+
effectiveEnvironment[OMX_LORE_COMMIT_GUARD_ENV] = configuredValue;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
750
765
|
return effectiveEnvironment;
|
|
751
766
|
}
|
|
752
767
|
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
import { readFile } from "fs/promises";
|
|
9
9
|
import { spawnSync } from "child_process";
|
|
10
|
+
import { closeSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeFileSync } from "fs";
|
|
11
|
+
import { dirname, join } from "path";
|
|
12
|
+
import { tmpdir } from "os";
|
|
10
13
|
|
|
11
14
|
interface NotifyDispatcherMetadata {
|
|
12
15
|
managedBy?: string;
|
|
@@ -16,6 +19,195 @@ interface NotifyDispatcherMetadata {
|
|
|
16
19
|
dispatcherNotify?: string[];
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
const DISPATCH_LOCK_STALE_MS = 45_000;
|
|
23
|
+
// Codex Desktop can replay a backlog of turn-ended callbacks well after the UI
|
|
24
|
+
// window has gone away. Keep the default same-turn coalescing window longer
|
|
25
|
+
// than a heavily loaded notification hook invocation so sequential queued
|
|
26
|
+
// callbacks from one thread do not slip through merely because the first
|
|
27
|
+
// dispatch was slow. Payloads with different thread/session identity retain
|
|
28
|
+
// independent notification cadence.
|
|
29
|
+
const DEFAULT_TURN_DISPATCH_MIN_INTERVAL_MS = 10_000;
|
|
30
|
+
const DEFAULT_STALE_EVENT_AGE_MS = 5 * 60_000;
|
|
31
|
+
|
|
32
|
+
interface DispatchGuard {
|
|
33
|
+
ok: boolean;
|
|
34
|
+
release?: () => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface DispatchGuardState {
|
|
38
|
+
lastDispatchAt?: unknown;
|
|
39
|
+
lastDispatchByIdentity?: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseNonNegativeEnvMs(name: string, fallback: number): number {
|
|
43
|
+
const raw = process.env[name];
|
|
44
|
+
if (typeof raw !== "string" || raw.trim() === "") return fallback;
|
|
45
|
+
const parsed = Number(raw);
|
|
46
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function parsePayloadObject(payloadArg: string): Record<string, unknown> | null {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(payloadArg) as unknown;
|
|
52
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
53
|
+
? (parsed as Record<string, unknown>)
|
|
54
|
+
: null;
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isTurnEndedPayload(payload: Record<string, unknown> | null): boolean {
|
|
61
|
+
if (!payload) return false;
|
|
62
|
+
const type = String(payload.type ?? payload.event ?? payload.hook_event_name ?? "")
|
|
63
|
+
.trim()
|
|
64
|
+
.toLowerCase();
|
|
65
|
+
return type === ""
|
|
66
|
+
|| type === "agent-turn-complete"
|
|
67
|
+
|| type === "turn-complete"
|
|
68
|
+
|| type === "turn-ended";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function readPayloadTimestampMs(payload: Record<string, unknown>): number | null {
|
|
72
|
+
for (const key of ["timestamp", "created_at", "createdAt", "event_time", "eventTime", "time"]) {
|
|
73
|
+
const value = payload[key];
|
|
74
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
75
|
+
return value > 1_000_000_000_000 ? value : value * 1000;
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === "string" && value.trim()) {
|
|
78
|
+
const parsed = Date.parse(value);
|
|
79
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function readPayloadIdentity(payload: Record<string, unknown> | null): string {
|
|
86
|
+
if (!payload) return "global";
|
|
87
|
+
for (const key of [
|
|
88
|
+
"thread_id",
|
|
89
|
+
"threadId",
|
|
90
|
+
"conversation_id",
|
|
91
|
+
"conversationId",
|
|
92
|
+
"session_id",
|
|
93
|
+
"sessionId",
|
|
94
|
+
]) {
|
|
95
|
+
const value = payload[key];
|
|
96
|
+
if (typeof value === "string" && value.trim()) {
|
|
97
|
+
return `${key}:${value.trim()}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return "global";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function dispatchGuardDir(metadataPath: string): string {
|
|
104
|
+
if (metadataPath) return dirname(metadataPath);
|
|
105
|
+
return join(tmpdir(), "oh-my-codex-notify-dispatch");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function writeDispatchGuardState(
|
|
109
|
+
statePath: string,
|
|
110
|
+
state: DispatchGuardState,
|
|
111
|
+
identity: string,
|
|
112
|
+
minIntervalMs: number,
|
|
113
|
+
staleEventAgeMs: number,
|
|
114
|
+
): void {
|
|
115
|
+
const previousByIdentity = state.lastDispatchByIdentity && typeof state.lastDispatchByIdentity === "object"
|
|
116
|
+
? state.lastDispatchByIdentity
|
|
117
|
+
: {};
|
|
118
|
+
const retainedByIdentity: Record<string, number> = {};
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
const retentionMs = Math.max(minIntervalMs, staleEventAgeMs, DEFAULT_TURN_DISPATCH_MIN_INTERVAL_MS);
|
|
121
|
+
for (const [key, value] of Object.entries(previousByIdentity)) {
|
|
122
|
+
if (typeof value === "number" && now - value <= retentionMs) {
|
|
123
|
+
retainedByIdentity[key] = value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
retainedByIdentity[identity] = now;
|
|
127
|
+
writeFileSync(statePath, JSON.stringify({
|
|
128
|
+
lastDispatchAt: identity === "global" ? now : (typeof state.lastDispatchAt === "number" ? state.lastDispatchAt : undefined),
|
|
129
|
+
lastDispatchByIdentity: retainedByIdentity,
|
|
130
|
+
pid: process.pid,
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function acquireTurnDispatchGuard(metadataPath: string, payloadArg: string): DispatchGuard {
|
|
135
|
+
const payload = parsePayloadObject(payloadArg);
|
|
136
|
+
if (!isTurnEndedPayload(payload)) return { ok: true };
|
|
137
|
+
|
|
138
|
+
const now = Date.now();
|
|
139
|
+
const staleEventAgeMs = parseNonNegativeEnvMs("OMX_NOTIFY_DISPATCH_STALE_EVENT_AGE_MS", DEFAULT_STALE_EVENT_AGE_MS);
|
|
140
|
+
const eventTimestampMs = payload ? readPayloadTimestampMs(payload) : null;
|
|
141
|
+
if (eventTimestampMs !== null && staleEventAgeMs > 0 && now - eventTimestampMs > staleEventAgeMs) {
|
|
142
|
+
return { ok: false };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const dir = dispatchGuardDir(metadataPath);
|
|
146
|
+
mkdirSync(dir, { recursive: true });
|
|
147
|
+
const lockPath = join(dir, "notify-dispatch.lock");
|
|
148
|
+
const statePath = join(dir, "notify-dispatch.guard.json");
|
|
149
|
+
try {
|
|
150
|
+
const lockStat = statSync(lockPath);
|
|
151
|
+
if (now - lockStat.mtimeMs > DISPATCH_LOCK_STALE_MS) unlinkSync(lockPath);
|
|
152
|
+
} catch {
|
|
153
|
+
// Missing or unreadable lock: try to acquire below.
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let fd: number;
|
|
157
|
+
try {
|
|
158
|
+
fd = openSync(lockPath, "wx");
|
|
159
|
+
writeFileSync(fd, String(process.pid));
|
|
160
|
+
closeSync(fd);
|
|
161
|
+
} catch {
|
|
162
|
+
return { ok: false };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const release = () => {
|
|
166
|
+
try {
|
|
167
|
+
unlinkSync(lockPath);
|
|
168
|
+
} catch {
|
|
169
|
+
// Best effort.
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const minIntervalMs = parseNonNegativeEnvMs("OMX_NOTIFY_DISPATCH_MIN_INTERVAL_MS", DEFAULT_TURN_DISPATCH_MIN_INTERVAL_MS);
|
|
175
|
+
const identity = readPayloadIdentity(payload);
|
|
176
|
+
let state: DispatchGuardState = {};
|
|
177
|
+
try {
|
|
178
|
+
state = JSON.parse(readFileSync(statePath, "utf-8")) as typeof state;
|
|
179
|
+
} catch {
|
|
180
|
+
// No prior guard state.
|
|
181
|
+
}
|
|
182
|
+
if (minIntervalMs > 0) {
|
|
183
|
+
const byIdentity = state.lastDispatchByIdentity && typeof state.lastDispatchByIdentity === "object"
|
|
184
|
+
? state.lastDispatchByIdentity
|
|
185
|
+
: {};
|
|
186
|
+
const identityLastDispatchAt = typeof byIdentity[identity] === "number" ? byIdentity[identity] : 0;
|
|
187
|
+
const legacyLastDispatchAt = identity === "global" && typeof state.lastDispatchAt === "number" ? state.lastDispatchAt : 0;
|
|
188
|
+
const lastDispatchAt = Math.max(identityLastDispatchAt, legacyLastDispatchAt);
|
|
189
|
+
if (lastDispatchAt > 0 && now - lastDispatchAt < minIntervalMs) {
|
|
190
|
+
release();
|
|
191
|
+
return { ok: false };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
ok: true,
|
|
196
|
+
release: () => {
|
|
197
|
+
try {
|
|
198
|
+
writeDispatchGuardState(statePath, state, identity, minIntervalMs, staleEventAgeMs);
|
|
199
|
+
} catch {
|
|
200
|
+
// Guard state is best effort; the lock still prevents concurrent duplicate dispatch.
|
|
201
|
+
}
|
|
202
|
+
release();
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
} catch {
|
|
206
|
+
release();
|
|
207
|
+
return { ok: false };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
19
211
|
function parseArgs(): { metadataPath: string; payloadArg: string } {
|
|
20
212
|
let metadataPath = "";
|
|
21
213
|
const args = process.argv.slice(2);
|
|
@@ -200,11 +392,17 @@ function runNotify(
|
|
|
200
392
|
async function main(): Promise<void> {
|
|
201
393
|
const { metadataPath, payloadArg } = parseArgs();
|
|
202
394
|
if (!payloadArg || payloadArg.startsWith("-")) return;
|
|
203
|
-
const
|
|
204
|
-
if (!
|
|
205
|
-
|
|
395
|
+
const guard = acquireTurnDispatchGuard(metadataPath, payloadArg);
|
|
396
|
+
if (!guard.ok) return;
|
|
397
|
+
try {
|
|
398
|
+
const metadata = await readMetadata(metadataPath);
|
|
399
|
+
if (!isManagedPreviousNotify(metadata?.previousNotify, metadata)) {
|
|
400
|
+
runNotify(metadata?.previousNotify, payloadArg);
|
|
401
|
+
}
|
|
402
|
+
runNotify(metadata?.omxNotify, payloadArg);
|
|
403
|
+
} finally {
|
|
404
|
+
guard.release?.();
|
|
206
405
|
}
|
|
207
|
-
runNotify(metadata?.omxNotify, payloadArg);
|
|
208
406
|
}
|
|
209
407
|
|
|
210
408
|
main().catch(() => {});
|
|
@@ -17,35 +17,59 @@ export function runProcess(command: string, args: string[], timeoutMs = 3000): P
|
|
|
17
17
|
let stdout = '';
|
|
18
18
|
let stderr = '';
|
|
19
19
|
let finished = false;
|
|
20
|
+
let sigkillTimer: ReturnType<typeof setTimeout> | undefined;
|
|
20
21
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const cleanup = (clearPendingSigkill = true) => {
|
|
23
|
+
clearTimeout(timer);
|
|
24
|
+
if (clearPendingSigkill && sigkillTimer) {
|
|
25
|
+
clearTimeout(sigkillTimer);
|
|
26
|
+
sigkillTimer = undefined;
|
|
27
|
+
}
|
|
28
|
+
child.stdout.off('data', onStdout);
|
|
29
|
+
child.stderr.off('data', onStderr);
|
|
30
|
+
child.off('error', onError);
|
|
31
|
+
child.off('close', onClose);
|
|
32
|
+
};
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
const onStdout = (chunk: Buffer) => {
|
|
29
35
|
stdout += chunk.toString();
|
|
30
|
-
}
|
|
31
|
-
|
|
36
|
+
};
|
|
37
|
+
const onStderr = (chunk: Buffer) => {
|
|
32
38
|
stderr += chunk.toString();
|
|
33
|
-
}
|
|
34
|
-
|
|
39
|
+
};
|
|
40
|
+
const onError = (err: Error) => {
|
|
35
41
|
if (finished) return;
|
|
36
42
|
finished = true;
|
|
37
|
-
|
|
43
|
+
cleanup();
|
|
38
44
|
reject(err);
|
|
39
|
-
}
|
|
40
|
-
|
|
45
|
+
};
|
|
46
|
+
const onClose = (code: number | null) => {
|
|
41
47
|
if (finished) return;
|
|
42
48
|
finished = true;
|
|
43
|
-
|
|
49
|
+
cleanup();
|
|
44
50
|
if (code === 0) {
|
|
45
51
|
resolve({ stdout, stderr, code });
|
|
46
52
|
} else {
|
|
47
53
|
reject(new Error(stderr.trim() || `${command} exited ${code}`));
|
|
48
54
|
}
|
|
49
|
-
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const timer = setTimeout(() => {
|
|
58
|
+
if (finished) return;
|
|
59
|
+
finished = true;
|
|
60
|
+
child.kill('SIGTERM');
|
|
61
|
+
sigkillTimer = setTimeout(() => {
|
|
62
|
+
sigkillTimer = undefined;
|
|
63
|
+
child.kill('SIGKILL');
|
|
64
|
+
}, 250);
|
|
65
|
+
sigkillTimer.unref?.();
|
|
66
|
+
cleanup(false);
|
|
67
|
+
reject(new Error(`timeout after ${effectiveTimeoutMs}ms`));
|
|
68
|
+
}, effectiveTimeoutMs);
|
|
69
|
+
|
|
70
|
+
child.stdout.on('data', onStdout);
|
|
71
|
+
child.stderr.on('data', onStderr);
|
|
72
|
+
child.on('error', onError);
|
|
73
|
+
child.on('close', onClose);
|
|
50
74
|
});
|
|
51
75
|
}
|
|
@@ -822,6 +822,7 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
822
822
|
prompt: request.trigger_message,
|
|
823
823
|
submitKeyPresses,
|
|
824
824
|
typePrompt: shouldTypePrompt,
|
|
825
|
+
queueFirstSubmit: leaderTargeted,
|
|
825
826
|
});
|
|
826
827
|
if (!sendResult.ok) {
|
|
827
828
|
return {
|
|
@@ -876,11 +877,13 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
876
877
|
tmux_injection_attempted: true,
|
|
877
878
|
};
|
|
878
879
|
}
|
|
879
|
-
// Do not declare success while a
|
|
880
|
-
//
|
|
881
|
-
//
|
|
882
|
-
//
|
|
883
|
-
|
|
880
|
+
// Do not declare success while a pane is not input-ready. Otherwise a
|
|
881
|
+
// pre-ready send can be marked "confirmed" and later appear as a stuck
|
|
882
|
+
// unsent draft once the UI finishes loading. This includes leader-fixed:
|
|
883
|
+
// its Codex UI can show "tab to queue message" while busy, and marking
|
|
884
|
+
// delivered before queue/consumption confirmation loses the orchestration
|
|
885
|
+
// nudge until a human presses Tab manually.
|
|
886
|
+
if (!paneLooksReady(wideCap.stdout)) {
|
|
884
887
|
continue;
|
|
885
888
|
}
|
|
886
889
|
if (!triggerInNarrow && !triggerNearTail) {
|
|
@@ -904,6 +907,7 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
904
907
|
prompt: request.trigger_message,
|
|
905
908
|
submitKeyPresses,
|
|
906
909
|
typePrompt: false,
|
|
910
|
+
queueFirstSubmit: leaderTargeted,
|
|
907
911
|
}).catch(() => {});
|
|
908
912
|
}
|
|
909
913
|
|
|
@@ -134,6 +134,7 @@ export async function sendPaneInput({
|
|
|
134
134
|
submitKeyPresses = 2,
|
|
135
135
|
submitDelayMs = 0,
|
|
136
136
|
typePrompt = true,
|
|
137
|
+
queueFirstSubmit = false,
|
|
137
138
|
}: any): Promise<any> {
|
|
138
139
|
const target = safeString(paneTarget).trim();
|
|
139
140
|
if (!target) {
|
|
@@ -163,6 +164,12 @@ export async function sendPaneInput({
|
|
|
163
164
|
if (typePrompt) {
|
|
164
165
|
await runProcess('tmux', argv.typeArgv, 3000);
|
|
165
166
|
}
|
|
167
|
+
if (queueFirstSubmit && argv.submitArgv.length > 0) {
|
|
168
|
+
await runProcess('tmux', ['send-keys', '-t', target, 'Tab'], 3000);
|
|
169
|
+
if (submitDelayMs > 0) {
|
|
170
|
+
await new Promise((resolve) => setTimeout(resolve, submitDelayMs));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
166
173
|
for (const submit of argv.submitArgv) {
|
|
167
174
|
if (submitDelayMs > 0) {
|
|
168
175
|
await new Promise((resolve) => setTimeout(resolve, submitDelayMs));
|
|
@@ -5,6 +5,14 @@ import { join, resolve } from 'node:path';
|
|
|
5
5
|
const DEFAULT_TEST_TIMEOUT_MS = 0;
|
|
6
6
|
const DEFAULT_RUNNER_TIMEOUT_MS = 30 * 60 * 1_000;
|
|
7
7
|
const DEFAULT_CI_TEST_CONCURRENCY = 1;
|
|
8
|
+
const RUNTIME_STATE_ENV_KEYS = [
|
|
9
|
+
'OMX_ROOT',
|
|
10
|
+
'OMX_STATE_ROOT',
|
|
11
|
+
'OMX_TEAM_STATE_ROOT',
|
|
12
|
+
'OMX_SESSION_ID',
|
|
13
|
+
'CODEX_SESSION_ID',
|
|
14
|
+
'SESSION_ID',
|
|
15
|
+
] as const;
|
|
8
16
|
|
|
9
17
|
function parseBooleanEnv(value: string | undefined): boolean {
|
|
10
18
|
if (!value) return false;
|
|
@@ -91,6 +99,11 @@ console.error(
|
|
|
91
99
|
const childEnv = { ...process.env };
|
|
92
100
|
delete childEnv.NODE_TEST_CONTEXT;
|
|
93
101
|
childEnv.OMX_TEST_RELAX_TMUX_TIMEOUT = '1';
|
|
102
|
+
if (!parseBooleanEnv(process.env.OMX_NODE_TEST_PRESERVE_RUNTIME_ENV)) {
|
|
103
|
+
for (const key of RUNTIME_STATE_ENV_KEYS) {
|
|
104
|
+
delete childEnv[key];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
94
107
|
|
|
95
108
|
const result = spawnSync(process.execPath, testArgs, {
|
|
96
109
|
stdio: 'inherit',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mkdtempSync,
|
|
3
|
+
realpathSync,
|
|
3
4
|
rmSync,
|
|
4
5
|
} from 'node:fs';
|
|
5
6
|
import { mkdirSync } from 'node:fs';
|
|
@@ -24,6 +25,16 @@ export const PACKED_INSTALL_SMOKE_CORE_COMMANDS = [
|
|
|
24
25
|
['sparkshell', '--help'],
|
|
25
26
|
] as const;
|
|
26
27
|
|
|
28
|
+
export const PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS = [
|
|
29
|
+
'SessionStart',
|
|
30
|
+
'PreToolUse',
|
|
31
|
+
'PostToolUse',
|
|
32
|
+
'UserPromptSubmit',
|
|
33
|
+
'PreCompact',
|
|
34
|
+
'PostCompact',
|
|
35
|
+
'Stop',
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
27
38
|
function usage(): string {
|
|
28
39
|
return [
|
|
29
40
|
'Usage: node scripts/smoke-packed-install.mjs',
|
|
@@ -112,6 +123,99 @@ function npmBinName(name: string): string {
|
|
|
112
123
|
return process.platform === 'win32' ? `${name}.cmd` : name;
|
|
113
124
|
}
|
|
114
125
|
|
|
126
|
+
function resolveGlobalNodeModules(prefixDir: string): string {
|
|
127
|
+
const result = run('npm', ['root', '-g', '--prefix', prefixDir], { cwd: prefixDir });
|
|
128
|
+
const root = String(result.stdout || '').trim();
|
|
129
|
+
if (!root) throw new Error('npm root -g did not return a node_modules directory');
|
|
130
|
+
return root;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function validateHookStdout(eventName: string, stdout: string): void {
|
|
134
|
+
const trimmed = stdout.trim();
|
|
135
|
+
if (!trimmed) return;
|
|
136
|
+
try {
|
|
137
|
+
JSON.parse(trimmed);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`native hook ${eventName} emitted invalid JSON stdout: ${error instanceof Error ? error.message : String(error)}`,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function buildNativeHookSmokePayload(
|
|
146
|
+
eventName: typeof PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS[number],
|
|
147
|
+
smokeCwd: string,
|
|
148
|
+
): Record<string, unknown> {
|
|
149
|
+
const base = {
|
|
150
|
+
hook_event_name: eventName,
|
|
151
|
+
session_id: `packed-install-smoke-${eventName}`,
|
|
152
|
+
cwd: smokeCwd,
|
|
153
|
+
};
|
|
154
|
+
switch (eventName) {
|
|
155
|
+
case 'SessionStart':
|
|
156
|
+
return {
|
|
157
|
+
...base,
|
|
158
|
+
transcript_path: join(smokeCwd, 'nonexistent-transcript.jsonl'),
|
|
159
|
+
};
|
|
160
|
+
case 'PreToolUse':
|
|
161
|
+
return {
|
|
162
|
+
...base,
|
|
163
|
+
tool_name: 'Bash',
|
|
164
|
+
tool_use_id: 'packed-install-smoke-tool',
|
|
165
|
+
tool_input: { command: 'echo packed install smoke' },
|
|
166
|
+
};
|
|
167
|
+
case 'PostToolUse':
|
|
168
|
+
return {
|
|
169
|
+
...base,
|
|
170
|
+
tool_name: 'Bash',
|
|
171
|
+
tool_use_id: 'packed-install-smoke-tool',
|
|
172
|
+
tool_input: { command: 'echo packed install smoke' },
|
|
173
|
+
tool_response: {
|
|
174
|
+
exit_code: 0,
|
|
175
|
+
stdout: 'packed install smoke\n',
|
|
176
|
+
stderr: '',
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
case 'UserPromptSubmit':
|
|
180
|
+
return {
|
|
181
|
+
...base,
|
|
182
|
+
transcript_path: join(smokeCwd, 'nonexistent-transcript.jsonl'),
|
|
183
|
+
prompt: 'packed install native hook smoke test',
|
|
184
|
+
};
|
|
185
|
+
case 'PreCompact':
|
|
186
|
+
case 'PostCompact':
|
|
187
|
+
case 'Stop':
|
|
188
|
+
return base;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function smokeInstalledNativeHookDist(prefixDir: string): void {
|
|
193
|
+
const globalNodeModules = resolveGlobalNodeModules(prefixDir);
|
|
194
|
+
const packageRoot = join(globalNodeModules, 'oh-my-codex');
|
|
195
|
+
const hookScript = join(packageRoot, 'dist', 'scripts', 'codex-native-hook.js');
|
|
196
|
+
const smokeCwd = mkdtempSync(join(tmpdir(), 'omx-packed-hook-smoke-'));
|
|
197
|
+
try {
|
|
198
|
+
for (const eventName of PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS) {
|
|
199
|
+
const payload = buildNativeHookSmokePayload(eventName, smokeCwd);
|
|
200
|
+
const result = run(process.execPath, [realpathSync(hookScript)], {
|
|
201
|
+
cwd: smokeCwd,
|
|
202
|
+
env: {
|
|
203
|
+
...process.env,
|
|
204
|
+
OMX_NATIVE_HOOK_DOCTOR_SMOKE: '1',
|
|
205
|
+
OMX_ROOT: join(smokeCwd, '.omx-packed-hook-root'),
|
|
206
|
+
OMX_SESSION_ID: `packed-install-smoke-${eventName}`,
|
|
207
|
+
OMX_SOURCE_CWD: smokeCwd,
|
|
208
|
+
OMX_STARTUP_CWD: smokeCwd,
|
|
209
|
+
},
|
|
210
|
+
input: JSON.stringify(payload),
|
|
211
|
+
});
|
|
212
|
+
validateHookStdout(eventName, result.stdout as string);
|
|
213
|
+
}
|
|
214
|
+
} finally {
|
|
215
|
+
rmSync(smokeCwd, { recursive: true, force: true });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
115
219
|
export function parseNpmPackJsonOutput(stdout: string): Array<{ filename: string }> {
|
|
116
220
|
const start = stdout.lastIndexOf('\n[');
|
|
117
221
|
const jsonText = (start >= 0 ? stdout.slice(start + 1) : stdout).trim();
|
|
@@ -147,6 +251,7 @@ async function main(): Promise<void> {
|
|
|
147
251
|
for (const argv of PACKED_INSTALL_SMOKE_CORE_COMMANDS) {
|
|
148
252
|
run(omxPath, argv, { cwd: repoRoot });
|
|
149
253
|
}
|
|
254
|
+
smokeInstalledNativeHookDist(prefixDir);
|
|
150
255
|
|
|
151
256
|
console.log('packed install smoke: PASS');
|
|
152
257
|
} finally {
|
|
@@ -55,7 +55,6 @@ const PLUGIN_NAME = "oh-my-codex";
|
|
|
55
55
|
const SETUP_OWNED_PLUGIN_MANIFEST_FIELDS = [
|
|
56
56
|
"agents",
|
|
57
57
|
"prompts",
|
|
58
|
-
"hooks",
|
|
59
58
|
] as const;
|
|
60
59
|
|
|
61
60
|
async function readJsonFile<T>(path: string): Promise<T> {
|
|
@@ -199,13 +198,14 @@ async function assertPluginManifestPolicy(
|
|
|
199
198
|
const pkg = await readJsonFile<PackageJson>(join(root, "package.json"));
|
|
200
199
|
const expectedFields: Pick<
|
|
201
200
|
PluginManifest,
|
|
202
|
-
"name" | "version" | "skills" | "mcpServers" | "apps"
|
|
201
|
+
"name" | "version" | "skills" | "mcpServers" | "apps" | "hooks"
|
|
203
202
|
> = {
|
|
204
203
|
name: PLUGIN_NAME,
|
|
205
204
|
version: pkg.version,
|
|
206
205
|
skills: "./skills/",
|
|
207
206
|
mcpServers: "./.mcp.json",
|
|
208
207
|
apps: "./.app.json",
|
|
208
|
+
hooks: "./hooks/hooks.json",
|
|
209
209
|
};
|
|
210
210
|
|
|
211
211
|
for (const [field, expectedValue] of Object.entries(expectedFields)) {
|
|
@@ -229,7 +229,7 @@ async function assertPluginManifestPolicy(
|
|
|
229
229
|
"plugin_bundle_metadata_out_of_sync",
|
|
230
230
|
"kind=plugin-manifest",
|
|
231
231
|
`field=${field}`,
|
|
232
|
-
"message=setup-owned agents/prompts
|
|
232
|
+
"message=setup-owned agents/prompts must not be plugin-scoped",
|
|
233
233
|
].join("\n"),
|
|
234
234
|
);
|
|
235
235
|
}
|
|
@@ -199,11 +199,11 @@ export async function verifyNativeAgents(
|
|
|
199
199
|
? await readPluginManifest(root)
|
|
200
200
|
: options.pluginManifest;
|
|
201
201
|
if (pluginManifest) {
|
|
202
|
-
for (const field of ["agents", "prompts"
|
|
202
|
+
for (const field of ["agents", "prompts"]) {
|
|
203
203
|
if (pluginManifest[field] !== undefined) {
|
|
204
204
|
throw errorBlock("native_agent_plugin_boundary_violation", {
|
|
205
205
|
field,
|
|
206
|
-
message: "native agents/prompts
|
|
206
|
+
message: "native agents/prompts are setup-owned, not plugin-scoped",
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
}
|
|
@@ -108,6 +108,13 @@
|
|
|
108
108
|
"core": false,
|
|
109
109
|
"internalRequired": false
|
|
110
110
|
},
|
|
111
|
+
{
|
|
112
|
+
"name": "prometheus-strict",
|
|
113
|
+
"category": "planning",
|
|
114
|
+
"status": "active",
|
|
115
|
+
"core": false,
|
|
116
|
+
"internalRequired": false
|
|
117
|
+
},
|
|
111
118
|
{
|
|
112
119
|
"name": "best-practice-research",
|
|
113
120
|
"category": "planning",
|
|
@@ -499,6 +506,21 @@
|
|
|
499
506
|
"status": "merged",
|
|
500
507
|
"canonical": "analyst"
|
|
501
508
|
},
|
|
509
|
+
{
|
|
510
|
+
"name": "prometheus-strict-metis",
|
|
511
|
+
"category": "coordination",
|
|
512
|
+
"status": "active"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"name": "prometheus-strict-momus",
|
|
516
|
+
"category": "coordination",
|
|
517
|
+
"status": "active"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
"name": "prometheus-strict-oracle",
|
|
521
|
+
"category": "coordination",
|
|
522
|
+
"status": "active"
|
|
523
|
+
},
|
|
502
524
|
{
|
|
503
525
|
"name": "critic",
|
|
504
526
|
"category": "coordination",
|