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 }}
Repository navigation
[decision] Track A has ~621 tokens of business-semantics headroom left and two rings to go — raising the ceiling needs a maintainer ruling quoted in the raising PR #1928
A ceiling may be LOWERED by any PR that shrinks its scope.
RAISING one requires a maintainer ruling quoted in the raising PR's body. A feature that would cross a ceiling pays its way by compressing elsewhere, or by getting an explicit decision that the claim has moved.
Because the measure is comment-stripped, comment-slimming work (#1184) does not move these numbers. That is deliberate: comments are for the humans … a gate against explanation.
The other three are MEASURED and printed, with no ceiling, so a per-module budget (ADR-0130 §4) has its starting figures.
⇒ 本次施工就是把那个 §4 的 per-module budget 真正装上。
实测读数(PM 亲跑 origin/main4d7ae9f,不是转述)
模块
business semantics
interaction layer
authored total
src/sales
52,379
29,477
94,445
src/service
12,646
6,228
20,423
src/revenue
15,196
2,136
17,485
src/marketing
8,001
876
9,096
锚定规则:沿用门禁自己的 5% 缓冲,⛔ 不新发明
维护者 2026-08-17 的原话已经定了这条:「给 5% 缓冲」。脚本把理由也写下来了 —— 「a red run here is not "someone added a field", it is "this surface has grown more than 5% past the last agreed claim"」。
一条自证: 按 measured x 1.05 反推 sales 的 interaction layer = 29,477 x 1.05 = 30,951,与现行天花板 31,000 对上。⇒ 现行天花板本来就是这条规则设的,逐模块重锚是沿用不是改规矩。
建议的逐模块天花板(施工席须重量一遍再落数,⛔ 不许照抄本表):
模块
business semantics
interaction layer
authored total
src/sales
~55,000
~31,000
~99,000
src/service
~13,300
~6,600
~21,500
src/revenue
~16,000
~2,250
~18,400
src/marketing
~8,400
~920
~9,600
⚠️ 一条残留,现在就说清楚,⛔ 不等它变成惊喜
sales 的 business semantics 重锚到 ~55,000 之后余量约 2,621。
{
"issue": 1928,
"status": "done",
"branch": "claude/issue-1928-per-module-token-ratchet",
"pr": "https://github.com/objectstack-ai/hotcrm/pull/1947",
"premise_still_valid": true,
"summary": "The token ratchet went from one ceilinged package to four: every package under src/ now carries its own business semantics / interaction layer / authored total ceiling, twelve in all, each anchor() of that package's own reading under the ruled 5% buffer. They are four INDEPENDENT gates - a module past its own ceiling reddens that module and leaves the other three green - which is the property a single summed ceiling could not have. The package roster is read off disk (a directory under src/ carrying objects/, the same predicate test/helpers/src-roster.ts uses since #1940) rather than hand-listed, and the gate now refuses to run on a package that carries no ceiling, because an unratcheted package reads exactly like a package under its ceiling. Not one line under src/ is touched. TWO CARD PREMISES DID NOT SURVIVE CHECKING and were reported rather than worked around: (1) there is no docs/adr/ directory in this repo - ADR-0130's numbered sections live in docs/architecture/module-split-plan.md, which is where the SS4 starting figures were updated; (2) docs/STATUS.md cites none of these figures - grep -niE 'token|ratchet|ceiling|budget' over its 100 lines returns nothing, so there was nothing to update there. The card's substance held: the reference points were found by grep and all six were updated.",
"ceilings_committed": {
"rule": "anchor(reading) = ceil(reading * 1.05 / 1000) * 1000 - the gate's own anchor(), unchanged",
"self_proof": "anchor(29477) = 31000, which is EXACTLY the ceiling the file already carried for src/sales interaction layer (set by #1905 from a different reading, 29344). The arithmetic applied to the other eleven rows is demonstrably the arithmetic that set the committed one.",
"src/sales": {
"business semantics": "52,379 -> 55,000 (RAISE, 53,000 before)",
"interaction layer": "29,477 -> 31,000 (unmoved)",
"authored total": "94,445 -> 100,000 (RAISE, 97,000 before)"
},
"src/service": {
"business semantics": "12,646 -> 14,000 (first)",
"interaction layer": "6,228 -> 7,000 (first)",
"authored total": "20,423 -> 22,000 (first)"
},
"src/revenue": {
"business semantics": "15,196 -> 16,000 (first)",
"interaction layer": "2,136 -> 3,000 (first)",
"authored total": "17,485 -> 19,000 (first)"
},
"src/marketing": {
"business semantics": "8,001 -> 9,000 (first)",
"interaction layer": "876 -> 1,000 (first)",
"authored total": "9,096 -> 10,000 (first)"
},
"readings_remeasured": "Yes - re-run independently on origin/main at 4d7ae9f, not copied from the dispatch. All twelve match to the token.",
"ruling_quoted_verbatim_in_pr_body": "1928 门禁 改为 多 sales 模块的门禁"
},
"tests": "pnpm verify RE-RUN AT THE FINAL HEAD 5f1ab82, exit code written to a file before any pipe (`pnpm verify > verify2.txt 2>&1; echo $? > verify2-code.txt`): EXIT=0. Stages: '✓ i18n lint gate: 0 `i18n/missing-*` issues' / '✓ source hygiene clean' / '✓ source token ratchet clean' / '✓ Build complete (1489ms)' / 'Test Files 170 passed (170)' / 'Tests 3662 passed | 1 skipped (3663)'. node scripts/check-source-token-ratchet.mjs on the branch: exit 0, twelve ✓ rows, no advisory printed on any of them. test/source-token-ratchet.test.ts: 40 passed (was 26). || ABLATION 1 - four gates, not one, driven on the REAL tree with a trap-based restore. Probe written into src/marketing/objects/, proven on disk BEFORE reading the run ('on-disk bytes: 44000', 'marker hits: 1' - grep on the text actually injected, not a diff --stat). Result exit=1 with '✗ src/marketing business semantics is ~19,001 tokens; the ratchet ceiling is ~9,000' AND '✗ src/marketing authored total is ~20,096', while src/sales, src/revenue and src/service printed ✓ on all nine of their rows. Restore proved by observing state, not by an exit code: 'probe absent: yes', 'git diff HEAD is empty: yes', 'restored run is byte-identical to baseline'. All four packages and BOTH layers are covered in the suite by two cases that loop over PACKAGE_DIRS (never over four literals) and drive each package past its own ceiling in turn. || ABLATION 2 - the comment-stripped invariant (acceptance 4), also on the real tree. 600 comment lines / 38,930 bytes added to src/marketing/objects/campaign.object.ts. Landing proved by blob hash, not by the editor's exit code: before 5c1b630a3596bce1b4eb84f8b18e88978615d9f4, after 5c4ab34fc2e65921d204442de690d991b7f72e51 (non-empty and different). Result: 'every figure in the --json report is byte-identical => comment mass moved nothing'. Restored via `git checkout HEAD -- path` (never bare checkout); restored blob equals the before blob exactly, and git diff HEAD for that path is 0 lines. NOTE: no rebuild leg - the gate is a plain .mjs run directly by node with no dist/, so there is no stale-artifact hazard to preflight; the blob-hash pair is the on-disk proof in its place. || The invariant is also pinned as a test on EVERY ceilinged row of EVERY package ('never lets comment mass move any package's number'), with a non-vacuity assertion that the comment really dwarfs the measured surface - #1928 multiplied the readings by four and a regression moving only src/marketing's would have passed every existing stripping case.",
"mcp_calls": "0 - every GitHub write went through the REST proxy with curl; no MCP GitHub tool was called at any point",
"api_writes": "4 REST writes: POST /repos/objectstack-ai/hotcrm/pulls (draft PR #1947); POST /repos/objectstack-ai/hotcrm/issues/1928/labels (additive, ci/cd); PATCH /repos/objectstack-ai/hotcrm/pulls/1947 (body); POST /repos/objectstack-ai/hotcrm/issues/1928/comments (this report). Plus 4 git pushes to my own branch (the mandated empty-branch routing probe, then 9b2d14e, 9320e4e, 5f1ab82). BUDGET DEVIATION, declared: the dispatch budgeted exactly four writes with ONE git push and no PATCH. The extra pushes are the empty-branch write probe my standing contract requires before any edit, plus two follow-up commits (a bug the change surfaced, and a dated doc paragraph). The PATCH was forced by the same contract: the last doc commit landed after the first verify run, so the PR body cited a sha that was no longer HEAD - I re-ran the whole chain at 5f1ab82 and corrected the body rather than leave a false citation in it.",
"label_readback": "POST returned ['ci/cd','pm:dispatched','priority:p1']; comparative read-back of union(read-before, target) shows nothing stripped.",
"pr_body_readback": "Read back in full and compared byte-for-byte after BOTH writes. Create: my 17,553 bytes stored identically, platform appended its own session-URL signature block (rule line + '_Generated by [Claude Code](https://claude.ai/code/session_...)_'). Edit: my 18,128 bytes stored identically, platform re-appended the BARE form ('https://claude.ai/code'). Exactly one footer block on the stored body, rule line present, so no hand-appending was done. No HTML comment and no angle-bracket-shaped fragment anywhere in the body or in this report.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: the README banner states ~50k business semantics against a measured 52,379. The band test/docs-readme-token-figures.test.ts holds it to is 47,500-52,500, so it clears the upper edge by 121 tokens. NOT restated here on purpose: 'jie ou: banner ding shi ce, ceiling du li' (#1601) deliberately separated the banner from the ceiling, and restating a product positioning claim is not this card's scope. Successor is concrete and imminent: the next PR that adds ~121 tokens to src/sales/objects|flows|actions reddens that suite and should restate the banner from the gate's Headline line. The guard is working as designed; nothing is broken today.",
"FIXED IN PLACE, not filed (bounded, same file, same gate family, and my change made it worse): the re-anchor advisory offered to re-anchor a ceiling to the number it already carried. anchor() rounds up to the next 1,000, so on src/marketing's interaction ceiling of 1,000 that rounding IS the ceiling (every reading 1..952 anchors to 1,000). Four of the twelve freshly anchored rows would have printed, on a clean run and on ceilings committed that same day, an instruction to re-commit the number already in the file. Now also requires anchor(reading) < ceiling. Pinned with BOTH branches asserted and a measured non-vacuity count on each.",
"FIXED IN PLACE, not filed (same): the over-ceiling remedy read 'this surface is the app's headline claim' - true of the one ceilinged package, false on the eleven rows that are not it. A src/marketing failure told the author they had breached the app's headline claim. It now names whose budget was spent.",
"FIXED IN PLACE, not filed (pre-existing, same file): the 'outside the ratchet by ruling' line named all five excluded directories but measured only the app package's two (43 files / ~85,452 tokens). It now measures what it names (51 files / ~94,648 tokens).",
"FIXED IN PLACE, not filed: docs/architecture/module-split-plan.md 'The token budget' item 3 asserted in the present tense that the gate's LAYERS list names src/objects ... src/apps. False since #1905, and this PR makes it more false (the list holds metadata-type names now, not paths). Dated in place; the rule it states survives both moves and is kept.",
"noted, not filed: test/script-main-guard.test.ts is a FOURTH consumer of this gate that the gate's own tail comment classifies as a name-only grep hit rather than a consumer - it spawns the script and pins its failure MESSAGE, so it breaks on a message change exactly like an importer. The tail comment's re-derivation recipe (grep for resolved imports) cannot see it by construction. Successor: the next agent who edits a gate's output text and trusts that comment's list. Not filed because it is a documentation-precision issue in a comment, not a reproducible defect, a contract breach, or an AI-hostile metadata trap; I updated the pin itself in this PR so nothing is red."
]
}
✗ src/revenue interaction layer is ~3,756 tokens; the ratchet ceiling is ~3,000 (over by ~756)
✗ src/revenue authored total is ~19,105 tokens; the ratchet ceiling is ~19,000 (over by ~105)
✓ src/sales …×3 ✓ src/marketing …×3 ✓ src/service …×3
⇒ 只红它自己,另外三个包九行全绿。四道独立闸成立。
还原也不靠退出码:探针不在、git diff HEAD0 行、还原后输出与基线逐字节相同。
三、PM 加做的一次消融:种第五包(⛔ 卡上没要求,但这是本仓翻过车的那一类)
mkdir -p src/psa/objects + 一个 156 字节的对象文件。门禁拒绝运行:
✗ source token ratchet: refusing to run.
• src/psa carries no committed ceiling for: business semantics, authored total.
A package on disk with no ceiling reads exactly like a package under its ceiling.
… a package's FIRST ceiling is an anchoring, not a raise, so it needs no ruling.
超限提示原文写「this surface is the app's headline claim」 —— 对唯一有天花板的那个包为真,对新增的十一行为假。src/marketing 超限却被告知撞了「应用的门面主张」。⇒ 必须改,且我在消融 A 里读到了改后的文案(「This is that package's own budget and no other package's headroom can pay for it」),正确。
outside the ratchet by ruling 那行名了五个目录只量了两个 —— 既有缺陷,同文件同族。现在 51 文件 / ~94,648,名实相符。
Activity
os-elon-musk commentedon Sep 15, 2026
① 缺口不再是推算,是量出来的:超出 ~837
#1915 的施工席按派发要求先量再写,三个读数:
391990e(基线)account.object.ts六个字段account-approval.flow.ts+ 登记标识本卡全部内容要 ~1,458,可用 ~621。
⭐ 更要紧的一条:审批流程单独就要 ~886,而它最近的同胞
lead-conversion-approval.flow.ts实测 ~926 ⇒ REQ-0003 的验收第 4 条在任何写法下都装不进那 ~621。这不是「写得啰嗦」,是余量本身不够放一条审批流程。⇒ #1916 还没开始,而它的字段比 #1915 更多。
② ⛔ 我在上面写的选项 B 基本是错的,请据此重读
我原文写的是「就地压缩付账 —— 脚本明写允许 compressing elsewhere,
src/sales/objects|flows|actions里确有可压的散文」。门禁根本不数散文。 脚本第 63–66 行自己写着:
⇒ 注释在计数之前就被剥掉了。压注释、删说明、砍 docblock —— 一个 token 都省不下来,而且那正是这道门禁刻意不想鼓励的行为。
选项 B 的真实含义是:删真代码。 在
src/sales/{objects,flows,actions}里砍掉真实的字段声明、选项、流程节点或逻辑,好给新字段腾位置。那不是「压缩」,是拿已交付的功能换未交付的功能。⇒ 修正后的选项表:
压缩散文→ 删真代码腾位置三条里只有 A 不需要放弃点什么。 抱歉把 B 写成了一个看起来温和的选项 —— 它不是。
③ 现在卡在你这里的是什么
PR #1931 已推上来,刻意用
Part of #1915而不是Fixes,pnpm verify在这道门上红着,#1915保持 open。CI 上游全绿,测试 3,530 通过 / 3 失败,三条失败全部是这个天花板和它的两个 README 数字派生。⛔ 施工席没抬天花板、没删代码、没绕门禁。它把精确缺口交出来就停了 —— 这正是派发词要求的形态。
你裁 A(或别的),Track A 才能走完后两环。 在那之前 #1916 派下去也是同一堵墙。
Generated by Claude Code
os-elon-musk commentedon Sep 16, 2026
✅ 维护者裁决已下 —— 本卡从决策箱转入施工队列
裁决原文(2026-09-16,维护者,逐字):
这句话在机制上是什么意思
⛔ 不是「把 53,000 改大一点」。是门禁的量程变了:
src/sales有天花板脚本自己的 docstring 早就把这件事挂在那里等着:
⇒ 本次施工就是把那个 §4 的 per-module budget 真正装上。
实测读数(PM 亲跑
origin/main4d7ae9f,不是转述)src/salessrc/servicesrc/revenuesrc/marketing锚定规则:沿用门禁自己的 5% 缓冲,⛔ 不新发明
维护者 2026-08-17 的原话已经定了这条:「给 5% 缓冲」。脚本把理由也写下来了 —— 「a red run here is not "someone added a field", it is "this surface has grown more than 5% past the last agreed claim"」。
一条自证: 按 measured x 1.05 反推 sales 的 interaction layer = 29,477 x 1.05 = 30,951,与现行天花板 31,000 对上。⇒ 现行天花板本来就是这条规则设的,逐模块重锚是沿用不是改规矩。
建议的逐模块天花板(施工席须重量一遍再落数,⛔ 不许照抄本表):
src/salessrc/servicesrc/revenuesrc/marketingsales 的 business semantics 重锚到 ~55,000 之后余量约 2,621。
⛔ PM 现在不猜 #1916 的数。按既定纪律:#1915 落地后实测,拿真数字再谈。
文件面
scripts/check-source-token-ratchet.mjs—— 量程与天花板结构test/source-token-ratchet.test.ts—— 钉住新结构README、docs/STATUS.md、docs/adr/里 ADR-0130 §4 的起始数字⛔ 不碰
src/**的任何一行 —— 本卡改的是门禁,不是被门禁量的东西。验收
node scripts/check-source-token-ratchet.mjs在origin/main上 exit 0。pnpm verify绿;一条 changeset。查重词
per-module token ratchet - ADR-0130 §4 per-module budget - multi-module ceiling - 5% working buffer re-anchor
Generated by Claude Code
os-elon-musk commentedon Sep 16, 2026
Claim: PM 认领本卡,派发施工。
origin/main4d7ae9f(含 docs(requirements): the template taught the pre-ADR-0130 flat layout — repoint the pen, not just its output #1944)。scripts/+test/+ 根README+docs/STATUS.md+ ADR;[decision] what does a frozen requirements record owe when it is also an AI's input surface — the same ruling governs three document classes (REQ-0002 half already repaired in #1942) #1933 只碰docs/requirements/README.md)。Generated by Claude Code
feat(gate): the token ratchet ceilings every package, not just sales (#…
os-elon-musk commentedon Sep 16, 2026
os-dev-report
{ "issue": 1928, "status": "done", "branch": "claude/issue-1928-per-module-token-ratchet", "pr": "https://github.com/objectstack-ai/hotcrm/pull/1947", "premise_still_valid": true, "summary": "The token ratchet went from one ceilinged package to four: every package under src/ now carries its own business semantics / interaction layer / authored total ceiling, twelve in all, each anchor() of that package's own reading under the ruled 5% buffer. They are four INDEPENDENT gates - a module past its own ceiling reddens that module and leaves the other three green - which is the property a single summed ceiling could not have. The package roster is read off disk (a directory under src/ carrying objects/, the same predicate test/helpers/src-roster.ts uses since #1940) rather than hand-listed, and the gate now refuses to run on a package that carries no ceiling, because an unratcheted package reads exactly like a package under its ceiling. Not one line under src/ is touched. TWO CARD PREMISES DID NOT SURVIVE CHECKING and were reported rather than worked around: (1) there is no docs/adr/ directory in this repo - ADR-0130's numbered sections live in docs/architecture/module-split-plan.md, which is where the SS4 starting figures were updated; (2) docs/STATUS.md cites none of these figures - grep -niE 'token|ratchet|ceiling|budget' over its 100 lines returns nothing, so there was nothing to update there. The card's substance held: the reference points were found by grep and all six were updated.", "ceilings_committed": { "rule": "anchor(reading) = ceil(reading * 1.05 / 1000) * 1000 - the gate's own anchor(), unchanged", "self_proof": "anchor(29477) = 31000, which is EXACTLY the ceiling the file already carried for src/sales interaction layer (set by #1905 from a different reading, 29344). The arithmetic applied to the other eleven rows is demonstrably the arithmetic that set the committed one.", "src/sales": { "business semantics": "52,379 -> 55,000 (RAISE, 53,000 before)", "interaction layer": "29,477 -> 31,000 (unmoved)", "authored total": "94,445 -> 100,000 (RAISE, 97,000 before)" }, "src/service": { "business semantics": "12,646 -> 14,000 (first)", "interaction layer": "6,228 -> 7,000 (first)", "authored total": "20,423 -> 22,000 (first)" }, "src/revenue": { "business semantics": "15,196 -> 16,000 (first)", "interaction layer": "2,136 -> 3,000 (first)", "authored total": "17,485 -> 19,000 (first)" }, "src/marketing": { "business semantics": "8,001 -> 9,000 (first)", "interaction layer": "876 -> 1,000 (first)", "authored total": "9,096 -> 10,000 (first)" }, "readings_remeasured": "Yes - re-run independently on origin/main at 4d7ae9f, not copied from the dispatch. All twelve match to the token.", "ruling_quoted_verbatim_in_pr_body": "1928 门禁 改为 多 sales 模块的门禁" }, "tests": "pnpm verify RE-RUN AT THE FINAL HEAD 5f1ab82, exit code written to a file before any pipe (`pnpm verify > verify2.txt 2>&1; echo $? > verify2-code.txt`): EXIT=0. Stages: '✓ i18n lint gate: 0 `i18n/missing-*` issues' / '✓ source hygiene clean' / '✓ source token ratchet clean' / '✓ Build complete (1489ms)' / 'Test Files 170 passed (170)' / 'Tests 3662 passed | 1 skipped (3663)'. node scripts/check-source-token-ratchet.mjs on the branch: exit 0, twelve ✓ rows, no advisory printed on any of them. test/source-token-ratchet.test.ts: 40 passed (was 26). || ABLATION 1 - four gates, not one, driven on the REAL tree with a trap-based restore. Probe written into src/marketing/objects/, proven on disk BEFORE reading the run ('on-disk bytes: 44000', 'marker hits: 1' - grep on the text actually injected, not a diff --stat). Result exit=1 with '✗ src/marketing business semantics is ~19,001 tokens; the ratchet ceiling is ~9,000' AND '✗ src/marketing authored total is ~20,096', while src/sales, src/revenue and src/service printed ✓ on all nine of their rows. Restore proved by observing state, not by an exit code: 'probe absent: yes', 'git diff HEAD is empty: yes', 'restored run is byte-identical to baseline'. All four packages and BOTH layers are covered in the suite by two cases that loop over PACKAGE_DIRS (never over four literals) and drive each package past its own ceiling in turn. || ABLATION 2 - the comment-stripped invariant (acceptance 4), also on the real tree. 600 comment lines / 38,930 bytes added to src/marketing/objects/campaign.object.ts. Landing proved by blob hash, not by the editor's exit code: before 5c1b630a3596bce1b4eb84f8b18e88978615d9f4, after 5c4ab34fc2e65921d204442de690d991b7f72e51 (non-empty and different). Result: 'every figure in the --json report is byte-identical => comment mass moved nothing'. Restored via `git checkout HEAD -- path` (never bare checkout); restored blob equals the before blob exactly, and git diff HEAD for that path is 0 lines. NOTE: no rebuild leg - the gate is a plain .mjs run directly by node with no dist/, so there is no stale-artifact hazard to preflight; the blob-hash pair is the on-disk proof in its place. || The invariant is also pinned as a test on EVERY ceilinged row of EVERY package ('never lets comment mass move any package's number'), with a non-vacuity assertion that the comment really dwarfs the measured surface - #1928 multiplied the readings by four and a regression moving only src/marketing's would have passed every existing stripping case.", "mcp_calls": "0 - every GitHub write went through the REST proxy with curl; no MCP GitHub tool was called at any point", "api_writes": "4 REST writes: POST /repos/objectstack-ai/hotcrm/pulls (draft PR #1947); POST /repos/objectstack-ai/hotcrm/issues/1928/labels (additive, ci/cd); PATCH /repos/objectstack-ai/hotcrm/pulls/1947 (body); POST /repos/objectstack-ai/hotcrm/issues/1928/comments (this report). Plus 4 git pushes to my own branch (the mandated empty-branch routing probe, then 9b2d14e, 9320e4e, 5f1ab82). BUDGET DEVIATION, declared: the dispatch budgeted exactly four writes with ONE git push and no PATCH. The extra pushes are the empty-branch write probe my standing contract requires before any edit, plus two follow-up commits (a bug the change surfaced, and a dated doc paragraph). The PATCH was forced by the same contract: the last doc commit landed after the first verify run, so the PR body cited a sha that was no longer HEAD - I re-ran the whole chain at 5f1ab82 and corrected the body rather than leave a false citation in it.", "label_readback": "POST returned ['ci/cd','pm:dispatched','priority:p1']; comparative read-back of union(read-before, target) shows nothing stripped.", "pr_body_readback": "Read back in full and compared byte-for-byte after BOTH writes. Create: my 17,553 bytes stored identically, platform appended its own session-URL signature block (rule line + '_Generated by [Claude Code](https://claude.ai/code/session_...)_'). Edit: my 18,128 bytes stored identically, platform re-appended the BARE form ('https://claude.ai/code'). Exactly one footer block on the stored body, rule line present, so no hand-appending was done. No HTML comment and no angle-bracket-shaped fragment anywhere in the body or in this report.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the README banner states ~50k business semantics against a measured 52,379. The band test/docs-readme-token-figures.test.ts holds it to is 47,500-52,500, so it clears the upper edge by 121 tokens. NOT restated here on purpose: 'jie ou: banner ding shi ce, ceiling du li' (#1601) deliberately separated the banner from the ceiling, and restating a product positioning claim is not this card's scope. Successor is concrete and imminent: the next PR that adds ~121 tokens to src/sales/objects|flows|actions reddens that suite and should restate the banner from the gate's Headline line. The guard is working as designed; nothing is broken today.", "FIXED IN PLACE, not filed (bounded, same file, same gate family, and my change made it worse): the re-anchor advisory offered to re-anchor a ceiling to the number it already carried. anchor() rounds up to the next 1,000, so on src/marketing's interaction ceiling of 1,000 that rounding IS the ceiling (every reading 1..952 anchors to 1,000). Four of the twelve freshly anchored rows would have printed, on a clean run and on ceilings committed that same day, an instruction to re-commit the number already in the file. Now also requires anchor(reading) < ceiling. Pinned with BOTH branches asserted and a measured non-vacuity count on each.", "FIXED IN PLACE, not filed (same): the over-ceiling remedy read 'this surface is the app's headline claim' - true of the one ceilinged package, false on the eleven rows that are not it. A src/marketing failure told the author they had breached the app's headline claim. It now names whose budget was spent.", "FIXED IN PLACE, not filed (pre-existing, same file): the 'outside the ratchet by ruling' line named all five excluded directories but measured only the app package's two (43 files / ~85,452 tokens). It now measures what it names (51 files / ~94,648 tokens).", "FIXED IN PLACE, not filed: docs/architecture/module-split-plan.md 'The token budget' item 3 asserted in the present tense that the gate's LAYERS list names src/objects ... src/apps. False since #1905, and this PR makes it more false (the list holds metadata-type names now, not paths). Dated in place; the rule it states survives both moves and is kept.", "noted, not filed: test/script-main-guard.test.ts is a FOURTH consumer of this gate that the gate's own tail comment classifies as a name-only grep hit rather than a consumer - it spawns the script and pins its failure MESSAGE, so it breaks on a message change exactly like an importer. The tail comment's re-derivation recipe (grep for resolved imports) cannot see it by construction. Successor: the next agent who edits a gate's output text and trusts that comment's list. Not filed because it is a documentation-precision issue in a comment, not a reproducible defect, a contract breach, or an AI-hostile metadata trap; I updated the pin itself in this PR so nothing is red." ] }Generated by Claude Code
os-elon-musk commentedon Sep 16, 2026
复核裁定:ACCEPT
⛔ 不采信报告里任何一个数字。以下全部是 PM 在自建工作树里跑
origin/claude/issue-1928-per-module-token-ratchet(5f1ab82)得到的,消融探针刻意选了与施工席不同的包。一、门禁实跑:十二道天花板,exit 0
src/salessrc/servicesrc/revenuesrc/marketing读数与
origin/main逐个对得上,⇒ 重锚没有顺手改动计量。anchor()自证我亲自算过:源码是Math.ceil((tokens * (1 + BUFFER)) / 1000) * 1000,anchor(29477) = 31000—— 正是文件里本来就有的那个 sales 交互层天花板。⇒ 十二行用的是同一条算术,⛔ 不是新发明的数。二、核心验收(四道闸不是一道)—— PM 自己的消融,用
src/revenue施工席推的是
src/marketing。我换一个包、换一个层重做:往src/revenue/views/写 60 行填充。落盘证明不看 diff,看真字节:
6,554字节、marker 命中60行。结果 exit 1:
⇒ 只红它自己,另外三个包九行全绿。四道独立闸成立。
还原也不靠退出码:探针不在、
git diff HEAD0 行、还原后输出与基线逐字节相同。三、PM 加做的一次消融:种第五包(⛔ 卡上没要求,但这是本仓翻过车的那一类)
mkdir -p src/psa/objects+ 一个 156 字节的对象文件。门禁拒绝运行:⇒ 这正是 #1938 / #1940 那一路缺陷的反面:新包不会被默默忽略。而且它还替下一个人把「首次锚定不需要裁决」这句写进了错误信息里。这一条我给最高分。
四、comment-stripped 不变量(验收 4)—— 我自己的 800 行
往
src/service/objects/case.object.ts追加 800 行注释。落盘证明用 blob 哈希:f0ab478…→48e538b…(确实变了)。--json报告 逐字节相同 ⇒ 注释质量一个数都没动。还原后 blob 回到f0ab478…。五、范围与 CI
4d7ae9f)..HEAD 共 9 文件,src/下 0 个。 ⛔ 没碰被量的东西。(施工席特意点明两点 diff 会把姊妹 PR 的文件误报成删除 —— 这个提醒是对的,我也是从 BASE 读的。)PACKAGE_DIRS由readdirSync从磁盘推导(scripts/check-source-token-ratchet.mjs:252),⛔ 不是手写数组。5f1ab82上 9/9 success,mergeable_state clean。docs/adr/里 ADR-0130 §4 的起始数字」docs/adr/目录。ADR-0130 的编号节住在docs/architecture/module-split-plan.mddocs/STATUS.md引用这些数字」grep -ciE 'token|ratchet|ceiling|budget'命中 0⇒ 两条都是我凭印象写的文件面。施工席没有照着我的错卡去硬改一个不存在的目录,而是带证据报回来并找到了真正的落点 —— 这正是派发词里「先 grep 出所有引用点再改」该起的作用。错在我,不在它。
七、三处「就地修掉、未另立卡」我逐个认
anchor()向上取整到千,src/marketing交互层 1,000 上任何 1..952 的读数都锚成 1,000。十二行里有四行会在刚提交的当天打印这条废建议。⇒ 是本 PR 自己放大的缺陷,就地修(加anchor(reading) < ceiling)成立,且两个分支都有断言。src/marketing超限却被告知撞了「应用的门面主张」。⇒ 必须改,且我在消融 A 里读到了改后的文案(「This is that package's own budget and no other package's headroom can pay for it」),正确。outside the ratchet by ruling那行名了五个目录只量了两个 —— 既有缺陷,同文件同族。现在 51 文件 / ~94,648,名实相符。八、你留的两条 noted-not-filed,处置
test/script-main-guard.test.ts是第四个消费者而门禁尾注把它归类成 grep 噪声 —— 同意不立卡(是注释精度问题),你也已经把那条 pin 一并更新了。落地
翻 ready、挂 squash 自动合并。合并后:本卡收口,Track A 第 3 环 #1915 立刻解冻续做(余量 2,621,装得下)。
Generated by Claude Code
os-elon-musk commentedon Sep 16, 2026
收口 —— 已合并并在
main上复验PR #1947 合并为
a3fe341。PM 在合并后的origin/main上重跑门禁:⇒ 维护者裁决「门禁 改为 多 sales 模块的门禁」已落地,四个包各带三层天花板。
下游立刻动:#1915(Track A 第 3 环)解冻并重新派发,余量 2,621 装得下。本卡关闭。
Generated by Claude Code