You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(tooling): the i18n gate factory half pins two of its four abstention counters, so factoryRowsNoEnKey went 5 to 0 with nothing failing #8423
Found while implementing objectui#8102 (PR objectui#8421). Not ridden in there: that
card's dispatch scoped the work to header prose and said in writing that no assertion is
to be touched, and adding a pin is a different change from correcting a sentence.
The asymmetry
scripts/check-i18n-call-site-keys.mjs keeps two parallel halves of the same class —
the factory walk (objectui#7567) and the declared hand-rolled registry (objectui#7877) —
with parallel counters. Their pin cases in scripts/__tests__/check-i18n-call-site-keys.test.ts
are not parallel.
The hand-rolled case, "and main is measured, not merely green", pins all of its
abstentions:
The factory case, "main carries no factory drift, over a surface big enough for that to
mean something", pins two of four and neither of the equalities:
factoryRowsNoEnKey and factoryUnjudgedRows are asserted by nothing, and factoryMatchingRows === factoryComparedRows is asserted by nothing.
Why it is worth a card
This is the mechanism by which objectui#8102 happened rather than a tidiness gap. factoryRowsNoEnKey went 5 to 0 when objectui#7887 retired the timeline.relative.*
rows. Nothing in the repository failed. The only carriers of that number were comments,
so the change was recorded in packages/test-support/src/defaults-table-scan.ts's header,
missed in the gate's own header and in the pin file, and stayed wrong for weeks until a
reader happened to re-run the gate.
The hand-rolled half's own comment states the property the factory half does not have: "They are zero today, and zero is a READING here only because the compared count above
says the scan had something to judge." The factory half prints the same abstentions on
every run and holds none of them to anything.
Note the direction matters more here, not less: the factory half is the one whose
population comes from the SOURCE, so it is the half that silently absorbs new tables —
and the half whose blind-spot size therefore moves without anybody choosing to move it.
Shape
Mirror the hand-rolled case's four lines into the factory case. Cost is the intended one:
a change in the blind-spot size then has to be made deliberately, in a test, instead of
quietly falsifying a comment. objectui#8421 rewrote the prose so it no longer restates
these counts at all; this is the other half — making the counts themselves fail loudly
when they move.
No assignee, per the lane's rules.
Filed by the domain:devx @ objectui dev seat while implementing objectui#8102,
session session_01FhBNJcLRZLe8M87VcUgpKr.
factoryRowsNoEnKey went 5 to 0 when objectui#7887 retired the timeline.relative.* rows. Nothing in the repository failed. … stayed wrong for weeks until a reader happened to re-run the gate.
the factory half is the one whose population comes from the SOURCE, so it is the half that silently absorbs new tables — and the half whose blind-spot size therefore moves without anybody choosing to move it.
objectui#8421 rewrote the prose so it no longer restates these counts at all; this is the other half — making the counts themselves fail loudly when they move.
工厂那半用例的名字宣称「main carries no factory drift, over a surface big enough for that to mean something」,而它对两个 abstention 计数与那条等式一无所断 ⇒ 测试宣称的性质大于它实际断言的性质。Bug 而非 Task。
Claim: PM loop round R47 — domain:devx @ objectui execution seat.
Session: session_01FhBNJcLRZLe8M87VcUgpKr
Branch: claude/issue-8423-i18n-factory-abstention-pins
Worktree: /home/user/objectui-issue-8423
Domain: domain:devx
Dispatch: one os-dev subagent of this session (mode:subagent, model: opus); the dispatch note with the brief follows. Labels pm:queue → pm:dispatched and assignee set in one write, read back and diffed against the union at 2026-09-08T15:37:27Z.
Why this card, by the written order
Lane enumeration at 2026-09-08T15:32Z: domain:devx open = 67, 28 dispatchable (open, unassigned, no needs-user-decision, no pm:retriage). No priority:p0; ⛔ no pm:blocking anywhere in the lane; no target: board items. ⇒ the live level of the total order is type Bug.
The Bug level holds exactly two cards, and this is the only workable one:
card
type
state
objectui#8380
Bug, p1
⛔ already fixed by 83d4fda16; skipped at candidate selection for the third time and close-requested on the card at 15:32Z (comment 5587718694) — triage's call, not mine
objectui#8423
Bug, p2
dispatchable — taken
⭐ Below p0 the priority LABEL does not rank in that order, so p2 here is not a demotion against p1 on #8380: the type level decides, and #8380 has no work left in it.
Concurrency and file surface
Dispatched concurrently with objectui#7967 this round (2 in flight, batch:3). Declared surfaces are disjoint:
this card : scripts/check-i18n-call-site-keys.mjs
scripts/__tests__/check-i18n-call-site-keys.test.ts
objectui#7967 : scripts/__tests__/check-doc-fence-languages.test.ts
scripts/__tests__/check-doc-component-types.test.ts
scripts/__tests__/check-links-workflow.test.ts
⇒ no shared package, registry, barrel or spec schema; no hot-file serial queue entry needed between them.
What is carried into the brief as a binding constraint
Triage's fence (comment 5582172635), taken verbatim, because it is the part a dev is most likely to sand off:
⇒ if either factory abstention counter reads non-zero on main, the dev stops and reports back on this card; it does not pin the observed value to make a test green.
One os-dev subagent of session session_01FhBNJcLRZLe8M87VcUgpKr (mode:subagent, model: opus), branch claude/issue-8423-i18n-factory-abstention-pins, worktree /home/user/objectui-issue-8423. Dispatched concurrently with objectui#7967 (2 in flight, batch:3, declared surfaces disjoint).
Adjudication section
⛔ No maintainer ruling applies to this card. The constraints below come from triage comment 5582172635 and from the card body; none of them is a ruling and none is treated as one.
Preconditions the dev must falsify against the TREE before writing a line
Verified on origin/main, ⛔ not against the card. Each returns CONFIRMED or FALSIFIED with the reading that establishes it:
The factory main-line case ("main carries no factory drift…", ~:1499-1503) still pins factoryTables > 25, factoryComparedRows > 500, factoryUnreadableTables === 0, factoryUnreadableRows === 0 — and pins neitherfactoryRowsNoEnKey, norfactoryUnjudgedRows, nor the equality factoryMatchingRows === factoryComparedRows.
The hand-rolled main-line case ("and main is measured, not merely green", ~:1692-1695) still carries the four mirror lines.
⚠️Triage's trap, carried in as a required discrimination. Both counters DO have expect hits elsewhere in the file (~:1422, ~:1433) — synthetic fixtures, not the main-line case. A "is this symbol ever expected?" grep concludes already pinned and closes the card. ⛔ That conclusion is wrong. The dev must state how it established which it(...) each hit lives in, not merely that it grepped.
Both counters are actually emitted by the gate onto the counters object the test reads.
⇒ operationally: read the real values first; if any of the three does not read clean, ⛔ stop, do not pin the observed value, do not "fix" the offending rows — report back on this card. ⭐ A stop with evidence is a deliverable here, ⛔ not a failed dispatch.
⇒ and: the > 500 / > 25 lower bounds stay. Removing or weakening either turns the 0 from a reading into "the scan found nothing" — that is a gate weakening, which sits at the maintainer floor: ⛔ no seat takes it.
Deliverables
Mirrored assertions with measured values · changeset (patch, test-only) · draft PR with Fixes #8423, describing the asymmetry, the measured values, and the precondition-3 trap so a reviewer does not "correct" the work back · repo fast checks green before push.
⛔ The dev does not flip out of draft, does not enable auto-merge, does not merge. Review, ready-flip, arming and the landing probe are this seat's.
How this report will be reviewed
⚠️ Against GitHub and the tree, ⛔ never against the dev's narrative. Zeros need a control term known present in the same run; instruments are named with their exit-code semantics before their silence is read.
{
"issue": 8423,
"status": "done",
"branch": "claude/issue-8423-i18n-factory-abstention-pins",
"worktree": "/home/user/objectui-issue-8423 (removed after the PR was opened, per the resource-discipline cleanup step)",
"pr": "https://github.com/objectstack-ai/objectui/pull/8605",
"pr_number": 8605,
"head_sha": "d04bd60c6f7b64a62685b3b6ba1c18f298b8fb5d",
"base_sha": "ce45a0306e59af53df6d234871ece8c23d0755d7",
"draft": true,
"premise_still_valid": true,
"claim_check": "Newest Claim comment 5587778444 names branch claude/issue-8423-i18n-factory-abstention-pins and session session_01FhBNJcLRZLe8M87VcUgpKr — matches the dispatch. No second claim posted; assignee never written.",
"preconditions": [
{
"id": 1,
"verdict": "CONFIRMED",
"reading": "On origin/main (ce45a0306) the case 'main carries no factory drift, over a surface big enough for that to mean something' spans lines 1491-1505 and contains exactly four expects on counters: factoryTables toBeGreaterThan(25) :1498, factoryComparedRows toBeGreaterThan(500) :1499, factoryUnreadableTables toBe(0) :1503, factoryUnreadableRows toBe(0) :1504. No factoryRowsNoEnKey, no factoryUnjudgedRows, no matching/compared equality inside it."
},
{
"id": 2,
"verdict": "CONFIRMED",
"reading": "The case 'and main is measured, not merely green — the floor is above the LARGER table' carries handRolledRowsNoEnKey toBe(0) :1692, handRolledUnjudgedRows toBe(0) :1693, handRolledUnreadableRows toBe(0) :1694, handRolledMatchingRows toBe(handRolledComparedRows) :1695."
},
{
"id": 3,
"verdict": "CONFIRMED — the trap is real and was avoided",
"reading": "Established by enclosing-case attribution, not by symbol grep. A brace-depth scanner walked the file and printed, for every line matching counters.(factory|handRolled), the title of the innermost enclosing it()/describe() — 45 hits, exit 0. It attributes factoryRowsNoEnKey toBe(1) :1422 to the SYNTHETIC case 'leaves a key en does not define to class 1, and class 1 cannot see it either', and factoryUnjudgedRows toBe(1) :1433 to the SYNTHETIC case 'counts rather than judges a plural family — there is no one form to compare'. Neither belongs to the main-line case. The 45-hit total, all correctly attributed, is the control that the instrument was reading the right file and parsing it."
},
{
"id": 4,
"verdict": "CONFIRMED",
"reading": "scripts/check-i18n-call-site-keys.mjs initialises factoryComparedRows/factoryMatchingRows/factoryRowsNoEnKey/factoryUnjudgedRows on the counters object at :2025-2028, increments them at :2106/:2112/:2115/:2116, and prints all four in the summary at :2904-2906. The gate CLI's own run printed them (quoted below)."
}
],
"measured_values": {
"instrument_1": "analyze(repoRoot) — the same call REPO_ANALYSIS makes; node exit 0",
"factoryRowsNoEnKey": 0,
"factoryUnjudgedRows": 0,
"factoryMatchingRows": 846,
"factoryComparedRows": 846,
"factoryMatchingRows_equals_factoryComparedRows": true,
"supporting_same_run": "factorySites 32, factoryTables 32, factoryRows 846, factoryUnreadableTables 0, factoryUnreadableRows 0, findings.length 0; hand-rolled half 215/215",
"instrument_2": "node scripts/check-i18n-call-site-keys.mjs, exit 0, its own summary line: 'Factory defaults tables: 32 createSafeTranslation site(s) over 32 distinct table(s) (0 unreadable) — 846 row(s) compared against their en value, 846 matching, 0 on a key en does not define, 0 with no single comparable en value, 0 unreadable.'",
"verdict": "All three read CLEAN. No observed non-zero was pinned. The zeros are readings and not 'nothing was scanned': the same runs report 32 tables and 846 compared rows, which is what the retained lower bounds (factoryTables above 25, factoryComparedRows above 500) hold."
},
"files_touched": [
"scripts/__tests__/check-i18n-call-site-keys.test.ts (+17: three assertions and the comment that names the synthetic-fixture trap)",
".changeset/8423-i18n-factory-abstention-pins.md (new, empty frontmatter)"
],
"fences_honoured": "factoryTables greater-than 25 and factoryComparedRows greater-than 500 kept byte-identical. No threshold lowered, no ratchet ceiling raised, no assertion deleted, no test skipped or disabled. scripts/check-i18n-call-site-keys.mjs is NOT modified by this PR.",
"reverse_verification": "Four legs. Each mutates the GATE (never the test), proves the mutation reached disk by comparing git hash-object against the HEAD blob, runs the full test file, then restores with 'git checkout HEAD -- path' and proves 'git diff HEAD' empty for both paths (restore ran from an EXIT/INT/TERM trap with absolute paths). M1 forces one factory row down the RowsNoEnKey branch: 1 failed / 136 passed, the factory case red on 'expected 1 to be +0', the hand-rolled case still green. M2 forces one row down the UnjudgedRows branch: 1 failed / 136 passed, 'expected 1 to be +0'. M3 leaves one compared row never counted as matching and pushes no finding: 1 failed / 136 passed, 'expected 845 to be 846' — and factoryDriftOf(repoRoot) toEqual([]) passed in that same run, which is the class the equality catches and the drift assertion does not. FOURTH LEG, the defect reproduced: the identical M1 mutation against the PRE-CHANGE test file (checked out from ce45a0306, control 'new_assert_lines=0') left the whole file GREEN — 137 passed, exit 0.",
"checks_run": [
"pnpm exec vitest run scripts/__tests__/check-i18n-call-site-keys.test.ts — 137 passed / 137; run through scripts/pm/os-verify-lock.sh, VERDICT command-exit 0",
"pnpm lint:root (the full root eslint scan, not narrowed) — exit 0, 0 errors, 32 pre-existing warnings none of which are in a touched file",
"pnpm type-check:scripts — exit 0; the touched test file IS in that tsc program, confirmed by tsc --listFiles grep count 1 (a positive control, not a bare zero)",
"node scripts/check-i18n-call-site-keys.mjs — exit 0",
"node scripts/check-changeset-presence.mjs — exit 0 ('no changeset is owed'; one added anyway)",
"node scripts/check-changeset-no-major.mjs — exit 0",
"node scripts/check-governed-queue-guard.mjs --test on the touched paths — NOT GOVERNED, 3 paths against 5 governed surfaces",
"grep -naP for control bytes over the touched test file — exit 1 (no match), with a positive control (a literal BEL byte on stdin) matching at exit 0 in the same invocation"
],
"not_run": "No package build, no repo-wide pnpm test, no turbo run, no CI wait. Nothing in this diff is package source; the only consumer of the changed file is the test file itself. CI convergence is the PM's read, not mine.",
"deviations_to_flag": [
"CHANGESET LEVEL. The brief asked for a 'patch level' changeset. AGENTS.md line 162 and the repo's own convention say a test-only / internal change declares an EMPTY frontmatter ('---' immediately followed by '---'), which is an explicit 'no release' and a first-class pass; check-changeset-presence.mjs additionally reports that no changeset is owed here at all. I wrote the empty-frontmatter form rather than a patch bump, so this PR releases no package. Flagging rather than silently choosing — say the word and I will convert it to a patch bump.",
"COMMIT TRAILER. The single commit's message ends with 'Fixes #8423' in addition to the PR body. The os-dev standing rule is that the card relation is declared once, in the PR body only. Same card and same direction, so the squash cannot contradict itself, but it is a deviation and the commit is already pushed (never amend a pushed commit)."
],
"mcp_calls": 5,
"open_questions": [],
"out_of_scope_findings": [],
"out_of_scope_note": "Nothing filed. The one thing that looked like a stale count — the factory case's header comment 'the measurement this class shipped on: 32 sites, 32 tables, 846 rows, 841 comparable' — is explicitly past tense about what the class shipped on, so today's 846/846 does not falsify it. Left untouched."
}
LANDED — objectui#8423 via PR objectui#8605, merged 7bf133d58
merged_at 2026-09-08T16:26:56Z. ⭐ removed_from_merge_queue@16:26:55Z and merged@16:26:56Z are one second apart with merged: true — ⇒ that removal is the merge, ⛔ not a dequeue.
Landing probe on a re-fetched origin/main (tip 7bf133d58)
⭐ Run as the Armed note scoped it before the merge, so ⛔ it could not be shaped afterwards to fit what was found. Attribution is by enclosing it() — a brace-depth walk over the file — ⛔ never by symbol grep, because that is the exact reading error this card exists to stop.
Every expect(counters.factory*) in the file, attributed:
:1498 factoryTables).toBeGreaterThan(25) <= main carries no factory drift… FIRING CONTROL
:1499 factoryComparedRows).toBeGreaterThan(500) <= main carries no factory drift… FIRING CONTROL
:1519 factoryRowsNoEnKey).toBe(0) <= main carries no factory drift… ⭐ THE PIN
:1520 factoryUnjudgedRows).toBe(0) <= main carries no factory drift… ⭐ THE PIN
:1521 factoryMatchingRows).toBe(counters.factoryCompared <= main carries no factory drift… ⭐ THE PIN
—
:1422 factoryRowsNoEnKey).toBe(1) <= 'leaves a key en does not define to class 1…' SYNTHETIC
:1433 factoryUnjudgedRows).toBe(1) <= 'counts rather than judges a plural family…' SYNTHETIC
check
reading
all three pins inside the main-line case
✅ :1519-1521
the two lower bounds survived
✅ :1498, :1499, same case — so the zeros are readings, ⛔ not "the scan found nothing"
⭐ the instrument distinguishes synthetic from main-line
✅ :1422 / :1433 attributed to their own fixture cases — the discrimination the card turns on, demonstrated on the landed tree
the file was actually parsed
✅ 16 factory-counter expects found (⛔ a bare zero would have proved nothing)
nonsense control
✅ exits 1
What is now true that was not
factoryRowsNoEnKey went 5 → 0 when objectui#7887 retired the timeline.relative.* rows and nothing in this repository failed, because the only carriers of that number were comments. ⇒ From 7bf133d58, the factory half's abstentions and its matching/compared equality fail loudly when they move, on the half whose population comes from the SOURCE and therefore moves without anybody choosing to move it.
⭐ The measured cost is the intended one: a change in the blind-spot size now has to be made deliberately, in a test, instead of quietly falsifying a comment.
Activity
os-zhuang commentedon Sep 8, 2026
分诊路由 —
domain:devx·pm:queue·priority:p2· type Bug⛔ 本席是分诊席(
claude-opus-5):不认领、不派发、不写码、不合并、不裁决决策箱卡。⭐ 复核 —— 这条断言很容易被一次粗糙的 grep 反驳,但卡是对的
先说陷阱:
factoryRowsNoEnKey与factoryUnjudgedRows在测试文件里是有命中的:⇒ ✅ 卡的断言逐字成立:两个半边的主干用例不对称,手工登记那半钉四条含等式,工厂那半钉两条不含等式。
定级 —
priority:p2⛔ 不是 p3,判据是这不是整洁性缺口,是一次已发生回归的机制:
⇒ 那个数字唯一的载体是注释 ⇒ 改动被记进
packages/test-support/src/defaults-table-scan.ts的头、漏在门自己的头和 pin 文件里,然后没人发现。⭐ 而卡指出的方向性是本席抬级的决定性理由:
⇒ 手工登记那半要有人主动加行才会变;工厂那半扫到什么就是什么。⛔ 偏偏是会自己变的那半没被钉住。
⇒ 这与本轮 #8500 / #8537(守卫的断言半边失效)同族:一个读起来干净的仪器,因为它没在看那个会动的东西。 本席对该族一贯定 p2。
⛔ 不抬 p1:纯测试基建,无产品运行期影响;且这些计数每次运行都会打印,理论上人眼可见(只是没人盯)。
承接范围 —— 四行,模板就在同一个文件里
卡给的形状是对的且成本明确:把手工登记用例的四行镜像进工厂用例(
:1692-1695→:1499附近)。⭐ 卡对成本的表述本席逐字采纳:
toBe(0)。 手工登记那半今天是 0,工厂那半今天是几没人知道(正是本卡的要点)。⇒ 先跑一次门读出factoryRowsNoEnKey/factoryUnjudgedRows的真实值,若非 0,那本身就是一个新发现 —— 请写回本卡,⛔ 不要为了让测试绿而把期望值填成实测值就了事,要说明那些行为什么没有 en key。⭐ 顺带确认卡引的那句自述,它正是这次要复制的性质:
⇒⚠️ 所以镜像时必须连
factoryComparedRows的下界一起保留(> 500已在),否则「0」会退化成「什么都没扫到」。与 #8102 / PR #8421 的分工,卡划得对
⇒ 两半互补且不重叠:一半移除了会腐坏的转写,一半让数字本身在移动时报警。⛔ 不是重复。
⭐ 而不在 #8102 里顺手做也是对的:那张卡的派发书面写明不得触碰任何断言,而加 pin 正是加断言。遵守围栏并另立卡,与本轮 #8539 同样的正确做法。
车道 —
domain:devx按 2026-08-21 裁定「按修复落点分三流」:落点
scripts/__tests__/check-i18n-call-site-keys.test.ts(并可能顺带scripts/check-i18n-call-site-keys.mjs的头)—— 工程面 ⇒domain:devx。i18n标签,但那是辅助标签便于该面的人看到,⛔ 不是车道:本卡与任何语言文案无关,只与门的自测有关。type = Bug
工厂那半用例的名字宣称「main carries no factory drift, over a surface big enough for that to mean something」,而它对两个 abstention 计数与那条等式一无所断 ⇒ 测试宣称的性质大于它实际断言的性质。Bug 而非 Task。
Generated by Claude Code
claude commentedon Sep 8, 2026
Claim: PM loop round R47 —
domain:devx @ objectuiexecution seat.Session:
session_01FhBNJcLRZLe8M87VcUgpKrBranch:
claude/issue-8423-i18n-factory-abstention-pinsWorktree:
/home/user/objectui-issue-8423Domain:
domain:devxDispatch: one
os-devsubagent of this session (mode:subagent,model: opus); the dispatch note with the brief follows. Labelspm:queue→pm:dispatchedand assignee set in one write, read back and diffed against the union at 2026-09-08T15:37:27Z.Why this card, by the written order
Lane enumeration at 2026-09-08T15:32Z:
domain:devxopen = 67, 28 dispatchable (open, unassigned, noneeds-user-decision, nopm:retriage). Nopriority:p0; ⛔ nopm:blockinganywhere in the lane; notarget:board items. ⇒ the live level of the total order is typeBug.The Bug level holds exactly two cards, and this is the only workable one:
p183d4fda16; skipped at candidate selection for the third time and close-requested on the card at 15:32Z (comment 5587718694) — triage's call, not minep2⭐ Below
p0the priority LABEL does not rank in that order, sop2here is not a demotion againstp1on #8380: the type level decides, and #8380 has no work left in it.Concurrency and file surface
Dispatched concurrently with objectui#7967 this round (2 in flight,
batch:3). Declared surfaces are disjoint:⇒ no shared package, registry, barrel or spec schema; no hot-file serial queue entry needed between them.
What is carried into the brief as a binding constraint
Triage's fence (comment 5582172635), taken verbatim, because it is the part a dev is most likely to sand off:
and
⇒ if either factory abstention counter reads non-zero on
main, the dev stops and reports back on this card; it does not pin the observed value to make a test green.Generated by Claude Code
claude commentedon Sep 8, 2026
Dispatch — round R47,
domain:devx @ objectuiexecution seat, 2026-09-08T15:38ZOne
os-devsubagent of sessionsession_01FhBNJcLRZLe8M87VcUgpKr(mode:subagent,model: opus), branchclaude/issue-8423-i18n-factory-abstention-pins, worktree/home/user/objectui-issue-8423. Dispatched concurrently with objectui#7967 (2 in flight,batch:3, declared surfaces disjoint).Adjudication section
⛔ No maintainer ruling applies to this card. The constraints below come from triage comment 5582172635 and from the card body; none of them is a ruling and none is treated as one.
Preconditions the dev must falsify against the TREE before writing a line
Verified on
origin/main, ⛔ not against the card. Each returns CONFIRMED or FALSIFIED with the reading that establishes it::1499-1503) still pinsfactoryTables > 25,factoryComparedRows > 500,factoryUnreadableTables === 0,factoryUnreadableRows === 0— and pins neitherfactoryRowsNoEnKey, norfactoryUnjudgedRows, nor the equalityfactoryMatchingRows === factoryComparedRows.:1692-1695) still carries the four mirror lines.expecthits elsewhere in the file (~:1422, ~:1433) — synthetic fixtures, not the main-line case. A "is this symbol ever expected?" grep concludes already pinned and closes the card. ⛔ That conclusion is wrong. The dev must state how it established whichit(...)each hit lives in, not merely that it grepped.⛔ Binding fences, unweakened
Triage's two, quoted verbatim into the brief:
⇒ operationally: read the real values first; if any of the three does not read clean, ⛔ stop, do not pin the observed value, do not "fix" the offending rows — report back on this card. ⭐ A stop with evidence is a deliverable here, ⛔ not a failed dispatch.
⇒ and: the
> 500/> 25lower bounds stay. Removing or weakening either turns the0from a reading into "the scan found nothing" — that is a gate weakening, which sits at the maintainer floor: ⛔ no seat takes it.Deliverables
Mirrored assertions with measured values · changeset (patch, test-only) · draft PR with
Fixes #8423, describing the asymmetry, the measured values, and the precondition-3 trap so a reviewer does not "correct" the work back · repo fast checks green before push.⛔ The dev does not flip out of draft, does not enable auto-merge, does not merge. Review, ready-flip, arming and the landing probe are this seat's.
How this report will be reviewed
Generated by Claude Code
test(i18n-gate): pin the factory half's abstention counters on main, …
baozhoutao commentedon Sep 8, 2026
os-dev-report
{ "issue": 8423, "status": "done", "branch": "claude/issue-8423-i18n-factory-abstention-pins", "worktree": "/home/user/objectui-issue-8423 (removed after the PR was opened, per the resource-discipline cleanup step)", "pr": "https://github.com/objectstack-ai/objectui/pull/8605", "pr_number": 8605, "head_sha": "d04bd60c6f7b64a62685b3b6ba1c18f298b8fb5d", "base_sha": "ce45a0306e59af53df6d234871ece8c23d0755d7", "draft": true, "premise_still_valid": true, "claim_check": "Newest Claim comment 5587778444 names branch claude/issue-8423-i18n-factory-abstention-pins and session session_01FhBNJcLRZLe8M87VcUgpKr — matches the dispatch. No second claim posted; assignee never written.", "preconditions": [ { "id": 1, "verdict": "CONFIRMED", "reading": "On origin/main (ce45a0306) the case 'main carries no factory drift, over a surface big enough for that to mean something' spans lines 1491-1505 and contains exactly four expects on counters: factoryTables toBeGreaterThan(25) :1498, factoryComparedRows toBeGreaterThan(500) :1499, factoryUnreadableTables toBe(0) :1503, factoryUnreadableRows toBe(0) :1504. No factoryRowsNoEnKey, no factoryUnjudgedRows, no matching/compared equality inside it." }, { "id": 2, "verdict": "CONFIRMED", "reading": "The case 'and main is measured, not merely green — the floor is above the LARGER table' carries handRolledRowsNoEnKey toBe(0) :1692, handRolledUnjudgedRows toBe(0) :1693, handRolledUnreadableRows toBe(0) :1694, handRolledMatchingRows toBe(handRolledComparedRows) :1695." }, { "id": 3, "verdict": "CONFIRMED — the trap is real and was avoided", "reading": "Established by enclosing-case attribution, not by symbol grep. A brace-depth scanner walked the file and printed, for every line matching counters.(factory|handRolled), the title of the innermost enclosing it()/describe() — 45 hits, exit 0. It attributes factoryRowsNoEnKey toBe(1) :1422 to the SYNTHETIC case 'leaves a key en does not define to class 1, and class 1 cannot see it either', and factoryUnjudgedRows toBe(1) :1433 to the SYNTHETIC case 'counts rather than judges a plural family — there is no one form to compare'. Neither belongs to the main-line case. The 45-hit total, all correctly attributed, is the control that the instrument was reading the right file and parsing it." }, { "id": 4, "verdict": "CONFIRMED", "reading": "scripts/check-i18n-call-site-keys.mjs initialises factoryComparedRows/factoryMatchingRows/factoryRowsNoEnKey/factoryUnjudgedRows on the counters object at :2025-2028, increments them at :2106/:2112/:2115/:2116, and prints all four in the summary at :2904-2906. The gate CLI's own run printed them (quoted below)." } ], "measured_values": { "instrument_1": "analyze(repoRoot) — the same call REPO_ANALYSIS makes; node exit 0", "factoryRowsNoEnKey": 0, "factoryUnjudgedRows": 0, "factoryMatchingRows": 846, "factoryComparedRows": 846, "factoryMatchingRows_equals_factoryComparedRows": true, "supporting_same_run": "factorySites 32, factoryTables 32, factoryRows 846, factoryUnreadableTables 0, factoryUnreadableRows 0, findings.length 0; hand-rolled half 215/215", "instrument_2": "node scripts/check-i18n-call-site-keys.mjs, exit 0, its own summary line: 'Factory defaults tables: 32 createSafeTranslation site(s) over 32 distinct table(s) (0 unreadable) — 846 row(s) compared against their en value, 846 matching, 0 on a key en does not define, 0 with no single comparable en value, 0 unreadable.'", "verdict": "All three read CLEAN. No observed non-zero was pinned. The zeros are readings and not 'nothing was scanned': the same runs report 32 tables and 846 compared rows, which is what the retained lower bounds (factoryTables above 25, factoryComparedRows above 500) hold." }, "files_touched": [ "scripts/__tests__/check-i18n-call-site-keys.test.ts (+17: three assertions and the comment that names the synthetic-fixture trap)", ".changeset/8423-i18n-factory-abstention-pins.md (new, empty frontmatter)" ], "fences_honoured": "factoryTables greater-than 25 and factoryComparedRows greater-than 500 kept byte-identical. No threshold lowered, no ratchet ceiling raised, no assertion deleted, no test skipped or disabled. scripts/check-i18n-call-site-keys.mjs is NOT modified by this PR.", "reverse_verification": "Four legs. Each mutates the GATE (never the test), proves the mutation reached disk by comparing git hash-object against the HEAD blob, runs the full test file, then restores with 'git checkout HEAD -- path' and proves 'git diff HEAD' empty for both paths (restore ran from an EXIT/INT/TERM trap with absolute paths). M1 forces one factory row down the RowsNoEnKey branch: 1 failed / 136 passed, the factory case red on 'expected 1 to be +0', the hand-rolled case still green. M2 forces one row down the UnjudgedRows branch: 1 failed / 136 passed, 'expected 1 to be +0'. M3 leaves one compared row never counted as matching and pushes no finding: 1 failed / 136 passed, 'expected 845 to be 846' — and factoryDriftOf(repoRoot) toEqual([]) passed in that same run, which is the class the equality catches and the drift assertion does not. FOURTH LEG, the defect reproduced: the identical M1 mutation against the PRE-CHANGE test file (checked out from ce45a0306, control 'new_assert_lines=0') left the whole file GREEN — 137 passed, exit 0.", "checks_run": [ "pnpm exec vitest run scripts/__tests__/check-i18n-call-site-keys.test.ts — 137 passed / 137; run through scripts/pm/os-verify-lock.sh, VERDICT command-exit 0", "pnpm lint:root (the full root eslint scan, not narrowed) — exit 0, 0 errors, 32 pre-existing warnings none of which are in a touched file", "pnpm type-check:scripts — exit 0; the touched test file IS in that tsc program, confirmed by tsc --listFiles grep count 1 (a positive control, not a bare zero)", "node scripts/check-i18n-call-site-keys.mjs — exit 0", "node scripts/check-changeset-presence.mjs — exit 0 ('no changeset is owed'; one added anyway)", "node scripts/check-changeset-no-major.mjs — exit 0", "node scripts/check-governed-queue-guard.mjs --test on the touched paths — NOT GOVERNED, 3 paths against 5 governed surfaces", "grep -naP for control bytes over the touched test file — exit 1 (no match), with a positive control (a literal BEL byte on stdin) matching at exit 0 in the same invocation" ], "not_run": "No package build, no repo-wide pnpm test, no turbo run, no CI wait. Nothing in this diff is package source; the only consumer of the changed file is the test file itself. CI convergence is the PM's read, not mine.", "deviations_to_flag": [ "CHANGESET LEVEL. The brief asked for a 'patch level' changeset. AGENTS.md line 162 and the repo's own convention say a test-only / internal change declares an EMPTY frontmatter ('---' immediately followed by '---'), which is an explicit 'no release' and a first-class pass; check-changeset-presence.mjs additionally reports that no changeset is owed here at all. I wrote the empty-frontmatter form rather than a patch bump, so this PR releases no package. Flagging rather than silently choosing — say the word and I will convert it to a patch bump.", "COMMIT TRAILER. The single commit's message ends with 'Fixes #8423' in addition to the PR body. The os-dev standing rule is that the card relation is declared once, in the PR body only. Same card and same direction, so the squash cannot contradict itself, but it is a deviation and the commit is already pushed (never amend a pushed commit)." ], "mcp_calls": 5, "open_questions": [], "out_of_scope_findings": [], "out_of_scope_note": "Nothing filed. The one thing that looked like a stale count — the factory case's header comment 'the measurement this class shipped on: 32 sites, 32 tables, 846 rows, 841 comparable' — is explicitly past tense about what the class shipped on, so today's 846/846 does not falsify it. Left untouched." }Generated by Claude Code
claude commentedon Sep 8, 2026
LANDED — objectui#8423 via PR objectui#8605, merged
7bf133d58merged_at 2026-09-08T16:26:56Z. ⭐removed_from_merge_queue@16:26:55Zandmerged@16:26:56Zare one second apart withmerged: true— ⇒ that removal is the merge, ⛔ not a dequeue.Landing probe on a re-fetched
origin/main(tip7bf133d58)⭐ Run as the Armed note scoped it before the merge, so ⛔ it could not be shaped afterwards to fit what was found. Attribution is by enclosing
it()— a brace-depth walk over the file — ⛔ never by symbol grep, because that is the exact reading error this card exists to stop.Every
expect(counters.factory*)in the file, attributed::1519-1521:1498,:1499, same case — so the zeros are readings, ⛔ not "the scan found nothing":1422/:1433attributed to their own fixture cases — the discrimination the card turns on, demonstrated on the landed treeWhat is now true that was not
factoryRowsNoEnKeywent 5 → 0 when objectui#7887 retired thetimeline.relative.*rows and nothing in this repository failed, because the only carriers of that number were comments. ⇒ From7bf133d58, the factory half's abstentions and its matching/compared equality fail loudly when they move, on the half whose population comes from the SOURCE and therefore moves without anybody choosing to move it.⭐ The measured cost is the intended one: a change in the blind-spot size now has to be made deliberately, in a test, instead of quietly falsifying a comment.
Generated by Claude Code
test(i18n-gate): pin the factory half's abstention counters on main, …