Repository navigation
packages/drivers/driver-sql/README.md documents DriverSQL.configure() three times — the class is not exported and the static does not exist #9867
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentationand removed
on Aug 19, 2026 Claimed by the
domain:devxPM seat — dispatching to anos-devsubagent now.- Session ID:
session_01XqDQYVU5smx29ts9pAErja - Branch:
claude/issue-9867-driversql-configure - Container & model: S, mode:subagent, model: opus (SKILL default tier; neither mandatory clause applies — no
.claude/skills/pm-dispatch/**edit, and nothing here changes a contract's accept/reject behaviour or widens public surface.⚠️ note Decide: does mandatory-fable clause ② cover packages/lint authoring rules that newly reject clean metadata? (PR #9890 held) #9894 is an open decision on clause ②'s boundary; it does not reach this card.)
State:
pm:queue→pm:dispatched, assignedos-steve.
Generated by Claude Code
- Session ID:
- added a commit that references this issue
on Aug 19, 2026 { "issue": 9867, "status": "done", "branch": "claude/issue-9867-driversql-configure", "pr": "https://github.com/objectstack-ai/objectstack/pull/9906", "premise_still_valid": true, "summary": "The card reproduces exactly: 0 occurrences of `DriverSQL` in the built dist/index.d.ts, both `configure` hits prose in doc comments. Ruled correctly as not-a-substitution, and the sweep found why: the surrounding shape was fabricated too. H1's working form is `plugins: [new DriverPlugin(new SqlDriver({...}))]` (DriverPlugin from @objectstack/runtime) — `defineStack({ driver: ... })` is not a key of ObjectStackDefinitionSchema, which is `.strict()` since #8687, so all six `driver:` call sites THROW at load rather than being ignored. Nine further defect classes fixed on the same page (see H2 table). All 19 TS fences on the rewritten page are script-extracted verbatim and compile against the built .d.ts; both defineStack shapes are additionally executed. Patch changeset included (README.md ships in the npm tarball), same shape as the sibling mcp-readme-shipped-surface.md. Draft PR, auto-merge NOT enabled, still draft.", "tests": "All at HEAD 511ad56cee, after the final commit, on a fully built tree (pnpm build 71/71 tasks). NEGATIVE probes (old forms, tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --strict --types node, hosted under packages/cli so pnpm resolves the workspace): n1 `TS2353 ... 'driver' does not exist in type 'ObjectStackDefinitionInput''; n5 `TS7053` on configs[env] + `TS2304 Cannot find name 'DriverSQL''; n8 `TS2554 Expected 2-3 arguments, but got 1` (find) and `TS2339` on transaction/raw/checkConnection/destroy; n9 `TS2724 ... has no exported member named 'SQLDriverConfig'. Did you mean 'SqlDriverConfig'?'; n10 `TS2339 Property 'getDriver' does not exist on type 'ObjectKernel''; n11 `TS2353 ... 'strategy' does not exist in type '{ enabled: boolean; tenantField?: string; organizationField?: string }''; n12 `TS2353 ... 'filters' does not exist in type 'DriverQuery''. POSITIVE: 19/19 fences PASS, ANY_FAIL=0, re-extracted from the committed file by script rather than transcribed. RUNTIME probe against the built @objectstack/spec: `driver` key THREW 'Unrecognized key(s) on this stack definition: `driver`', tenancy.strategy THREW 'Unrecognized key(s) on `tenancy`: `strategy` ... removed from @objectstack/spec after v15.0 (#2763)', both NEW shapes accepted with NO ERROR. GATES: check:published-readme-exports PASS (60 published docs, 212 imports, 49 type entries, baseline still `entries: []`, 0 findings are call sites); check:published-readme-links PASS (152 links); check:nul-bytes PASS; check:doc-authoring PASS; check:slot-lookup PASS; check:test-source-alias PASS; check:type-source-resolution PASS; check-affected-docs PASS. PACKAGE: `pnpm --filter @objectstack/driver-sql typecheck` PASS (script name echoed, not a zero-match); `pnpm --filter @objectstack/driver-sql test` PASS — 101 files passed / 5 skipped, 1761 tests passed / 62 skipped. The three path-derived gates come from `node scripts/pm/dispatch-gates.mjs packages/drivers/driver-sql/README.md`; the two README-specific gates were added by hand because that script's own residue note explains a gate whose population is a top-level `README.md` literal scores *silent* for every card. No ablation performed — nothing under packages/qa/dogfood is touched by a docs-only change.", "open_questions": [], "out_of_scope_findings": [ "filed as #9907: the `objectstack-platform` skill still teaches that an unknown top-level `defineStack` key is silently stripped, which #8687 changed to a throw (three sites in rules/bootstrap-patterns.md, one general statement in SKILL.md:189) — governed surface, untouched by this PR, filed unassigned with the `finding` label" ] }H1 — the working form, with compile evidence
plugins: [new DriverPlugin(new SqlDriver({ … }))].History checked before assuming, per the dispatch.
DriverSQL.configure()was never real: commit86d1d5ee1b(2026-05-07) calls it "the imaginary.configure(...)static factory" and repaired it in this same file — but only in the Basic Usage section. That is the source of the internal contradiction the card names: correctSqlDriverimport at line 43, fabricatedDriverSQLat 448/482/516. No commit ever added aDriverSQLclass.But the form that repair produced is also wrong. It wrote
defineStack({ driver: new SqlDriver(...) }), anddriveris not a declared key. Corroborated three ways:skills/objectstack-platform/rules/bootstrap-patterns.md("There is nodriver:key ondefineStack()… Drivers are plugins"); the already-merged #9544 changeset, which recorded the same fact forpackages/mcp; and real call sites (examples/app-todo/test/*.tsusekernel.use(new DriverPlugin(...)), while example apps that need no custom options setOS_DATABASE_URLand letos devbuild the driver). Both routes are on the rewritten page.H2 — full-page audit
Every claim checked is tabulated in the PR body, OK verdicts included. OK: the line-43 import, line-137
IDataDriversubpath,getKnex(),options.bypassTenantAudit/OS_TENANT_AUDIT=0, the tenant-scope matrix,engine.execute(sql), both sibling-driver links, and theKnex.Configoption names. Wrong:DriverSQL.configure()×3 (the card's finding),defineStack({ driver: … })×6,driver.raw()×6 (it isexecute()),checkConnection()×2 (it ischeckHealth(), which resolvesfalserather than throwing — so the try/catch was wrong in shape too),destroy()(it isdisconnect()),transaction(cb)+trx.insert({ object, data })(real seam isbeginTransaction()+options.transaction+commit()/rollback()),kernel.getDriver()×3 (no such member; the engine'sgetDriveris private), the query AST in three places (object name is argument one; filter key iswherewith the ObjectQL dialect; sorting isorderBy: [{ field, order }]—sort/directionis the retired aliasSortNodeSchemaitself names),interface SQLDriverConfig(the export isSqlDriverConfig, and all four ObjectStack keys were undocumented),tenancy.strategy,configs[env], top-levelssl, theobjectstack_*table names ×12, the knex-CLI migration workflow, the inverted "never raw DDL" best practice, the knex index migration, and a dead@vercel/postgresimport.H3 — runnability
Worse than a wrong method name, exactly the class the dispatch pointed at: two config blocks on this page could not load at all. Both
driver:andtenancy.strategythrow atdefineStack(), measured by execution, not inference. A third, quieter failure: every raw-SQL example queriedobjectstack_-prefixed tables, butStorageNameMapping.resolveTableNamemakes the physical table name the namespace-prefixed object name (crm_account,sys_user) — 12 occurrences naming tables that never exist. No undocumented env var is required by this page's own configs (unlike the mcp case): the driver is constructed with an explicit config, so the gap does not reproduce here.H4 — line 137 confirmed
import type { IDataDriver } from '@objectstack/spec/contracts'still resolves —./contractsis a declared subpath, and the isolated probe compiles at exit 0. No regression:check:published-readme-exportsis green on a fully built tree with the baseline still atentries: [], and it now reads more of this page than before, because fences that previously imported nothing now carry real imports.
Generated by Claude Code
- added a commit that references this issue
on Aug 23, 2026
Found while rewriting
packages/mcp/README.md(#9579), by sweeping published READMEs for the shape that card is about: a method call on a receivercheck:published-readme-exportscannot see.The finding
packages/drivers/driver-sql/README.mdtells the reader to build a stack driver like this, at three separate call sites:driver: DriverSQL.configure(getDatabaseConfig())driver: DriverSQL.configure({ client: 'pg', connection: { … }, debug: true })driver: DriverSQL.configure({ … })Measured against the built
packages/drivers/driver-sql/dist/index.d.ts:DriverSQLis not exported. Zero occurrences of the identifier anywhere in the type entry. The real export isSqlDriver— which the same README imports correctly at line 43, so the page contradicts itself.configurestatic exists onSqlDriveror on anything else the package exports. Greppingconfigurein the type entry returns two hits, both prose inside doc comments.This is the
PluginAudit.configure()shape from #9517 / #9532, still live on a page npm renders (README.mdis infiles,privateunset).Why the gate did not catch it
Both halves of
check:published-readme-exportskey on a name the fence imported. The fences at 448/482/516 import nothing;DriverSQLappears out of nowhere as a free identifier, so the import half has no claim to make and the call-site half never adds it tolocalNames. #9544 recorded a different row in this same file (line 137, theIDriversubpath) and PR #9581 fixed that one — this one sat one section further down, outside what the gate reports.Census behind that: across the 60 published markdown documents, 38 carry at least one method call on a receiver the gate cannot see, 235 call sites in total. This is the one instance in that population that measurably names nothing real.
Why this is not a mechanical substitution
Swapping in the real export does not produce working code:
SqlDriverhas noconfigureeither, so the correct form is a decision about how a host actually supplies a driver todefineStack— the same class of question the mcp README needed a ruling for. Filing rather than folding it into #9579, whose ruling is scoped topackages/mcp.Refs: #9579 · #9544 · #9532 · #9517 · PR #9581
Generated by Claude Code