Skip to content

Commit ea0708c

Browse files
huangyiireneclaude
andauthored
Two-legged identifier-liveness gate over the published skills catalog (#13678) (#13892)
* feat(devx): two-legged identifier-liveness gate over the published skills catalog Leg 1 (phantom row): a skills/** table row citing an identifier that greps to zero in packages/** is a red. Leg 2 (missing row): a section REGISTERED as exhaustive over a schema symbol that does not document every member is a red. One corpus walk, two legs. Leg 2 is table-driven rather than inferred, and that is a measurement result: auto-binding a doc table to any enum it is a subset of scores 1 true positive in 3 on this corpus. The heuristic ships as --suggest, which cannot fail. Zero skills/** edits: the five surviving Leg 1 sites and the one measured Leg 2 gap are ledgered, not fixed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EnE7G31tqbxN1rqpQmzurT * chore(devx): register the liveness gate with the farm's convention gates - check-ratchet-remedy-authority CONTROL row (the sweep classified it `marked` before the row was written; the row is recorded from that verdict). - bare-root-worklist: REFUSE-WIDE for IMPL_ROOTS `packages` — the word index reads 5405 of 5640 tracked files (96%), so the population IS the root and a true declaration would name this gate on every card touching any package. - The watch-hint self-test asserts the spelling without writing a second declaration site; spelling it as a regex literal made the real one unjudgeable ("2 declaration sites"). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EnE7G31tqbxN1rqpQmzurT --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4902a25 commit ea0708c

6 files changed

Lines changed: 1280 additions & 0 deletions

File tree

.github/workflows/lint.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,38 @@ jobs:
18621862
- name: Teaching-corpus lexical anti-drift ratchet
18631863
run: pnpm check:corpus-claim-drift
18641864

1865+
# #13678: the third gate over this corpus, and the only one asking an
1866+
# EXISTENCE question rather than a lexical one. The two steps above ask
1867+
# whether a forbidden word appears, and whether a spelling stands next to
1868+
# prose naming a semantic it does not have. This one asks, in both
1869+
# directions, whether the identifiers the catalog names and the schema
1870+
# members it enumerates are the same set:
1871+
#
1872+
# Leg 1 (phantom row) a table row citing an identifier that greps to
1873+
# zero in `packages/**` is a red. Measured: 3 of 6
1874+
# falsehoods in one skill were this class, every one
1875+
# catchable by a single grep of the cited name.
1876+
# Leg 2 (missing row) a section REGISTERED as exhaustive over a schema
1877+
# symbol that does not document every member is a
1878+
# red. Measured on a later flight: 15 of 20.
1879+
#
1880+
# Leg 2 is table-driven rather than inferred, and that is a measurement
1881+
# result, not a preference — auto-binding a doc table to any enum it is a
1882+
# subset of scored 1 true positive in 3 on this corpus, because deliberate
1883+
# subsets ("Three action types dispatch headlessly") and semantically mixed
1884+
# enums are indistinguishable from real gaps without a human. The heuristic
1885+
# ships as `--suggest`, which cannot fail anything.
1886+
#
1887+
# It lives in this job for the reason every other docs guard does
1888+
# (`check:doc-anchors`, `check:role-word`, `check:corpus-claim-drift`
1889+
# above): this job carries the whole `check:*` gate family and has no paths
1890+
# filter. That matters more here than for its neighbours — the gate's two
1891+
# inputs are `skills/**` and `packages/**`, so a paths filter on either
1892+
# would let the OTHER side drift a member in or an identifier out without
1893+
# ever running the check that notices.
1894+
- name: Published-skills identifier liveness gate (two legs)
1895+
run: pnpm check:skill-identifier-liveness
1896+
18651897
# #11671: `os i18n extract --fill=default` fills GAPS only, so revising a
18661898
# source string rewrites `en` and strands the previous source text in every
18671899
# other locale. The bundle stays in sync BY KEY, so `check:i18n` reports OK

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"check:template-version-sync": "node scripts/sync-template-versions.mjs --self-test",
5656
"check:role-word": "node scripts/check-role-word.mjs --self-test && node scripts/check-role-word.mjs",
5757
"check:corpus-claim-drift": "node scripts/check-corpus-claim-drift.mjs --self-test && node scripts/check-corpus-claim-drift.mjs",
58+
"check:skill-identifier-liveness": "node scripts/check-skill-identifier-liveness.mjs --self-test && node scripts/check-skill-identifier-liveness.mjs",
5859
"check:quick-reference-counts": "node scripts/check-quick-reference-counts.mjs --self-test && node scripts/check-quick-reference-counts.mjs",
5960
"check:overlay-whitelist-table": "node scripts/check-overlay-whitelist-table.mjs --self-test && node scripts/check-overlay-whitelist-table.mjs",
6061
"check:runtime-services-index": "node scripts/check-runtime-services-index.mjs --self-test && node scripts/check-runtime-services-index.mjs",

scripts/check-ratchet-remedy-authority.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,34 @@ const CONTROL = {
756756
why: 'PR for #13582. Its per-file, per-rule baseline is shrink-only; the author\'s remedy is to reword the sentence, and the baseline path that admits a genuinely true construction beside a pinned spelling is offered only as a maintainer\'s.',
757757
},
758758

759+
// The eleventh, and the third gate over the published catalog (#13678). It
760+
// carries TWO offers on ONE ledger file and both are marked, which is why the
761+
// row is worth reading rather than counting:
762+
//
763+
// LEG 1 offers an EXEMPTION — "this identifier is live somewhere this repo
764+
// cannot index". That half is shrink-only BY CONSTRUCTION rather than by
765+
// policy: `--update` prunes entries the scan no longer reaches and there is
766+
// no code path that adds one, because the `kind`/`note` a row must carry are
767+
// human judgements nothing in the tree encodes. A hand edit is therefore the
768+
// only way in, and it is the maintainer's.
769+
//
770+
// LEG 2 offers a GAP entry — a measured count of schema members a section
771+
// registered as exhaustive does not document. That half IS regenerated from
772+
// the tree, so its flag moves whichever way the tree moved and only policy
773+
// tells a ratchet-down from a weakening apart. Same treatment as the two
774+
// `--update` gates above.
775+
//
776+
// Both messages offer the author's own remedy first and unmarked (correct the
777+
// row; document the member), which is the shape this convention wants.
778+
//
779+
// ⚠️ Recorded from the sweep's own verdict — this gate reported it as `marked`
780+
// before the row was written, and the row was written because the sweep
781+
// demanded it. Author intent and detector agreeing is the point of the corpus.
782+
'check-skill-identifier-liveness.mjs': {
783+
expect: 'marked',
784+
why: 'PR for #13678. A two-legged liveness gate over skills/**: a row citing an identifier that greps to zero, and a section registered exhaustive that omits a live schema member. One ledger, two halves — the Leg 1 exemptions are shrink-only by construction (--update only prunes them), the Leg 2 gaps are a regenerated shrink-only ratchet — and both weakening paths are the maintainer\'s, offered after the author\'s own.',
785+
},
786+
759787
// ── Declaration registries and near-misses: recording the fact IS the fix ──
760788
'check-agent-model-declared.mjs': {
761789
expect: 'excluded',

0 commit comments

Comments
 (0)