Commit Graph

38 Commits

Author SHA1 Message Date
4e22c4920a docs: reconcile LESSONS.md and VISION.md with what the branch removed
- LESSONS.md's 2026-06-22 test-placement entry told authors to put test
  files directly in scripts/ with a README row. The file-structure contract
  the repo now enforces permits tests/ as one of four directories, requires
  a tests/README.md when it exists, and FAILs test files in scripts/.
- LESSONS.md's 2026-08-16 entry described a dispatch chain ending at
  skill-author/references/retrofit.md in the present tense. This branch
  deleted that file. Sibling entries whose referents the branch removed
  were marked historical; this one was not.
- VISION.md's Phase 1 now puts stack, framework and deployment choices out
  of scope for this repo, while Phase 3 still named React Native and Tauri.

README.md was checked and needed no change: its offline guarantee already
carries the populated-apm_modules condition from 8cfd54f and agrees with
gates.md and AGENTS.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2
2026-09-20 18:38:21 +00:00
1f3d4f9962 docs: correct stale resolver, status and duplication claims
ADR-0014 gains a dated correction: skill-size-check now sources the
boundary resolver from kyberforge (ef27c97), so restoring the external
hook contract needs it made self-contained first. ADR-0017's status
reflects its supersession, architecture.md and gates.md carry the
current duplication counts and reason, gates.md defines vacuous green
inline, and the gitleaks lesson is marked historical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 15:27:29 +00:00
69119f4754 docs: reconcile the ADRs, gates and audit log with the shipped behaviour
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
2026-09-16 09:14:01 +00:00
ffcbed6c41 fix(tests): replace pipefail-racy echo | grep -q with here-strings
Why

Two suites failed intermittently — tests/test-vale-wrap.sh case 21 and
tests/test-check-release-needed.sh cases 4 and 15 — on correct output, and never
when run alone. The cause is the `echo "$OUT" | grep -q P` idiom under
`set -o pipefail`: grep -q exits as soon as it has an answer, bash's echo can
hand a multi-line value to the pipe one line at a time, and a write after the
reader is gone kills echo with SIGPIPE. pipefail then reports the writer's
death, so output that DID match reads as "no match". Every observed failure had
lines after its match; case 15's match is on line 1 of 6, the widest window in
that file.

Forced with a pause before the writer's last line, the pipe form failed 50 of 50
runs; a here-string, a match on the last line, and the same pipe without
pipefail each passed 50 of 50. Unforced the rate is about 1 per 670 suite runs,
which is why it read as a flaky gate rather than a bug.

The failures at review time are consistent with this, but were not proven to be
it: the suite was running while agents edited live config files in place, and a
brief change to .vale.ini or .pre-commit-hooks.yaml would produce the same two
failures. The race is real and fixed either way.

Implementation Notes

`grep -q P <<< "$VAR"` has no separate writer process, so there is nothing to
race. It is not a retry or a sleep. 121 sites converted across 9 files, three of
them scripts rather than tests: new-agent.sh, new-skill.sh and
check-executables-allow-sync.sh. None ships via .pre-commit-hooks.yaml, so no
external consumer pins them, and all three are single-pipeline checks whose
verdict cannot change.

Left alone deliberately: 14 sites whose writer is a command, not a shell
builtin — they either absorb the writer's status with `|| true` or are python3
and awk, which write once at exit — and one file with no pipefail. `printf '%s'`
sites differ from a here-string only by a trailing newline, which no -q verdict
on a non-empty pattern depends on.

tests/test-no-pipefail-early-exit-grep.sh is a static guard against new
occurrences, discovered automatically by run-tests.sh. It only scans files that
set pipefail, joins continuation lines, skips comments, and flags only
echo/printf writers. Its first case proves the scanner can fail before its
second trusts a clean verdict on the tree.

A guard covers exactly the spellings its regex models, so the miss surface was
measured rather than assumed. Four were found and closed: pipefail declared as
`set -o errexit -o pipefail` (where the old pattern required pipefail to follow
the FIRST -o, and a file-level miss skips every site in that file); a writer
separated from grep by an intermediate stage; a pipeline wrapped on a trailing
`|` rather than a backslash; and readers spelled egrep, fgrep, /bin/grep,
`command grep` or with an env-var prefix. Segment characters exclude a bare `&`
so `echo ok && other | grep -q x`, whose writer is `other`, does not false-fire.
Widening surfaced 5 live sites invisible to the original scanner, all in
tests/test-apm-current-hook.sh, all `echo "$out" | json_field ... | grep -q`;
they are safe today only because json_field is python3, which reads to EOF and
writes once. Fixtures go 4 to 12 vulnerable spellings plus near-miss negatives.

Two `grep ... | head -1` sites (test-vale-wrap.sh) are the same race with a
different early-exiting reader, and are fixed by absorbing the writer. The
scanner deliberately does not model `head`, `sed -n 1p` or a bare `read`: most
legitimate uses in this tree are already absorbed with `|| true` and the scanner
cannot see absorption from pipeline text, so a high false-positive rate would be
how this guard gets weakened. Heredoc bodies are scanned as code; none in the
tree trips it today.

Impact

The bug predates the factory-audit merge: every converted site in
check-release-needed and case 21 dates to 4d018af and aa8cc22 (2026-08-09).

Test suites go 19 to 20. `run-tests.sh --strict` passes 20/20 with 0 skipped,
four consecutive runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
2026-09-16 09:14:01 +00:00
620f20b0fd refactor(kyberforge)!: merge skill-audit and agent-audit into factory-audit
Why

The two audit skills carried 1,724 lines of byte-identical duplication: the ADR-0020 boundary
resolver (1,061), vale-wrap.sh (526), the Vale style rules (44) and the Contributing-files parser
(93). Nothing shared them — they were held in sync by a 413-line pre-push gate and its 797-line
test suite. Sync-by-gate had already failed once: at 484357a the two parser copies drifted into
different spellings of the bullet loop while a docstring asserted they were identical. That drift
was behaviour-neutral and was re-unified by hand at 598a7c3, so the copies were identical at merge
time — but nothing had caught it, and the next drift need not be neutral.

Implementation Notes

Self-containment binds BETWEEN skills, not within one. The agentskills.io spec forbids reaching
across skill directories, which is why two separate skills needed embedded copies; two files inside
ONE skill may source a third. That is the whole reason the merge removes duplication rather than
relocating it.

The union of both bodies measured 1,532 words against BODY_MAX_WORDS=900, and only 211 of those
words were shared, so SKILL.md is a dispatch body. Step 0 resolves the flow from the target path
before any validation, and its table mirrors validate.sh's detection exactly: a directory holding
SKILL.md or a SKILL.md file (skill); a *.agent.md, or a .md directly under an agents/ directory
(agent); anything else stops without running a validator. Steps 1-3 live in
references/skill-flow.md and references/agent-flow.md, and gotchas that apply to one flow live in
that flow's file, since it is loaded on every invocation anyway. If validate.sh reports on the
other artifact type, the body restarts at Step 0.

Named factory-audit rather than forge-audit because forge is a live skill, and a family prefix that
matches a live sibling reads as ownership rather than membership.

The description carries one arrow per boundary target, because ADR-0020 resolves only the first
target after an arrow. It drops the quoted "audit this skill"-style phrases, which restated
"audited" in a second register (ADR-0020's duplicate-register rule). 241 characters, Gotchas 16%
of the body: no size SUGGESTIONs.

The boundary resolver stays embedded in two files rather than imported: a cache-installed plugin
cannot read outside its own directory, and the repo-root hook resolves via .pre-commit-hooks.yaml
where entry[0] is the only token pre-commit rewrites, so no single file is reachable by both.
tests/test-adr0020-contract.sh hashes both copies for byte-identity, and asserts validate.sh sources
the resolver and that no third copy exists.

The entry scripts classify the target from its resolved parent directory, so a bare agent filename
typed inside agents/ works; resolve SCRIPT_DIR CDPATH-safely; and exit 2 when a lib-*.sh is
missing, rather than dying with exit 1, the tier the flows relay as real findings.

The provenance run functions stash their findings code in KYBERFORGE_PROV_RC and
return 0, so validate-provenance.sh calls them UNTESTED. Testing a function's
status (`f || RC=$?`) disables errexit for its entire body, and no subshell or
`set -e` inside can re-arm it once the call sits in a condition context
(measured, both spellings). Their error paths use `exit`, which is unaffected
either way; this keeps errexit armed for anything added later.

Case 0's readability guard reads the file instead of asking `[[ -r ]]`. `-r` is
access(2), which answers yes for uid 0 even on a mode-000 file, and this repo's
dev environment is root -- so the guard could never fire where it exists to fire.
A read attempt is also the stricter question, catching EIO. This is the reasoning
scripts/check-vale-style-sync.sh carried before this commit deleted it; the
hazard did not go with it.

All three entry scripts are CDPATH-safe, vale-wrap.sh included: both of its cd sites are cleared,
the --config resolution and the directory-mirror walk, where an exported CDPATH would otherwise
print a decoy path into the -print0 stream and build the mirror from the decoy's files. The two
remaining bare cd calls take absolute paths, which CDPATH is never consulted for.

Impact

BREAKING: skill-audit and agent-audit no longer exist as invocable skills. kyberforge goes to
2.0.0 (catalog 0.4.7).

Check logic is unchanged: differential runs of the old and new validators across every skill and
agent produced byte-identical stdout, stderr and exit codes, and the reconstructed Python payloads
differ only in comments and the references/field-inventory.md -> agent-field-inventory.md rename.
One doctrine governs the tiers: 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 at all. Edge paths DID change,
deliberately (full table in ADR-0025):
- a missing target exits 2 (never ran), not 1, under its own "does not exist" message; detection is
  by path shape, so a shape-matching path that is simply absent used to reach the validator and come
  back as a FAIL against a file that never existed;
- an unshaped target exits 2 under the generic "matches neither" message, and a directory with no
  SKILL.md under a third, distinct one -- three exit-2 messages, not one;
- a dangling symlink or a symlink loop stays exit 1: it is present but broken, which is a finding
  about the artifact rather than a usage error;
- a SKILL.md file path is audited as its skill directory instead of refused;
- a .md agent outside an agents/ directory is refused rather than audited;
- a missing script library, a missing python3, a missing PyYAML, and no argument at all each exit 2.
  validate-provenance.sh already exited 2 for the last two; validate.sh now matches it.

.pre-commit-hooks.yaml is a published contract consumed by external repos. Both hook IDs and both
files: regexes are unchanged; only entry: and description: moved.

scripts/check-vale-style-sync.sh (413), scripts/sync-vale-styles.sh (21),
tests/test-check-vale-style-sync.sh (797) and agent-audit/scripts/README.md (47) are deleted. The
checker made 17 assertions: 6 compared the two Vale copies and are moot; 10 are rehomed into
tests/test-vale-wrap.sh (case 0, cases 28-31, and the suite's Vale-absent skip); and the
cross-manifest files: agreement check, which selected hooks by entry: and so could not survive both
hooks sharing one, is ported as case 33 pairing hooks by id:. Cases 28, 30 and 33 carry mutation
self-tests; narrowing the local skill prefilter to 6 of 38 SKILL.md files now fails the suite.

Skills go 39 to 38. Pre-push goes 9 repo-authored hooks to 8.

ADR: 0025
BREAKING-CHANGE: the skill-audit and agent-audit skills are removed. Both flows are served by
  factory-audit, which auto-detects whether it was handed a skill directory or an agent file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
2026-09-16 09:13:57 +00:00
062ca47a18 docs: correct claims left stale by today's apm-only commits
A five-agent review of today's seven commits found no executable
regressions and no dangling references, but a set of documents still
asserting, in present tense, machinery that ADR-0024 and its commits
removed. This corrects them in place, keeping the original text as the
historical record wherever the repo's amendment convention applies.

LESSONS.md: the 2026-06-21 entry prescribed a `claude plugin validate`
sweep that now fails on every plugin, so it is marked superseded with
the surviving gates named. The 2026-08-09 entry gained a recurrence
note: today's manifest deletion broke apm's MCP propagation exactly as
that lesson describes, and its prescribed repo-local grep could not
have caught it, because `plugin_parser.py` ships in the apm toolchain
installed outside this repository.

ADR-0019, ADR-0011 and ADR-0021: amendments extended to passages the
earlier correction passes stepped over -- a dead native-consumer guard,
Consequences bullets still calling for a `plugins/gitea/.mcp.json` that
must not be recreated, and a drift-gate list naming a deleted script.
ADR-0021's list is down to one gate, not two: `apm audit --ci` never
read `description` and was never a drift gate.

architecture.md and enrichments.md: the self-containment constraint is
restated on its live source, the agentskills.io APM package-mode spec,
rather than on Claude Code's plugin cache-install, which ADR-0024
consequence 6 pins as a superseded rationale. releasing.md's pointer to
the deleted sync script is rewritten as history.

tests/run-bats.sh and scripts/lib/batch-run.sh: comment-only. The
`.claude/skills/` exclusion comment claimed a duplication that is not
live yet; apm does not strip `tests/`, and the deployed tree is empty
of them only because the lockfile still resolves the six dependencies
to a pre-ADR-0024 commit carrying the flat mirror. The exclusion is
correct but forward-looking, and now says so.

SIMPLIFICATION-AUDIT.md: reconciled against what the commits actually
did. Two closed findings recorded conclusions that ADR-0024 reversed
hours later; findings 1, 3, 31 and 35 carried prescriptions voided the
same day; finding 28 is now recorded as having moved backwards, with
docs/adr/ measured at +336 lines over the day. The section 1 headline
table is re-measured at a6434e0 and labelled with its basis. The
ADR-0012 contradiction between finding 2b and section 8 is resolved in
2b's favour after reading the ADR: only finding 24 is governed by it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
2026-09-14 19:50:23 +00:00
629320b8fd docs: trim stale entries from LESSONS.md
Finding 30 of the simplification audit. 41 entries had grown to 255
lines; 10 described a write-skill / write-eval bootstrap workflow
whose skills no longer exist in this repo, and the longest entries ran
200-550 words of incident narrative for a one-line lesson.

Deleted the 10 stale entries. Kept 3 same-dated ones (RLHF defaults,
secrets-rule gap, HITL gap) whose content is unrelated to the defunct
workflow and still applies. Removed one open-work entry ("neither part
landed", about CONTEXT.md not being @import-ed at session start)
rather than filing it as a tracker issue -- not turned into an issue,
just dropped; the audit's own commit history and this repo's session
transcript carry the detail if it's wanted later. Compressed the
remaining 30 entries to roughly 60-90 words each.

255 -> 131 lines, 41 -> 30 entries.

Refs: SIMPLIFICATION-AUDIT.md finding 30

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
2026-09-12 18:38:26 +00:00
a3e721e937 docs: retire the META.md guidance ADR-0022 overruled, bump touched plugins
Why: ADR-0022 made `metadata.version` mandatory in SKILL.md frontmatter, but three documents still
instructed the opposite — that `version:`, `source:`, `references:` and `when:` belong in a separate
META.md. That recommendation was never implemented: META.md exists exactly once in this repo, inside
a vendored third-party research example, and all 39 skills now contradict it. A stale instruction
that outranks nothing is worse than no instruction, because an author following it undoes the ADR.

Implementation notes:
- Two LESSONS.md entries deleted outright — their entire payload was the rejected fix. Two kept and
  rewritten: the copy-fill entry loses only its META-TEMPLATE clause, and the `model:` entry keeps
  the provider-extension fact and the invocation-time boundary rule, which stand on their own.
- One factual error corrected in passing: the `extracted` slug entry claimed provenance is recorded
  in META.md. It lives in `references/sources.md` keyed by `source_keys:`, verified against
  validate-provenance.sh.
- Both docs/notes files gain `metadata.version` in their required-field lists. Deleting the stale
  paragraph while leaving those lists silent would have re-created the gap.
- `bin/write-docs` carried `metadata.version: "1.0"` — the only non-semver value in the corpus, and
  the result of relocating its old top-level `version:` without normalising it. Now `1.0.0`.
  ADR-0022 records the relocation it previously omitted, which issue #127 had asked it to decide.

Impact: patch bumps for the four plugins whose `.apm/` content changed — bin, git, gitea,
kyberforge. core and lint are untouched and stay put. Root apm.yml's `executables.allow` key and
marketplace package versions move in lockstep; the marketplace release version is unchanged.

Refs: #127
ADR: 0022
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP
2026-09-09 05:15:41 +00:00
4d336bbf35 docs: stop the preloaded instruction set asserting machine state
Why: four defects in the files every session pays for, all introduced or left
behind by the trim.

AGENTS.md told agents the `<plugin>:` form still resolves "because user-scope
native installs were left enabled on purpose", and that a working namespaced
call "is not something to fix". That premise is false on this machine:
installed_plugins.json is empty, no enabledPlugins key exists in ~/.claude.json,
and ~/.apm/marketplaces.json is empty. ADR-0018 already reversed itself once on
this exact claim (Correction 2026-08-14) using that same enablement as its
evidence, so flipping the assertion again would be the third revision in three.
Both files now assert nothing about install state at all, which removes the
flip-flop surface instead of re-aiming it.

The other three are guard-rails whose instruction survived the trim while the
caveat that made it safe did not:
- The run-tests.sh line omitted --strict, so it named the one invocation that
  reports SKIPPED rather than failed when a dependency is missing. gates.md
  records this gate going green having verified 15 of 17 suites on a vale-less
  PATH. .pre-commit-config.yaml:70 already uses --strict for that reason.
- The .claude/settings.json prohibition lost its ADR-0019 exception, so an agent
  applying it literally would strip apm's own merged SessionStart entry and
  create the drift the rule exists to prevent.
- LESSONS.md still routed graduated rules to CONTEXT.md's Principles section,
  which this branch deleted.

Implementation notes: the six terms the trim dropped while AGENTS.md still
claimed CONTEXT.md glosses everything -- authoring root, content mirror, apm
package, output profile, near-miss, vacuous green -- are restored as one-line
entries per CONTEXT-FORMAT.md, sourced from architecture.md, gates.md and
skill-audit's description-quality.md rather than reworded. ADR-0018 gets a third
dated note recording the observation and the fact that the state has now been
described two ways, and its stale user-scope inventory is replaced by a pointer
to it; the decision it records is untouched. LESSONS.md:3 carried the identical
stale claim as :5 and is fixed with it.

Impact: preloaded context is now free of assertions about machine state.

Refs: #105

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
2026-08-17 12:28:30 +00:00
56cc173f65 fix: re-anchor doc citations that the CONTEXT.md trim broke
Why: eight comments and one status note cited CONTEXT.md or AGENTS.md text that
b9c7762 and 1929ffd moved or deleted. All are inert at runtime, but they are the
rationale comments that tell the next maintainer why an assertion exists, and
they now name a file that no longer explains it.

Implementation notes: re-anchored by what the citation is for, not uniformly.
- Four sites quoted facts ADR-0013 owns — every rule is `level: error` with no
  ignorable tier (ADR-0013:59-70), and KyberforgeCopilot's `.agent.md`-only
  scope (ADR-0013:43-46). These now cite ADR-0013. ADRs are append-only here;
  the spec docs are refactored, which is what caused this rot.
- Two sites quoted the glob location-independence property, which no ADR owns.
  The quote was already inline and carried the full rationale, so the citation
  added a rot surface and no information — dropped, statement kept.
- sync-marketplace-mirror.sh's header attributed the mirror-not-a-profile fact
  to CONTEXT.md; the parenthetical beside it already carries the evidence, so
  the attribution is dropped rather than re-pointed.
- .pre-commit-config.yaml cited an AGENTS.md instruction that no longer exists;
  generalised to "the documented instruction".
- LESSONS.md:29 misquoted AGENTS.md's current session-start line.

Also corrects a pre-existing misattribution at tests/test-vale-wrap.sh:454:
AGENTS.md has never named bash 3.2 as a repo target (`git log -S'3.2'` on it is
empty). LESSONS.md and the script headers do.

Impact: no behaviour change. test-check-vale-style-sync.sh and test-vale-wrap.sh
both pass (42 passed, 0 failed).
2026-08-17 10:09:51 +00:00
ede3f06689 fix(kyberforge): restore the authoring rules the ADR-0020 trim dropped
Diffing each retrofitted SKILL.md against its replacement references/ files found
rules that existed on main and now existed nowhere — relocated in intent, deleted in
fact. A trim that loses a rule is not progressive disclosure, it is data loss with a
smaller word count.

Three had no survivor. The least-privilege guidance for `tools` kept its mechanics
and lost the "restrict to what the agent needs" half, so the remaining text read as
encouragement to omit the field. The improve flow lost its regression check, so
nothing compared the closing audit against the pre-edit state and a PASS quietly
becoming a SUGGESTION went unnoticed — restored on both halves of the author pair,
since agent-author had dropped its equivalent too. And agent bodies lost "would the
agent get this wrong without it?", which mattered more than it looks: ADR-0020
deliberately sets no body word gate for agents, three of the four already sit
between 933 and 1,199 words, and the delegation check only fires on procedure a
skill already owns. That heuristic was the only brake left.

Two more were reachable only from the wrong scope. agent-author tells the reader to
load only the file for the resolved scope, but the mcp__ glob syntax for
disallowedTools and the five tools no subagent ever receives had both landed in
project-user-scope.md. disallowedTools is the ONLY permitted fence at plugin/APM
scope, so the scope that needs the syntax most could not reach it, and a plugin-scope
run could write a body telling the agent to ask the user a question.

Two documents were actively wrong rather than merely thin. agent-audit told auditors
that validate.sh resolves boundary targets for skills only; it runs at both scopes,
so the auditor was hand-resolving what the script had already decided and could
contradict it. And skill-audit routed to its script-troubleshooting reference
whenever validate.sh "fails" — but it exits 1 on ordinary content FAILs, the normal
outcome for the whole #99 population, so 1,302 words loaded on nearly every audit.
A context-budget regression inside the skill that enforces the context budget.

Finally, two illustrations taught the shape the gate ERRORs on, unfenced, while an
adjacent rubric called it a hard ERROR.

LESSONS.md records the reference-chain depth rule flipping from "one level deep" to
"two hops, never three". ADR-0020 is silent on it and the reversal rode entirely on
the diff; the looser rule is what mandatory dispatch requires.

Refs: #99
ADR: 0020

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015W3iwF9ncfRZddGBxsMCYi
2026-08-16 19:49:38 +00:00
64ffb9f35a docs: make ADR-0020 match what actually shipped, and record what did not
The ADR was written against base commit `f9b919d` and then not updated as the
implementation moved, so several of its numbers were measuring one thing and being
read as another — the exact conflation the ADR exists to stop, reproduced inside
it. Corrections, all reproducible now that each figure states its method:

- The preload tax is 23,427 chars / ~5,900 tokens, not 23,612 / ~6,200.
- `MAX_WORDS=2770` is a density proxy for the agentskills.io ~5,000-token ceiling,
  not "2× p90". Neither percentile reaches it: 2× the body-only p90 is 2,698 and
  2× the whole-file p90 is 3,052. Reading it as a percentile pairs a whole-file
  gate against a body-only distribution.
- `apm-workflow` is a 421-word body; 554 is its whole-file count. `skill-author`
  and `agent-author` were 2,623 and 2,582 body words — 2,760 and 2,758 whole-file,
  which is where "within twelve words of the gate" comes from. Two numbers for one
  file is the point, and only one of them is what either gate measures.
- Every `file:line` citation now says it resolves against `f9b919d`, since this
  change rewrites most of the cited files.

Three things the ADR asserted that no validator implemented are now filed by tier
in an exhaustive enforcement table — deterministic, prose-pattern, or auditor
judgment — because a rule filed under "Enforcement" that nothing enforces is the
failure mode this ADR is most exposed to. The Gotchas entry count moves to
SUGGESTION to match the script; the paraphrase FAIL is marked as an auditor's,
since semantic equivalence is not pattern-matchable.

Two gaps recorded rather than quietly left:

- The agent body-gate exemption lives in `agent-audit`'s validator and in the
  `skill-size-check` hook's `SKILL.md`-only `files:` pattern — *not* in
  `scripts/skill-size-check.sh`, which measures whatever path it is handed and
  today reports 900-word body FAILs on `git-orchestrate` (933),
  `gitea-orchestrate` (1,199) and `apm-orchestrate` (1,080). Agents escape by file
  pattern, not because the script knows the difference, so widening that pattern
  would silently enforce a gate this ADR declines to set.
- The `skill-audit`/`agent-audit` merge is deferred to #101. This change made the
  split deeper, not shallower: the dispatch retrofit took them from 3 and 4
  reference files to 7 and 8, and their two same-named `description-quality.md`
  files now differ on 100 of ~120 lines after normalising skill/agent. The merge
  reopens ADR-0008 and touches every call site in `skill-author`, `agent-author`
  and `forge`, so it is its own change. #100 carries the dangling-target fixes.

AGENTS.md and CONTEXT.md take the same corrections plus the two live setup
changes: PyYAML is now a hard requirement rather than an optional accelerator (a
fallback that mis-parses an unfamiliar scalar shape reports a clean pass on a file
it never measured), and `.claude/settings.json`'s `pretty-format-json` exclusion is
documented as load-bearing rather than as a tidy-up candidate.

LESSONS.md's autofix entry is corrected on its own provenance, which it got wrong
in both directions. `git log --date=iso` puts the introducing commit at 18:47 and
the fix at 21:54 — three hours, not "weeks" — and `git branch -a --contains` puts
the introducing commit on this branch only, not on main. It was manufactured
inside the same PR that diagnosed it. The added lesson is that "pre-existing" is a
claim about history and history is queryable: a defect found while working on a
branch feels inherited, and the feeling is not evidence.

Refs: ADR-0020, #99, #100, #101
2026-08-16 16:41:45 +00:00
76075223c7 fix(ci): unbreak the pre-push gate — strict-mode leak and apm-owned settings drift
Two pre-existing failures, both red at HEAD before ADR-0020 work began,
both invisible in an ordinary local run.

RUN_TESTS_STRICT leaked from the environment into test-run-tests.sh's
fixture children. The meta-test is itself a suite the runner discovers,
so under the gate's own invocation the variable propagated outer runner
-> batch_run -> the fixture's copy of run-tests.sh, flipping it strict.
Case 10c (a deliberate control asserting a skip is tolerated WITHOUT
strict) then failed. Six further cases were silently running strict too
and asserting against the wrong stream — case 9 was matching the stderr
strict block rather than the stdout skip list it was written to check.
run_fake now spawns via 'env -u RUN_TESTS_STRICT', so fixture strictness
is a property of the case, never of how the file was launched. No
assertion weakened; run-tests.sh itself is untouched.

pretty-format-json --autofix was re-sorting apm's output on the way into
every commit. .claude/settings.json is apm-owned (ADR-0018/0019) and its
exclude list named fifteen generated manifests but not this file, so
since 2e395a4 it has been committed in a key order apm would never write
— permanent drift on a file with an empty git diff. Content was always
byte-identical; only JSON key order differed. The exclude ships in the
same commit as the corrected file because otherwise the hook re-breaks
it during staging.

apm.lock.yaml: generated_at churn, plus lint's exec_status corrected from
'deployed' to 'gated_pending_approval' — executables.allow grants only
kyberforge#1.5.0, so lint's hooks/bin are genuinely gated.

New coverage: an ambient RUN_TESTS_STRICT must not reach a fixture that
did not ask for it, and under --strict the skip report goes to stderr
only with the stdout list suppressed. Neither was pinned.
2026-08-14 21:54:00 +00:00
4a5c3c0cff feat(kyberforge): enforce the ADR-0020 context contract for skills and agents
Skill name+description pairs are preloaded into every session, costing
~6,200 tokens across 39 skills before any skill is invoked. The authoring
rules mandated that growth: skill-author:104 and description-quality.md:21
both required padding, while skill-author:102 (the deflating rule) had no
FAIL condition behind it.

Gates (blocking, no baseline file):
- description 250 chars SUGGESTION / 400 FAIL, measured on the folded
  YAML value
- body-only 600 words SUGGESTION / 900 FAIL, independent of the unchanged
  whole-file 2770-word / 500-line spec backstop
- every boundary-clause routing target must resolve to a real skill or
  agent; catches skill-improve, neuledge-context and gitea-labels
- agents take the description gates but deliberately no body gate; a test
  pins that absence

Vale: DescriptionOpener widened to ^This\b, new CompositionNote rule
banning architecture notes from descriptions. 10 hits, 0 false positives.

Kyberforge's own four skills retrofitted: descriptions 3,364 -> 938 chars
(-72%), bodies 8,306 -> 2,487 words (-70%), all via the apm-workflow
dispatch pattern. Fixes the skill-improve dangling route and the
agent-author misroute to manual review.

Also fixes a pre-existing false positive where any line-initial 'read '
was flagged as interactive input, which had already caused two scripts to
be rewritten around it.

Refs: ADR-0020
2026-08-14 21:13:13 +00:00
430f46b8e8 docs: correct the claims this review found false
AGENTS.md told an offline agent to push with SKIP=apm-marketplace-check and
asserted that hook was "the only one whose failure mode is 'no network'".
Running all 12 pre-push hooks under a network namespace shows two fail, for
one shared cause: apm-pack-check-clean resolves the same remote entry. An
exact pin does not remove the ls-remote, so both hooks are named now.

AGENTS.md also said everything in a plugin root except .apm/ is generated.
Plugin roots carry hand-authored README.md, docs/, bin/, sources.md and
.mcp.json, so an agent would hunt for an .apm/ source that does not exist or
refuse the edit. The rule is positional: immunity belongs to the plugin root,
and anything inside a mirrored directory is still rm -rf'd.

ADR-0017 said apm strips a hooks field. The real loop is (agents, skills,
commands, instructions) -- hooks absent, instructions never mentioned -- and
it can never fire, because synthesize_plugin_json_from_apm_yml only emits the
eight identity fields. The decision stands; the mechanism was overstated. Its
mcpServers amendment is rewritten for the pointer payload and now records the
real reason: inlining bypassed apm's credential sanitizer.

ADR-0015's owner.email and version-pin passages are corrected against the apm
source, and ADR-0016 gains the disallowedTools amendment. agent-audit's
allowlist is data, so it gains disallowedTools too -- the ADR and the
validator that enforces it had come apart.

architecture.md described a root CLAUDE.md that imports two files (it imports
one, plus an RTK block) and pointed at an ADR index that does not exist.
Seven skill READMEs listed tests/ files the mirror strips, promising installed
users files their install lacks; those rows are marked source-only, with the
depth-4 template tests explicitly called out as surviving. And
plugins/kyberforge/hooks/README.md, deleted during the conversion and
preserved nowhere, is restored to a path the mirror does not own -- verified
by running a sync against a scratch copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
2026-08-14 11:04:56 +00:00
55d956b298 docs: log two lessons from PR #95's fourth review round
The first is new: four fixes specified by the orchestrating reviewer were wrong,
each in a way that would have shipped a guard catching nothing. A finding arrives
with evidence and gets scrutinised; the fix beside it arrives with the same
authority and gets implemented. Worth naming because the failure is silent — the
guard looks right and the suite stays green.

The second is flagged as a graduation candidate rather than promoted: it overlaps
two 2026-08-09 entries on assertions that pin something adjacent to what they
name. Per the graduation rule, promotion to core/instructions/testing.md is the
human's call, not mine.

Refs: #95

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
2026-08-14 07:09:19 +00:00
7910b8b12c docs(kyberforge): fix path drift and content gaps from apm conversion
The apm conversion (5e23250) moved skills/agents to plugins/<name>/.apm/
and deleted plugin-author/marketplace-author, but a review against issue
#90's Definition of Done found several stale pre-conversion references
left behind by straight git-mv's, plus one real content gap:

- ADR-0014 still documented the old flat vale-prefilter paths in 6
  places, despite ADR-0015 claiming it had been updated.
- ADR-0015 also overclaimed: it said ADR-0014 had both a skills/ and an
  agents/ path regex updated, but ADR-0014 never had an agents/ path
  regex to begin with (its one "agents" mention is a Vale glob-section
  identifier, not a filesystem path). Corrected the wording.
- CONTEXT.md's Skill glossary entry, its Vale-prefilter section, and its
  plugin-author/marketplace-author forward-pointer all still described
  the pre-conversion layout or a "pending issue #90" state that has since
  landed.
- LESSONS.md and two skill test READMEs pointed at skill-author/
  skill-audit/agent-author paths without the .apm/ segment.
- apm-workflow/references/marketplace.md cited plugin-author/SKILL.md's
  Gotchas for the Claude Code reserved plugin-name-prefix list, but that
  list was never actually carried into apm-workflow during the
  conversion despite ADR-0015 claiming it was. Recovered the list from
  git history and inlined it directly rather than leaving a dangling
  citation.
- agent-author/references/deployment-modes.md had an example
  contradicting its own stated .apm/agents/ convention two lines above.

Refs: #90
2026-08-13 07:50:56 +00:00
7cf9a98509 docs(lessons): record two patterns from PR #85's round 6
The aggregate-assertion failure joins the "a clean result can mean nothing ran"
family as its fifth instance: a total over N subjects is satisfiable by a
proper subset, so it proves nothing about any individual subject. Records the
reverse mutation sweep — neuter each assertion, confirm exactly one case fails
— as standing practice for checks whose failure mode is silence.

The second entry is about accepted residuals: the U+2019 rewrite survived
review because its justification was documented in the same breath as the
workaround, and the covering test asserted the residual's presence rather than
the behaviour it cost. Documentation records a belief; a belief adjacent to a
workaround is the one most worth attacking.

Refs: #85
2026-08-09 17:24:08 +00:00
afc2b7fdfd docs(lessons): record two patterns from PR #85's round 4
A config's local mode can prove nothing about the mode that ships:
repo: local collapses the clone prefix, cwd and repo root into one
directory, so a byte-identical entry: string worked locally for a
reason that exists only locally, through three review rounds.

Deleting a token from a shared artifact breaks whatever parses it,
silently: dropping --config killed the loop that gave the bundled
Vale styles release coverage, shrinking a derived path list with no
error and no failing test.

Kept separate from the adjacent "clean linter result" and "one signal,
two consumers" entries, which describe different failure modes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
2026-08-09 13:32:32 +00:00
acd2f1d422 fix(lint): harden check-release-needed.sh, script the vale-style sync
A review of PR #85's last two commits (1164f3a, 4d018af) found the new
release-gate script fails open in four separate ways, and the new drift
check for the duplicated Vale styles only ever detects drift after a
human already hand-edited both copies out of sync.

check-release-needed.sh:
- The `-e` existence filter dropped a RELEASE_PATHS entry from the diff
  pathspec once it was deleted from the tree, so deleting a path exposed
  via .pre-commit-hooks.yaml since the last tag passed the gate clean —
  exactly the breakage the gate exists to catch. git diff reports
  deletions fine without an existence check; the filter is gone.
- `git diff ... 2>/dev/null || true` turned any git failure (a shallow
  clone missing the tag's objects, a corrupted ref) into an empty,
  falsely-clean diff. The diff result is no longer swallowed: a failure
  now hard-fails with the underlying git error visible.
- RELEASE_PATHS was a hand-maintained array duplicating
  .pre-commit-hooks.yaml's entry: paths with only a comment holding them
  in sync, and was already over-broad (it swept in validate.sh /
  validate-provenance.sh, which no hook entry references). It's now
  parsed straight from .pre-commit-hooks.yaml's entry: lines at
  runtime, so it can't drift from the manifest and only tracks what a
  hook actually exposes.
- `git describe --tags --abbrev=0` accepted any tag reachable from HEAD
  as the diff baseline, not just release tags. Added
  `--match 'v[0-9]*.[0-9]*.[0-9]*'` so an incidental checkpoint tag
  can't shift the baseline and mask a real release-relevant change.

check-vale-style-sync.sh still only detects drift between skill-audit's
and agent-audit's duplicated vale-wrap.sh/styles/Kyberforge copies
(both copies must exist independently per the plugin's no-cross-skill-
path packaging rule — a symlink would break at install time). Added
scripts/sync-vale-styles.sh to regenerate skill-audit's copy from
agent-audit's canonical one on demand, and pointed the sync check's
failure message at it, so fixing drift is one command instead of a
hand diff across two files.

Also recorded, rather than silently left unfixed: check-release-needed.sh
only fires on a local `git push` through pre-commit's pre-push hook — a
PR merged via Gitea's merge button, or CI invoking
`pre-commit run --hook-stage pre-push` directly, never sets
PRE_COMMIT_REMOTE_BRANCH and skips the gate entirely. Closing that needs
a server-side CI job this repo doesn't have yet; documented as a known
limitation in ADR-0014 rather than papered over.

Separately, LESSONS.md's "a clean check can mean nothing ran" entry was
marked **Graduated** without ever being promoted per the repo's own
graduation rule (3+ instances → a standing doc, marked
`[graduated → target file]`). Actually promoted it into
core/instructions/testing.md and fixed the marker.

tests/test-check-release-needed.sh gained 4 regression tests, one per
check-release-needed.sh fix above, each verified to fail against the
pre-fix script and pass against the current one.

Verification: bash tests/run-tests.sh (11 scripts + 125 bats, all
passing), pre-commit run --all-files, and
pre-commit run --all-files --hook-stage pre-push all clean.

ADR: 0014
2026-08-09 11:20:55 +00:00
1164f3abad fix(lint): make Vale prefilter portable via the plugin
skill-audit/agent-audit's Step 1 resolved vale-wrap.sh/.vale.ini via
`git rev-parse --show-toplevel`, which returns whichever repo the skill
happens to run in. Inside ai-development that works; in any external repo
that installs kyberforge@holocron as a plugin, it resolves to that repo's
own root, which has no .vale.ini — the prefilter silently fell back to
full LLM judgment. ADR-0013 named this as a deliberately deferred gap.

Vale's config/styles/wrapper now ship inside the plugin itself: a
canonical copy in agent-audit/assets/vale/ (Kyberforge + KyberforgeCopilot,
the superset agent-audit needs) and a smaller duplicate in
skill-audit/assets/vale/ (Kyberforge only) — per the no-cross-skill-path
rule already established for plugin cache-installs. Both skills resolve
these relative to their own directory, same as scripts/validate.sh
already does.

A new root .pre-commit-hooks.yaml exposes both copies plus
skill-size-check so any external repo can enforce the same rules via
`repo: <this-repo-url>, rev: <tag>` in its own pre-commit config,
independent of Claude Code entirely — the same mechanism covers CI. This
repo's own pre-commit hook now consumes the identical plugin-bundled
copies via repo: local (not a third root copy, and not a pinned
self-reference, which would lint working-tree edits against the last
tagged release instead of the change being made). Split into
vale-audit-prefilter-skill/-agent hooks after confirming, by diffing the
full corpus against both old and new config before deleting the old
files, that one combined hook pointed at only one copy silently 0-file-
skips the other file type.

scripts/check-vale-style-sync.sh guards the two copies against drift,
wired at pre-push alongside check-manifests.

ADR: 0014
2026-08-09 10:04:19 +00:00
864e7c689c docs(lessons): record three patterns from PR #85's review rounds
Three rounds of review on the Vale prefilter surfaced patterns worth
keeping rather than just fixing.

The first has now recurred three times in a single PR — a check reporting
success because it had silently not run — so it is flagged as a
graduation candidate per LESSONS.md's own three-instance rule.

- A clean linter result can mean "nothing was checked": the frontmatter
  scope silently not matching, warning-level rules never affecting an
  exit code, and globs matching zero files all produced green results
  that were then cited as evidence of cleanliness.
- One signal, two consumers, no named distinction: Vale severities were
  tuned for the audit report while the commit gate silently inherited the
  resulting exit code, because CONTEXT.md described both as one mechanism.
- Measure a rule's false-positive rate at the severity you will ship it
  at: VagueQualifier was trialled at warning, where a false positive is
  free, and shipped at error, where it costs a blocked commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
2026-08-08 20:54:19 +00:00
Claude Code AI - Gitea MCP
060771b481 fix(tests): auto-init submodules when bats binary is missing (#77) 2026-07-05 13:49:49 +00:00
7a00368683 docs: remove ROADMAP.md and scrub all references
## Why

ROADMAP.md was a static file that duplicated tracking information now
owned by Gitea milestones and issues. Keeping it created a maintenance
burden — references drifted out of sync with the actual state of work,
and agents were directed to read it when the source of truth had moved.

## Implementation Notes

All inbound references replaced with either the relevant Gitea milestone
("Skills & Agents") or removed where the context made them redundant.
Test assertions that verified ROADMAP.md content removed; test output
strings updated to drop the ROADMAP cross-reference instruction.

## Impact

Agents no longer read docs/ROADMAP.md at session start. Gitea milestones
and issues are the canonical source for roadmap and open-question tracking.

---

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 19:37:43 +00:00
52c154d4ce docs(lessons): record skill-author provenance lesson
Agents briefed to write skill files directly bypass the provenance
step — always invoke /skill-author explicitly instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 11:24:13 +00:00
4cbc993af4 docs: remove stale references to deleted setup scripts
Update docs to reflect pre-commit migration and cleanup:
- spec/overview.md: removed phantom test file references
- ROADMAP.md: removed references to non-existent test files
- LESSONS.md: removed reference to setup-hooks.sh bug

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-27 19:04:20 +00:00
0c6268f9fe docs(lessons): capture multi-fork validation and conflict patterns
## Why

Two recurring failure modes surfaced during the agent-author workstream
that are worth capturing before they repeat: biased forks producing
false-PASS audits, and parallel forks producing conflicting fixes on
the same file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 15:15:35 +00:00
95ba57d0d5 fix(kyberforge): address self-audit findings and update lessons
- Reorder skill-audit description to lead with 'Use when...' trigger (P3)
- Add concrete example to 'control calibration' body discipline check (P4)
- Add bats test files to README file tables for both skills
- Fix REPO_ROOT and SCRIPT paths in bats files after tests/ subdirectory removed
- Add three lessons: plugin cache isolation, spec-grounded rubrics, test file placement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 20:16:24 +00:00
1a0cebc5e0 docs(lessons): record three patterns from 2026-06-21 audit session
- claude plugin validate --strict absent from standard test sweep
- gitleaks source/deployed config silent divergence risk
- shellcheck without -x blocks pre-commit on scripts using source

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv5iNACZxumtF2k6TsK18q
2026-06-21 01:37:20 +00:00
663f10c3fe fix: write-skill progressive disclosure — sub-file structure and lessons
- Add sub-file constraint: content-type split rule (explains vs. directs),
  three spec-defined optional directories (scripts/, references/, assets/),
  one-level-deep rule, and wiring syntax requirement
- Update output format section to list optional sub-files as a third output
- Add self-check item for sub-file placement and wiring
- Update SKILL-TEMPLATE.md constraints and output format examples to match
- Bump META.md to v1.3
- Add two LESSONS.md entries: research agents presenting synthesis as spec
  fact; META-TEMPLATE fix deferred with explicit do-not-apply note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 18:33:36 +00:00
be2910f8f6 fix: write-skill governance review — model field, eval self-check, grill wiring
- Add model: sonnet to SKILL.md frontmatter (Claude Code extension; correct
  location per research — runtime config belongs in frontmatter, not META.md)
- Document model field in SKILL-TEMPLATE.md with factory §9 routing guidance
- Wire grill output explicitly to trigger description step (step 3 now references
  agreed name/category/purpose from grill rather than drafting independently)
- Strengthen eval self-check: presence check → coverage check (trigger cases +
  at least one output case required)
- Bump META.md to v1.2 (2026-05-26)
- Add three LESSONS.md entries: META-TEMPLATE comment retention, overlap check
  scope (deployed dir not just repo), model field placement boundary

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 18:12:03 +00:00
e3cc0b65f4 refactor: write-skill phase 1 refactor — grill, implementation, lessons
Complete 2026-05-18 workstream for write-skill refactor (issue 0018 phase 1).

Grill output (handoff in docs/issues/0018-factory-write-skill.md):
- 6-section standard replaces 8: Role and When/When not dropped (not in
  agentskills.io spec; description carries trigger scope and negatives)
- Frontmatter reduced to 3 fields; provenance moves to META.md
  (progressive disclosure — not loaded at every skill scan)
- SKILL-TEMPLATE.md and META-TEMPLATE.md as authoritative copy-fill artifacts
- CATEGORIES.md as self-contained category reference in skill directory
- Copy and fill explicitly split into separate process steps for determinism

New files in .agents/skills/write-skill/:
- SKILL-TEMPLATE.md — 6-section template with XML blocks and inline examples per section
- META-TEMPLATE.md — provenance schema with inline-commented YAML; source vs references explicit
- CATEGORIES.md — self-contained category table (no runtime dependency on factory docs)
- META.md — write-skill's own provenance (v1.1, self-authored)

SKILL.md rewritten: 8-step process, XML blocks (<requirements>, <steps>, <checks>),
3-field frontmatter, copy-then-fill steps explicit.

Supporting docs updated:
- skill-implementation-workflow.md: SKILL-TEMPLATE.md as authoritative template;
  source:/references: now reference META.md; when: marked resolved
- factory-integration-decisions.md: frontmatter spec corrected
- ROADMAP.md: authoring standard description updated
- CONTEXT.md: Source field entry corrected; META.md added to glossary
- docs/spec/overview.md: 2026-05-18 refactor entry added
- docs/issues/0018: handoff status updated; acceptance criteria marked complete

LESSONS.md: 3 entries added in grill session (cargo-culted body sections,
provenance fields in frontmatter, copy-fill determinism) + 1 from implementation
(planning meta-commentary does not belong in deployed artifacts).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 06:48:46 +00:00
3dcd0f08fb feat: implement issue 0018 phase 2 — write-docs skill (first factory output)
Produces write-docs via the write-skill factory. First skill authored
end-to-end by the factory (SKILL.md via write-skill, eval via write-eval).

- Add .agents/skills/write-docs/SKILL.md (category: implement)
- Add .agents/evals/implement/write-docs/eval.yaml (6 trigger + 3 output tests)
- Remove write-a-skill placeholder (superseded by write-skill)
- Extend issue 0018 with Phase 3 (doc convention, grill-first)
- Tighten workflow steps 5a and 5d based on session lessons
- Update factory-integration-decisions: write-a-skill → write-skill
- Add 2 LESSONS.md entries (trigger gate, write-eval sub-agent bypass)
- Update docs/spec/overview.md and ROADMAP

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 19:05:47 +00:00
58476a96fd feat: implement issue 0018 phase 1 — factory/write-skill bootstrap skill
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 18:24:28 +00:00
83715018eb feat: implement issue 0017 — factory/write-eval bootstrap skill
Adds write-eval, the first factory meta-skill. Produces eval.yaml test
files for skills following the two-section schema (trigger_tests +
output_tests) with provider-agnostic string assertions and show-plan-
then-merge-on-rerun behaviour. Hand-written bootstrap — subsequent
skills will use write-eval to produce their own evals.

Also tightens skill-implementation-workflow.md step 5b: per-section
options walk-through is now a named gate before writing, separate from
the synthesis grill. LESSONS.md entry added.

HITL behavioral test pending.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 17:52:02 +00:00
c705a38809 docs: issue 0016 — skill implementation workflow grill
Produces docs/notes/skill-implementation-workflow.md with agreed conventions
for all Chunk 3 skill issues (0017–0028). Key decisions:

- Per-skill process: source discovery (sub-agent) → source review with
  licence/security check (sub-agent) → conflict check vs constitution +
  factory principles (sub-agent) → synthesis grill → co-write iteratively
- Bootstrap: write-eval (hand-written) → write-skill (hand-written) →
  write-docs (first factory-authored, phase 2 of 0018) → everything else
- Upstream review changed from per-chunk-start to per-skill
- `when:` and `references:` frontmatter fields added to authoring standard
- Sub-agent usage prescribed as named steps in the workflow
- HITL: human reviewed and approved conventions

Updates: PRD implementation decisions; issues 0016–0028 with specific
acceptance criteria; docs/spec/overview.md; ROADMAP Chunk 3 housekeeping note
(bootstrap order, cadence, acceptance criteria status); CONTEXT.md Source field
(per-skill cadence, references: companion field); LESSONS.md with three patterns
from the grill session.

Post-grill additions (same session): Step 6 (session handoff) added to the
workflow; handoff section appended to issue 0016; handoff checklist item added
to Chunk 3 closure issue (0028).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 17:06:35 +00:00
74f5e1840d test: run Chunk 2 and governance behavioral tests; fix failing rules
13 manual scenarios run across instructions and governance layers (two
rounds for failures). Fixed four rules that lost to RLHF defaults:

- Exploratory question format: tightened with boundary framing; added
  @import CONTEXT.md to repo CLAUDE.md and a standing rule to check
  docs/adr/ and ROADMAP resolved entries before answering design questions
  (3-round iteration to resolve)
- File-edit intent: added counter-example to stop clarification-seeking
- Push confirmation: reframed as "do not call the tool" not "ask first"
- Secrets rule: extended to cover credential reproduction in response
  text and usage examples, with explicit placeholder requirement

Scenario 4 (push confirmation) inconclusive — no remote configured.
Governance scenario 3 (HITL on real infra) untestable — Nginx not installed.
Both share the same root cause: agent delegates to permission system.

Also corrects stale skill list in docs/spec/overview.md (12 actual
deployed skills vs 16 names previously listed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:44:56 +00:00
b55eede1ef docs: implement issues 0013 and 0014 — LESSONS.md and docs/spec/
Add LESSONS.md as the long-loop feedback log at repo root. Patterns
observed during development graduate to standing rules when three or
more entries appear.

Introduce docs/spec/ as the living spec layer: overview.md (deployed
state) and architecture.md (directory structure, install pipeline,
provider model, governance layer). Refactor docs/VISION.md to goals
and intent only — architecture content moved to docs/spec/architecture.md.

Update CLAUDE.md and CONTEXT.md to reference the new spec files.
Close issues 0013 and 0014. Update ROADMAP and factory integration
note to reflect completion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 10:36:59 +00:00