Archive read path: tail reads, offset paging, and a readable mirror #54

Merged
mprihoda merged 15 commits from archive-read-path into main 2026-07-16 05:14:30 +00:00
mprihoda commented 2026-07-15 20:59:42 +00:00 (Migrated from github.com)

Acts on the consumer's session-history gap report (Gaps 1+2 of docs/design/session-history-feedback-response.md, included here together with the resume-identity probe under docs/design/probes/).

What's here

  • Mirror preserves the vendor projects layoutarchiveDir/<encoded-cwd>/<sid>.jsonl + subagent tree (was flat; unreleased, so no migration).
  • Vendor→mirror read fallback on every read surface (forSession/entries/subagentEntries/tail reads): a cleanupPeriodDays-pruned session stays readable through the same API. SessionRecord.root: RecordRoot exposes provenance (Vendor | Archive).
  • Custody is one-directional: mirror with the vendor tree absent is a no-op that never touches the archive (tested byte-identical), SessionNotFound only when neither root has the session.
  • Tail reads + offset paging: lastEntries(sessionId, limit) and entriesBefore(token, limit) returning EntryPage — backward block reads from EOF (pure BackwardLineReader in core), opaque PageToken carrying the resolved source + byte offset. Tokens survive file growth (append-only region reads); a token minted against a source that has since changed resolution fails with typed PageSourceMoved instead of silently reading a different file at the same offset. Torn final line (live CLI append) is excluded by rule.

Review cycle

Four-dimension review + adversarial verification: 4 confirmed findings, all fixed — three doc/PURPOSE precision items and one real correctness bug caught by review: os.read.bytes can short-read mid-file, corrupting backward-scan offset math; fixed with a pure ByteRangeReader.readFully loop, TDD.

Verification

__.fix --check, __.compile (zero warnings), __.test 526/526, __.itest 730/730 — including the real-CLI archive E2E (now also tail-reading the transcript the CLI wrote) and the new prune-simulation integration flow.

🤖 Generated with Claude Code

Acts on the consumer's session-history gap report (Gaps 1+2 of `docs/design/session-history-feedback-response.md`, included here together with the resume-identity probe under `docs/design/probes/`). ## What's here - **Mirror preserves the vendor projects layout** — `archiveDir/<encoded-cwd>/<sid>.jsonl` + subagent tree (was flat; unreleased, so no migration). - **Vendor→mirror read fallback** on every read surface (`forSession`/`entries`/`subagentEntries`/tail reads): a `cleanupPeriodDays`-pruned session stays readable through the same API. `SessionRecord.root: RecordRoot` exposes provenance (Vendor | Archive). - **Custody is one-directional**: `mirror` with the vendor tree absent is a no-op that never touches the archive (tested byte-identical), `SessionNotFound` only when neither root has the session. - **Tail reads + offset paging**: `lastEntries(sessionId, limit)` and `entriesBefore(token, limit)` returning `EntryPage` — backward block reads from EOF (pure `BackwardLineReader` in core), opaque `PageToken` carrying the resolved source + byte offset. Tokens survive file growth (append-only region reads); a token minted against a source that has since changed resolution fails with typed `PageSourceMoved` instead of silently reading a different file at the same offset. Torn final line (live CLI append) is excluded by rule. ## Review cycle Four-dimension review + adversarial verification: 4 confirmed findings, all fixed — three doc/PURPOSE precision items and one real correctness bug caught by review: `os.read.bytes` can short-read mid-file, corrupting backward-scan offset math; fixed with a pure `ByteRangeReader.readFully` loop, TDD. ## Verification `__.fix --check`, `__.compile` (zero warnings), `__.test` 526/526, `__.itest` 730/730 — including the real-CLI archive E2E (now also tail-reading the transcript the CLI wrote) and the new prune-simulation integration flow. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
mprihoda commented 2026-07-15 22:39:35 +00:00 (Migrated from github.com)

Code review gate (iterative-works review-code): PASSED after fixes

Nine specialized reviewers over the diff: 1 critical, 14 warnings, ~10 suggestions → critical + all warnings + cheap suggestions fixed (9 commits); deferrals recorded. Full report + resolution: project-management/reviews/review-pr54-2026-07-15.md.

Highlights:

  • Contract precision (the critical): the port now states one-directional custody on mirror itself — Archive-root resolution is a documented no-op, never a truncation.
  • Race/robustness: vanished-file reads re-resolve once before failing typed; mirror listing tolerates files pruned mid-run; presence classification distinguishes "pruned" from "couldn't check" (an unreadable vendor tree fails typed instead of silently serving the mirror and no-opping custody).
  • Bounds: InvalidPageSize validation (max 10000), 32 MiB backward-scan budget with typed CorruptTranscript overflow, linear accumulation.
  • Type-enforced opacity: PageToken constructor is private; minting lives in the pure TranscriptPage.fromTail (core), reusable by future direct/effectful adapters.
  • Defense-in-depth: read path now refuses symlinks like the write path (incl. shared sidechain listing).
  • Structure/tests: ArchiveMirror extracted from the adapter; index throwaway-constructor coupling removed; ArchiveErrorTest added with sanitization regressions (control-char filter widened to close a C1 gap).

Final gates: scalafix, compile (zero warnings), __.test 526/526, __.itest 730/730 incl. the real-CLI archive E2E (tail-reading the transcript the CLI wrote). CI green.

🤖 Generated with Claude Code

## Code review gate (iterative-works review-code): PASSED after fixes Nine specialized reviewers over the diff: **1 critical, 14 warnings, ~10 suggestions** → critical + all warnings + cheap suggestions fixed (9 commits); deferrals recorded. Full report + resolution: `project-management/reviews/review-pr54-2026-07-15.md`. Highlights: - **Contract precision (the critical):** the port now states one-directional custody on `mirror` itself — Archive-root resolution is a documented no-op, never a truncation. - **Race/robustness:** vanished-file reads re-resolve once before failing typed; mirror listing tolerates files pruned mid-run; presence classification distinguishes "pruned" from "couldn't check" (an unreadable vendor tree fails typed instead of silently serving the mirror and no-opping custody). - **Bounds:** `InvalidPageSize` validation (max 10000), 32 MiB backward-scan budget with typed `CorruptTranscript` overflow, linear accumulation. - **Type-enforced opacity:** `PageToken` constructor is private; minting lives in the pure `TranscriptPage.fromTail` (core), reusable by future `direct`/`effectful` adapters. - **Defense-in-depth:** read path now refuses symlinks like the write path (incl. shared sidechain listing). - **Structure/tests:** `ArchiveMirror` extracted from the adapter; index throwaway-constructor coupling removed; `ArchiveErrorTest` added with sanitization regressions (control-char filter widened to close a C1 gap). Final gates: scalafix, compile (zero warnings), `__.test` 526/526, `__.itest` 730/730 incl. the real-CLI archive E2E (tail-reading the transcript the CLI wrote). CI green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
iterative-works/claude-code-query!54
No description provided.