docs(service-datasource): re-anchor the dead tracker citations to the commits that decided them - #20693
Conversation
… commits that decided them Every comment and docblock site under packages/services/service-datasource/src that cited a tracker number answering 404 now cites the commit in this repository's history that decided what the line describes, and says in its own words what that commit decided (ruling C+D, form C): 75 sites on 74 lines in 23 files, 16 numbers, 17 commits, plus 4 reflow lines. Comments only; every file keeps its line count, and no citation number is added. Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H Co-authored-by: Claude <noreply@anthropic.com>
The rewritten docblocks ship in dist (index.d.ts / index.d.cts, and the runtime bundles for the ones tsup keeps), so the released package changes bytes and owes a patch changeset. Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check8 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 1 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin df43dd03b7714d4619b3a808246369755c4ef92c && git checkout df43dd03b7714d4619b3a808246369755c4ef92c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 14f80e23957165f6fb23c2b3d59bdc7668652dfb 265dc6861ea8235e3fe5962fd814276c391a6ad2 && git checkout -B drift-repro 14f80e23957165f6fb23c2b3d59bdc7668652dfb && git merge --no-ff 265dc6861ea8235e3fe5962fd814276c391a6ad2
node scripts/docs-audit/affected-docs.mjs --json 14f80e23957165f6fb23c2b3d59bdc7668652dfb |
Part of #20596
Clause-②: no
What changed
This is the fifth stage of the
domain:serviceslane of the dead-citation sweep. It coverspackages/services/service-datasource/src/**and nothing else. By the seat's fresh census at the claim (5894843429), it is the largest package in the lane that no in-flight work holds. Later stages cover the other packages, so this PR saysPart ofand the card stays open.Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on #19123), by the method of stages 1 to 4 (PR #20609 as
422db788a, PR #20626 asb80ab579d, PR #20634 as4d04b6be3, PR #20658 as9a4b2bb38). That is 75 sites on 74 lines in 23 files, covering 16 numbers:Each rewritten line now cites the commit in
origin/mainhistory that decided what the line describes, and says in its own words what was decided: 17 distinct shas.#8696was one card fixed in two halves, so its lines cite the half they describe: the mysql DSN branch (72050cc47) or the mongodb DSN branch (90a12fb18).PR #8588was itself a pull request, and it now cites its squash commit3dede582b. No number in this package has an ADR or ruling record of its own in the repository (a grep ofdocs/adr/for all 16 finds none), so every anchor is a commit, per ruling C's order. No number was dropped.Only comments changed. Every touched source file keeps its line count (78 lines out, 78 in, over 23 files), so no line citation into these files moves. 4 of those 78 lines hold no dead citation; they are reflow, listed under Wordings below. No code token moves (see the guard below).
No citation number is added. Every tracker number on an added line was already on the line it replaces: the only one is
#12482, which resolves and stood ondatasource-connection-service.ts:101before. Over the whole diff, added minus removed is 0 or negative for every number, and no number is new to the diff. No PR number stands on an added line.Thirteen dead sites are left on purpose, all of them test titles (see the list below).
One more file: a
patchchangeset for@objectstack/service-datasource, because the rewritten docblocks ship (see Changeset below).Census:
service-datasource, before and afterInstrument (A1). The gate's own
node scripts/check-issue-citations.mjs --census --json, read-only and unchanged. The count below is itsallocated-but-absentfindings underpackages/services/service-datasource/. Each run counts as a reading only because its board frontier equals the newest issue number, read by a separate request just before and just after the run.allocated-but-absent6981abfd2, run 2026-09-29T17:02:34Z to 17:06:27Zf5ec6bacd, run 17:18:37Z to 17:22:33ZThe before count matches the seat's census at the claim (44 sites in 9 files, at
6bff748b). The whole-repo drop is 44, exactly this diff's census sites. Theresolvestally is 32,909 in both runs, andresolves-as-pull-request(1,984) andcross-repo-unjudged(994) did not move either. The after run was taken onf5ec6bacd; the head265dc6861adds only the changeset. No run was truncated or discarded: all four enumerations in this stage (two census runs and the two supplementary boards below) read 186 pages at the newest frontier.Supplementary instrument, the whole scope. The census does not read test files or strings, and this stage's scope includes test comments. So a second reading runs the gate's own exported
extractCitations(whole-file and comment-prose projections) andclassifyCitationover every.tsfile underservice-datasource/src(61 files). It uses one board for both trees, enumerated by the gate's ownenumerateBoardat 17:22:42Z (186 pages, frontier #20686, equal to the newest).6981abfd2f5ec6bacdIts src-comment column equals the census's 44, which is the control on the second instrument. The 646 resolving and 57 pull-request citations are the same in both readings, and the drop of 75 citations is exactly the rewritten sites. An earlier board (17:07:08Z, frontier #20685) gave the same base reading. A third, raw reading (every
#followed by digits, judged against the same board, whatever surrounds it) finds 88 dead occurrences before and 13 after, and its residue equals the gate's residue site for site.Per-number table
Sites and files count every dead occurrence in scope at the base (comments and strings, tests included).
rewritten / leftcounts the sites rewritten and the sites left. Each anchor was read in its message and diff, not only its subject.#626868f5eccb1: the libSQL/Turso host loader gets one owner (@objectstack/runtime), andMissingDriverPackageErrorbecomes one class across both hosts, becauseserve.tsdecides fatality withinstanceof. The cli and runtime stages' anchor#6345e2798fab7: one driver vocabulary;mongorenamed tomongodb,tursomade a full builtin with a contract, and this factory's dispatch made exhaustive. The spec stages' anchor#85883dede582b:external.credentialsRef(and only it) allowed onschemaMode: 'managed';#8588was that pull request, and this is its squash commit#869672050cc47, a boundcredentialsRefreaches the mysql client on the DSN branch as{ uri, password }(5 sites);90a12fb18, the mongodb DSN branch carries it inoptions.authbeside an unmodified url (5 sites). The spec stage's anchor for the mongo half#8873096106522: a boundcredentialsRefreaches the postgres SERVER on the DSN branch;connectionStringis dropped andpggets its own parse of the url with the credential attached. The spec stage's anchor#8874d70428ae7: a declaredsslreaches the mysql client on both branches, in the spellingmysql2accepts ({}, nevertrue). The spec stage's anchor#8876d634e665b:urlUserinfoUsernameexported, the username half of the shared URL userinfo grammar. The spec stage's anchor#904024206416a: a credential in the mongo options passthrough (config.options.auth.password) is refused at publish. The spec stage's anchor#9041d491625c1: a boundcredentialsRefwith a user-less mongoconfig.urlis refused at the one door that sees both halves. The spec stage's anchor#10537e634ecf6a:POST /external/validatescoped to the URL's datasource; it addsvalidateDatasource. The rest and runtime stages' anchor#1096229d067646: one live introspection per datasource per validation sweep, memoised per call and never per instance (its message names#10962)#11166735f5c709: an unreachable remote is the newunreachablediff kind, notmissing_table. The runtime stage's anchor#1201077b91bdb4:ConnectionEngineLikederived from the engine contract, andregisterDriverstops promising it accepts any value. The runtime stage's anchor#122488425c17cc: the ruled engine members adopted ontoIDataEngine, the datasource-lifecycle trio among them. The spec stage's anchor#12943090f2302e: the guarded optional-driver loads declared as optional peers of this package. The cli and runtime stages' anchor#132796a180e42d: a failed permission-store read raisesAuthzStoreUnavailableError(503) instead of reading as zero grants; its message carries the 2026-08-30 ruling, and it moveddriver-error-classification.tsinto@objectstack/types. The anchor of stage 2 and of the rest, runtime and types stagesEvery cited sha matches exactly one commit (
git rev-parse --disambiguate, count 1 for each of the 17), and every one is an ancestor of the base (merge-base --is-ancestor, exit 0 for all 17; the history is complete,--is-shallow-repositoryfalse, 15,110 commits). Where an earlier stage already anchored a number, this stage reuses that anchor after checking it against this package's lines. New to the sweep here:72050cc47(the mysql half of#8696),3dede582band29d067646.Wordings to check
#8696's two halves. The mysql arm's lines (default-datasource-driver-factory.ts:718,:824, andbound-secret-dsn-branches.test.ts:4,mysql-dsn-ssl.test.ts:189,:263) cite72050cc47; the mongo arm's lines (default-datasource-driver-factory.ts:926,:954,:1243,datasource-credential-migration.ts:182, and the headingbound-secret-dsn-branches.test.ts:72, 「the mongodb half, added second」) cite90a12fb18.datasource-connection-service.ts:95-96. 「the inventory that filed that card」 lost its referent with the number, so it now says 「the inventory that filed its card」, the card behind77b91bdb4(1 reflow line).datasource-connection-service.ts:100-101. 「IDataEngine contract adoption ruled by #11833: declare resolveEffectiveDatasource + getDriverForObject (optional members), and give getObject a real return contract #12248 adjudicated all three onto IDataEngine」 became 「Commit 8425c17 adopted all three onto IDataEngine per the ruling」: the ruling decided and the commit carried it out, as its changeset says (1 reflow line).default-datasource-driver-factory.ts:412andmysql-dsn-ssl.test.ts:40. 「the one A declaredsslblock is silently dropped on the mysql arm's DSN branch (postgres honours it there) #8874 describes as honouring」 became 「the one commit d70428a's card describes as honouring」, since the words quote the card, not the commit.default-datasource-driver-factory.ts:736. 「the falsy-value note under A declaredsslblock is silently dropped on the mysql arm's DSN branch (postgres honours it there) #8874 below」 points at the heading at:767, which now carriescommit d70428ae7, so the pointer names the same anchor.postgres-dsn-bound-secret.test.ts:223. 「the authoring door (Nothing refuses the contradictory pair "external.credentialsRefbound + aconfig.urlnaming no user" — the binding is a silent no-op at connect #9041), which this card lands before」 became 「(commit d491625), which landed after this pin」.096106522(this file's commit) is an ancestor ofd491625c1, both on 2026-08-16.external-datasource-service.test.ts:444. 「The card's measured defect」 became 「Its card's measured defect」, the card behind735f5c709;:588「the pre-POST /datasources/:name/external/validate introspects every federated datasource, not only :name — the route filters validateAll() output after the work is done #10537 route」 became 「the route … before commit e634ecf」.datasource-admin-service.test.ts:674. 「Before PR feat(spec): allow external.credentialsRef (and only it) on schemaMode 'managed' #8588」 became 「Before commit 3dede58」, the squash commit of that pull request, which answers 404.datasource-connection-service.ts:96,:101,default-datasource-driver-factory.ts:825,:826.The 13 sites left
describe/ittitles, which are string tokens, left as stages 1 to 4 left theirs:admin-routes-authz-outage-envelope.test.ts:158(#13279);admin-routes-tenancy-posture-admission.test.ts:557(#13279);bound-secret-dsn-branches.test.ts:136,:244(#8696);connection-engine-like-contract.test.ts:21(#12010);datasource-config-redaction.test.ts:406(#9040);datasource-credential-migration.test.ts:226(#9040);external-datasource-service.test.ts:453(#11166),:690(#10962);mysql-dsn-ssl.test.ts:165,:324(#8874),:260(#8696);postgres-dsn-bound-secret.test.ts:160(#8873).Mechanical guard: no code token moves
The guard compares the TypeScript parser's leaf nodes, with comments as trivia and JSDoc nodes never visited, base
6981abfd2against head. Template literals are therefore read in context. It ran over all 23 touched.tsfiles.default-datasource-driver-factory.ts(Lazy + caught exactly liketoLazy and caught exactly like): 0 files changed, as expected (exit 0).default-datasource-driver-factory.ts(const url = resolveTursoUrl(spec);given a trailing?? undefined): DIFFER (exit 1).mysql-dsn-ssl.test.ts:165): DIFFER (exit 1).Every mutation went through
scripts/ablation-replace.mjs, and each landed (anchor 1 to 0, blob changed). Each restore was proven byte-identical to the HEAD blob (8c164aa6178f,2feeaeb0411d), withgit diff HEADempty and a clean tree afterwards. A first draft of the guard used the bare scanner, which loses template context and reported token changes inside comments; it was replaced by the parser walk before any reading was taken from it.Changeset
This change ships bytes, so a
patchchangeset for@objectstack/service-datasource(.changeset/20596-service-datasource-provenance-anchors.md) is included. It says only that the provenance comments were re-anchored, in stages 3 and 4's words.Measured on the built package (A3):
files[]isdist,README.mdandCHANGELOG.md. After the build, the rewritten comments reachdist:6a180e42d,e2798fab7ande634ecf6aonce, and29d067646three times, in each ofdist/index.d.ts,index.d.cts,index.jsandindex.cjs;68f5eccb14 times,090f2302etwice, and77b91bdb4and8425c17cconce each, in both declaration files. Positive control: the unchanged line 「registerDatasourceDef,markDatasourceUnavailable,」 beside the shipped rewrite atdatasource-connection-service.ts:95is found once inindex.d.ts. A never-written negative phrase appears nowhere indist. No dead number of the 16 is left anywhere indist.Gates (head
265dc6861)pnpm check:issue-citations(self-test) exits 0.node scripts/check-issue-citations.mjsexits 0: the diff-scoped run judged 1 citation (#12482), and it resolves.pnpm check:doc-authoringexits 0, with the sibling-package prose ids at their baseline and no growth.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat265dc6861derived 63 commands: all 54 derived at dispatch, pluscheck:duration-unit-keys,check:dispatcher-error-vocabulary,check:engine-double-contract,check:logger-receiver-detach,check:objectql-double-limit,check:query-options-erasure,check:type-check-coverage,check:type-check-debtandcheck:where-matcher. Each ran with its exit code captured before any pipe, and all 63 exit 0.--ran, fed each command with its exit code, reports 63 run, 0 NOT MEASURED (a derived zero), 0 unrun, and exits 0. A fullturbo run buildof./packages/*and./packages/*/*ran first under the shared verify lock (71 of 71 tasks, exit 0), so no gate hit an unbuilt workspace.node scripts/check-changeset-fixed.mjs,pnpm check:authz-resolver,pnpm check:error-code-casingandpnpm check:filter-alias-parity, each exit 0.pnpm --filter @objectstack/service-datasource test: 34 files pass and 693 tests pass. That is every test file in the package, the 14 touched ones included.pnpm --filter @objectstack/service-datasource typecheckexits 0. Itstsconfig.jsonincludes all ofsrc, and--listFilesshows all 61 files undersrc/, the 34 test files included, and all 23 touched files in the program.eslint --no-inline-config --format jsonover the 23 touched.tsfiles gives 23 files, 0 errors and 0 warnings. All 23 are in eslint's own population (isPathIgnoredis false for each).eslint.config.mjsnever enables type-aware linting (noparserOptions.project, as its own lines 327-328 state), so a comment edit here cannot move the verdict on any untouched file. The repo-widepnpm lintis CI's run.pnpm check:nul-bytesexits 0, and a raw scan of the 24 changed files for control bytes finds none.Acceptance notes
CITATION_RErefuses a hyphen after the digits and a/before the#(check-issue-citations closeout (extractor spellings):CITATION_RErefuses a hyphen after the digits, so a dead#N-wordcitation (#13398-class) is invisible to the diff gate and to the census #20636). In this package there is no#N-wordspelling at all. There are 7#A/#Blines (admin-routes.ts:28,datasource-route-ledger.ts:159,turso-driver-config.ts:132,external-introspection-seam.test.ts:14,:102,:163,turso-bound-secret-authoring.test.ts:8), and every second number on them is live:#10998,#4251and#4249are issues, and#8078,#4176and#4202are pull requests. So nothing there needed rewriting. The raw scan above, which sees both spellings, agrees.#13279→6a180e42d;#12010→77b91bdb4;#6345→e2798fab7;#6268→68f5eccb1;#12943→090f2302e;#8696→72050cc47(mysql) or90a12fb18(mongodb);#8873→096106522;#8874→d70428ae7;#10962→29d067646.origin/main(14f80e239, read at 17:27Z). None touchesservice-datasource,scripts/or.changeset/config.json, so there was no merge.Generated by Claude Code