oh-my-codex 0.21.13 → 0.21.15

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.
Files changed (141) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +17 -0
  4. package/dist/adapt/herdr/__tests__/wiring.test.js +21 -0
  5. package/dist/adapt/herdr/__tests__/wiring.test.js.map +1 -1
  6. package/dist/adapt/herdr/wiring.d.ts.map +1 -1
  7. package/dist/adapt/herdr/wiring.js +5 -0
  8. package/dist/adapt/herdr/wiring.js.map +1 -1
  9. package/dist/auth/__tests__/hotswap.test.js +28 -0
  10. package/dist/auth/__tests__/hotswap.test.js.map +1 -1
  11. package/dist/auth/hotswap.d.ts +1 -0
  12. package/dist/auth/hotswap.d.ts.map +1 -1
  13. package/dist/auth/hotswap.js +4 -1
  14. package/dist/auth/hotswap.js.map +1 -1
  15. package/dist/cli/__tests__/codex-plugin-layout.test.js +196 -0
  16. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  17. package/dist/cli/__tests__/doctor-warning-copy.test.js +2 -1
  18. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  19. package/dist/cli/__tests__/index.test.js +14 -1
  20. package/dist/cli/__tests__/index.test.js.map +1 -1
  21. package/dist/cli/__tests__/session-timeline.test.d.ts +2 -0
  22. package/dist/cli/__tests__/session-timeline.test.d.ts.map +1 -0
  23. package/dist/cli/__tests__/session-timeline.test.js +155 -0
  24. package/dist/cli/__tests__/session-timeline.test.js.map +1 -0
  25. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +1 -0
  26. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  27. package/dist/cli/doctor.d.ts.map +1 -1
  28. package/dist/cli/doctor.js +1 -0
  29. package/dist/cli/doctor.js.map +1 -1
  30. package/dist/cli/index.d.ts +1 -0
  31. package/dist/cli/index.d.ts.map +1 -1
  32. package/dist/cli/index.js +11 -0
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/session-search.d.ts.map +1 -1
  35. package/dist/cli/session-search.js +7 -0
  36. package/dist/cli/session-search.js.map +1 -1
  37. package/dist/cli/session-timeline.d.ts +9 -0
  38. package/dist/cli/session-timeline.d.ts.map +1 -0
  39. package/dist/cli/session-timeline.js +174 -0
  40. package/dist/cli/session-timeline.js.map +1 -0
  41. package/dist/config/__tests__/codex-hooks.test.js +3 -1
  42. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  43. package/dist/config/__tests__/generator-idempotent.test.js +1 -0
  44. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  45. package/dist/config/codex-hooks.d.ts +1 -1
  46. package/dist/config/codex-hooks.d.ts.map +1 -1
  47. package/dist/config/codex-hooks.js +5 -0
  48. package/dist/config/codex-hooks.js.map +1 -1
  49. package/dist/evals/astra-defaults/__tests__/collector.test.js +51 -23
  50. package/dist/evals/astra-defaults/__tests__/collector.test.js.map +1 -1
  51. package/dist/evals/astra-defaults/collector.d.ts +2 -0
  52. package/dist/evals/astra-defaults/collector.d.ts.map +1 -1
  53. package/dist/evals/astra-defaults/collector.js +19 -8
  54. package/dist/evals/astra-defaults/collector.js.map +1 -1
  55. package/dist/hooks/extensibility/__tests__/dispatcher.test.js +143 -0
  56. package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
  57. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
  58. package/dist/hooks/extensibility/dispatcher.js +120 -28
  59. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  60. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  61. package/dist/hooks/extensibility/runtime.js +1 -0
  62. package/dist/hooks/extensibility/runtime.js.map +1 -1
  63. package/dist/hooks/extensibility/types.d.ts +2 -0
  64. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  65. package/dist/hooks/native/types.d.ts +1 -1
  66. package/dist/hooks/native/types.d.ts.map +1 -1
  67. package/dist/hooks/native/types.js.map +1 -1
  68. package/dist/notifications/__tests__/lifecycle-dedupe.test.js +200 -2
  69. package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -1
  70. package/dist/notifications/lifecycle-dedupe.d.ts +10 -0
  71. package/dist/notifications/lifecycle-dedupe.d.ts.map +1 -1
  72. package/dist/notifications/lifecycle-dedupe.js +175 -19
  73. package/dist/notifications/lifecycle-dedupe.js.map +1 -1
  74. package/dist/scripts/__tests__/codex-native-hook.test.js +278 -6
  75. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  76. package/dist/scripts/__tests__/native-hook-protocol.test.d.ts +2 -0
  77. package/dist/scripts/__tests__/native-hook-protocol.test.d.ts.map +1 -0
  78. package/dist/scripts/__tests__/native-hook-protocol.test.js +329 -0
  79. package/dist/scripts/__tests__/native-hook-protocol.test.js.map +1 -0
  80. package/dist/scripts/__tests__/smoke-packed-install.test.js +7 -6
  81. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  82. package/dist/scripts/codex-execution-surface.d.ts +1 -1
  83. package/dist/scripts/codex-execution-surface.d.ts.map +1 -1
  84. package/dist/scripts/codex-execution-surface.js.map +1 -1
  85. package/dist/scripts/codex-native-hook.d.ts +1 -1
  86. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  87. package/dist/scripts/codex-native-hook.js +124 -13
  88. package/dist/scripts/codex-native-hook.js.map +1 -1
  89. package/dist/scripts/hook-payload-guard.d.ts +1 -1
  90. package/dist/scripts/hook-payload-guard.d.ts.map +1 -1
  91. package/dist/scripts/hook-payload-guard.js +1 -0
  92. package/dist/scripts/hook-payload-guard.js.map +1 -1
  93. package/dist/scripts/smoke-packed-install.d.ts +2 -2
  94. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  95. package/dist/scripts/smoke-packed-install.js +12 -1
  96. package/dist/scripts/smoke-packed-install.js.map +1 -1
  97. package/dist/session-history/__tests__/timeline.test.d.ts +2 -0
  98. package/dist/session-history/__tests__/timeline.test.d.ts.map +1 -0
  99. package/dist/session-history/__tests__/timeline.test.js +459 -0
  100. package/dist/session-history/__tests__/timeline.test.js.map +1 -0
  101. package/dist/session-history/export.d.ts +2 -3
  102. package/dist/session-history/export.d.ts.map +1 -1
  103. package/dist/session-history/export.js +5 -66
  104. package/dist/session-history/export.js.map +1 -1
  105. package/dist/session-history/timeline.d.ts +97 -0
  106. package/dist/session-history/timeline.d.ts.map +1 -0
  107. package/dist/session-history/timeline.js +325 -0
  108. package/dist/session-history/timeline.js.map +1 -0
  109. package/dist/session-history/transcript.d.ts +16 -0
  110. package/dist/session-history/transcript.d.ts.map +1 -0
  111. package/dist/session-history/transcript.js +111 -0
  112. package/dist/session-history/transcript.js.map +1 -0
  113. package/dist/subagents/tracker.d.ts +6 -0
  114. package/dist/subagents/tracker.d.ts.map +1 -1
  115. package/dist/subagents/tracker.js +32 -0
  116. package/dist/subagents/tracker.js.map +1 -1
  117. package/dist/team/__tests__/runtime.test.js +12 -3
  118. package/dist/team/__tests__/runtime.test.js.map +1 -1
  119. package/dist/team/__tests__/scaling.test.js +25 -0
  120. package/dist/team/__tests__/scaling.test.js.map +1 -1
  121. package/dist/team/__tests__/tmux-session.test.js +30 -0
  122. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  123. package/dist/team/tmux-session.d.ts.map +1 -1
  124. package/dist/team/tmux-session.js +9 -1
  125. package/dist/team/tmux-session.js.map +1 -1
  126. package/dist/wiki/__tests__/session-hooks.test.js +26 -0
  127. package/dist/wiki/__tests__/session-hooks.test.js.map +1 -1
  128. package/dist/wiki/lifecycle.d.ts.map +1 -1
  129. package/dist/wiki/lifecycle.js +6 -1
  130. package/dist/wiki/lifecycle.js.map +1 -1
  131. package/package.json +1 -1
  132. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  133. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +85 -18
  134. package/plugins/oh-my-codex/hooks/hooks.json +10 -0
  135. package/src/scripts/__tests__/codex-native-hook.test.ts +273 -5
  136. package/src/scripts/__tests__/native-hook-protocol.test.ts +362 -0
  137. package/src/scripts/__tests__/smoke-packed-install.test.ts +7 -6
  138. package/src/scripts/codex-execution-surface.ts +1 -0
  139. package/src/scripts/codex-native-hook.ts +130 -11
  140. package/src/scripts/hook-payload-guard.ts +1 -0
  141. package/src/scripts/smoke-packed-install.ts +12 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=native-hook-protocol.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-hook-protocol.test.d.ts","sourceRoot":"","sources":["../../../src/scripts/__tests__/native-hook-protocol.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,329 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdir, mkdtemp, readFile, readdir, realpath, rm, writeFile } from "node:fs/promises";
3
+ import { existsSync } from "node:fs";
4
+ import { spawnSync } from "node:child_process";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ import { afterEach, beforeEach, describe, it } from "node:test";
8
+ import { MANAGED_HOOK_EVENTS, buildManagedCodexHooksConfig } from "../../config/codex-hooks.js";
9
+ import { writeSessionStart } from "../../hooks/session.js";
10
+ import { createSubagentTrackingState, readSubagentTrackingState, recordNativeSubagentAuthorityObservation, recordSubagentTurn, withCrossProcessFileLockSync } from "../../subagents/tracker.js";
11
+ import { dispatchCodexNativeHook, mapCodexHookEventToOmxEvent } from "../codex-native-hook.js";
12
+ import { CODEX_HOOK_EVENT_NAMES, extractRawCodexHookEventName, MAX_NATIVE_STDIN_JSON_BYTES } from "../hook-payload-guard.js";
13
+ import { MANAGED_CODEX_HOOK_EVENTS } from "../smoke-packed-install.js";
14
+ describe("native hook protocol compatibility", () => {
15
+ let cwd;
16
+ let env;
17
+ const sessionId = "omx-protocol-session";
18
+ const parentId = "native-parent";
19
+ const agentId = "native-child";
20
+ beforeEach(async () => {
21
+ env = { ...process.env };
22
+ for (const key of Object.keys(process.env)) {
23
+ if (key.startsWith("OMX_") || key === "CODEX_THREAD_ID")
24
+ delete process.env[key];
25
+ }
26
+ cwd = await realpath(await mkdtemp(join(tmpdir(), "omx-native-protocol-")));
27
+ process.env.CODEX_HOME = join(cwd, "codex-home");
28
+ await mkdir(process.env.CODEX_HOME);
29
+ });
30
+ afterEach(async () => {
31
+ process.env = env;
32
+ await rm(cwd, { recursive: true, force: true });
33
+ });
34
+ function stop(overrides = {}) {
35
+ return {
36
+ hook_event_name: "SubagentStop",
37
+ cwd,
38
+ session_id: parentId,
39
+ agent_id: agentId,
40
+ agent_type: "executor",
41
+ turn_id: "child-turn-1",
42
+ transcript_path: null,
43
+ agent_transcript_path: null,
44
+ last_assistant_message: null,
45
+ stop_hook_active: false,
46
+ ...overrides,
47
+ };
48
+ }
49
+ async function start() {
50
+ await writeSessionStart(cwd, sessionId, { nativeSessionId: parentId, pid: process.pid });
51
+ }
52
+ function runNativeHookCli(input = JSON.stringify(stop())) {
53
+ return spawnSync(process.execPath, [join(process.cwd(), "dist/scripts/codex-native-hook.js")], {
54
+ cwd, env: process.env, input, encoding: "utf8", timeout: 10_000,
55
+ });
56
+ }
57
+ async function captureLifecycle(notifications) {
58
+ await writeFile(join(process.env.CODEX_HOME, ".omx-config.json"), JSON.stringify({
59
+ notifications: { enabled: true, ...notifications },
60
+ }));
61
+ const eventsPath = join(cwd, "child-events.jsonl");
62
+ await mkdir(join(cwd, ".omx/hooks"), { recursive: true });
63
+ await writeFile(join(cwd, ".omx/hooks/capture.mjs"), `import { appendFileSync } from 'node:fs';\nexport function onHookEvent(event) { appendFileSync(${JSON.stringify(eventsPath)}, JSON.stringify(event) + '\\n'); }\n`);
64
+ return eventsPath;
65
+ }
66
+ for (const notifications of [
67
+ { verbosity: "session", includeChildAgents: true },
68
+ { verbosity: "agent" },
69
+ { verbosity: "verbose" },
70
+ { verbosity: "session" },
71
+ { verbosity: "minimal" },
72
+ ]) {
73
+ it(`applies the SubagentStop lifecycle policy for ${JSON.stringify(notifications)}`, async () => {
74
+ await start();
75
+ const eventsPath = await captureLifecycle(notifications);
76
+ await dispatchCodexNativeHook(stop());
77
+ assert.ok((await readSubagentTrackingState(cwd)).sessions[sessionId].threads[agentId].completed_at);
78
+ if (notifications.includeChildAgents !== true && !["agent", "verbose"].includes(notifications.verbosity)) {
79
+ assert.equal(existsSync(eventsPath), false);
80
+ return;
81
+ }
82
+ await dispatchCodexNativeHook(stop({ stop_hook_active: true, stopHookActive: true }));
83
+ const events = (await readFile(eventsPath, "utf8")).trim().split("\n").map(line => JSON.parse(line));
84
+ assert.equal(events.length, 1);
85
+ assert.equal(events[0].event, "subagent-stop");
86
+ assert.equal(events[0].source, "native");
87
+ assert.equal(events[0].session_id, sessionId);
88
+ assert.equal(events[0].thread_id, agentId);
89
+ assert.equal(events[0].turn_id, "child-turn-1");
90
+ assert.equal(events[0].context.native_session_id, agentId);
91
+ assert.equal(events[0].context.payload.session_id, parentId);
92
+ assert.equal(events[0].context.payload.stop_hook_active, undefined);
93
+ assert.equal(events[0].context.payload.stopHookActive, undefined);
94
+ await dispatchCodexNativeHook(stop({ turn_id: "child-turn-2" }));
95
+ assert.equal((await readFile(eventsPath, "utf8")).trim().split("\n").length, 2);
96
+ });
97
+ }
98
+ it("deduplicates interleaved child and turn replays independently", async () => {
99
+ await start();
100
+ const eventsPath = await captureLifecycle({ includeChildAgents: true });
101
+ await dispatchCodexNativeHook(stop());
102
+ await dispatchCodexNativeHook(stop({ agent_id: "other-child" }));
103
+ await dispatchCodexNativeHook(stop());
104
+ await dispatchCodexNativeHook(stop({ turn_id: "child-turn-2" }));
105
+ await dispatchCodexNativeHook(stop());
106
+ const events = (await readFile(eventsPath, "utf8")).trim().split("\n").map(line => JSON.parse(line));
107
+ assert.deepEqual(events.map(event => [event.thread_id, event.turn_id]), [
108
+ [agentId, "child-turn-1"], ["other-child", "child-turn-1"], [agentId, "child-turn-2"],
109
+ ]);
110
+ });
111
+ it("deduplicates lifecycle hooks when legacy Stop and SubagentStop report the same child turn", async () => {
112
+ await start();
113
+ const eventsPath = await captureLifecycle({ includeChildAgents: true });
114
+ const legacyFirstChild = "legacy-first-child";
115
+ const nativeFirstChild = "native-first-child";
116
+ for (const childThreadId of [legacyFirstChild, nativeFirstChild]) {
117
+ recordNativeSubagentAuthorityObservation(cwd, {
118
+ sessionIds: [sessionId], childThreadId, parentThreadId: parentId,
119
+ rootNativeSessionId: parentId, authorityEvidence: "valid",
120
+ });
121
+ }
122
+ await dispatchCodexNativeHook({
123
+ hook_event_name: "Stop", cwd, session_id: legacyFirstChild,
124
+ thread_id: legacyFirstChild, turn_id: "turn-legacy-first", stop_hook_active: true,
125
+ });
126
+ await dispatchCodexNativeHook(stop({ agent_id: legacyFirstChild, turn_id: "turn-legacy-first" }));
127
+ await dispatchCodexNativeHook(stop({ agent_id: nativeFirstChild, turn_id: "turn-native-first" }));
128
+ await dispatchCodexNativeHook({
129
+ hook_event_name: "Stop", cwd, session_id: nativeFirstChild,
130
+ thread_id: nativeFirstChild, turn_id: "turn-native-first", stop_hook_active: true,
131
+ });
132
+ const events = (await readFile(eventsPath, "utf8")).trim().split("\n").map(line => JSON.parse(line));
133
+ assert.deepEqual(events.map(event => [event.event, event.thread_id, event.turn_id]), [
134
+ ["stop", legacyFirstChild, "turn-legacy-first"],
135
+ ["subagent-stop", nativeFirstChild, "turn-native-first"],
136
+ ]);
137
+ });
138
+ it("does not deduplicate separate SubagentStop completions when turn IDs are absent", async () => {
139
+ await start();
140
+ const eventsPath = await captureLifecycle({ includeChildAgents: true });
141
+ await dispatchCodexNativeHook(stop({ turn_id: null }));
142
+ await dispatchCodexNativeHook(stop({ turn_id: null }));
143
+ const events = (await readFile(eventsPath, "utf8")).trim().split("\n").map(line => JSON.parse(line));
144
+ assert.equal(events.length, 2);
145
+ assert.deepEqual(events.map(event => event.event), ["subagent-stop", "subagent-stop"]);
146
+ assert.deepEqual(events.map(event => event.turn_id), [undefined, undefined]);
147
+ });
148
+ it("does not treat missing turn IDs as proof of a duplicate completion", () => {
149
+ const first = recordSubagentTurn(createSubagentTrackingState(), {
150
+ sessionId, threadId: agentId, kind: "subagent", completed: true,
151
+ completionSource: "native_stop_event",
152
+ });
153
+ const second = recordSubagentTurn(first, {
154
+ sessionId, threadId: agentId, kind: "subagent", completed: true,
155
+ completionSource: "native_stop_event",
156
+ });
157
+ assert.equal(second.sessions[sessionId].threads[agentId].turn_count, first.sessions[sessionId].threads[agentId].turn_count + 1);
158
+ });
159
+ it("keeps malformed tracker authority bytes intact and returns CLI no-op with a diagnostic", async () => {
160
+ await start();
161
+ const eventsPath = await captureLifecycle({ includeChildAgents: true });
162
+ const trackerPath = join(cwd, ".omx/state/subagent-tracking.json");
163
+ const malformed = '{"schemaVersion":1,"sessions":{"preserve-authority":';
164
+ await writeFile(trackerPath, malformed);
165
+ const result = runNativeHookCli();
166
+ assert.equal(result.status, 0, result.stderr || result.stdout);
167
+ assert.deepEqual(JSON.parse(result.stdout), {});
168
+ assert.equal(await readFile(trackerPath, "utf8"), malformed);
169
+ assert.equal(existsSync(eventsPath), false);
170
+ const logDir = join(cwd, ".omx/logs");
171
+ const logFile = (await readdir(logDir)).find(name => name.startsWith("native-hook-"));
172
+ assert.ok(logFile);
173
+ const diagnostic = await readFile(join(logDir, logFile), "utf8");
174
+ assert.match(diagnostic, /native_subagent_completion_tracking_error/);
175
+ assert.match(diagnostic, /Malformed subagent tracker authority state/);
176
+ });
177
+ it("returns CLI no-op without dispatch or mutation when the tracker lock stays held", async () => {
178
+ await start();
179
+ const eventsPath = await captureLifecycle({ includeChildAgents: true });
180
+ recordNativeSubagentAuthorityObservation(cwd, {
181
+ sessionIds: [sessionId], childThreadId: agentId, parentThreadId: parentId,
182
+ rootNativeSessionId: parentId, authorityEvidence: "valid",
183
+ });
184
+ const trackerPath = join(cwd, ".omx/state/subagent-tracking.json");
185
+ const before = await readFile(trackerPath, "utf8");
186
+ const result = withCrossProcessFileLockSync(trackerPath, () => runNativeHookCli());
187
+ assert.equal(result.status, 0, result.stderr || result.stdout);
188
+ assert.deepEqual(JSON.parse(result.stdout), {});
189
+ assert.equal(await readFile(trackerPath, "utf8"), before);
190
+ assert.equal(existsSync(eventsPath), false);
191
+ });
192
+ it("rejects unbound identities before opted-in SubagentStop lifecycle dispatch", async () => {
193
+ await start();
194
+ const eventsPath = await captureLifecycle({ includeChildAgents: true });
195
+ for (const overrides of [{ session_id: "foreign-parent" }, { agent_id: parentId }, { agent_id: null }]) {
196
+ await dispatchCodexNativeHook(stop(overrides));
197
+ }
198
+ assert.equal(existsSync(eventsPath), false);
199
+ assert.equal(existsSync(join(cwd, ".omx/state/subagent-tracking.json")), false);
200
+ });
201
+ it("keeps setup, bounded input parsing, dispatch, plugin, and packed smoke event rosters aligned", async () => {
202
+ assert.deepEqual(CODEX_HOOK_EVENT_NAMES, MANAGED_HOOK_EVENTS);
203
+ assert.deepEqual(MANAGED_CODEX_HOOK_EVENTS, MANAGED_HOOK_EVENTS);
204
+ const plugin = JSON.parse(await readFile(join(process.cwd(), "plugins/oh-my-codex/hooks/hooks.json"), "utf8"));
205
+ assert.deepEqual(Object.keys(plugin.hooks), [...MANAGED_HOOK_EVENTS]);
206
+ const config = buildManagedCodexHooksConfig("/repo");
207
+ assert.deepEqual(Object.keys(config.hooks), [...MANAGED_HOOK_EVENTS]);
208
+ for (const event of MANAGED_HOOK_EVENTS) {
209
+ assert.equal(extractRawCodexHookEventName(JSON.stringify({ hook_event_name: event })), event);
210
+ assert.ok(mapCodexHookEventToOmxEvent(event));
211
+ assert.match(config.hooks[event][0].hooks[0].command, /codex-native-hook\.js/);
212
+ }
213
+ assert.equal(mapCodexHookEventToOmxEvent("SubagentStop"), "subagent-stop");
214
+ });
215
+ it("records the child, accepts nullable optional fields, and never changes the leader pointer or grants authority", async () => {
216
+ await start();
217
+ const pointer = join(cwd, ".omx/state/session.json");
218
+ const before = await readFile(pointer, "utf8");
219
+ const modePath = join(cwd, ".omx/state/autopilot-state.json");
220
+ const activeMode = JSON.stringify({ active: true, current_phase: "implementation", session_id: sessionId });
221
+ await writeFile(modePath, activeMode);
222
+ const result = await dispatchCodexNativeHook(stop({ future_field: { ignored: true } }));
223
+ assert.equal(result.hookEventName, "SubagentStop");
224
+ assert.equal(result.omxEventName, "subagent-stop");
225
+ assert.equal(result.outputJson, null);
226
+ assert.equal(await readFile(pointer, "utf8"), before);
227
+ assert.equal(await readFile(modePath, "utf8"), activeMode);
228
+ const state = await readSubagentTrackingState(cwd);
229
+ const thread = state.sessions[sessionId].threads[agentId];
230
+ assert.equal(thread.kind, "subagent");
231
+ assert.equal(thread.mode, "executor");
232
+ assert.equal(thread.completion_source, "native_stop_event");
233
+ assert.equal(thread.last_completed_turn_id, "child-turn-1");
234
+ assert.ok(thread.completed_at);
235
+ assert.equal(thread.direct_child_root_id, undefined);
236
+ assert.equal(state.sessions[sessionId].threads[parentId], undefined);
237
+ assert.equal(state.sessions[parentId], undefined);
238
+ });
239
+ it("completes the child in every existing correlated tracker partition", async () => {
240
+ await start();
241
+ recordNativeSubagentAuthorityObservation(cwd, {
242
+ sessionIds: [sessionId, parentId, "previous-canonical-session"],
243
+ childThreadId: agentId,
244
+ parentThreadId: parentId,
245
+ rootNativeSessionId: parentId,
246
+ authorityEvidence: "valid",
247
+ });
248
+ await dispatchCodexNativeHook(stop());
249
+ const state = await readSubagentTrackingState(cwd);
250
+ for (const partitionId of [sessionId, parentId, "previous-canonical-session"]) {
251
+ const thread = state.sessions[partitionId]?.threads[agentId];
252
+ assert.equal(thread?.kind, "subagent");
253
+ assert.equal(thread?.completion_source, "native_stop_event");
254
+ assert.equal(thread?.last_completed_turn_id, "child-turn-1");
255
+ assert.ok(thread?.completed_at);
256
+ assert.equal(thread?.status, "closed");
257
+ assert.equal(thread?.direct_child_root_id, parentId);
258
+ }
259
+ });
260
+ it("deduplicates replays and legacy Stop for the same child turn, but records a new turn", async () => {
261
+ await start();
262
+ recordNativeSubagentAuthorityObservation(cwd, {
263
+ sessionIds: [sessionId], childThreadId: agentId, parentThreadId: parentId,
264
+ rootNativeSessionId: parentId, authorityEvidence: "valid",
265
+ });
266
+ const legacy = { hook_event_name: "Stop", cwd, session_id: sessionId, thread_id: agentId,
267
+ turn_id: "child-turn-1", stop_hook_active: true };
268
+ await dispatchCodexNativeHook(legacy);
269
+ const first = (await readSubagentTrackingState(cwd)).sessions[sessionId].threads[agentId];
270
+ await Promise.all([dispatchCodexNativeHook(stop()), dispatchCodexNativeHook(stop())]);
271
+ await dispatchCodexNativeHook(legacy);
272
+ const replay = (await readSubagentTrackingState(cwd)).sessions[sessionId].threads[agentId];
273
+ assert.deepEqual(replay, first);
274
+ await dispatchCodexNativeHook(stop({ turn_id: "child-turn-2" }));
275
+ const next = (await readSubagentTrackingState(cwd)).sessions[sessionId].threads[agentId];
276
+ assert.equal(next.turn_count, first.turn_count + 1);
277
+ assert.equal(next.last_completed_turn_id, "child-turn-2");
278
+ });
279
+ it("ignores absent, malformed, conflicting, foreign, or leader identities without creating tracking state", async () => {
280
+ await start();
281
+ for (const overrides of [
282
+ { agent_id: null }, { agent_id: "" }, { agent_id: {} }, { agent_id: "../escape" },
283
+ { agent_id: parentId }, { agent_id: sessionId }, { session_id: null },
284
+ { session_id: "" }, { session_id: {} }, { session_id: "other-session" },
285
+ { sessionId: "conflicting-session" },
286
+ ]) {
287
+ const result = await dispatchCodexNativeHook(stop(overrides));
288
+ assert.equal(result.outputJson, null);
289
+ assert.equal(existsSync(join(cwd, ".omx/state/subagent-tracking.json")), false, JSON.stringify(overrides));
290
+ }
291
+ });
292
+ it("does not promote a legacy child Stop without thread_id into its own leader session", async () => {
293
+ await start();
294
+ recordNativeSubagentAuthorityObservation(cwd, {
295
+ sessionIds: [sessionId], childThreadId: agentId, parentThreadId: parentId,
296
+ rootNativeSessionId: parentId, authorityEvidence: "valid",
297
+ });
298
+ const before = await readSubagentTrackingState(cwd);
299
+ await dispatchCodexNativeHook({
300
+ hook_event_name: "Stop", cwd, session_id: agentId,
301
+ turn_id: "child-turn-1", stop_hook_active: true,
302
+ });
303
+ assert.deepEqual(await readSubagentTrackingState(cwd), before);
304
+ await dispatchCodexNativeHook(stop());
305
+ const state = await readSubagentTrackingState(cwd);
306
+ assert.equal(state.sessions[agentId], undefined);
307
+ assert.ok(state.sessions[sessionId].threads[agentId].completed_at);
308
+ });
309
+ it("does not bootstrap a root session from a standalone SubagentStop", async () => {
310
+ assert.equal((await dispatchCodexNativeHook(stop())).outputJson, null);
311
+ assert.equal(existsSync(join(cwd, ".omx")), false);
312
+ });
313
+ it("does not apply leader Stop behavior to malformed SubagentStop input", async () => {
314
+ await start();
315
+ const result = runNativeHookCli('{"hook_event_name":"SubagentStop",');
316
+ assert.equal(result.status, 0, result.stderr || result.stdout);
317
+ assert.deepEqual(JSON.parse(result.stdout), {});
318
+ });
319
+ it("does not block an oversized SubagentStop completion", async () => {
320
+ await start();
321
+ const result = runNativeHookCli(JSON.stringify({
322
+ ...stop(),
323
+ oversized_field: "x".repeat(MAX_NATIVE_STDIN_JSON_BYTES),
324
+ }));
325
+ assert.equal(result.status, 0, result.stderr || result.stdout);
326
+ assert.deepEqual(JSON.parse(result.stdout), {});
327
+ });
328
+ });
329
+ //# sourceMappingURL=native-hook-protocol.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-hook-protocol.test.js","sourceRoot":"","sources":["../../../src/scripts/__tests__/native-hook-protocol.test.ts"],"names":[],"mappings":"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"}
@@ -395,7 +395,7 @@ test('packed lifecycle requires enabled command handlers and integer hook metada
395
395
  assert.doesNotThrow(() => parseCodexHooksListResult(valid, project, hooksPath), `${source} is a valid hook source`);
396
396
  }
397
397
  });
398
- test('packed lifecycle requires exactly seven generated OMX trust keys and an isolated approval target', () => {
398
+ test('packed lifecycle requires exactly eight generated OMX trust keys and an isolated approval target', () => {
399
399
  const hooks = MANAGED_CODEX_HOOK_EVENTS.map((event, index) => ({
400
400
  event,
401
401
  command: 'node /tmp/omx/dist/scripts/codex-native-hook.js',
@@ -410,8 +410,8 @@ test('packed lifecycle requires exactly seven generated OMX trust keys and an is
410
410
  assert.throws(() => assertGeneratedTrustMatchesCodex({
411
411
  ...trust,
412
412
  '/tmp/project/.codex/hooks.json:foreign:0:0': 'sha256:foreign',
413
- }, hooks), /exactly the 7 current OMX hooks with no stale keys/);
414
- assert.throws(() => assertGeneratedTrustMatchesCodex(Object.fromEntries(Object.entries(trust).slice(0, -1)), hooks), /exactly the 7 current OMX hooks with no stale keys/);
413
+ }, hooks), /exactly the 8 current OMX hooks with no stale keys/);
414
+ assert.throws(() => assertGeneratedTrustMatchesCodex(Object.fromEntries(Object.entries(trust).slice(0, -1)), hooks), /exactly the 8 current OMX hooks with no stale keys/);
415
415
  assert.doesNotThrow(() => assertCodexBatchWriteResult({
416
416
  filePath: '/tmp/isolated-codex-home/config.toml',
417
417
  status: 'ok',
@@ -449,10 +449,10 @@ test('packed lifecycle fails closed on malformed project hooks.state entries and
449
449
  assert.throws(() => generatedHookTrustState(`[hooks.state]\n${malformedEntry}`), /invalid hooks\.state entry first/);
450
450
  }
451
451
  const staleRawTrust = generatedHookTrustState(`${validConfig}\nforeign = { trusted_hash = "sha256:foreign" }`);
452
- assert.throws(() => assertGeneratedTrustMatchesCodex(staleRawTrust, hooks), /exactly the 7 current OMX hooks with no stale keys/);
452
+ assert.throws(() => assertGeneratedTrustMatchesCodex(staleRawTrust, hooks), /exactly the 8 current OMX hooks with no stale keys/);
453
453
  const protoRawTrust = generatedHookTrustState(`${validConfig}\n__proto__ = { trusted_hash = "sha256:proto" }`);
454
454
  assert.equal(Object.hasOwn(protoRawTrust, '__proto__'), true);
455
- assert.throws(() => assertGeneratedTrustMatchesCodex(protoRawTrust, hooks), /exactly the 7 current OMX hooks with no stale keys/);
455
+ assert.throws(() => assertGeneratedTrustMatchesCodex(protoRawTrust, hooks), /exactly the 8 current OMX hooks with no stale keys/);
456
456
  });
457
457
  test('packed lifecycle treats only the production command grammar as managed ownership', () => {
458
458
  const hooks = MANAGED_CODEX_HOOK_EVENTS.map((event, index) => ({
@@ -879,6 +879,7 @@ test('packed install smoke covers every installed native hook event with minimal
879
879
  'UserPromptSubmit',
880
880
  'PreCompact',
881
881
  'PostCompact',
882
+ 'SubagentStop',
882
883
  'Stop',
883
884
  ]);
884
885
  for (const eventName of PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS) {
@@ -1093,7 +1094,7 @@ test('packed install native hook stdout validation allows empty or JSON output o
1093
1094
  assert.doesNotThrow(() => validateHookStdout('Stop', '{}\n'));
1094
1095
  assert.throws(() => validateHookStdout('UserPromptSubmit', '{not json'), /native hook UserPromptSubmit emitted invalid JSON stdout/);
1095
1096
  });
1096
- test('packed lifecycle and native hook smoke share the seven managed event names', () => {
1097
+ test('packed lifecycle and native hook smoke share the managed event names', () => {
1097
1098
  assert.deepEqual(MANAGED_CODEX_HOOK_EVENTS, PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS);
1098
1099
  });
1099
1100
  test('packed install native hook stdout validation enforces event output contracts', () => {