Skip to content

fix(spec): #4001 重测 —— 实测剩余站点清单,并修好测量它的那把尺 - #4852

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-4001-strictness-remeasure
Aug 3, 2026
Merged

fix(spec): #4001 重测 —— 实测剩余站点清单,并修好测量它的那把尺#4852
os-zhuang merged 4 commits into
mainfrom
claude/issue-4001-strictness-remeasure

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Refs #4001
Refs #4721

按 2026-08-03 维护者裁决「必要的全收」执行注意第 1 条 —— 先重测,再切批

本轮不改任何 schema 的 strictness 姿态。 产出是一份实测的剩余站点清单,供 PM 据实拆批。


一、先说结论:那把尺本身是坏的,而且两个方向同时坏

台账的站点计数一直是对源码做文本匹配(z.object( / strictObject()。这次用一把独立的 AST 尺去对,七个文件不一致 —— 出现在这场战役专门为了「地图不许悄悄过期」而写的那个闸门里

方向 实例
把注释算成站点 ui/action.zod.ts 声明 9,实为 8(第 9 个在一段 JSDoc 里);kernel/metadata-protection.zod.tsshared/suggestions.zod.ts 整个是注释
认不出折行的调用 prettier 把长链写成 z\n .object({,z\.object\( 匹配不到 —— ui/chart.zod.ts 漏 1、kernel/manifest.zod.ts 漏 2
不认识 z.looseObject( data/field-value.zod.ts 声明 1,实为 2

ui/ 上这两个错误恰好抵消(−1 和 +1),于是 section 总数校验因为第二个错误而通过,盖在两行错的数字上。

最要命的一个:automation/time-relative-trigger.zod.ts 计数为 0 —— 它唯一的站点是折行写的,而零站点文件会被覆盖检查刻意跳过(「没东西可分类」)。于是一个作者手写的可授权 schema 落在地图外,闸门照样打印「no undeclared schema files」。

这不是 data/driver/ 那次的重演:那次是遍历瞎了;这次遍历是好的,是喂给它的计数器返回了一个错误的零,而遍历正确地尊重了那个零。盲区往里挪了一层,走的还是一条正确的代码路径。

修法是结构性的而非再往正则里补一种拼法:计数器改读 AST,不会被格式或注释骗,也不用每出一种新写法就学一次 —— 和第 9 条发现里信封探针改走结构遍历是同一个动作。

二、同一次遍历顺带给出姿态,这才是重测真正要的东西

台账过去只能回答「这个文件里有没有 .strict()」,永远回答不了「它还有几个站点是开的」。而后者正是拆批要用的数。

裁决当时是按 strictObject( 的出现次数排的期 —— 那个写法漏掉每一个用更早的 z.object(…).strict() 关掉的 schema:

strictObject( 实测 strict 站点
ui/ 49 72
automation/ 0 8
data/ 17 40
security/ 7(已全关)
studio/ 27 27(已全关)

三、新增「剩余 strip 站点」地图,并且双向上闸

check:strictness-ledger 现在还守这张表:

  • 正向 —— 任何还有 strip 站点的文件,必须有一行,数字要对;
  • 反向 —— 一行所对应的文件一旦 strip 归零,闸门报红,该行必须删掉。

反向那一半更重要。能活过自己工作的清单,一定会活过:这个台账已经记过一次自己把「已发布的功能」列成待办,ADR-0010 欠债清单当初也是为同一个理由加的反向钉。

四、每一条绿色都先证过红

战役自己的规矩:信一个绿色读数之前,先让它在一个你确知存在的东西上变红。

  • 计数器改完后,闸门在四处已知漂移上报红(ui/action 9→8、ui/chart 6→7、data/field-value 1→2、automation/ 一个未声明文件),补完才转绿;
  • 新增的剩余站点检查,四种失败模式逐一诱发并观察到报红(行内数字错、漏行、已关闭文件残留行、表头算术),再恢复绿;
  • 姿态读数在测试里自带变异对照:把 strictObject( 还原成 z.object( 必须读成 strip,给一个 strip 站点加 .strict() 必须读成 strict。

验证

  • check:strictness-ledger PASS(两行绿:67 文件 / 5 目录;51 个未关闭文件 / 325 strip 站点)
  • check:generated 8/8
  • @objectstack/spec:294 文件 / 7369 用例通过,tsc --noEmit 干净
  • 全仓 pnpm typecheck:122/122
  • 合并 origin/main(4 个提交)后复验:merge 未触及 packages/spec/src,实测数不变,闸门仍绿

范围

只改测量脚本 / 测试 / 台账 + 一个 changeset。零 schema 改动,content/docs/releases/ 未触碰。

剩余清单、分类依据、拆批建议与 #4721 现状核实见 issue #4001 上的重测报告评论。

🤖 Generated with Claude Code

https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9


Generated by Claude Code

claude added 2 commits August 3, 2026 10:10
…r measuring it

Measurement step only — no schema changes posture in this commit. Produces the
real remaining-site list the 2026-08-03 ruling asked for before the remaining
batches are cut.

The site counter now reads the AST instead of matching source text. The textual
method was wrong in BOTH directions on seven files: it counted `z.object({ … })`
appearing inside JSDoc prose (ui/action.zod.ts declared 9 sites, has 8), and it
missed both the prettier-wrapped `z\n  .object({` form (ui/chart.zod.ts 6 -> 7)
and `z.looseObject(` (data/field-value.zod.ts 1 -> 2). On ui/ the two errors
cancelled exactly, so a correct section total sat over two wrong rows.

The consequential case: automation/time-relative-trigger.zod.ts counted ZERO,
because its only site is written wrapped — and a zero-site file is deliberately
skipped by the coverage walk. An authorable schema sat outside the map while the
gate printed "no undeclared schema files". Not the data/driver/ blind spot
repeated: that walk was blind, this walk was fine and honoured a zero the
counter got wrong. Now classified.

check:strictness-ledger gains a remaining-strip-site map: per file, how many
object sites still silently discard unknown keys. That number is what batch
plans are scheduled against and nothing measured it before — which is why the
ruling was cut against `strictObject(` occurrence counts, an idiom that misses
every schema closed with the older `z.object(…).strict()` spelling and reads
automation/ as 0 strict when it has 8. Gated in both directions: a file with
strip sites must have a row, and a row whose file reaches zero strip sites
FAILS, so a closed file drops out of the worklist rather than outliving it.

Every new check verified to go red on a known input before being trusted
(campaign rule): the four remaining-strip failure modes were each induced and
observed, and the posture reads carry mutation controls in the test file.

Refs #4001, #4721

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

vercel Bot commented Aug 3, 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 3, 2026 12:11pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/l labels Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 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

状态说明:本 PR 从未进入合并队列,已重跑失败 job

跟进时发现 auto-merge 挂了约 100 分钟未动,而同期队列消化了 #4841 / #4870 / #4863 / #4872 / #4869 等多单 —— 排查后确认不是队列慢:

merge_group runs(近 10 次):pr-4871 / pr-4870 / pr-4841 / pr-4863 / pr-4872 /
                             pr-4869 / pr-4846 / pr-4861 / pr-4858 / pr-4857
→ 从未出现 pr-4852

原因是时序:本 PR 的 CI 红在 10:1xZ,签名是 #4796 的 5s 超时族;而那条的修复 #4856(testTimeout: 60_000)11:31 才合入 main(d40f43a79)。红检查 → auto-merge 永不触发 → 永不入队。

rerun_failed_jobs。PR CI 检出的是「本 PR 合进当前 main」的合并提交,现在的 main 已带 60s 超时,重跑应当转绿并自动入队。

若重跑后仍红且仍是 5s 超时签名,那就不是这条 flaky —— 按 #4796 的约定重新诊断,不套旧结论。


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

更正:重跑不够 —— rerun_failed_jobs 重放的是原提交,不会带上新 main

上一条我说「PR CI 检出的是合进当前 main 的合并提交,重跑应当转绿」。这是错的,实测打脸:重跑后仍是

FAIL src/cloud/tenant.test.ts > [#4739] TenantPlan(Schema) … × 5065ms
Error: Test timed out in 5000ms.
Tests  1 failed | 7368 passed (7369)

仍是 5000ms,说明 #4856testTimeout: 60_000 没生效 —— GitHub 的 re-run 复用原 run 的提交/合并 ref,不重算。要带上 main 的新提交,只能推一个新提交

#4796 的约定「再出现超时就重新诊断、不套旧结论」查完:这次的失败确实还是 5s 那条,但原因不是 flaky 复发,而是修复根本没进到这次运行里——诊断结论与处置手段的错配,记在这里免得下次再绕一圈。

已做

PM 直接完成同步(实施 agent 已收工、worktree 已拆):

  • git merge origin/main(禁 rebase / force-push),提交 ffc1884c4;
  • 本 PR 不碰任何生成物(只改测量脚本 / 测试 / 台账 + changeset),故无 os-regen 静默吞并风险,无需 checkout-重生成;
  • 但台账计数可能因 main 上的 schema 变动而漂,所以本地实跑验证过:
✓ strictness ledger: 67 file(s) across 5 triaged director(ies) — site counts match,
  no undeclared schema files, section totals balance.
✓ remaining-strip map: 51 open file(s) / 325 strip site(s) across 4 director(ies) —
  counts match, no file with strip sites is missing a row, no closed file still carries one.

两行仍绿,实测基数(51 文件 / 325 strip 站点)不变,拆批依据无需修订。

新推送会触发全新 CI,合并 ref 将包含 #4856,超时线为 60s。


Generated by Claude Code

@os-zhuang
os-zhuang added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit a2ebea2 Aug 3, 2026
24 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-4001-strictness-remeasure branch August 3, 2026 12:32
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/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants