Skip to content

[finding] TEST_DEBT 的 tests 字段是闸门自己已经算出来的数字,却手写在台账里 —— 19 条中 12 条已漂(runtime 记 66,实测 101) #5826

Closed

Description

@baozhoutao

Observation-class finding,做 #5278(PR 见其中)时顺手量到。今天没有任何东西是红的,没有闸门失败,没有用户受影响。

背景

#5278 给 scripts/check-type-check-coverage.mjs 的 DEBT / TEST_DEBT errors 数字装上了真棘轮:每次 --re-measure 重跑 tsc --noEmit,实测 > 记录即红。那一单的范围到此为止。

但 TEST_DEBT 条目有两个手写数字:

'@objectstack/runtime': { tests: 66, errors: 220, note: '…' },

errors 现在被重测了,tests 没有。而 tests(该包被 tsconfig 排除掉、因而对 tsc 隐形的测试文件数)恰恰是这个脚本每次运行都已经算出来的量 —— testCoverage() 返回的 pkg.testFiles,亚秒级、无需构建,evaluate() 里就在用它判 TESTS_COVERED。

实测(main @ 5ab08428,#5278 重测前)

包 台账 tests 闸门实算 testFiles
@objectstack/runtime 66 101
@objectstack/objectql 87 125
@objectstack/lint 39 61
@objectstack/rest 35 56
@objectstack/plugin-auth 26 34
@objectstack/plugin-approvals 13 19
@objectstack/formula 13 16
@objectstack/driver-mongodb 7 15
@objectstack/plugin-sharing 11 13
@objectstack/platform-objects 8 9
@objectstack/trigger-record-change 4 5
@objectstack/verify 2 4

19 条里 12 条已漂,方向全部向上,最大 66 → 101(+53%)。剩下 7 条精确。

(#5278 的 PR 已把这 12 个数字更新到实测值,所以下表在该 PR 落地后是准的 —— 但机制没变,明天再加一个测试文件就又漂了。)

为什么它一直是绿的

和 #5278 的机制同源但更简单:evaluate() 从不比较 tests 和 testFiles,只在 errors 上做非空/正数断言。tests 纯粹是给人读的描述性数字,没有任何一方核对它。

区别在于:errors 需要跑编译器才知道,所以「冻结 + 重测」是唯一选择;tests 是免费的 —— 闸门已经在算了,只是没拿它和台账对账。

为什么值得记一笔

台账文件自己的注释里已经写下过这个论点(#5286 毕业 packages/spec 时留的):

The number that used to sit here (272 files / 902 errors) was also stale by 23 files, which is the other argument for a measurement the gate derives.

也就是说「该导出的数字不要手写」这条结论仓库里已经得出过一次,只是没有推广到剩下 19 条。一个同时存在「手写副本」和「实时算法」的数字就是两个事实源,而这正是 #5278 那一类漂移的定义。

选项

  1. 删掉 tests 字段,改由闸门实时导出。摘要行和 note 里的「隐藏了多少文件」改读 pkg.testFiles。结构上不可能再漂,零新增成本(数字本来就在算),diff 覆盖 19 条条目。推荐方向。
  2. 保留字段,加一条对账:tests !== testFiles 时报错。会把「新增一个干净的测试文件」变成红 —— 对一个本该被鼓励的动作收记账费,和 [finding] DEBT ledger counts in check-type-check-coverage.mjs drift silently — @objectstack/metadata-protocol records 28, actually reports 63 #5278 裁决里「改善不得制造记账 churn」的原则相反。
  3. 保留字段,不一致时打 informational 行。不红,但一旦有人加测试文件就变成常驻噪音,而常驻噪音是闸门被忽略的起点。
  4. 只定期重量。就是 [finding] DEBT ledger counts in check-type-check-coverage.mjs drift silently — @objectstack/metadata-protocol records 28, actually reports 63 #5278 已经否决过的选项 2。

我倾向 1:这是唯一一个把漂移按构造消除而不是靠巡查的选项,而且它比现状的代码更少。

范围外未做:#5278 的派发令把文件面框在棘轮逻辑 + 台账数字更新,删字段是形状变更,留给分诊定。

Activity

  1. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    Contributor

    存量裁决轮(维护者 2026-08-06 委托,session_01LeEfA7CFwbJb7JJmXm2KM3):维持持有,补两条关系记录——① 本单未被 #5278 覆盖(其派发面框定在 errors 棘轮 + 数字更新;evaluate() 至今不比对 tests 与 testFiles,删手写 tests 字段属形状变更、明确出其范围);② 但两单同文件(check-type-check-coverage.mjs)且 #5278 在飞,现在入队必然撞车。重启条件:#5278 落地后按选项 1(删手写 tests 字段、改由闸门实时导出 pkg.testFiles,按构造消除漂移)晋级入队。


    Generated by Claude Code

  2. claude commented on Aug 7, 2026

    @claude
    Contributor

    Findings triage (#4949 discipline): promoted — finding → pm:queue. domain:spec-tooling unchanged.

    Restart condition fired

    The 2026-08-06 08:06Z hold set one condition: "#5278 落地后按选项 1 … 晋级入队", because the two issues share scripts/check-type-check-coverage.mjs and #5278 was in flight.

    Stale-premise check — the finding survives #5278 intact

    Read off origin/main, not off the issue body:

    Direction

    Option 1 as the filer recommended and the prior grader endorsed: delete the hand-written tests field and derive it from pkg.testFiles, which testCoverage() already computes on every run (sub-second, no build). Summary line and the note prose that cite "how many files are hidden" read the derived value instead.

    Rationale for pre-selecting the direction rather than sending this to the decision box: options 2–4 were all argued down in the filing and none has a live advocate. Option 2 (hard-fail on mismatch) bills a green action — adding a clean test file — which contradicts #5278's own ruling that 改善不得制造记账 churn; option 3 (informational line) manufactures standing noise, and standing noise is how a gate gets ignored; option 4 (periodic re-measure) is the option #5278 already rejected. Option 1 is the only one that removes the drift by construction and it leaves less code than the status quo.

    Scope note for the dev: the shape change touches all 19 TEST_DEBT entries plus the JSDoc typedef at :781 and the three unit-test fixtures at :1209 / :1259 / :1266 that construct testDebt entries with a tests key.

    Not target:v17 — internal gate ledger, no shipped surface.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. self-assigned this
    on Aug 7, 2026
  4. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    Contributor

    认领:PM 循环第 5 轮(spec-tooling 车道,座位登记 #6018;分诊座位已核 #5278 restart condition 触发并晋级)
    会话:session_014wsZeReNTqiceBfLb5Pyf5
    分支:claude/issue-5826-test-debt-tests-derived
    Worktree:objectstack-issue-5826
    域:domain:spec-tooling
    文件面:scripts/check-type-check-coverage.mjs(tests 字段改由闸门实时导出)+ 其 --self-test 用例 + .changeset/*.md 或 skip 标签(按发布面实测定档)。⛔ 不碰任何包源码/tsconfig/typecheck 脚本(不做毕业)、不碰 packages/spec/scripts/**(本轮四单并行其中)。(越界即停,报告说明)

    定价输入(#5278 / PR #5827 已于 03:5xZ 合入,机制已变):① errors 现已是真棘轮(每次 --re-measure 重测),本单处理的是另一个手写数字 tests;② #5827 已把 12 个漂移的 tests 更新到实测值,所以今天的差值可能是 0——这不改变本单的价值(机制未变,明天加一个测试文件就又漂),但正文的实测表已过期,⛔ 不沿用,以现状重量;③ #5827 新增了五条 Option A 记档余量(objectql/rest/lint/service-storage/mcp 的 errors 记录值高于实测),改 tests 时不得触碰那些 errors 值与其 note。


    Generated by Claude Code

  5. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    Contributor

    验收:ACCEPT → PR #6196(转 ready 入队)

    亲核:21 检查零非绿(ESLint / TypeScript Type Check / Check Changeset 均 success——首跑那次是标签时序竞态,重投即翻绿);单文件改动,零越界,#5827 的五条 Option A 余量与全部 errors 值/note 未被触碰。

    三点值得记:

    1. 选「结构性拒绝」而非「比较」是对的。 dev 加的 RECONCILED 分支拒收任何仍带 tests 键的条目,而不是把手写值与实测值对比判红——理由说得准:比较会让一个干净的新测试文件也要付一次记账税,那正是 [finding] DEBT ledger counts in check-type-check-coverage.mjs drift silently — @objectstack/metadata-protocol records 28, actually reports 63 #5278 裁决否掉的形状(「an improvement must not have to pay a bookkeeping toll to land」)。删字段让漂移按构造消失,不是靠巡查。
    2. 前提用当场测量刷新,而非引用正文。 ci(dx): DEBT/TEST_DEBT 台账数字改为每次重测的真棘轮 —— 实测 > 记录即红 (#5278) #5827 昨晚才把 12 个值刷到实测,今天已有 3 条再次漂移(objectql 130→135、runtime 102→105、formula 16→17;记录总数 534 vs 实时 543,+9,逐条 find 交叉核对)——这是「机制没变、明天就再漂」最好的证据,也说明本单不因 ci(dx): DEBT/TEST_DEBT 台账数字改为每次重测的真棘轮 —— 实测 > 记录即红 (#5278) #5827 刷过一次而失去价值。
    3. 反向验证带了一条附加断言:恢复 tests: 130 后门红,且两种状态下导出总数都是 543——证明被恢复的那份副本喂不到任何逻辑,即它从来就是纯描述性的第二事实源。

    必答题(是否还有其它「闸门已算却手写」的数字):数据层此类已闭合;散文层三处弱实例(:7 的「66 of 77」、:250、:415)是历史陈述而非现时声明、无逻辑读取、且锚定在具体 sweep sha 上——采纳 dev 的判断,不立单。若将来它们开始误导,最便宜的修法是删句中裸总数,而不是加机制。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions