Skip to content

refactor(driver-sql): the sql-driver codemod retires 15 facade-gate exception rows (knex calls, spelled return types, comments in parameters, accessors, computed defaults, the logger default) (#30147 phase 2a) - #30249

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-6gf6xi
Nov 5, 2026

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Yibo Wang · project thread

Part of #30147 (phase 2a of 2a-2d: the sql-driver codemod learns six mechanisms and retires 15 exception rows. 2b, 2c and 2d, then the phase 3 measurement, stay open on the card.)

维护者速读

  • 改了什么:scripts/codemod-split-sql-driver.mjs 新增六种机制(knex 调用、写出返回类型、参数列表里的注释、getter、计算型参数默认值、logger 字段默认值),用它重新生成 sql-driver.ts 和 9 个模块(新增 sql-driver-schema-introspection.ts),登记表删去 15 条 sql-driver.ts 例外(88 → 73)。
  • 为什么改:Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147 要求 codemod 自己移走这些"能力不足"的例外,而不是手改生成结果。
  • 风险与回滚:方法体逐字节不变(171/171),公开 .d.ts 与 base 逐字节相同;回滚即 revert 本 PR。
  • 先看:codemod 里四张新表 RECEIVER_FREE_FIELDS / EXPLICIT_RETURN_TYPES / MOVED_ACCESSORS / MOVED_FIELD_DEFAULTS,以及 verify 里对应的撤销逻辑。
  • 两分钟验证:node scripts/codemod-split-sql-driver.mjs --verify --base 21510bba,预期 171/171 moved bodies identical to base、sql-driver.ts 18334 -> 10717 lines,退出 0;node scripts/check-facade-delegation-only.mjs 打印 73 条具名例外,退出 0。
  • 需要你做的:无,席位审阅并落地。

Clause-②: no
Metadata-protocol: none

What changes

The sql-driver codemod (scripts/codemod-split-sql-driver.mjs) learns six mechanisms. Each one is regenerated from the unsplit sql-driver.ts at 21510bba and re-proved by --verify (undoing the split rebuilds the base byte for byte). No generated file is edited by hand.

mechanism table or rule members it moves
a body may call this.knex(...) RECEIVER_FREE_FIELDS (a Knex instance is the function knex(tableName, options) closure, which reads knex.context, never this) listPhysicalColumns, explainUnkeyableTextColumn, explainHashShadowDuplicate (and getBuilder's field-call half)
the stub writes the return type the base leaves inferred EXPLICIT_RETURN_TYPES (types copied from dist/index.d.ts built at base) getBuilder, applyFilters, ensureDatabaseExists, createDatabase
a comment between the parentheses moves with the base list verbatim rule (the comment-in-parameters stay reason is gone) assertOperatorAppliesToColumn
a get accessor keeps its signature; its body moves MOVED_ACCESSORS insertReturnsStoredRows, dateGranularityCapabilities, supportsWalJournal, dialectName
a computed parameter default is written optional on the stub (nowMs?: number) and stays where the body is rule (the gate's own data-default reading, mirrored) rotateShards, ensureRotation (hand-series stubs: the default stays in the seam function)
a field initializer becomes a facet member typed as the field MOVED_FIELD_DEFAULTS (instance fields only) logger

sql-driver.ts goes from 10,979 to 10,717 lines. Moved bodies go from 158 to 171.

Registry (scripts/facade-delegation-registry.json): the 15 rows those members held are deleted (the gate refuses a row whose member is already a delegation). Five rows that stay get their reason rewritten for the half that remains:

  • applyFilterCondition: inferred-return-type only (2d).
  • ensureShardTable and initObjects: path-reader only (their knex half is retired).
  • get supports: an accessor whose object type the base leaves inferred, with a docblock on each key.
  • static DIALECT_CONNECT_TIMEOUT: a static initializer runs while the class is evaluated, so a facet call there could meet its module in the temporal dead zone.
card before after
#30020 17 17
#30054 16 16
#30055 6 6
#30147 49 34 (sql-driver.ts 27 → 12)
total 88 73

scripts/check-tenant-chokepoint.mjs lists the new sql-driver-schema-introspection.ts in DECLARED_WATCH_HINTS, as its self-test requires for every scanned module.

Tests

  • The codemod's --self-test gains a sixth pinned battery, "codemod-limit retirements (Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147)", with 31 cases: each mechanism moves only when its table names it; the generated text; two runs give one tree; the generated split proves; one edit per mechanism fails the proof (an unlisted return type, an edited written type, an edited comment, an edited getter body, an optional parameter spelled with another type, a facet member or seam that drops the default, a missing seam, an edited initializer, a field calling another member); every stale or wrong table row refuses. 98 cases in 6 batteries pass (67 in 5 before). The battery floor goes from 5 to 6.
  • No test file changes. The suites below ran at base f2a9007e and at head; the counts are equal.
suite base head
driver-sql (vitest run) 238 files passed, 12 skipped; 3,859 passed, 216 skipped the same
driver-turso (subclasses SqlDriver) 97 files; 2,514 passed, 34 skipped the same
driver-sqlite-wasm (subclasses SqlDriver) 40 files; 750 passed the same
cli by-path pins (9 files: generate-* pins, clean.operator-text-21418, migrate, schema-migrate) 9 files; 116 passed the same
types / metadata / metadata-protocol by-path tests, spec check-liveness.test 53 / 11 / 33 / 74 passed the same

Acceptance notes

Verification

Head 34fc09d0, base origin/main f2a9007e.

Proof readings
  • Byte-identity: node scripts/codemod-split-sql-driver.mjs --verify --base 21510bba exit 0: "171/171 moved bodies identical to base (body, parameters, return type, async); 127/127 moved top-level declarations identical to base; sql-driver.ts 18334 -> 10717 lines; undoing the split does rebuild the base byte-for-byte".
  • Determinism: two --write runs from the unsplit input give output tree sha256 07b3a5053a23098c2754bb36caefb96532bbc4c7497ae29ab5dd357aff036454 both times (input sha256 2d2ebebd…).
  • Public .d.ts: dts-public.mjs over the base and head dist exit 0, pass: true, both files raw-equal (index.d.ts sha256 92e2cfb2… on both sides). rotateShards and ensureRotation read the same at base and head, nowMs?: number in both (signature hashes c8bded77… and d0ab9226… on both sides); so do getBuilder and get dialectName.
  • Typecheck: pnpm --filter @objectstack/driver-sql typecheck exit 0.
  • check-tenant-chokepoint: base and head both read 24 getBuilder() bindings, 21 read doors, 3 insert builders, 4 tenant predicates, 0 D8 arms (38 files at base, 39 at head: the new module); --self-test exit 0.
  • Facade gate: node scripts/check-facade-delegation-only.mjs exit 0, "3 facade file(s) hold delegations only, 73 named exception(s)"; --self-test exit 0, 36 cases (gate script and its cases untouched).
  • node scripts/pm/dispatch-gates.mjs --commands: 67 derived commands, each run, all exit 0; --ran reconciles 67 derived, 67 run, 0 NOT-MEASURED. Two first exited 3 on prerequisites (the shallow clone lacked the check-plugin-teardown-shape fixture commit; check:dual-build-cjs-loads needed unbuilt dists): after fetching that commit and building those packages, both exit 0.
  • Also run: the codemod, check-tenant-chokepoint and facade gate --self-tests (exit 0), check:lean-entry-closure (exit 0), eslint over the changed scripts and driver-sql sources (exit 0).
  • Changed lines 1,551 (+1,052 / -499), under the 3,000 threshold.

Generated by Claude Code

…xception rows (knex calls, spelled return types, comments in parameters, accessors, computed defaults, the logger default) (#30147 phase 2a)

The codemod (scripts/codemod-split-sql-driver.mjs) learns six mechanisms,
each proved by --verify (undoing the split rebuilds the base byte for byte):

- RECEIVER_FREE_FIELDS: a body may call `this.knex(...)`; a Knex instance
  is a closure that never reads `this`, so the host's getter keeps the call.
- EXPLICIT_RETURN_TYPES: four stubs write the return type the base's
  declaration output prints (copied from dist/index.d.ts built at base).
- A comment between a method's parentheses moves with the base list verbatim.
- MOVED_ACCESSORS: four get accessors keep their signature; the body moves.
- A computed parameter default (`nowMs = Date.now()`) is written optional on
  the stub (`nowMs?: number`) and stays where the body is, a seam function
  for the two hand-series stubs.
- MOVED_FIELD_DEFAULTS: the `logger` field's initializer becomes a facet
  member typed as the field.

sql-driver.ts 10,979 -> 10,717 lines; 171/171 moved bodies identical to
base; public .d.ts byte-identical. 15 sql-driver.ts registry rows deleted
(88 -> 73); five reasons rewritten for the halves that remain.
check-tenant-chokepoint declares the new sql-driver-schema-introspection.ts.

Claude-Session: https://claude.ai/code/session_01WGufzj4B2cbnRLVdgtLcDZ
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/driver-sql, touching 78 documentable anchor(s).

9 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/data-modeling/drivers.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/data-modeling/index.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/data-modeling/queries.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/permissions/tenant-audit-census.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/plugins/packages.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/protocol/kernel/index.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/protocol/kernel/lifecycle.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/protocol/objectql/query-syntax.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/protocol/objectql/types.mdx (via SqlDriver (symbol, a top-level class))

⛔ 4 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-0.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/releases/v17/17-5.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/releases/v17/17-6.mdx (via SqlDriver (symbol, a top-level class))
  • content/docs/releases/v18/18-1.mdx (via SqlDriver (symbol, a top-level class))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 2 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 103 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 13 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 797f9257c988fbf93cc08cf672b37edf484d75e5 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 384caa70fab820126aa7ce2dff98e438c49d8b74 — the merge of head 34fc09d0d0b6218425272b6b50530dbe31b1308a into base 797f9257c988fbf93cc08cf672b37edf484d75e5, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 384caa70fab820126aa7ce2dff98e438c49d8b74 && git checkout 384caa70fab820126aa7ce2dff98e438c49d8b74
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 797f9257c988fbf93cc08cf672b37edf484d75e5 34fc09d0d0b6218425272b6b50530dbe31b1308a && git checkout -B drift-repro 797f9257c988fbf93cc08cf672b37edf484d75e5 && git merge --no-ff 34fc09d0d0b6218425272b6b50530dbe31b1308a

node scripts/docs-audit/affected-docs.mjs --json 797f9257c988fbf93cc08cf672b37edf484d75e5

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 797f9257c988fbf93cc08cf672b37edf484d75e5 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:devx#1 · os-support-ai · session_01WGufzgBDcBNVmSmo7VFHpj

Stamp: 2026-11-05T03:31Z
Head-sha: 34fc09d

维护者速读

  • 改了什么: 扩展 scripts/codemod-split-sql-driver.mjs,重新生成 sql-driver facade,又有 15 个成员改成一行委托:

    • 4 个 accessor;
    • 3 个只读 knex 实例的方法;
    • 4 个显式返回类型,类型字符串从 base 构建的 dist/index.d.ts 原样复制;
    • 1 个带注释的参数表;
    • 2 个计算默认值(nowMs: number = Date.now() 改成 nowMs?: number,默认值留在 facet 里);
    • 1 个初始化器(logger)。

    登记表例外行从 88 条降到 73 条。

  • 为什么改: Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147 第二阶段 2a,用 codemod 消掉 sql-driver.ts 里能消的例外行(裁决 6624345766 第 3 条)。

  • 风险与回滚: 搬走的方法体逐字节相同,公共 .d.ts EQUAL,driver-sql 及直接消费方的测试数量与 base 一致。回滚就是 revert。

  • 先看: scripts/codemod-split-sql-driver.mjs 里新增的 accessor 委托、显式返回类型表和计算默认值的改写。

  • 两分钟验证: node scripts/codemod-split-sql-driver.mjs --verify --base 21510bba,退出 0,171/171 个方法体相同。

  • 需要你做的: 无,由席位落地。

  • 席位意见: ACCEPT。

席位核对

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant