Skip to content

docs(skills): cite the platform-tool registry instead of restating it - #17259

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-16853-cite-tool-registry
Sep 10, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-16853-cite-tool-registry

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #16853

The 〈Naming the tools: the resolution ladder〉 passage in skills/objectstack-ai/SKILL.md restated the platform-tool registry — three tool counts and two source line ranges — instead of citing it. Triage's ruling on the card is taken over the card's own minimum:

the passage restates the registry instead of citing it. Correcting three numbers buys one release; making the passage cite platform-tool-names.ts as the authority ends the class. The claiming seat should prefer the second even though the card only asks for the first.

So no number and no range is replaced with a fresher one. They are removed, and the passage cites the registry and the resolver by symbol. There is nothing left in the passage that a registry change can falsify.

Before / after

Before (the two spots this PR touches):

A `skill.tools[]` entry resolves against the union of three sources
(`packages/lint/src/validate-ai-tool-references.ts:148-171`):
...
2. **`PLATFORM_PROVIDED_TOOL_NAMES`** — the 30 statically-registered platform
   tools, grouped by owning package in
   `packages/spec/src/system/constants/platform-tool-names.ts:38-82` — 6 data /
   knowledge tools from `service-ai` (`query_records`, `get_record`,
   `query_data`, `aggregate_data`, `search_knowledge`, `visualize_data`) and 24
   schema / metadata / package tools from `service-ai-studio`. Read that file for
   the exact set: it is the registry the lint rule checks against.

After:

A `skill.tools[]` entry resolves against the union of three sources
(`collectToolUniverse` in `packages/lint/src/validate-ai-tool-references.ts`):
...
2. **`PLATFORM_PROVIDED_TOOL_NAMES`** — the statically-registered platform
   tools, flattened from `PLATFORM_TOOLS_BY_PACKAGE` in
   `packages/spec/src/system/constants/platform-tool-names.ts`: data /
   knowledge tools from `service-ai`, schema / metadata / package tools from
   `service-ai-studio`. Read that file for the exact set: it is the registry
   the lint rule checks against.

Items 1 and 3 of the ladder, and every other line of the file, are untouched. The diff is 7 insertions / 8 deletions in one file.

Measurements — every fact the passage keeps, and where it was read

All read on origin/main 5a95b0e9 (the branch point), never copied from the card.

fact the rewritten passage asserts measured how
collectToolUniverse is the resolver livepackages/lint/src/validate-ai-tool-references.ts:144, body ends :163 grep -n; this is why the removed :148-171 was already wrong, independently of PR #16844
PLATFORM_TOOLS_BY_PACKAGE is the registry livepackages/spec/src/system/constants/platform-tool-names.ts, :38 to :87 grep -n
PLATFORM_PROVIDED_TOOL_NAMES is flattened from it true — it is a Set over Object.values(PLATFORM_TOOLS_BY_PACKAGE).flat() at :93-94 source read
grouped by exactly two owning packages, service-ai and service-ai-studio trueObject.keys returns exactly those two, in that order tsx import of the module
PLATFORM_TOOL_FAMILY_PREFIXES (kept from the old text, untouched) live — same file, :107 grep -n

Measured and then deliberately not written into the file: service-ai holds 6 names, service-ai-studio 29, flattened total 35, and the registry object ends at :87. Those confirm the card's predictions (30 → 35, 24 → 29, 38-82 → 38-87) exactly — and they are precisely the values this PR deletes rather than refreshes.

The six service-ai names — the ruling's conditional, answered

The card's shape allowed keeping the six inline names only if they are still exactly that group and the passage's own reason for listing them survives. Both halves were measured:

  • Still exactly the group: yes. The six names in the old text are set-equal to PLATFORM_TOOLS_BY_PACKAGE['service-ai'] today (aggregate_data, get_record, query_data, query_records, search_knowledge, visualize_data).
  • The reason does not survive. The list existed as the concrete half of a count breakdown — "6 data / knowledge tools … and 24 schema / metadata / package tools". With the counts gone, an exhaustive inline copy of one group is the same restatement under a different spelling: it goes stale the next time a tool is added to service-ai, and it is exactly Leg 2 of check-skill-identifier-liveness's own measured defect class — "a doc enumeration presented as exhaustive stopped growing when the schema did". The passage already tells the reader to open the file for the exact set.

So they are dropped into the citation. What is kept is each group's character — data / knowledge from service-ai, schema / metadata / package from service-ai-studio — which is structure rather than a count, and tells a reader which group to look in without naming a member.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack from the real change set (1 path, committed), then reconciled with --ran:

✓ dispatch-gates --ran: 24 derived famil(ies) accounted for — 24 run, 0 NOT-MEASURED.

All 24 exit 0. The verdict lines that carry this card's specific content:

✓ check-skills-token-ratchet: skills/objectstack-ai/SKILL.md is 5444 tokens (ceiling 6806; headroom 1362).
check-skill-identifier-liveness OK — Leg 1: 463 citation(s) over 46 published file(s) checked against 100771 implementation word tokens
check-skill-compatibility: 11 pinned major(s) all match the workspace (@objectstack/spec is 17.x)
check-skill-frame-sync: 4 axes … binding sentence present in all 2; 4 count mention(s) agree
governed-surface predicate: ⛔ GOVERNED — a human merge is the review record for this PR (#9495 regime).

One gate refused before measuring anything on the first pass and is reported honestly: pnpm --filter @objectstack/lint run check:doc-formula-expressions exited 3 with PREREQUISITE NOT MET — the workspace package @objectstack/formula is not built. That is not a finding. After pnpm exec turbo run build --concurrency=2 --filter=@objectstack/formula --filter=@objectstack/lint (under the shared verify lock, VERDICT command-exit 0), it re-ran at exit 0.

pnpm --filter @objectstack/spec run check:skill-refs was run in addition to the 24 — AGENTS.md's regeneration table names it for any SKILL.md body change, while the path derivation does not. It is green (9 generated files in sync with packages/spec), and check:skill-docs is green too: that generator reads only the YAML frontmatter, which this PR does not touch, so neither skills/README.md nor content/docs/ai/skills-reference.mdx moves.

Repo-wide pnpm lint is CI's run, not this PR's; no package source is touched, so no build closure beyond the one a gate demanded above.

Size — the published catalog is priced in tokens, and this PR pays in

reading before after delta
skills/objectstack-ai/SKILL.md lines 417 416 -1
skills/objectstack-ai/SKILL.md tokens 5467 5444 -23
whole catalog, all 11 SKILL.md — lines 6853 6852 -1
whole catalog, all 11 SKILL.md — tokens 79679 79656 -23

Net decrease on both units, so nothing is bought on credit and no ceiling moves. The ceiling was not lowered even though the gate invites it ("A ceiling may be LOWERED by any PR that shrinks its file"): that edit lands in scripts/check-skills-token-ratchet.mjs, outside this card's declared one-file surface. It is left for a maintainer or a follow-up.

Changeset — measured, not assumed

No changeset is added, because nothing published moves:

  • No package ships this path. Every tracked package.json in the workspace was read; not one files[] array names skills at any depth. @objectstack/spec ships dist, json-schema, liveness, prompts, llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface, spec-changes.json; @objectstack/cli ships dist, README.md, CHANGELOG.md.
  • Symbol grep with a positive control. Searching every built dist/, packages/spec/prompts/, packages/spec/llms.txt and every package README.md for the passage's text (resolution ladder) returns 0 hits. The positive control — a string known to be published, Machine name (snake_case) — returns hits in 3 files under packages/spec/dist/. So the search reaches published bytes and this passage is not among them.
  • The one generator that reads this file writes nowhere published: build-skill-docs.ts regenerates skills/README.md and content/docs/ai/skills-reference.mdx from the frontmatter only, and check:skill-docs is green with no drift.

node scripts/check-changeset-no-major.mjs --base origin/main — exit 0:

Diffing HEAD from 5a95b0e93 (merge base with origin/main).
✓ This diff introduces no `major` bump.

skip-changeset is the correct disposition, and the label is applied on this PR.

维护者速读(草稿)

改了什么 — 只改一段已发布的 skill 散文:skills/objectstack-ai/SKILL.md 里讲「一个 skill 的工具名去哪里解析」的那段。原文把平台工具注册表的内容抄了一份进来(30 个工具、6 个 / 24 个的分组、两处源码行号区间),现在改成指过去:点名 PLATFORM_TOOLS_BY_PACKAGE 这个注册表和 collectToolUniverse 这个解析函数,不写数量、不写行号。一个文件、7 增 8 删,无代码改动。

为什么改 — 这些数字没有任何程序在读,却要求每次注册表变化都手工同步一次,而事实是没人同步:validate-ai-tool-references.ts 的行号区间在 PR #16844 之前就已经错了,三个数量则在 #16844 合并当天全部作废。这段文字会被整份装进客户的 AI 上下文,写错就是每个客户项目里被执行一次的错误指令。定级席位的原话是「Correcting three numbers buys one release; making the passage cite platform-tool-names.ts as the authority ends the class」——改数字只买一个版本,改成引用才终结这一类问题。本 PR 取后者。

风险与代价(含回滚) — 风险极低:纯散文,零运行时影响,零 API 变化,不发布任何包(已实测,见上)。代价是读者少了六个工具名的「即看即得」——换来的是这段话不会再过期,而且它原本就已经写着「Read that file for the exact set」。回滚就是 git revert 这一个提交,不牵连任何其它文件、不需要重新生成任何产物。24 个门禁族全绿。

席位意见

你要做的 — ① 这是受管面(skills/**),必须人工合并,任何 AI 席位都不会点 ready、不会入队、不会开 auto-merge;请确认后手动合并。② 如果你更希望保留那六个工具名(理由:给读者一个具体的手感),请直接说,我改回去——但那样就需要一个会在数量漂移时变红的检查,否则第四次手工订正还会漏。③ token 上限(6806)这次没有下调,虽然文件已经降到 5444;下调要动 scripts/ 下的门禁脚本,超出本卡声明的文件面,留给你或后续 PR 决定。

Acceptance notes

  • Scope held to one passage in one file. The card and the dispatch both fence this to skills/objectstack-ai/SKILL.md; no packages/**, no scripts/**, no other skill file, and no rider. A single governed path makes the whole diff human-merge-only, so a mixed diff would have changed this PR's landing route.
  • The card's alternative was declined by construction. It offered "keep the numbers and add a check that fails when they drift". Taking the citation route leaves no number for such a check to read, so no new reader was written.
  • Same class, elsewhere in the same file — noted, not filed. Four other passages cite sources with line ranges: packages/spec/src/ai/skill.zod.ts:37-51, 139-202, packages/spec/src/stack.zod.ts:595-602, packages/spec/src/ai/agent.zod.ts:36-40, and packages/spec/src/ai/agent.zod.ts:234, :251. All four were spot-checked and are accurate today (:37 and :51 land on the two trigger-operator constants; :139 and :202 bracket the refinement and the schema that calls it), so none is a defect now — but they carry the same drift liability this card is about. Left alone deliberately: this card is fenced to one passage, and a governed-surface PR that quietly widened its own file surface would be the wrong precedent. Successor: whoever next edits one of those passages, or a dedicated follow-up card if a maintainer wants the class closed file-wide.
  • The ratchet ceiling was not lowered — see the Size section. Deliberate, and outside the declared file surface rather than overlooked.
  • No new identifiers were introduced that the liveness gate would have to learn. collectToolUniverse, PLATFORM_TOOLS_BY_PACKAGE, PLATFORM_PROVIDED_TOOL_NAMES and PLATFORM_TOOL_FAMILY_PREFIXES are all live symbols in the tree, verified before naming any of them; check:skill-identifier-liveness is green.

Generated by Claude Code

The resolution-ladder passage in `skills/objectstack-ai/SKILL.md` carried
three tool counts and two source line ranges. Counts and ranges are copies
of the registry, so every registry change owed this passage a correction
that nobody made: the `validate-ai-tool-references.ts` range was already
wrong before the registry grew, and the counts went stale on the merge that
added tools.

Cite by symbol instead. `collectToolUniverse` names the resolver and
`PLATFORM_TOOLS_BY_PACKAGE` names the registry, both without ranges; the
per-package character of each group stays (structure, not counts) and the
passage keeps telling the reader to open the file for the exact set. Nothing
in the tree read the removed numbers, so no gate or generator follows.

Claude-Session: https://claude.ai/code/session_01MoTv7pn338AZ71owsp19gQ
Co-authored-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

维护者速读

改了什么 — 只改一段已发布的 skill 散文:skills/objectstack-ai/SKILL.md 里讲「skill 的工具名去哪里解析」那段。原文把平台工具注册表抄了一份进来(30 个工具、6 / 24 的分组、两处源码行号),现在改成指过去:点名 PLATFORM_TOOLS_BY_PACKAGE 这个注册表和 collectToolUniverse 这个解析函数,不写数量、不写行号;六个工具名随计数一并去掉,「读那个文件取准确集合」的句子保留。一个文件,7 增 8 删,无代码改动。

为什么改 — 这些数字没有任何程序在读,却要求注册表每变一次就手工同步一次,而事实是没人同步:行号区间在 PR #16844 之前就已经错了,三个数量在 #16844 合并当天全部作废。这段文字会整份装进客户的 AI 上下文,写错就是在每个客户项目里被执行一次的错误指令。分诊席的判断是「改数字只买一个版本,改成引用才终结这一类」,本 PR 取后者。

风险与代价(含回滚) — 纯散文、零运行时影响、不发布任何包(dev 三种方法实测不欠 changeset)。代价是读者少了六个工具名的即看即得,换来这段话不会再过期。四个被引用的符号在树上都在,skills 门禁与 CI 全绿。回滚 = revert 这一个提交。

席位意见 — 本席以契约复审档复核通过:改法与裁决一致、段内无残留数字、引用符号全部在树、合并无冲突。建议合并。同文件另有四处按行号引用的段落今天仍准确,同类隐患,不在本卡范围,若你想整文件一次清掉,说一声我立一张卡。

你要做的 — 受管面走人工合并:看一眼改后的那段,认可即批准并合并本 PR。是否合并?


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation needs-user-decision size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants