Skip to content

release(next): #21988 reds on the skills token ratchet at 18.0.0-next.0 (the prerelease version stamp adds 7 bytes to two SKILL.md files with 0 and 1 token of headroom) #23176

Closed

Description

@objectstack-fleet

Maintainer-directed: 「21988 ci报错,你负责立卡并派发解决。」 / 「21988 是生成的,要修main 哦」 / 「我等着发版本,相关任务都是高优先级」 (this seat's session, 2026-10-13). Filing-gate category ①, a defect with a named landing point. It is the red that was hidden behind #23135's two roots.

Reader who acts: the domain:devx execution seat. It dispatches the fix once the maintainer picks the route below (the route needs the maintainer's word: the gate marks the loosening direction ⛔ MAINTAINER-ONLY).

Dedupe: issue search on this repo, closed included, with the words "skills token ratchet prerelease version stamp next SKILL.md ceiling". No hit for this class.

What is measured

Measured by this seat's read-only probe on 63eb607ad1 (#21988's head) with PR #23155's two files overlaid; the main figures were re-read by the seat on origin/main.

✗ check-skills-token-ratchet: skills/objectstack-automation/SKILL.md is 5786 tokens; the ratchet ceiling is 5785 (over by 1). …
✗ check-skills-token-ratchet: skills/objectstack-data/SKILL.md is 6129 tokens; the ratchet ceiling is 6128 (over by 1). …
✗ check-skills-token-ratchet: 2 of 64 published bundle file(s) failed their check.
  • Cause: the version commit rewrites each SKILL.md frontmatter stamp from version: "17.7.0" to version: "18.0.0-next.0", +7 bytes. The gate counts ceil(utf8 bytes / 4).
file main bytes → tokens ceiling (scripts/check-skills-token-ratchet.mjs) headroom on main at 18.0.0-next.0
skills/objectstack-automation/SKILL.md 23135 → 5784 5785 (:323) 1 5786, red
skills/objectstack-data/SKILL.md 24509 → 6128 6128 (:341) 0 6129, red
  • The other SKILL.md files take the same 7 bytes with at least 6 tokens of headroom. A plain 18.0.0 stamp is the length of 17.7.0, so the red lives only on the prerelease line; -next.10 and above add 8 bytes.
  • Steps 36, 38–41 and the five Test Core packages turbo never started on chore: version packages (next) #21988 (http-conformance, plugin-dev, plugin-pinyin-search, service-sms, knowledge-ragflow) are green on the same tree.

What done looks like

  • chore: version packages (next) #21988, refreshed from a main carrying the fix, has Type Check · source gates green (step 37 included) and every other check green or an expected skip.
  • main's own ratchet reading is unchanged or stricter; the route below says which.

Activity

  1. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    决策:skills token ratchet 在 18.0.0-next.0 上变红,修法选哪条 · domain:devx seat 1 · session_012zwsLMxQBwHUYJgPyrpEvx · 2026-10-13T05:30Z

    Governing text: scripts/check-skills-token-ratchet.mjs:697 的报错原文:"Loosening a ceiling to fit new text is not the fix: these ceilings are shrink-only. The other direction lands only in a PR whose body quotes a maintainer ruling authorizing it. ⛔ MAINTAINER-ONLY"。

    为什么要裁决:

    • 红的起因是发布机器人改写的版本戳(多了 -next.0,共 7 字节),不是作者加的文字。
    • 门禁给的唯一不需裁决的补救是"在同一文件里删文字";另外两条路都属于放宽方向,门禁自己标了 ⛔ MAINTAINER-ONLY。
    选项 做什么 落点 / 落地方式 工作量 代价
    A(推荐) 门禁计数前,把 frontmatter version: 值里的预发布后缀(-next.N)剥掉,按正式版宽度计 scripts/check-skills-token-ratchet.mjs 加自测行;非受管面,普通合并队列 dev 约 40 分钟,CI 加队列约 1 小时 预发布树上少计 7 字节;main 的读数不变,上限一个不动
    B 在两个 SKILL.md 里删文字:automation 至少 2 字节,data 至少 4 字节 skills/**(受管面,Tier H,需你亲自批准合并;skills 车道) dev 约 30 分钟,加你的审批 不改门禁;但 data 在 main 上余量为 0,每次大版本 pre 模式都会在余量不足 2 token 的文件上再红,每次再付
    C(最快) 两个上限各加 2:5785→5787,6128→6130(-next.10 起多 8 字节,所以加 2) 同一脚本两个数字;普通队列;PR 正文引你的裁决原话 约 1 小时以内 永久放宽,破了只减不增的约定;GA 后要有人再收紧

    四棱(按 A 对照):

    • 实际业务需求: 发版被阻塞是实测的(chore: version packages (next) #21988)。被计入的 7 字节是发布机器人写的版本戳,作者没有办法用"删同文件文字"来付这笔账。
    • 项目长远合理性: 每个大版本都走 Changesets pre 模式(.changeset/pre.json),而 ratchet 会把余量压到 0。所以 A 一次修掉这一类;B 每次大版本都重付;C 留下永久放宽。
    • 防 AI 犯错: 在 A 下,main 计数不变、上限不动,AI 加的文字照样被拦。C 给 AI 多留 2 token 的空间。
    • 不扩散: A 只在现有门禁里改计数口径,不新增门禁,也不新增面。

    推荐 A。 长远轴领起,其余三轴同向。若发版时间压过一切,C 最快,但留下永久放宽。

  2. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 6 · domain:devx seat 1 · 2026-10-13T05:33Z · maintainer-ruled: route A on the decision 6138951701. The maintainer picked 「A 剥预发布后缀 (Recommended)」 in this seat's session. Standing orders 「21988 ci报错,你负责立卡并派发解决。」 / 「我等着发版本,相关任务都是高优先级」
    Session: session_012zwsLMxQBwHUYJgPyrpEvx
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-23176-ratchet-prerelease-stamp
    Worktree: objectstack-issue-23176
    Domain: domain:devx
    Seat: domain:devx#1
    File surface: scripts/check-skills-token-ratchet.mjs only (its count and its self-test). ⛔ No ceiling moves. ⛔ No edit to skills/**, .github/workflows/** or any other governed surface. ⛔ No edit to changeset-release/main / #21988
    Container & model: M, mode:subagent, model: opus (the default judgment tier; dispatch-gates --tier on this surface: "no path-derived mandate", floor sonnet · default opus · ceiling fable)
    Clause-②: no (an internal repo gate; no published accept set or public surface)
    Responsibility: the skills token ratchet counts the release bot's prerelease version stamp as authored text, so two SKILL.md files with 0 and 1 token of headroom go red at 18.0.0-next.0 | no platform path covers it: the stamp is written by changeset version, and the gate's only no-ruling remedy (delete text in the same file) cannot pay for bytes no author wrote | #21988 cannot go green, and the next release waits
    Thread-read: 6138951701
    Serial constraints cleared: no open PR touches scripts/check-skills-token-ratchet.mjs, skills/objectstack-automation/SKILL.md or skills/objectstack-data/SKILL.md (all open PRs' file lists read at this act).

  3. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23176,
      "status": "done",
      "branch": "claude/issue-23176-ratchet-prerelease-stamp",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23187",
      "session": "session_012zwsLMxQBwHUYJgPyrpEvx (subagent: the parent's id; the relay derived the same id from the container)",
      "premise_still_valid": true,
      "summary": "Route A as ruled on decision 6138951701 (verbatim choice: 「A 剥预发布后缀 (Recommended)」). It lands in scripts/check-skills-token-ratchet.mjs only, +122/-6, at head f06e7f636 (PR #23187, draft). The gate now judges pricedTokens(): countTokens minus the semver prerelease segment of the frontmatter metadata.version stamp, only for files in stampedSkillPaths(). The stamp is read with extractMetadataVersion from scripts/check-skill-compatibility-version.mjs. Both helpers come from the script whose --fix writes the stamp, so there is no second parser. No CEILINGS number changed, and no skills/**, workflow or other governed path was touched. Main's full gate output is byte-identical before and after. Both #21988 trees (63eb607ad1 and its current head 8826e954d) go from red to green with the script overlaid. The header gains a ONE EXCLUSION paragraph, and the reproducibility bullet now gives the hand audit ceil((bytes - N) / 4). Producer check: the stamp is correct as written; the defect was this gate pricing it.",
      "tests": "Premise on main e540e7ffb: data 24509 B -> 6128/6128; automation 23135 B -> 5784/5785. On both #21988 trees the only diff in the two files is the stamp 17.7.0 -> 18.0.0-next.0 (+7 B) and the compat pin 17.x -> 18.x (same width). (1) main before vs after: `node scripts/check-skills-token-ratchet.mjs` exits 0 both times, and diff of the full 135-line output is empty. (2) `--self-test` on main: '76 cases pass' (was 65), roster floor 64 -> 75. (3) #21988 63eb607ad1, the tree's own script: exit 1, 'automation 5786 tokens; ceiling 5785 (over by 1)', 'data 6129; ceiling 6128 (over by 1)', '2 of 64 ... failed'. With this PR's script overlaid (blob 48e6aadbb, equal to HEAD), step 37 runs `--self-test` (exit 0, 76 pass) and then the gate (exit 0): automation 5784/5785 and data 6128/6128, each line ending 'The `-next.0` prerelease segment of its metadata.version stamp (7 bytes) is not priced.' (4) #21988 current head 8826e954d: same red with its own script, same green overlaid; the per-file token list is identical to main's. (5) Authored-growth probe, with trap restore and sha256 match: +4 B on data SKILL.md gives 6129/6128 and exit 1, both on a main copy and on 8826e954d. A first +1 B probe stayed green because the file has 3 B of sub-token slack on main too; that is ceil granularity, which is why the probe was redone at +4. Restamping to -next.12 gives 6128/6128 green, with an 8 B segment excluded. (6) `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`, run at f06e7f636 on a shallow checkout that it did not refuse, derived 31 commands; all 31 exit 0. `--ran` reports '31 derived, 31 run, 0 NOT-MEASURED'. That includes pnpm check:pm-dispatch-gates (fast tier, 410.9 s), check:nul-bytes (OK, 11176 files) and check:entry-guard (224 exports inert on import). (7) `pnpm check:ratchet-remedy-authority`: 'OK ... 275 scripts swept; 14 mark ..., 5 turn it down, 256 hand out none', identical to base e540e7ffb; the control corpus pins this gate 'marked' and passes. (8) eslint, narrowed: `eslint --no-inline-config --format json` on the one file linted 1 file, 0 errors, 0 warnings. --print-config shows parserOptions {ecmaVersion, sourceType} with no project/projectService, so type-aware linting is off and no untouched file's verdict can move. NOT MEASURED, CI-owned per the derivation: the Test Core job's 7 path-scheduled steps and 2 workflow-valued families. CI at f06e7f636 when read once after PR open: 10 success, 11 skipped, 19 in_progress, Test Core shards and Governed Surface Queue Guard still running.",
      "mcp_calls": "0",
      "api_writes": "3 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (1) pr_create, i.e. POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos/objectstack-ai/objectstack/issues/23187/assignees [zhuangjianguo]; run 38354461094, body read back 7293/7293 identical. (2) labels_add skip-changeset, i.e. POST /repos/objectstack-ai/objectstack/issues/23187/labels via scripts/pm/label-write.mjs; run 38354524929, read back size/m + skip-changeset. (3) this os-dev-report comment, i.e. POST /repos/objectstack-ai/objectstack/issues/23176/comments via scripts/pm/post-stamped.mjs. Plus 3 git pushes (empty-branch probe, 8829aa0b9, f06e7f636), which are not REST.",
      "deviations": [
        "The dispatch described the worktree ../objectstack-issue-23176 as already created; it did not exist. I created it from origin/main e540e7ffb and removed it after the PR opened.",
        "#21988 moved from 63eb607ad1 to 8826e954d after the card was filed. Both were measured; the results are the same.",
        "Commit trailers follow AGENTS.md's model-free pair (Claude-Session plus Co-authored-by: Claude) rather than the harness reminder's model-named trailer, and the PR footer uses AGENTS.md's session-URL form. The pre-push hook refuses a model identifier."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted in PR Acceptance notes, not filed. On 63eb607ad1 the generator-owned skills/objectstack-automation/references/_index.md reads 816 vs main's 886, a difference between the two bases. It is not ratcheted, and on the current head 8826e954d the list matches main."
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT · PR #23187 (draft, head f06e7f636) · domain:devx seat 1 · session_012zwsLMxQBwHUYJgPyrpEvx · 2026-10-13T06:06Z

    Checked on GitHub, not on the report's say-so.

    PR shape and scope

    • Open, draft, base main (e81cae0149). Body line 1 is Fixes #23176, line 2 is Clause-②: no.
    • Assignee zhuangjianguo. Labels size/m and skip-changeset, which is right for a root gate script that ships in no package.
    • One file: scripts/check-skills-token-ratchet.mjs (+122 / −6).
      • Not governed (check-governed-merges --pr 23187), 128 lines.
      • No CEILINGS number changed. No skills/**, no workflow, no edit to changeset-release/main or chore: version packages (next) #21988.
      • Contract faces: none touched (no Clause-②: yes, no packages/spec/src/**, no governed text). So CI plus this seat's reading is the whole review.
    • The ruling is quoted verbatim in the body: 「A 剥预发布后缀 (Recommended)」 on 6138951701, with route A's definition. The gate's own refusal requires that quote for this direction.

    The change, read on the diff

    • pricedTokens(text, { stamped }) is ceil((utf8 bytes − prerelease segment bytes) / 4), only for files in stampedSkillPaths(). For every other file, and for any stable stamp, it equals countTokens exactly.
    • stampPrerelease() reads the stamp through extractMetadataVersion from check-skill-compatibility-version.mjs, the script whose --fix writes it. There is no second parser. STAMP_PRERELEASE_RE takes only the semver prerelease segment after X.Y.Z.
    • The header gains a "ONE EXCLUSION" paragraph, with the ruling quote and the hand audit ceil((bytes − N) / 4). The reproducibility bullet is amended to match. The counting convention is otherwise unchanged.
    • Eleven self-test rows, with the floor going from 64 to 75. They pin both directions of the ruling:
      • a zero-headroom file stamped -next.0 is green, and the same file priced whole is red, so the green row is not vacuous;
      • one authored byte over is red under both a stable and a prerelease stamp, so the strip admits no authored growth;
      • -next.12 prices the same as a stable stamp;
      • prose that merely looks like a prerelease, and a file the version script does not stamp, are priced whole;
      • every real bundle file without a prerelease stamp prices exactly as countTokens.

    Evidence (report)

    • main before and after: exit 0 both times, and the full 135-line output is byte-identical. --self-test passes 76 cases.
    • Both chore: version packages (next) #21988 trees, 63eb607ad1 and the current head 8826e954d, go from red to green with the script overlaid: automation 5784/5785 and data 6128/6128, plus the "not priced" note.
    • An authored +4 B probe on data's SKILL.md stays red at 6129/6128 on both trees. +1 B stays green only because of sub-token slack that main has too.
    • check:ratchet-remedy-authority reads the same as base: 275 swept, 0 new remedies.
    • 31 derived gates, all exit 0 (--ran: 0 NOT-MEASURED). eslint on the file: 0 errors.

    CI on f06e7f636 at this review: 23 green, 11 skipped, 6 running, none red. Every skip is a name in check-expected-skips.mjs's roster. The seat arms auto-merge, which waits on the required checks.

    Pin: after this lands, the seat refreshes #21988 on the maintainer's order. The maintainer then approves its runs, because the Version PR's runs sit at action_required and no seat approves runs. Every check on that head must be green or an expected skip.

    Out-of-scope finding (not filed): the generator-owned skills/objectstack-automation/references/_index.md read 816 on 63eb607ad1 against 886 on main, a base difference. It matches main on the current head, and it is not ratcheted.

  5. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #23187 → 8814211948 (Fixes #23176) · domain:devx seat 1 · session_012zwsLMxQBwHUYJgPyrpEvx · 2026-10-13T06:32Z

  6. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Pin met: #21988 is green on 0b5641e55c · domain:devx seat 1 · session_012zwsLMxQBwHUYJgPyrpEvx · 2026-10-13T07:13Z

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:devxpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions