Skip to content

Split oversized skill cards along task lines; subset fences; shared filters reference - #136

Merged
ysyneu merged 4 commits into
feat/ai-srefrom
feat/skill-cards-split
Aug 6, 2026
Merged

Split oversized skill cards along task lines; subset fences; shared filters reference#136
ysyneu merged 4 commits into
feat/ai-srefrom
feat/skill-cards-split

Conversation

@ysyneu

@ysyneu ysyneu commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What

Splits the two oversized skill cards along task lines and adds the generator support that makes the split possible:

  • skilldoc subset fences — a GENERATED: fence id can now be group[verb-prefix,…]: a subset fence claiming every verb starting with one of the prefixes, while the bare-group fence renders the unclaimed remainder (catch-all). gen/check discover fences by scanning the cards for markers instead of assuming one file per command group. New topology validation: a verb claimed twice, a prefix claiming nothing, unclaimed verbs with no catch-all, and duplicated fences all fail gen and surface as fence-topology issues in check.
  • channel.md → channel.md + escalation.md + noise.md — channel CRUD stays; escalate-rule-* (dispatch/escalation policy) and silence-rule-* / inhibit-rule-* / unsubscribe-rule-* (noise reduction) get their own cards.
  • incident.md → incident.md + postmortem.md — the 13 post-mortem-* verbs move out; triage/investigation stays together (those verbs interleave in real flows).
  • New reference/filters.md — shared reference for filters / source_filters / target_filters: OR-of-AND shape, IN/NOTIN semantics including the missing-key trap (NOTIN on a key the object doesn't carry matches everything), /regex/ values, construction-from-incident-labels rules, and the per-rule-family key vocabulary. The rule cards and alert.md's pipeline section point here instead of restating it.
  • Canonical keys only — guidance now teaches severity / status / data_source_id; the per-surface aliases (event_severity, alert_severity, incident_severity, alert_status, incident_status, integration_id) always carry the same stored value as the canonical key and are called out as never-use. On incident-scoped rules alert_severity is an alias of the incident's severity, so spelling it invites wrong reads.
  • SKILL.md router — narrowed channel row, new escalation/noise/postmortem rows, shared-reference note for filters.md.

Why

A reference card is the second level of progressive disclosure: the router sends a task to one card. When one card carries four rule families beside channel CRUD (367 lines) or a whole post-mortem surface beside triage (508 lines), every task pays for the whole domain, and guidance competing for attention within one card is exactly how a hot-flow example gets misread. Card sizes after the split: channel 112, escalation 122, noise 205, postmortem 160, filters 77, incident 420.

Verification

  • go test ./... green; new fence-topology tests in internal/skilldoc/fence_test.go and split-across-cards gen tests in internal/cmd/skilldoc/main_test.go.
  • skilldoc gen regenerated every fence from the live CLI tree; skilldoc check reports cards OK.
  • Cross-reference sweep: no remaining pointers to the moved sections.

🤖 Generated with Claude Code

ysyneu added 4 commits August 5, 2026 23:44
A fence id can now be group[verb-prefix,...]: a subset fence claiming every
verb starting with one of the prefixes, while the bare-group fence renders
the unclaimed remainder as the catch-all. gen/check discover fences by
scanning the cards for markers instead of deriving one filename per group,
so a large command group's reference card can be split along task lines.
Topology violations (a verb claimed twice, a prefix claiming nothing,
unclaimed verbs with no catch-all, a duplicated fence) fail gen and are
reported by check as fence-topology issues.
channel.md (367 lines) carried four rule families beside channel CRUD, and
incident.md (508) carried the whole post-mortem surface — every task paid
for the whole domain, and the guidance competing for attention is exactly
how a hot-flow example gets misread. Split along task lines using subset
fences:

- channel.md → channel CRUD only; escalation.md (escalate-rule-*);
  noise.md (silence-rule-*, inhibit-rule-*, unsubscribe-rule-*)
- incident.md → triage/investigation; postmortem.md (post-mortem-*)
- filters.md: new shared reference for filters/source_filters/
  target_filters — OR-of-AND shape, IN/NOTIN semantics incl. the
  missing-key trap, /regex/ values, construction-from-labels rules, and
  the per-family key vocabulary. Consumer cards and alert.md's pipeline
  section point here instead of restating it.
- Canonical keys only: guidance now teaches severity/status/
  data_source_id; the per-surface aliases (event_severity,
  alert_severity, incident_severity, alert_status, incident_status,
  integration_id) always carry the same stored value and are called out
  as never-use.
- SKILL.md router: channel row narrowed; new escalation/noise/postmortem
  rows; shared-reference note for filters.md.
… guard splice index; single-file two-fence test

- filters.md: integration_id is not a legacy alias — the server accepts it
  and data_source_id interchangeably (the API's response docs in fact
  deprecate data_source_id), so present the pair as equivalent and keep the
  never-use list to the severity/status aliases, scoped to rule-evaluation
  time.
- runGen: check the start-marker index before slicing the body with it.
- New TestRunGen_TwoFencesInOneFile pins the sequential splice loop for a
  subset fence and catch-all living in one card.
…corpus load, FindFence

- Prefix claims are now hyphen-boundary-bounded (verb == p or p + "-"):
  an unbounded match could misroute a near-miss verb (rule2-list under
  rule-) with a clean single-owner partition no topology check would
  flag. Fence ids normalized to the boundary-safe form
  (incident[post-mortem]); a trailing-hyphen prefix now claims nothing
  and dies loudly as a dead-prefix violation.
- runGenAll loads the card corpus once and threads it through every
  group via genGroup (was one full reload per group); genGroup updates
  the in-memory docs after each write so later groups see current
  content. runGen's docOrder/byPath bookkeeping dropped — it iterates
  the docs slice directly.
- New skilldoc.FindFence(body, id) centralizes start/end-marker location
  for both gen and check (the two ad-hoc copies had already drifted in
  error wording); hasCatchAll bool and a no-op map insert removed;
  CheckFences reuses groups(d)'s existing order instead of re-sorting.
@ysyneu
ysyneu merged commit 824acfb into feat/ai-sre Aug 6, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant