Skip to content

Commit 4941c40

Browse files
feat(scripts): skills link/anchor gate and three liveness-exhaustive sections (#31432)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} --> _Requested by **Steedos** · [project thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbPjpDtuAfMiZPGY3g5SZw34)_ Part of #31115 (items 1 and 2). Item 3 follows in a separate PR. Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么:** 新增 skills 链接/锚点检查 `check:skill-links`(按 GitHub 的标题锚点规则核对 `skills/**` 里每个相对链接),并让现有的标识符存活检查多守三张表:`requires:` 能力表、`os generate` 那一行、过滤运算符表;`os generate` 行顺手补全为 10 种类型。 - **为什么改:** 11 月 2 日的技能复审手工找到了 3 个失效锚点和这几张表的缺漏,而当时所有门禁都是绿的;这两项让同类问题以后在 PR 上直接变红(维护者已对新增门禁回复「同意」)。 - **风险与回滚:** 只加检查脚本和一行技能文字,不改任何运行时代码;main 上新检查全绿(248 个链接 0 失效)。回滚即 revert 本 PR。 - **先看:** `scripts/check-skill-links.mjs`(锚点规则 `githubSlug`,误报风险所在);`scripts/check-skill-identifier-liveness.mjs`(新的 `literalMembersOf` 读取器与三条绑定);`.github/workflows/lint.yml`(新增的一个步骤)。 - **两分钟验证:** 运行 `pnpm check:skill-links`,应看到自测 22 条全过,以及「248 relative link(s) … resolve」。 - **需要你做的:** 这是受管面 PR(`skills/**` 与 `.github/workflows/**`),需要一位受管审批人批准(APPROVED review)。 ## What changes - **`scripts/check-skill-links.mjs` (new) + `check:skill-links`.** Walks every `*.md` under `skills/**` and resolves each relative link: the file must exist, and a `#fragment` on a markdown target must match a heading slug under GitHub's own rule (rendered text, lower-case, punctuation and em-dashes deleted, spaces to hyphens with no collapsing, `-N` for repeats) or an HTML `id`/`name`. Fenced code, inline code spans, HTML comments, absolute URLs and fragments on non-markdown targets are not judged. Exit 0 / 1 (dead link) / 2 (prerequisite, including a lit control on the live link count). Battery-floored `--self-test` with the verdict handshake, copied from `check-skill-top-level-keys.mjs`; it reproduces the three moved-verbatim links from the review and pins each slug case (em-dash, code span, emoji, intra-word underscore, duplicates). - **Wiring.** `package.json` `check:skill-links` (`--self-test && scan`); one step in `lint.yml` `typecheck-source-gates`, beside `check:skill-top-level-keys`, `continue-on-error` with an `id:` so the lane verdict carries it. No new job. - **`scripts/check-skill-identifier-liveness.mjs`: three Leg 2 bindings.** - `requires-capability-tokens`: platform SKILL.md `### requires:` section against `PLATFORM_CAPABILITY_TOKENS` ∩ `CAPABILITY_PROVIDERS`. - `generate-kinds`: operations.md `## Build & runtime`, row `os generate <kind>`, against `GENERATORS` minus `RETIRED_GENERATORS`; a retired kind listed in the row is its own red (`[leg2-retired-row]`). - `filter-operators`: filters.md `## Operator Reference` against `FILTER_OPERATORS` (`$empty` is a member, confirmed on main). - To read these, the gate gains `literalMembersOf` (a string array or an object literal's top-level keys, read by name with a character scanner that refuses spreads and computed keys), `intersect` / `minus` set algebra and an optional `row` scope on a binding. `extractSymbols` is unchanged, so `--suggest` is unchanged. - **`skills/objectstack-platform/references/operations.md`.** The `os generate <kind>` row listed four kinds in prose; it now lists all ten. Two restating clauses in the same file's port table pay for the bytes (line count 180 → 180; tokens 3375 → 3370). - **`.changeset/31115-skills-link-and-liveness-gates.md`**: `@objectstack/skills` patch. ## Why All the mechanical skill gates were green while the 2026-11-02 review found these defects by hand. The maintainer approved the new gate (ruling 6708443569, 「同意」 to letter A). Items 2 and 3 widen existing gates onto their measured blind spots. ## Tests <details><summary>Self-tests and scans at the final head</summary> - `pnpm check:skill-links`: self-test 22 cases pass; scan "248 relative link(s) in 71 published skill file(s) resolve; 119 fragment(s) name a real heading". - `pnpm check:skill-identifier-liveness`: self-test OK (new battery "LEG 2: string arrays, object keys, set algebra and row scope", 15 cases; roster floor 10 → 11); scan OK, "Leg 2: 11 registered exhaustive section(s), 0 ledgered gap(s)". - Live mutation (restored, `git diff HEAD` empty afterwards): `agent` added to the generate row reds `[leg2-retired-row]`; the `mailbox` row deleted from the requires table reds `[leg2-missing-row]`. - `node scripts/check-skills-token-ratchet.mjs`: exit 0 (operations.md 3370 / 3375). - `pnpm exec eslint --no-inline-config` on the touched scripts: exit 0. </details> ## Acceptance notes - **Re-measure of the card on main.** Item 1: the three named anchors already resolve on main (the text-fix cards #31130 and #31131 landed first); the new gate is green there. Item 2: `package-registry` and `mailbox` are already in the requires table, `$empty` already in the operator table, and the generate row no longer names `agent`; but the row listed only four of the ten kinds, so it was red as an exhaustive row and is fixed here. - **Item 3 is not in this PR.** Where its `--fix` writes land (the release post-version guard reads `stampedSkillPaths()`, and the token ratchet prices body pins) is open with the maintainer; it follows in its own PR. - **Not judged by the link gate:** whether a link that leaves `skills/` reaches a file that also ships in the published package. - **`skills/**` readings:** operations.md 180 → 180 lines; the bundle (all SKILL.md) 4524 → 4524 lines. ## Verification - Head `11be7732` (merge base `cd6618e88`). Full workspace `pnpm build`: 119 of 119 tasks. - `node scripts/pm/dispatch-gates.mjs --ran`: 89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUN. All 89 exit 0, rerun at this head after the item-3 revert, including `check:doc-formula-expressions`, `check:dts-closure`, `check:dual-build-cjs-loads`, `check:lean-entry-closure` and `check:sourcemap-no-sources-content` on the built tree. - Left to this PR's check-runs: the artifact-roster and wide-population families, the path-scheduled CI jobs, the type-check lanes and the always-runs tail that dispatch-gates prints outside the derived total. - Deviations: `dispatch-gates --tier` names claude-fable-5-1 for `skills/**` (clause 1); this was built on the default tier. The two port-table clauses in operations.md were deleted to pay the token ratchet for the longer generate row. Item 3 was committed and then reverted on this branch with `git revert` (no history rewrite), so `scripts/check-skill-compatibility-version.mjs` is byte-identical to main. --- _Generated by [Claude Code](https://claude.ai/code/session_01QsR2jU4PLtyyimMz72z285)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent bc3d8c6 commit 4941c40

6 files changed

Lines changed: 783 additions & 20 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/skills': patch
3+
---
4+
5+
docs(skills): the operations reference's `os generate <kind>` row names every kind the CLI scaffolds
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
`skills/objectstack-platform/references/operations.md`: the `os generate <kind>` row listed four kinds in prose ("an object / view / flow / skill"); it now lists all ten `GENERATORS` keys (`object` `view` `action` `flow` `dashboard` `app` `skill` `picklist` `permission` `dataset`). The liveness gate now holds that row exhaustive against `GENERATORS` minus `RETIRED_GENERATORS`, so a new generator without a row, or a retired one (`agent`, `schema`) listed again, reds. Two restating clauses in the same file's port table ("so several example apps run side-by-side", "It never silently drifts") were deleted to pay the token ratchet for the longer row.

‎.github/workflows/lint.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5385,6 +5385,14 @@ jobs:
53855385
continue-on-error: true
53865386
run: pnpm check:skill-top-level-keys
53875387

5388+
# Rationale: `scripts/check-skill-links.mjs` header (#31115). Same job, no
5389+
# paths filter: a section moved between skill files breaks the links INTO
5390+
# it from files the move never touched.
5391+
- name: Check every relative link and anchor in the published skills resolves
5392+
id: check-every-relative-link-and-anchor-in
5393+
continue-on-error: true
5394+
run: pnpm check:skill-links
5395+
53885396
# Rationale: `scripts/check-agent-model-declared.mjs` header (#6803, #6686).
53895397
- name: Check every agent definition declares a model
53905398
id: check-every-agent-definition-declares

‎package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"check:skill-frame-freshness": "node scripts/check-skill-frame-freshness.mjs --self-test && node scripts/check-skill-frame-freshness.mjs",
6969
"check:skill-compatibility": "node scripts/check-skill-compatibility-version.mjs --self-test && node scripts/check-skill-compatibility-version.mjs",
7070
"check:skill-top-level-keys": "node scripts/check-skill-top-level-keys.mjs --self-test && node scripts/check-skill-top-level-keys.mjs",
71+
"check:skill-links": "node scripts/check-skill-links.mjs --self-test && node scripts/check-skill-links.mjs",
7172
"check:agent-model-declared": "node scripts/check-agent-model-declared.mjs --self-test && node scripts/check-agent-model-declared.mjs",
7273
"check:agent-test-spelling": "node scripts/check-agent-test-spelling.mjs --self-test && node scripts/check-agent-test-spelling.mjs",
7374
"check:ratchet-remedy-authority": "node scripts/check-ratchet-remedy-authority.mjs --self-test && node scripts/check-ratchet-remedy-authority.mjs",

0 commit comments

Comments
 (0)