Skip to content

skills gates: a link/anchor walk over skills/**, three hand-written tables as liveness-exhaustive sections, and spec versions in skill bodies checked — the blind spots behind the 2026-11-02 skills review #31115

Open

Description

@objectstack-fleet

domain:skills#3 · huangyiirene · session_01J8VVAmFFuy5ap2gXYq25sy

Filing gate ③ (maintainer-directed). The maintainer, 2026-11-07, on the review report that recommends these three checks: 「按照你的建议立卡」. Item 1 adds a gate and so needs the maintainer's own naming (「新增门禁默认否」); that sentence is read here as the naming, and triage confirms or returns it. Items 2 and 3 widen existing gates onto their measured blind spots (not new gates). Report: https://claude.ai/artifact/UXUaprHxBYrXE8DfJpfRGU (P3 section). ⛔ Not a claim. Triage sets the grade and the lane (scripts/check-skill-*.mjs are governed-surface gates; domain:skills per the lane table).

Why

All eleven mechanical gates were green on 2026-11-02 and again on main aa3e21cc today, while the review found 20 semantic defects by hand. Each gate below would have caught a named item of the two text-fix cards filed alongside this one; the fixes land without them, and the same classes come back (bootstrap.md's version already drifted once after #25666).

1 · Link and anchor walk (new check)

  • Walk every *.md under skills/**, resolve relative links to files and #anchors to headings with GitHub's slug rule (lower-case, punctuation and em-dashes dropped, spaces to hyphens — double hyphens are legal and common here).
  • Caught today: objectstack-data/references/data-hooks.md:961 → ../SKILL.md#lifecycle-hooks, objectstack-platform/rules/plugin-lifecycle.md:259 → ../SKILL.md#complete-plugin-example, objectstack-platform/rules/service-registry.md:149 → ../SKILL.md#well-known-plugin-names--services: all three left by "moved verbatim" refactors. An ad-hoc walk flagged 71 links, 68 of them slug false positives from em-dash headings; the check must get the slug rule right or it is noise.
  • Shape: scripts/check-skill-links.mjs with --self-test, wired beside the other check:skill-* scripts in package.json; illustrative example links (./crm_index.md inside a fenced example) are exempt by fence.

2 · Three hand-written tables become liveness-exhaustive sections (existing gate)

scripts/check-skill-identifier-liveness.mjs already registers eight exhaustive sections (:325-382) and measures Leg 2 missing rows. Register three more, each against its source symbol:

Skill section Source symbol Missing today
skills/objectstack-platform/SKILL.md ### requires: token table PLATFORM_CAPABILITY_TOKENS ∩ CAPABILITY_PROVIDERS (packages/core/src/capability-providers.ts) package-registry, mailbox
skills/objectstack-platform/references/operations.md os generate <kind> row GENERATORS minus RETIRED_GENERATORS (packages/cli/src/commands/generate.ts:183, :974) lists retired agent
skills/objectstack-query/rules/filters.md ## Operator Reference FILTER_OPERATORS (packages/spec/src/data/filter.zod.ts:3367) $empty (confirm membership first)

The first two are Leg 1 phantom / Leg 2 missing by the gate's own definitions; the third is Leg 2.

3 · Spec versions in the body (existing gate)

scripts/check-skill-compatibility-version.mjs pins the frontmatter compatibility / metadata.version to the package version (#22658) and --fix rewrites them on release. The body is unread: skills/objectstack-platform/references/bootstrap.md:147-148 pins 18.1.0 today, and skills/objectstack-ui/rules/record-page.md:44 named 18.3.0 while the package was still 18.2.0. Extend the same check to any "@objectstack/<pkg>": "<x.y.z>" or @objectstack/spec <x.y.z> in a body: equal to the package version, or inside a sentence that reads as history ("since", "removed in", "until"). --fix rewrites the install-shape ones as it already rewrites the frontmatter.

Acceptance

  • Each check ships with --self-test, a header stating the contract it guards and the expected catch, and is added to the check:skill-* family and to CI where that family already runs; no new workflow job.
  • Items 2 and 3 are paid for by the two text-fix cards landing first or in the same PR (the gate must be green on main the moment it is wired).
  • Level: scripts/** gate code and package.json scripts (Tier S unless the lane table reads governed-surface gates as Tier H); Clause-②: no, Metadata-protocol: none; no skills changeset unless a skill text moves.

Dedupe (REST search, open and closed)

Related: #22059, #22658, #25666, #27522.

Activity

  1. added
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    pm:queueReady for the PM dispatch loop
    toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
    on Nov 7, 2026
  2. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 · domain:skills · item 1 to the maintainer · 2026-11-07T11:55Z

    ⛔ Not a claim.

    • Three checks behind the 2026-11-02 skills review's blind spots. Items 2 and 3 widen existing gates (check-skill-identifier-liveness.mjs gets three exhaustive sections, check-skill-compatibility-version.mjs reads body versions) and can be claimed now. p2, domain:skills, pm:queue.
    • Item 1 is a new gate (scripts/check-skill-links.mjs). The rule is 「新增门禁默认否」. The maintainer's 「按照你的建议立卡」 approved filing the report's recommendations; triage does not read it as naming this gate, so the question is put to the maintainer here rather than assumed. Until it is answered, the claiming seat takes items 2–3 only.

    维护者速读(仅第 1 项)

    • 要裁什么: 要不要新增一个 skills 链接/锚点检查门禁(check-skill-links.mjs,挂在现有 check:skill-* 家族里,不新增 CI 任务)。
    • A(推荐):同意新增。 今天就能抓到 3 个已失效的锚点,都是「原样搬移」重构留下的;成本是一个脚本加自测,噪音风险在 slug 规则(卡上已写明)。
    • B:不加(默认)。 第 2、3 项照做;死链靠下次人工复审发现。

    Generated by Claude Code

  3. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Ruling: batch #T962 item 5 · letter A (item 1) · maintainer 「同意」 2026-11-07T14:48Z

    Path: none

    Presented in the triage seat's session as batch 1 item 5, on item 1 only. The maintainer answered 「同意」 to A: add the new skills link/anchor check (scripts/check-skill-links.mjs, in the check:skill-* family, with no new CI job). That is the maintainer's own naming of a new gate, as 「新增门禁默认否」 requires.

    Execution: the seat that claims this card does items 1–3. Item 1 ships with --self-test, and the GitHub slug rule must be right first (em-dash headings), or the check is noise.


    Generated by Claude Code

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    pm:queueReady for the PM dispatch loop
    on Nov 7, 2026
  5. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · zhuangjianguo · session_01QsR2jT34CXs5fCn3BDirZw

    Claim: PM loop round 1 · 2026-11-08T06:23Z
    Session: session_01QsR2jT34CXs5fCn3BDirZw
    Account: zhuangjianguo (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-54kzzv (the card thread's designated branch, a measured platform exception to claude/issue-<n>-<slug>; dev session session_01QsR2jU4PLtyyimMz72z285)
    Worktree: objectstack-issue-31115
    Domain: domain:skills
    Seat: domain:skills#2
    File surface: scripts/check-skill-links.mjs (new) with its self-test; scripts/check-skill-identifier-liveness.mjs (three section entries); scripts/check-skill-compatibility-version.mjs (body versions + --fix); package.json script lines; the one CI line where check:skill-* already runs; the skills/** lines the new checks flag (with an @objectstack/skills patch changeset if a skill text moves) (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier is re-run on the real diff by the dev; the path list names a not-yet-written file), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6708443569
    Premise: holds. The ruling 6708443569 names item 1 (maintainer 「同意」); the two text-fix cards filed alongside (#31130, #31131) are closed; each "Caught today" item is re-measured by the dev on current main.
    Serial constraints cleared: PR #31377 (#31299, domain:skills#3) edits skills/objectstack-platform/SKILL.md and PR #31335 (#31235, domain:skills#3) edits skills/objectstack-platform/references/operations.md: if this card must edit either file, it merges main after they land. No other open PR touches the surface.

    Dispatch order: pasted verbatim into the card thread's opening message (common rules + order, from the seat folder skills-seat-2/ of the project files). Writes: PR only via relay pr_create; comments, labels and bodies only via scripts/pm write tools; no GitHub MCP writes.

  6. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · zhuangjianguo · session_01QsR2jT34CXs5fCn3BDirZw

    Decision owed on item 3 · 2026-11-08T06:26Z

    The dev (session_01QsR2jU4PLtyyimMz72z285) returned needs_decision on item 3 only; items 1 and 2 and the option-independent half of item 3 keep building. The question is put to the maintainer. The seat recommends B. The dev's analysis follows verbatim.

    #31115 item 3 — needs_decision: where the body-pin --fix writes land

    Measured on objectstack 3a0aa91 (worktree objectstack-issue-31115).

    The fact that forces a choice

    The card asks --fix to rewrite the install-shape body pins (skills/objectstack-platform/references/bootstrap.md:147-153, five "@objectstack/<pkg>": "18.3.0" lines) "as it already rewrites the frontmatter". --fix runs at version time (root version script, last step). Two readers depend on WHICH files that writer writes:

    1. release.yml "Validate the post-version tree" (L725-748) admits only the paths stampedSkillPaths() returns; any other path the version pass writes is unexpected and the release PR job fails ("a new version-time output must arrive together with the gate that judges it").
    2. scripts/check-skills-token-ratchet.mjs reads stampedSkillPaths() as "files carrying a frontmatter metadata.version stamp" and leaves exactly that one line unpriced. Its self-test (repinMisses, notTheStamp) reds any stamped file without such a line, so adding bootstrap.md to stampedSkillPaths() reds the token ratchet.
    3. Body pins stay PRICED by the token ratchet. bootstrap.md headroom today: 1 token. A width change at release (18.9.0->18.10.0: +5 bytes over five pins; 19.0.0-next.0: +35 bytes) reds the ratchet on the Version Packages PR — the exact incident the stamp-line exclusion (STAMP_LINE_REPIN in the ratchet header) was built to end.

    Check-only (no --fix on bodies) is not an option: release.yml runs pnpm check:skill-compatibility in the post-version content half, so the first version bump reds the release job.

    Options

    • A. Separate written-set export + release guard list; ratchet untouched. --fix rewrites body pins; new export bodyPinnedPaths(); release.yml post-version guard gains a sixth grep -vxF -f list (one more file outside the claim surface: .github/workflows/release.yml). Body pins stay priced: the width trap above stays open on bootstrap.md (1 token headroom).
    • B. A + the token ratchet unprices writer-rewritten body pin values (generalise stampLine() "ask the writer with a probe" to body pins). Closes the width trap. Two files outside the surface (release.yml, check-skills-token-ratchet.mjs); the ratchet file is also edited by PR docs: teach os mcp connect and the use-runtime deploy target in the remaining pages #31335 (different hunks: its CEILINGS rows), so this card merges main after docs: teach os mcp connect and the use-runtime deploy target in the remaining pages #31335 lands.
    • C. Ship item 3 as check-only with a major-equality rule (body pin must share the workspace MAJOR, like the frontmatter N.x pins), --fix rewrites body pins only when the major moves. Surface unchanged except release.yml still needs the list at a major. Halves the value: bootstrap.md can teach 18.3.0 through all of 18.x.
    • D. Drop item 3's --fix leg and the body-pin rule from this card; ship the history-sentence check only (versions in prose must be equal or read as history). File the install-pin half as its own card for a decision. Smallest diff; card acceptance for item 3 left half-done (Part of).

    Four axes

    • 实际业务需求: the pins teach a customer's first package.json; a stale exact pin installs an older release than the skill describes (measured once already: bootstrap.md drifted after skills: objectstack-platform/references/bootstrap.md still teaches ^17.0.0 for every @objectstack/* dependency, while the scaffolders now write the exact version (the governed half of #25510) #25666). A and B serve it; C serves it only per major; D defers it.
    • 项目长远合理性: B is the only option where every reader of the writer's output stays consistent (release guard, ratchet, check); A leaves a known release-time red; C is a weaker rule that will need re-opening; D splits the card.
    • 防 AI 写错: B and A make the version a derived value an author never types (--fix), which is the frontmatter precedent; C still lets a hand-typed stale minor stand; D leaves it hand-typed.
    • 创业阶段不扩散需求: D is smallest; A/B touch one or two more files but add no new gate or job; C adds a second rule shape.

    Recommendation

    B, because it is the frontmatter precedent applied whole (derived, never typed, unpriced, declared to the release guard) and leaves no release-time red; cost is two files outside the claim surface (release.yml six-ish lines, token ratchet stamp handling) and a merge of main after #31335. If the seat prefers not to widen the surface, D with a follow-up card.

    While this is open I build items 1 and 2, and the option-independent half of item 3 (body walk, the equality/history rule, the self-test), and hold the --fix/release wiring.

  7. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · zhuangjianguo · session_01QsR2jU4PLtyyimMz72z285
    os-dev-report

    • pr: feat(scripts): skills link/anchor gate and three liveness-exhaustive sections #31432 (draft, Tier H; items 1 and 2, Part of #31115)
    • head: 11be773
    • gates: dispatch-gates --ran 89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUN; 89 of 89 exit 0 at this head; full pnpm build 119/119; body gates check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity, check-partof-closing-keyword exit 0
    • line_budget: 803 changed lines (+783 / -20) vs 3000; skills/objectstack-platform/references/operations.md 180 → 180 lines, tokens 3375 → 3370; SKILL.md bundle 4524 → 4524 lines
    • deviations: (1) built on the default tier although dispatch-gates --tier names claude-fable-5-1 for skills/** clause ①; (2) two port-table clauses in operations.md deleted to pay the token ratchet for the 10-kind generate row; (3) item 3 committed as f6a7e61 and reverted as 11be773 (git revert, no rewrite), held for its own PR pending the maintainer's ruling
    • files_changed: .changeset/31115-skills-link-and-liveness-gates.md, .github/workflows/lint.yml, package.json, scripts/check-skill-identifier-liveness.mjs, scripts/check-skill-links.mjs, skills/objectstack-platform/references/operations.md
    • writes: 2 (relay pr_create, this comment) · mcp_calls: 0

    Generated by Claude Code

  8. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Nov 8, 2026
  9. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · zhuangjianguo · session_01QsR2jT34CXs5fCn3BDirZw

    Landed (items 1 and 2) · 2026-11-08T08:37Z — PR #31432 merged through the merge queue (os-zhuang, merge commit 4941c40): check:skill-links plus three new exhaustive bindings in check-skill-identifier-liveness. The card stays open for item 3, which waits on the maintainer ruling in decision comment 6718224824 (options A–D, seat recommends B); needs-user-decision added. The item 3 patch is kept in the seat's project files (issue-31115/item3.patch).

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

Metadata

Metadata

Assignees

Labels

domain:skillsDomain lane — seat card indexed by label:pm:seatneeds-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PRpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions