feat(agents): configure the repo for the mattpocock engineering skills - #235
Merged
Merged
Conversation
Ran `setup-matt-pocock-skills` from the `mattpocock-skills` plugin, which scaffolds the per-repo configuration its other engineering skills read before they touch an issue or a codebase. - `docs/agents/issue-tracker.md`: GitHub Issues on `Syndic/unnatural_designs`, driven by `gh`. Seeded from the skill's GitHub template, plus a note that `gh` runs on the host rather than through `devcontainer exec` — the carve-out this repo's tooling rule already makes for read-side `git` and `gh`, and where the authenticated session lives. "PRs as a request surface" stays off, the skill's default. Read by `to-tickets`, `to-spec`, `triage`, `wayfinder`, `code-review`, and `ask-matt`. - `docs/agents/triage-labels.md`: the five canonical triage roles, each label string equal to its name. None of the five exist on the repo yet; `triage` creates them on first use. - `docs/agents/domain.md`: multi-context layout, adapted away from the template's `src/<context>/` assumption. A context here is a Bazel package tree under one of the README's top-level directories, and only `//meta/` and `//tools/network_infrastructure_maintenance/` hold code today. - `.claude/CLAUDE.md`: an `## Agent skills` block pointing at the three files. It goes here rather than in a new root `CLAUDE.md` — the skill's literal instruction — because the project instructions already live at this path, and a second root file would split them in two. `CONTEXT-MAP.md` and `docs/adr/` are deliberately absent: the skill's own consumer rule has `domain-modeling` create them lazily, when a term or decision actually needs recording, rather than seeding empty scaffolding. Markdown-only, so nothing is packaged: `bazel run //:gazelle` produces no BUILD changes and no `glob()` in the tree matches these files.
Syndic
force-pushed
the
claude/install-mattpocock-skills-plugin-9edef4
branch
from
August 20, 2026 02:01
ed509ae to
1249c08
Compare
`docs/agents/domain.md` declares this repo multi-context, which means the engineering skills look for a root `CONTEXT-MAP.md` to find where each context lives. Nothing was there to find, so every skill fell through to "proceed silently" and got no domain bearings at all. The map names the two contexts that hold code today — `tools/network_infrastructure_maintenance/` (the NetBox/UniFi domain) and `meta/` (the repo's own automation) — and records the one relationship worth stating: `meta/` operates on the repository as an artifact and shares no domain language with what it builds, so a change in one is not expected to move the other's vocabulary. Per-context `CONTEXT.md` files are still absent, and the map says so inline rather than linking at files that aren't there. Those stay lazily created by `/domain-modeling`, when a term actually gets resolved; seeding empty glossaries would just be scaffolding that reads as a gap. The five scaffolding directories are listed under "Not yet contexts" with the rule for promoting one, so the next person to add code under `//apps/` or `//services/` knows the map is theirs to update.
`//platforms/` was listed alongside `//apps/`, `//libs/`, `//services/`, and `//infra/` as a directory that "exists as scaffolding and carries only a `BUILD.bazel`". That was written without reading the file. The other four hold a `BUILD.bazel` containing one comment line and nothing else; `platforms/BUILD.bazel` defines the three `platform()` targets `.bazelrc` selects with `--config=linux_x86_64`, `--config=linux_arm64`, and `--config=darwin_arm64`, and README.md points at them as the platform definitions. Being wrong about the emptiness also made the placement wrong. "Not yet contexts" carries an implicit promise — add a `CONTEXT.md` here once there's code — and `//platforms/` is not waiting on that. It has code now, and three constraint tuples still have no vocabulary to model and no decisions to record, so a glossary there would stay empty for reasons that won't change. It gets its own section saying so. `docs/agents/domain.md` keeps `//platforms/` in its parenthetical, which enumerates the README's top-level directories rather than asserting any of them is a context; the exception belongs in the map, which is where a reader looks for what is and isn't one.
The seed template ends with "Edit the right-hand column to match whatever vocabulary you actually use." That line is addressed to the human running `setup-matt-pocock-skills`, and it was answered when the file was written: the column says `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`, and those five labels now exist on the repo. Left in place it is worse than redundant. This file is read by agents as configuration, and a standing imperative in a config file reads as a directive to act on rather than as scaffolding from the generator that produced it. The mapping table is the whole contract; a maintainer who wants different label strings edits the table, and needs no instruction in the file to know it. `issue-tracker.md` keeps its "Set to `yes` if…" parenthetical, which is not the same thing: it declares the flag's current value and defines what the other value means, and a reader needs both to interpret the flag.
CONTEXT-MAP.md described the network context as "the tools that keep those two in agreement: an
audit…, drift detection…, and a NetBox → UniFi sync" — one sentence covering one binary that exists
and two that don't. `bazel query 'kind("go_binary", //tools/...)'` returns only
`cmd/netbox_audit:netbox_audit`; the tool's README describes the other two with their command names
elided as dots, so they have no names yet, let alone code.
The reason this matters more than an ordinary inaccuracy: `/triage` reads exactly this kind of
domain description. Its first step searches for an existing implementation *by domain concept
rather than by the request's wording*, and a hit is an already-implemented `wontfix` that closes
the issue. So a future request for drift detection could be matched against a sentence claiming
drift detection is part of the context, and closed as already-done. That branch also skips writing
to `.out-of-scope/` — that KB is for rejected requests, not built ones — so the bogus close would
leave less of a trail than a real rejection.
Built and planned are now separate paragraphs, and a closing line says the vocabulary describes the
modelled network rather than the tools that exist against it, so the domain language can't be read
as an inventory.
domain.md carried its own copy of the directory inventory — "Only `//meta/` and `//tools/network_infrastructure_maintenance/` hold code today; the other top-level directories are scaffolding" — which is the same false claim about `//platforms/` that CONTEXT-MAP.md was corrected for. Fixing one copy and not the other left the branch contradicting itself: the map says `//platforms/` holds the three `platform()` targets `.bazelrc` selects, while domain.md said every directory but two was scaffolding. Both files are read by the same skills. The duplication is the actual defect; the drift is what it produced, inside a single commit. Which directories are contexts is precisely what CONTEXT-MAP.md exists to record, so domain.md now points there rather than restating a corrected version. The instruction it was wrapped around — add a `CONTEXT.md` when a context gains code, and register it in the same change — is domain.md's to give and stays. The paragraph above it keeps the README directory list: that defines what a context *is* and where one may live, which is this file's job, not an inventory of which ones exist.
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.
What
Ran
setup-matt-pocock-skillsfrom the newly installedmattpocock-skillsplugin. It scaffolds the per-repo configuration the plugin's other engineering skills read before
they touch an issue or a codebase: where issues live, what the triage label vocabulary is, and how
domain docs are laid out.
Two commits, markdown only:
docs/agents/issue-tracker.mdghdocs/agents/triage-labels.mddocs/agents/domain.md.claude/CLAUDE.md## Agent skillsblock pointing at the threeCONTEXT-MAP.mdWhy these choices
Issue tracker: GitHub. The remote is GitHub and
ghis already in the devcontainer. Seeded fromthe skill's own GitHub template, with one addition: a note that
ghruns on the host rather thanthrough
devcontainer exec. That is the carve-out this repo's tooling rule already makes forread-side
gitandgh, and the host is where the authenticated session lives. "PRs as a requestsurface" stays off, the skill's default.
Triage labels: the defaults. Each label string equals its role name. Four of the five did not
exist on the repo and have been created out-of-band (
needs-triage,needs-info,ready-for-agent,ready-for-human);wontfixalready existed as one of GitHub's stock labels andwas left alone, since its description already matches the canonical role and
triageshould applyit rather than duplicate it.
Domain docs: multi-context. This needed the most adaptation. The skill's template assumes
src/<context>/; here a context is a Bazel package tree under one of the README's top-leveldirectories, and only
//meta/and//tools/network_infrastructure_maintenance/hold code today.The file says so, and says to add a context's
CONTEXT.mdwhen that context gains code.The block lands in
.claude/CLAUDE.md, not a new rootCLAUDE.md. The skill's step 4 looks onlyat the repo root and would have created one there. The project instructions already live at
.claude/CLAUDE.md, which Claude Code loads the same way, so a second root file would split them intwo — against this repo's own one-canonical-home rule.
CONTEXT-MAP.mdis seeded rather than left to appear later. Declaring the repo multi-contextmeans the skills look for a root map to find where each context lives; with nothing there, every
skill fell through to "proceed silently" and got no domain bearings at all. The map names the two
contexts that hold code and records the one relationship worth stating:
meta/operates on therepository as an artifact and shares no domain language with what it builds, so a change in one is
not expected to move the other's vocabulary. The five scaffolding directories are listed under "Not
yet contexts" with the rule for promoting one.
Deliberately absent
Per-context
CONTEXT.mdfiles anddocs/adr/. The skill's consumer rule hasdomain-modelingcreate them lazily, when a term or decision actually needs recording, rather than seeding empty
glossaries that read as a gap.
CONTEXT-MAP.mdsays as much inline instead of linking at files thataren't there, so the map has no dead links.
Verification
bazel run //:gazelleproduces no BUILD changes, and noglob()in the tree matches markdown, sothese files need no packaging.
bazel test //...— 22/22 pass. All cached, which is itself the signal that a markdown-only changeinvalidated nothing.
skipped: no files of their kinds changed).
For the reviewer
The
docs/agents/*.mdfiles are meant to be edited directly as preferences change; re-running thesetup skill is only for switching issue trackers or starting over. The two files worth reading
closely are
docs/agents/domain.mdandCONTEXT-MAP.md, since both are my adaptation to thisrepo's Bazel layout rather than the skill's template.
This branch was rebased onto
164767a(#234), which appended its own section to the end of.claude/CLAUDE.md— the same place this change appends. The conflict was positional, not semantic;both sections are kept, with
## Agent skillslast.🤖 Generated with Claude Code