Why A six-agent review of the two preceding commits found their code sound -- the differential claim holds, the published hook contract is byte-unchanged -- but their prose drifted from it in three ways: statements of fact the code contradicts, markers in a convention this repo does not use, and figures that went stale when the merge changed what they counted. Implementation Notes ADR-0025's edge-path table is rewritten around one stated doctrine: exit 0 is audited and clean, exit 1 is audited with findings or a target present but unreadable, exit 2 is that nothing was audited. Its old row 1 promised "one generic matches-neither message" for three different inputs; there are three distinct messages, and the missing-path case exited 1 until the preceding commit fixed it. Rows are added for the preflight and CDPATH changes, because a table claiming to enumerate every entry-point behaviour change reproduces its own "an earlier revision of this ADR said they were behaviour-neutral" failure if it omits any. ADR-0025 also gains a Consequences supersession record in ADR-0016's form: partially-superseded entries for 0008, 0014, 0020 and 0021, and explicit "is not superseded" entries with reasoning for the rest. Twelve ADRs are amended and it previously listed none. ADR-0008 moves from an amendment note to partially superseded. Its contract genuinely narrowed -- an agent .md outside an agents/ directory was audited before the merge and is refused now -- and ADR-0020 already recorded that the merge "reopens ADR-0008". Its detector description said "a path under .apm/agents/", the phrasing ADR-0025 rejects as wider than the script and circular; the shipped rule is a .md whose immediate parent is named agents/, at any scope. ADR-0020's amendment claimed the boundary resolver is sourced by validate-provenance.sh. It is not, and never was; only validate.sh sources it, once per mode branch. Three Home-column entries pointed at reference filenames the merge renamed, one of which now resolves to two files because its row covers skills and agents. Five ADRs opened with "Skill renamed per ADR-0025", a form this repo does not use, in the same commit that used the conventional "Amended by ADR-0025" twice. They are normalized. "Renamed" was also wrong: the BREAKING-CHANGE trailer says the skills were removed and their flows merged. SIMPLIFICATION-AUDIT.md had 2026-09-15 notes attached to headlines that were never updated, against its own convention of correcting in place with strikethrough. Every figure here was re-derived at HEAD by command, and several differed from the review's own numbers, so the notes record the basis rather than the result alone. LESSONS.md asserted the two review-time suite failures were the SIGPIPE race. The commit that fixed that race explicitly declined to claim it -- the suite was running while agents edited live config files -- so the hedge is restored. Impact No code, test or configuration change; documentation only. Suites stay 20/20 strict with 0 skipped and 374/374 bats. No gate parses ADR or gates.md content, so nothing here is load-bearing for a hook. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
78 lines
4.5 KiB
Markdown
78 lines
4.5 KiB
Markdown
# Plugin-scope agent provenance file moves to `<plugin-root>/sources.md`
|
|
|
|
**Partially supersedes:** ADR-0005 (agent-author dual-provider scaffold) — specifically the
|
|
claim that "both files share a single `agents/sources.md` for provenance." The rest of
|
|
ADR-0005 (dual-provider generation, scope detection, single-root script interface) is
|
|
unaffected and remains in force.
|
|
|
|
**Path update per ADR-0016:** at plugin scope, agent files no longer live at
|
|
`<plugin-root>/agents/<name>.md`. The authoring source is now
|
|
`<plugin-root>/.apm/agents/<name>.agent.md` — a single vendor-neutral file (no dual Claude/
|
|
Copilot pair) compiled to both targets via `apm pack`. See ADR-0016 for why (the field-dropping
|
|
rationale, `tools:` incompatibility, the compiled-output mechanics) — not restated here. This
|
|
ADR's own conclusion is unaffected by that move: the provenance file still belongs at
|
|
`<plugin-root>/sources.md`, outside any directory `claude plugin validate --strict`
|
|
auto-scans, and `.apm/agents/` is, if anything, further removed from plugin-root than the old
|
|
flat `agents/` directory was, so the reasoning below still holds. References below to
|
|
`<plugin-root>/agents/` describe the pre-APM layout in effect when this decision was made.
|
|
**Amended by ADR-0025 (2026-09-15).** `agent-audit` was removed and its flow merged with
|
|
`skill-audit`'s into `factory-audit`; read the `agent-audit` references below as `factory-audit`'s
|
|
agent flow, whose `validate-provenance.sh` still resolves `<plugin-root>/sources.md` exactly as this
|
|
ADR decided.
|
|
**Scope boundary (per ADR-0016):** this path change is plugin scope only. Project scope
|
|
(`.claude/agents/` + `.github/agents/`) and user scope (`~/.claude/agents/` +
|
|
`~/.copilot/agents/`) are unaffected — they are not APM packages and keep the dual-file
|
|
Claude+Copilot pair model this ADR originally described.
|
|
|
|
`claude plugin validate --strict` auto-discovers every `.md` file directly under a plugin's
|
|
`agents/` directory and treats it as an agent definition requiring YAML frontmatter (`name`,
|
|
`description`, etc.). A flat provenance file at `agents/sources.md` — no frontmatter, by
|
|
design, since it is not an agent — fails validation with a missing-frontmatter warning that
|
|
`--strict` promotes to an error.
|
|
|
|
This was first hit in `plugins/git/agents/sources.md` (added by the git-plugin skill suite).
|
|
It failed the `validate-plugins` pre-push hook. The stopgap in commit `0239b00` added
|
|
throwaway agent frontmatter to unblock the push:
|
|
|
|
```yaml
|
|
---
|
|
name: git-agents-sources
|
|
description: Provenance record for the git plugin's agents, not an invokable agent. Do not invoke.
|
|
tools: none
|
|
---
|
|
```
|
|
|
|
That workaround is now reverted — the file no longer lives where it needs to impersonate an
|
|
agent to pass validation.
|
|
|
|
## Considered options
|
|
|
|
**Exclude via an explicit `agents` manifest array (rejected)** — `plugin.json` supports
|
|
`"agents": ["./agents/reviewer.md"]` as an alternative to `"agents": "agents/"`. The
|
|
hypothesis was that listing only real agent files would stop the validator from also
|
|
discovering `sources.md` in the same directory. Tested empirically on a scratch copy of the
|
|
git plugin: `claude plugin validate --strict` still auto-discovered and failed on the
|
|
unlisted `sources.md`, regardless of the explicit array. The manifest field controls what
|
|
Claude Code loads as agents at runtime; it does not control what the validator scans on
|
|
disk. There is no manifest-level or CLI-flag mechanism to exclude a file from `agents/`
|
|
auto-discovery.
|
|
|
|
**Keep the frontmatter workaround permanently (rejected)** — cheapest fix, already applied,
|
|
but semantically wrong: it makes a plain provenance record indistinguishable from a real
|
|
invokable agent to any tooling or UI that lists available agents (e.g. it could appear as a
|
|
callable agent in the `/agents` picker), which is confusing and incorrect.
|
|
|
|
## Consequences
|
|
|
|
- The provenance file moves to `<plugin-root>/sources.md` — a flat file, plugin-root
|
|
relative, sitting outside any directory that Claude Code or its validator auto-scans. No
|
|
frontmatter is needed or added.
|
|
- `agent-author`'s `new-agent.sh` now writes `<root>/sources.md` instead of
|
|
`<root>/agents/sources.md` at plugin scope.
|
|
- `agent-audit`'s `validate-provenance.sh` now looks for `<plugin-root>/sources.md` when
|
|
checking `source_keys` provenance chains.
|
|
- All doc and template references to `agents/sources.md` (agent-author `SKILL.md`,
|
|
agent-audit `SKILL.md`/`README.md`, both provider templates) are updated to `sources.md`.
|
|
- `plugins/git/agents/sources.md` is relocated to `plugins/git/sources.md` and the
|
|
`0239b00` frontmatter workaround is removed.
|