Commit 5e1ea65
* ci(dx): re-measure the type-check DEBT/TEST_DEBT ledger on every run (#5278)
The coverage gate asserted only that a ledgered package had *some* positive
error count written down -- `errors: 28` and `errors: 1` were equally
acceptable to it, because the ledger was never re-measured. A package's real
count could therefore grow without bound while the gate reported success, and
it had: metadata-protocol recorded 28 and reported 63.
`--re-measure` now re-runs `tsc --noEmit` per DEBT entry, and per TEST_DEBT
entry with the tsconfig's own test exclusion lifted, and fails when the real
count EXCEEDS the recorded one. Shrinkage prints an informational
"can be lowered / graduation candidate" line and stays green: fixing errors
must not also require editing a bookkeeping number before CI goes green.
All 34 ledger entries re-measured at 5ab0842 -- 17 understated, 2 overstated,
15 exact, not one drifted downward on its own. Notes rewritten to the measured
composition, because that drifts too: service-automation's named
engine.test.ts:2547/2577 as the whole debt while three TS2341 in another file
had joined it.
Wired into lint.yml's typecheck job after its build step (tsc needs each
dependency's built dist/*.d.ts); the cheap structural half stays where it is.
Measured cost of the re-measure pass: ~4 min.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
* ci(dx): 补两处台账 note 与死代码清理 —— 根条目会随 showcase 动,measureDebt 的 || 分支不可达
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
* ci(dx): rest 的 TEST_DEBT 重测到 143 —— 记录 merge-commit 竞态,那正是闸门起作用的证据
CI 在 b8433ca 上判红:@objectstack/rest 记 136,实测 140。原因不是量错了 ——
`pull_request` 运行编译的是「分支 merge 进当前 main」的树,而 sweep 之后 main
又落地了三个动 packages/rest 的 PR(#5808 / #5821 / #5806)。合并 main 后重量
得 143,tests 56 -> 58,其余 33 条纹丝不动。
这个竞态是引导期的一次性成本,不是常态:本不变式上了 main 之后,引入错误的那个
PR 自己会红 —— 这正是它的目的。写进 MEASURED 的文档块和 rest 的 note,下一个做
全量重测的人不必再自己发现一遍。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
* ci(dx): objectql 的 TEST_DEBT 校准到 335,并把合并队列的竞态写进不变式文档
队列把本 PR 踢出:@objectstack/objectql 记 333,队列基实测 334。333 是在 07:41
的 main 上冻结的,而 #5802(registry.test.ts +116 行)与 #5850 在 07:52 之后才
落地。合并当前 main 后实测 335,两条增量都能逐一归因:
- +1 TS2339 在 src/registry.test.ts —— #5802 新增的 registry 测试;
- +1 TS2554 在 src/engine-update-prior-read-scope.test.ts —— #5850(#5284)
新建的文件。
tests 125 -> 126。其余 33 条纹丝不动(总计 2018 raw errors,无一超出记录值)。
先证伪了另一种解释:同一棵树连跑两次 --re-measure,输出逐字节相同,所以不是 tsc
计数不确定,校准就是正确处置(不需要谈容差)。
顺带把队列这一面写进 MEASURED 的文档块:队列是按「合并到队首」构建的,队首会随
前面的条目落地而移动,所以重跑失败的 job 无法自愈(重跑复用同一个 merge ref,
量的还是那个旧基),唯一修法是推新提交;以及排在后面的 PR 会被连坐,红了要先撤出
队列再修。双跑证伪法也一并写下,免得下一个人重新推导。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
* ci(dx): objectql 的 TEST_DEBT 校准到 339 —— +4 全在 #5861 新增的那一个文件里
第三次基漂移,签名同前:335 是在推上校准提交那一刻冻结的,而 #5861
(SaveMetaItemResponseSchema,#5745)几乎同分钟落地。合并 c15fcee 后实测 339,
+4 全部集中在该 PR 新增的 src/save-meta-response-conformance.test.ts 一个文件:
- :115 TS2554 Expected 2-5 arguments, but got 1
- :119 TS6133 'LOG' is declared but its value is never read
- :119 TS2304 Cannot find name 'appendFileSync'
- :119 TS2304 Cannot find name 'OUT'
tests 126 -> 127。其余 33 条纹丝不动(合计 2022 raw errors,无一超出记录值,也没有
一行 can-be-lowered —— 34 条全部与实测严格相等)。
那两条 TS2304 已在 note 里点名:名字都解析不到,那一行根本跑不起来,不是类型讲究
问题 —— 但那是 #5861 自己要修的,不是本台账要修的,所以只记录、不代修。
按非确定性假说已证伪(前一轮双跑逐字节相同),本轮不再双跑。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
* ci(dx): 按裁决(option A)在合并树上全量重校准,三个热包记档 +10 余量
merge origin/main 后在合并树 e8db1a2 上重跑 --re-measure:5 条上漂
(service-analytics 7->10、runtime 218->227、rest 143->153、plugin-auth
129->131、lint 30->32)、1 条下降(service-storage 42->41),其余 28 条与
记录值严格相等。
按维护者 2026-08-07 的裁决执行选项 A:今日实证的三个热包
(objectql / lint / rest)按实测 +10 记档,note 逐条写明「bootstrap margin
(+10 over N measured at e8db1a2) -- tighten via the ℹ hint immediately
after landing」,并在 MEASURED 文档块加一段说明这是台账里唯一的余量、
每轮打印的 ℹ 行就是收紧工单。其余条目一律精确等于实测。
note 成分按实测重写,delta 能归因的逐条归因、不能的明说:
- runtime +9 全部是 TS18048,全在本窗口新增的一个文件
src/domains/meta-item-envelope.test.ts(#5563 / PR #5895);
- rest +10 中 8 条来自三个新增测试文件,余 2 条落在既有文件、不再编造归因;
- plugin-auth +2 中 1 条在新增的 last-admin-guard.test.ts(#5941 / PR #5993);
- service-analytics +3 仍全在 measure-source-field-gate.test.ts 同一文件、
同一错误码(#5716 / PR #5963),该包 3 -> 7 -> 10 全程无人看见;
- lint +2 两条 TS7006 均在既有文件,pre-merge 逐文件计数未留存,如实记录不归因;
- service-storage -1 跟着 #5540 / PR #5983 摘除 IStorageService.list(prefix),
下调而非留着——高于实测又没写明的余量就是暗账。
tests 文件数一并对齐实测(objectql 130、runtime 102、rest 62、plugin-auth 38、
plugin-security 35、service-sms 5)。
合并冲突只有 TEST_DEBT 一处:main 的 #5773 / PR #5982 改过 service-sms
一行,本分支重写了整块——取本分支并把该条的事实并入,两侧都不丢。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
* ci(dx): 删掉空 frontmatter changeset,改走 skip-changeset —— #5471 / PR #6059 在飞行途中落地
新门禁 `scripts/check-empty-changeset.mjs` 明确判定:PR 新增的空 frontmatter
changeset 是违规。本 PR 的 `.changeset/type-check-debt-ledger-ratchet.md` 正是
「A added, empty at head」这一行,门禁在合并树上逐字点名了它。
按门禁给的两条路选:本 PR 只动 dev scripts / CI(`scripts/`、`.github/workflows/`、
`package.json`、`AGENTS.md`),不发布任何包 —— 走 route 2:删掉 changeset,改用
`skip-changeset` 标签。空 changeset 名不到任何包,正文到不了任何 CHANGELOG,却是
changesets/action 的真实输入(全空集会让 Release 静默且绿地空跑,即 #4898);标签
不产生输入,因此严格更优。
原 PR body 的「## changeset」一节因此过期,更正写在正文「裁决落地」一节里,原节
按接手协议不改写。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
* ci(dx): 第二个合并窗口的再校准 —— service-storage 转记档余量,objectql 余量按新实测抬回 +10
合并 main 到 dca5bd3 后再全量重测,余量在一小时内被兑付了两笔,记录如下:
- `@objectstack/objectql` 实测 339 -> **345**(+6 全是 TS2554,全在
`src/summary-rollup.test.ts`,由飞行途中落地的 #5749 / PR #6013 扩写)。
记档 349 把它静默吸收了 —— 若按精确值 339 记账,这就是同一场赛跑的第 6 次红。
按裁决「实测 +10」把记录抬到 **355**,恢复满额余量。
- `@objectstack/service-storage` 42 -> 41 -> **42**:`IStorageService.list(prefix)`
的退休被拆成两个 PR,spec 半边(#5540 / PR #5983)减 1、适配器半边
(#5541 / PR #6061)删旧测试(-1 TS7006)又新增
`storage-adapter-list-retirement.test.ts`(+2 TS2835),净 +1。上一轮我按实测
下调到 41,一小时后就被咬红 —— 正是派发令说的「非余量条目被基漂移咬住」,
按同一记档规则给这条加 +10,记 **52**,不开精确校准 lap。
一个值得写进文档块的新形状:**拆成两个 PR 的退休会让计数先降后升**,在两半之间
记下的精确值,推上去之前就已经过期。
`rest` / `lint` 两条实测未动(153 / 32),余量原样,note 补记「一小时后在
77c7c88 复测仍是该值」。
重测输出:四条记档余量各打印一行 ℹ(各 -10),无一条上漂,exit 0。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
* ci(dx): 第三个合并窗口的再校准 —— @objectstack/mcp 转记档余量(#5278 option A 第五条)
合并队列在 03:25:18Z 把本 PR 踢出,唯一红线是 `@objectstack/mcp`:
TEST_DEBT 记 52,`tsc --noEmit` 实测 53(+1)。这 +1 不是队列里排在
前面的 #6077 引入的(该 PR 自己那一代队列构建是绿的),而是一条此前
无人可见的既有漂移 —— ratchet 第一次对着移动的 base 重测,就把它照了
出来。换句话说,这个不变量在自己的引入 PR 上先抓到了一条真实漂移,
这本身就是它有效的证据。
+1 已完全归因:src/skill-prompts.test.ts(185,23),一处把
`SkillPrompt | null` 断言成 `Record< string, unknown >` 的 TS2352 ——
正是 #3905 / PR #6077 投影 skill `instructions` 为 MCP prompt 原语时
新增的文件,测试文件数也因此 8 -> 9。
按裁决走 option A(记实测 +10)而不是再跑一轮精确校准:packages/mcp
今天刚落一个 feature,属于活跃变动包,精确数字大概率会再输一次已经
被裁决判死的那场竞速(option D 连输五次)。RECORDED 63 = 实测 53 @
34558c2 + 10,note 按顶栏要求重写了成分 —— 旧 note 写的
"`error` is of type unknown, one catch-block idiom" 是错的,51 条
TS18046 全部是响应体 `json` 绑定,与 catch 块无关。
顶栏 BOOTSTRAP MARGINS 段同步从"四条"改为"五条"。
验证:`pnpm check:type-check-debt` 退出 0,34 条台账全部重测、无一条
高于记录值,五条余量各自打印 `ℹ can be lowered`;同一棵树上连测两次
数字逐字一致(mcp 53 / objectql 346 / rest 153 / lint 32 /
service-storage 42),故这是校准问题而非 tsc 不确定性。
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: os-zhuang <jack@objectstack.ai>
1 parent def5919 commit 5e1ea65
4 files changed
Lines changed: 676 additions & 51 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
509 | 509 | | |
510 | 510 | | |
511 | 511 | | |
512 | | - | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
513 | 516 | | |
514 | 517 | | |
515 | 518 | | |
| |||
720 | 723 | | |
721 | 724 | | |
722 | 725 | | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
723 | 762 | | |
724 | 763 | | |
725 | 764 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
32 | 41 | | |
33 | 42 | | |
34 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
| |||
0 commit comments