feat(scripts): lint-skill-frontmatter — enforce required keys on SKILL.md frontmatter (soc-e8pj #skill-md-frontmatter-linter)#376
Open
boshu2 wants to merge 1 commit into
Conversation
1c381f3 to
f9d20fe
Compare
38ab179 to
c32983d
Compare
boshu2
added a commit
that referenced
this pull request
May 20, 2026
… 1 #catalog-generator) (#379) ## Why `registry.json` (47KB) is too coarse — agents grepping for "which skill produces a ratchet?" have to scan markdown. Hand-curated /skills tables drift. Future `ao skill new` scaffolders need a queryable inventory. This is slice 1 of soc-vuu6.4 (the generator + schema + CI gate). Go CLI subcommands and showcase consumer are filed as follow-up beads. ## What Three artifacts: 1. `schemas/skill-catalog.schema.json` — JSON Schema for the catalog. Required fields: name, description, hexagonal_role, consumes, produces, context_rel, user_invocable, references_count, codex_override_present. hexagonal_role enum mirrors soc-e8pj/PR #376. 2. `scripts/generate-skill-catalog.sh` — walks every `skills/*/SKILL.md`, parses YAML frontmatter via awk, emits `skills/catalog.json` with all 79 skills. Modes: default (write), `--check` (CI drift gate, exits 1 on drift), `--stdout`, `--out PATH`. 3. `scripts/check-skill-catalog-drift.sh` — thin wrapper over `--check` so the future workflow has a stable, named entry point. 4. `skills/catalog.json` — generated artifact, committed. 79 skills, 40KB. The parser handles the SKILL.md frontmatter subset we actually use: scalar key:value, lists (`- item`), and `context_rel` nested objects (`- kind:` / `with:`). A regression test covers the "last context_rel entry dropped on transition to next scalar" parser bug caught during development. ## Test 14 bats tests, all passing. Cover: envelope fields, name/description extraction, list round-trip, context_rel parsing (incl. the regression for the dropped-last-entry bug), user_invocable boolean, references_count, codex_override_present, default file-write, `--check` pass + drift detection, drift wrapper exit codes, empty-skills case, unknown-flag error. Self-dogfood: real skills/ tree → 79 skills generated, all 4 keys validated by lint-skill-frontmatter (#376), drift check green. ## Follow-up beads filed - Slice 2 — `ao skills list/consumers/producers/graph` (Go CLI subcommands, blocks on this PR) - Slice 3 — Showcase consumes catalog.json instead of hand tables Closes-scenario: soc-vuu6.4#catalog-generator Bounded-context: BC1-Corpus Evidence: scripts/generate-skill-catalog.sh Evidence: scripts/check-skill-catalog-drift.sh Evidence: tests/scripts/generate-skill-catalog.bats Co-authored-by: Codex <codex@example.invalid>
c32983d to
0a934d3
Compare
…L.md frontmatter (soc-e8pj #skill-md-frontmatter-linter)
Walks every skills/*/SKILL.md, validates name/description/hexagonal_role/consumes/produces/context_rel. hexagonal_role enum: {domain, driving-adapter, driven-adapter, supporting, generic}. Modes: --check --list --json --skill.
Backfills the 3 missing keys on expert-council/SKILL.md so the linter ships strict from day one. Self-dogfood: 79 clean.
Closes-scenario: soc-e8pj#skill-md-frontmatter-linter
Bounded-context: BC1-Corpus
Evidence: scripts/lint-skill-frontmatter.sh
Evidence: tests/scripts/lint-skill-frontmatter.bats
0a934d3 to
8b4ba5b
Compare
boshu2
added a commit
that referenced
this pull request
May 21, 2026
…e-2-of-3) (#393) ## Why soc-dspz asks for 3 advisory I0 jobs to wire in. Two of the three source scripts are already on `main` (after PRs #373, #379 merged); the third (`scripts/lint-skill-frontmatter.sh` from #376) is still pending merge. Per the new agile invariant (soc-5qit, PR #392), the right move is to ship the unblocked part and leave the parent bead open for the third when #376 lands — instead of waiting for everything. ## What changed | Surface | Change | |---|---| | `.github/workflows/validate.yml` | Added 2 stanzas: `lint-evidence-lines-advisory` (PR-event triggered) and `check-skill-catalog-drift-advisory` (skills/CI path-filtered). Both `continue-on-error: true` so they emit `::warning::` annotations without blocking merges. | | `.github/workflows/validate.yml` summary job | `needs:` extended with both new advisory jobs. | | `docs/contracts/ci-jobs.yaml` | 2 manifest entries, alphabetically slotted. | | `AGENTS-CI.md` | Regenerated via `scripts/generate-ci-jobs-table.sh --write` (69 rows). | ## Promotion path Per soc-dspz acceptance: I0 advisory → T2 required after one clean week of runs. File a follow-up bead to flip `continue-on-error: true` off and promote both jobs to required. ## What's NOT in this PR - `lint-skill-frontmatter-advisory` — depends on PR #376 (open) adding `scripts/lint-skill-frontmatter.sh`. soc-dspz stays open after this merges; a follow-up small PR will add that 3rd stanza once #376 lands. ## Validation - `python3 -c 'import yaml; yaml.safe_load(...)'` parses both YAML files clean - `scripts/validate-ci-policy-parity.sh`: `CI_JOBS_TABLE: PASS (69 rows)` Closes-scenario: soc-dspz#wire-2-of-3 Bounded-context: BC4-CI Evidence: scripts/validate-ci-policy-parity.sh
Owner
Author
|
Parking pending soc-g2qd (/evolve --mode=loop epic). Both this PR's surface and the epic touch overlapping infrastructure; resolving the upstream contract first avoids rebase churn. Will rebase + resume after epic ships. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The hexagonal-architecture model generates
docs/contracts/context-map.mdfrom everyskills/*/SKILL.mdfrontmatter (hexagonal_role,consumes,produces,context_rel). When a SKILL.md misses one of those keys, the generated map drifts silently and the next consumer (e.g.,soc-vuu6.4's skills/catalog.json work) hits surprises. Today 1-of-79 skills (expert-council) was missing the three list keys.What
scripts/lint-skill-frontmatter.sh— walks everyskills/*/SKILL.md, parses the YAML frontmatter, and validates:name,descriptionpresent + non-emptyhexagonal_role∈ {domain, driving-adapter, driven-adapter, supporting, generic}consumes,produces,context_relkeys present (value may be empty list)Modes:
--check(default; exits 1 on any miss),--list(per-skill report),--json(machine),--skill <name>(scope to one).Also backfills the 3 missing keys on
skills/expert-council/SKILL.mdso the linter can ship strict from day one (mirrors thecouncilparent skill it aliases).Test
15 bats tests, all passing. Cover: clean skill / each missing-key case / invalid enum value / empty value / all 5 valid enum values / no-frontmatter /
--skillscoping / unknown-skill error /--listformat /--jsonshape / no-skills-dir graceful / unknown-flag error.Self-dogfooded: linter run on the full skills/ tree → 79 clean (after the expert-council backfill).
Closes-scenario: soc-e8pj#skill-md-frontmatter-linter
Bounded-context: BC1-Corpus
Evidence: scripts/lint-skill-frontmatter.sh
Evidence: tests/scripts/lint-skill-frontmatter.bats