Skip to content

fix(core,storage): unify the Codex thread source gate - #3702

Open
cat0825 wants to merge 1 commit into
apache:mainfrom
cat0825:fix/3693-codex-source-authority
Open

fix(core,storage): unify the Codex thread source gate#3702
cat0825 wants to merge 1 commit into
apache:mainfrom
cat0825:fix/3693-codex-source-authority

Conversation

@cat0825

@cat0825 cat0825 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #3693.

The foreign-session scanner (@maka/core/foreign-session) and the Codex Session adapter (@maka/storage) each owned a private set of eligible Codex source tokens. The sets drifted, so the same Codex thread could be visible through one surface and invisible through the other:

source on the thread scanner (before) adapter (before)
exec dropped listed
atlas, chatgpt (bare) listed dropped
{"custom":"cli"}, {"custom":"vscode"} listed dropped
NULL / absent column dropped listed

The last two rows are divergences beyond the table in the issue. The NULL case is the one that bites hardest in practice: older Codex schemas have no source column at all, so the scanner hid every legacy thread that the adapter happily catalogued.

CODEX_SUPPORTED_THREAD_SOURCES in @maka/core/foreign-session is now the single authority, and the adapter's duplicate isRootCodexSource is deleted.

On the union. The issue asks for a ruling on whether bare exec belongs. It does: #2502's own description lists "root cli, exec, and vscode Sessions" as what the adapter surfaces, and exec has been in the adapter's set since its first commit (23f624b). The scanner's set predates it (#1057, #1208) and simply never learned about headless codex exec runs. The unified set is therefore cli, exec, vscode, atlas, chatgpt — the union, adopting exec rather than dropping it.

Two supporting changes fall out of the merge:

  • codexSourceToken now also accepts an already-parsed object, which is the shape rollout session_meta payloads arrive in. Previously the adapter needed its own recursion to handle that; now one function covers the bare token, the JSON object string, and the parsed object.
  • isSupportedCodexThreadSource states the absent-is-eligible rule once, instead of having each call site re-derive it (the scanner spelled it row.source !== undefined && token === undefined, the adapter spelled it as an early return true, and only one of the two also handled null).

Internal subagent threads ({"subagent":{"thread_spawn":{…}}}) resolve to no token in either form and stay out of both surfaces, unchanged.

Verification

  • npm --workspace @maka/core run test — 658 pass, 0 fail (clean + build + node --test)
  • npm --workspace @maka/storage run test — 927 pass, 14 skipped, 0 fail
  • npm exec -- biome check on the four changed files — no fixes applied

New coverage:

  • packages/core/src/__tests__/foreign-session.test.ts — bare exec; already-parsed objects ({custom:'atlas'}atlas, {custom:'unknown'} → undefined, subagent → undefined); a table-driven check that every token in the set resolves in both the bare and {"custom":…} forms; NULL source column treated as absent rather than unsupported.
  • packages/storage/src/__tests__/codex-session-adapter.test.ts — a catalog listing seeded with all five sources in both forms plus a subagent thread, asserting the adapter now lists exactly what the scanner accepts and still excludes the subagent.

The storage test was checked against a negative control: reverting only codex-session-adapter.ts and rebuilding fails it with wrapped cli was dropped, so it exercises the merged gate rather than passing vacuously.

The foreign-session scanner and the Codex Session adapter each owned a
private set of eligible `source` tokens, so the same Codex thread could be
visible through one surface and invisible through the other:

- bare `exec` was accepted by the adapter but dropped by the scanner;
- bare `atlas`/`chatgpt` and wrapped `{"custom":"cli"}` / `{"custom":"vscode"}`
  were accepted by the scanner but dropped by the adapter;
- a NULL `source` column was admitted by the adapter but dropped by the
  scanner, hiding threads written by older Codex schemas.

Make `CODEX_SUPPORTED_THREAD_SOURCES` in `@maka/core/foreign-session` the
single authority (`cli`, `exec`, `vscode`, `atlas`, `chatgpt`) and delete the
adapter's duplicate gate. `codexSourceToken` now also accepts an
already-parsed object, which is the shape rollout `session_meta` payloads
arrive in, and the new `isSupportedCodexThreadSource` states the
absent-is-eligible rule once instead of at each call site. Internal
subagent threads (`{"subagent":{…}}`) still resolve to no token and stay
out of both surfaces.

Closes apache#3693
@cat0825

cat0825 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

@Astro-Han when you have a moment, would you mind taking a look at this one?

Status: CI is green, and GitHub reports it as mergeable against current main with no conflicts. The change is small (+112 / -40 across 4 files) and scoped to unifying the Codex thread source gate between core and storage, with test coverage on both sides.

No rush — flagging it since it is review-ready and I would rather not let it drift into conflict. Happy to rebase or split it if that makes review easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex thread source eligibility differs between the foreign-session scanner and the Codex session adapter

1 participant