Skip to content

#1126 Check a package's own guidance content before it ships - #1138

Merged
williamthorsen merged 8 commits into
mainfrom
1126
Jul 31, 2026
Merged

#1126 Check a package's own guidance content before it ships#1138
williamthorsen merged 8 commits into
mainfrom
1126

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Jul 31, 2026

Copy link
Copy Markdown
Owner

What

Adds a validate command that checks the CodeAssembly guidance bundled with a package and reports all defects found. The check covers every type of content and all harnesses to which it could be deployed.

Why

Opening guidance production to any npm package left every correctness gate still assuming the content root was this repository's own. A package could publish guidance it had no way to check, and a consuming repository got only partial cover, because its checks ran over the closure it declared rather than over the catalog its dependencies ship. When a mechanism opens to third parties, what guards it has to be reachable as a command.

Details

🎉 Features

  • codeassembly-agents validate runs the checks a consumer's install runs before writing — dependency closure, artifact resolution, delivery collisions, and a per-harness render — over a whole content root, requiring no consuming declaration and writing nothing.
  • The root comes from --content <dir>, or from the codeassembly.content key the package's package.json already declares; neither yielding one is an error naming both routes.
  • --harness narrows the run to one harness; the default checks every harness the root could deploy to, so a defect that reaches only one is not missed. A defect every harness raises collapses to a single line, while one confined to a subset names the harnesses it reaches.
  • Coverage is everything the root ships that reaches a consumer: rulebooks, skills, subagents, collections, and the support entries under skills/ that carry no SKILL.md.
  • Defects are confined to artifacts the content root owns. A dependency edge still resolves into the built-in library so it resolves the way it will at a consumer, but a library defect is not reported against a path the producer does not have; an edge that resolves from nowhere is still reported, against the artifact that declared it.
  • A clean root exits 0; any defect exits 1 after a report grouped by file.

🐛 Bug fixes

  • A SKILL.md that is itself a directory is no longer mistaken for a skill, so an entry carrying one installs as the support content it is. Such an entry previously deployed through neither pass — skipped by the installer as the sync pass's to handle, and absent from the catalog the sync pass walks.
  • Installing from content that ships no skills/ directory names the missing path and says what it skipped, the way a missing scripts/ or guidance directory already does.

♻️ Refactoring

  • Four rules that the install, sync, and validate passes each have to apply identically now have one definition apiece: what counts as a skill directory, which entries under skills/ are support content, the harness-relative prefix a deployed skill's links are built under, and how a support entry renders. Each was previously copied per caller.
  • Source-directory validation and the two skill-name collision rules are available to callers outside the sync command, which previously held them privately. Each collision rule comes in two forms — one returning the collisions it finds, one throwing on the first — so a caller that must collect every defect and a caller that must stop before writing share one rule.
  • Each CLI subcommand group resolves in its own function, bringing the top-level dispatcher back under the configured complexity ceiling.

📚 Documentation

  • The command list and flag reference cover validate and --content, and the package-producer walkthrough shows how to wire the check into a producer's own build, what it covers, and which exit code each outcome carries.

Closes #1126

…dules

Source-directory validation and the two skill-name collision rules are available to callers outside the sync command, which previously held them privately. Each collision rule now comes in two forms: one that returns the collisions it finds, and one that throws on the first, so a caller that must collect every defect and a caller that must stop before writing can share one rule.
…claration

A content root can be checked end to end with no `codeassembly.yaml` anywhere on its path: the root is resolved as a declared source with the built-in library behind it, so a dependency edge into a library artifact resolves the way it will at a consumer.

Coverage is everything the root ships that reaches one — rulebooks, skills, subagents, collections, and the support entries under `skills/` that carry no `SKILL.md` — checked against every harness given. A single run reports the whole list rather than stopping at the first rejection, and a defect every harness raises collapses to one line while one confined to a subset names the harnesses it reaches.
…sumer

`codeassembly-agents validate` checks a guidance-shipping package's content the way a consumer's install would, writing nothing. A producer can now gate its own content in its own CI instead of finding out when the content fails at a consumer.

The root comes from `--content <dir>`, or from the `codeassembly.content` key the package's `package.json` already declares; neither yielding one is an error naming both routes. `--harness` narrows the check to one harness, and the default checks every harness the root could deploy to. A clean root exits 0; any defect exits 1 after a report grouped by file.
…nables

The command list and flag reference cover `validate` and `--content`, and the package-producer walkthrough shows how to wire the check into a producer's own build, what it covers, and which exit code each outcome carries.
`validate` accepts a content root the installer accepts. A loose non-Markdown file under `skills/` installs as a verbatim copy, and the check now treats it that way rather than failing the run on a directory read.

Defects are confined to the artifacts the content root owns. A dependency edge still resolves into the built-in library so it resolves the way it will at a consumer, but a defect in a library artifact no longer reports against a path the producer does not have and cannot repair; an edge that resolves from nowhere is still reported, against the artifact that declared it.
…LI switch

Each subcommand group resolves in its own function, bringing the top-level dispatcher back under the configured complexity ceiling and leaving headroom for the next command.
Four rules that install, sync, and validate each have to apply identically now have one definition apiece: what counts as a skill directory, which entries under `skills/` are support content, the harness-relative prefix a deployed skill's links are built under, and how a support entry renders. Each was previously copied per caller, which is how the passes came to disagree about a loose non-Markdown file — a shape install copies and validate rejected.

A `SKILL.md` that is itself a directory is no longer mistaken for a skill, so an entry carrying one installs as the support content it is rather than being skipped by every pass.
Installing from content with no `skills/` directory names the missing path and says what it skipped, the way a missing `scripts/` or guidance directory already does. It previously reported a clean install while omitting the support files every skill reads at runtime.
@williamthorsen williamthorsen added feature Added or improved external functionality scope:agents labels Jul 31, 2026
@github-actions

Copy link
Copy Markdown

Dependency audit

Production dependency audit passed.

@williamthorsen williamthorsen self-assigned this Jul 31, 2026
@williamthorsen
williamthorsen marked this pull request as ready for review July 31, 2026 19:46
@williamthorsen
williamthorsen merged commit 68818b5 into main Jul 31, 2026
3 checks passed
@williamthorsen
williamthorsen deleted the 1126 branch July 31, 2026 19:47
williamthorsen added a commit that referenced this pull request Aug 4, 2026
…e-v0.2.2 codeassembly-v0.4.0 factory-v0.2.2 codeassembly-mcp-v0.2.2

codeassembly-v0.4.0
- #1153 feat: Make codeassembly and kb CLI tools publishable (#1164)
- #1091 fix: Anchor a project-deployed link where its target deploys (#1159)
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- refactor: Refine typescript-preferences
- #1150 fix: State doc-description form and make comment mood opt-in (#1151)
- deps: Upgrade first-party linting deps to latest version
- #1137 feat: Establish personal rulebooks for code layout and TypeScript preferences (#1144)
- #1126 feat: Check a package's own guidance content before it ships (#1138)
- refactor: Fix lint
- tooling: Remove redundant lint rules
- #1133 fix: Reject an anchor link that names no heading (#1135)
- #1122 feat: Capture lede decisions as an accumulating corpus (#1132)
- #1125 feat: Honor invocation tokens in rulebook bodies (#1129)
- #1107 feat: Render rulebook links and path tokens per harness (#1124)
- #1115 feat: Sync guidance at build and install so an upgrade cannot leave it stale (#1123)
- #1114 feat: Adopt a dependency's guidance by naming the package (#1121)
- #1088 feat: Deliver project ambient rulebooks per harness (#1113)
- #1087 refactor: Rename the authoring rulebook and mark its enforced rules (#1092)
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- #1094 refactor: Remove the ambient ripgrep dependency from the test suite (#1097)
- deps: Upgrade all deps to latest version
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint
- #1077 feat: Show the proposed edit above post-review menu options (#1078)
- #1068 feat: Deliver ambient rulebooks mechanically, retiring GLOBAL.md (#1075)
- #1069 feat: Add a no-second-person rule to the lede-voice doctrine (#1070)
- #1050 feat: Add a redundancy rule to the lede-voice doctrine (#1058)
- #1035 internal: Add lifecycle workspace with the canonical envelope, vocabulary & lane fold (#1049)
- #1006 internal: Extend lifecycle-event instrumentation to five high-traffic skills (#1034)
- #1028 feat: Rule out absence-of-removed-code tests (#1032)
- #114 feat: Let reviewers emit gated insights into review artifacts (#1031)
- #1027 internal: Retire input.received and redundant skill.progress emits (#1030)
- #1026 fix: Name the side effects an approval ask authorizes (#1029)
- #1022 fix: Normalize action and question label identifiers across asks blocks (#1025)

factory-v0.2.2
- #1156 refactor: Rename packages to publishable names (#1157)
- deps: Upgrade all deps to latest version
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- tooling: Remove redundant lint rules
- deps: Upgrade deps to latest version
- deps: Upgrade all deps to latest version
- deps: Upgrade all deps to latest version
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint
- deps: Upgrade all deps to latest version

kb-v0.3.0
- #1153 feat: Make codeassembly and kb CLI tools publishable (#1164)
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- tooling: Remove redundant lint rules
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint

codeassembly-lifecycle-v0.2.0
- #1153 feat: Make codeassembly and kb CLI tools publishable (#1164)
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- tooling: Remove redundant lint rules
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- #1038 feat: Add the read-only git adapter for worktree and base-branch ground truth (#1059)
- #1051 feat: Bound fold memory and rescan cost with a retention window (#1057)
- #1035 internal: Add lifecycle workspace with the canonical envelope, vocabulary & lane fold (#1049)

codeassembly-mcp-v0.2.2
- deps: Upgrade all deps to latest version
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint

codeassembly-run-core-v0.2.2
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Added or improved external functionality scope:agents

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A guidance-shipping package has no way to validate its own content

1 participant