oh-my-codex 0.13.1 → 0.13.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 +5 -5
- package/Cargo.toml +1 -1
- package/README.md +2 -0
- package/crates/omx-explore/src/main.rs +221 -10
- package/dist/catalog/__tests__/generator.test.js +2 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +95 -1
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +41 -3
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +25 -1
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +70 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +15 -0
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/update.js +1 -1
- package/dist/cli/update.js.map +1 -1
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.js +36 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.js +48 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/keyword-detector.test.js +32 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +185 -8
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +26 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +44 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +126 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +8 -1
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +55 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +23 -4
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +38 -0
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +11 -3
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/notifications/__tests__/reply-listener.test.js +34 -1
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts +1 -0
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +14 -2
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +178 -15
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/generate-release-body.test.d.ts +2 -0
- package/dist/scripts/__tests__/generate-release-body.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/generate-release-body.test.js +144 -0
- package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +23 -44
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/generate-release-body.d.ts +34 -0
- package/dist/scripts/generate-release-body.d.ts.map +1 -0
- package/dist/scripts/generate-release-body.js +249 -0
- package/dist/scripts/generate-release-body.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +43 -20
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/active-team.d.ts.map +1 -1
- package/dist/scripts/notify-hook/active-team.js +2 -1
- package/dist/scripts/notify-hook/active-team.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +17 -2
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +16 -0
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +26 -5
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook.js +1 -7
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +6 -0
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +1 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts +2 -0
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/worker-runtime-identity.test.js +250 -0
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -0
- package/dist/team/leader-activity.d.ts.map +1 -1
- package/dist/team/leader-activity.js +26 -15
- package/dist/team/leader-activity.js.map +1 -1
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +9 -8
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +10 -9
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +3 -2
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js +3 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
- package/dist/wiki/__tests__/slug-nonascii.test.js +11 -5
- package/dist/wiki/__tests__/slug-nonascii.test.js.map +1 -1
- package/dist/wiki/storage.d.ts.map +1 -1
- package/dist/wiki/storage.js +2 -1
- package/dist/wiki/storage.js.map +1 -1
- package/package.json +3 -1
- package/skills/analyze/SKILL.md +101 -134
- package/src/scripts/__tests__/codex-native-hook.test.ts +214 -17
- package/src/scripts/__tests__/generate-release-body.test.ts +166 -0
- package/src/scripts/codex-native-hook.ts +81 -61
- package/src/scripts/generate-release-body.ts +295 -0
- package/src/scripts/notify-fallback-watcher.ts +44 -21
- package/src/scripts/notify-hook/active-team.ts +2 -1
- package/src/scripts/notify-hook/ralph-session-resume.ts +17 -2
- package/src/scripts/notify-hook/state-io.ts +16 -0
- package/src/scripts/notify-hook/team-leader-nudge.ts +24 -4
- package/src/scripts/notify-hook.ts +1 -6
- package/templates/AGENTS.md +1 -1
- package/templates/catalog-manifest.json +2 -4
|
@@ -338,6 +338,29 @@ describe("codex native hook dispatch", () => {
|
|
|
338
338
|
await rm(cwd, { recursive: true, force: true });
|
|
339
339
|
}
|
|
340
340
|
});
|
|
341
|
+
it("does not activate Ralph workflow state from a plain conversational mention", async () => {
|
|
342
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-ralph-plain-text-"));
|
|
343
|
+
try {
|
|
344
|
+
await mkdir(join(cwd, ".omx", "state"), { recursive: true });
|
|
345
|
+
const result = await dispatchCodexNativeHook({
|
|
346
|
+
hook_event_name: "UserPromptSubmit",
|
|
347
|
+
cwd,
|
|
348
|
+
session_id: "sess-ralph-plain-text",
|
|
349
|
+
thread_id: "thread-ralph-plain-text",
|
|
350
|
+
turn_id: "turn-ralph-plain-text",
|
|
351
|
+
prompt: "why does ralph keep blocking stop?",
|
|
352
|
+
}, { cwd });
|
|
353
|
+
assert.equal(result.omxEventName, "keyword-detector");
|
|
354
|
+
assert.equal(result.skillState, null);
|
|
355
|
+
assert.equal(result.outputJson, null);
|
|
356
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "skill-active-state.json")), false);
|
|
357
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", "sess-ralph-plain-text", "skill-active-state.json")), false);
|
|
358
|
+
assert.equal(existsSync(join(cwd, ".omx", "state", "sessions", "sess-ralph-plain-text", "ralph-state.json")), false);
|
|
359
|
+
}
|
|
360
|
+
finally {
|
|
361
|
+
await rm(cwd, { recursive: true, force: true });
|
|
362
|
+
}
|
|
363
|
+
});
|
|
341
364
|
it("clarifies that prompt-side $ralph activation does not invoke the PRD-gated CLI path", async () => {
|
|
342
365
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-ralph-routing-"));
|
|
343
366
|
try {
|
|
@@ -1649,7 +1672,12 @@ esac
|
|
|
1649
1672
|
cwd,
|
|
1650
1673
|
session_id: "sess-stop-team-worker-terminal",
|
|
1651
1674
|
}, { cwd });
|
|
1652
|
-
assert.
|
|
1675
|
+
assert.deepEqual(result.outputJson, {
|
|
1676
|
+
decision: "block",
|
|
1677
|
+
reason: `OMX team pipeline is still active (worker-stop-team-terminal) at phase team-exec; continue coordinating until the team reaches a terminal phase.${TEAM_STOP_COMMIT_GUIDANCE}`,
|
|
1678
|
+
stopReason: "team_team-exec",
|
|
1679
|
+
systemMessage: "OMX team pipeline is still active at phase team-exec.",
|
|
1680
|
+
});
|
|
1653
1681
|
}
|
|
1654
1682
|
finally {
|
|
1655
1683
|
if (typeof prevTeamWorker === "string")
|
|
@@ -2278,8 +2306,9 @@ esac
|
|
|
2278
2306
|
await rm(cwd, { recursive: true, force: true });
|
|
2279
2307
|
}
|
|
2280
2308
|
});
|
|
2281
|
-
it("
|
|
2282
|
-
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-ralph-
|
|
2309
|
+
it("keeps blocking Ralph Stop replays until the active task advances", async () => {
|
|
2310
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-ralph-replay-"));
|
|
2311
|
+
const previousOmxSessionId = process.env.OMX_SESSION_ID;
|
|
2283
2312
|
try {
|
|
2284
2313
|
const stateDir = join(cwd, ".omx", "state");
|
|
2285
2314
|
await mkdir(stateDir, { recursive: true });
|
|
@@ -2287,16 +2316,33 @@ esac
|
|
|
2287
2316
|
active: true,
|
|
2288
2317
|
current_phase: "executing",
|
|
2289
2318
|
}));
|
|
2290
|
-
|
|
2319
|
+
process.env.OMX_SESSION_ID = "sess-stop-ralph-replay";
|
|
2320
|
+
const payload = {
|
|
2291
2321
|
hook_event_name: "Stop",
|
|
2292
2322
|
cwd,
|
|
2293
|
-
|
|
2323
|
+
last_assistant_message: "Next active targets:\n\n1. scheduler integration\n\nI am continuing.",
|
|
2324
|
+
};
|
|
2325
|
+
const expected = {
|
|
2326
|
+
decision: "block",
|
|
2327
|
+
reason: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
2328
|
+
stopReason: "ralph_executing",
|
|
2329
|
+
systemMessage: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
2330
|
+
};
|
|
2331
|
+
const first = await dispatchCodexNativeHook(payload, { cwd });
|
|
2332
|
+
const replay = await dispatchCodexNativeHook({
|
|
2333
|
+
...payload,
|
|
2294
2334
|
stop_hook_active: true,
|
|
2295
2335
|
}, { cwd });
|
|
2296
|
-
assert.equal(
|
|
2297
|
-
assert.
|
|
2336
|
+
assert.equal(first.omxEventName, "stop");
|
|
2337
|
+
assert.deepEqual(first.outputJson, expected);
|
|
2338
|
+
assert.equal(replay.omxEventName, "stop");
|
|
2339
|
+
assert.deepEqual(replay.outputJson, expected);
|
|
2298
2340
|
}
|
|
2299
2341
|
finally {
|
|
2342
|
+
if (typeof previousOmxSessionId === "string")
|
|
2343
|
+
process.env.OMX_SESSION_ID = previousOmxSessionId;
|
|
2344
|
+
else
|
|
2345
|
+
delete process.env.OMX_SESSION_ID;
|
|
2300
2346
|
await rm(cwd, { recursive: true, force: true });
|
|
2301
2347
|
}
|
|
2302
2348
|
});
|
|
@@ -2324,7 +2370,7 @@ esac
|
|
|
2324
2370
|
await rm(cwd, { recursive: true, force: true });
|
|
2325
2371
|
}
|
|
2326
2372
|
});
|
|
2327
|
-
it("
|
|
2373
|
+
it("re-blocks duplicate native auto-nudge replays for the same Stop reply", async () => {
|
|
2328
2374
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-auto-nudge-once-"));
|
|
2329
2375
|
try {
|
|
2330
2376
|
const stateDir = join(cwd, ".omx", "state");
|
|
@@ -2348,13 +2394,18 @@ esac
|
|
|
2348
2394
|
last_assistant_message: "Keep going and finish the cleanup.",
|
|
2349
2395
|
}, { cwd });
|
|
2350
2396
|
assert.equal(result.omxEventName, "stop");
|
|
2351
|
-
assert.
|
|
2397
|
+
assert.deepEqual(result.outputJson, {
|
|
2398
|
+
decision: "block",
|
|
2399
|
+
reason: DEFAULT_AUTO_NUDGE_RESPONSE,
|
|
2400
|
+
stopReason: "auto_nudge",
|
|
2401
|
+
systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
|
|
2402
|
+
});
|
|
2352
2403
|
}
|
|
2353
2404
|
finally {
|
|
2354
2405
|
await rm(cwd, { recursive: true, force: true });
|
|
2355
2406
|
}
|
|
2356
2407
|
});
|
|
2357
|
-
it("
|
|
2408
|
+
it("re-blocks duplicate native auto-nudge replays across native/canonical session-id drift", async () => {
|
|
2358
2409
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-auto-nudge-session-drift-"));
|
|
2359
2410
|
try {
|
|
2360
2411
|
const stateDir = join(cwd, ".omx", "state");
|
|
@@ -2382,7 +2433,12 @@ esac
|
|
|
2382
2433
|
last_assistant_message: "Keep going and finish the cleanup.",
|
|
2383
2434
|
}, { cwd });
|
|
2384
2435
|
assert.equal(result.omxEventName, "stop");
|
|
2385
|
-
assert.
|
|
2436
|
+
assert.deepEqual(result.outputJson, {
|
|
2437
|
+
decision: "block",
|
|
2438
|
+
reason: DEFAULT_AUTO_NUDGE_RESPONSE,
|
|
2439
|
+
stopReason: "auto_nudge",
|
|
2440
|
+
systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
|
|
2441
|
+
});
|
|
2386
2442
|
const persisted = JSON.parse(await readFile(join(stateDir, "native-stop-state.json"), "utf-8"));
|
|
2387
2443
|
assert.deepEqual(Object.keys(persisted.sessions ?? {}), ["omx-canonical"]);
|
|
2388
2444
|
}
|
|
@@ -2705,7 +2761,7 @@ esac
|
|
|
2705
2761
|
await rm(cwd, { recursive: true, force: true });
|
|
2706
2762
|
}
|
|
2707
2763
|
});
|
|
2708
|
-
it("
|
|
2764
|
+
it("auto-continues native Stop for permission-seeking prompts even outside OMX runtime", async () => {
|
|
2709
2765
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-auto-nudge-plain-session-"));
|
|
2710
2766
|
try {
|
|
2711
2767
|
await dispatchCodexNativeHook({
|
|
@@ -2722,10 +2778,15 @@ esac
|
|
|
2722
2778
|
session_id: "plain-stop-session",
|
|
2723
2779
|
thread_id: "plain-thread",
|
|
2724
2780
|
turn_id: "plain-turn-1",
|
|
2725
|
-
last_assistant_message: "
|
|
2781
|
+
last_assistant_message: "If you want, I can continue with the cleanup from here.",
|
|
2726
2782
|
}, { cwd });
|
|
2727
2783
|
assert.equal(result.omxEventName, "stop");
|
|
2728
|
-
assert.
|
|
2784
|
+
assert.deepEqual(result.outputJson, {
|
|
2785
|
+
decision: "block",
|
|
2786
|
+
reason: DEFAULT_AUTO_NUDGE_RESPONSE,
|
|
2787
|
+
stopReason: "auto_nudge",
|
|
2788
|
+
systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
|
|
2789
|
+
});
|
|
2729
2790
|
}
|
|
2730
2791
|
finally {
|
|
2731
2792
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -2814,7 +2875,12 @@ esac
|
|
|
2814
2875
|
stop_hook_active: true,
|
|
2815
2876
|
}, { cwd });
|
|
2816
2877
|
assert.equal(duplicate.omxEventName, "stop");
|
|
2817
|
-
assert.
|
|
2878
|
+
assert.deepEqual(duplicate.outputJson, {
|
|
2879
|
+
decision: "block",
|
|
2880
|
+
reason: `OMX team pipeline is still active (current-team) at phase team-verify; continue coordinating until the team reaches a terminal phase.${TEAM_STOP_COMMIT_GUIDANCE}`,
|
|
2881
|
+
stopReason: "team_team-verify",
|
|
2882
|
+
systemMessage: "OMX team pipeline is still active at phase team-verify.",
|
|
2883
|
+
});
|
|
2818
2884
|
const fresh = await dispatchCodexNativeHook({
|
|
2819
2885
|
hook_event_name: "Stop",
|
|
2820
2886
|
cwd,
|
|
@@ -2837,6 +2903,103 @@ esac
|
|
|
2837
2903
|
await rm(cwd, { recursive: true, force: true });
|
|
2838
2904
|
}
|
|
2839
2905
|
});
|
|
2906
|
+
it("re-blocks active execution modes on repeated Stop hooks", async () => {
|
|
2907
|
+
const cases = [
|
|
2908
|
+
{
|
|
2909
|
+
mode: "autopilot",
|
|
2910
|
+
phase: "execution",
|
|
2911
|
+
reason: "OMX autopilot is still active (phase: execution); continue the task and gather fresh verification evidence before stopping.",
|
|
2912
|
+
},
|
|
2913
|
+
{
|
|
2914
|
+
mode: "ultrawork",
|
|
2915
|
+
phase: "executing",
|
|
2916
|
+
reason: "OMX ultrawork is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
|
|
2917
|
+
},
|
|
2918
|
+
{
|
|
2919
|
+
mode: "ultraqa",
|
|
2920
|
+
phase: "diagnose",
|
|
2921
|
+
reason: "OMX ultraqa is still active (phase: diagnose); continue the task and gather fresh verification evidence before stopping.",
|
|
2922
|
+
},
|
|
2923
|
+
];
|
|
2924
|
+
for (const testCase of cases) {
|
|
2925
|
+
const cwd = await mkdtemp(join(tmpdir(), `omx-native-hook-stop-${testCase.mode}-repeat-`));
|
|
2926
|
+
try {
|
|
2927
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
2928
|
+
await mkdir(stateDir, { recursive: true });
|
|
2929
|
+
await writeJson(join(stateDir, `${testCase.mode}-state.json`), {
|
|
2930
|
+
active: true,
|
|
2931
|
+
current_phase: testCase.phase,
|
|
2932
|
+
});
|
|
2933
|
+
await dispatchCodexNativeHook({
|
|
2934
|
+
hook_event_name: "Stop",
|
|
2935
|
+
cwd,
|
|
2936
|
+
session_id: `sess-stop-${testCase.mode}-repeat`,
|
|
2937
|
+
thread_id: `thread-stop-${testCase.mode}-repeat`,
|
|
2938
|
+
turn_id: `turn-stop-${testCase.mode}-repeat-1`,
|
|
2939
|
+
}, { cwd });
|
|
2940
|
+
const repeated = await dispatchCodexNativeHook({
|
|
2941
|
+
hook_event_name: "Stop",
|
|
2942
|
+
cwd,
|
|
2943
|
+
session_id: `sess-stop-${testCase.mode}-repeat`,
|
|
2944
|
+
thread_id: `thread-stop-${testCase.mode}-repeat`,
|
|
2945
|
+
turn_id: `turn-stop-${testCase.mode}-repeat-1`,
|
|
2946
|
+
stop_hook_active: true,
|
|
2947
|
+
}, { cwd });
|
|
2948
|
+
assert.equal(repeated.omxEventName, "stop");
|
|
2949
|
+
assert.deepEqual(repeated.outputJson, {
|
|
2950
|
+
decision: "block",
|
|
2951
|
+
reason: testCase.reason,
|
|
2952
|
+
stopReason: `${testCase.mode}_${testCase.phase}`,
|
|
2953
|
+
systemMessage: `OMX ${testCase.mode} is still active (phase: ${testCase.phase}).`,
|
|
2954
|
+
});
|
|
2955
|
+
}
|
|
2956
|
+
finally {
|
|
2957
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
it("re-blocks active ralplan skill state on repeated Stop hooks", async () => {
|
|
2962
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-skill-repeat-"));
|
|
2963
|
+
try {
|
|
2964
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
2965
|
+
await mkdir(join(stateDir, "sessions", "sess-stop-skill-repeat"), { recursive: true });
|
|
2966
|
+
await writeJson(join(stateDir, "session.json"), { session_id: "sess-stop-skill-repeat" });
|
|
2967
|
+
await writeJson(join(stateDir, "sessions", "sess-stop-skill-repeat", "skill-active-state.json"), {
|
|
2968
|
+
active: true,
|
|
2969
|
+
skill: "ralplan",
|
|
2970
|
+
phase: "planning",
|
|
2971
|
+
});
|
|
2972
|
+
await writeJson(join(stateDir, "sessions", "sess-stop-skill-repeat", "ralplan-state.json"), {
|
|
2973
|
+
active: true,
|
|
2974
|
+
current_phase: "planning",
|
|
2975
|
+
});
|
|
2976
|
+
await dispatchCodexNativeHook({
|
|
2977
|
+
hook_event_name: "Stop",
|
|
2978
|
+
cwd,
|
|
2979
|
+
session_id: "sess-stop-skill-repeat",
|
|
2980
|
+
thread_id: "thread-stop-skill-repeat",
|
|
2981
|
+
turn_id: "turn-stop-skill-repeat-1",
|
|
2982
|
+
}, { cwd });
|
|
2983
|
+
const repeated = await dispatchCodexNativeHook({
|
|
2984
|
+
hook_event_name: "Stop",
|
|
2985
|
+
cwd,
|
|
2986
|
+
session_id: "sess-stop-skill-repeat",
|
|
2987
|
+
thread_id: "thread-stop-skill-repeat",
|
|
2988
|
+
turn_id: "turn-stop-skill-repeat-1",
|
|
2989
|
+
stop_hook_active: true,
|
|
2990
|
+
}, { cwd });
|
|
2991
|
+
assert.equal(repeated.omxEventName, "stop");
|
|
2992
|
+
assert.deepEqual(repeated.outputJson, {
|
|
2993
|
+
decision: "block",
|
|
2994
|
+
reason: "OMX skill ralplan is still active (phase: planning); continue until the current ralplan workflow reaches a terminal state.",
|
|
2995
|
+
stopReason: "skill_ralplan_planning",
|
|
2996
|
+
systemMessage: "OMX skill ralplan is still active (phase: planning).",
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
finally {
|
|
3000
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3001
|
+
}
|
|
3002
|
+
});
|
|
2840
3003
|
it("does not block Stop from another session's stale root team state when no scoped team state exists", async () => {
|
|
2841
3004
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-stale-root-team-"));
|
|
2842
3005
|
try {
|