Skip to content

docs(audit): inventory the transcript capture producers (#716, slice 1) - #874

Merged
cdeust merged 2 commits into
mainfrom
fix/716-rollout-capture
Nov 5, 2026
Merged

cdeust merged 2 commits into
mainfrom
fix/716-rollout-capture

Conversation

@cdeust

@cdeust cdeust commented Nov 5, 2026 •

Copy link
Copy Markdown
Owner

Summary

First slice of #716 (resumable incremental transcript capture). The issue's own first step is "audit all capture producers first; reuse any existing cursor/idempotency mechanism". This PR is that audit, with no code change: docs/audits/transcript-capture-producers-2026-11-05.md.

Findings (each cited to a line at main 2126d2a):

  • No producer keeps a cursor into a transcript (no offset, line count or last-seen turn). Existing progress markers: a 64 KiB head hash (backfill), transcript stem / sha256(session_id) (SessionEnd), spool and queue files, exact-content dedup in remember.
  • Nothing discovers Codex rollouts; a rollout is read only when SessionEnd hands its transcript_path, and only tool names and turn counts are extracted.
  • Codex SessionEnd intake (session_queue.py) keys its job by sha256(session_id) alone and drops a second SessionEnd of the same session (receipt exists, or os.link keeps the first queued payload): a second rollout file reaches neither the session log nor the profile — the first blocker for acceptance item 1 of feat: specify and verify resumable incremental transcript capture across Codex rollouts #716. The stem / session_id key split in session_lifecycle only matters for a direct (unqueued) call.
  • The resident capture worker acknowledges before storing (inferred: loss, not duplicate, on crash after ack).

Refs #716 — not Closes.

Type of change

  • Documentation (audit)

Test plan

Not verified here: the claims marked inferred in the audit were derived from the cited code, not executed.

Audit notes

Remaining slices of #716, after the owner's product decision (build a cursor, or document the limits and close, per the issue's Alternatives considered):

  1. Test: one session over two rollout files reaches the log and the profile with both files' activity; the fix starts at the Codex intake key (sha256(session_id) in session_queue.py), which must also name the file or its turns, then the stem / session_id split for direct calls.
  2. Repeat delivery + lost acknowledgement test on the capture worker path (ack-before-store).
  3. Prefix-rewrite detection, or an explicit documented limit.
  4. Native event receipts per advertised host, separate from synthetic hook tests.

Breaking changes

None.


Generated by Claude Code

No producer keeps a cursor into a transcript, none discovers Codex
rollouts, and the only rollout reader extracts tool names and turn
counts. The audit cites each session key, dedup and replay path so the
owner can decide between a durable cursor and documented limits.

Refs #716

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYthhBeHYUUVXweieTP
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T18:51:28.764765Z 0db1f65 New commits
🔒 Security Review ✅ Completed 2026-11-05T18:52:00.889948Z 0db1f65 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 2m 59s —— View job


PR #874 review (1 of 3)

Blocker (1): the audit's P1 claim at docs/audits/transcript-capture-producers-2026-11-05.md:50-53 is false for Codex. It says a Codex session continued into a second rollout file "gets two log rows but one profile update". In fact, Codex intake keys each job by sha256(session_id). A second SessionEnd with the same session_id is dropped at intake, either by the existing receipt or by the swallowed os.link error. So the second file reaches neither the log nor the profile, and the planned "stem / session_id key split" fix would not cover Codex.

Notes (3, no action before merge):

  • The inventory misses a producer: record_session_end.
  • Some cited lines are missing or off by one.
  • Two head/tail-read caveats are missing from P3/P4.

CI gates are unaffected and no security problems were found.

Verdict: block

@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: 238a40585d

ℹ️ 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 +50 to +53
(`session_lifecycle.py:359-372`). *Inferred:* a Codex session continued
into a second rollout file gets two log rows but one profile update, so
the second file's activity never reaches the profile — acceptance item 1
of #716 fails on the profile path.

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 Account for intake deduplication in the multi-rollout conclusion

For the Codex hook path described above, a second rollout with the same session_id never reaches the lifecycle handler: plugins/hypermnesia-mcp-codex/scripts/session_queue.py::enqueue keys the job solely by sha256(session_id), returns immediately when its completed receipt exists, and preserves the first queued payload when the job is still pending. Consequently, this path produces neither a second log row nor a second profile update. Please distinguish direct lifecycle calls from queued Codex delivery and identify the intake deduplication as an additional blocker; otherwise the audit directs the later multi-file fix toward the log/profile key split while overlooking where the second file is actually discarded.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmé et corrigé dans 0db1f65. enqueue clé le job par sha256(session_id) seul, rend la main dès qu'un reçu completed/ existe, et os.link conserve la première charge d'un job encore en attente (session_queue.py:89-111). Sur le chemin Codex en file d'attente, le second rollout n'atteint donc jamais session_lifecycle. L'audit distingue maintenant la livraison en file d'attente (rejet à l'entrée, premier obstacle au critère 1 de #716) de l'appel direct (la séparation des clés journal/profil, toujours marquée inferred). La section « What a later slice can reuse » ne présente plus la clé session_id comme la bonne pour une session sur plusieurs fichiers.


Generated by Claude Code

@claude

claude Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 1m 32s —— View job


Review 1 of 3: no Blockers. Verdict: approve

The cited lines match the code, and the fixup 0db1f65 addresses Codex's comment about the intake dedup. I didn't run the doc-claims or craftsmanship checks; I read the scripts instead. Neither can fail here: one doesn't scan docs/audits/ or CHANGELOG.md, and the other only checks Python. The /review-pr skill failed to load, so I ran the five reviews directly.

Notes, no action before merge

  • The capture_client.py:39 citation is off by one; the docstring it backs is at :40.
  • In P2, "at-least-once" for the spool is too broad. A failed or timed-out store is renamed *.rejected and never retried.
  • P2, P4 and P5 cite whole files with no line numbers, unlike the rest of the doc.

@claude

claude Bot commented Nov 5, 2026

Copy link
Copy Markdown

PR #874 review (1 of 3), head 238a405

I ran five reviews: documentation accuracy, code quality/CI, security, performance and test coverage. All but one of the cited lines match the tree. CI gates are unaffected: check_doc_claims.py doesn't scan docs/audits/ or CHANGELOG.md, and the craftsmanship gate only checks Python files. Nothing leaks.

Blocker

The P1 claim about Codex sessions is false (docs/audits/transcript-capture-producers-2026-11-05.md:50-53, repeated at :115-118).

The audit says a Codex session continued into a second rollout file "gets two log rows but one profile update". That can't happen on the Codex path:

  • Codex SessionEnd reaches session_lifecycle only through session_queue.py intake (plugins/hypermnesia-mcp-codex/hooks/hooks.json:92).
  • Intake keys the job by sha256(session_id) (session_queue.py:95-96).
  • If the first job already finished, its receipt exists, so the second SessionEnd returns at :97-98. Receipts are never deleted (the only writer is :203).
  • If the first job is still queued, os.link raises FileExistsError, which is swallowed (:108-111). The second payload and its transcript_path are discarded.

So Codex writes one log row and one profile update, both from the first file. The second file's activity reaches neither, so acceptance item 1 of #716 fails on both paths, not just the profile path. The stem / session_id split only applies to the direct Claude hook.

This matters because the remaining-slices plan aims at "the fix of the stem / session_id key split". On Codex that fix would change nothing: the drop happens at intake. Your own :57-58 already describes this short-circuit, so the audit contradicts itself.

Fix this →

Notes, no action before merge

  • The inventory misses a producer: the record_session_end MCP tool writes memories through remember (mcp_server/handlers/record_session_end_memory.py:46-81). The "five producers" count in CHANGELOG would change.
  • Some citations don't meet the "every claim cites a line" promise. P2's memory_exact_sql.py/remember.py/capture_drain.py (capture_drain.py:65-72) and P4/P5 have no line numbers, and capture_client.py:39 is the def line (the docstring is at :40).
  • P3/P4 should qualify two points. Both readers see only head and tail, so a file's middle is never captured. And "a long transcript that grows is never re-read" holds only for files over 64 KiB.

Verdict: block

@claude

claude Bot commented Nov 5, 2026

Copy link
Copy Markdown

Review 1 of 3 — PR #874 (head 0db1f65)

Five reviews were run: documentation accuracy, code quality, security, performance and test coverage. Every cited file:line was checked against the tree at 2126d2a, and the PR changes no code. No Blockers.

  • The cited ranges match the code:
    • session_lifecycle.py:233-238/240-241/257-261/359-372
    • session_queue.py:89-111/201-204
    • capture_server.py:56-58
    • backfill_helpers.py:79-84
    • backfill_memories.py:339-345
    • transcript_rollout.py:1-14
  • The Codex P2 comment on 238a405, that the intake dedup drops the second rollout, is addressed in the fixup 0db1f65.
  • check_doc_claims.py does not scan docs/audits/ or CHANGELOG.md, and check_craftsmanship.py only checks Python, so neither gate can fail on this PR.
  • The test-coverage claims hold:
    • no test covers a session over two rollout files or a rewritten prefix;
    • no import_sessions idempotency test;
    • no compaction replay test.

Notes, no action before merge

  • capture_client.py:39 points at ) -> None:. The "never replayed" docstring is at :40; cite :37-42.
  • P2 spool: a failed or timed-out store is retired as *.rejected and never retried (capture_drain.py:41-45,64-71). "At-least-once" holds only for a crash during the store.
  • P2, P4 and P5 cite whole files with no line numbers, which falls short of the doc's "every claim cites the line read".

Verdict: approve

@cdeust
cdeust merged commit 2d6082d into main Nov 5, 2026
18 checks passed
@cdeust
cdeust deleted the fix/716-rollout-capture branch November 5, 2026 21:04
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.

2 participants