@makaio/client-codex 1.0.0-dev-1789642522820 → 1.0.0-dev-1790599449321

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/README.md CHANGED
@@ -11,7 +11,7 @@ Static client definition and schema library for the OpenAI Codex CLI. This packa
11
11
  | `version` | `0.1.0` |
12
12
  | `description` | OpenAI Codex CLI — an agentic coding assistant |
13
13
  | `binary.name` | `codex` |
14
- | `binary.supportedVersions` | `0.144.1` |
14
+ | `binary.supportedVersions` | `0.158.0` |
15
15
  | `defaultApprovalPolicy` | `full-access` |
16
16
  | `defaultAuth` | `openai-codex` via client method `native` |
17
17
  | `configIsolation.envVar` | `CODEX_HOME` |
package/descriptor.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "id": "codex",
15
15
  "name": "Codex",
16
16
  "description": "OpenAI Codex CLI \u2014 an agentic coding assistant",
17
- "binary": { "name": "codex", "managed": true, "version": "0.144.1" }
17
+ "binary": { "name": "codex", "managed": true, "version": "0.158.0" }
18
18
  }
19
19
  ]
20
20
  }
@@ -1,6 +1,6 @@
1
1
  import { codexCapabilityMap, createClientDefinition } from "@makaio/framework/contracts";
2
2
  import { z } from "zod";
3
- import { AbsolutePathSchema, BinaryNotFoundError, ClientSubjects, ClientWiringApplyResponseSchema, ClientWiringListResponseSchema, ClientWiringRemoveResponseSchema, DEFAULT_HOOK_HANDLE_TIMEOUT_MS, NOOP_HOOK_HANDLE_RESPONSE, assertAbsoluteProjectDir, atomicModifyFile, buildClientCommand, buildHookCommand, collectContributions, createClientNamespace, deriveSessionEventDescriptors, pickNonEmptyString } from "@makaio/framework/clients";
3
+ import { AbsolutePathSchema, BinaryNotFoundError, ClientSubjects, ClientWiringApplyResponseSchema, ClientWiringListResponseSchema, ClientWiringRemoveResponseSchema, DEFAULT_HOOK_HANDLE_TIMEOUT_MS, NOOP_HOOK_HANDLE_RESPONSE, assertAbsoluteProjectDir, atomicModifyFile, buildClientCommand, buildHookCommand, collectContributions, createClientNamespace, deriveSessionEventDescriptors, pickNonEmptyString, pickNonEmptyStringValue } from "@makaio/framework/clients";
4
4
  import { MakaioBus, RequestError } from "@makaio/framework/bus";
5
5
  import { BaseService } from "@makaio/framework/service-base";
6
6
  import * as fs$1 from "node:fs/promises";
@@ -45,12 +45,12 @@ const clientDefinition = createClientDefinition({
45
45
  description: "OpenAI Codex CLI — an agentic coding assistant",
46
46
  binary: {
47
47
  name: "codex",
48
- supportedVersions: "0.144.1"
48
+ supportedVersions: "0.158.0"
49
49
  },
50
50
  managedInstall: {
51
51
  type: "npm",
52
52
  package: "@openai/codex",
53
- version: "0.144.1"
53
+ version: "0.158.0"
54
54
  },
55
55
  versionCommand: {
56
56
  executable: {
@@ -973,11 +973,13 @@ async function handleCodexConfigPrime(payload) {
973
973
  *
974
974
  * The `SessionStart` hook payload has no lineage field at all: it carries
975
975
  * `session_id`, `transcript_path`, `cwd`, `hook_event_name`, `model`,
976
- * `permission_mode` and `source` — nothing else. A fork also reports
977
- * `source: 'startup'`, exactly like a brand-new thread, so the hook alone
978
- * cannot distinguish the two. `transcript_path` points at the rollout file
979
- * the CLI has just materialized for the starting thread, which makes the
980
- * rollout head the only lineage source available at session-start time.
976
+ * `permission_mode` and `source` — nothing else. Since Codex `0.158.0` a fork
977
+ * reports `source: 'fork'`, so the hook tells *that* a thread is a fork but not
978
+ * *whose* fork it is. `transcript_path` points at the rollout file the CLI has
979
+ * just materialized for the starting thread; the sniff confirms the parent from
980
+ * that rollout's first `session_meta` line, which makes the rollout head the
981
+ * only lineage source available at session-start time. An ephemeral fork has no
982
+ * rollout file (`transcript_path: null`), so its parent cannot be recovered.
981
983
  *
982
984
  * ## Detection invariant
983
985
  *
@@ -990,8 +992,10 @@ async function handleCodexConfigPrime(payload) {
990
992
  * - `forked_from_id` absent (or equal to the own id, which would be a
991
993
  * self-reference and is never a usable parent) → no fork signal.
992
994
  * - No parseable `session_meta` inside the window → inconclusive; return
993
- * `undefined`. Fork registration is fill-once on the ingestion side, so a
994
- * guessed parent would be permanently wrong while deferring is safe.
995
+ * `undefined`. The caller then reports the start as `'fresh'` without a
996
+ * parent instead of guessing one: fork lineage is existing-wins at
997
+ * ingestion, so a guessed parent would stick, while an unset parent can
998
+ * still be filled by a later import.
995
999
  *
996
1000
  * Anchoring the window at the start of the file is what makes the rule sound
997
1001
  * under a byte cap: the decisive record is the first one, so no earlier record
@@ -1130,7 +1134,7 @@ async function sniffRolloutFork(rolloutPath, hookSessionId) {
1130
1134
  * emissions. Any event NOT listed here is left as raw `client:codex`
1131
1135
  * namespace data only.
1132
1136
  *
1133
- * Event names are verified against pinned source `rust-v0.144.1`
1137
+ * Event names are verified against pinned source `rust-v0.158.0`
1134
1138
  * (`codex-rs/hooks/src/lib.rs`).
1135
1139
  */
1136
1140
  const CODEX_HOOK_SESSION_START = "SessionStart";
@@ -1169,7 +1173,7 @@ const CODEX_HOOK_PRE_COMPACT = "PreCompact";
1169
1173
  * are never emitted into the global `client.*` namespace.
1170
1174
  *
1171
1175
  * **Source notes:** Event names are verified against the pinned
1172
- * `rust-v0.144.1` Codex source (`codex-rs/hooks/src/lib.rs`). Update this
1176
+ * `rust-v0.158.0` Codex source (`codex-rs/hooks/src/lib.rs`). Update this
1173
1177
  * normalizer when a new binary version changes or adds hook names.
1174
1178
  *
1175
1179
  * **Subagent hooks:** On both `SubagentStart` and `SubagentStop`, the raw
@@ -1193,21 +1197,20 @@ const COMPACTION_TRIGGERS = new Set(CLIENT_SESSION_COMPACTION_TRIGGERS);
1193
1197
  * Map from the Codex CLI `SessionStart.source` union to the
1194
1198
  * framework-level {@link ClientSessionStartMode}.
1195
1199
  *
1196
- * - `'startup'` → `'fresh'` (brand-new thread — **and a fork child**, see
1197
- * below; the owning service upgrades the fork case to `'fork'`)
1200
+ * - `'startup'` → `'fresh'` (brand-new thread; never a fork)
1198
1201
  * - `'resume'` → `'resume'` (thread continued from its own rollout file)
1199
1202
  * - `'clear'` → `'clear'` (conversation cleared, new thread id)
1200
1203
  * - `'compact'` → `'compact'` (context compacted, same thread id)
1204
+ * - `'fork'` → `'fork'` (fork child with a new thread id)
1201
1205
  *
1202
- * The vendor union has exactly these four values in the pinned `rust-v0.144.1`
1203
- * source (`codex-rs/hooks/src/events/session_start.rs`, `SessionStartSource`);
1204
- * there is no `'fork'` value. In `codex-rs/core/src/session/session.rs` a fork
1205
- * is classified next to a brand-new thread — the match arm that maps
1206
- * `InitialHistory::New` to `SessionStartSource::Startup` also covers
1207
- * `InitialHistory::Forked` — which is why `'startup'`, not `'resume'`, is the
1208
- * mode that may still turn out to be a fork.
1209
- * Lineage is recovered from the rollout file instead; see the fork sniff in
1210
- * `fork-sniff.ts` and its caller in `codex-client-session-service.ts`.
1206
+ * The vendor union has these five values in the pinned `rust-v0.158.0`
1207
+ * source (`codex-rs/hooks/src/events/session_start.rs`, `SessionStartSource`).
1208
+ * Forks are reported explicitly as `'fork'`; `'startup'` covers only
1209
+ * `InitialHistory::New`, so a `'startup'` session is never a fork.
1210
+ * The hook payload still carries no parent id: the owning service recovers it
1211
+ * from the rollout file and falls back to `'fresh'` when it cannot. See the
1212
+ * fork sniff in `fork-sniff.ts` and its caller in
1213
+ * `codex-client-session-service.ts`.
1211
1214
  *
1212
1215
  * Vendor values not in this map yield `undefined`, leaving `startMode`
1213
1216
  * absent from the normalized payload — safe for forward compatibility when
@@ -1217,7 +1220,8 @@ const VENDOR_SOURCE_TO_START_MODE = {
1217
1220
  startup: "fresh",
1218
1221
  resume: "resume",
1219
1222
  clear: "clear",
1220
- compact: "compact"
1223
+ compact: "compact",
1224
+ fork: "fork"
1221
1225
  };
1222
1226
  /**
1223
1227
  * Extract the `source` field from a `SessionStart` hook payload and map it
@@ -1490,13 +1494,13 @@ function normalizeCodexHook(raw, machineId) {
1490
1494
 
1491
1495
  //#endregion
1492
1496
  //#region src/runtime/hook-response-contracts.ts
1493
- /** Codex 0.144.1 synchronous hook-response contract. @packageDocumentation */
1497
+ /** Codex 0.158.0 synchronous hook-response contract. @packageDocumentation */
1494
1498
  const CODEX_CLIENT_ID = "codex";
1495
1499
  const CODEX_CONTRACT_ID = "openai.codex-hook-response";
1496
1500
  /**
1497
1501
  * Semantic version of the Codex hook-response contract.
1498
1502
  *
1499
- * Pinned to the proven capabilities of Codex CLI 0.144.1. Bump this version
1503
+ * Pinned to the proven capabilities of Codex CLI 0.158.0. Bump this version
1500
1504
  * when a future CLI release expands the native response surface.
1501
1505
  *
1502
1506
  * `1.2.0` adds `SubagentStart` as a request-capable, non-blockable interaction
@@ -1742,7 +1746,7 @@ const codexProviderContractCatalog = Object.freeze({
1742
1746
 
1743
1747
  //#endregion
1744
1748
  //#region src/runtime/hook-response-composer.ts
1745
- /** Deterministic Codex 0.144.1 hook-response composition. @packageDocumentation */
1749
+ /** Deterministic Codex 0.158.0 hook-response composition. @packageDocumentation */
1746
1750
  /**
1747
1751
  * Resolve the declared response capabilities for one Codex event.
1748
1752
  * @param eventName - Native Codex hook event name.
@@ -3408,8 +3412,9 @@ var CodexClientSessionService = class extends BaseService {
3408
3412
  *
3409
3413
  * The handler receives request-mode hook payloads and returns a
3410
3414
  * {@link ClientHookHandleResponse} composed by
3411
- * {@link composeCodexHookResponse}. The pinned Codex `0.144.1` source
3412
- * parses synchronous responses for all five declared events.
3415
+ * {@link composeCodexHookResponse}. The pinned Codex `0.158.0` source
3416
+ * parses synchronous responses for every event the definition declares
3417
+ * with response capabilities.
3413
3418
  *
3414
3419
  * Extracted from {@link onInit} to keep the init method concise.
3415
3420
  */
@@ -3485,7 +3490,7 @@ var CodexClientSessionService = class extends BaseService {
3485
3490
  * Called for every `client.runtime.started` event. Only events whose
3486
3491
  * `clientId` equals `'codex'`, whose `source.layer` is `'adapter'`, and
3487
3492
  * that carry a non-empty `adapterSessionId` update the managed-sessions gate.
3488
- * Events from other clients (e.g. `'claude-code'`, `'gemini'`) are ignored
3493
+ * Events from other clients (e.g. `'claude-code'`, `'qwen'`) are ignored
3489
3494
  * unconditionally — their adapter sessions must not suppress Codex hook
3490
3495
  * emissions. Non-adapter sources (e.g. `'supervisor'`, `'statusline'`) are
3491
3496
  * also ignored to prevent accidental suppression of native hook paths.
@@ -3519,6 +3524,7 @@ var CodexClientSessionService = class extends BaseService {
3519
3524
  */
3520
3525
  async handleHookReceived(raw) {
3521
3526
  const events = normalizeCodexHook(raw, this.machineId);
3527
+ await this.observeRootRuntime(raw, events);
3522
3528
  if (events.length === 0 && (raw.eventName === "SubagentStart" || raw.eventName === "SubagentStop")) console.warn(`[CodexClientSessionService] ${raw.eventName} hook produced no normalized events — agent_id is likely absent. The hook remains raw-only on client:codex.*.`);
3523
3529
  const sharedAdapterSessionId = events[0]?.payload.adapterSessionId;
3524
3530
  const isManagedSession = this.isAdapterManagedSession(sharedAdapterSessionId);
@@ -3570,6 +3576,38 @@ var CodexClientSessionService = class extends BaseService {
3570
3576
  if (firstError !== void 0) throw firstError;
3571
3577
  }
3572
3578
  /**
3579
+ * Enrich a supervisor-owned Codex runtime with the native session ID observed
3580
+ * on its root `SessionStart` hook.
3581
+ *
3582
+ * Subagent hooks never produce `client.session.started`, so they cannot bind
3583
+ * a root runtime. The supervisor correlation key joins observations; it does
3584
+ * not grant ownership of an arbitrary native session.
3585
+ * @param raw - Raw hook payload delivered on `client:codex.hook.received`.
3586
+ * @param events - Normalized events derived from the raw hook.
3587
+ */
3588
+ async observeRootRuntime(raw, events) {
3589
+ if (raw.eventName !== "SessionStart") return;
3590
+ const supervisorSessionId = pickNonEmptyStringValue(raw.metadata?.supervisorSessionId);
3591
+ const rootStart = events.find((event) => event.subject === ClientSubjects.session.started);
3592
+ const adapterSessionId = rootStart?.payload.adapterSessionId;
3593
+ if (supervisorSessionId === void 0 || rootStart === void 0 || adapterSessionId === void 0) return;
3594
+ try {
3595
+ if (!(await this.bus.requestOptional(ClientSubjects.runtime.observe, {
3596
+ clientId: CLIENT_ID,
3597
+ source: {
3598
+ layer: "client-hook",
3599
+ producer: "codex-client-session-service"
3600
+ },
3601
+ observedAt: raw.receivedAt,
3602
+ supervisorSessionId,
3603
+ adapterSessionId,
3604
+ ...rootStart.payload.startMode === "clear" && { adapterSessionTransition: "root-clear" }
3605
+ })).handled) console.warn("[CodexClientSessionService] Runtime identity join is unavailable.");
3606
+ } catch {
3607
+ console.warn("[CodexClientSessionService] Runtime identity join is unavailable.");
3608
+ }
3609
+ }
3610
+ /**
3573
3611
  * Determine whether a normalized native hook belongs to an adapter-managed
3574
3612
  * session whose global observed-semantics events are already emitted by the
3575
3613
  * adapter layer.
@@ -3595,37 +3633,45 @@ var CodexClientSessionService = class extends BaseService {
3595
3633
  return startMode !== "compact" && startMode !== "clear";
3596
3634
  }
3597
3635
  /**
3598
- * Enrich a `client.session.started` payload with fork lineage when the
3599
- * normalizer reported `startMode: 'fresh'` and a rollout path is available.
3636
+ * Resolve fork lineage for a `client.session.started` payload the normalizer
3637
+ * reported with `startMode: 'fork'`.
3638
+ *
3639
+ * Codex `0.158.0` reports a fork child explicitly as `SessionStart` with
3640
+ * `source: 'fork'`, but the payload carries no parent id. The child's rollout
3641
+ * file opens with its own `session_meta` record, and that record names
3642
+ * `forked_from_id` — the parent thread id. This method performs a bounded
3643
+ * read of the rollout head to recover it and populates
3644
+ * `parentAdapterSessionId`.
3600
3645
  *
3601
- * Codex classifies a fork child next to a brand-new thread: both fire
3602
- * `SessionStart` with `source: 'startup'`, and the payload carries no
3603
- * lineage field. The child's rollout file, however, opens with its own
3604
- * `session_meta` record, and that record names `forked_from_id` — the parent
3605
- * thread id. This method performs a bounded read of the rollout head to
3606
- * recover it, upgrading `startMode` from `'fresh'` to `'fork'` and
3607
- * populating `parentAdapterSessionId`.
3646
+ * When the parent cannot be recovered — no rollout path (an ephemeral fork
3647
+ * reports `transcript_path: null`), an unreadable file, or no
3648
+ * `forked_from_id` — the payload is downgraded to `startMode: 'fresh'`, so a
3649
+ * `'fork'` event never goes out without its parent.
3608
3650
  *
3609
- * Only `'fresh'` is sniffed. A resume appends to the *existing* rollout file,
3610
- * so a resumed fork child would still show its original `forked_from_id`;
3651
+ * Only `'fork'` is sniffed. `'startup'` (mapped to `'fresh'`) is only ever a
3652
+ * brand-new thread, and a resume appends to the *existing* rollout file, so a
3653
+ * resumed fork child would still show its original `forked_from_id`;
3611
3654
  * upgrading it to `'fork'` would re-register an already known session instead
3612
3655
  * of letting ingestion rebind it by adapter session id.
3613
3656
  *
3614
3657
  * Runs **after** the managed-session suppression gate (so adapter-managed
3615
3658
  * sessions are already filtered out) and **before** bus emission.
3616
3659
  *
3617
- * On any sniff error the payload is returned unchanged — hook processing must
3618
- * never be blocked by a sniff failure.
3660
+ * Sniff errors never throw — hook processing must never be blocked by a
3661
+ * sniff failure; they count as "parent not recovered".
3619
3662
  * @param payload - Normalized `client.session.started` payload
3620
- * @returns The payload, potentially enriched with fork lineage fields
3663
+ * @returns The payload with fork lineage, the payload downgraded to
3664
+ * `'fresh'`, or the unchanged payload for any other start mode
3621
3665
  */
3622
3666
  async enrichForkLineage(payload) {
3623
- if (payload.startMode !== "fresh" || payload.transcriptPath === void 0 || payload.adapterSessionId === void 0) return payload;
3624
- const sniffResult = await sniffRolloutFork(payload.transcriptPath, payload.adapterSessionId);
3625
- if (sniffResult === void 0) return payload;
3667
+ if (payload.startMode !== "fork") return payload;
3668
+ const sniffResult = payload.transcriptPath === void 0 || payload.adapterSessionId === void 0 ? void 0 : await sniffRolloutFork(payload.transcriptPath, payload.adapterSessionId);
3669
+ if (sniffResult === void 0) return {
3670
+ ...payload,
3671
+ startMode: "fresh"
3672
+ };
3626
3673
  return {
3627
3674
  ...payload,
3628
- startMode: "fork",
3629
3675
  parentAdapterSessionId: sniffResult.parentAdapterSessionId
3630
3676
  };
3631
3677
  }
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as CodexConfigHooksAddResponseSchema, B as CodexScopeHookRecordSchema, D as CodexWiringSchemas, F as CodexConfigSchemas, I as CodexHookEntrySchema, L as CodexNativeCommandHookSchema, M as CodexConfigHooksListResponseSchema, N as CodexConfigHooksRemoveRequestSchema, O as AbsolutePathSchema, P as CodexConfigHooksRemoveResponseSchema, R as CodexNativeHookMatcherGroupSchema, U as clientDefinition, V as CodexScopeSchema, j as CodexConfigHooksListRequestSchema, k as CodexConfigHooksAddRequestSchema, o as CodexClientSubjects, t as CodexClientSessionService, z as CodexNativeHooksFileSchema } from "./codex-client-session-service-BrCcbB06.mjs";
2
- import { t as codexPackage } from "./src-D25LSa6Y.mjs";
1
+ import { A as CodexConfigHooksAddResponseSchema, B as CodexScopeHookRecordSchema, D as CodexWiringSchemas, F as CodexConfigSchemas, I as CodexHookEntrySchema, L as CodexNativeCommandHookSchema, M as CodexConfigHooksListResponseSchema, N as CodexConfigHooksRemoveRequestSchema, O as AbsolutePathSchema, P as CodexConfigHooksRemoveResponseSchema, R as CodexNativeHookMatcherGroupSchema, U as clientDefinition, V as CodexScopeSchema, j as CodexConfigHooksListRequestSchema, k as CodexConfigHooksAddRequestSchema, o as CodexClientSubjects, t as CodexClientSessionService, z as CodexNativeHooksFileSchema } from "./codex-client-session-service-SDzI8cot.mjs";
2
+ import { t as codexPackage } from "./src-D8eg77KO.mjs";
3
3
 
4
4
  export { AbsolutePathSchema, CodexClientSessionService, CodexClientSubjects, CodexConfigHooksAddRequestSchema, CodexConfigHooksAddResponseSchema, CodexConfigHooksListRequestSchema, CodexConfigHooksListResponseSchema, CodexConfigHooksRemoveRequestSchema, CodexConfigHooksRemoveResponseSchema, CodexConfigSchemas, CodexHookEntrySchema, CodexNativeCommandHookSchema, CodexNativeHookMatcherGroupSchema, CodexNativeHooksFileSchema, CodexScopeHookRecordSchema, CodexScopeSchema, CodexWiringSchemas, clientDefinition, codexPackage };
@@ -29,7 +29,7 @@
29
29
  * silently dropped — the adapter path already owns the canonical emission.
30
30
  * Sessions whose `adapterSessionId` is absent or not yet registered emit as
31
31
  * before (fail-open). Events from other clients (e.g. `'claude-code'`,
32
- * `'gemini'`) are ignored unconditionally — their adapter sessions must not
32
+ * `'qwen'`) are ignored unconditionally — their adapter sessions must not
33
33
  * suppress Codex hook emissions.
34
34
  *
35
35
  * The managed-session set is bounded at {@link MANAGED_SESSION_CAP} entries to
@@ -165,8 +165,9 @@ export declare class CodexClientSessionService extends BaseService {
165
165
  *
166
166
  * The handler receives request-mode hook payloads and returns a
167
167
  * {@link ClientHookHandleResponse} composed by
168
- * {@link composeCodexHookResponse}. The pinned Codex `0.144.1` source
169
- * parses synchronous responses for all five declared events.
168
+ * {@link composeCodexHookResponse}. The pinned Codex `0.158.0` source
169
+ * parses synchronous responses for every event the definition declares
170
+ * with response capabilities.
170
171
  *
171
172
  * Extracted from {@link onInit} to keep the init method concise.
172
173
  */
@@ -188,7 +189,7 @@ export declare class CodexClientSessionService extends BaseService {
188
189
  * Called for every `client.runtime.started` event. Only events whose
189
190
  * `clientId` equals `'codex'`, whose `source.layer` is `'adapter'`, and
190
191
  * that carry a non-empty `adapterSessionId` update the managed-sessions gate.
191
- * Events from other clients (e.g. `'claude-code'`, `'gemini'`) are ignored
192
+ * Events from other clients (e.g. `'claude-code'`, `'qwen'`) are ignored
192
193
  * unconditionally — their adapter sessions must not suppress Codex hook
193
194
  * emissions. Non-adapter sources (e.g. `'supervisor'`, `'statusline'`) are
194
195
  * also ignored to prevent accidental suppression of native hook paths.
@@ -199,6 +200,7 @@ export declare class CodexClientSessionService extends BaseService {
199
200
  */
200
201
  private handleRuntimeStarted;
201
202
  private handleHookReceived;
203
+ private observeRootRuntime;
202
204
  /**
203
205
  * Determine whether a normalized native hook belongs to an adapter-managed
204
206
  * session whose global observed-semantics events are already emitted by the
@@ -12,11 +12,13 @@
12
12
  *
13
13
  * The `SessionStart` hook payload has no lineage field at all: it carries
14
14
  * `session_id`, `transcript_path`, `cwd`, `hook_event_name`, `model`,
15
- * `permission_mode` and `source` — nothing else. A fork also reports
16
- * `source: 'startup'`, exactly like a brand-new thread, so the hook alone
17
- * cannot distinguish the two. `transcript_path` points at the rollout file
18
- * the CLI has just materialized for the starting thread, which makes the
19
- * rollout head the only lineage source available at session-start time.
15
+ * `permission_mode` and `source` — nothing else. Since Codex `0.158.0` a fork
16
+ * reports `source: 'fork'`, so the hook tells *that* a thread is a fork but not
17
+ * *whose* fork it is. `transcript_path` points at the rollout file the CLI has
18
+ * just materialized for the starting thread; the sniff confirms the parent from
19
+ * that rollout's first `session_meta` line, which makes the rollout head the
20
+ * only lineage source available at session-start time. An ephemeral fork has no
21
+ * rollout file (`transcript_path: null`), so its parent cannot be recovered.
20
22
  *
21
23
  * ## Detection invariant
22
24
  *
@@ -29,8 +31,10 @@
29
31
  * - `forked_from_id` absent (or equal to the own id, which would be a
30
32
  * self-reference and is never a usable parent) → no fork signal.
31
33
  * - No parseable `session_meta` inside the window → inconclusive; return
32
- * `undefined`. Fork registration is fill-once on the ingestion side, so a
33
- * guessed parent would be permanently wrong while deferring is safe.
34
+ * `undefined`. The caller then reports the start as `'fresh'` without a
35
+ * parent instead of guessing one: fork lineage is existing-wins at
36
+ * ingestion, so a guessed parent would stick, while an unset parent can
37
+ * still be filled by a later import.
34
38
  *
35
39
  * Anchoring the window at the start of the file is what makes the rule sound
36
40
  * under a byte cap: the decisive record is the first one, so no earlier record
@@ -23,7 +23,7 @@
23
23
  * are never emitted into the global `client.*` namespace.
24
24
  *
25
25
  * **Source notes:** Event names are verified against the pinned
26
- * `rust-v0.144.1` Codex source (`codex-rs/hooks/src/lib.rs`). Update this
26
+ * `rust-v0.158.0` Codex source (`codex-rs/hooks/src/lib.rs`). Update this
27
27
  * normalizer when a new binary version changes or adds hook names.
28
28
  *
29
29
  * **Subagent hooks:** On both `SubagentStart` and `SubagentStop`, the raw
@@ -4,7 +4,7 @@ export declare const CODEX_CONTRACT_ID = "openai.codex-hook-response";
4
4
  /**
5
5
  * Semantic version of the Codex hook-response contract.
6
6
  *
7
- * Pinned to the proven capabilities of Codex CLI 0.144.1. Bump this version
7
+ * Pinned to the proven capabilities of Codex CLI 0.158.0. Bump this version
8
8
  * when a future CLI release expands the native response surface.
9
9
  *
10
10
  * `1.2.0` adds `SubagentStart` as a request-capable, non-blockable interaction
@@ -1,4 +1,4 @@
1
- import { C as createCodexStopBlockEffect, E as normalizeCodexHook, H as CODEX_HOOK_RESPONSE_CAPABILITIES, S as createCodexSessionStartContextEffect, T as createCodexUserPromptSubmitContextEffect, _ as createCodexPreToolUseBlockEffect, a as CODEX_CLIENT_NAMESPACE, b as createCodexPreToolUseUpdateEffect, c as CODEX_CLIENT_ID, d as CODEX_INTERACTION_BLOCKABILITY, f as CODEX_RESPONSE_CAPABILITIES, g as createCodexPostToolUseContextEffect, h as createCodexPostToolUseBlockEffect, i as withCodexNativeAuthSourceLock, l as CODEX_CONTRACT_ID, m as codexProviderContractCatalog, n as buildCodexNativeAuthSourceLockPath, o as CodexClientSubjects, p as CODEX_SUPPORTED_INTERACTIONS, r as executeCodexNativeAuthSourceLock, s as composeCodexHookResponse, t as CodexClientSessionService, u as CODEX_CONTRACT_VERSION, v as createCodexPreToolUseContextEffect, w as createCodexUserPromptSubmitBlockEffect, x as createCodexSessionStartBlockEffect, y as createCodexPreToolUseDenyEffect } from "../codex-client-session-service-BrCcbB06.mjs";
1
+ import { C as createCodexStopBlockEffect, E as normalizeCodexHook, H as CODEX_HOOK_RESPONSE_CAPABILITIES, S as createCodexSessionStartContextEffect, T as createCodexUserPromptSubmitContextEffect, _ as createCodexPreToolUseBlockEffect, a as CODEX_CLIENT_NAMESPACE, b as createCodexPreToolUseUpdateEffect, c as CODEX_CLIENT_ID, d as CODEX_INTERACTION_BLOCKABILITY, f as CODEX_RESPONSE_CAPABILITIES, g as createCodexPostToolUseContextEffect, h as createCodexPostToolUseBlockEffect, i as withCodexNativeAuthSourceLock, l as CODEX_CONTRACT_ID, m as codexProviderContractCatalog, n as buildCodexNativeAuthSourceLockPath, o as CodexClientSubjects, p as CODEX_SUPPORTED_INTERACTIONS, r as executeCodexNativeAuthSourceLock, s as composeCodexHookResponse, t as CodexClientSessionService, u as CODEX_CONTRACT_VERSION, v as createCodexPreToolUseContextEffect, w as createCodexUserPromptSubmitBlockEffect, x as createCodexSessionStartBlockEffect, y as createCodexPreToolUseDenyEffect } from "../codex-client-session-service-SDzI8cot.mjs";
2
2
  import { dep } from "@makaio/framework/contracts";
3
3
  import { ClientsCoreToken } from "@makaio/framework/clients";
4
4
 
@@ -8,13 +8,18 @@
8
8
  * The hook name constants below are the canonical event names reported in the
9
9
  * `eventName` field of {@link RawClientHookPayload} by the Codex CLI.
10
10
  *
11
- * Event names are verified against the pinned `rust-v0.144.1` Codex source
11
+ * Event names are verified against the pinned `rust-v0.158.0` Codex source
12
12
  * (`codex-rs/hooks/src/lib.rs` — `HOOK_EVENT_NAMES` and
13
- * `engine/output_parser.rs`). The full set present in 0.144.1 is:
13
+ * `engine/output_parser.rs`). The full set present in 0.158.0 is:
14
14
  * `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop`,
15
15
  * `SubagentStart`, `SubagentStop`, `PreCompact`, `PostCompact`,
16
- * `PermissionRequest`. `SessionEnd` and `Interrupt` are NOT present.
17
- * @see https://github.com/openai/codex/tree/rust-v0.144.1/codex-rs/hooks
16
+ * `PermissionRequest`, `SessionEnd`, `Interrupt`.
17
+ *
18
+ * `SessionEnd` and `Interrupt` (new since 0.156) are deliberately NOT declared
19
+ * or modelled here (maintainer decision, FACT-88): they have no consumer and
20
+ * no bus subject, and declaring them would spawn a hook process on every
21
+ * interrupt and every session end.
22
+ * @see https://github.com/openai/codex/tree/rust-v0.158.0/codex-rs/hooks
18
23
  * @packageDocumentation
19
24
  */
20
25
  export { RawClientHookPayloadSchema, type RawClientHookPayload } from '@makaio/framework/clients';
@@ -25,7 +30,7 @@ export { RawClientHookPayloadSchema, type RawClientHookPayload } from '@makaio/f
25
30
  * emissions. Any event NOT listed here is left as raw `client:codex`
26
31
  * namespace data only.
27
32
  *
28
- * Event names are verified against pinned source `rust-v0.144.1`
33
+ * Event names are verified against pinned source `rust-v0.158.0`
29
34
  * (`codex-rs/hooks/src/lib.rs`).
30
35
  */
31
36
  export declare const CODEX_HOOK_SESSION_START = "SessionStart";
package/dist/server.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as codexPackage } from "./src-D25LSa6Y.mjs";
1
+ import { t as codexPackage } from "./src-D8eg77KO.mjs";
2
2
  import { codexClientRuntimePackage } from "./runtime/package.mjs";
3
3
 
4
4
  //#region src/server.ts
@@ -1,4 +1,4 @@
1
- import { U as clientDefinition } from "./codex-client-session-service-BrCcbB06.mjs";
1
+ import { U as clientDefinition } from "./codex-client-session-service-SDzI8cot.mjs";
2
2
 
3
3
  //#region src/package.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makaio/client-codex",
3
- "version": "1.0.0-dev-1789642522820",
3
+ "version": "1.0.0-dev-1790599449321",
4
4
  "type": "module",
5
5
  "main": "dist/index.mjs",
6
6
  "exports": {