Repository navigation
Route getDraft and saveDraft through an async repository (#431) - #466
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
There was a problem hiding this comment.
The inline comments in this review were generated by Claude and haven't been closely human-reviewed, so treat them as leads to check rather than conclusions.
Checked against main and found matching: the storage calls and their order, the shard journal, the model-version guard, and the per-source queues.
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
Left a little nit that is not super-super important
@alex-rawlings-yyc reviewed 16 files and all commit messages, made 2 comments, and resolved 8 discussions.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on imnasnainaec).
src/types/analysis-repository.ts line 25 at r2 (raw file):
* Loads the whole stored draft. * * @throws {SyntaxError} If the stored draft contains invalid JSON.
⛏️ Not all invalid JSON throws here. Invalid JSON in the envelope throws, but invalid JSON in a book's shard just loads that book as empty (parseAnalysisShard). This @throws makes it sound like either one throws. The implementation's wording, "the draft's stored value", is narrower and would fit here too.
imnasnainaec
left a comment
There was a problem hiding this comment.
@imnasnainaec reviewed all commit messages and resolved 1 discussion.
Reviewable status: 15 of 16 files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).
AnalysisRepository is the seam a later storage backend replaces: async calls taking and returning only JSON-plain values, with payload reads named per kind (getTokenAnalyses, getPhraseAnalyses, getSegmentAnalyses) and exportAll/replaceAll for callers that still exchange the whole draft. DraftRepository implements it in memory over today's draft envelope and per-book shards, keeping projectStorage's guards: only changed shards are rewritten, the shard journal recovers interrupted saves, and a draft written by a newer build is neither read nor overwritten. It reaches storage only through a KeyValueStorage and imports nothing from PAPI. getDraft and saveDraft keep their contracts and storage calls. The perf harness seeds each tier's draft and saved projects from Node, writing the app's storage files through the repository, so seeding no longer depends on saveDraft or saveAnalysis carrying a whole analysis. perf:shape reads stored drafts through it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The interface keeps only exportAll and replaceAll; per-kind reads are left to 3b, which settles the repository's naming. DraftRepository no longer holds records between calls, only the per-book record of what storage holds, so host memory matches main. The storage-boundary violation report moves to its own module, shared by the draft repository and project storage. A packaged perf run seeds each tier with the app stopped, inside the restart before its first open. A dev-core run seeds live, and every view close first waits for any autosave an edit or Save started, so no late save overwrites a seeded draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use load and save for draft operations throughout the repository, keeping read and write for single storage calls. Rename the shard record to shardContents and the logger type to WarningLogger, which serve more than the repository. Shorten the moved doc prose, fold the restart parameter note into its summary, and fix the perf README's difference count and AGENTS.md's description of the seam. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Document exportAll's throws on the seam, state KeyValueStorage's contract alone, and give read and delete the same doc form. Correct the claim that a dropped book never leaves a shard: one the load could not use is held. Split the newer-build test into its load and save refusals, and test isStringArray and reportAnalysisViolations directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A shard holding invalid JSON loads its book as empty rather than throwing, so the seam's @throws names only the draft's own record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e61f065 to
170aa7a
Compare
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
@alex-rawlings-yyc reviewed 3 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on imnasnainaec).
Part of #424; closes #431.
Summary
getDraftandsaveDraftnow go through an async repository. Its implementation imports nothing from PAPI, so Node runs it too. The perf harness uses that to seed its tiers without PAPI.getDraftandsaveDraftmake the same storage calls as before. The existing unit suite passes unedited.projectStoragedid.perf:shapereads stored drafts through the repository. It fails on a missing draft rather than measuring zeros.Evidence
projectStorage.test.tspasses unedited.projectStorage's PAPI mocks.saveDraft,createProjectandsaveAnalysisover PAPI.perf:app. Both need a running Platform.Bible. Playwright loads the perf spec.Deviations from the issue and its comment
From the issue
projectIdsindex directly.From the comment
exportAll(): DraftProjectandreplaceAll(draft).ChangeSet,ApplyResult,intent,capabilities, scope, and the naming that lookups and the catalog follow. 3a may defer parts further.applyand undo in 3b, lookups in 3c, the catalog andcountUsagesin 5a.pullRemoteChangesandclose. Nothing in the plan needs them yet.getScopefolded intoexportAll. Separate calls would mean either holding the draft between them or reading storage twice.ScopeRecord. The scope is the draft's own envelope. A type pairing a draft with its interlinear project is part of what 3a settles.null.Decisions with a strong alternative
Reviewer push-back is welcome.
AnalysisRepository<Scope>, ready for saved projects.projectStorageinto a Node-safe core now.src/types/src/services/, beside the implementation, with a coverage exclusion.src/types/by convention.Automated review
Devin's review raised two items. Given the rebuttals, Devin agreed that neither needs a change.
draftRepositorieswould keep a repository bound to an earlier activation's token.deactivatestays an option if a host ever keeps the module loaded.getDraftandsaveDraft. Measurements don't change, since every run seeds a draft before measuring. Telling absent from empty would need a delete outside the repository, or one the plan doesn't include.Comments on other issues
Merge Danger
Door: two-way
The stored format and storage calls are unchanged, so a revert restores main's behavior on the same data.
Blast Radius: drafts
Every draft load and autosave goes through the new code. The perf harness's seeding changes too.
🤖 Generated with Claude Code
This change is
Summary by CodeRabbit