Skip to content

docs(pm-dispatch,os-dev): 假引擎的 delete() 一律路由 assertEngineDeleteDispatch,并收编 run-summary 的盲区实例 (#5197) - #5630

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-5197-osdev-delete-dispatch-line
Aug 5, 2026
Merged

docs(pm-dispatch,os-dev): 假引擎的 delete() 一律路由 assertEngineDeleteDispatch,并收编 run-summary 的盲区实例 (#5197)#5630
os-zhuang merged 1 commit into
mainfrom
claude/issue-5197-osdev-delete-dispatch-line

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5197

三个落点,前两个是同措辞的一行纪律,第三个是评论里已定位的盲区实例收编。

为什么值得动 agent 定义文件

同一天三个互不相同任务、互不相同包的 dev agent(3/3)新写假引擎全部踩 check:engine-double-contract 判红,错误一模一样 —— 手抄守卫、未路由 assertEngineDeleteDispatch(#5173#5191#5192),各花一轮 CI 往返 ≈15 分钟;#5584 的新测试是第四次同款命中(即当前 main 上的 #5604)。门禁没漏,防线是好的;代价纯粹是「新增测试 + 需要假引擎 + delete 路径」这个高频组合缺一行提交前的提示。

两处措辞相互一致,都点名手抄守卫真有洞这一实测事实(而不是「风格不推荐」):#5173 的手抄副本放行了 where: { id: { $in: [...] } } —— 看着像 id,实为多行谓词,真引擎无 multi 时拒收。样板引用的是「门禁绿跑时自己列出的 pinned 假引擎」,不是一个会过期的计数。

第三处:run-summary.test.ts 的盲区实例

packages/services/service-automation/src/run-summary.test.ts 的内联假引擎 async delete() { return false; } 对谓词删除照单全收。而 delete_record#5393 起转发 multi: cfg.multi === true,所以 { objectName: 'deal', filter: { stale: true } } 这一形状真引擎是 reject

该文件既不在 pinned 也不在 DEBT 台账:门禁的形参个数判据(isEngineDeleteShape 要求 delete 至少两个形参)够不到零形参的 delete,所以这是检测器盲区,不是已登记的债。这个扫描面缺口连同实测口径另立 #5629(实测:只放开该判据,发现面从 59 个 double/58 文件涨到 150 个/107 文件),⛔ 本 PR 不修它。后果不是假设 —— #5225 里 showcase 的 showcase_inquiry_purge 从上线起每次 acted: 0,单测却一路绿。

收编按补声明处置,不是重写断言:该 fixture 从来就不是契约内合法的,补 multi: true 声明其批量意图,于是 sweep 真的到达驱动、驱动报告匹配 0 行,用例原本的主题(计数器读 0)完整保留。执行器侧的 reject 传播已由 builtin/crud-bulk-intent.test.ts:153 钉住,此处不重复。@objectstack/objectql 早已是本包 devDependency(#5393 加的),无需动 package.json,无 turbo 环。

反向验证:预期红,实测仍然绿 —— 所以断言也得加强

先说方向,再说结果。预期是「假引擎收编 + 撤掉 multi:true → 判红」。实测绿:

Test Files  1 passed (1)
     Tests  1 passed | 33 skipped (34)

原因是 acted: 0 既是「删了 0 行」也是「删除被拒」留下的痕迹 —— 运行失败了,summary 照样记 acted: 0,原用例唯一的断言两种情形都满足,是为空而绿(os-dev.md 里 fixture triage 那条「assertion keeps passing because nothing is produced」的活体标本)。

所以只收编假引擎对这个用例买不到任何东西,断言必须同时加强。补 res.success 与该节点 runs: 1 / failures: 0 / acted: 0 之后,同一撤销才真的判红:

FAIL  src/run-summary.test.ts > delete_record reports 0 when the driver reports nothing deleted
AssertionError: expected false to be true
 ❯ src/run-summary.test.ts:443:29  expect(res.success).toBe(true);

恢复 multi: true 后全绿。这一步是实测逼出来的,不是顺手加固。

验证

变更集

.claude/ 文档 + 测试-only,无用户可见面 → 走 skip-changeset 标签路线,未写空 frontmatter changeset。请 PM 落标签。


Generated by Claude Code

…ch,并收编 run-summary 的盲区实例 (#5197)

同一天三个互不相同任务的 dev agent(3/3)新写假引擎全部踩 `check:engine-double-contract`
判红,错误一模一样 —— 手抄守卫、未路由 `assertEngineDeleteDispatch`(#5173#5191#5192),各花一轮 CI 往返 ≈15 分钟;#5584 的新测试是第四次同款命中(#5604)。这不是门禁
漏了,防线工作正常,代价纯粹是「新增测试 + 需要假引擎 + delete 路径」这个高频组合缺一行
提交前的提示。

os-dev 定义与 pm-dispatch 派发词模板各加一行同措辞纪律,把这轮往返省在提交前。两处都点名
手抄守卫**真有洞**这一实测事实,而不只是「风格不推荐」:#5173 的手抄副本放行了
`where: { id: { $in: [...] } }` —— 它看着像 id,是多行谓词,真引擎无 `multi` 时拒收。
引用的样板是「门禁绿跑时自己列出的 pinned 假引擎」而不是一个会过期的计数。

第三处是 `service-automation/src/run-summary.test.ts` 的盲区实例(#5197 评论定位):它的
内联假引擎 `async delete() { return false; }` 对谓词删除照单全收,而 `delete_record` 自
#5393 起转发 `multi: cfg.multi === true`,所以 `{ objectName: 'deal', filter: { stale:
true } }` 这一形状真引擎是 reject。该文件既不在 pinned 也不在 DEBT 台账 —— 门禁的形参个数
判据够不到零形参的 delete(另立 #5629 记录该扫描面缺口及实测口径),所以是检测器盲区,不是
已登记的债。后果不是假设:#5225 里 showcase 的清扫流从上线起每次 `acted: 0`,单测全绿。

收编后按「补声明」处置而非重写断言:该 fixture 从来就不是契约内合法的,补 `multi: true`
声明其批量意图,于是 sweep 真的到达驱动,驱动报告匹配 0 行,用例原本的主题(计数器读 0)
完整保留。执行器侧的 reject 传播已由 `builtin/crud-bulk-intent.test.ts:153` 钉住,不在此
重复。

断言同时加强,这一步是实测逼出来的而非顺手:反向验证(假引擎已收编、`multi` 撤掉)预期红,
实际**仍然绿** —— 因为 `acted: 0` 既是「删了 0 行」也是「删除被拒」留下的痕迹,原用例唯一
的断言两种情形都满足,是为空而绿。补 `res.success` 与该节点 `runs: 1 / failures: 0` 之后
同一撤销才真的判红(`expected false to be true`),用例才在读它声称在读的那件事。

Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE

Co-authored-by: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 5, 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 5, 2026 8:55pm

Request Review

@github-actions github-actions Bot added the size/s label Aug 5, 2026
@os-zhuang os-zhuang added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/s labels Aug 5, 2026 — with Claude
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

Copy link
Copy Markdown
Contributor Author

门禁口径追记 —— 正文里的「改动后仍是 1 problem」是在分支切点 cc5b048a0 上量的,而 #5615(fix(runtime): route #5138 test engine doubles through assertEngineDeleteDispatch)已在此后落地 main(2614aefb3),#5604 那个红点已经被它修掉。

把本分支与当前 origin/main 做一次一次性试合(git merge --no-commit --no-ff,量完即 --abort,不入本 PR 历史)后重跑,门禁整体全绿:

engine doubles: 59 in 58 test file(s) — 27 pinned to ObjectQL.delete's dispatch predicate, 32 in the shrink-only baseline.
check-engine-double-contract: OK — 27 pinned, 31 in the DEBT ledger, 1 exempt.

即 25(切点上含本 PR 的 +1)+ 2(#5615 收编的两个)= 27 pinned;台账 34 → 32 是 #5615 顺带对账掉的两条,不是本 PR 动的(本 PR 一个字都没动 scripts/engine-double-contract.baseline.json)。发现面 59 / 58 文件在两侧一致 —— 那两个 double 本来就在扫描面内,只是从 unguarded 变成 pinned。

同时核过在飞重叠:cc5b048a0..origin/main 的 4 个 commit 无一触碰本 PR 的三个文件,也没碰门禁脚本与台账。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 5, 2026 21:10
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit 0d5c416 Aug 5, 2026
29 of 30 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5197-osdev-delete-dispatch-line branch August 5, 2026 21:23
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 6, 2026
…objectstack-ai#5579) (objectstack-ai#5642)

该段给出的唯一理由是「One raw control byte makes grep treat the whole file as
binary: zero matches, no signal」——而这条只对 NUL 成立。在容器内独立复现(样本用
printf 生成,未粘贴裸字节;GNU grep 3.11 + ripgrep 14.1.0):

    U+0000  grep: binary file matches            rg: binary file matches (found "\0" ...)
    U+0001  grep: 2:searchable line              rg: 2:searchable line
    U+007F  grep: 2:searchable line              rg: 2:searchable line

即门禁扫描面里除 NUL 之外的每个字节(含 objectstack-ai#5460 纳入门禁、objectstack-ai#5577 补进自扫字符类的
DEL)都不会让文件被当成二进制。危害只写这一条的后果不是文字不精确:agent 写出一枚
非 NUL 控制字节、自扫命中后去核对指令,会发现唯一被陈述的判据不成立,从而把门禁的红
判成误报。

`scripts/check-nul-bytes.mjs` 脚本头早就把两侧分开论证好了(objectstack-ai#5157 段),本次把散文
口径搬过去对齐:

- binary-file / zero-matches 那条点名 NUL,并标明是实测结论;
- 其余扫描面字节引脚本头写清的三条:渲染为空(代码对每个读者说谎)、两种拼写互不
  命中(文件里是字节,不是你会去搜的转义文本)、事故源不挑字节值;
- 补一句直接堵住上述推理:「不是 NUL、grep 还能搜到」永远不构成把门禁红或自扫命中
  读成误报的理由;
- 危害论证指向脚本头「引用它,不要重新推导」,不在此处再抄一遍论证细节。

顺带修同段两处陈旧:

- 「this repo has paid four times」的硬编码计数改为免计数措辞——该族已多于四例,
  objectstack-ai#5624 刚因同样的漂移把台账里的 sibling 计数改成不含数字的表达;
- 「a `0x01` that `check:nul-bytes` does not scan for (objectstack-ai#5157)」的现在时已错:objectstack-ai#5157
  正是把该字节纳入扫描面的那一单,改为过去时的事实句。

未做(留档而非顺手扩面):单源化——让字符类与危害论证不再手抄多处——是 objectstack-ai#5484 正文
留下的方向,本 PR 只修散文口径,不动 `scripts/check-nul-bytes.mjs`、不动 objectstack-ai#5577 刚
补的自扫字符类、不动 objectstack-ai#5630 刚加的 Toolchain traps 条目。

纪律:全程未向任何文件写入裸控制字节,散文沿用该文件与脚本头既有的 `0x01`/`0x7f`
十六进制写法(不含反斜杠转义,不会被编辑工具 materialise)。
`node scripts/check-nul-bytes.mjs` 绿;改动文件自扫
`grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` 无命中;`cat -A` / `od -c` 复核新增
行无意外字节。

`.claude/` 文档-only,无用户可见变更,走 skip-changeset 标签路线。

Fixes objectstack-ai#5579

Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 6, 2026
…in 滞后、死代码删除复核 (objectstack-ai#5513) (objectstack-ai#5645)

2026-08-05 跑完一整条 filter 缺陷链(objectstack-ai#5363 / objectstack-ai#5366 / objectstack-ai#5368 / objectstack-ai#5375 / objectstack-ai#5431 / objectstack-ai#5445,
cloud#1117)后回看,六处在那一轮真实咬过人或真实救过场的规程,SKILL 里没有对应条目。
六条各落在 issue 指定的节内,**纯增补**:111 行插入、0 行删除,既有条目(objectstack-ai#5501 的接力
模式、objectstack-ai#5522 的座位模型、objectstack-ai#5630 的 assertEngineDeleteDispatch 条款)一字未动。

落点与要点:

1. **Multi-repo,rule 2 之后**「pin 滞后」——`Blocked-by:` 只保证上游已合并,姊妹仓还有
   第二个读数:本仓 pin 是否覆盖那个 commit。cloud#1116 的裁决落于 framework objectstack-ai#5368
   (`9c5abf4e9`),而 cloud 的 `.objectstack-sha` 未覆盖它,于是 `TursoDriver` 有一个
   方向反了的分叉窗口(fail-closed 一侧先到)。规程:派发前核祖先关系;未覆盖则 dev 在
   PR 正文留档窗口与方向,⛔ pin bump 不做 rider。
2. **step 3** 末「阻塞解除后重新定价」—— 前一单合入会改变后一单的成本模型,方向不止一个
   (本轮变便宜、没变、成本估计过期各有实例)。两个动作配对:派发前一单时带必答项
   「你的改动是否让 #X 变简单 / 变难 / 不必要 / 无影响」,派发被延后那单前用该回答重读
   其选项与成本估计。
3. **step 5** 派发令「多面组件的测试落点」—— 同一契约 ≥2 实现面时,新用例进共享一致性
   覆盖而非独立文件(原话照录)。附 objectstack-ai#5375 / objectstack-ai#5431 / objectstack-ai#5445 三条正交轴共用一条不变量。
4. **step 7 清单**「收益穿过它必经的那道边界之后还在吗」—— 判据是价值主张是否依赖下游
   如实转发;实例即 objectstack-ai#5423(4xx 直通曾整条替换 ≥500 字符正文,`code` 到了正文没到)。
5. **step 7 清单**「死代码删除的复核」——「这是死代码」是断言而非能从 diff 读出的事实,
   PM 在 origin/main 独立核一次引用面再 ACCEPT(查法用 Operational notes 6:notes 6 说
   怎么查不假阴性,本条说什么时候必须查)。
6. **step 8** 升级门槛之后「带前提的裁决」—— 分歧关键是可被代码证伪的事实时,第三档 =
   裁决 + 前提验证要求 + 「前提不成立报 fork,不许硬做也不许悄悄改选」禁令,三件缺一
   不可;缺第 3 条即退化为无人裁决且无读数显示。

实施时两处核实结果与 issue 正文不同,成文按核实后的事实写:

- issue 的附带论断「没有任何闸门在量这个 pin 滞后」**不成立** —— cloud 的
  `scripts/check-pin-staleness.sh`(test.yml 以 `continue-on-error` 跑)每次 CI 都报两个
  pin 各落后 main 多少 commit,advisory 是**有意设计**(`--max-behind` 需显式传)。它答
  的是「落后多少」,不是「是否覆盖我这条裁决 commit」;成文因此指向该脚本,并只把后一个
  问题留给派发前的祖先判断。据此**未**另立「无闸门」的发现单。
- 第 4 条的 rest-server 缺陷本身已由 objectstack-ai#5423 按「截断而非替换」修掉,成文改用过去时并注明,
  以免后来的读者去找一个已不存在的活 bug;该条要补的是**复核清单的缺口**,与代码是否已修
  无关。

第 1 / 3 条按 issue「未验证的部分」的克制写入适用判据(前后单共用同一契约或数据表示;
组件对同一契约有 ≥2 实现面),形态迥异的批次(纯 UI、纯文档)明确不强加。

验证:`node scripts/check-nul-bytes.mjs --self-test` + 全仓扫描绿(48 断言 / 5537 文件);
改动文件自扫 `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` 零命中,并用邻近词反查证伪
「扫描器坏了」;`check:docs-audit-scope` 绿;markdown 结构核对(强调标记成对、代码围栏
16 个偶数、嵌套围栏缩进对齐)。

Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: os-zhuang <hr@objectstack.ai>
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/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

os-dev 派发词/定义可加一行:测试假引擎的 delete() 必须路由 assertEngineDeleteDispatch —— 同一门禁一日两红(#5173、#5192)

1 participant