@deksden-com/dd-flow-cli 0.9.0-beta.10 → 0.9.0-beta.11

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @deksden-com/dd-flow-cli
2
2
 
3
+ ## 0.9.0-beta.11
4
+
5
+ ### Patch Changes
6
+
7
+ - Bind a native Codex subagent Work to the child Thread identifier supplied as
8
+ `agent_id`, rather than Codex's inherited root hook session identifier.
9
+
3
10
  ## 0.9.0-beta.10
4
11
 
5
12
  ### Patch Changes
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "cli_package": "@deksden-com/dd-flow-cli",
3
- "cli_version": "0.9.0-beta.10",
4
- "cli_commit": "460b71fed9e52e0be2cb95d3a565d9ec015d6da7",
5
- "built_at": "2026-09-04T16:11:29.424Z",
3
+ "cli_version": "0.9.0-beta.11",
4
+ "cli_commit": "67fea9fdb3fbcc04cc0a45de9afc5f7120c13a08",
5
+ "built_at": "2026-09-04T20:59:42.597Z",
6
6
  "built_with_canon": {
7
7
  "version": "4.0.2",
8
8
  "commit": "fccdb9fe7359f2ba321eebace328fd18557dcd25",
@@ -268,7 +268,13 @@ export function handleCodexHook(context, input) {
268
268
  if (eventName !== "PreToolUse") {
269
269
  return { ok: true, observed: false, reason: "event_not_participating", event: eventName };
270
270
  }
271
- const sessionId = stringValue(payload.session_id);
271
+ const rootProviderSessionId = stringValue(payload.session_id) ?? null;
272
+ // Codex deliberately retains its legacy root session_id inside a
273
+ // thread-spawned subagent. `agent_id` is the current child Thread id and
274
+ // therefore the only valid identity for a fresh Work.
275
+ const rawChildProviderSessionId = stringValue(payload.agent_id) ?? null;
276
+ const providerSessionId = rawChildProviderSessionId ?? rootProviderSessionId;
277
+ const parentProviderSessionId = rawChildProviderSessionId ? codexNativeParentId(payload, rawChildProviderSessionId) : null;
272
278
  const turnId = stringValue(payload.turn_id);
273
279
  const toolName = stringValue(payload.tool_name) ?? toolNameFromPayload(payload);
274
280
  const command = lifecycleCommandFromPayload(payload);
@@ -303,10 +309,16 @@ export function handleCodexHook(context, input) {
303
309
  const project = projectForHook(context, input.projectRoot ?? commandProjectRoot, stringValue(payload.cwd));
304
310
  if (!project)
305
311
  return { ok: true, observed: false, reason: "unrelated_cwd" };
306
- const binding = sessionId ? upsertSessionBindingFromPayload(context, project, sessionId, payload) : undefined;
307
- const storageId = sessionId ? storageSessionId(nativeSessionIdentity("codex-desktop", sessionId)) : null;
312
+ const binding = rootProviderSessionId ? upsertSessionBindingFromPayload(context, project, rootProviderSessionId, payload) : undefined;
313
+ const storageId = providerSessionId ? storageSessionId(nativeSessionIdentity("codex-desktop", providerSessionId)) : null;
314
+ const parentSessionId = parentProviderSessionId ? storageSessionId(nativeSessionIdentity("codex-desktop", parentProviderSessionId)) : null;
308
315
  const observedSession = flowPayload
309
- ? bindObservedFlowSession(context, project, { ...flowPayload, harness: "codex-desktop", provider_session_id: sessionId ?? flowPayload.provider_session_id ?? null }, storageId ?? undefined)
316
+ ? bindObservedFlowSession(context, project, {
317
+ ...flowPayload,
318
+ harness: "codex-desktop",
319
+ provider_session_id: providerSessionId ?? flowPayload.provider_session_id ?? null,
320
+ parent_session_id: parentSessionId
321
+ }, storageId ?? undefined)
310
322
  : undefined;
311
323
  const effectiveSessionId = observedSession?.session_id ?? storageId;
312
324
  const protocolId = observedSession?.protocol_id ?? binding?.protocol_id ?? null;
@@ -315,10 +327,10 @@ export function handleCodexHook(context, input) {
315
327
  projectId: project.id,
316
328
  protocolId,
317
329
  harness: "codex-desktop",
318
- providerSessionId: sessionId ?? null,
319
- parentSessionId: null,
330
+ providerSessionId: providerSessionId ?? null,
331
+ parentSessionId,
320
332
  sessionId: effectiveSessionId,
321
- agentId: stringValue(payload.agent_id) ?? null,
333
+ agentId: rawChildProviderSessionId ?? null,
322
334
  turnId: turnId ?? null,
323
335
  eventName,
324
336
  toolName: toolName ?? null,
@@ -345,9 +357,10 @@ export function handleCodexHook(context, input) {
345
357
  observed: inserted,
346
358
  duplicate: !inserted,
347
359
  event_key: eventKey,
348
- session: sessionId ? nativeSessionIdentity("codex-desktop", sessionId) : null,
360
+ session: providerSessionId ? nativeSessionIdentity("codex-desktop", providerSessionId) : null,
361
+ ...(parentProviderSessionId ? { parent_session: nativeSessionIdentity("codex-desktop", parentProviderSessionId) } : {}),
349
362
  protocol_id: protocolId,
350
- ...(sessionId && (flowPayload || stageStart || stageResume || workStart)
363
+ ...(providerSessionId && (flowPayload || stageStart || stageResume || workStart)
351
364
  ? {
352
365
  hookSpecificOutput: {
353
366
  hookEventName: "PreToolUse",
@@ -358,6 +371,24 @@ export function handleCodexHook(context, input) {
358
371
  : {})
359
372
  };
360
373
  }
374
+ /** The hook protocol does not carry the immediate parent. Recover it only from this child's own native transcript. */
375
+ function codexNativeParentId(payload, childId) {
376
+ const transcript = stringValue(payload.transcript_path);
377
+ if (!transcript || !path.isAbsolute(transcript))
378
+ return null;
379
+ try {
380
+ const firstLine = fs.readFileSync(transcript, "utf8").split("\n", 1)[0];
381
+ if (!firstLine)
382
+ return null;
383
+ const record = JSON.parse(firstLine);
384
+ return record.type === "session_meta" && record.payload?.id === childId && typeof record.payload.parent_thread_id === "string"
385
+ ? record.payload.parent_thread_id
386
+ : null;
387
+ }
388
+ catch {
389
+ return null;
390
+ }
391
+ }
361
392
  /** Convert a zcode-acp Bash tool notification into the same trusted lifecycle receipt used by Codex hooks. */
362
393
  export function handleZcodeEvent(context, input) {
363
394
  const notification = parseJsonObject(input.stdin || "{}", "zcode ACP notification");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deksden-com/dd-flow-cli",
3
- "version": "0.9.0-beta.10",
3
+ "version": "0.9.0-beta.11",
4
4
  "description": "Mechanical runtime CLI for dd-flow workflows.",
5
5
  "type": "module",
6
6
  "bin": {