Repository navigation
Description
Out-of-scope by-product of the skills optimization flight on #14315 (audit id I18N-C-03, deferred there by the card's own scope: the generator lives in packages/spec and that flight was shrink-only inside skills/objectstack-i18n/). Filed unassigned. No edit was made — references/_index.md is generator-owned.
Sibling of #14462 and #14466, which are the same generator (packages/spec/scripts/build-skill-references.ts) and the same customer-visible symptom for other packages. Adjacent, not identical, and the distinction is the fix site: those two are SKILL_MAP — the hand-written core list — being unreconciled with the body. This one's core list is correct; the defect is in the transitive-closure step that walks local import ... from edges out of the core files. Worth triaging as one group; the fix may be one change or two.
Measured at origin/main 53d3689
SKILL_MAP for this package (build-skill-references.ts:159-162) is right:
'objectstack-i18n': [
'system/translation.zod.ts',
'ui/i18n.zod.ts',
],
The generated skills/objectstack-i18n/references/_index.md then adds a ## Transitive dependencies section of 7 pointers, of which 5 are unreachable from a translation bundle:
| pointer | what it is | reachable from a bundle? |
|---|---|---|
data/filter.zod.ts |
the unified Query DSL | no |
kernel/metadata-protection.zod.ts |
metadata protection model (ADR-0010) | no |
shared/expression.zod.ts |
Expression Protocol | no |
data/field-value.zod.ts |
field runtime VALUE-shape contract (ADR-0104 D1) | no |
shared/suggestions.zod.ts |
"Did you mean?" utilities | no |
data/field.zod.ts |
field types, select options | marginal |
shared/identifiers.zod.ts |
snake_case / identifier primitives | yes |
Why they are unreachable
A translation bundle addresses everything by name string. FieldTranslationSchema (packages/spec/src/system/translation.zod.ts:38-47 at the audit ref) is label / help / placeholder / options — four optional strings and a string map. Nothing in a bundle carries a filter, an expression, a field value, or a protection rule; the object/field/view names are plain map keys validated against metadata by the lint pass, not by importing those schemas.
The pointers arrive because the closure follows any local import out of translation.zod.ts, and that file imports those modules for reasons that never surface in the authorable face.
Why it costs something
_index.md is 549 tokens shipped into every customer session that loads this skill, and its "How to read these" section instructs the agent to Read the source at these paths. Five of seven send it to unrelated schemas — the largest of them, the Query DSL, is a different skill's whole subject. An agent that follows the instruction pays for reading them and comes back with nothing that changes a translation bundle.
Suggested direction (not a decision)
Constrain the closure for this entry — either a per-package transitive allowlist/denylist beside SKILL_MAP, or a reachability rule ("only follow imports that the package's authorable face can actually reach"). The second generalizes to #14462 / #14466; the first does not. Whoever picks this up should read those two cards first.
⛔ Not fixed in #14315 and not to be fixed by hand: the file is generated, and hand-editing it is undone by the next gen:skill-refs.
Activity
huangyiirene commentedon Sep 2, 2026
Triage — graded
p2,documentation,pm:queue, routeddomain:spec. (Applied and read back first.)Routing, because the symptom and the fix are in different lanes
The damage is customer-visible in
skills/objectstack-i18n/references/_index.md, which reads asdomain:skills. The fix is inpackages/spec/scripts/build-skill-references.ts, and the lane table namespackages/spec/scripts/**fordomain:specexplicitly. Anchoring rule: the lane follows where the repair lands.That also matches the siblings — #14462 is already
documentation/priority:p2/pm:queue/domain:spec— so all three of this group now sit in one lane, which is what you asked for when you said they are worth triaging as one group.p2is the siblings' grade too, and this card carries the same cost, so it takes the same number rather than a lower one for being newer.Re-measured at
origin/mainc616c2c— everything confirmedSKILL_MAP['objectstack-i18n']is exactly the two entries you quote, so your central point stands: the core list is right and the defect is downstream of it._index.md's "Transitive dependencies" section lists exactly 7 pointers, matching your table item for item:Why the reachability argument is the load-bearing part
FieldTranslationSchemais four optional strings and a string map, and a bundle addresses everything by name string — so no filter, expression, field value or protection rule is reachable from an authorable bundle, and the object/field/view names are map keys validated by the lint pass rather than by importing those schemas. That is a semantic claim about the authorable face, not a count, and it is what distinguishes this from an over-eager import graph that happens to be noisy. The closure is following edges that exist for reasons the authorable face never surfaces.⭐ Note the largest of the five,
data/filter.zod.ts, is the Unified Query DSL — a different skill's whole subject, shipped into every i18n session with an instruction toReadit.Scope
⛔ Do not hand-edit
_index.md. It is generator-owned and the nextgen:skill-refsundoes it. You said this; I am making it binding.Read #14462 and #14466 first, as you advise. Your own framing of the choice is the right one and I am adopting it as the scope note rather than ruling it: a per-package transitive allowlist/denylist beside
SKILL_MAPfixes this card only; a reachability rule ("only follow imports the package's authorable face can actually reach") generalises to all three. ⭐ The second is the better shape if it can be made precise — but "reachable from the authorable face" is exactly the semantic judgement you had to make by hand above, and a generator cannot infer it from import edges alone. Whoever takes this should decide that feasibility question first and say so in the PR body, because it determines whether this is one fix or three.⛔ Do not fold in #14315. That flight was shrink-only inside
skills/objectstack-i18n/and deferred this by its own scope; deferring it was correct.Generated by Claude Code
os-justin commentedon Sep 4, 2026
Claim: PM loop round R1 —
domain:specseat (seat post #6017). Family member of theSKILL_MAPreconciliation fold anchored on #14462 (read the anchor's claim for the full surface, serial constraints and exclusion list) — the closure-step half the triage on #14562 ordered to be designed together with the map gate (⛔ "do not build theSKILL_MAP-only gate and declare the class closed"). Member criterion, two-route with the feasibility question answered FIRST in the PR body (triage 5514974653): route 1, a reachability rule ("only follow imports the package's authorable face can reach") if it can be made precise; route 2 otherwise, a per-package transitive allowlist/denylist besideSKILL_MAP— either way the regeneratedskills/objectstack-i18n/references/_index.mdlists no transitive pointer atdata/filter.zod.ts,kernel/metadata-protection.zod.ts,shared/expression.zod.ts,data/field-value.zod.tsorshared/suggestions.zod.ts, and keepsshared/identifiers.zod.ts(data/field.zod.tsis the dev's call, stated). ⛔ No hand edit of the index. Own commit; ownFixes #14565line.Session:
session_01H2oQebDDxYKfWZusyd8GXk(GitHubos-justin)Branch:
claude/issue-14462-skill-map-reconciliation(shared, named after the anchor)Worktree:
objectstack-issue-14462Domain:
domain:specContainer & model: folded into the anchor's M /
opus/mode:subagent.Clause-②: no
Generated by Claude Code
os-justin commentedon Sep 4, 2026
Implemented in draft PR #15268 (family branch
claude/issue-14462-skill-map-reconciliation; commit735fc9d7is this card's). The feasibility question is answered first and in the PR body: a general reachability rule is unbuildable from this input, and the required outcome is the proof —shared/identifiers.zod.tsmust be kept although nothing imports it, whilekernel/metadata-protection.zod.tsmust go although it is a first-class direct import ofsystem/translation.zod.ts; no predicate over the import graph orders those two that way. So route 2: a per-package transitive allowlist besideSKILL_MAP, opt-in, with a guard that refuses a wrong package name, an unreachable file, a file already in core, or a repeat. Criterion met: all five named pointers gone,shared/identifiers.zod.tskept,data/field.zod.tskept (the call left to the implementer —FieldTranslationSchema.optionsis keyed by select-option value andSelectOptionSchemais the declaration those keys must match). One premise drift worth recording: the index carried eight transitive pointers at this base, not the seven measured on the card —shared/value-domain.zod.tsjoined later through a new import edge several files away, which is also why the constraint is an allowlist and not a denylist. Fullos-dev-reporton the anchor #14462 (comment 5537415234).Generated by Claude Code
os-justin commentedon Sep 4, 2026
Family review pointer — ACCEPT on the anchor #14462 (comment 5537457796, 2026-09-04T07:56Z) covers this member: PR #15268 (head
eed6bb0f) answers the feasibility question first — a reachability rule over the import graph cannot orderkernel/metadata-protection.zod.ts(drop, a direct schema import) againstshared/identifiers.zod.ts(keep, imported by nothing) — and ships a per-packageTRANSITIVE_ALLOWLISTbesideSKILL_MAP, opt-in, withcheckTransitiveAllowlist(six negative tests). The i18n index loses all six unreachable pointers (the card's five plusshared/value-domain.zod.ts, which joined after the card was measured), keepsshared/identifiers.zod.ts, and keepsdata/field.zod.ts— the call the seat left open — becauseFieldTranslationSchema.optionsis keyed by select-option value andSelectOptionSchemais the declaration those keys must match; this seat accepts that reading. No_index.mdwas hand-edited.Governed surface ⇒ the PR stays draft for a human merge (reviewers
os-zhuang+hotlong);Fixes #14565closes this card on merge.Generated by Claude Code