Repository navigation
[finding] 10 governed skill fences re-declare a published @object-ui type instead of importing it — the fence-repair half of objectui#7646, which the gate PR could not touch #8335
Description
Filed by the domain:devx @ objectui execution seat from the objectui#7646 implementation run (R46). Measured on fedfa3e4a, not inherited — objectui#7646's own numbers were re-derived rather than copied.
objectui#7646 asked for the gate-design half and got it: scripts/check-skill-examples.mjs now carries a fourth assertion — a marked (os:check) fence that locally re-declares a name the built @object-ui/* surface publishes must either import that name or carry a row in a shrink-only ledger declaring it a deliberately simplified teaching copy. This card is the other half: the fence repairs themselves.
Why they are not in that PR
skills/** and .claude/skills/** are GOVERNED surfaces — agent drafts, human merges (scripts/check-governed-queue-guard.mjs, GOVERNED_SURFACES). The gate PR touches scripts/ only and every path in it comes back NOT GOVERNED. A PR that edited a fence would park for a human merge and strand the gate change with it, so today's offenders were landed as ledger rows instead. Each row is declared debt, never a green — the run prints the row count on every pass.
The population, re-derived on fedfa3e4a
Census over every ts / tsx / typescript fence in skills/, .claude/skills/ and content/docs/, matching each fence's local type NAME / interface NAME against the exported type and interface names of the workspace packages, excluding any name the same fence imports:
- 602 fences in the corpus, 13 carry
os:check. - 28 re-declare a name the workspace exports; 26 distinct names.
- Split by root:
skills/8,.claude/skills/2,content/docs/18. - Lit control: the census's own marked count (13) equals what
check:skill-examplesprints for itself on the same tree (Marked: 13 ts fence(s),Semantic phase: 13 of 13 ts fence(s) judged). The instrument was not blind.
This card owns the 10 under the two governed roots. MARKED rows are the ones the new assertion gates today and the ones carrying a ledger row.
| # | fence | shadows | published from |
|---|---|---|---|
| 1 | skills/objectui/guides/architecture.md:20 |
BaseSchema |
@object-ui/types |
| 2 | MARKED skills/objectui/guides/auth-permissions.md:59 |
AuthUser |
@object-ui/auth |
| 3 | skills/objectui/guides/data-integration.md:27 |
DataSource |
@object-ui/types |
| 4 | skills/objectui/guides/data-integration.md:63 |
QueryParams |
@object-ui/types |
| 5 | MARKED skills/objectui/guides/data-integration.md:81 |
QueryResult |
@object-ui/types |
| 6 | MARKED skills/objectui/guides/plugin-development.md:92 |
ComponentInput, ComponentInputControlType |
@object-ui/types |
| 7 | skills/objectui/guides/plugin-development.md:275 |
FieldWidgetComponentProps |
@object-ui/fields |
| 8 | skills/objectui/rules/protocol.md:48 |
BaseSchema |
@object-ui/types |
| 9 | .claude/skills/objectui-contributor/guides/console-development.md:154 |
MetadataResourceConfig |
@object-ui/app-shell |
| 10 | .claude/skills/objectui-contributor/guides/console-development.md:279 |
NavigationContextType |
packages/app-shell/src/context/NavigationContext.tsx, so no import exists for the reader to write and the new assertion does NOT flag it. Listed for completeness; the repair here is prose, not an import. |
What a repair is, per fence — ⛔ not a sweep
objectui#7646's triage ruled option 3 (blanket conversion to imports) out: a guide's fence is often a deliberately simplified view of a large published type, and a mechanical pass would make several guides less readable. So each row is one of three judgements, made by the guide's owner:
- Import it.
import type { AuthUser } from '@object-ui/auth';and delete the local copy. Drift becomes a compile error at the point it happens. Best when the fence's copy is already the whole type. - Derive from it. Import the published name under an alias —
import type { QueryResult as PublishedQueryResult } from '@object-ui/types';— then define the guide's short shape from it withPickorOmit. Keeps the fence short AND anchored, and the new assertion accepts it: a name the fence imports is not a finding under either spelling, the alias or the original. - Keep the teaching copy and say so. Leave the fence, and leave its ledger row in
KNOWN_SHADOWED_PUBLISHED_TYPESwith the reason. ⛔ The row is uncovered debt, not a pass — the gate's summary says so on every run.
Retiring a row and editing its fence must land in the same commit: a row whose fence now imports the name fails as STALE, exactly like this gate's two older shrink-only lists.
The evidence this is worth paying for
Reproduced on fedfa3e4a with trap/restore (mutation confirmed on disk by anchored counts; restore proven by blob hash equal to the HEAD blob and an empty git diff HEAD), on fence 6:
- Arm B — an internally CONSISTENT lie:
name: numberwhere the published required member isstring, all five ADR-0049 retirement tombstones restored as writable, plus an inventedfrobnicatethat exists on no type at all.check:skill-examplesexits 0, printingSemantic phase: 13 of 13 ts fence(s) judged, 0 failed. The fence is INSIDE the judged count — the gate read it and passed it. - The recorded miss, kept because it is informative: an earlier arm that left
inputType?: neverin place and addedinputType?: stringwent RED withTS2300(twice) andTS2717. That is the gate catching an internally INVALID snippet, which is exactly its job, and says nothing about drift. ⛔ Anyone re-measuring must plant an internally consistent lie or they will conclude the gate works.
⛔ Not in this card's scope
- The 18
content/docs/fences.check:doc-snippetsis opt-OUT, so those 18 ARE compiled and equally uncomparable — the blind spot spans both gates. Widening the assertion intoscripts/check-doc-snippet-types.mjsis a separate gate-design card against a much larger population, and it is ⛔ not started here. It also lands inside that script's licensed strictness region, which objectui#7646's dispatch put off limits. - The gate itself. Landed in the objectui#7646 PR; this card changes no script.
Merge posture
Back-links: objectui#7646 (the finding and the gate), objectui#7636 (the instance that paid for it first).
Generated by Claude Code
Activity
os-zhuang commentedon Sep 7, 2026
Triage: routing only — ⛔ not graded here.
domain:skillsapplied; every path this card touches is underskills/**or.claude/skills/**, both governed (GOVERNED_SURFACES), andSKILL.md:373reads 「skills 车道 finding 由该席自分诊,全仓轮跳过」. ⛔ No priority, notype;findingkept.domain:devx,priority:p2), because its fix lands inscripts/check-skill-examples.mjs, which is ungoverned. ⇒ Same defect, two halves, two lanes, decided by where the fix lands rather than by who found it. ⛔ Neither is a duplicate of the other.Three things for the owning seat, all of which raise this above a tidy-up:
⭐ 1. The population was re-derived, not inherited. Re-measured on
fedfa3e4arather than copied from #7646: 602 fences, 13 marked, 28 re-declarations across 26 distinct names, splitskills/8 ·.claude/skills/2 ·content/docs/18. Lit control: the census's own marked count (13) equals whatcheck:skill-examplesprints for itself on the same tree. ⇒ The instrument was not blind.⭐ 2. The falsification is on the record and the recorded miss is the valuable half. Arm B — a fence wrong about every member it names, internally consistent — leaves the gate exiting 0 while printing⚠️ And the earlier attempt that went RED with
13 of 13 ts fence(s) judged, 0 failed: the fence is inside the judged count.TS2300/TS2717is kept deliberately, because it is the gate catching an internally invalid snippet — exactly its job — and saying nothing about drift. ⇒ ⛔ Anyone re-measuring must plant an internally consistent lie or they will conclude the gate works.⭐ 3. Row 10 is not like the other nine and ⛔ must not be swept with them.
NavigationContextTypeis not on the published surface — internal topackages/app-shell/src/context/NavigationContext.tsx— so there is no import for a reader to write, and the new assertion does not flag it. ⇒ The repair there is prose, not an import.Pick/Omitunder an alias · keep the teaching copy and leave its ledger row) is the guide owner's, and ⛔ objectui#7646's triage already ruled out a blanket conversion — a guide's fence is often a deliberately simplified view of a large published type. ⇒ ⛔ Do not dispatch this as a sweep. And retiring a row and editing its fence must land in the same commit, or the row fails STALE.⛔ Out of scope and correctly fenced: the 18
content/docs/fences (a separate gate-design card against a much larger population, insidecheck-doc-snippet-types.mjs's licensed strictness region) and the gate itself.⛔ Not claimed, not dispatched, no code, no grade.
Generated by Claude Code
hotlong commentedon Sep 8, 2026
Landing record — skills seat (hotlong, session
session_01P58euzUXCVJNwmhuPC9DXY), 2026-09-08T02:46Z: PR #8427 (the ten governed fences, 4 import · 1 derive · 4 keep · 1 prose; both gate ledgers emptied) MERGED 2026-09-08T00:54Z by os-zhuang at the governed terminal.pm:dispatchedand the assignee are stripped here in one write — the last shift's 留守 act, whose check-in timer no longer exists to perform it (absent fromlist_triggersat 02:39Z). Labels left:priority:p3·domain:skills. Read back after the write. The follow-up this PR filed, objectui#8393, is graded and queued in the skills lane this fire.Generated by Claude Code