Skip to content

feat(build): copy governances into the skills that use them - #87

Merged
unional merged 3 commits into
mainfrom
cyberlegion/unit-6d5650ac6fb4b638
Sep 17, 2026
Merged

unional merged 3 commits into
mainfrom
cyberlegion/unit-6d5650ac6fb4b638

Conversation

@unional

@unional unional commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Step 2 of the governance-retrieval migration tracked in repobuddy/buddy-agent-harness#122.

Why

A skill reads a governance today through a pinned npx <pkg> governance show <name> — a registry lookup on every read, network required, and a package runner required on PATH. The only thing that call buys is the guarantee that the skill reads the version it was tested against, and that version is known at build time. So the document moves to build time: plugin build copies each governance into the skill that uses it, and the skill reads it from disk.

What changed

  • <skill>/references/governances/ is the declaration. The .md files already in that folder say which governances the skill uses. Nothing is declared in plugin.json (the owner's decision in #122).
  • Owner resolution. Each name is resolved against the plugin being built first, then the packages its package.json declares — a governance ships in its owner's package at governances/<name>.md. The plugin wins a name it and a dependency both ship.
  • Transitive copies. Every governance a copy references (governance show <other>) is copied into the same folder.
  • Pointer rewriting. Each governance show <other> inside a copy becomes Load `references/governances/<other>.md` if it is not already loaded. — the Agent Skills spec asks that SKILL.md reference every file directly, so a copy must never send the agent back to a command. A fence holding nothing but pointers is unwrapped; a fence mixing pointers with real commands keeps it.
  • Three build failures, each writing nothing: a declared file naming no resolvable governance, a referenced governance with no copy to point at, and a SKILL.md that does not list a copy under References.
  • plugin build --check. The copies are committed (small text; a git-sourced install must work offline). --check writes nothing at all and exits 1 naming each copy that differs from its source and the package that owns it. pnpm verify runs it via the new check:governances script, so CI catches a commit that skipped the build.
  • The copy step runs once per build, before any vendor is derived — a copy is vendor-neutral skill content.

Spec: ADR-0016, the plugin/build/ node and 14 new build.feature scenarios, and a placement-map bullet drawing the line between the two governance homes — governance/ resolves a name for a run-time caller, plugin/build/ places the document in the skill folder at build time.

Not in this PR

No skill in this repository declares a governance yet, so the check is green and a no-op here. Adoption is step 6 of the migration ("migrate the callers, one repository per change"); plugin-design also references three documents that ACED will own, and none of them is installed here yet.

universal-plugin governance show is untouched. #122 retires it in a later step.

Test plan

  • pnpm verify — 8/8 turbo tasks, 697 tests pass, including the new check:governances run against this repository.
  • New unit tests, src/governance/copy.test.ts (20): pointer extraction across the pinned-npx, bare-prose and namespaced (<plugin>/<name>) forms; fence unwrapping vs. fence preservation; list-marker and CRLF preservation; a pointer-free body left byte-for-byte alone; the References-section check accepting a bullet or a markdown link, rejecting a mention outside the section or past the next same-level heading.
  • New application tests, src/governance/copy-sync.test.ts (13): copy from the plugin's own governances/, from an installed dependency, and the plugin winning a shared name; a three-deep transitive chain; pointer rewriting end to end; unchanged leaving mtime alone; --check reporting stale without writing; each of the three failure modes.
  • New build tests, src/build/build.test.ts (5): the copy reported in BuildResult.governances and written; each failure mode throwing; --check deriving no manifest; one copy across a three-vendor build.
  • New CLI-boundary tests, src/build/cli.test.mts (3), driving the built bin/universal-plugin.mjs: --check exits 1 naming the stale copy and pointing at plugin build, exits 0 when copies match, and the plain build repairs what the check reported.

🤖 Generated with Claude Code

unional and others added 3 commits September 17, 2026 12:22
A skill reads a governance today through a pinned `npx <pkg> governance show
<name>`, which costs a registry lookup per read and needs network. `plugin
build` now copies each governance into the skill instead, so the skill reads it
from disk (repobuddy/buddy-agent-harness#122, step 2).

The files already in `<skill>/references/governances/` declare which governances
the skill uses — nothing is declared in plugin.json. Each is rewritten from its
owner's current copy: the plugin being built, else a package it declares as a
dependency, which ships the document at `governances/<name>.md`. Governances a
copy references are copied too, transitively, and every `governance show <other>`
pointer inside a copy becomes an instruction to load the sibling copy, so no copy
sends an agent back to a command to reach the next document.

The build fails when a declared file names no governance, when a referenced one
has no copy to point at, or when SKILL.md does not list a copy under References —
the specification asks that every file an agent needs is one level deep from
SKILL.md.

The copies are committed: they are small text, and a git-sourced install needs
its default to work offline. `plugin build --check` writes nothing and exits 1
naming every copy that differs from its source; `pnpm verify` runs it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ADR-0016 records the decision from repobuddy/buddy-agent-harness#122: a
governance is copied into every skill that uses it at build time and read from
disk at run time, with the copies committed and `--check` verifying them.

`plugin/build/` gains the behavior and the scenarios, and the root spec's
placement map draws the line between the two governance homes — `governance/`
resolves a name for a caller asking at run time, `plugin/build/` places the
document in the skill folder at build time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8fde5f7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
universal-plugin Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@unional
unional merged commit 2de2681 into main Sep 17, 2026
6 checks passed
@unional
unional deleted the cyberlegion/unit-6d5650ac6fb4b638 branch September 17, 2026 19:33
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