Skip to content

feat(ingest): distinguish T3 app Codex sessions - #633

Open
EtanHey wants to merge 8 commits into
mainfrom
feat/d3-t3-provenance
Open

feat(ingest): distinguish T3 app Codex sessions#633
EtanHey wants to merge 8 commits into
mainfrom
feat/d3-t3-provenance

Conversation

@EtanHey

@EtanHey EtanHey commented Aug 1, 2026

Copy link
Copy Markdown
Owner

What broke and how it was found

T3-app-initiated Codex transcripts were indistinguishable from ordinary terminal Codex sessions: provenance_class LIKE %t3% returned 0. The explicit discriminator is provider_session_runtime.resume_cursor_json.threadId in the read-only T3 state DB.

Evidence

  • The canonical systems Codex session 019fb03f-0650-7f53-850b-921246951edc has 728 chunks and links to T3 thread 5ca576df-592c-406f-a8f1-7db9c56d36c9.
  • 29 linked Codex sessions were found; 1,228 genuine codex-session rows are tagged t3-app-session.
  • The non-collision fixture proves a plain Codex working on t3layer remains codex-session; schema drift raises an alarm.

Review

This branch was pair-reviewed by a separate agent under the taste gate: smallest correct solution, behavioural tests, and no speculative machinery.

Provenance-column warning

chunks.provenance_class currently serves both as a trust ladder and a source class, with independent writers and no precedence rule. This PR is correct, but enrichment can overwrite its source tag until that collision is resolved. See design collision.

Enrichment and drain are currently disabled with launchctl to stop that decay; re-enable deliberately only after the column question is settled.


Note

Medium Risk
Changes provenance classification and can bulk-update chunks.provenance_class; incorrect T3 linkage or retag misuse could mislabel searchable memory, though rollback and schema-drift alarms mitigate operational risk.

Overview
Codex transcripts started from the T3 Code app are now labeled t3-app-session instead of generic codex-session, using explicit linkage from the read-only T3 runtime DB (provider_session_runtime.resume_cursor_json.threadId).

Ingest path: New t3_provenance helpers resolve linked session IDs; classify_provenance checks T3 linkage before recon-agent and default Codex rules, and the realtime watcher loads linked IDs once per flush (via BRAINLAYER_T3_STATE_DB). Missing T3 state is ignored; present DB with bad schema or invalid cursor JSON raises alarms rather than silently mis-tagging.

Backfill: scripts/retag_t3_app_provenance.py dry-runs or batch-updates existing codex-session rows for linked sessions, with JSONL rollback/restore and optimistic WHERE provenance_class = ? guards.

Other: mcp is capped at <2; pytest autouse fixture points BRAINLAYER_T3_STATE_DB at a non-existent path so tests never hit a developer’s live T3 DB.

Reviewed by Cursor Bugbot for commit 17e293b. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Tag Codex sessions initiated by the T3 app with a distinct 't3-app-session' provenance

  • Adds t3_provenance.py with utilities to extract Codex session IDs from filenames and query the T3 runtime SQLite state DB for linked session IDs.
  • Extends classify_provenance in agent_provenance.py to return t3-app-session (with KEEP search policy) for Codex sessions linked by the T3 runtime, taking precedence over recon-agent signatures.
  • Updates watcher_bridge.py to load T3-linked session IDs once per flush and pass them to classify_provenance, avoiding repeated DB queries.
  • Adds retag_t3_app_provenance.py, a CLI script to retroactively re-tag existing codex-session chunks to t3-app-session with dry-run, rollback artifact, and batched conditional UPDATE support.
  • Risk: classification now reads the T3 state DB on every watcher flush (once per flush); missing or schema-mismatched DB raises a BrainLayer alarm.

Macroscope summarized 17e293b.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@EtanHey, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d85f5405-416b-4cdc-9f47-64c76d6c9c15

📥 Commits

Reviewing files that changed from the base of the PR and between 0a8cbbf and 17e293b.

📒 Files selected for processing (8)
  • pyproject.toml
  • scripts/retag_t3_app_provenance.py
  • src/brainlayer/agent_provenance.py
  • src/brainlayer/t3_provenance.py
  • src/brainlayer/watcher_bridge.py
  • tests/conftest.py
  • tests/test_retag_t3_app_provenance.py
  • tests/test_t3_app_provenance.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread scripts/retag_t3_app_provenance.py Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 20e0108. Configure here.

Comment thread src/brainlayer/t3_provenance.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20e0108fa0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/retag_t3_app_provenance.py Outdated
for batch_start in range(0, len(candidates), batch_size):
batch = candidates[batch_start : batch_start + batch_size]
connection.executemany(
"UPDATE chunks SET provenance_class = ? WHERE id = ?",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard retags with the selected provenance

When the watcher or enrichment changes a candidate after _candidates() reads it but before this batch executes, the unconditional update overwrites that newer provenance with t3-app-session. The busy timeout only serializes individual SQLite statements, while each batch commit leaves a race across the scan-to-update interval; add the expected codex-session value to the WHERE clause or hold the repository's writer lock for the operation.

AGENTS.md reference: AGENTS.md:L28-L30

Useful? React with 👍 / 👎.

Comment thread scripts/retag_t3_app_provenance.py Outdated
else {}
)
existing.update(dict(candidates))
with path.open("w", encoding="utf-8") as artifact:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve existing rollback artifacts atomically

When --apply is rerun with an existing artifact, this "w" open truncates the only rollback record before the preserved entries are rewritten. A crash, interruption, or ENOSPC during that rewrite can therefore destroy recovery data for rows changed by the earlier run even though the merge behavior explicitly supports artifact reuse; write a temporary file and atomically replace the artifact instead.

AGENTS.md reference: AGENTS.md:L5-L8

Useful? React with 👍 / 👎.

Comment thread scripts/retag_t3_app_provenance.py Outdated
pre_restore_path.parent.mkdir(parents=True, exist_ok=True)
with pre_restore_path.open("x", encoding="utf-8") as artifact:
for chunk_id, _ in candidates:
artifact.write(json.dumps({"id": chunk_id, "provenance_class": current_values[chunk_id]}) + "\n")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle deleted chunks in pre-restore snapshots

If any chunk recorded in an older rollback artifact has since been deleted, current_values has no entry for that ID and this lookup raises KeyError. Because the pre-restore file has already been opened with "x", the failed rollback also leaves an empty or partial artifact that blocks retry, so later rollback of the remaining rows cannot proceed without manual cleanup; skip absent IDs or represent their absence explicitly.

AGENTS.md reference: AGENTS.md:L5-L8

Useful? React with 👍 / 👎.

@EtanHey

EtanHey commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

VERDICT: ITERATE
TASTE: The runtime-link discriminator is direct and appropriately small (20e0108f:src/brainlayer/t3_provenance.py:37-45, 20e0108f:src/brainlayer/t3_provenance.py:48-86). The surrounding hot-path lookup and rollback framework are working-but-scenic: classification reopens and rescans the live T3 DB once per emitted chunk (20e0108f:src/brainlayer/watcher_bridge.py:376-422), while the added recovery machinery is not atomic or concurrency-safe. CodeRabbit status: SKIPPED — rate-limited; manual red-team/blue-team fallback performed.
TESTS: Clean baseline/final: 18 passed across test_t3_app_provenance.py, test_retag_t3_app_provenance.py, and test_agent_provenance.py; Ruff check/format passed. Mutation 1 disabled the T3 precedence return and 4/6 T3 feature tests died. Mutation 2 removed the exact codex-session candidate guard and the retag test died (3 candidates/retags instead of 1). Mutation 3 disabled only_null_prior_values and the rollback test died (2 restored instead of 1). Scratch reproductions additionally measured 5 T3 DB opens for 5 classifications, both retag and rollback overwriting a newer ladder value, a missing rollback row raising KeyError and leaving a zero-byte pre-restore artifact, and a simulated write failure truncating a reused rollback artifact to zero bytes. The GitHub Python 3.11 job fails during collection in untouched MCP code (Server.list_tools); this diff does not touch that path.
MISSED BY FIRST REVIEW: The apply-side race was noted by automated review, but rollback has the same unguarded clobber: UPDATE chunks SET provenance_class = ? WHERE id = ? overwrites enrichment changes made after retagging (20e0108f:scripts/retag_t3_app_provenance.py:153-159). Under the known two-writer collision, this is not safe. Also confirmed the post-review findings for per-chunk DB scans, non-atomic artifact reuse, and deleted-row rollback failure.
BLOCKERS: 1) Load linked T3 session IDs once per watcher flush and pass/reuse that set instead of opening/scanning the DB per chunk. 2) Guard retag updates with expected codex-session and rollback updates with expected t3-app-session, and report actual matched/changed rows (20e0108f:scripts/retag_t3_app_provenance.py:91-101, 20e0108f:scripts/retag_t3_app_provenance.py:153-163). 3) Write rollback and pre-restore artifacts through fsynced temporary files plus atomic replace; skip/report missing IDs without leaving an empty artifact that blocks retry (20e0108f:scripts/retag_t3_app_provenance.py:37-52, 20e0108f:scripts/retag_t3_app_provenance.py:126-152).

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@cursor

cursor Bot commented Aug 1, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_c56bff01-49fd-4531-a378-51d94e69a48a)

@EtanHey

EtanHey commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@cursor @BugBot review

@cursor

cursor Bot commented Aug 1, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_4d748502-2014-4a2e-9860-6aa39a776b64)

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@EtanHey

EtanHey commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

@codex review

CI compatibility follow-up: constrain MCP to the supported 1.x API range after MCP 2.0 removed Server.list_tools.

@cursor

cursor Bot commented Aug 1, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_5db5e816-8ed7-4cde-a982-9766c34634e5)

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17e293b630

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +150 to +153
is_t3_app_initiated_codex_session(
source_file,
state_db=t3_state_db,
linked_session_ids=t3_linked_session_ids,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cache T3 linkage for the report scan

When a T3 state DB exists, scripts/provenance_classify_report.py:32-37 calls classify_provenance once for every chunk without supplying t3_linked_session_ids, so every Codex chunk reaching this branch reopens and rescans provider_session_runtime. Since a single session can contain hundreds of chunks, the canonical report now performs O(C×R) SQLite work and may classify one session inconsistently if T3 state changes mid-scan; load the linked IDs once in build_report and pass that set to each classification.

Useful? React with 👍 / 👎.

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.

1 participant