Skip to content

test/docs-drift.test.ts is at 97.8% of the 100KB hygiene cap — the next rule added to it turns the gate red #1196

Description

@os-steve

Found while landing #1187. Filing rather than fixing: out of that card's scope.

Problem

test/docs-drift.test.ts is 100,190 bytes on main @ 540e4887. The cap in
scripts/check-source-hygiene.mjs is MAX_FILE_BYTES = 100 * 1024 = 102,400, so
the file has 2,210 bytes of headroom — 97.8% full.

That is not a hypothetical. #1187 asked for a new doc-drift rule and pointed it at
this file's "docs match the built stack" family, which is the right family for it.
Appending the rule took the file to 107KB:

✗ no source file over 100KB — 1 violation(s)
    test/docs-drift.test.ts:0  107KB
    → split the file — oversized modules defeat review

#1187 shipped its rule as a sibling test/docs-readme-token-figures.test.ts
instead, which is where most of that family already lives, so nothing is blocked
today. But the next author who reaches for this file — reasonably, because it is
the named home of the drift rules — pays a detour to discover the same thing.

Why this is worth a card rather than a shrug

Two closed precedents show the same condition being noticed only at the moment it
bites: #814 (test/metadata-references.test.ts, 817 bytes of headroom) and #635
(src/data/index.ts, ~1.5KB under). In both, the discovery cost landed on an
unrelated PR. The cap has no early warning: the gate is silent at 99% and red at
101%, so the signal arrives as a failed run on someone else's change.

Worth considering, in rough order of cost:

  1. Split docs-drift.test.ts along the seams it already has. It holds several
    independent describe families (the flow-threshold rules, the [17.0-rc2验收] README 与 marketplace 文档的对象/flow 数量仍是旧值(15 objects / 23 flows),rc.2 实际为 17 / 24 #729 count rule,
    the [17.0-rc2验收] objectstack.config.ts 的 engines.protocol 仍是 ^17.0.0-rc.1,与 objectstack.manifest.json(rc.2)及 build 产物不一致 #728 protocol-version rule, the docs/STATUS.md 的「当前状态」全表过期:对象/流程/仪表盘/动作计数、平台版本、测试规模无一与 main 相符 #1011 STATUS transcript rule), each with
    its own long header comment. Most would move out whole.
  2. Warn before failing. A hygiene advisory at, say, 90% of the cap would have
    surfaced all three instances of this while the fix was still cheap — the same
    shape as the token ratchet's re-anchor nag.

No behavior change either way; the tests all pass at their current size.

Not in scope here

The 100KB cap itself is well-argued and this is not a request to raise it.

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    and removed on Aug 25, 2026
  2. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    定级(首触)→ pm:queue。它现在还挡着 #1135,所以不是「等它咬人再说」。

    按本席常设授权定级。finding 同笔摘除。

    前提对 origin/main @ 6ed7b8d 重测

    $ wc -c test/docs-drift.test.ts       →  99,746
      cap (MAX_FILE_BYTES = 100 * 1024)   →  102,400
      headroom                            →   2,654 B   (97.4% 满)
    

    卡片记的是 100,190 / 2,210 余量;文件这期间小了一点,但结论一字未变:下一条规则塞进去就红。

    为什么晋级 —— 它已经不是假设了

    卡片说「nothing is blocked today」。那句话今天不成立了:本轮定级把 #1135 判进了队列,而 #1135 的可交付正是往 test/docs-drift.test.ts 里加断言(它要复用那里已有的 capCel 机器,那是正确的落点)。

    ⇒ 两张卡在同一个文件上硬串行,而顺序是确定的:#1196 先,#1135 后。反过来做,#1135 会在实施到一半时撞上 100KB 上限,然后面对一个它没被授权做的选择(拆文件 / 抬上限 / 换文件)—— 这正是 #814 和 #635 各自付过的账,卡片把它们列为先例。

    裁定:走选项 1(沿既有接缝拆分),⛔ 不抬上限

    拆分时的两条要求

    1. ⚠️ 拆完要留一张指路表。 test/metadata-references.test.ts 距 100KB hygiene 上限只剩 817 字节 —— 下一个往里加测试的 PR 会被 gate 拦住 #814 拆 metadata-references.test.ts 时留了 SPLIT BY FAMILY (#814) 一节逐族列出兄弟文件,那是对的做法 —— 但它也制造了 src/ 与 bulk-action-dispatch.test.ts 里 4 条「见 metadata-references.test.ts 的某守卫」的注释,指向的守卫已随 #814 拆分搬家(需多跳一次) #931(四条注释指向搬走了的守卫)。所以:拆分的同时,grep 全仓对被搬走的 describe 的引用并一并更新,⛔ 不要留给下一张卡。
    2. 拆完复测每个新文件的字节数并写进报告 —— 拆成两个 51KB 的文件等于什么都没解决。

    面:test/docs-drift.test.ts + 拆出的兄弟文件 + 指向它们的注释。⚠️ 这个文件是本仓最热的守卫文件之一,派发前查热文件队;#1135 明确排在本卡之后。

    先例:#814(metadata-references.test.ts,817 B 余量)· #635(src/data/index.ts,约 1.5KB)—— 两次都是在咬人的那一刻才被发现,代价落在无关的 PR 上。


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 25, 2026
  4. self-assigned this
    on Aug 25, 2026
  5. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    Claim: PM loop round 2
    Session: session_01STpYzSP2LiZwZinh6m6Qgf
    Branch: claude/issue-1196-docs-drift-split
    Worktree: hotcrm-issue-1196
    Domain: (hotcrm has no domain:* taxonomy — repo-wide seat, objectstack#10282)
    File surface: test/docs-drift.test.ts + the sibling test/*.test.ts files you split it into, + comments that reference the moved describes. ⛔ The reference sweep is fenced OUT of src/pages/**, src/actions/**, src/flows/** and src/translations/** — those are #1207's, dispatched in the same batch. If a reference lives there, report it, do not edit it (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus
    Clause-②: no — test-file reorganisation.
    Serial constraints cleared: 4 open PRs, all dependabot, none touching test/. Batch siblings #1207 (fenced above) and #1169 (.github/workflows/docs-app.yml) — disjoint. ⚠️ #1135 is pm:queue and is explicitly serialised BEHIND this card — it adds assertions to this very file and would hit the 100KB cap mid-implementation. ⛔ Do not implement #1135's assertions here.

    Read the full issue body and every comment on GitHub yourself before starting, and verify the body is not truncated.


    Ruling (⛔ not re-adjudicable)

    • ✅ Split along the seams the file already has (the card's option 1).
    • ⛔ Do NOT raise MAX_FILE_BYTES. The card says the 100KB cap is well-argued and is not asking for it to be raised; independently, raising a gate threshold is 门禁削弱 and sits on the maintainer floor — AI has a structural incentive to make CI green, so weakening the farm must be a human action. ⛔ Not negotiable, including "just this once for the split".
    • ⏭️ The 90%-of-cap advisory (the card's option 2) is NOT in this card. It is a capability change to scripts/check-source-hygiene.mjs, a different file and a different design. If you conclude the split will re-fill without it, report it and I will file it — ⛔ do not ride it along.

    Measured starting point (falsify if wrong)

    On origin/main @ 6ed7b8d:

    wc -c test/docs-drift.test.ts   →  99,746
    MAX_FILE_BYTES (100 * 1024)     → 102,400
    headroom                        →   2,654 B   (97.4% full)
    

    Twelve describe families, which are the seams:

    :196  package docs do not drift from the flows they document
    :318  maintainer docs do not point at directories that no longer exist
    :371  product docs do not point at directories that no longer exist
    :392  docs that draw the src/ tree only draw directories that exist
    :442  documented agent names resolve to a platform agent
    :568  the dashboards docs page lists tiles that exist
    :785  translated docs pages keep the English page callouts
    :882  the action example teaches a selection key the platform can deliver (#813)
    :989  product docs do not name a retired copilot persona (#612)
    :1190 the docs print the version the manifest declares (#612)
    :1421 one protocol version, declared in three files (#728)
    :1534 product docs state the metadata counts the stack registers (#729)
    

    ⚠️ How to group them into files is your judgement — the card names four independent families; the listing above shows twelve. Group by subject, keep each describe whole with its header comment, and say in the report why you grouped as you did.

    ⚠️ Two requirements the card does not state, and I do

    1. Grep the repo for references to the moved describes and update them in the same PR. test/metadata-references.test.ts 距 100KB hygiene 上限只剩 817 字节 —— 下一个往里加测试的 PR 会被 gate 拦住 #814 split metadata-references.test.ts and left a SPLIT BY FAMILY pointer table — good — but it also produced src/ 与 bulk-action-dispatch.test.ts 里 4 条「见 metadata-references.test.ts 的某守卫」的注释,指向的守卫已随 #814 拆分搬家(需多跳一次) #931: four comments still pointing at the old file, one of which is still stale today. ⛔ Do not create src/ 与 bulk-action-dispatch.test.ts 里 4 条「见 metadata-references.test.ts 的某守卫」的注释,指向的守卫已随 #814 拆分搬家(需多跳一次) #931's successor. Known referencing files include src/objects/_thresholds.ts, src/docs/*.md, test/helpers/*, test/sharing-coverage.test.ts, test/persona-copy.test.ts, test/docs-revenue-approvals-navigation.test.ts — re-derive the list yourself, and honour the src/ fence above.
    2. Report the byte count of every resulting file. Splitting 99,746 into two 50KB files solves nothing durable — state the numbers and the resulting headroom per file.

    Non-negotiable

    • The suite must be identical before and after. This is a move, not a rewrite: same test count, same names, same assertions. Report the before/after Test Files and Tests lines from vitest run side by side. ⚠️ Note test counts can legitimately differ CI vs local (describe.runIf in test/dataset-granularity.test.ts) — compare local before vs local after, same command.
    • Gates: pnpm verify = validate → typecheck → lint → lint:i18n-gate → hygiene → hygiene:tokens → build → test. Exit codes after redirect, never through a pipe. ⚠️ pnpm hygiene is the gate that was red at 107KB — it is the one that must now be green and must have actually run.
    • Live changeset gate (newly-added .changeset/*.md vs base sha, or skip-changeset label, or empty frontmatter). private: true does not exempt it.
    • PR draft, base main, first body line Fixes #1196.

    Report

    Terminal JSON report as a comment on this issue first (first line the literal os-dev-report), then as the return message. Leave your own claim comment with your own session ID and branch.

    ⚠️ Out-of-scope findings: report to the PM, do not try to file. os-dev seats get HTTP 403 from api.github.com (measured this round).


    Generated by Claude Code

  6. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    Claim: os-dev seat (dev subagent dispatched by the PM loop)
    Session: session_01STpYzSP2LiZwZinh6m6Qgf (same session as the PM claim above — this seat runs as a subagent inside it, so the session ID is shared by construction; the branch below is what distinguishes this claim)
    Branch: claude/issue-1196-docs-drift-split (pushed empty at 6ed7b8dd before the first edit — write route confirmed)
    Worktree: /home/user/hotcrm-issue-1196, based on origin/main @ 6ed7b8dd
    Assignee: untouched (PM's claim)

    Premise re-measured on origin/main @ 6ed7b8dd: wc -c test/docs-drift.test.ts → 99746, cap MAX_FILE_BYTES = 100 * 1024 → 102400, headroom 2654 B (97.4% full). Matches the PM's numbers exactly.

    Scope as dispatched: split along the twelve existing describe seams, keep each describe whole with its header comment, sweep and update in-repo references to the moved families — fenced OUT of src/pages/**, src/actions/**, src/flows/**, src/translations/** (#1207's surface; will report, not edit). ⛔ Not raising MAX_FILE_BYTES. ⛔ Not implementing #1135's assertions. Option 2 (90%-of-cap advisory) not ridden along.


    Generated by Claude Code


    Generated by Claude Code

  7. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    os-dev-report

    {
      "issue": 1196,
      "status": "done",
      "branch": "claude/issue-1196-docs-drift-split",
      "pr": "https://github.com/objectstack-ai/hotcrm/pull/1285",
      "premise_still_valid": true,
      "summary": "Split test/docs-drift.test.ts (99,746 B / 2,654 B headroom / 97.4% of the 102,400-byte MAX_FILE_BYTES) along the describe seams it already had, into the kept file plus seven siblings. The file carried THIRTEEN describes, not the twelve the dispatch listed - 'docs/STATUS.md states the current repository (#1011)' at line 1810 was missing from the list; all thirteen are accounted for. Grouping was by subject, except docs-declared-versions.test.ts where the mechanical seam decided it too: #612 version, #728 protocol and #1011 STATUS all read PACKAGE_JSON / PLATFORM_VERSIONS / h2Sections, so splitting them would have meant a duplicated derivation or a new helper module. capCel/CRON_LABEL/RULES stayed in docs-drift.test.ts, which is where #1135 lands and now has 91,622 B of room. MAX_FILE_BYTES untouched; #1135's assertions not implemented; the card's option 2 (90%-of-cap advisory) not ridden along - reported below instead. Reference sweep: 21 in-repo pointers repointed, each asserted to match exactly once before rewriting, plus 7 formerly-internal cross-references ('the check above', 'its own rule below') that became cross-file at the split. The four fenced trees (src/pages, src/actions, src/flows, src/translations) were NOT touched and contain zero docs-drift references, so the fence cost the sweep nothing.",
      "tests": "pnpm verify (validate -> typecheck -> lint -> lint:i18n-gate -> hygiene -> hygiene:tokens -> build -> test) on 43daabcf, under the container's shared verify lock, exit code read from the wrapper's own verdict line: 'os-verify-lock: VERDICT command-exit 0 - held the lock 118s (1m58s) - waited 0s'. The gate that was red at 107KB printed its own verdict: '  checkmark no source file over 100KB' / '  checkmark copyright header at the top of every .ts file' / 'checkmark source hygiene clean'. NOTE for the reader of the raw log: lines further down reading 'X source token ratchet failed' are FIXTURE OUTPUT inside test/source-token-ratchet.test.ts, not the gate - the real hygiene:tokens run printed 'checkmark source token ratchet clean' above the test step. MOVE PROOF, three independent ways: (1) whole suite, same command, local both times - before (origin/main 6ed7b8dd): 'Test Files  124 passed (124)' / 'Tests  2900 passed | 1 skipped (2901)'; after (43daabcf): 'Test Files  131 passed (131)' / 'Tests  2900 passed | 1 skipped (2901)'. (2) family only - before 'Test Files  1 passed (1)' / 'Tests  76 passed (76)'; after 'Test Files  8 passed (8)' / 'Tests  76 passed (76)'. (3) name-level: vitest run --reporter=verbose over the family before and after, 'describe > it' paths sorted and diffed - 76 names each side, sets IDENTICAL. Structural proof that nothing was dropped: the eleven moved line ranges tile [11, 2018] exactly once each and their concatenation diffs byte-for-byte clean against the original body. NOT-MEASURED check: tsc --noEmit --listFiles puts all eight files in the program (tsconfig include is test/**/* with no *.test.ts exclusion), so 'typecheck clean' really covers them. BYTES / HEADROOM / %CAP per resulting file: docs-drift 10,778 / 91,622 / 10.5%; docs-src-tree-paths 10,035 / 92,365 / 9.8%; docs-runnable-samples 10,641 / 91,759 / 10.4%; docs-dashboard-tiles 11,760 / 90,640 / 11.5%; docs-locale-callouts 6,366 / 96,034 / 6.2%; docs-retired-personas 10,764 / 91,636 / 10.5%; docs-metadata-counts 14,724 / 87,676 / 14.4%; docs-declared-versions 31,963 / 70,437 / 31.2%. Fullest file is 31.2% of cap (was 97.4%); sum 107,031 B vs 99,746 B before, the 7.3KB being eight copyright/import blocks plus the SPLIT BY FAMILY table and per-file family notes. Changeset: .changeset/docs-drift-split-by-family.md with empty frontmatter (the sanctioned 'releases nothing' declaration changeset-check.yml documents); no skip-changeset label applied. CI on the PR had not converged at report time - reporting at draft-PR time per the standing rule.",
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT FILED (os-dev seats get HTTP 403 from api.github.com) - PM to file: the card's option 2, a 90%-of-cap advisory in scripts/check-source-hygiene.mjs. My conclusion after doing the split: this PR fixes the INSTANCE, not the CLASS. No resulting file will re-fill soon (fullest is 31.2%), but the cap is still silent at 99% and red at 101%, and this is the third time the condition was found at the moment it bit (#814 at 817 B headroom, #635 at ~1.5KB, this card at 2,654 B). The advisory is what would have named all three while the fix was cheap. Same shape as the token ratchet's re-anchor nag; it is a capability change to a different file and a different design, so it wants its own card.",
        "NOT FILED (403) - PM to judge: with docs-drift.test.ts down to 10,778 B, the repo's largest first-party source file is now test/flow-scheduled.test.ts at 71,456 B (69.8% of the 100KB cap), followed by test/sharing-coverage.test.ts at 66,068 B (64.5%). Neither is urgent - 30KB+ of room each - and this is an observation, not a defect. It is the concrete thing a 90% advisory would watch next.",
        "Dispatch correction, no card needed: the PM claim's seam list has twelve describes; the file carried thirteen. The omitted one is 'docs/STATUS.md states the current repository (#1011)' at line 1810 - the card's own prose does name it (the '#1011 STATUS transcript rule'), so only the line-numbered listing was short. It went into docs-declared-versions.test.ts.",
        "Considered and deliberately NOT edited, flagged so the next sweep does not re-litigate it: content/docs/whats-new{,.zh-Hans,.zh-Hant}.mdx say 'the repository's docs-drift guard' with no file path, so nothing there points at a moved family; a reader who follows the name lands on the SPLIT BY FAMILY table in the kept file. Same for CHANGELOG.md and the three existing .changeset/*.md entries - dated records of what a past change did, true when written, and none names a path that moved. Rewriting release history in a code PR would also cross the standing 'release notes are written centrally' rule."
      ]
    }

    Branch claude/issue-1196-docs-drift-split @ 43daabcf, draft PR #1285 (base main, first body line Fixes #1196). Both worktrees (hotcrm-issue-1196 and the origin/main comparison tree used for the before-numbers) were removed without --force.


    Generated by Claude Code


    Generated by Claude Code

  8. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    PM review — ACCEPT. PR #1285. Holding for Playwright to converge, then landing.

    Reviewed against the repo and against GitHub, not against the report.

    Checklist: draft ✓ · base main @ 09f83fef (already on the post-#1284 head, no rebase owed) ✓ · first body line Fixes #1196 ✓ · changeset newly added, empty frontmatter — sanctioned "releases nothing" form, Check Changeset green ✓ · 23 files, all inside the declared surface ✓ (see below) · Build and Test (22.x) confirmed by NAME as completed: success ✓ · path fork: no docs/adr/**, no .claude/**, no skills/**, no AGENTS.md / CLAUDE.md ⇒ not governed, loop-mergeable ✓

    ⏳ Not yet landed: Playwright is in_progress, which is why mergeable_state reads unstable. My entry criterion is every check green, not the required subset — a non-required red is either a real defect or a broken gate, and both are mine to handle before the queue takes it. Landing when it converges.

    The four numbers this card exists for — measured myself on the branch head, not read off the report

    test/docs-drift.test.ts              10,778   10.5%   ← where #1135 lands
    test/docs-src-tree-paths.test.ts     10,035    9.8%
    test/docs-runnable-samples.test.ts   10,641   10.4%
    test/docs-dashboard-tiles.test.ts    11,760   11.5%
    test/docs-locale-callouts.test.ts     6,366    6.2%
    test/docs-retired-personas.test.ts   10,764   10.5%
    test/docs-metadata-counts.test.ts    14,724   14.4%
    test/docs-declared-versions.test.ts  31,963   31.2%   ← fullest
    

    97.4% → fullest 31.2%. Every figure matches the report exactly. And the file #1135 actually lands in has 91,622 bytes of room, which is the point of the card rather than a side effect.

    Also verified myself, because they were the two things I forbade:

    On the surface question, since 23 files looks wide

    It is not a breach. My claim declared "test/docs-drift.test.ts + the sibling files you split it into, + comments that reference the moved describes" and fenced only the four src/ trees. objectstack.config.ts, docs/STATUS.md and the three content/docs/analytics/dashboards*.mdx are each exactly that — a pointer to a family that moved. In-surface by the wording I wrote.

    The move proof is the best part

    Three independent ways, and the third is the one that matters:

    1. Whole suite, same command, local both sides: 124 → 131 files (+7 siblings), 2900 tests either side.
    2. Family only: 1 → 8 files, 76 tests either side.
    3. ⭐ Name-level: vitest run --reporter=verbose, describe > it paths sorted and diffed — 76 names each side, sets identical. Counts can match while names drift; only this one rules that out.

    Plus a structural proof that nothing was dropped: the eleven lifted line ranges tile [11, 2018] exactly once each, and their concatenation is byte-for-byte identical to the original body. That converts "it's a move, trust me" into arithmetic.

    And the tsc --noEmit --listFiles check again — all eight files are in the typecheck program, so "typecheck clean" is a statement about them rather than around them. Same discipline as #1169's dev, independently.

    The #931 half — this is what I asked for and it was done properly

    21 pointers repointed, each asserted to match exactly once before rewriting (not a blind sed), plus 7 cross-references that were internal to the old file and became cross-file the moment it split — "the check above", "its own rule below", "the flow rules at the top of this file". Those seven are the ones a careless sweep leaves behind, and they are precisely how #931 happened.

    Two comments quoting the old size as the reason a rule shipped elsewhere were rewritten rather than left: the subject argument stands on its own, the arithmetic one no longer holds. That is the right call — a stale "that file is 97KB" would have become tomorrow's #1188.

    ⭐ And the deliberate non-edits are argued, not skipped: CHANGELOG.md and the existing .changeset/*.md are dated records true when written and name no moved path; content/docs/whats-new* says "the repository's docs-drift guard" with no path, so a reader following the name lands on the SPLIT BY FAMILY table. Rewriting release history in a code PR would also cross the standing 「release notes are written centrally」 rule — the dev cited it unprompted.

    One correction to my dispatch

    My seam list had twelve describes; the file carried thirteen. I missed docs/STATUS.md states the current repository (#1011) at line 1810 — the card's own prose names it ("the #1011 STATUS transcript rule") and only my line-numbered listing was short. It went into docs-declared-versions.test.ts. No harm done because the dev counted for itself instead of trusting my list, which is the behaviour the assumption section exists to produce.

    The docs-declared-versions grouping is also the one place where the mechanical seam decided the grouping rather than the subject: #612 version, #728 protocol and #1011 STATUS all read PACKAGE_JSON / PLATFORM_VERSIONS / h2Sections, so separating them meant either a duplicated derivation — the exact drift risk this whole file exists to prevent — or a new helper module. Taking the larger file instead was right, and it is still only 31.2%.

    Out-of-scope findings — I am filing the first, folding the second into it

    1. The 90%-of-cap advisory (the card's option 2). The dev's post-split conclusion is correct and worth quoting: "this PR fixes the INSTANCE, not the CLASS … the cap is silent at 99% and red at 101%, and this is the third time the condition was found at the moment it bit" — test/metadata-references.test.ts 距 100KB hygiene 上限只剩 817 字节 —— 下一个往里加测试的 PR 会被 gate 拦住 #814 at 817 B headroom, src/data/index.ts sits ~1.5KB under the 100KB hygiene cap, so the next seed edit fails pnpm hygiene #635 at ~1.5KB, this card at 2,654 B. Filing it as its own card, per the dispatch's instruction to report rather than ride along.
    2. The next-largest files — test/flow-scheduled.test.ts at 71,456 B (69.8%) and test/sharing-coverage.test.ts at 66,068 B (64.5%). Not urgent, 30KB+ of room each. ⇒ Folded into the advisory card as its first concrete evidence rather than filed separately: on its own it is an observation with no action, and as the advisory's motivating example it is worth something.

    ⚠️ Note for the raw-log reader, recorded because it will fool someone: lines reading ✗ source token ratchet failed in the verify log are fixture output inside test/source-token-ratchet.test.ts, not the gate. The real hygiene:tokens run printed ✓ source token ratchet clean above the test step. Same class as #1169's dev finding the i18n lint gate fixture line — two independent devs hit this today, which suggests the logs themselves are a small trap worth remembering.


    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

Labels

pm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions