oh-my-codex 0.16.2 → 0.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/README.md +3 -3
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/cli/__tests__/cleanup.test.js +27 -0
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +137 -6
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +303 -4
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +58 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +48 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +8 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +350 -27
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +85 -3
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +1 -1
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +269 -0
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +69 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +90 -6
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +109 -19
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +8 -4
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/codex-feature-probe.d.ts +9 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -0
- package/dist/cli/codex-feature-probe.js +28 -0
- package/dist/cli/codex-feature-probe.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +168 -16
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +168 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +8 -8
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +3 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +88 -0
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +21 -0
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +4 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +7 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -3
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +177 -43
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +54 -15
- package/dist/cli/team.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 +64 -5
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/uninstall.d.ts +2 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +76 -5
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update.d.ts +10 -2
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +99 -5
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
- package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
- package/dist/config/__tests__/codex-feature-flags.test.js +35 -0
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.js +188 -4
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +129 -10
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +148 -7
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
- package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
- package/dist/config/codex-feature-flags.d.ts +21 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -0
- package/dist/config/codex-feature-flags.js +56 -0
- package/dist/config/codex-feature-flags.js.map +1 -0
- package/dist/config/codex-hooks.d.ts +40 -4
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +204 -18
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/generator.d.ts +19 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +319 -83
- package/dist/config/generator.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +3 -1
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
- package/dist/config/omx-first-party-mcp.js +2 -2
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +92 -2
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +29 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +10 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +1 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +176 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +148 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +3 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.js +1 -2
- package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +1 -1
- package/dist/hooks/agents-overlay.js +2 -2
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +7 -5
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +164 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +4 -5
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +61 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +166 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +23 -2
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +22 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +57 -26
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +5 -0
- package/dist/modes/base.js.map +1 -1
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +316 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +481 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/artifacts.test.js +597 -4
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/__tests__/context-pack-status.test.js +524 -0
- package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
- package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
- package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
- package/dist/planning/__tests__/markdown-structure.test.js +459 -0
- package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts +2 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts.map +1 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +612 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -0
- package/dist/planning/artifacts.d.ts +7 -2
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +279 -26
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/planning/context-pack-status.d.ts +31 -0
- package/dist/planning/context-pack-status.d.ts.map +1 -1
- package/dist/planning/context-pack-status.js +291 -25
- package/dist/planning/context-pack-status.js.map +1 -1
- package/dist/planning/markdown-structure.d.ts +20 -0
- package/dist/planning/markdown-structure.d.ts.map +1 -0
- package/dist/planning/markdown-structure.js +137 -0
- package/dist/planning/markdown-structure.js.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.js +121 -0
- package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
- package/dist/ralph/completion-audit.d.ts +8 -0
- package/dist/ralph/completion-audit.d.ts.map +1 -0
- package/dist/ralph/completion-audit.js +99 -0
- package/dist/ralph/completion-audit.js.map +1 -0
- package/dist/ralph/persistence.d.ts +1 -1
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +8 -2
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +359 -24
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js +126 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +142 -76
- 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 +4 -2
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-dispatcher.d.ts +7 -0
- package/dist/scripts/notify-dispatcher.d.ts.map +1 -0
- package/dist/scripts/notify-dispatcher.js +87 -0
- package/dist/scripts/notify-dispatcher.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +4 -0
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +96 -8
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +6 -2
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/visual-verdict.js +3 -3
- package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
- package/dist/scripts/notify-hook.js +127 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +102 -27
- 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 +9 -3
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +7 -0
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +25 -8
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +1 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +22 -15
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.js +3 -3
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.js +84 -1
- package/dist/team/__tests__/approved-execution.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +178 -19
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +497 -2
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +1 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +45 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/approved-execution.d.ts +1 -0
- package/dist/team/approved-execution.d.ts.map +1 -1
- package/dist/team/approved-execution.js +53 -0
- package/dist/team/approved-execution.js.map +1 -1
- package/dist/team/delivery-log.d.ts.map +1 -1
- package/dist/team/delivery-log.js +8 -1
- package/dist/team/delivery-log.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +104 -18
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +43 -0
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/mailbox.d.ts +1 -0
- package/dist/team/state/mailbox.d.ts.map +1 -1
- package/dist/team/state/mailbox.js +10 -1
- package/dist/team/state/mailbox.js.map +1 -1
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +5 -1
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +3 -7
- package/dist/team/state.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +7 -2
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +17 -4
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +124 -1
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts +44 -2
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +197 -13
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/wiki/lifecycle.js +1 -1
- package/dist/wiki/lifecycle.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/.mcp.json +5 -5
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +21 -24
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
- package/skills/analyze/SKILL.md +0 -2
- package/skills/ask-claude/SKILL.md +5 -3
- package/skills/ask-gemini/SKILL.md +5 -3
- package/skills/autopilot/SKILL.md +2 -2
- package/skills/code-review/SKILL.md +1 -3
- package/skills/deep-interview/SKILL.md +5 -7
- package/skills/doctor/SKILL.md +2 -2
- package/skills/ecomode/SKILL.md +105 -1
- package/skills/frontend-ui-ux/SKILL.md +4 -26
- package/skills/git-master/SKILL.md +2 -4
- package/skills/omx-setup/SKILL.md +3 -3
- package/skills/pipeline/SKILL.md +3 -3
- package/skills/plan/SKILL.md +3 -6
- package/skills/ralph/SKILL.md +9 -10
- package/skills/swarm/SKILL.md +5 -3
- package/skills/tdd/SKILL.md +95 -1
- package/skills/ultragoal/SKILL.md +36 -3
- package/skills/ultraqa/SKILL.md +21 -24
- package/skills/ultrawork/SKILL.md +8 -8
- package/skills/web-clone/SKILL.md +348 -1
- package/skills/wiki/SKILL.md +13 -13
- package/src/scripts/__tests__/codex-native-hook.test.ts +389 -24
- package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
- package/src/scripts/codex-native-hook.ts +168 -64
- package/src/scripts/codex-native-pre-post.ts +4 -1
- package/src/scripts/notify-dispatcher.ts +113 -0
- package/src/scripts/notify-fallback-watcher.ts +6 -2
- package/src/scripts/notify-hook/ralph-session-resume.ts +117 -8
- package/src/scripts/notify-hook/state-io.ts +4 -2
- package/src/scripts/notify-hook/visual-verdict.ts +3 -3
- package/src/scripts/notify-hook.ts +119 -1
|
@@ -24,6 +24,7 @@ import { writeSessionStart } from "../../hooks/session.js";
|
|
|
24
24
|
import { resetTriageConfigCache } from "../../hooks/triage-config.js";
|
|
25
25
|
import { executeStateOperation } from "../../state/operations.js";
|
|
26
26
|
import { OMX_TMUX_HUD_OWNER_ENV } from "../../hud/reconcile.js";
|
|
27
|
+
import { readAllState } from "../../hud/state.js";
|
|
27
28
|
import { writePage } from "../../wiki/storage.js";
|
|
28
29
|
import { WIKI_SCHEMA_VERSION } from "../../wiki/types.js";
|
|
29
30
|
|
|
@@ -236,7 +237,7 @@ describe("codex native hook config", () => {
|
|
|
236
237
|
matcher?: string;
|
|
237
238
|
hooks?: Array<Record<string, unknown>>;
|
|
238
239
|
};
|
|
239
|
-
assert.equal(sessionStart.matcher, "startup|resume");
|
|
240
|
+
assert.equal(sessionStart.matcher, "startup|resume|clear");
|
|
240
241
|
assert.equal(sessionStart.hooks?.[0]?.statusMessage, undefined);
|
|
241
242
|
|
|
242
243
|
const preToolUse = config.hooks.PreToolUse[0] as {
|
|
@@ -276,6 +277,20 @@ describe("codex native hook config", () => {
|
|
|
276
277
|
hooks?: Array<Record<string, unknown>>;
|
|
277
278
|
};
|
|
278
279
|
assert.equal(stop.hooks?.[0]?.timeout, 30);
|
|
280
|
+
|
|
281
|
+
const postCompact = config.hooks.PostCompact[0] as {
|
|
282
|
+
matcher?: string;
|
|
283
|
+
hooks?: Array<Record<string, unknown>>;
|
|
284
|
+
};
|
|
285
|
+
assert.equal(postCompact.matcher, undefined);
|
|
286
|
+
assert.match(
|
|
287
|
+
String(postCompact.hooks?.[0]?.command || ""),
|
|
288
|
+
/codex-native-hook\.js"?$/,
|
|
289
|
+
);
|
|
290
|
+
assert.doesNotMatch(
|
|
291
|
+
String(postCompact.hooks?.[0]?.command || ""),
|
|
292
|
+
/PostCompact Nudge|additionalContext|printf/,
|
|
293
|
+
);
|
|
279
294
|
});
|
|
280
295
|
});
|
|
281
296
|
|
|
@@ -522,7 +537,7 @@ describe("codex native hook dispatch", () => {
|
|
|
522
537
|
|
|
523
538
|
|
|
524
539
|
|
|
525
|
-
it("
|
|
540
|
+
it("does not write PreCompact stdout that Codex rejects as hook JSON", async () => {
|
|
526
541
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-precompact-"));
|
|
527
542
|
try {
|
|
528
543
|
writePage(cwd, {
|
|
@@ -549,16 +564,44 @@ describe("codex native hook dispatch", () => {
|
|
|
549
564
|
|
|
550
565
|
assert.equal(result.hookEventName, "PreCompact");
|
|
551
566
|
assert.equal(result.omxEventName, "pre-compact");
|
|
552
|
-
|
|
553
|
-
?.hookSpecificOutput?.additionalContext ?? "";
|
|
554
|
-
assert.match(additionalContext, /Wiki: 1 pages/);
|
|
555
|
-
assert.match(additionalContext, /architecture/);
|
|
567
|
+
assert.equal(result.outputJson, null);
|
|
556
568
|
} finally {
|
|
557
569
|
await rm(cwd, { recursive: true, force: true });
|
|
558
570
|
}
|
|
559
571
|
});
|
|
560
572
|
|
|
561
|
-
it("
|
|
573
|
+
it("emits no CLI stdout for PreCompact when no Codex action is needed", async () => {
|
|
574
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-precompact-cli-"));
|
|
575
|
+
try {
|
|
576
|
+
writePage(cwd, {
|
|
577
|
+
filename: "architecture.md",
|
|
578
|
+
frontmatter: {
|
|
579
|
+
title: "Architecture",
|
|
580
|
+
tags: ["architecture"],
|
|
581
|
+
created: "2026-05-08T00:00:00.000Z",
|
|
582
|
+
updated: "2026-05-08T00:00:00.000Z",
|
|
583
|
+
sources: [],
|
|
584
|
+
links: [],
|
|
585
|
+
category: "architecture",
|
|
586
|
+
confidence: "high",
|
|
587
|
+
schemaVersion: WIKI_SCHEMA_VERSION,
|
|
588
|
+
},
|
|
589
|
+
content: "\n# Architecture\n\nCompaction-relevant architecture note.\n",
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
const stdout = runNativeHookCli({
|
|
593
|
+
hook_event_name: "PreCompact",
|
|
594
|
+
cwd,
|
|
595
|
+
session_id: "sess-precompact-cli",
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
assert.equal(stdout, "");
|
|
599
|
+
} finally {
|
|
600
|
+
await rm(cwd, { recursive: true, force: true });
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
it("does not write PostCompact stdout that Codex rejects as hook JSON", async () => {
|
|
562
605
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-postcompact-"));
|
|
563
606
|
try {
|
|
564
607
|
const result = await dispatchCodexNativeHook({
|
|
@@ -569,11 +612,22 @@ describe("codex native hook dispatch", () => {
|
|
|
569
612
|
|
|
570
613
|
assert.equal(result.hookEventName, "PostCompact");
|
|
571
614
|
assert.equal(result.omxEventName, "post-compact");
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
615
|
+
assert.equal(result.outputJson, null);
|
|
616
|
+
} finally {
|
|
617
|
+
await rm(cwd, { recursive: true, force: true });
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it("emits no CLI stdout for PostCompact when no Codex action is needed", async () => {
|
|
622
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-postcompact-cli-"));
|
|
623
|
+
try {
|
|
624
|
+
const stdout = runNativeHookCli({
|
|
625
|
+
hook_event_name: "PostCompact",
|
|
626
|
+
cwd,
|
|
627
|
+
session_id: "sess-postcompact-cli",
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
assert.equal(stdout, "");
|
|
577
631
|
} finally {
|
|
578
632
|
await rm(cwd, { recursive: true, force: true });
|
|
579
633
|
}
|
|
@@ -1164,7 +1218,7 @@ describe("codex native hook dispatch", () => {
|
|
|
1164
1218
|
assert.equal(result.omxEventName, "keyword-detector");
|
|
1165
1219
|
assert.equal(result.skillState?.skill, "ralplan");
|
|
1166
1220
|
assert.ok(result.outputJson, "UserPromptSubmit should emit developer context");
|
|
1167
|
-
assert.match(JSON.stringify(result.outputJson), /
|
|
1221
|
+
assert.match(JSON.stringify(result.outputJson), /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
1168
1222
|
|
|
1169
1223
|
assert.equal(
|
|
1170
1224
|
existsSync(join(cwd, ".omx", "state", "skill-active-state.json")),
|
|
@@ -1187,6 +1241,112 @@ describe("codex native hook dispatch", () => {
|
|
|
1187
1241
|
}
|
|
1188
1242
|
});
|
|
1189
1243
|
|
|
1244
|
+
it("records boxed keyword activation mode detail and skill state under OMX_ROOT", async () => {
|
|
1245
|
+
const root = await mkdtemp(join(tmpdir(), "omx-native-hook-boxed-"));
|
|
1246
|
+
const cwd = join(root, "source");
|
|
1247
|
+
const omxRoot = join(root, "box");
|
|
1248
|
+
const sessionId = "sess-boxed-ralplan";
|
|
1249
|
+
const previousOmxRoot = process.env.OMX_ROOT;
|
|
1250
|
+
const previousOmxStateRoot = process.env.OMX_STATE_ROOT;
|
|
1251
|
+
const previousTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
1252
|
+
const previousOmxSessionId = process.env.OMX_SESSION_ID;
|
|
1253
|
+
try {
|
|
1254
|
+
await mkdir(cwd, { recursive: true });
|
|
1255
|
+
process.env.OMX_ROOT = omxRoot;
|
|
1256
|
+
delete process.env.OMX_STATE_ROOT;
|
|
1257
|
+
delete process.env.OMX_TEAM_STATE_ROOT;
|
|
1258
|
+
process.env.OMX_SESSION_ID = sessionId;
|
|
1259
|
+
|
|
1260
|
+
const result = await dispatchCodexNativeHook(
|
|
1261
|
+
{
|
|
1262
|
+
hook_event_name: "UserPromptSubmit",
|
|
1263
|
+
cwd,
|
|
1264
|
+
session_id: sessionId,
|
|
1265
|
+
thread_id: "thread-boxed",
|
|
1266
|
+
turn_id: "turn-boxed",
|
|
1267
|
+
prompt: "$ralplan implement issue #1307",
|
|
1268
|
+
},
|
|
1269
|
+
{ cwd },
|
|
1270
|
+
);
|
|
1271
|
+
|
|
1272
|
+
assert.equal(result.omxEventName, "keyword-detector");
|
|
1273
|
+
assert.equal(result.skillState?.skill, "ralplan");
|
|
1274
|
+
|
|
1275
|
+
const boxedSessionDir = join(omxRoot, ".omx", "state", "sessions", sessionId);
|
|
1276
|
+
assert.equal(existsSync(join(boxedSessionDir, "skill-active-state.json")), true);
|
|
1277
|
+
assert.equal(existsSync(join(boxedSessionDir, "ralplan-state.json")), true);
|
|
1278
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", sessionId, "skill-active-state.json")), false);
|
|
1279
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", sessionId, "ralplan-state.json")), false);
|
|
1280
|
+
|
|
1281
|
+
const hudState = await readAllState(cwd);
|
|
1282
|
+
assert.equal(hudState.ralplan?.active, true);
|
|
1283
|
+
assert.equal(hudState.ralplan?.current_phase, "planning");
|
|
1284
|
+
} finally {
|
|
1285
|
+
if (typeof previousOmxRoot === "string") process.env.OMX_ROOT = previousOmxRoot;
|
|
1286
|
+
else delete process.env.OMX_ROOT;
|
|
1287
|
+
if (typeof previousOmxStateRoot === "string") process.env.OMX_STATE_ROOT = previousOmxStateRoot;
|
|
1288
|
+
else delete process.env.OMX_STATE_ROOT;
|
|
1289
|
+
if (typeof previousTeamStateRoot === "string") process.env.OMX_TEAM_STATE_ROOT = previousTeamStateRoot;
|
|
1290
|
+
else delete process.env.OMX_TEAM_STATE_ROOT;
|
|
1291
|
+
if (typeof previousOmxSessionId === "string") process.env.OMX_SESSION_ID = previousOmxSessionId;
|
|
1292
|
+
else delete process.env.OMX_SESSION_ID;
|
|
1293
|
+
await rm(root, { recursive: true, force: true });
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1297
|
+
it("records native keyword activation mode detail and skill state under OMX_TEAM_STATE_ROOT", async () => {
|
|
1298
|
+
const root = await mkdtemp(join(tmpdir(), "omx-native-hook-team-root-"));
|
|
1299
|
+
const cwd = join(root, "source");
|
|
1300
|
+
const teamStateRoot = join(root, "team-state");
|
|
1301
|
+
const sessionId = "sess-team-root-ralplan";
|
|
1302
|
+
const previousOmxRoot = process.env.OMX_ROOT;
|
|
1303
|
+
const previousOmxStateRoot = process.env.OMX_STATE_ROOT;
|
|
1304
|
+
const previousTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
1305
|
+
const previousOmxSessionId = process.env.OMX_SESSION_ID;
|
|
1306
|
+
try {
|
|
1307
|
+
await mkdir(cwd, { recursive: true });
|
|
1308
|
+
delete process.env.OMX_ROOT;
|
|
1309
|
+
delete process.env.OMX_STATE_ROOT;
|
|
1310
|
+
process.env.OMX_TEAM_STATE_ROOT = teamStateRoot;
|
|
1311
|
+
process.env.OMX_SESSION_ID = sessionId;
|
|
1312
|
+
|
|
1313
|
+
const result = await dispatchCodexNativeHook(
|
|
1314
|
+
{
|
|
1315
|
+
hook_event_name: "UserPromptSubmit",
|
|
1316
|
+
cwd,
|
|
1317
|
+
session_id: sessionId,
|
|
1318
|
+
thread_id: "thread-team-root",
|
|
1319
|
+
turn_id: "turn-team-root",
|
|
1320
|
+
prompt: "$ralplan implement issue #1307",
|
|
1321
|
+
},
|
|
1322
|
+
{ cwd },
|
|
1323
|
+
);
|
|
1324
|
+
|
|
1325
|
+
assert.equal(result.omxEventName, "keyword-detector");
|
|
1326
|
+
assert.equal(result.skillState?.skill, "ralplan");
|
|
1327
|
+
|
|
1328
|
+
const teamSessionDir = join(teamStateRoot, "sessions", sessionId);
|
|
1329
|
+
assert.equal(existsSync(join(teamSessionDir, "skill-active-state.json")), true);
|
|
1330
|
+
assert.equal(existsSync(join(teamSessionDir, "ralplan-state.json")), true);
|
|
1331
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", sessionId, "skill-active-state.json")), false);
|
|
1332
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", sessionId, "ralplan-state.json")), false);
|
|
1333
|
+
|
|
1334
|
+
const hudState = await readAllState(cwd);
|
|
1335
|
+
assert.equal(hudState.ralplan?.active, true);
|
|
1336
|
+
assert.equal(hudState.ralplan?.current_phase, "planning");
|
|
1337
|
+
} finally {
|
|
1338
|
+
if (typeof previousOmxRoot === "string") process.env.OMX_ROOT = previousOmxRoot;
|
|
1339
|
+
else delete process.env.OMX_ROOT;
|
|
1340
|
+
if (typeof previousOmxStateRoot === "string") process.env.OMX_STATE_ROOT = previousOmxStateRoot;
|
|
1341
|
+
else delete process.env.OMX_STATE_ROOT;
|
|
1342
|
+
if (typeof previousTeamStateRoot === "string") process.env.OMX_TEAM_STATE_ROOT = previousTeamStateRoot;
|
|
1343
|
+
else delete process.env.OMX_TEAM_STATE_ROOT;
|
|
1344
|
+
if (typeof previousOmxSessionId === "string") process.env.OMX_SESSION_ID = previousOmxSessionId;
|
|
1345
|
+
else delete process.env.OMX_SESSION_ID;
|
|
1346
|
+
await rm(root, { recursive: true, force: true });
|
|
1347
|
+
}
|
|
1348
|
+
});
|
|
1349
|
+
|
|
1190
1350
|
it("warns completion-like prompts when active goal workflows need Codex snapshot reconciliation", async () => {
|
|
1191
1351
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-goal-warning-"));
|
|
1192
1352
|
try {
|
|
@@ -1240,6 +1400,100 @@ describe("codex native hook dispatch", () => {
|
|
|
1240
1400
|
}
|
|
1241
1401
|
});
|
|
1242
1402
|
|
|
1403
|
+
it("does not block Stop for non-passing autoresearch-goal professor-critic verdicts", async () => {
|
|
1404
|
+
for (const verdict of ["blocked", "fail", "failed"]) {
|
|
1405
|
+
const cwd = await mkdtemp(join(tmpdir(), `omx-native-hook-autoresearch-${verdict}-stop-`));
|
|
1406
|
+
const slug = `${verdict}-mission`;
|
|
1407
|
+
try {
|
|
1408
|
+
await writeJson(join(cwd, ".omx", "goals", "autoresearch", slug, "mission.json"), {
|
|
1409
|
+
version: 1,
|
|
1410
|
+
workflow: "autoresearch-goal",
|
|
1411
|
+
slug,
|
|
1412
|
+
topic: "Blocked research",
|
|
1413
|
+
status: verdict === "blocked" ? "blocked" : "failed",
|
|
1414
|
+
});
|
|
1415
|
+
await writeJson(join(cwd, ".omx", "goals", "autoresearch", slug, "completion.json"), {
|
|
1416
|
+
verdict,
|
|
1417
|
+
passed: false,
|
|
1418
|
+
});
|
|
1419
|
+
|
|
1420
|
+
const result = await dispatchCodexNativeHook({
|
|
1421
|
+
hook_event_name: "Stop",
|
|
1422
|
+
cwd,
|
|
1423
|
+
session_id: `sess-autoresearch-${verdict}-stop`,
|
|
1424
|
+
thread_id: `thread-autoresearch-${verdict}-stop`,
|
|
1425
|
+
last_assistant_message: "Autoresearch goal complete; next call update_goal({status: \"complete\"}).",
|
|
1426
|
+
}, { cwd });
|
|
1427
|
+
|
|
1428
|
+
assert.notEqual(result.outputJson?.decision, "block");
|
|
1429
|
+
assert.doesNotMatch(JSON.stringify(result.outputJson), new RegExp(`autoresearch-goal complete --slug ${slug}`));
|
|
1430
|
+
assert.doesNotMatch(JSON.stringify(result.outputJson), /get_goal snapshot reconciliation/);
|
|
1431
|
+
} finally {
|
|
1432
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
|
|
1437
|
+
it("blocks Stop for passing autoresearch-goal professor-critic verdicts that need reconciliation", async () => {
|
|
1438
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-autoresearch-pass-stop-"));
|
|
1439
|
+
try {
|
|
1440
|
+
await writeJson(join(cwd, ".omx", "goals", "autoresearch", "passing-mission", "mission.json"), {
|
|
1441
|
+
version: 1,
|
|
1442
|
+
workflow: "autoresearch-goal",
|
|
1443
|
+
slug: "passing-mission",
|
|
1444
|
+
topic: "Passing research",
|
|
1445
|
+
status: "validation_passed",
|
|
1446
|
+
});
|
|
1447
|
+
await writeJson(join(cwd, ".omx", "goals", "autoresearch", "passing-mission", "completion.json"), {
|
|
1448
|
+
verdict: "fail",
|
|
1449
|
+
passed: true,
|
|
1450
|
+
});
|
|
1451
|
+
|
|
1452
|
+
const result = await dispatchCodexNativeHook({
|
|
1453
|
+
hook_event_name: "Stop",
|
|
1454
|
+
cwd,
|
|
1455
|
+
session_id: "sess-autoresearch-pass-stop",
|
|
1456
|
+
thread_id: "thread-autoresearch-pass-stop",
|
|
1457
|
+
last_assistant_message: "Autoresearch goal complete; next call update_goal({status: \"complete\"}).",
|
|
1458
|
+
}, { cwd });
|
|
1459
|
+
|
|
1460
|
+
assert.equal(result.outputJson?.decision, "block");
|
|
1461
|
+
assert.match(JSON.stringify(result.outputJson), /get_goal snapshot reconciliation/);
|
|
1462
|
+
assert.match(JSON.stringify(result.outputJson), /omx autoresearch-goal complete --slug passing-mission/);
|
|
1463
|
+
} finally {
|
|
1464
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
it("blocks Stop for autoresearch-goal verdict=pass even when passed is omitted", async () => {
|
|
1469
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-autoresearch-verdict-pass-stop-"));
|
|
1470
|
+
try {
|
|
1471
|
+
await writeJson(join(cwd, ".omx", "goals", "autoresearch", "verdict-pass-mission", "mission.json"), {
|
|
1472
|
+
version: 1,
|
|
1473
|
+
workflow: "autoresearch-goal",
|
|
1474
|
+
slug: "verdict-pass-mission",
|
|
1475
|
+
topic: "Passing research",
|
|
1476
|
+
status: "validation_passed",
|
|
1477
|
+
});
|
|
1478
|
+
await writeJson(join(cwd, ".omx", "goals", "autoresearch", "verdict-pass-mission", "completion.json"), {
|
|
1479
|
+
verdict: "pass",
|
|
1480
|
+
});
|
|
1481
|
+
|
|
1482
|
+
const result = await dispatchCodexNativeHook({
|
|
1483
|
+
hook_event_name: "Stop",
|
|
1484
|
+
cwd,
|
|
1485
|
+
session_id: "sess-autoresearch-verdict-pass-stop",
|
|
1486
|
+
thread_id: "thread-autoresearch-verdict-pass-stop",
|
|
1487
|
+
last_assistant_message: "Autoresearch goal complete; next call update_goal({status: \"complete\"}).",
|
|
1488
|
+
}, { cwd });
|
|
1489
|
+
|
|
1490
|
+
assert.equal(result.outputJson?.decision, "block");
|
|
1491
|
+
assert.match(JSON.stringify(result.outputJson), /omx autoresearch-goal complete --slug verdict-pass-mission/);
|
|
1492
|
+
} finally {
|
|
1493
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1243
1497
|
it("treats workflow keywords in native subagent prompt text as literal delegation text", async () => {
|
|
1244
1498
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-subagent-keyword-literal-"));
|
|
1245
1499
|
try {
|
|
@@ -1327,7 +1581,7 @@ describe("codex native hook dispatch", () => {
|
|
|
1327
1581
|
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } })?.hookSpecificOutput?.additionalContext || "",
|
|
1328
1582
|
);
|
|
1329
1583
|
assert.match(message, /\$oh-my-codex:ralplan" -> ralplan/);
|
|
1330
|
-
assert.match(message, /
|
|
1584
|
+
assert.match(message, /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
1331
1585
|
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", "sess-plugin-1", "ralplan-state.json")), true);
|
|
1332
1586
|
} finally {
|
|
1333
1587
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -1544,7 +1798,7 @@ describe("codex native hook dispatch", () => {
|
|
|
1544
1798
|
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } })?.hookSpecificOutput?.additionalContext || "",
|
|
1545
1799
|
);
|
|
1546
1800
|
assert.match(message, /\$ralph" -> ralph/);
|
|
1547
|
-
assert.match(message, /
|
|
1801
|
+
assert.match(message, /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
1548
1802
|
assert.match(message, /Prompt-side `\$ralph` activation seeds Ralph workflow state only; it does not invoke `omx ralph`\./);
|
|
1549
1803
|
assert.match(message, /Use `omx ralph --prd \.\.\.` only when you explicitly want the PRD-gated CLI startup path\./);
|
|
1550
1804
|
} finally {
|
|
@@ -1574,7 +1828,7 @@ describe("codex native hook dispatch", () => {
|
|
|
1574
1828
|
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } })?.hookSpecificOutput?.additionalContext || "",
|
|
1575
1829
|
);
|
|
1576
1830
|
assert.match(message, /\$oh-my-codex:ralph" -> ralph/);
|
|
1577
|
-
assert.match(message, /
|
|
1831
|
+
assert.match(message, /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
1578
1832
|
assert.match(message, /Prompt-side `\$ralph` activation seeds Ralph workflow state only; it does not invoke `omx ralph`\./);
|
|
1579
1833
|
} finally {
|
|
1580
1834
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -1656,7 +1910,7 @@ describe("codex native hook dispatch", () => {
|
|
|
1656
1910
|
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } })?.hookSpecificOutput?.additionalContext || "",
|
|
1657
1911
|
);
|
|
1658
1912
|
assert.match(message, /\$deep-interview" -> deep-interview/);
|
|
1659
|
-
assert.match(message, /
|
|
1913
|
+
assert.match(message, /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
1660
1914
|
assert.match(message, /Deep-interview is active, but this session is not attached to tmux/);
|
|
1661
1915
|
assert.match(message, /Do not invoke `omx question`, `omx hud`, or `omx team`/);
|
|
1662
1916
|
assert.match(message, /native structured question tool when available/);
|
|
@@ -2132,8 +2386,11 @@ export async function onHookEvent(event) {
|
|
|
2132
2386
|
|
|
2133
2387
|
assert.match(JSON.stringify(denied.outputJson), /denied workflow keyword/i);
|
|
2134
2388
|
assert.match(JSON.stringify(denied.outputJson), /Unsupported workflow overlap: team \+ autopilot\./);
|
|
2135
|
-
assert.match(JSON.stringify(denied.outputJson),
|
|
2136
|
-
assert.match(JSON.stringify(denied.outputJson),
|
|
2389
|
+
assert.match(JSON.stringify(denied.outputJson), /omx state clear --input/);
|
|
2390
|
+
assert.match(JSON.stringify(denied.outputJson), /mode\\":\\"<mode>/);
|
|
2391
|
+
assert.match(JSON.stringify(denied.outputJson), /--json/);
|
|
2392
|
+
assert.match(JSON.stringify(denied.outputJson), /explicit MCP compatibility is enabled/);
|
|
2393
|
+
assert.match(JSON.stringify(denied.outputJson), /`omx_state\.\*` tools/);
|
|
2137
2394
|
assert.equal(
|
|
2138
2395
|
existsSync(join(cwd, ".omx", "state", "sessions", "sess-deny-1", "autopilot-state.json")),
|
|
2139
2396
|
false,
|
|
@@ -2210,7 +2467,7 @@ export async function onHookEvent(event) {
|
|
|
2210
2467
|
assert.match(message, /\$ralph" -> ralph/);
|
|
2211
2468
|
assert.doesNotMatch(message, /mode transiting:/);
|
|
2212
2469
|
assert.match(message, /planning preserved over simultaneous execution follow-up; deferred skills: team, ralph\./);
|
|
2213
|
-
assert.match(message, /
|
|
2470
|
+
assert.match(message, /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
2214
2471
|
assert.doesNotMatch(message, /Use the durable OMX team runtime via `omx team \.\.\.`/);
|
|
2215
2472
|
} finally {
|
|
2216
2473
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -2242,7 +2499,7 @@ export async function onHookEvent(event) {
|
|
|
2242
2499
|
assert.match(message, /\$oh-my-codex:ralph" -> ralph/);
|
|
2243
2500
|
assert.doesNotMatch(message, /mode transiting:/);
|
|
2244
2501
|
assert.match(message, /planning preserved over simultaneous execution follow-up; deferred skills: team, ralph\./);
|
|
2245
|
-
assert.match(message, /
|
|
2502
|
+
assert.match(message, /use CLI-first state updates via `omx state write\/read\/clear --input '<json>' --json`/);
|
|
2246
2503
|
} finally {
|
|
2247
2504
|
await rm(cwd, { recursive: true, force: true });
|
|
2248
2505
|
}
|
|
@@ -4352,7 +4609,7 @@ exit 0
|
|
|
4352
4609
|
);
|
|
4353
4610
|
assert.match(
|
|
4354
4611
|
additionalContext,
|
|
4355
|
-
/omx state
|
|
4612
|
+
/omx state write --input/,
|
|
4356
4613
|
);
|
|
4357
4614
|
assert.match(
|
|
4358
4615
|
additionalContext,
|
|
@@ -4600,7 +4857,7 @@ exit 0
|
|
|
4600
4857
|
assert.equal(hookSpecificOutput?.hookEventName, "PostToolUse");
|
|
4601
4858
|
assert.match(
|
|
4602
4859
|
String(hookSpecificOutput?.additionalContext || ""),
|
|
4603
|
-
/Retry via CLI parity with `omx state
|
|
4860
|
+
/Retry via CLI parity with `omx state write --input '\{\}' --json`\./,
|
|
4604
4861
|
);
|
|
4605
4862
|
assert.match(
|
|
4606
4863
|
String(hookSpecificOutput?.additionalContext || ""),
|
|
@@ -4686,7 +4943,7 @@ exit 0
|
|
|
4686
4943
|
hookSpecificOutput: {
|
|
4687
4944
|
hookEventName: "PostToolUse",
|
|
4688
4945
|
additionalContext:
|
|
4689
|
-
"Clear MCP transport-death signal detected. Preserve current team/runtime state. Retry via CLI parity with `omx state
|
|
4946
|
+
"Clear MCP transport-death signal detected. Preserve current team/runtime state. Retry via CLI parity with `omx state write --input '{\"mode\":\"team\",\"active\":true}' --json`. OMX MCP servers are plain Node stdio processes, so they still shut down when stdin/transport closes. If this happened during team runtime, inspect first with `omx team status <team>` or `omx team api read-stall-state --input '{\"team_name\":\"<team>\"}' --json`, and only force cleanup after capturing needed state. For root-cause debugging, rerun with `OMX_MCP_TRANSPORT_DEBUG=1` to log why the stdio transport closed.",
|
|
4690
4947
|
},
|
|
4691
4948
|
});
|
|
4692
4949
|
|
|
@@ -6106,6 +6363,41 @@ exit 0
|
|
|
6106
6363
|
}
|
|
6107
6364
|
});
|
|
6108
6365
|
|
|
6366
|
+
it("ignores stale source-root team Stop fallback when OMX_TEAM_STATE_ROOT is authoritative", async () => {
|
|
6367
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-stale-source-root-"));
|
|
6368
|
+
const teamStateRoot = join(cwd, "shared-team-state");
|
|
6369
|
+
const priorTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
6370
|
+
try {
|
|
6371
|
+
process.env.OMX_TEAM_STATE_ROOT = teamStateRoot;
|
|
6372
|
+
await mkdir(join(cwd, ".omx", "state"), { recursive: true });
|
|
6373
|
+
await mkdir(join(teamStateRoot, "team", "stale-source-team"), { recursive: true });
|
|
6374
|
+
await writeJson(join(cwd, ".omx", "state", "team-state.json"), {
|
|
6375
|
+
active: true,
|
|
6376
|
+
team_name: "stale-source-team",
|
|
6377
|
+
current_phase: "team-exec",
|
|
6378
|
+
});
|
|
6379
|
+
await writeJson(join(teamStateRoot, "team", "stale-source-team", "phase.json"), {
|
|
6380
|
+
current_phase: "team-exec",
|
|
6381
|
+
});
|
|
6382
|
+
|
|
6383
|
+
const result = await dispatchCodexNativeHook(
|
|
6384
|
+
{
|
|
6385
|
+
hook_event_name: "Stop",
|
|
6386
|
+
cwd,
|
|
6387
|
+
session_id: "sess-stale-source-team",
|
|
6388
|
+
},
|
|
6389
|
+
{ cwd },
|
|
6390
|
+
);
|
|
6391
|
+
|
|
6392
|
+
assert.equal(result.omxEventName, "stop");
|
|
6393
|
+
assert.equal(result.outputJson, null);
|
|
6394
|
+
} finally {
|
|
6395
|
+
if (typeof priorTeamStateRoot === "string") process.env.OMX_TEAM_STATE_ROOT = priorTeamStateRoot;
|
|
6396
|
+
else delete process.env.OMX_TEAM_STATE_ROOT;
|
|
6397
|
+
await rm(cwd, { recursive: true, force: true });
|
|
6398
|
+
}
|
|
6399
|
+
});
|
|
6400
|
+
|
|
6109
6401
|
it("returns Stop continuation output from canonical team state rooted via OMX_TEAM_STATE_ROOT", async () => {
|
|
6110
6402
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-env-root-"));
|
|
6111
6403
|
const previousTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
@@ -7141,6 +7433,79 @@ exit 0
|
|
|
7141
7433
|
}
|
|
7142
7434
|
});
|
|
7143
7435
|
|
|
7436
|
+
it("blocks Codex App Stop when Ralph is marked complete without completion-audit evidence", async () => {
|
|
7437
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-ralph-complete-audit-missing-"));
|
|
7438
|
+
try {
|
|
7439
|
+
const sessionId = "sess-ralph-complete-missing";
|
|
7440
|
+
const statePath = join(cwd, ".omx", "state", "sessions", sessionId, "ralph-state.json");
|
|
7441
|
+
await writeJson(join(cwd, ".omx", "state", "session.json"), { session_id: sessionId, native_session_id: sessionId, cwd });
|
|
7442
|
+
await writeJson(statePath, {
|
|
7443
|
+
active: false,
|
|
7444
|
+
mode: "ralph",
|
|
7445
|
+
current_phase: "complete",
|
|
7446
|
+
session_id: sessionId,
|
|
7447
|
+
completed_at: "2026-05-10T12:00:00.000Z",
|
|
7448
|
+
});
|
|
7449
|
+
|
|
7450
|
+
const result = await dispatchCodexNativeHook(
|
|
7451
|
+
{
|
|
7452
|
+
hook_event_name: "Stop",
|
|
7453
|
+
cwd,
|
|
7454
|
+
session_id: sessionId,
|
|
7455
|
+
last_assistant_message: "Done. Ralph complete.",
|
|
7456
|
+
},
|
|
7457
|
+
{ cwd },
|
|
7458
|
+
);
|
|
7459
|
+
|
|
7460
|
+
assert.equal(result.omxEventName, "stop");
|
|
7461
|
+
assert.match(String(result.outputJson?.reason), /Ralph completion audit is missing required evidence/);
|
|
7462
|
+
assert.equal(result.outputJson?.stopReason, "ralph_completion_audit_missing_completion_audit");
|
|
7463
|
+
const reopened = JSON.parse(await readFile(statePath, "utf-8")) as Record<string, unknown>;
|
|
7464
|
+
assert.equal(reopened.active, true);
|
|
7465
|
+
assert.equal(reopened.current_phase, "verifying");
|
|
7466
|
+
assert.equal(reopened.completion_audit_gate, "blocked");
|
|
7467
|
+
assert.equal(reopened.completion_audit_missing_reason, "missing_completion_audit");
|
|
7468
|
+
assert.equal(typeof reopened.completed_at, "undefined");
|
|
7469
|
+
} finally {
|
|
7470
|
+
await rm(cwd, { recursive: true, force: true });
|
|
7471
|
+
}
|
|
7472
|
+
});
|
|
7473
|
+
|
|
7474
|
+
it("allows Codex App Stop when complete Ralph state carries checklist and verification evidence", async () => {
|
|
7475
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-ralph-complete-audit-present-"));
|
|
7476
|
+
try {
|
|
7477
|
+
const sessionId = "sess-ralph-complete-present";
|
|
7478
|
+
await writeJson(join(cwd, ".omx", "state", "session.json"), { session_id: sessionId, native_session_id: sessionId, cwd });
|
|
7479
|
+
await writeJson(join(cwd, ".omx", "state", "sessions", sessionId, "ralph-state.json"), {
|
|
7480
|
+
active: false,
|
|
7481
|
+
mode: "ralph",
|
|
7482
|
+
current_phase: "complete",
|
|
7483
|
+
session_id: sessionId,
|
|
7484
|
+
completed_at: "2026-05-10T12:00:00.000Z",
|
|
7485
|
+
completion_audit: {
|
|
7486
|
+
passed: true,
|
|
7487
|
+
prompt_to_artifact_checklist: ["issue #2260 fixed", "tests added"],
|
|
7488
|
+
verification_evidence: ["node --test dist/scripts/__tests__/codex-native-hook.test.js"],
|
|
7489
|
+
},
|
|
7490
|
+
});
|
|
7491
|
+
|
|
7492
|
+
const result = await dispatchCodexNativeHook(
|
|
7493
|
+
{
|
|
7494
|
+
hook_event_name: "Stop",
|
|
7495
|
+
cwd,
|
|
7496
|
+
session_id: sessionId,
|
|
7497
|
+
last_assistant_message: "Done with completion audit evidence recorded.",
|
|
7498
|
+
},
|
|
7499
|
+
{ cwd },
|
|
7500
|
+
);
|
|
7501
|
+
|
|
7502
|
+
assert.equal(result.omxEventName, "stop");
|
|
7503
|
+
assert.equal(result.outputJson, null);
|
|
7504
|
+
} finally {
|
|
7505
|
+
await rm(cwd, { recursive: true, force: true });
|
|
7506
|
+
}
|
|
7507
|
+
});
|
|
7508
|
+
|
|
7144
7509
|
it("returns Stop continuation output while Ralph is active without an explicit session pin", async () => {
|
|
7145
7510
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-"));
|
|
7146
7511
|
try {
|