Worked example
August 8, 2026 · View on GitHub
A real three-legged system, built August 2026. Everything below is live and inspectable.
| Leg | Repo / path | Visibility |
|---|---|---|
| Plugin | spec-led-certification-plugin | Public |
| Template | Spec-Led-Certification | Public, marked as a GitHub template |
| Workspace | One private repo per search, instantiated from the template | Private |
| Vault | ~/.claude-plugins/spec-led-certification/ | Local |
What it does
Chooses a professional certification specification-first: it interviews you, derives a weighted scorecard from your answers alone, freezes it before any credential is looked up, then surveys the market and scores candidates against it.
That freeze is why the workspace has to be a repo. The claim "the scorecard was fixed before the research ran" is only worth anything if it can be checked, and a commit timestamp checks it. A folder cannot.
How the legs divide
Plugin — 14 skills, 3 subagents, one command. Twelve of the skills and all three agents are vendored from the template; two are plugin-owned:
create-workspace— instantiates the template as a private repo and clones itscaffold-workspace— copies the structure into a local directory when there is nogh, or when the search belongs inside an existing repo
Both are plugin-owned for the reason in sync.md: inside an existing workspace there is nothing left for them to do.
Template — the working structure (profile/, scorecard/, research/, report/),
the twelve stage skills, the three agents, AGENTS.md, and a Typst report template.
Because the skills ship in the template, an instantiated workspace is runnable with the
plugin uninstalled, by a different assistant, on a different machine. That is the
agent-agnostic claim delivered rather than asserted.
Workspace — one private repo per search, named for the subject and the month, since a second search on the same subject two years later is a different repo rather than an overwrite. Holds the profile, the frozen scorecard, the research with its sources, the reports, and archived previous runs.
Vault — owner, visibility, workspace_parent, naming, and the template
override. Without it create-workspace asks four questions; with it, one confirmation.
Points where the pattern earned itself
The freeze is evidenced by git. Three mechanisms enforce it, and the one that actually settles arguments is the commit ordering. Nothing in a folder-based design could have provided it.
The workspace outlives the plugin. The template carries the skills, so the private repo is not a data directory for a tool — it is a self-contained record of a decision, readable by whatever comes next.
The vault kept personal defaults out of two public repos. A GitHub username and a preference for private repos are unremarkable, and neither belongs in a repository strangers clone. Without the third leg they would have ended up in the template as "defaults", and every fork would have inherited them.
Instantiation is not a fork. gh repo create --template produces a squashed
Initial commit with no upstream link, so a workspace cannot receive template changes
later. That sounds like a limitation and is the correct behaviour here: changing the
skills underneath a frozen scorecard is exactly the drift the method exists to prevent.
Things learned building it
gh repo create --template --clone handles the instantiation race itself. Template
population is asynchronous and an immediate clone can in principle come back empty. It
does not — gh retries internally. Verified against a throwaway repo: seven seconds,
46 files, complete. No wait loop is needed, which is worth knowing because writing a
speculative one is the obvious defensive move.
Hardcoding one plugin-owned skill name cost a false drift report. The sync script
originally excluded scaffold-workspace by name in two places. Adding a second
plugin-owned skill made --check report drift on every run until both were replaced
with a list. Use a list from the start.
A vendored copy is not a place to make small adjustments. The byte-identical rule is
what makes --check mean anything; one legitimate difference and the check reports
drift forever and everyone stops reading it.
Reading it
The clearest single file is the plugin's
scripts/sync-from-template.sh —
it states the canonical direction, the ownership split and the empty-data guard in
about a hundred lines. A generalised copy is in
reference/sync-from-template.sh.