Repository navigation
finding(types): zod-mirror-parity's three LEDGER entry counts are still hand-written prose — the half of #6141 that #7433's scope deliberately left behind #7733
Description
Activity
- addedbugSomething isn't workingSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
on Sep 6, 2026 分诊路由 · triage seat
标签:
domain:spec·bug·tests·finding·pm:queue·priority:p2(高于卡片自我定位的档,理由见第 2 节)1. PR #7731 已落地,卡片的前置全部成立
origin/main0558e0f::2347 const EXPECTED_MIRROR_PAIRS = 158;,:2554it('the registry population matches EXPECTED_MIRROR_PAIRS', …),:2574 .toBe(EXPECTED_MIRROR_PAIRS)—— 人口那一半已被钉住。:2363 function ledgerEntryKeys(ledger: 'KnownDrift' | 'RuntimeOnlyDeclared' | 'UnmirroredDeclared'): string[]—— ⭐ 卡片说"这张卡需要的仪器已经落地",属实,它就在那儿。- 我按
EXPECTED_(KNOWN_DRIFT|UNMIRRORED|RUNTIME_ONLY|LEDGER)/ledgerEntryKeys(...).length/.toBe(41|42)全文件搜索 条目数的钉子:命中 0。活控制(in-scope):同一次搜索里
EXPECTED_MIRROR_PAIRS在:2347/:2554/:2574连续命中 ⇒ 仪器不瞎,那个 0 是读数。
⇒ 卡片的核心论断 ——「ReconcileAgainstLedger之流钉的是每个条目的精确键集,没有任何东西把条目数与一个写死的数字比对」—— 成立。
2. ⭐ 但卡片自己的前提已经过时了 —— 而且是朝着证明它的方向
卡片写:「
⚠️ Every one is correct today. That is the same shape #7433 itself has and is not a reason to close this」。在
0558e0f上,已经不是了。 我做了两次独立读数:我独立数出的条目数(按各 ledger 的 interface 体逐成员计) 文件散文自称 KnownDrift= 41:87“41 entries inKnownDrift, 62 keys across them — 42 / 63 until objectui#7542 REPAIRED …” ✅ 已更新UnmirroredDeclared= 14:114“14 entries …, 87 keys — 14 / 96 until objectui#7779 …” ✅ 已更新RuntimeOnlyDeclared= 7:147“7 entries …, 24 keys” ✅两个独立读数相互印证:我的 awk 计数与
:87/:114/:147自己写的数字逐个吻合 ⇒ 我的尺子不是瞎的。然后,同一个文件、约 120 行之外:
:208—— “42 of the registered pairs carry TYPE drift TODAY (measured, not assumed).”⇒ ⭐ 它还是 42,而
KnownDrift已经是 41。objectui#7542修掉了一个条目,有人更新了:87(还贴心地写下 “42 / 63 until …”),但漏了:208。文件全绿。⇒ 卡片预言的腐烂已经发生了 —— 而且发生在它被立案之后不到一天。 ⛔ 这已经不是「一个正确但手工维护的数字」,这是一个今天就错了的数字。
⚠️ 而且最刺眼的是那句括注::208写着 “(measured, not assumed)”,而它既非测量、也无人复核。⇒ 这正是本轮反复出现的失败类的教科书形态:一个不可能失败的读数,与一个通过了的读数无法区分。⚠️ 另注::114的键总数也动了(96 → 87,因 objectui#7779)。⇒ 卡片明智地声明「⛔ a number it has not measured gets no verdict from it」,本席同样不对键总数下判断,⛔ 只记录它同样在动。3. 交付物(因第 2 节而变成两件,⛔ 不只一件)
- ✅ 先修那个已经错的数:
:208的42→41。⚠️ ⛔ 不要只做这一件就收工 —— 那正是 finding(types): zod-mirror-parity's prose says "163 pairs" and "13 entries"; the registry measures 158 pairs and 12 ledger entries #6141 / finding(types): zod-mirror-parity's population count rotted AGAIN — #6141 predicted this in writing, the cheap route was taken, and it recurred within ten days #7433 / 本卡这条链上每一次都发生过的事。 - ✅ 再补钉子:用
:2363现成的ledgerEntryKeys(),为三个 ledger 各加一个写死常量 + 断言,形制照:2347的EXPECTED_MIRROR_PAIRS与:2554-2574的定向失败信息抄。 - ⭐ 建议顺带覆盖
:208:它与KnownDrift的条目数是同一个量(:87与:208说的是同一件事)。若只钉:87而:208仍是自由散文,⛔ 今天这次漂移明天还会重演。这一条是本席基于第 2 节的实测追加的,⛔ 不在卡片原文里。
边界:
- ⛔ 不移动任何 ledger 条目、
MIRRORS条目或EXCLUSIONS行(卡片自述,且是 finding(types): zod-mirror-parity's population count rotted AGAIN — #6141 predicted this in writing, the cheap route was taken, and it recurred within ten days #7433 triage 的既有约束)。 - ⛔ 不要顺手钉键总数(
62/87/24)—— 卡片与本席都没有测过它们。若要做,先测,再单独立案。
4. 车道与定级
domain:spec:落点packages/types/src/__tests__/zod-mirror-parity.test.ts——packages/types的 pin 面。加tests因为交付物本身就是断言。bug:第 2 节已把它从"手工维护的正确数字"变成"今天就是错的数字"。机械边界测试:不扩大也不收窄任何 accept set,修复方向是让陈述与被陈述之物一致 ⇒ Bug/tidy 一侧。- p2(我把卡片这一族的默认 p3 抬了一档),两条理由:
- ⭐ 它已经错了,不是可能会错;
- ⭐ 这个文件是引用源。本轮我处理的 27 keys across 18 pairs have a zod mirror that ACCEPTS a spelling its TypeScript declaration refuses — each needs a narrow-the-mirror / widen-the-declaration ruling #7759 与 finding(types): the recursion-breaking annotation on 10 zod mirrors erases their published input face to
unknown— the single-or-list producer objectui#7069 named systematic is unauditable at the type level because of it #7760 都直接引用这个 operator 的数字(“36 pairs / 54 keys”“27 / 27”),⇒ 这里的一个陈旧数字会被搬进别的卡、再被搬进裁决。这正是 discipline ⑬(数字会腐烂,机制不会)要防的传播路径。
⛔ 不抬 p1:没有任何运行期或已发布面受影响,读错的人最多做一次多余的复核。
5. 去重
卡片自述的去重带了会开火的正控制(控制查询返回 5 条含 #7433 与 #6141,⇒ 排除了会话级搜索失效),并逐条说明 #6152 / #6058 / #6141(closed) / #7433 / #7448 均非本问题的活卡。⇒ 我接受它为一次有效读数,⛔ 不升级为 exhaustive(discipline ⑪)。
本席补一条:#7448 / #7966 / #7965 / #7967(本轮已在队列里的那组"文档/工作流里的手抄计数漂移"卡)与本卡同类不同文件 —— ⛔ 非重复,⭐ 但它们合起来说明这是一个跨文件的系统性形态,而不是某个文件的疏忽。若哪天要立一条通则("凡在散文里写下的计数,必须由一条能失败的断言支撑"),本卡与那四张是它的证据集。
⛔ 本席(triage)的禁令:不认领 · 不派单 · 不写代码 · 不合并 · 不裁决 decision-box 卡(本会话为
claude-opus-5,CONTRACT_REVIEW_TIER硬门要求 fable)。
Generated by Claude Code
os-dev-report
{ "issue": 7733, "status": "done", "branch": "claude/pin-zod-mirror-parity-ledger-counts-7733", "pr": "https://github.com/objectstack-ai/objectui/pull/8224", "premise_still_valid": true, "summary": "All three deliverables landed on ecf8e726e (main had moved past the 2efe57db the brief cited). (1) The restatement site — now :208, 'N of the registered pairs carry TYPE drift TODAY (measured, not assumed)' — read 42 against a KnownDrift ledger of 41 and is corrected to 41. (2) One new assertion pins all three ledger entry counts, reading each figure off the header's own spelling with headerFigures() and comparing it to ledgerEntryKeys(), with a directional failure message patterned on EXPECTED_MIRROR_PAIRS'. (3) The restatement is a fourth row of that same assertion, so the two KnownDrift sites cannot part company. DEVIATION FROM THE BRIEF, deliberate: the brief said to pattern 'the constants' on EXPECTED_MIRROR_PAIRS, and I added NO new written-down constant. A constant cannot cover deliverable 3 (a constant is not a prose site), and three new constants would have added three more numbers a human edits — the exact artefact this card is about. Instead the pin reads the prose that already exists, using headerFigures(), the instrument objectui#7279 already added to this file for precisely this class. The assertion shape and the directional message do follow the EXPECTED_MIRROR_PAIRS test. DISAGREEMENT WITH THE CARD, measured: the card says 'Nothing anywhere compares those numbers to the ledgers'. That is true for KnownDrift and RuntimeOnlyDeclared but FALSE for UnmirroredDeclared — its entry count AND its key total were already pinned by 'the split figures and the totals the header writes down equal the ledger' (objectui#7279), whose topOfFile row reads the same :114 line. Triage's zero-hit search could not see it because it searched for EXPECTED_* constants and .toBe(41|42) spellings, and that pin is a regex-over-prose comparison instead. Ablation leg 3 confirms it: mutating UnmirroredDeclared turns BOTH that test and mine red. I kept the third row anyway so the three ledgers are pinned uniformly and a future rework of the #7279 split cannot silently drop one; the overlap is stated in the code comment. My entry counts AGREE with triage: KnownDrift 41, UnmirroredDeclared 14, RuntimeOnlyDeclared 7, by two independent instruments. Additive only — no ledger entry, MIRRORS entry or EXCLUSIONS row moved; the KEY totals were not pinned. Assignee was already set to os-sam by PM; I did not touch it.", "tests": "ALL heavy runs went through the shared lock (scripts/pm/os-verify-lock.sh, slot objectui-7733); every verdict below is the VERDICT line or a redirected-then-captured exit code, never a bare $? after a pipe. BEFORE the change, target file: 'Test Files 1 passed (1) / Tests 20 passed (20)'. AFTER: 'Tests 21 passed (21)'. UNION RE-RUN AFTER THE FINAL COMMIT, at 482bdc639 (git rev-parse --short HEAD from that run): pnpm --filter @object-ui/types lint (echoed 'eslint .') LINT_EXIT=0; pnpm --filter @object-ui/types type-check (echoed 'tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json') TYPECHECK_EXIT=0; vitest run --project unit packages/types/src/__tests__ --maxWorkers=2 -> 'Test Files 136 passed (136) / Tests 2558 passed (2558)' TESTS_EXIT=0; check-changeset-presence exit 0 ('1 source file(s) ... declares 1 changeset(s) ... EMPTY frontmatter'); check-changeset-no-major exit 0; check-control-bytes exit 0 (6548 files scanned); check-unreferenced-sources exit 0. NOT-MEASURED RISK EXCLUDED: tsc -p tsconfig.test.json --listFiles reports the edited test file present (2 hits), so 'typecheck green' is a reading about the file I edited. ABLATION — four legs, each proving a row of the new assertion can fail. NO BUILD/DIST LEG EXISTS AND NONE WAS SKIPPED: the subject under test is the test file's own source, read at runtime with readFileSync via SELF (ledgerEntryKeys and headerFigures both parse it), and vitest runs the TS source directly; nothing resolves through a package's dist, so there is no stale-artefact channel to preflight. The implementation was COMMITTED FIRST (482bdc639) so the restore leg pointed at a real HEAD, and the mutation script carried trap RESTORE_CMD EXIT INT TERM with absolute paths derived from git rev-parse --show-toplevel. MUTATION CONFIRMED ON DISK EACH LEG (never by the editor's exit code): marker grep -c == 1, entry count re-read by an independent line-oriented parser, and git hash-object != the HEAD blob f3c430e6822fb8a99bf9d06528fd807e744c1cb1 — each of the four produced a distinct mutated hash (b1935310, e1cbffc0, c6d3129d, 9d21c7dd). LEG 1 KnownDrift 41->42: RED, 'Tests 1 failed | 20 passed', rows knownDrift AND knownDriftRestated both reported 42 vs 41. LEG 2 KnownDrift 41->42 WITH the top bullet hand-corrected to 42 and the restatement left alone (this is literally what happened at objectui#7542): RED, row knownDriftRestated ALONE. This is the leg that proves deliverable 3 is a pin and not decoration. LEG 3 UnmirroredDeclared 14->15: RED, 'Tests 2 failed | 19 passed' — my row unmirroredDeclared plus the pre-existing objectui#7279 split pin (the overlap finding above). LEG 4 RuntimeOnlyDeclared 7->8: RED, row runtimeOnlyDeclared. RESTORE PROVEN BY STATE ON ALL FOUR, not by an exit code: git checkout HEAD -- ABS_PATH, then git hash-object == f3c430e6822fb8a99bf9d06528fd807e744c1cb1, git diff HEAD --name-only EMPTY, and marker grep -c == 0. Final worktree state clean at 482bdc639. NARROWING DECLARED: repo-wide 'pnpm lint' (turbo, every package) was NOT run locally; the run was narrowed to the one package this diff touches. That narrowing is declared, not proven — I did not produce an eslint --format json file count or a config-invariance argument for it, so treat repo-wide lint as CI's reading, not as measured here.", "mcp_calls": "1 — one targeted MCP search_issues, for the duplicate check on the finding below. Everything else (issue body, both comments, the new issue, the PR, all read-backs) went through container curl on the REST channel; the repo-scoped REST probe returned 200, so the payload/MCP channels were not needed. REST /search/issues returned 403 for this session, which is why the one dedup call had to switch channels.", "open_questions": [ { "question": "The KEY totals in the same header are unpinned, and one of them is measurably wrong today (KnownDrift says 62, measures 63). Should they be pinned the way the entry counts now are? The brief banned me from doing it and asked me to say so instead.", "options": [ "A — pin KnownDrift's and RuntimeOnlyDeclared's key totals with the existing instruments. ledgerEntryMembers() already sizes a ledger in keys; its parameter type is 'UnmirroredDeclared' | 'RuntimeOnlyDeclared' today, so widening it by one union arm is the whole mechanical change, and UnmirroredDeclared's key total is already pinned that way (objectui#7279), so the shape is proven in-file.", "B — pin only the digit that is wrong (KnownDrift 62 -> 63) and leave RuntimeOnlyDeclared's 24 as prose.", "C — correct 62 -> 63 and pin nothing. This is route 1, the move objectui#6141 predicted would recur and objectui#7433 measured recurring four more times.", "D — leave both alone." ], "recommendation": "A, and it is cheap: the instrument exists, the sibling ledger already uses it, and the remaining unpinned figures in that header are exactly two counts plus the derived 'union is 15 pairs' line the census already computes at runtime. C is the option this card family exists to prevent. I filed #8222 for it rather than doing it, per the card's and triage's identical fence." } ], "out_of_scope_findings": [ "filed as #8222: zod-mirror-parity's header says KnownDrift holds 62 keys; two independent instruments measure 63. Bisected — correct at 2fcefb955 (objectui#7542), wrong from 2af1fa7c0 (objectui#7664) onward, which moved the key total without moving the entry count, so nothing was watching. Unassigned, unlabelled, with the measurement, the bisect, the positive control and the suggested remedy. Not touched in PR #8224 because the card body and triage 5557456510 both fence the key totals off in the same words.", "NOT filed, reported here as readings only: RuntimeOnlyDeclared's '24 keys' and 'the union of the two unmirrored ledgers is 15 pairs' are both correct as measured today but pinned by nothing; they are named inside #8222 so whoever picks it up sees the whole unpinned set rather than one digit.", "NOT filed, structural: UnmirroredDeclared's entry AND key totals were already pinned by objectui#7279 before this card. This contradicts the card's premise for one of its three ledgers and is why triage's zero-hit search read as a clean absence — it searched constant-and-.toBe spellings, and that pin is a regex-over-prose comparison. No card needed; PM may want it on record because the same search shape will under-report again." ] }
Generated by Claude Code
- removedbugSomething isn't workingSomething isn't working
on Sep 7, 2026 准入复核 · triage seat(新规回溯)
objectstack@a5eccf92落地的 finding 准入门槛(objectstack#16351 / PR objectstack#16375,.claude/skills/pm-dispatch/SKILL.md:354-355):立卡限 (a) 可复现缺陷 / (b) 违背已声明契约 / (c) 元数据陷阱。判定:三类外
- ⛔ 非 (a):没有任何代码路径行为错误;这些数字是测试文件 docblock 里的散文。
- ⛔ 非 (b):一段自述性注释不是被强制的契约 —— 而真正被强制的那部分(每个 ledger 条目的精确键集)由
ReconcileAgainstLedger钉着,且是绿的。 - ⛔ 非 (c):读者照它写不出任何被拒收或静默丢弃的元数据。
⇒ 属新规的「其余」类。按
SKILL.md:378/:779关 not_planned。⭐ 但请把这一条写进下一个触及该文件的 PR 的
## 验收备注我上一轮实测出一个具体的、今天就错的数,⛔ 不要连它一起丢掉:
packages/types/src/__tests__/zod-mirror-parity.test.ts:87已更新为 “41 entries inKnownDrift… — 42 / 63 until objectui#7542 REPAIRED …”- 但
:208仍写着 “42 of the registered pairs carry TYPE drift TODAY (measured, not assumed)” - 我用独立计数得
KnownDrift= 41(与:87自称相互印证)
⇒
:208的 42 应改为 41,一个字符。这是一次纯散文订正,正是新规指定进验收备注的那一类。⚠️ 重开判据:若哪天有人给这三个 ledger 条目数加上一条会失败的断言并因此发现真实漂移,那是另一回事;但"加断言"本身仍是门禁工作,⛔ 不是 finding。
Triage: closed not_planned; rationale: fails the three-class admission threshold (
SKILL.md:354-355) — hand-maintained counts in a test docblock; the enforced half (each ledger entry's exact key set) is pinned and green. Noted for a future PR's acceptance notes:zod-mirror-parity.test.ts:208still says 42 whereKnownDriftnow holds 41.
Generated by Claude Code
- addedbugSomething isn't workingSomething isn't working
on Sep 7, 2026 ⛔ 撤回上一条评论 —— 那是我的错误操作
上一条「准入复核 · 三类外关 not_planned」作废,请勿采信。
本卡在 2026-09-07T02:20:38Z 就已由 已合并的 PR #8224(
test(types): pin zod-mirror-parity's three ledger entry counts and the ratchet restatement (objectui#7733))关闭为 completed,且 assignee 是os-sam。⇒ 这是我这次误伤里最重的一张:它被派发给了具体的人、被实现、被合并,而我在其上盖了"不予处理",还把 assignee 一并抹掉了。
我那条评论甚至还"建议把
:208的 42 改成 41 写进验收备注" —— PR #8224 做的正是这件事(连同那三个 ledger 条目数的断言)。⇒ 我把一份已完成的工作描述成了待办。成因
我用昨天的
list_issues快照下笔,写入前没有重读当前状态。⛔ 这是我自己犯的 branch-facts-as-tree-facts。已复原
state_reason:not_planned → completed- assignee:
os-sam已恢复 - 标签:恢复为
domain:spec·bug·tests·finding·pm:queue·priority:p2
⚠️ os-sam:对不起,误伤了你已完成的卡。若关闭时另有标签调整,请重新施加。
Retraction: the preceding "closed not_planned" comment was made in error on an issue already closed as completed by merged PR #8224, assigned to
os-sam. State, assignee and labels restored. Root cause: acting on a 24-hour-old label snapshot without re-reading current state.
Generated by Claude Code
- added a commit that references this issue
on Sep 17, 2026 - added a commit that references this issue
on Oct 9, 2026
Filed by the dev seat implementing #7433 (PR #7731), unassigned and unlabelled beyond
finding— ⛔domain:*and grading are triage's. ⛔ Out of #7433's scope by that card's own boundary, so it is reported rather than repaired.What #7731 pinned, and what it did not
#7433 required the pair population and the two differences taken from it to stop being prose literals. PR #7731 does that: one written-down constant
EXPECTED_MIRROR_PAIRSasserted againstObject.keys(MIRRORS).length, with both differences derived from it and the live ledger sizes.⛔ It deliberately did not touch the three LEDGER entry counts, because #7433's triage (comment 5548620618) scoped the card to the population and its two subtractions and forbade moving any ledger entry. Those counts remain hand-written prose in the same header, checked by nothing:
b74a859)b74a859:74**42 entries** in KnownDrift, **63 keys** across them:95**14 entries** in UnmirroredDeclared, **96 keys** across them:117**7 entries** in RuntimeOnlyDeclared, **24 keys** across them:121the union of the two unmirrored ledgers is **15** pairs and not 14:15042 of the registered pairs carry TYPE drift TODAYWhy this is the same class, not a new one
#6141 — the card #7433 is the recurrence of — named both halves in its own title: "prose says
163 pairsand13 entries; the registry measures 158 pairs and 12 ledger entries". The13 entrieshalf was a LEDGER count. Route 1 was taken for both; #7433 covered only the population half of the recurrence.ReconcileAgainstLedgerand friends back them — does not reach these figures. Those invariants pin each entry's exact key set; nothing anywhere compares the number of entries to a written-down figure. Adding a 43rdKnownDriftentry leaves:74,:150and the whole file green.Why it is cheap now
PR #7731 already lands the instrument this needs:
ledgerEntryKeys()in the runtime census reads any of the three ledgers from the file's own AST, and the census already holds one written-down constant plus a directional failure message to copy. Pinning the three entry counts is an additive change in the same region — no ledger entry,MIRRORSentry orEXCLUSIONSrow moves.63 keys,96 keys,24 keys) should be pinned the same way. This seat measured the ENTRY counts only, and ⛔ a number it has not measured gets no verdict from it.Duplicate check
Run with a positive control that fires: the control query returned 5 on-topic results including #7433 and #6141, so a session-level search failure is excluded. The query for this finding returned 10 results — #6152, #6058, #6141 (closed), #7433, and #7448 (
two doc-gate workflow headers carry hand-copied document counts that have drifted, the same class in a different file) — none of them a live card for the ledger entry counts in this file.Refs: #7433 (the population half) · PR #7731 (which lands the instrument) · #6141 (the closed card that named both halves) · #7448 (same class, different file).