Skip to content

refactor(driver-sql)!: distinct 的第三参收成裸 FilterCondition (#6320) - #6517

Merged
os-zhuang merged 7 commits into
mainfrom
claude/issue-6320-sql-distinct-filter-condition
Aug 8, 2026
Merged

refactor(driver-sql)!: distinct 的第三参收成裸 FilterCondition (#6320)#6517
os-zhuang merged 7 commits into
mainfrom
claude/issue-6320-sql-distinct-filter-condition

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #6320

这份 PR 是「接手 + 验证」,不是从零重做

上一位实施 agent 在提交后、推送前失联,PM 把分支原样抢救推上远端(未改一行、未经任何验证)。本 PR 在此基础上完成:合 main(落后 37 个提交)→ 逐条复核 → 全套实测 → 补齐它漏掉的门禁产物

⚠️ 下面每一条证据都是我这一轮亲自跑出来的。抢救到的提交信息里写了一份读数,我没有沿用任何一条,全部重测;结论与它一致的地方我也重新跑过,不一致或它没做的地方在下文明确标出。

一、改了什么

SqlDriver.distinct 的第三参 filters?: any 收成 FilterCondition非测试改动 100% 是一个类型注解加一段 JSDoc,零运行时改动 —— 没有一条语句移动。

方法体一直说得很清楚:applyFilters(builder, filters) 拿的是实参本身,从来不是 .where,所以它要的是 find() 放在 query.where 里的那个值,不是 query 信封。distinct 不在 IDataDriver 上(已核:packages/spec/src/contracts/data-driver.ts 全文无该方法),所以 #5181 / #6075 的收窄程序没走到它。

收窄消掉的那一格是标量

distinct('orders', 'product', 'completed')

applyFilters 对「真值但非对象、非数组」的 filter 不发射任何谓词,于是这个真心想按条件去重的调用编译通过,然后拿到全集。这就是 #6320 说的「方向是放宽」。现在它是 TS2345。

不碰driver-memory / driver-mongodb#5499 冻结面)、aggregate 区(#6404 批 B 刚落地)、applyLike / $icontains 区(#5702 在飞)。

二、调用点实测 —— 立单记 3 处,实测 14 处

自己数的,不是沿用:

调用点 其中传第三参
driver-sql 11 2
driver-sqlite-wasm 3 2
driver-turso 0 0
合计(本 PR 新增 pin 测试之外) 14 4

传第三参的 4 处本来就写的裸 filter 对象,零报错、零 fixture 改动。加上本 PR 新增的两个 pin 文件(sql 7 + wasm 2)共 23 处。

三、反向验证 —— 方向先判后跑,其中一向推翻了派发模板的预判

A. 签名改回 any ⇒ pin 必须红(预判:红)

预判命中,逐条相符:

driver-sql:
  sql-driver-distinct-filter-narrowing.test.ts(88,13): error TS2322: Type '"narrowed"' is not assignable to type 'never'.
  sql-driver-distinct-filter-narrowing.test.ts(112,9): error TS2578: Unused '@ts-expect-error' directive.
  sql-driver-distinct-filter-narrowing.test.ts(121,9): error TS2578: Unused '@ts-expect-error' directive.
driver-sqlite-wasm(重建 driver-sql 之后):
  sqlite-wasm-distinct-filter-narrowing.test.ts(62,11): error TS2322: Type '"narrowed"' is not assignable to type 'never'.
  sqlite-wasm-distinct-filter-narrowing.test.ts(75,7): error TS2578: Unused '@ts-expect-error' directive.

即 sql 3 红(1x TS2322 + 2x TS2578)、wasm 2 红(1x TS2322 + 1x TS2578)。

B. ⚠️ 「query 信封交给 sql.distinct 必须编译不过」—— 这一向是反的,如实报告

派发模板预判此处应当编译失败。我的预判是它会成功编译,实测证实了这一点,理由不是实现漏了,而是任何类型都关不上这一格

FilterCondition 的键就是字段名,所以它是开放映射(packages/spec/src/data/filter.zod.ts:304[key: string]: any)。{ object, where } 在结构上是一个完全合法的 filter —— 约束两个分别叫 objectwhere 的列。没有任何注解能把它和正当 filter 分开。

实测:给那一行加 @ts-expect-error,编译器反过来报「这里根本没有错误可压」:

sql-driver-distinct-filter-narrowing.test.ts(166,9): error TS2578: Unused '@ts-expect-error' directive.

抢救到的代码在这一点上是诚实的:它没有假装关上,而是把注释写清楚,并改用运行期 pin 钉住「响亮失败」—— 信封的 where 值是对象,而没有任何比较值可以是对象,于是 assertCompilableComparandINVALID_FILTER / 400。这条 pin 是绿的(测试通过)。数组形式(FilterArray,#5158)同理,同样只能靠运行期。

结论#6320 正文提的「让反向错配也编译不过」在这个参数上不可达;能拿到的保证是运行期响亮失败,已按行为钉住。这一格我按实测写,没有把模板的预判硬套上去。

C. driver-sqlite-wasm 确实读到新构建的 d.ts(预判:sql 6 红 / wasm 3 红)

wasm 读的是 driver-sql 构建后的 dist/*.d.ts 而不是源码,是已知门禁盲区,所以按 #6354 / PR #6396 的做法证明而不是假设:往参数类型临时塞一个调用方不可能满足的成员(FilterCondition & { __os6320_probe__: never }),重建 driver-sql,看调用点是否逐一变红。

预判逐处列名后再跑,数量与位置全部相符

  • driver-sql 6 红sql-driver-advanced.test.ts 393、403;...narrowing.test.ts 97、140、166、182 —— 恰是全部 6 处传第三参的调用点。
  • driver-sqlite-wasm 3 红sqlite-wasm-driver-advanced.test.ts 382、392;...narrowing.test.ts 67 —— 恰是该包全部 3 处传第三参的调用点。探针只存在于 driver-sql 的源码里,wasm 自己一行没改,所以这 3 红只可能来自新构建的 d.ts

构建产物同步核对:探针期 dist/index.d.ts:1442 读到 filters?: FilterCondition & {,还原重建后读回 filters?: FilterCondition

@ts-expect-error 那两处标量调用在探针期没有新增报错(指令仍被使用),与预判一致 —— 这一条是区分「真的逐点红」与「整片红」的判据。

四、ADR-0087 门 —— 走 registered,并说明为什么另外三格都不诚实

changeset 标 major,触发 #6148 的门。四格逐一判:

  • not-required (unpublished)@objectstack/driver-sql@objectstack/driver-sqlite-wasm 都是 private: false,这一格机械上就过不了。
  • not-required (already-registered)。没有既有条目覆盖这个面。
  • not-required (no-migration-prescription)不诚实。本 changeset 正文带着一段实打实的 FROM 到 TO 迁移处方,门会按「自相矛盾」拒绝它 —— 用它就是把「被回答」变成「被绕过」,⛔ 不用。
  • registered这一格成立,落一条 step-17 semantic 台账条目 driver-sql-distinct-bare-filter-typed

条目开篇就写明它记录的是「加类型」而不是「退役某个面」,因为这个区分决定了谁需要动手。它与 data-driver-find-stream-retired#4484)、storage-service-list-retired#5540)、actor-user-roles-to-positions#6011)、driver-aggregate-undeclared-key-aliases-removed#6321)同族:驱动调用参数是代码、不是 stack 元数据,所以没有 D2 链要改写,也刻意不立 schema 墓碑。

为什么它确实欠一条条目:本次零运行时改动,所以无类型的 JS 调用方既拿不到编译错误、也没有行为变化 —— 而这类调用方恰恰是 tsc 永远够不到的那一批,「静默返回全集」这个缺陷他们改动前后都可能正坐在上面。生成的升级指南是唯一能触达他们的渠道。

渲染位置已核对(不是推断):条目落在 docs/protocol-upgrade-guide.md:372,位于 ### Semantic (delegated to you, with acceptance criteria)(第 274 行)之下,不在 ### Mechanical (applied for you)(221–273 行)的表里 —— 所以它不带任何 migrate meta 含义。

⚠️ 抢救到的版本在这里漏了一步,本 PR 补上:台账条目落了,但 spec-changes.json 与升级指南没有重新生成,两道同步门当场是红的:

spec-changes.json is stale — the ADR-0087 registries changed without regenerating the manifest.

已用 gen:spec-changes / gen:upgrade-guide 重新生成(非手改),两门现已绿。

五、我对抢救到的代码做的修改

  1. 补生成产物(上一节)—— 缺了它 CI 必红。
  2. 两条运行期 pin 从「局部变量」改成「实参位」。原写法是 const envelope: FilterCondition = ... 再传进去,那只证明别名接受这个形状;要钉的是它未经强制转换地到达这个参数,只有实参位能证明。这正是 fix(lint): 删除 validateOrgAxisRedLines 里 spec 合法 stack 到不了的四条分支 (#5009) #5018 / validateOrgAxisRedLines 读的 sharing-rule 键是 spec 拒收的:ADR-0105 D6 ① 在 criteria 路径上从不触发 #4984 的死 pin 形状。
  3. 两个新测试文件不再用 (driver as any).knexknexprotected,fixture 确实需要一次转换,但改成 fix(drivers): 聚合函数拒收带上 ADR-0112 信封,并把两类条件分开措辞 (#5907) #6204 体例的具名写法 (driver as unknown as { knex: Knex }).knex,只点名要读的那一个成员,而不是把整个 driver 抹成 anyknexInstance 因此从 any 变成 Knex。一个通篇主题是「这个参数不再是 any」的文件,不该在自己的脚手架里引入 any。⛔ 兄弟测试文件(同包约 50 个)不顺手扫 —— 超出本单范围。

六、门禁与测试(全部本轮实跑)

结果
driver-sql typecheck / test ✅ 967 passed | 46 skipped(74 文件)
driver-sqlite-wasm typecheck / test ✅ 257 passed(19 文件)
spec test ✅ 8710 passed(340 文件)
下游 turbo typecheck --filter='...@objectstack/driver-sql' + spec 96 tasks successful
check:adr-0087-registration registered driver-sql-distinct-bare-filter-typed (new here: ...)
check:spec-changes / check:upgrade-guide / check:generated ✅ 10 个生成产物全部最新
check:empty-changeset
check:type-check-debt ✅ 34 条台账重测,无一超出记录值(见下)
check:nul-bytes + 改动文件自扫 ✅ 6108 文件,零控制字节
改动文件 eslint --no-inline-config
check:query-options-erasure ✅ 见下面的诚实说明

⚠️ check:query-options-erasure 的绿不是本次改动挣来的护栏:它的词表只匹配 query/options 位置的 as any,本次改动的两个文件从头到尾没进过它的计数(改动前后都是 263 test-surface sites in 49 files,一模一样)。如实记录,不当成本单的成绩。

⚠️ check:type-check-debt 一度报红,归因后确认不是本次改动(§9 陈旧产物陷阱):@objectstack/http-conformance 记录 4、实测 10(+6)。逐条读错误内容后确认——10 条里 2 条在 node_modules(该条目自己的 note 就预告了这一点),6 条来自 metadata-protocol / objectql / runtime / service-cluster陈旧 dist/*.d.ts,指名的是 SeedLoaderConfigInput / ExecutionContextInput / ClusterCapabilityConfigInput 这些被 main 今天合入的 #6083(ADR-0122 phase 2)退役掉的名字,与 distinct / FilterCondition / driver-sql 无一相关。重建该闭包后重测:10 降到 3,反而比台账记的 4 还低一条。门现已整体绿。

七、changeset 复核

级别 major 正确:两个包都已发布,distinctSqlDriver 的公开方法,标量第三参从「能编译」变成「TS2345」,对 TS 使用者是编译期破坏。driver-sqlite-wasm 同标 major 也正确 —— SqliteWasmDriver extends SqlDriver 且不覆写 distinct,它已发布的 .d.ts 里这个方法签名同样收窄。

正文里的每一条读数我都独立复算过(14 个调用点、6/3 与 3/2 的两组反向读数、五种形状的运行期结果),与正文相符。迁移处方如实写了「这不是等价改写:修完之后返回值会变,而变化后的那个才是调用方本来想要的答案」,我认同这个写法。


Generated by Claude Code

claude added 7 commits August 7, 2026 17:52
`SqlDriver.distinct` 不在 `IDataDriver` 上,所以 #5181 / #6075 的收窄没走到它,
#6212 批 A+E(#6355)收的是 analyzeQuery / findWithWindowFunctions,也没覆盖它。
方法体一直说得很清楚 —— `applyFilters(builder, filters)` 拿的是实参本身,因此它
要的是 find() 放在 query.where 里的那个值,不是 query 信封;`filters?: any` 只是
没把这句话写进类型里。

实测(三行数据,逐个形状喂给 distinct):

  { status: 'completed' }        RESOLVED ["Laptop","Mouse"]
  省略                           RESOLVED ["Laptop","Mouse","Ghost"]
  'completed'(标量)             RESOLVED ["Laptop","Mouse","Ghost"]  <- 静默放宽
  { object, where }(信封)       THREW INVALID_FILTER / 400
  ['status','=','completed']     THREW INVALID_FILTER / 400 (#5158)

第三行是本次消掉的那一格:applyFilters 对「真值但非对象、非数组」的 filter 不发射
任何谓词(尾注写着这件事),于是一个真心想按条件去重的调用编译通过并拿到全集。

有一格任何类型都关不上,如实写进注释而不是假装关上了:FilterCondition 的键就是
字段名,所以它是开放映射,`{ object, where }` 在结构上是合法 filter(约束两个分别
叫 object 和 where 的列)。#6320 提出的「让反向错配也编译不过」在这个参数上不可达,
实测确认;拿得到的保证是运行期响亮失败,已按行为 pin 钉住。driver-memory 那半边留在
#5499 冻结面内,本次不碰;aggregate 区(PR #6404 在飞)一行未动。

零运行时改动:非测试改动是一个类型注解加一段注释。

逐处复核了全部 14 个调用点(本单正文记 3 处,实测偏低):driver-sql 11、
driver-sqlite-wasm 3、driver-turso 0;真正传第三参的 4 处全部本来就写的裸 filter,
零报错、零 fixture 改动。

反向验证(先预判后跑,两次逐一相符):
  - 签名改回 any:driver-sql 3 红(1x TS2322 + 2x TS2578)、
    driver-sqlite-wasm 2 红(1x TS2322 + 1x TS2578)。
  - 往参数类型塞一个不可满足的成员并重建 driver-sql:driver-sql 6 红、
    driver-sqlite-wasm 3 红 —— 证明 sqlite-wasm 确实读到了新构建的 dist/*.d.ts,
    而不是陈旧副本。

Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx
Co-authored-by: Claude <noreply@anthropic.com>
…ger (#6320)

The #6148 gate asks a declared-breaking changeset what its ledger disposition
is. Answered as `registered` rather than exempted, and the three mechanical
categories are all genuinely closed to this changeset:

  - `unpublished`  -- @objectstack/driver-sql and @objectstack/driver-sqlite-wasm
                      are both published (private: false), so it fails outright.
  - `already-registered` -- no existing id covers this surface.
  - `no-migration-prescription` -- the changeset body carries a worked FROM -> TO
                      migration section, so the gate refuses this category by
                      construction. Using it would be a dodge, not an answer.

The entry says up front that it records a TYPE being added rather than a surface
being withdrawn, because that distinction decides who has to do anything. It
renders into the upgrade guide's "Semantic (delegated to you)" section, carries
no `migrate meta` implication and names no stored field -- the same disposition
four existing code-surface entries already carry: data-driver-find-stream-retired
(#4484), storage-service-list-retired (#5540), actor-user-roles-to-positions
(#6011), driver-aggregate-undeclared-key-aliases-removed (#6321).

The reason an entry is owed at all: the narrowing is compile-time only, so an
untyped JS caller gets neither an error nor a behaviour change -- and that caller
is exactly the one sitting on the silent-widening defect, before and after. The
generated upgrade guide is the only channel that reaches them.

Also moves both runtime pins in the driver-sql suite onto inline argument
positions. A `const envelope: FilterCondition = ...` proves only that the alias
admits the shape; the claim being pinned is that it reaches THIS PARAMETER
uncast, which only an argument position can show (#5018 / #4984 dead-pin shape).

Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-distinct-filter-condition

# Conflicts:
#	packages/spec/src/migrations/registry.ts
…ger entry (#6320)

`spec-changes.json` and `docs/protocol-upgrade-guide.md` are a pure projection
of the registries, and `check:spec-changes` / `check:upgrade-guide` pin the
synchrony. The ledger entry landed without them, so both gates were red:

    spec-changes.json is stale -- the ADR-0087 registries changed without
    regenerating the manifest.

Regenerated, not hand-edited (`pnpm --filter @objectstack/spec gen:spec-changes`
and `gen:upgrade-guide`). The entry renders where the disposition claims it does
and nowhere else -- under "Semantic (delegated to you, with acceptance criteria)"
at line 372, below the section head at 274, and NOT into the "Mechanical (applied
for you)" table at 221-273. So it carries no `migrate meta` implication, which is
the whole reason a code-surface entry is allowed to sit in this ledger at all.

Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…as any` (#6320)

Both new suites opened with `(driver as any).knex`, the idiom ~50 sibling files
in these two packages already use. It is not a query/options erasure -- the
`check:query-options-erasure` ratchet's vocabulary never matched it, and its
count is unchanged either way -- but a file whose entire subject is "this
parameter stopped being `any`" should not introduce `any` into its own harness.

`knex` is `protected` on `SqlDriver`, so a fixture outside the class does need a
cast. The #6204 spelling names the one member being reached instead of erasing
every member of the driver to get at it:

    knexInstance = (driver as unknown as { knex: Knex }).knex;

`knexInstance` is typed `Knex` rather than `any` as a result, which types the
`createTable` callback as `Knex.CreateTableBuilder` for free. Sibling suites are
deliberately NOT swept -- out of scope for this card, and worth its own pass.

Re-verified after the change, not assumed: driver-sql and driver-sqlite-wasm
both typecheck clean, 967 + 257 tests pass, eslint clean on both files, and the
erasure ratchet still reports 263 test-surface sites in 49 files.

Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 3:07am

Request Review

@github-actions github-actions Bot added the size/m label Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/driver-sql, @objectstack/spec.

114 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/glossary.mdx (via @objectstack/driver-sql)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/anatomy.mdx (via @objectstack/driver-sql)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 8, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 8, 2026 03:08
@os-zhuang
os-zhuang enabled auto-merge August 8, 2026 03:08
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit 62159bd Aug 8, 2026
26 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-6320-sql-distinct-filter-condition branch August 8, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants