Skip to content

feat(profiles): add session profile disk corroboration reader - #1922

Open
noxsystems wants to merge 4 commits into
Gentleman-Programming:mainfrom
noxsystems:feat/1064-3b-i-3-disk-reader
Open

noxsystems wants to merge 4 commits into
Gentleman-Programming:mainfrom
noxsystems:feat/1064-3b-i-3-disk-reader

Conversation

@noxsystems

@noxsystems noxsystems commented Oct 8, 2026 •

Copy link
Copy Markdown

Review size: this slice adds 609 changed lines on top of #1919: 171 module, 252 unit tests, 168 tests against a real SessionManager session file, 18 docs. GitHub's Files tab shows the cumulative diff with #1918/#1919 until they merge; review only commit 4d56f74b5. It is over the 400-line budget on purpose: the only cohesive cut (module + unit tests ≈ 440, SDK test ≈ 170) still leaves the first part over budget and separates the module from the evidence that it works on Pi's real JSONL. If you prefer that split anyway, it is a one-minute change.

Summary

Part of #1064, slice 3b-i (persistence). Supplies the corroboration that replaySessionProfileBranch (#1919) requires but cannot establish: whether the selected record on the active branch is actually on disk.

  • readSessionProfileDisk(source, options): stateless, synchronous. Takes the session id, session file path and public active branch; selects the newest profile-family entry on the branch, excluding caller-supplied knownFailedEntryIds; parses the JSONL file; admits the entry only when the disk record is identical (isDeepStrictEqual over a JSON snapshot, so getters and mutable references cannot leak in).
  • Result: the decoder result plus entryIndex and lineNumber, or indeterminate with one closed reason (missing-source, invalid-candidate-metadata, unreadable-file, source-changed, invalid-json, invalid-record, session-header-mismatch, duplicate-id, missing-header, selected-record-missing, selected-record-mismatch, unserializable-source). Reasons never carry record contents or exception messages.
  • Conservative by design: no writes, no fallback policy, no cache, no ancestry repair, no fsync. A missing or unreadable file never restores a profile found only in memory. Source identity is re-checked after the file read; any change is source-changed.
  • Still no consumer wiring: Enter, startup and routing do not change.

This is PR 3 of the chain.

Issue

Part of #1064

PR type

  • New feature (type:feature)

Changes

Commit Change
4d56f74b5 lib/session-profile-disk-reader.ts, tests/session-profile-disk-reader.test.ts, tests/session-profile-disk-reader-pi.test.ts, Disk corroboration section in docs/session-profile-format.md.

Test plan

Verified on top of #1919, main 9782d26df, Node 25.2.1:

  • tests/session-profile-disk-reader.test.ts: 29 pass, 0 fail (every indeterminate reason, failed-ID exclusion, source-changed detection, hostile getters, duplicate and header checks).
  • tests/session-profile-disk-reader-pi.test.ts: 4 pass, 0 fail, against a real SessionManager from @earendil-works/pi-coding-agent writing to a temp directory.
  • tests/session-profile-persistence.test.ts + agent-profiles + model-routing-authority: 77 pass.
  • node scripts/check-types.mjs: 186 recorded diagnostics, no regressions.
  • Native review (RDD): not run on this slice.

Review follow-ups (non-blocking)

  • The reader scans for the newest profile-family entry itself instead of calling replaySessionProfileBranch (feat(profiles): add session profile encoder and active-branch replay #1919), because it needs the raw branch index and the failed-ID exclusion before decoding. The "newest family entry is terminal" rule therefore lives in two places; happy to fold one into the other if you'd rather.

Chain Context

Field Value
Chain #1064 slice 3b-i: session profile persistence
Tracker PR Not needed
Position 3
Base main (fork PRs cannot stack bases; rebased as #1918/#1919 land)
Depends on #1919
Follow-up append controller, authority publication, Enter persistence wiring around #1824's selection path
Review budget 609 changed lines, of which 420 are tests and 18 docs.
main
 └─ #1918 decoder: record format, readSessionProfileEntry
   └─ #1919 encoder + replaySessionProfileBranch
     └─ PR 3 readSessionProfileDisk: on-disk corroboration        📍 this PR
       └─ (later) append controller, authority, Enter persistence wiring

Summary by CodeRabbit

  • New Features
    • Added support for creating, clearing, validating, and replaying session profile entries, including handling for unsupported or invalid entries.
    • Added a read-only check that compares the latest eligible profile entry on the active session branch with its disk record. Results distinguish absent, bound, cleared, and indeterminate states.
  • Documentation
    • Documented supported profile payloads, validation rules, replay behavior, and disk-check outcomes.

Part of Gentleman-Programming#1064 (slice 3b-i, codec). Standalone decoder for the
gentle-pi.session-profile/v1 custom entry: closed origin set, own-property
checks, one invalid route invalidates the whole snapshot, unknown fields
ignored, prototype keys kept as own data. No Pi API, disk access, Enter,
startup or routing changes.

Chain: main -> [this] decoder -> encoder + active-branch replay (next).
Out of scope: encoder, replay, disk-reader corroboration, Enter wiring.
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: afef5e6d-201a-4f95-8ff6-48ced4930652
📥 Commits

Reviewing files that changed from the base of the PR and between 9782d26 and f08be2b.

📒 Files selected for processing (6)
  • docs/session-profile-format.md
  • lib/session-profile-disk-reader.ts
  • lib/session-profile-persistence.ts
  • tests/session-profile-disk-reader-pi.test.ts
  • tests/session-profile-disk-reader.test.ts
  • tests/session-profile-persistence.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

Adds a v1 session-profile codec and branch replay helper. Adds a read-only disk reader that checks the selected profile entry against session JSONL records. Adds unit and integration tests and documents the payload, replay, and disk-reader contracts.

Changes

Session Profile Persistence and Disk Reader

Layer / File(s) Summary
Profile codec and branch replay
lib/session-profile-persistence.ts, tests/session-profile-persistence.test.ts
Adds v1 bind and clear payload constructors, validation and normalization, entry classification, and reverse-order replay that returns the newest non-absent profile-family result. Tests cover payloads, validation, defensive snapshots, and replay ordering.
Disk corroboration and source validation
lib/session-profile-disk-reader.ts, tests/session-profile-disk-reader*.test.ts, docs/session-profile-format.md
Adds a reader that matches the latest eligible branch entry to a session JSONL record, or returns absent or indeterminate. Tests cover selection, malformed or mismatched records, source changes, and persistence behavior. The documentation describes the payload, replay, and disk-reader contracts.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant SessionProfileSource
  participant readSessionProfileDisk
  participant SessionJSONL
  SessionProfileSource->>readSessionProfileDisk: Provide session ID, file path, and branch
  readSessionProfileDisk->>SessionJSONL: Read session records
  SessionJSONL-->>readSessionProfileDisk: Return JSONL contents
  readSessionProfileDisk->>SessionProfileSource: Recheck captured source state
Loading

Merge Risk: ⚪ Minimal · up to f08be

This change adds a read-only session profile disk corroboration reader with no consumer wiring, so production behavior is unchanged. No merge-blocking risk was identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.73% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 5 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the primary change: adding a session profile disk corroboration reader. It matches the main implementation and PR objective.
Full details: Docstring Coverage

Explanation

Docstring coverage is 22.73% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 5 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

…dicate

Export isSafeAgentName from model-routing-authority and use it in the
session profile decoder instead of probing normalizeModelConfig. Assert
constructor and prototype keys stay own data in the hostile-keys test.
Addresses the two CodeRabbit comments on Gentleman-Programming#1918.
Part of Gentleman-Programming#1064 (slice 3b-i, codec). Adds createSessionProfileBind and
createSessionProfileClear (explicit user selections only, typed undefined
model/thinking omitted, effort stays strict) and replaySessionProfileBranch:
the newest profile-family entry on a caller-supplied, already disk-corroborated
active branch is terminal, including invalid and unsupported, and never revives
an older binding. Still no disk access, Pi API, Enter or routing changes.

Chain: main -> decoder (previous) -> [this] encoder + replay.
Depends on: feat/1064-3b-i-1-codec-decoder.
Out of scope: disk-reader corroboration, Enter wiring, guards.
Part of Gentleman-Programming#1064 (slice 3b-i, disk reader). readSessionProfileDisk reads the
session's public active branch and JSONL file, selects the newest
profile-family entry (excluding known failed append IDs) and admits it only
when the record on disk is byte-identical; otherwise it returns one
indeterminate reason without record contents. No writes, fallback, cache,
ancestry repair or fsync; a missing file never restores a memory-only
profile. Verified against a real SessionManager session file.

Chain: main -> decoder (Gentleman-Programming#1918) -> encoder + replay (Gentleman-Programming#1919) -> [this].
Depends on: Gentleman-Programming#1919.
Out of scope: append controller, authority publication, Enter wiring.
@noxsystems
noxsystems force-pushed the feat/1064-3b-i-3-disk-reader branch from f08be2b to 4d56f74 Compare October 8, 2026 04:50

This branch has not been deployed

No deployments
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