From d7d34dbec20e0ae8b4f1cfce1c34a646079f06a2 Mon Sep 17 00:00:00 2001 From: Alex Rawlings Date: Thu, 22 Oct 2026 09:32:30 -0600 Subject: [PATCH 01/22] Add host sessions with read-only PT9 imports (#440) --- AGENTS.md | 8 +- __mocks__/papi-backend.ts | 5 + .../analysis-repository-conformance.ts | 88 ++++ src/__tests__/main.test.ts | 159 ++++++- .../services/analysisSessions.parity.test.ts | 45 ++ .../services/analysisSessions.test.ts | 434 ++++++++++++++++++ .../draftRepository.conformance.test.ts | 25 +- src/__tests__/services/projectStorage.test.ts | 129 ++++++ .../services/pt9ImportRepository.test.ts | 115 +++++ .../types/read-only-analysis-error.test.ts | 13 + src/__tests__/utils/free-translations.test.ts | 44 ++ src/components/InterlinearizerLoader.tsx | 10 +- src/main.ts | 127 +++++ src/services/analysisSessions.ts | 245 ++++++++++ src/services/draftRepository.ts | 3 + src/services/projectStorage.ts | 64 ++- src/services/pt9ImportRepository.ts | 88 ++++ src/types/analysis-repository.ts | 21 +- src/types/interlinearizer.d.ts | 30 ++ src/types/read-only-analysis-error.ts | 7 + src/utils/free-translations.ts | 7 + 21 files changed, 1643 insertions(+), 24 deletions(-) create mode 100644 src/__tests__/services/analysisSessions.parity.test.ts create mode 100644 src/__tests__/services/analysisSessions.test.ts create mode 100644 src/__tests__/services/pt9ImportRepository.test.ts create mode 100644 src/__tests__/types/read-only-analysis-error.test.ts create mode 100644 src/__tests__/utils/free-translations.test.ts create mode 100644 src/services/analysisSessions.ts create mode 100644 src/services/pt9ImportRepository.ts create mode 100644 src/types/read-only-analysis-error.ts create mode 100644 src/utils/free-translations.ts diff --git a/AGENTS.md b/AGENTS.md index fd1197177..12823d9a8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,12 +77,16 @@ The WebView root component is assigned to `globalThis.webViewComponent` (not exp [src/services/projectStorage.ts](src/services/projectStorage.ts) — owns all `papi.storage` reads and writes for interlinearizer projects. Two serialization queues prevent interleaved read-modify-write races. Tests must call `resetQueuesForTesting()` between tests because module state is not cleared by `resetMocks`. -Drafts are loaded and saved through [AnalysisRepository](src/types/analysis-repository.ts), the seam a later storage backend implements. [DraftRepository](src/services/draftRepository.ts) implements it over the draft envelope and its per-book shards, and rewrites only the books that changed. It imports nothing from PAPI and reaches storage only through a `KeyValueStorage`. That lets the perf harness run it in Node, straight over the storage files ([perf/storage.ts](perf/storage.ts)). +Drafts are loaded and saved through [AnalysisRepository](src/types/analysis-repository.ts), the seam a later storage backend implements. [DraftRepository](src/services/draftRepository.ts) implements it over the draft envelope and its per-book shards, and rewrites only the books that changed. It imports nothing from PAPI and reaches storage only through a `KeyValueStorage`. That lets the perf harness run it in Node, straight over the storage files ([perf/storage.ts](perf/storage.ts)). [Pt9ImportRepository](src/services/pt9ImportRepository.ts) serves a Paratext 9 import through the same seam, read-only. -[The conformance suite](src/__tests__/analysis-repository-conformance.ts) defines the seam: every `AnalysisRepository` implementation must pass it, and [draftRepository.conformance.test.ts](src/__tests__/services/draftRepository.conformance.test.ts) runs it against `DraftRepository`. A behavior every implementation owes goes in the suite; one particular to an implementation, such as which shards a save rewrites, goes in that implementation's own tests. A later backend runs the suite by passing `describeAnalysisRepositoryConformance` a factory that returns a fresh `ConformanceStore` for each test. +[The conformance suite](src/__tests__/analysis-repository-conformance.ts) defines the seam: every `AnalysisRepository` implementation must pass it, and [draftRepository.conformance.test.ts](src/__tests__/services/draftRepository.conformance.test.ts) runs it against `DraftRepository` and `Pt9ImportRepository`. A behavior every implementation owes goes in the suite; one particular to an implementation, such as which shards a save rewrites, goes in that implementation's own tests. A later backend runs the suite by passing `describeAnalysisRepositoryConformance` a factory that returns a fresh `ConformanceStore` for each test. Saved projects are listed through [ProjectSummaries](src/services/projectSummaries.ts): one record holding every project's summary, rewritten on each project write so listing reads no analysis. Like `DraftRepository`, it is PAPI-free. +### Sessions + +[AnalysisSessions](src/services/analysisSessions.ts) keeps the host's sessions, behind the `openSession`, `closeSession` and `setAnalysisLanguage` commands. A session is a handle on one source project's draft, paired with the interlinear project it saves to, or on a Paratext 9 import alone, read-only. A source has at most one session: opening another closes it. Each session runs its commands one at a time, through `run`, or `runEdit` for a command that changes stored analysis, which a read-only session refuses. The WebView doesn't use sessions yet. + ### Components Prefer Platform.Bible's `platform-bible-react` components (`Button`, `Input`, `Textarea`, `Label`, `Switch`, `RadioGroup`, `Popover`, `Tooltip`, etc.) over hand-rolled raw HTML (`