refactor(gates): source the boundary resolver into skill-size-check
Why: scripts/skill-size-check.sh embedded a byte-identical 1,061-line copy
of the ADR-0020 boundary resolver only because it was also exported
through .pre-commit-hooks.yaml, whose consumers could not reach a file
inside the plugin. 4de5b6b retired that export, so the hook now runs only
in this repo and can source factory-audit's lib-boundary-resolver.sh like
validate.sh does. One copy removes the edit-one-paste-the-other hazard.
Implementation Notes:
- The hook's Python program is assembled from its own preamble, the
library's resolver and its own checks, read from quoted here-docs. The
assembled program matches the old one line for line except one comment,
and the hook's stdout, stderr and exit code are identical over every
corpus SKILL.md and the 26 differential-suite fixtures.
- The hook fails closed, naming the library, when it is missing or
defines no resolver.
- test-adr0020-contract.sh assertion 1 now pins the single copy: one
marker pair in the library, none in the hook, fail-closed on a missing
or gutted library, and a sentinel planted in a copied library that must
appear in the hook's output. 1a expects exactly one authority. 27 -> 29
passes.
- ADR-0020 and ADR-0025 carry dated amendments; gates.md and the
library, hook and mode-library comments no longer describe two copies.
- factory-audit is new on this branch, so the version-bump gate exempts
it; kyberforge is already at 2.0.0 against main's 1.6.2.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,14 @@ applies the body tiers on the skill path only. The two copies must still stay by
|
||||
plugin script cannot source the root one, which is why a second copy exists at all. Read every
|
||||
"three" below as the count at the time of writing.
|
||||
|
||||
**Amended again (2026-09-16): one copy.** `scripts/skill-size-check.sh` no longer embeds the
|
||||
resolver. It sources `factory-audit/scripts/lib-boundary-resolver.sh` by path and fails closed if the
|
||||
library is missing or defines no resolver. The embedded copy had been kept only because the hook was
|
||||
also exported through `.pre-commit-hooks.yaml`, whose consumers could not reach a file inside the
|
||||
plugin; `4de5b6b` retired that export (ADR-0014), so the hook runs only inside this repo. The
|
||||
"byte-identical" sentence above is superseded: there is nothing left to keep identical, and
|
||||
`tests/test-adr0020-contract.sh` assertion 1 now pins the single copy instead of hashing a pair.
|
||||
|
||||
## Context
|
||||
|
||||
Every `file:line` citation in this ADR is against the base commit the decision was taken on,
|
||||
|
||||
@@ -10,6 +10,13 @@ below (both exported hook IDs survive) and the case 33 port no longer describe t
|
||||
deleted, and its one-plugin narrowing guard is now a property of case 32. See
|
||||
[ADR-0014's amendment](0014-vale-prefilter-ships-from-the-plugin.md#amendment-2026-09-16-the-external-hook-contract-is-retired).
|
||||
|
||||
**Amended (2026-09-16): the root hook sources the resolver.** Point 6 below records sourcing the
|
||||
resolver into `scripts/skill-size-check.sh` as refuted, because the hook was consumed through
|
||||
`.pre-commit-hooks.yaml`. That manifest is retired (above), so the reason no longer holds: the hook now
|
||||
sources `lib-boundary-resolver.sh`, the repo holds one resolver copy, and the contract test's
|
||||
assertion 1 pins that copy rather than hashing two. Assertion 1a's "exactly those two files" is now
|
||||
exactly one. Point 6 is left as the record of the decision at the time.
|
||||
|
||||
## Context
|
||||
|
||||
Every figure below was measured against the worktree on 2026-09-15. Re-derive rather than quote; the
|
||||
|
||||
@@ -410,14 +410,17 @@ skills. They are copied rather than imported because a cache-installed plugin's
|
||||
files outside their own plugin directory. `tests/test-skill-size-check.sh` asserts the copies agree,
|
||||
so drift fails CI rather than silently letting an audit bless a skill the commit hook then rejects.
|
||||
|
||||
**The shared boundary resolver is now two copies, not three** (ADR-0025). `scripts/skill-size-check.sh`
|
||||
still carries it embedded between `BEGIN`/`END ADR-0020 SHARED BOUNDARY RESOLVER` markers; the two
|
||||
plugin copies that used to sit inside `skill-audit`'s and `agent-audit`'s `validate.sh` collapsed
|
||||
into the single `factory-audit/scripts/lib-boundary-resolver.sh`, sourced by that skill's scripts.
|
||||
The two remaining copies must still stay byte-identical — a plugin script cannot source the root
|
||||
one, which is the constraint that forces a copy to exist at all.
|
||||
**The shared boundary resolver is one copy** (ADR-0025, then 2026-09-16). It lives between the
|
||||
`BEGIN`/`END ADR-0020 SHARED BOUNDARY RESOLVER` markers in `factory-audit/scripts/lib-boundary-resolver.sh`.
|
||||
ADR-0025 collapsed the two copies inside `skill-audit`'s and `agent-audit`'s `validate.sh` into that
|
||||
file. `scripts/skill-size-check.sh` kept an embedded, byte-identical third copy while it was also
|
||||
exported through `.pre-commit-hooks.yaml`, whose consumers could not reach a file inside the plugin.
|
||||
`4de5b6b` retired that export (ADR-0014), so the hook now sources the library by path and fails closed
|
||||
if the library is missing or defines no resolver.
|
||||
|
||||
`tests/test-adr0020-contract.sh` pins that arrangement, and one of its assertions was green on a
|
||||
`tests/test-adr0020-contract.sh` pins that arrangement: the library carries the only marker pair,
|
||||
the hook carries none, the hook fails closed without the library, and a sentinel planted in a copied
|
||||
library proves the hook executes the library's text. One of its assertions was green on a
|
||||
defect it named. "`validate.sh` sources the resolver in **both mode branches**" was implemented as a
|
||||
file-wide `grep -Ec … -ge 2`, which cannot see a branch at all: delete the `agent)` arm's source line
|
||||
and duplicate the `skill)` arm's, and the file-wide count is still 2 and the assertion still passes,
|
||||
@@ -425,7 +428,8 @@ with the agent path running no resolver or some other one. It is now a **per-arm
|
||||
each arm of `validate.sh`'s `case "$MODE" in` block must carry exactly one `source` line inside its
|
||||
own body, and the file must carry exactly those two — with a mutation self-test that performs that
|
||||
exact count-preserving edit on a copy and requires the check to fail on it. The suite went 25 → 28
|
||||
cases.
|
||||
cases. It stood at 27 before the 2026-09-16 change and 29 after it, which replaced the two-copy
|
||||
hash and its line-count floor with the six one-copy assertions above.
|
||||
|
||||
### `python3` and PyYAML are hard requirements
|
||||
|
||||
|
||||
Reference in New Issue
Block a user