You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
resolveCodexContext (hypaware-core/plugins-workspace/codex/src/exchange-projector.js:678-761) derives a turn's identity and lineage from x-codex-turn-metadata plus a set of bare header names. Read against Codex's own source (protocol.rs, client.rs:929, sturn.rs:342-345):
The authoritative thread_id is in the request BODY, not a header.client_metadata() always puts flat session_id + thread_id in the body. HypAware never reads it. Everything it does read is a header or the metadata blob, both of which are version-dependent.
compatibility_headers emits only four names: x-codex-window-id, x-codex-turn-metadata, x-codex-parent-thread-id, x-openai-subagent. Any other bare name HypAware looks for (readHeader is exact-match) can never match. Worth auditing every readHeader call in this file against that list.
x-codex-turn-metadata is emitted for every ordinary turn (request_kind = Turn), not only Desktop. llp/0083:31 and llp/0141:25-27 state or imply codex-tui never sends it, and PR Codex rollout cwd keys on the thread, not the session container (#459) #462 relied on that premise before its review disproved it. The LLP text was corrected there; the code still reads the blob as if it were a Desktop-only signal.
Because reading client_metadata.thread_id and correcting the header names both change recorded rows - conversation_id, parent_thread_id, is_sidechain. That is a data-shape change with backfill and row-identity consequences (see llp/0030, the partition key), not a bug fix, so it belongs to a human. #462 stayed inside the .hypignore cwd defect it was filed for.
Why it matters
Lineage decides is_sidechain and parent_thread_id, and thread identity feeds the cwd resolution that .hypignore is evaluated against (llp/0083, llp/0050). Deriving them from a version-specific surface while a stable one goes unread means the classification silently drifts with the Codex version - the same class of defect as #453 and #459, one layer up.
Suggested shape
Prefer body client_metadata.thread_id/session_id as the authority, keep the headers and metadata blob as fallbacks, and decide explicitly what happens to already-recorded rows (leave them, or backfill). Any change to conversation_id must be checked against row identity: the fallback-hash scope is conversation_id ?? session_id, so moving it silently re-keys history.
Ground-truth gate
Tests must pin: a turn with only body metadata resolves correctly; a turn with only the four real headers resolves correctly; a bare header name Codex never sends resolves to nothing rather than a wrong value; and part_id/message_id are byte-identical to today for existing shapes.
Provenance
Findings (b) and F2 from the review of PR #462 (#462), verified against Codex source. Related: #453, #459, LLP 0030, LLP 0083, LLP 0141.
What
resolveCodexContext(hypaware-core/plugins-workspace/codex/src/exchange-projector.js:678-761) derives a turn's identity and lineage fromx-codex-turn-metadataplus a set of bare header names. Read against Codex's own source (protocol.rs,client.rs:929,sturn.rs:342-345):thread_idis in the request BODY, not a header.client_metadata()always puts flatsession_id+thread_idin the body. HypAware never reads it. Everything it does read is a header or the metadata blob, both of which are version-dependent.compatibility_headersemits only four names:x-codex-window-id,x-codex-turn-metadata,x-codex-parent-thread-id,x-openai-subagent. Any other bare name HypAware looks for (readHeaderis exact-match) can never match. Worth auditing everyreadHeadercall in this file against that list.x-codex-turn-metadatais emitted for every ordinary turn (request_kind = Turn), not only Desktop.llp/0083:31andllp/0141:25-27state or implycodex-tuinever sends it, and PR Codex rollout cwd keys on the thread, not the session container (#459) #462 relied on that premise before its review disproved it. The LLP text was corrected there; the code still reads the blob as if it were a Desktop-only signal.Why it was not fixed in PR #462
Because reading
client_metadata.thread_idand correcting the header names both change recorded rows -conversation_id,parent_thread_id,is_sidechain. That is a data-shape change with backfill and row-identity consequences (seellp/0030, the partition key), not a bug fix, so it belongs to a human. #462 stayed inside the.hypignorecwd defect it was filed for.Why it matters
Lineage decides
is_sidechainandparent_thread_id, and thread identity feeds the cwd resolution that.hypignoreis evaluated against (llp/0083,llp/0050). Deriving them from a version-specific surface while a stable one goes unread means the classification silently drifts with the Codex version - the same class of defect as #453 and #459, one layer up.Suggested shape
Prefer body
client_metadata.thread_id/session_idas the authority, keep the headers and metadata blob as fallbacks, and decide explicitly what happens to already-recorded rows (leave them, or backfill). Any change toconversation_idmust be checked against row identity: the fallback-hash scope isconversation_id ?? session_id, so moving it silently re-keys history.Ground-truth gate
Tests must pin: a turn with only body metadata resolves correctly; a turn with only the four real headers resolves correctly; a bare header name Codex never sends resolves to nothing rather than a wrong value; and
part_id/message_idare byte-identical to today for existing shapes.Provenance
Findings (b) and F2 from the review of PR #462 (#462), verified against Codex source. Related: #453, #459, LLP 0030, LLP 0083, LLP 0141.