Skip to content

fix(objectql): 悬空引用巡检为「预算没轮到」的对象建诚实桶 unscannedObjects (#5718) - #5760

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-5718-audit-unscanned-bucket
Aug 6, 2026
Merged

fix(objectql): 悬空引用巡检为「预算没轮到」的对象建诚实桶 unscannedObjects (#5718)#5760
os-zhuang merged 1 commit into
mainfrom
claude/issue-5718-audit-unscanned-bucket

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5718

问题

packages/objectql/src/integrity/dangling-reference-audit.ts 主循环在
report.scanned >= maxRows(默认 DEFAULT_MAX_ROWS = 5_000)时直接 break,
其后所有对象既没被读、也没进任何桶。它们的 dangling: [] 与「真的读过且
干净」的表在报告里完全无法区分 —— 而这正是本文件所有诚实桶存在的理由:

已有桶 覆盖的不完整路径
truncatedObjects 某张表内部的行预算用完,只看了样本
unreadableObjects 试着读了,数据源不给
aborted(#4747) 运行被叫停

「整张表没轮到」是唯一没有对应桶的一条 —— 模块头注释原话:Together they are
what stops 0 dangling from ever being read as everything is fine

改动

新增 unscannedObjects: string[],在主循环每一处提前退出前把未轮到的对象名记下:

#5719 的关系:#4743 不是成因,只是把这条路径抬到「容易踩到」—— 溯源族入巡检
后几乎每个对象都有可审计字段,同样的预算摊到多得多的表上,提前 break 的概率显著
上升。三档 prioritise 决定拿到有限预算,本桶报告谁一点也没拿到,两件
事独立:扫描顺序无法让有界运行变完整,只有说出漏了什么才能让它诚实。

反向验证(方向在跑之前就预测好了)

预测:删掉预算处的 fileUnscanned(i) → 依赖预算停的用例转红;不依赖它的用例
(显式 []、被叫停、枚举前叫停)保持绿。实测完全一致:

× the objects behind the stop are listed, in the order the run would have read them
× an object with NO reference field is not listed — its silence was already proven
× an object the CALLER excluded is not listed — that narrowing is not the audit missing it
× a zero budget reads nothing and names EVERYTHING — the whole report is "not looked at"
× a truncated run and an unscanned run are DIFFERENT reports
× rides along in the warning payload, and does NOT raise the line on its own
AssertionError: expected [] to deeply equal [ 'showcase_task', 'showcase_note' ]
Tests  6 failed | 3 passed | 29 skipped (38)

第二处限位单独验:只删 abort 分支的 fileUnscanned(i)
a called-off run names what it never reached too 单独转红
(expected [] to deeply equal [ 'showcase_task', 'showcase_note' ]),其余保持绿。

注意这里断言的选择是关键:只断言 danglingscanned 的测试在旧的静默
break 下同样是绿的
—— 发现数一个都不变。名字本身才是被测行为。

测试证据

pnpm --filter @objectstack/objectql exec vitest run \
  src/integrity/dangling-reference-audit.test.ts \
  src/engine-dangling-reference-audit.test.ts --maxWorkers=2
 Test Files  2 passed (2)
      Tests  45 passed (45)

# 新增 [#5718] 块 10 例全绿
 Tests  10 passed | 29 skipped (39)

pnpm --filter @objectstack/objectql test        # 全包
 Test Files  123 passed (123)
      Tests  2031 passed (2031)

pnpm --filter @objectstack/objectql typecheck   # tsc --noEmit,无输出即通过

门禁:

check:nul-bytes                OK (5641 tracked text files, no raw control bytes)
check:query-options-erasure    ratchet holds, baseline verified against 5e3c83b
check:engine-double-contract   OK — 27 pinned, 65 DEBT, 1 exempt
check:type-check-coverage      OK — 63/78 packages
check:durability-log-level     OK — 24 seams, all loud
eslint (两个改动文件, --no-inline-config)  clean

改动面

  • packages/objectql/src/integrity/dangling-reference-audit.ts(主循环 + 报告类型)
  • packages/objectql/src/integrity/dangling-reference-audit.test.ts(新增 [#5718] 块 10 例)
  • .changeset/dangling-audit-unscanned-bucket.md(patch)

未碰 engine.ts / lifecycle-service.ts(有其他 dev 在飞),未碰
content/docs/releases/


Generated by Claude Code

)

悬空引用巡检的主循环在 `report.scanned >= maxRows` 时直接 break,其后所有
对象既没被读、也没进任何桶 —— 它们的 `dangling: []` 与「真的读过且干净」的
表完全无法区分,而这正是本文件所有诚实桶存在的理由(`truncatedObjects` /
`unreadableObjects` / `aborted` 已分别覆盖表内预算、数据源拒答、运行被叫停,
唯独「整张表没轮到」没有对应桶)。

新增 `unscannedObjects: string[]`:按扫描顺序(prioritise 三档)记下未轮到
的对象名,可直接回喂 `options.objects` 续跑。类型上 optional(同 `aborted`
与 #4743 的 `provenance`,手写 report 字面量仍可编译),运行时本模块产出的
每一份报告都显式赋值 —— 走到底就是 `[]`,永不缺席,`undefined` 只可能表示
「旧报告形状」。

不入桶的两类:无任何引用字段的对象(prioritise 已在循环前丢弃,其沉默是被
证明的而非假设的),以及调用方用 `options.objects` 排除的对象(那是调用方
自己的收窄,不是巡检漏看)。与 `truncatedObjects` 同族:不单独抬告警(大库
每次健康运行都会耗尽预算,常亮告警就是 #4747 的坏警报),只在告警载荷里逐项
带出,并始终留在返回的报告里。

被叫停的运行同样记录未轮到的对象,否则 `unscannedObjects: []` 与
`aborted: true` 并排会读成「早停了但什么都没漏」;唯一边界是在枚举注册表之前
就被叫停 —— 那时没有名单可给,由 `aborted` 承担,已用测试钉住。

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

vercel Bot commented Aug 6, 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 6, 2026 4:05am

Request Review

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

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/objectql.

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

  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/objectql)
  • content/docs/data-modeling/formulas.mdx (via packages/objectql)
  • content/docs/deployment/migration-from-objectql.mdx (via @objectstack/objectql)
  • content/docs/deployment/vercel.mdx (via @objectstack/objectql)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/objectql)
  • content/docs/kernel/services.mdx (via @objectstack/objectql)
  • content/docs/permissions/authentication.mdx (via @objectstack/objectql)
  • content/docs/plugins/index.mdx (via @objectstack/objectql)
  • content/docs/plugins/packages.mdx (via @objectstack/objectql)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/objectql)
  • content/docs/protocol/objectql/query-syntax.mdx (via packages/objectql)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/objectql)
  • content/docs/releases/implementation-status.mdx (via @objectstack/objectql)

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.

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

Development

Successfully merging this pull request may close these issues.

悬空引用巡检:行预算耗尽后剩余对象被静默丢弃 —— 报告里没有任何桶说「这些对象没被看过」

2 participants