[P3] markers-checklist: follow-up T1-stage-2 - Versification NetworkObject → projectInterface on ParatextProjectDataProvider#2256
Closed
rolfheij-sil wants to merge 2 commits into
Conversation
… projectInterface Addresses the deeper-architectural part of TJ Couch's review on PR #2219: > these methods should actually go in a projectInterface and go in a PDP > instead of just being their own thing. Each one starts with projectId; > that's a pretty dead giveaway that the whole service should just be a > projectInterface Implementation: Add versification lookups directly to the existing ParatextProjectDataProvider (mirrors the GetMarkerNames pattern), exposed as a new 'platformScripture.Versification' projectInterface. Delete the standalone VersificationService NetworkObject entirely. C# changes: - ProjectInterfaces.cs: add VERSIFICATION = "platformScripture.Versification". - LocalParatextProjects.cs: register VERSIFICATION in the project interface list. - ParatextProjectDataProvider.cs: add LookupFinalVerseNumber, LookupFinalChapter, LookupFinalVerseNumbersInBook methods (sourced from the deleted service); register them in GetFunctions(). Methods read ScrText.Settings.Versification fresh on each call so the projectInterface is correct under runtime versification changes (T1 stage 1 docstring fix on the follow-up PR confirmed this is real). - Program.cs: drop the VersificationService instantiation and InitializeAsync call from the WhenAll bundle. - VersificationService.cs: deleted. TypeScript changes: - platform-scripture.d.ts: define IVersificationProjectDataProvider extending IProjectDataProvider, with auxiliary lookup methods (no get/set/subscribe). Register under ProjectDataProviderInterfaces. Remove IVersificationService. - checklist.web-view.tsx + platform-scripture-editor.web-view.tsx: swap papi.networkObjects.get<IVersificationService>(...) for useProjectDataProvider('platformScripture.Versification', projectId). Drop the redundant projectId argument from each method call. C# tests: - Rename VersificationServiceTests → ParatextProjectDataProviderVersificationTests. - Construct via DummyParatextProjectDataProvider (mirrors the existing ParatextProjectDataProviderCommentTests pattern). Drop the projectId arg from each method call. Drop the "unknown projectId" test — that's now an earlier PDP-resolution failure, not the responsibility of these methods. Why this approach (Option B from the design study): 1. No precedent for "TS PDPE wraps a NetworkObject" — every layering PDPE in the codebase (ScriptureFinder, ScriptureExtender, lexical reference) does pure PDP composition. A TS wrapper around the existing NetworkObject would be a novel pattern. 2. ParatextProjectDataProvider already mixes get/set/subscribe with auxiliary methods (createComment, canUserAssignThread, getMarkerNames) — versification lookups fit the same shape naturally. 3. ParatextProjectDataProvider is per-project; the projectId arg becomes redundant. The consumer API gets cleaner. Verification: - C# tests: 704 passing, 6 skipped (the 8 refactored versification tests pass + no regressions in the broader suite). - TypeScript: npm run typecheck clean, npm run lint clean (0 errors, pre-existing warnings unchanged). - Tests: 1612 passing TS tests; 5 pre-existing storybook FAIL files (storybook-cache export issue on ai/main, unrelated). - Runtime smoke test via PAPI on the live app: • Old object:platformScripture.versificationService.* methods no longer in the rpc.discover schema (NetworkObject gone). • Each Paratext project PDP now exposes lookupFinalChapter, lookupFinalVerseNumber, lookupFinalVerseNumbersInBook. • Live calls return correct data: lookupFinalChapter(GEN)=50, lookupFinalVerseNumber(GEN,1)=31, lookupFinalVerseNumbersInBook(PHM) =[0,25].
This was referenced May 11, 2026
- platform-scripture.d.ts: replace malformed `@example` block on `lookupFinalVerseNumbersInBook` (prettier-plugin-jsdoc had reflowed it into prose, capitalizing `const`→`Const` and collapsing statements) with a fenced ```typescript code block matching the convention used by `engine.beginFindJob` etc. in the same file. - checklist.web-view.tsx: rewrite two stale cross-file line-number references — the block-header comment cited `platform-scripture-editor.web-view.tsx:351-377` (now ~351-373) and a second comment cited line 374's `[chapterNum]` access pattern (line 374 is now the deps array; the access is at line 370). Both now refer to the block/expression by name so they don't drift again. Both edits are pure JSDoc/comment changes; no code paths are affected. Surfaced by /review-paratext on PR #2256. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced May 13, 2026
Contributor
Author
|
Closed inadvertently when the head branch was renamed to the canonical Replaced by #2263 — same commits, same diff, canonical branch name so automated status reports pick it up. |
This was referenced May 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Code Review Summary
Branch:
ai/feature/markers-checklist-versification-pdp-rolf-05-11-2026Base:
origin/ai/mainDate: 2026-05-12
Review model: Claude Opus 4.7
Files changed: 9
Overview
This is the T1 stage 2 follow-up to TJ Couch's review of merged PR #2219 (markers-checklist). It removes the
IVersificationServiceNetworkObject and re-exposes its three lookup methods (lookupFinalVerseNumber,lookupFinalChapter,lookupFinalVerseNumbersInBook) directly onParatextProjectDataProviderunder a new'platformScripture.Versification'projectInterface — Option B from the design study, mirroring the existingGetMarkerNamespattern. The redundantprojectIdargument is dropped from each method.In-tree consumers (
checklist.web-view.tsx,platform-scripture-editor.web-view.tsx) are migrated in the same commit. The standaloneVersificationService.csis deleted along with itsProgram.csinstantiation. Eight existing tests are ported fromVersificationServiceTests.csto a renamedParatextProjectDataProviderVersificationTests.csthat mirrors the siblingParatextProjectDataProviderCommentTestspattern. No user-visible UI changes.API Changes
extensions/src/platform-scripture/src/types/platform-scripture.d.ts:export type IVersificationService(and the implicit'platformScripture.versificationService'network-object wire surface).export type VersificationProjectInterfaceDataTypes = Record<string, never>(auxiliary-only projectInterface — first one in this module to use the empty-data-types pattern; rationale documented inline).export type IVersificationProjectDataProvider— extendsIProjectDataProvider<VersificationProjectInterfaceDataTypes>withlookupFinalVerseNumber(bookNum, chapterNum),lookupFinalChapter(bookNum),lookupFinalVerseNumbersInBook(bookNum). All three drop the previousprojectIdfirst-arg.'platformScripture.Versification': IVersificationProjectDataProviderto thepapi-shared-typesProjectDataProviderInterfacesmap.c-sharp/Projects/ProjectInterfaces.cs: addedVERSIFICATION = "platformScripture.Versification".c-sharp/Projects/LocalParatextProjects.cs: addedProjectInterfaces.VERSIFICATIONtos_paratextProjectInterfaces.c-sharp/Projects/ParatextProjectDataProvider.cs: registered three new RPC functions (lookupFinalVerseNumber,lookupFinalChapter,lookupFinalVerseNumbersInBook) inGetFunctions().c-sharp/Projects/VersificationService.cs: deleted. Theobject:platformScripture.versificationServicenetwork object is removed from the wire surface.c-sharp/Program.cs: dropped theVersificationServiceinstantiation andInitializeAsynccall.papi.d.ts,lib/platform-bible-react/,lib/platform-bible-utils/: unchanged.Findings
Critical — Must address before merge
Removal of(Author confirmed: this surface never escaped paranext-core — the markers-checklist work is Paratext-internal and the versification service was newly minted in [P3][backend+ui] markers-checklist: Backend + UI implementation (C# data provider, React web view, E2E tests) #2219 with no third-party adopters. Safe to remove in one PR.)IVersificationService/platformScripture.versificationServiceis a breaking change to a public extension API surface (shipped in merged PR [P3][backend+ui] markers-checklist: Backend + UI implementation (C# data provider, React web view, E2E tests) #2219). External extensions consuming it viapapi.networkObjects.get<IVersificationService>(...)would error on both runtime and compile.Important — Should address before merge
@exampleJSDoc onlookupFinalVerseNumbersInBook(extensions/src/platform-scripture/src/types/platform-scripture.d.ts:843-845) — prettier-plugin-jsdoc reflowed the example as prose:constwas capitalized toConst(invalid TypeScript), and three example statements were collapsed onto shared lines. (Fixed during review: replaced with a fenced```typescriptcode block matching the established pattern used elsewhere in this file, e.g.engine.beginFindJob. Prettier verified to not re-flow the new form.)Versification tests skip(Author opted for status quo after deeper investigation: addingRegisterDataProviderAsync()in setup, unlike the siblingParatextProjectDataProviderCommentTests.cswhich calls it at line 57. Compliance analyzer worried this would let a future drop of aretVal.Add(...)line inGetFunctions()silently break the wire surface while tests still pass.RegisterDataProviderAsync()symmetrically wouldn't actually catch the analyzer's regression — registration would still succeed if one tuple were removed; it just wouldn't register that function. The Comment tests have the same blind spot. The pattern that would catch the regression is the CAP-012ManageBooksServiceRegistrationTestsstyle — callRegisterDataProviderAsync(), then assertClient.RegisteredRequestTypescontains each expectedobject:{name}-data.{methodName}. For 3 dead-simple passthrough methods with end-to-end live-app smoke-test coverage in the PR description and 8 existing off-by-one tests, the defensive value didn't justify the new test fixture.)Minor — Consider
(Author decision: acceptable as-is; rationale is documented inline.)VersificationProjectInterfaceDataTypes = Record<string, never>is novel in this module — no other*ProjectInterfaceDataTypesdeclaration uses an empty record. JSDoc above explains the rationale.checklist.web-view.tsx— the block-header comment at line 434 said "Mirrorsplatform-scripture-editor.web-view.tsx:351-377" but the editor block now spans ~351-373. A second stale reference at line 462 pointed to "scripture-editor.web-view.tsx:374's[chapterNum]access pattern" but line 374 is now the deps array, not the[chapterNum]access (which is at line 370). (Fixed during review: rewrote both to refer to the block/expression by name rather than line number, so they don't drift again.)(Author decision: leave as-is. The gap is pre-existing — the previousIVersificationProjectDataProvider's JSDoc directs callers that cache results to subscribe to the'platformScripture.versification'project setting. Neither in-tree consumer (checklist.web-view.tsxorplatform-scripture-editor.web-view.tsx) does — both useusePromise(fetchLastVersesInCurrentBook, [versificationPdp, currentBookNum]), so the cached result only invalidates on book-change or PDP re-acquisition, not on a runtime versification-setting change.IVersificationServicehad no subscription mechanism at all, so this PR actually improves the situation by giving consumers a documented way to subscribe via the PDP. Real-world impact is low: both UIs only care about the current book's verse counts, so a book switch refreshes anyway. Subscribe wiring can be added if/when the niche "user changes versification mid-session without switching books" scenario surfaces.)Three additional stylistic observations were flagged by analyzers but did not require action and were not raised in the interview:
var scrText = LocalParatextProjects.GetParatextProject(ProjectDetails.Metadata.Id);boilerplate in the new C# methods — consistent with the established convention inParatextProjectDataProvider.cs(~21 occurrences across the class).forloop body without braces inLookupFinalVerseNumbersInBook— consistent with surrounding C# style.'platformScripture.Versification') and setting key ('platformScripture.versification') is a copy-paste footgun, but it follows the existing PascalCase-vs-camelCase convention.Template Propagation
Shared Regions Modified
None. (None of the changed files contain
#region shared withmarkers.)Extension Config Changes
None. (
git diff --name-onlyshows no changes to anypackage.json,tsconfig*.json,webpack.config.*,.eslintrc*,.erb/configs/, or.github/workflows/files.)Positive Observations
MarkerNamesPDP pattern referenced in the PURPOSE — sameIProjectDataProvider<…DataTypes> & { … }shape, sameGetFunctions()registration, sameProjectInterfaces.VERSIFICATIONconstant andLocalParatextProjects._interfacesadvertisement.IVersificationService,versificationService, orplatformScripture.versificationServiceanywhere in the workspace.VersificationService.csis matched cleanly inProgram.cs(both the construction andInitializeAsync()call are removed).#region Versification (platformScripture.Versification)block inParatextProjectDataProvider.csnames the projectInterface explicitly — making code-to-projectInterface mapping easy to find, and an improvement over the existing#region USFM/#region Commentsstyle.ParatextProjectDataProviderVersificationTests.csfollows the naming convention of the siblingParatextProjectDataProviderCommentTests.cs, uses[ExcludeFromCodeCoverage]correctly, and the class-level summary documents what is and isn't worth testing. Good coverage of the off-by-one boundary inLookupFinalVerseNumbersInBook(length, index 0, index 1, last index, exhaustive parallel comparison) plus a single-chapter Philemon edge case.lookupFinalVerseNumbersInBookdocuments the 1-based indexing contract that the old version under-documented ("Index 0 is a filler0; the returned array has lengthlastChapter + 1"), reducing off-by-one risk for new callers.'platformScripture.versification'setting for change notifications — preempting an obvious follow-up question. The setting key is verified to exist (c-sharp/Services/ProjectSettingsNames.cs,projectSettings.json).'platformScripture.Versification'(uppercase V) is the projectInterface name;'platformScripture.versification'(lowercase v) is the project setting — both kept distinct and used consistently.useProjectDataProvider('platformScripture.Versification', projectId)replacespapi.networkObjects.get<IVersificationService>(...), theversificationPdpguard replaces theprojectIdguard, anduseCallbackdeps now correctly trackversificationPdpinstead ofprojectId.papi.d.ts; the auto-generated PAPI surface is correctly left alone.logger.debugdiagnostics, correctly excluded from localization).Interview Notes
IVersificationServiceNetworkObject to a per-project-PDP'platformScripture.Versification'projectInterface (Option B from the design study), mirroring theGetMarkerNamespattern. Companion to [P3] markers-checklist: follow-up - TJ review #2254 (small follow-up) and [P3] markers-checklist: follow-up - Sebastian UX-2 review (9 work packages) #2258 (Sebastian's UX-2 review, stacked on [P3] markers-checklist: follow-up - TJ review #2254).ParatextProjectDataProvideralready mixes auxiliary methods likecreateComment,canUserAssignThread,getMarkerNamesso versification fits naturally; the PDP is per-project so theprojectIdarg becomes redundant.IVersificationServicesurface never escaped paranext-core. The markers-checklist work is in-development and the versification service was newly added in [P3][backend+ui] markers-checklist: Backend + UI implementation (C# data provider, React web view, E2E tests) #2219 with no third-party adopters. Removal in a single PR is safe.RegisterDataProviderAsync()symmetrically with Comment tests) wouldn't actually catch the regression it was worried about — registration would still succeed if one tuple were dropped fromGetFunctions(). The pattern that would catch it (CAP-012ManageBooksServiceRegistrationTests— assertClient.RegisteredRequestTypescontains each expected wire name) wasn't worth the new fixture for 3 dead-simple passthrough methods already covered by 8 off-by-one tests and the live-app smoke test documented in the PR description.IVersificationServicehad no subscription mechanism either, so this PR strictly improves the situation by enabling subscription); real-world impact requires the niche case of "user changes versification mid-session without switching books", which neither UI currently encounters in practice.In-Review Quality Check
Two in-review edits, both pure JSDoc/comment changes with zero code-path impact:
extensions/src/platform-scripture/src/types/platform-scripture.d.ts:843-852— replaced malformed@exampleblock with a fenced```typescriptcode block.extensions/src/platform-scripture/src/checklist.web-view.tsx:432-436and462-465— rewrote two stale cross-file line-number references to refer to the block/expression by name.Verification performed:
npx prettier --checkon both files — clean (confirmsprettier-plugin-jsdocdoes not re-flow the new fenced code block, which was the original failure mode of the malformed@example).npm install(a full install for a comment-only review would be disproportionate). Both edits are JSDoc/comment-only and cannot affect type checking, lint output beyond formatting, or test results. The risk is effectively zero, but flagging the gap for transparency — the author should runnpm run typecheck && npm run lint && npm testonce before pushing if they want absolute confirmation.Suggested Review Focus
Prioritized areas for the author-reviewer meeting:
VersificationProjectInterfaceDataTypes = Record<string, never>is the first auxiliary-only projectInterface inplatform-scripture.d.ts. Worth flagging to the reviewer in case the team wants to standardize on a different convention for future auxiliary-only PDPs (e.g. inlineIProjectDataProvider<Record<string, never>>vs. a named alias).'platformScripture.versification'. Neither in-tree consumer does. Author judged the gap is pre-existing and low-impact, but the reviewer may want to confirm whether to add the subscribe wiring now or accept the documented-but-deferred contract.retVal.Add(...)line inGetFunctions(). The author deferred this defensive coverage as not worth the fixture given the methods' simplicity. The reviewer may want to confirm or push back, and if push back, theCAP-012ManageBooksServiceRegistrationTestspattern is the recommended template.IVersificationServiceas a breaking public-API change. Author confirmed it never shipped externally — worth a quick second confirmation from the reviewer (or whoever has visibility into downstream extensions /paranext-extension-template) before merge.Summary
Second follow-up to TJ Couch's review on merged PR #2219 (markers-checklist). Companion to #2254 (small follow-up).
T1 stage 2 — converts the
IVersificationServiceNetworkObject to a per-project-PDP'platformScripture.Versification'projectInterface, directly addressing TJ's deeper architectural feedback:Approach
Implemented as Option B from the design study — versification methods live directly on
ParatextProjectDataProvider(mirrors theGetMarkerNamespattern), exposed as a new projectInterface. The standaloneVersificationServiceNetworkObject is removed entirely.Why Option B rather than a TS layering PDPE around the existing service:
ParatextProjectDataProvideralready mixes get/set/subscribe with auxiliary methods (createComment,canUserAssignThread,getMarkerNames) — versification lookups fit the same shape naturally.ParatextProjectDataProvideris per-project; theprojectIdargument becomes redundant. The consumer API gets cleaner.Changes
C# (backend)
ProjectInterfaces.cs— addVERSIFICATION = "platformScripture.Versification"LocalParatextProjects.cs— register VERSIFICATION ins_paratextProjectInterfacesParatextProjectDataProvider.cs— addLookupFinalVerseNumber,LookupFinalChapter,LookupFinalVerseNumbersInBookmethods (sourced from the deleted service); register inGetFunctions(). Methods readscrText.Settings.Versificationfresh on each call so the projectInterface stays correct under runtime versification changes.Program.cs— dropVersificationServiceinstantiation +InitializeAsynccall.VersificationService.cs— deleted.TypeScript (frontend / contracts)
platform-scripture.d.ts— defineIVersificationProjectDataProviderextendingIProjectDataProvider; register underProjectDataProviderInterfaces. RemoveIVersificationService.checklist.web-view.tsx+platform-scripture-editor.web-view.tsx— swappapi.networkObjects.get<IVersificationService>(…)foruseProjectDataProvider('platformScripture.Versification', projectId). Drop the redundantprojectIdargument from each method call.C# tests
VersificationServiceTests→ParatextProjectDataProviderVersificationTests. Construct viaDummyParatextProjectDataProvider(mirrorsParatextProjectDataProviderCommentTests). Drop theprojectIdarg from each method call. Drop the "unknown projectId" test — that's now a PDP-resolution failure earlier in the pipeline, not the responsibility of these methods.Verification
dotnet test: 704 passing, 6 skipped. 8 versification tests pass after the refactor; 0 regressions in the broader suite.npm run typecheck: clean across all workspaces.npm run lint: 0 errors (pre-existing warnings unchanged).npm test: 1612 passing; 5 pre-existing storybook FAIL files are unrelated (storybook-cache export issue, same onai/main).object:platformScripture.versificationService.*methods no longer appear inrpc.discover(NetworkObject correctly de-registered).lookupFinalChapter,lookupFinalVerseNumber,lookupFinalVerseNumbersInBookonobject:<projectId>-pdp-data.*.lookupFinalChapter(GEN) → 50,lookupFinalVerseNumber(GEN, 1) → 31,lookupFinalVerseNumbersInBook(PHM) → [0, 25].Relationship to #2254
#2254 (small follow-up — Group A) ships docs/type fixes for the remaining TJ-feedback items. These two PRs are independent and can merge in either order — they touch disjoint code paths, so no rebase conflict either way.
Test plan
🤖 Generated with Claude Code
This change is