Commit Graph

67 Commits

Author SHA1 Message Date
0dd044a782 docs(kyberforge): add ADR-0016, agent tools-field omitted at plugin scope
#89's grilling session surfaced a real upstream gap: APM's agent
primitive has no per-target compile integrator, so tools: and every
Claude-only field (isolation, maxTurns, effort, memory, permissionMode)
would verbatim-copy into Copilot's file with an incompatible or
unrecognized shape. Omitting them entirely is the only option that
never ships a wrong value to a real harness.

Scoped to plugin-scope agent-author only — project/user scope keep
today's Claude+Copilot pair model unchanged. Partially supersedes
ADR-0005 and ADR-0008's plugin-scope clauses (addenda appended to
both); ADR-0009's field-inventory.md mechanism is unaffected, only
its plugin-scope content shape changes.

Refs: #89
2026-08-11 17:17:32 +00:00
92e7ff26aa docs(kyberforge): narrow issue #89 scope, migrate CC platform facts to apm-workflow
A grill-me session determined plugin-author/marketplace-author are fully
superseded by the landed apm-install/apm-workflow/apm-orchestrate artifacts
and will be deleted (not adapted) under issue #90, narrowing issue #89 to
skill-author/agent-author only; forge stays untouched. ADR-0015 is amended
to record this correction plus a three-way content-migration audit.

Claude Code platform-constraint facts that lived only in
plugin-author/marketplace-author (reserved name prefixes, the ADR-0010
agents/ stray-.md validator gotcha, claude plugin validate as a terminal
check, and a removal/re-pack confirm-before-proceeding note) remain true
post-conversion and are migrated into apm-workflow's reference docs via
kyberforge:skill-author, which also updated the skill's README and
sources.md provenance records. Dual-manifest-specific conventions (ADR-0006
parity, CC/Copilot field-placement split) do not carry forward since they
no longer apply.

ADR: 0015
2026-08-11 12:09:43 +00:00
394052ff66 docs(kyberforge): fix remaining PR #91 review findings, add apm install routing
Re-review (comment 24) of fix commit e16c3dc found six new issues, mostly
introduced by that fix commit itself: a dangling reference to a Hard Rule
bullet the same commit deleted (apm-orchestrate.md/.agent.md Process step
2 still named "secret indirection"), and an ADR-0015 Decision bullet that
claimed "this ADR does not update CONTEXT.md" while the same commit had
just added a forward-pointer sentence to CONTEXT.md's Plugin/Plugin
marketplace entries. Both reworded to match what actually happened.

apm-install's APM_INSTALL_DIR escape-hatch example dropped the curl pipe
entirely (`APM_INSTALL_DIR=... sh` with nothing piped into it) — fixed in
both apm-install/SKILL.md and the installation.md research doc, verified
against the upstream Microsoft APM docs via Context7.

Neither apm-workflow nor apm-orchestrate routed to plain `apm install
[PACKAGE_REF]`, the CLI command that actually resolves/fetches
dependencies declared in apm.yml — apm-install only bootstraps the apm
binary/runtime, not per-package deps. Added a 5th "install" dispatch
action to apm-workflow (new references/install.md, SKILL.md table row,
README usage/files sync, sources.md provenance entry) and a matching
"install" operation group on apm-orchestrate so it can route there.

configure.md's apm.yml schema block was also missing the "legacy singular
`target:` CSV form is still accepted" caveat its sibling research doc
documents for the same field — added for consistency.

The sixth finding (paired .md/.agent.md Output-contract disagreement) was
checked against git-orchestrate and gitea-orchestrate's existing pairs and
found to match established repo convention (JSON schema in .md, prose
summary without the enum in .agent.md) — left unchanged as a false
positive rather than "fixed."

kyberforge bumped 1.3.0 -> 1.3.1 via agent-author's normal improve flow.

Refs: #91

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186ERbyACLRuRxPRnqwpa4m
2026-08-11 11:09:43 +00:00
e16c3dc95f docs(kyberforge): fix PR #91 review findings in ADR-0015 and apm docs
ADR-0015's Decision bullet stated ADR-0001 was superseded as present
fact while Consequences framed it as conditional on issue #90 —
reworded Decision to match, and added a Supersedes header (repo
convention per ADR-0007/ADR-0010) so the pending change is visible
from the title. Also fixed a forward-note that misattributed the
pre-existing .agent.md convention (ADR-0005/0010) to the APM move,
and reworded the rejected-plugins/apm/ rationale to acknowledge the
shipped skills are actually generic rather than repo-specific.

CONTEXT.md's Plugin/Plugin-marketplace glossary entries got a
forward-pointer to ADR-0015 so a session-start read surfaces the
pending manifest-authoring change.

apm-orchestrate.md/.agent.md: removed a Hard Rule requiring ${VAR}
secret indirection that can never fire (the orchestrator has no
Edit/Write tool and never touches apm.yml — apm-workflow's SKILL.md
already owns this rule where content is actually written); removed
compile-manifest-check, an operation with no backing apm CLI command
anywhere in the research docs; added explicit CLI mappings for
add-package/add-marketplace so an executing agent can't invert them.

marketplace.md's release steps shelled out to raw git add/commit/
tag/push — replaced with a pointer to the git-commits/git-remotes
skills per AGENTS.md's "prefer plugin skills over raw shell" rule.

compile.md now states audit runs after compile/pack (audit scans
deployed output, not the source apm.yml) — answers a reviewer
question that had no documented answer.

Refs: #91

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186ERbyACLRuRxPRnqwpa4m
2026-08-10 21:23:07 +00:00
0e421acdbb docs(adr): add ADR-0015 for outright APM conversion
Records the grill-with-docs decision on issue #88: replace the
hand-authored plugin/marketplace manifest model with Microsoft APM
(apm.yml + .apm/) as this repo's authoring source of truth. The
plugins/<name>/ monorepo-hybrid layout survives; marketplace.json and
provider plugin.json files become compiled output. Supersedes
ADR-0001; touches but does not resolve ADR-0006/0010/0014. Follow-up
work tracked in issues #89 and #90.
2026-08-10 17:42:31 +00:00
302f6d0c19 fix(lint): tighten the SKILL.md word ceiling to 2770
MAX_WORDS=2900 was calibrated to the corpus median density and carried no
margin: at the densest observed 7.22 chars/word (~1.81 tokens/word) it permits
~5,240 tokens against the 5,000 it proxies for. 2770 holds the worst observed
density under the ceiling. The largest SKILL.md is 2,489 words, so the change
costs nothing today — 281 words of margin — and the header comment now argues
the new calibration rather than swapping the digits.

Both enforcement points move together, and a new test asserts they agree, since
a SKILL.md passing its own audit while the commit hook blocks it is the
disagreement this pair exists to prevent.

CONTEXT.md is deliberately left ungated: it is 2,816 words, and gating it would
block the build. Recorded here so the omission reads as a decision rather than
an oversight.

skill-audit's manual-fallback path listed only the line ceiling, so an agent
taking that path passed an oversized SKILL.md the hook then rejected. The word
ceiling is now named alongside it. agent-audit is deliberately unchanged: the
size hook scopes to SKILL.md only and agent-audit's validate.sh has no word
gate, so claiming it there would be false.

The Vale research doc still showed the MDX {/* vale off */} form under a
Markdown heading, contradicting CONTEXT.md and vale-run's troubleshooting
reference — that form suppresses nothing in plain .md. Fixed in both places it
appeared.

tests/run-tests.sh used mapfile (bash 4.0+) with unguarded array expansion,
though AGENTS.md tells contributors to run it and macOS ships bash 3.2. It now
collects via a while-read loop over process substitution and guards every
expansion. The newline-delimited find|sort pipeline is kept rather than -print0
with sort -z, whose BSD portability is the weaker link, and which matches
mapfile -t's previous behaviour exactly.

Refs: #85
ADR: 0013
2026-08-09 17:23:51 +00:00
ad1e5aaa9b fix(kyberforge): carry apostrophes verbatim through a |- literal block
The flattener's last-resort branch rewrote ASCII ' to U+2019, justified as the
one combination no YAML scalar can carry verbatim. That claim was false: a |-
literal block with a single indented content line carries ', ", \ and ": "
verbatim and keeps text.frontmatter.description matching — as the wrapper's own
docstring already said of literal blocks. The rewrite fired on 12 of 54
in-scope files, silently disabling every rule whose token contains an
apostrophe. Case 20 pinned only that the scope stayed alive, so it passed
either way.

The emission site now splits the emitted scalar on its first newline so a
carried-over trailing comment stays on the "description: |-" header line rather
than becoming part of the value, and pads by span_lines - 1 - newlines. The pad
stays non-negative because the branch is only reachable when the original span
is at least two lines. Verified across all 73 in-scope files: no line-count
changes, and exactly the 12 expected files take the new branch.

One reported position moves: an alert on a description that is itself flagged
shifts from the key line to the block's content line, both inside the original
span. YAML cannot put a literal block's content on the key's own line, so this
is unavoidable; no line at or after the end of any description span moves.

Also: --output no longer absolutises the built-in style names line, JSON and
CLI, which a same-named file or directory in cwd turned into a template path
(exit 2, E100 Runtime error). And case 19's empty-baseline guard no longer
lets five dependent comparisons print vacuous passes — while fixing it the
guard turned out to be unreachable, since under pipefail an alert-free report
aborted the script at the assignment.

Refs: #85
ADR: 0014
2026-08-09 17:23:24 +00:00
57654c4b02 docs(lint): correct the Vale scalar, size-ceiling and release-gate claims
Four claims in shipped agent-facing docs did not match verified behaviour.
These are read as ground truth by agents in other repos, so each was
reproduced against vale 3.15.2 before rewriting:

- CONTEXT.md and `vale-config/SKILL.md` said both `>` and `|` block scalars
  break the description scope. `|` does not — it lints normally and fires every
  alert, while `>` yields zero. An agent following the old text would rewrite a
  working `|` description into a plain multi-line scalar, which genuinely does
  break, inverting the intended remediation. Both now name the forms that do
  break and state that `|` does not.
- CONTEXT.md and ADR-0013 described the size hook as failing only above 500
  lines, omitting the 2900-word gate it also enforces. Both now describe the
  pair and state that `validate.sh` checks the same two.
- ADR-0014 recorded an accepted residual — a wholesale `assets/` deletion going
  unflagged — that commit 14c2c91 closed. Left as the point-in-time record and
  amended with an update describing the union-with-tag-manifest mechanism,
  following the amendment precedent in ADR-0005.
- `vale-config/SKILL.md` asserted a fresh `.vale.ini` fails until `vale sync`
  runs, contradicting its own note that built-in styles need no download. The
  claim is now scoped to package styles; this repo's two configs declare no
  packages and lint clean with zero syncs.

Also repoints AGENTS.md at the seven `gitea:*` skills — the `bin:gitea` route
it named no longer exists.

Refs: #85
2026-08-09 15:44:28 +00:00
e9234f6d8a docs(lint): correct the Vale exit-code and glob-scoping claims
cli-reference.md said vale exits non-zero for any alert at or above
MinAlertLevel. The exit code keys on error-level alerts alone;
MinAlertLevel filters display only. LESSONS.md records this exact
misconception as costing two review rounds, and this research doc is
the cited provenance source for the skills that state it correctly.

CONTEXT.md claimed a SKILL.md outside plugins/ matches no glob section.
[**/SKILL.md] matches any path ending in SKILL.md — the sentence is a
stale leftover from the path-scoped globs at cbc33d9, and contradicted
its own paragraph two sentences earlier. The NOT-RUN 0-files guard it
justifies is correct and is unchanged; only the rationale was wrong.
CONTEXT.md also cited the local files: regex as the scoping mechanism,
where the shipped manifest deliberately stays layout-agnostic.

ADR-0014 records the entry[0]-only prefixing constraint as the reason
the self-locating design is required, and that no entry may grow a
repo-internal path argument.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
2026-08-09 13:06:52 +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
4d018af03c fix(lint): hard-fail on main when a release tag is needed
.pre-commit-hooks.yaml now exposes hooks to external consumers pinning
rev: <tag>, but nothing enforced that a tag actually gets cut when the
files it references change — relying on memory is exactly what this
repo's governance rules say to avoid for a repeatable, deterministic
check.

scripts/check-release-needed.sh hard-fails at pre-push, but only when
PRE_COMMIT_REMOTE_BRANCH (set by pre-commit's hook-impl) is
refs/heads/main: it diffs .pre-commit-hooks.yaml's referenced paths
against the last tag reachable from HEAD, and fails if either no tag
exists yet or something changed since. It's a silent no-op on every
other branch — hard-failing on feature-branch pushes mid-review would
force a premature tag on a commit that might not survive a
squash-merge, the exact risk the repo: local (vs. pinned self-
reference) decision in ADR-0014 already avoids for this repo's own
dev-time gate.

Verified against the real git pre-push hook path (not just the script
in isolation): simulated stdin matching git's pre-push protocol through
.git/hooks/pre-push, confirmed it correctly fires and fails when
targeting main with no tag, and is silent otherwise.

ADR: 0014
Refs: #87
2026-08-09 10:20:43 +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
149d564f6a fix(lint): make the Vale gate actually gate, drop VagueQualifier
Round-3 review of PR #85 found the "enforcing" pre-commit hook enforced
nothing. Vale's exit code keys on error-level alerts alone: five of the
six rules were level: warning, so they exited 0, and pre-commit hides
output from a passing hook — the alerts were invisible and blocked
nothing. ADR-0013 rejected a report-only trial tier and then shipped one
by accident.

Flatten every rule to level: error. Vale's own exit code is then correct,
so the hook entry drops to a bare vale-wrap.sh call and the graded
error->FAIL / warning->SUGGESTION mapping disappears from both audit
skills: every alert is a FAIL, in the gate and the audit alike. No
ignorable tier, matching shellcheck, the test suite and
conventional-pre-commit.

Delete Kyberforge.VagueQualifier. Measured against the 41 skill/agent
files as they stood before the rule ever ran: 2 hits. One marginal
("very different" -> "fundamentally different"), one an unfixable false
positive — caveman/SKILL.md quotes "of course" as an example of filler,
a mention not a use — which forced the only Vale suppression comments in
the repo. Those four lines go with it; two of them were dead anyway,
suppressing a frontmatter-scoped rule on a body line. Held-out prose (273
files) fired 15 times, 9 inside out-of-scope research examples and the
rest one word in two idioms in a single doc. SentenceOpenerThereIs
survives: 22 held-out hits, both in-corpus hits clean rewrites, zero
suppressions.

Widen .vale.ini's globs to [**/SKILL.md], [**/agents/*.md] and
[**/*.agent.md]. The plugins/*/-prefixed globs scoped nothing — Vale's *
crosses /, so they already matched docs/research/examples/**/agents/*.md
and assets/templates/SKILL.md, the two paths CONTEXT.md claimed they
excluded. Scoping is and was the hook's files: regex. The old globs also
hid a silent false negative: a skill outside plugins/ matched no section,
so Vale reported 0 files and exited 0, which both audits read as clean.
They now treat a 0-file run as NOT RUN and fall back to full judgment.

Also:
- vale-wrap.sh resolves relative --config values and file arguments
  against the caller's cwd, as vale does, instead of the repo root, which
  hard-errored from a subdirectory and silently skipped flattening for
  file args that did not resolve from the root. Absolute paths inside the
  cwd are relativized so reports cite resolvable paths, not scratch ones.
- vale-run's exit-code model was documented backwards ("exits non-zero
  whenever it finds an alert at or above MinAlertLevel") and would have
  led anyone following it to build a gate that passes everything. Its
  Markdown suppression syntax was MDX-only and does not suppress in .md;
  corrected in the skill and its troubleshooting reference, with
  backtick/fence exemption documented as the first resort.
- skill-size-check.sh fails only above 500 lines, agreeing with
  skill-audit's validate.sh <= 500 pass.
- ADR-0013 and CONTEXT.md amended to match, recording why graded
  severities cannot gate.

Verified: 9 test scripts / 15 vale-wrap cases pass; vale-audit-prefilter,
skill-size-check and shellcheck pass --all-files; check-manifests and
claude plugin validate --strict clean. New tests fail against the old
script (3 of them) and pass against the new one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
2026-08-08 20:42:15 +00:00
792d3e1852 fix(lint): resolve round-1 and round-2 review findings on the Vale prefilter
Addresses PR #85's outstanding review items after grilling the open
questions against ADR-0013/CONTEXT.md/ADR-0010:

Blocking fixes:
- vale-wrap.sh: replace json.dumps() escaping (which silently defeated
  Vale's frontmatter scope on any description containing a quote,
  backslash, or non-ASCII char — ~58% of the corpus) with a single-quoted
  YAML scalar, substituting a Unicode right single quote for embedded
  apostrophes rather than '' doubling (Vale's frontmatter scanner isn't a
  full YAML parser and silently truncates on '' too).
- vale-wrap.sh: fix a blank-line-inside-a-folded-description truncation
  bug via indentation-based, blank-line-tolerant body capture; narrow
  flattening to `>`-style scalars only (`|` already works unflattened).
- skill-audit/agent-audit Step 1: make the vale-wrap.sh invocation
  cwd-independent via git rev-parse --show-toplevel, fixing a bug where
  no single cwd satisfied all three Step 1 commands.
- styles/Kyberforge/VagueQualifier.yml: prune 17 tokens verified
  false-positive-dominated on this repo's own voice via a real corpus
  sweep (obvious, clearly, usually, several, simple, easy, completely,
  simply, tiny, etc.), keep 13 with real or unattested noise. Revert the
  28 prose "fixes" those tokens drove across 14 skill files back to their
  original, correct wording, including a functional regression to
  caveman/SKILL.md's own filler-word list (a mention, not a use) — now
  guarded with vale-off comments against recurrence.

Gaps:
- --minAlertLevel=warning on the pre-commit hook and Step 1 invocation
  so warning-level rules actually surface, without collapsing the
  FAIL/SUGGESTION severity mapping skill-audit/agent-audit rely on.
- vale-wrap.sh: fix --config=<path> equals-form, absolute-path silent
  no-op, and a zero-file-argument stdin hang.
- Route vale-run and lint-runner through a documented wrapper script
  when a target repo has one, instead of unconditionally recommending
  bare `vale`.
- Wire Kyberforge.VagueQualifier/SentenceOpenerThereIs into skill-audit/
  agent-audit's dimension-mapping prose (Body discipline).
- Add plugins/lint/sources.md provenance for lint-runner (ADR-0010).
- Sync both marketplace.json lint-entry descriptions with plugin.json.
- Retune skill-size-check.sh's MAX_WORDS 5000->2900 (measured ~1.6-1.7
  tokens/word on this repo's corpus, the old value gated at ~8,500
  tokens against a stated 5,000 ceiling); fix the >/>= line-count
  boundary and wc -l undercount on files with no trailing newline.
- Document the vale binary as a Setup prerequisite in AGENTS.md.
- Fix SentenceOpenerThereIs's dead regex alternative and add a real
  sentence-start anchor/scope.
- Fix a stale docs/research/docs/vale/ index pointer in kyberforge's
  docs README (moved to plugins/lint/ in e1a5403).
- Rewrite ADR-0013's Consequences section past-tense to describe what
  actually landed, and record the styles-portability limitation
  (repo-root placement stays intentional; deferred to a separate
  session per this PR's review).

Test coverage: 9 new vale-wrap.sh fixtures (quotes, backslash/unicode,
blank-line paragraphs, --config= form, zero-arg/absolute-path handling,
literal-block no-regression) and boundary-pair tests for
skill-size-check.sh's line/word ceilings.

bash tests/run-tests.sh: 9 scripts + 125 bats assertions, all passing.
scripts/check-manifests.sh and claude plugin validate --strict: clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
2026-08-08 20:21:21 +00:00
3324a73225 feat(lint): expand Vale audit prefilter into a broader plugin-content harness
Deferred item from PR #85 review. Per ADR-0013: cherry-picks two low-noise
rules from trialing write-good/alex against the real corpus (VagueQualifier,
SentenceOpenerThereIs) into styles/Kyberforge rather than adopting either
package wholesale (both are tuned for blog prose and were noisy on this
repo's terse, imperative instruction files - see the ADR's rejected-rule
list). Adds a new skill-size-check pre-commit hook enforcing agentskills.io's
500-line/5,000-token SKILL.md ceiling, currently unenforced. Fixes the 28
resulting violations across 20 existing SKILL.md/agent files so the
enforcing pre-commit hook lands clean.

governance.md/CONTROLS.md were evaluated and excluded as rule sources -
they're org/CI-infrastructure controls, not prose patterns Vale can express.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUDczvw1H3eEeMD29Q9Lbi
2026-08-08 20:20:58 +00:00
6c8ea8e8f0 feat(core): add agentsmd-audit skill files
The previous commit only landed the research-folder rename — a multi-path
git add silently failed and left CONTEXT.md, ADR-0012, and the actual skill
files unstaged. This lands them: the agentsmd-audit skill itself (three
deterministic validators for secrets, structure, and drift against a target
repo's AGENTS.md), its bats test suite, provenance record, and the
CONTEXT.md/ADR entries documenting why this lives in core rather than
kyberforge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 17:08:19 +00:00
Claude Code AI - Gitea MCP
bc7b3ecdbf refactor(gitea): deep modules — split flat dispatch skill into 6 domain skills + orchestrator + agent (#67) 2026-07-05 19:53:26 +00:00
996d9be428 fix(agents): relocate provenance sources.md outside agents/ dir
`claude plugin validate --strict` auto-discovers every .md under a
plugin's agents/ directory as an agent requiring frontmatter, so the
provenance file there always needs fake agent frontmatter to pass
validation. Confirmed empirically that an explicit `agents` manifest
array can't suppress this discovery. Move the file to <plugin-root>/
sources.md instead, and update agent-author/agent-audit accordingly.

Adds ADR-0010, partially superseding ADR-0005's `agents/sources.md`
convention. Fixes #63.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 09:01:06 +00:00
05bb9d6e9f docs(adr): triage, rewrite, and renumber ADRs for clean slate
Complete ADR refactoring for issue #15:

## Changes

1. **Triage archival** — deleted chunk-era ADRs (0001–0003, 0006–0011, 0013); kept active decisions (0004, 0005, 0012, 0014+)
2. **ADR-0004 rewrite** — now reflects plugin-based skill distribution (`plugins/<name>/skills/` + `claude plugin install`) instead of monolithic `.agents/skills/` deployment
3. **Renumber to 0001–0009** — sequential clean slate after archival; all cross-references updated
4. **Content audit** — verified all 9 remaining ADRs for alignment with plugin model, removed stale chunk/deployment language

Kept ADRs: 0001–0009
- 0001: Skills distributed via plugins
- 0002: Two-tier CLAUDE.md (always-on + on-demand)
- 0003: AGENTS.md as provider-agnostic entry point
- 0004: INFO finding level in skill-audit
- 0005: agent-author dual provider scaffold
- 0006: Plugin version parity (version in both manifests)
- 0007: Gitea as exclusive issue tracker
- 0008: agent-audit single-file invocation
- 0009: agent-audit field inventory reference

All decisions are active and aligned with current repository state (marketplace/plugin model).

Closes #15 (ADR section of acceptance criteria)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-04 17:18:04 +00:00
92c13b997f feat(kyberforge): add agent-audit skill (closes #11)
## Why

agent-author produces paired agent definition files (Claude Code .md +
Copilot .agent.md) but had no companion audit skill to validate them.
agent-audit fills that gap, giving the same structured PASS/FAIL report
that skill-audit provides for SKILL.md files.

## Implementation Notes

- validate.sh uses scope detection (walk up for plugin.json / .git) to
  locate the counterpart file and determine whether plugin-silently-ignored
  fields (hooks, mcpServers, permissionMode) should be flagged
- CC-only and silently-ignored field lists are read from
  references/field-inventory.md at runtime rather than hardcoded —
  provenance back to the research corpus; see ADR-0019
- Single-file invocation (pass either file, counterpart derived) chosen
  over directory or name+root — see ADR-0018
- 12 bats tests cover provider detection, scope detection, all FAIL paths,
  and clean-pair pass

## Impact

- kyberforge bumped to v1.1.2
- agent-author close step should be updated to reference agent-audit (#11)
- Provenance/sources chain check deferred to #60

ADR: docs/adr/0018-agent-audit-single-file-invocation.md
ADR: docs/adr/0019-agent-audit-field-inventory-reference.md
Refs: #11
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0147vXtL5sP6vorDdqXGJJU9
2026-07-04 10:06:37 +00:00
69f395f0f6 chore: remove stale chunk/skills references from vision, scripts, and tests
## Why
The repo moved from a chunk-based delivery model with `.agents/skills/`
as the canonical skill source to a plugin model. Several files retained
references to the old model that were either dead code or misleading
framing.

## Impact
- `tests/test-install.sh`: dead `.agents/skills/` test blocks removed;
  suite now tests only what `install.sh` actually deploys
- `scripts/deploy-manifest.sh`: `DEPLOY_SKILLS_SRC` variable and stale
  `sync.sh (Chunk 6)` comment removed
- `tests/test-git-hooks-install.sh`: fixture stub no longer declares
  the removed `DEPLOY_SKILLS_SRC` variable
- `docs/VISION.md`: chunk delivery framing replaced with plugin model
  language throughout; manual test plan date updated
- `tests/test-instructions-and-docs.sh`: stale test plan date flagged
  as pre-refactor so readers know a re-run is needed

Refs: #15

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 20:04:45 +00:00
3b5b1b5199 docs(spec): remove overview.md, rewrite architecture.md for plugin model
## Why
overview.md described the chunk-based delivery model, which is superseded
by the marketplace/plugin pivot. architecture.md was equally stale: it
described .agents/skills/ as the canonical skills source (directory does not
exist), a provider-manifest.sh symlink mechanism (never built), and sync.sh /
init-project.sh as existing scripts (Chunk 6, not yet built).

## Implementation Notes
- overview.md deleted; all cross-references scrubbed from AGENTS.md, CONTEXT.md,
  and three notes/research files
- architecture.md fully rewritten: content deployment model reflects actual
  install.sh behaviour (DEPLOY_FILES / DEPLOY_EXECUTABLES / DEPLOY_DIRS);
  plugin model section added listing all 5 plugins; directory structure section
  removed (was describing a layout that no longer exists)
- "Chunk 6" phase label → "planned"; "chunk workflow" removed from AGENTS.md
  description
- Fixed broken path docs/HUMANS.md → docs/wiki/HUMANS.md in governance layer
  and core/instructions/governance.md

Refs: #15
2026-06-28 19:53:19 +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
d0437bacf9 chore: archive stale notes, delete to-issues/to-prd skills, clean install.sh
- docs/notes/archive/: move ai-ethics-security-principles.md and
  team-self-organisation-sprint-brief.md (superseded/out of scope)
- plugins/bin/skills/: delete to-issues and to-prd (stale mattpocock
  adoptions with no Gitea target; replacement tracked separately)
- scripts/install.sh: remove dead .agents/skills/ deployment block and
  provider skill adapter symlink code; neither path exists in this repo

Closes items 8, 9, 10 of issue #15.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 17:19:13 +00:00
49567e4082 chore(docs): delete docs/issues/ after migrating all 28 issues to Gitea
Issues 0001–0018 migrated as closed; 0019–0028 as open. All assigned to
the Legacy / Triage milestone (ID 5). Closes item 1 of issue #15.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 17:14:30 +00:00
13959f384c chore(docs): move HUMANS.md to wiki and delete from repo tree
## Why
HUMANS.md is practitioner-facing reference material, not a file agents
read from the repo. It belongs in the Gitea wiki where it is browsable
via the wiki UI. Removing it from docs/ keeps the repo tree clean.

## Impact
docs/HUMANS.md is gone from the main repo. The file is accessible at
the Gitea wiki (docs/wiki submodule, commit 5c29e79).

---
Refs: #15
2026-06-28 16:55:29 +00:00
8ccb34278d chore(docs): delete docs/prd/ after migrating all PRDs to Gitea
## Why
All four PRD files (chunk-1, chunk-2-instructions, chunk-3-skills-library,
governance-instruction-layer) have been migrated to Gitea as closed issues
(#16–#19) in the Legacy / Triage milestone. The local directory is
superseded as an artifact store.

## Impact
docs/prd/ is gone. Gitea issues #16–#19 are the canonical record.

---
Refs: #15
2026-06-28 16:50:38 +00:00
5834be3030 docs(adr): add ADR-0017 — Gitea as exclusive issue tracker
Supersedes ADR-0011 (provider-agnostic issue tracker with file-based
default). Gitea MCP is now configured and in active use; the file-based
fallback is removed. All local docs/issues/ files will be migrated to
Gitea as part of the great refactoring (issue #15).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 16:22:31 +00:00
d8307fe4e3 docs(roadmap): mark plugin-author and marketplace-author as shipped
Both skills are now part of the kyberforge plugin. Updated the Plugin
marketplace workstream Phase 1 skill list and the Skills pipeline
housekeeping note (count 4 → 6) to reflect the addition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 11:26:26 +00:00
4d061bd199 feat(kyberforge): add plugin-author and marketplace-author skills
## Why

Plugin and marketplace management had no governed authoring path. Creating or
updating a plugin required knowing the dual-manifest convention, version parity
rules, and directory skeleton by memory — nothing enforced consistency or guided
the process.

`/plugin-author` closes that gap by owning the full plugin scaffold lifecycle:
create, update, rename, and release. `/marketplace-author` handles the
marketplace-facing side: register, deregister, and update plugin entries in
`marketplace.json`.

ADR-0016 codifies the version parity convention (identical `version` in both
`plugin.json` and `.claude-plugin/plugin.json`) that `/plugin-author` now
enforces. The two plugin.json files in this repo are backfilled to comply
(keys also sorted to pass the pretty-format-json hook). CONTEXT.md gains
glossary entries for "plugin scaffold" and "version parity" so future agents
have shared vocabulary for these concepts.

## Implementation Notes

`/plugin-author` ships a `scripts/new-plugin.sh` scaffold script that generates
the directory skeleton and both manifests in one shot; the skill calls the script
rather than generating files ad hoc so the scaffold is reviewable and repeatable.

Version parity is an invariant, not a suggestion — the skill will fail loudly
on create/update if the two versions would diverge.

ADR: docs/adr/0016-plugin-version-parity.md
2026-06-28 10:45:03 +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
d98d0dae18 chore: migrate legacy pre-commit hook to .pre-commit-config.yaml
Replaces shell script (.git/hooks/pre-commit.legacy) with ecosystem-managed pre-commit framework:
- gitleaks/gitleaks: secret scanning
- jumanjihouse/pre-commit-hooks: shellcheck wrapper
- pre-commit/pre-commit-hooks: JSON/YAML validation, end-of-file-fixer, trailing-whitespace
- local hooks: SKILL.md frontmatter validation

Uses pinned versions for reproducibility across environments. Includes auto-fixes from hook runs (formatting, trailing whitespace, JSON beautification).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-27 18:54:37 +00:00
0f725deb61 docs(spec): update overview for agent-author skill
## Why
The convention requires living spec files to be updated in the same
commit as any behaviour change. Adding agent-author to kyberforge
without updating overview.md would leave the spec stale.

## Impact
kyberforge plugin entry now accurately reflects its three current skills
(skill-author, skill-audit, agent-author) and drops the outdated
reference to create-plugin, marketplace-architect, write-skill, and
write-eval which are no longer in the plugin.

---
Refs: #10
ADR: docs/adr/0015-agent-author-dual-provider-scaffold.md
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 15:12:25 +00:00
ba68b09c87 feat(kyberforge): add agent-author skill for Claude Code and Copilot CLI agents
## Why

skill-author explicitly excludes agent definition files ("Do not use to author
agent definition files"). No factory skill existed to create or improve the
.md / .agent.md files that define Claude Code subagents and Copilot CLI agents
in a plugin, project, or user scope. This fills that gap.

## Implementation Notes

Single-root scaffold convention: new-agent.sh <name> <root> derives both
provider file paths from the root by convention — plugin scope (plugin.json
present) writes both files into <root>/agents/; non-plugin scope writes
.claude/agents/<name>.md and .github/agents/<name>.agent.md. This keeps
input minimal while always generating both provider files. See ADR-0015.

Routing is file-level (not directory-level like skill-author): neither file
exists → create flow; at least one exists → improve flow; scaffold is a
file-by-file no-op so retries are safe.

No companion agent-audit skill — inline validation in the close step covers
the simpler agent field contract. agent-audit is tracked as a follow-on.

## Impact

Closes the skill-author gap for agent definitions. Follow-ons tracked in
Gitea #11: agent-audit skill and --copilot-dest override flag for non-standard
Copilot project paths.

---
ADR: docs/adr/0015-agent-author-dual-provider-scaffold.md
Refs: #10
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 15:07:33 +00:00
8dc5241c1c docs: add ADR-0014 and provenance chain glossary entries
Record the decision to add INFO as a third skill-audit finding level
(observational, non-actionable, does not affect pass/fail). Add
Provenance chain and INFO (finding level) to CONTEXT.md glossary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 09:09:43 +00:00
71dfa50107 chore: update wiki submodule pointer to latest commit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:49:56 +00:00
ac0d0ba2b2 chore: add holocron.wiki as submodule at docs/wiki
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:48:18 +00:00
62aa89b566 docs(adr): add ADR-0013 skill-author merge decision
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016z2ZFYHQCex8yZAMVMTZzZ
2026-06-24 18:04:39 +00:00
ac8235ca58 fix(gitleaks): suppress Token routing false positive; sync allowlists; update roadmap
gitleaks false positive (U1, Gitea issue #2):
- 'Token routing: Haiku/Sonnet/Opus' in ai-coding-factory-session.md:90
  triggers generic-api-key on entropy match of "Token". Not a credential.
- ROADMAP.md now documents this pattern and triggers the same rule.
- Both .gitleaks.toml (deployed, read by hook) and scripts/gitleaks.toml
  (source for setup-gitleaks.sh deploys) updated and aligned. Previously
  out of sync — deployed file had docs/research/.* already; source did not.

ROADMAP.md: governance workstream Phase 2 expanded with 7 immediately-
actionable test suite gaps and 5 Chunk 6 CI gaps, all mapped to
CONTROLS.md requirements. Housekeeping updated with audit entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv5iNACZxumtF2k6TsK18q
2026-06-21 01:33:34 +00:00
34c93d9c05 chore(docs): remove .gitkeep placeholders from docs/ard and docs/bug
Per repo convention, .gitkeep files are removed when the directory is
first populated with real content. Both directories are awaiting their
first ARD and Bug Brief respectively (Chunk 3+ work).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv5iNACZxumtF2k6TsK18q
2026-06-21 01:20:01 +00:00
d245807cae chore: remove hello-world demo plugin
No longer needed — kyberforge plugin-create provides a bundled template that
serves as the canonical scaffold reference. Remove hello-world from marketplace
manifests and update docs accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:57:52 +00:00
a3fa54595e docs: update ROADMAP with plugin marketplace workstream and kyberforge
Adds plugin marketplace workstream section documenting Phase 1 completion.
Updates skills pipeline note and pre-0019 cleanup paths to reflect skills
and evals now living in plugins/kyberforge/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:12:10 +00:00
5d46065b26 docs: update spec to reflect kyberforge plugin consolidation
Updates overview.md and architecture.md to document the kyberforge plugin,
the moved skills and evals, the removal of templates/, and the new plugins/
directory in the repo structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:10:43 +00:00
280e98cb71 feat: consolidate marketplace skills into kyberforge plugin
Moves create-plugin, marketplace-architect, write-skill, and write-eval
from canonical .agents/skills/ into plugins/kyberforge/skills/, along
with all bundled sub-files, evals, and the plugin-marketplace-architecture
research doc. Bundles templates/plugin/ into create-plugin/assets/plugin-template/
so the skill is self-contained after install-time caching. Removes
templates/plugin/ and docs/research/plugin-marketplace-architecture.md
from the repo root as they are now exclusively in the plugin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:02:47 +00:00
36ca3744aa feat: add marketplace-architect skill with Bash scripts and evals
Adds a new skill for creating, managing, and adopting plugins across
Claude Code and GitHub Copilot CLI marketplaces. Includes three Bash
scripts (inventory, gen_manifests, validate), three reference docs
(cross-compat, claude-code, copilot-cli), a test harness with 18
passing tests, and an eval.yaml. Also adds the `marketplace` category
to CATEGORIES.md and commits the plugin marketplace architecture
research doc that informed the skill design.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 13:09:16 +00:00
25a6a454b9 feat: add gitleaks secret scanning setup and skill
- scripts/setup-gitleaks.sh — installs gitleaks v8.24.2, seeds
  .gitleaks.toml on first run, writes managed pre-commit hook block;
  re-run replaces block in place without disturbing other hook content
- scripts/gitleaks.toml — base config template extending default ruleset
- .gitleaks.toml — repo config with docs/research/ path allowlist
  (high-entropy terminal captures; v8.24.2 [allowlist] syntax)
- tests/test-setup-gitleaks.sh — 6 behavior tests including stale-block
  replacement and idempotency
- .agents/skills/gitleaks/ — cross-cutting skill covering install,
  update, allowlist tuning, scan modes, and real-finding remediation
- .agents/evals/cross-cutting/gitleaks/eval.yaml — 7 trigger + 3 output
  tests including version-aware allowlist guidance case
- docs/spec/overview.md — updated to reflect new tooling and skill

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 11:29:10 +00:00
76cdbdff7a chore: roadmap housekeeping and orientation rule
- Mark 0017, 0018 phase 1 and phase 2 HITL as complete in roadmap
- Add pre-0019 cleanup block: 0018 phase 3, write-eval refactor, eval updates
- Add orientation question rule to CONTEXT.md — read ROADMAP and open issue handoffs before answering "what's next?" questions
- Note close-out workflow gap in 0018 phase 3 grill questions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 19:30:53 +00:00
5f355d664d chore: mark 0017 and 0018 HITL gates complete via HOTL subagent tests
Behavioral tests for write-eval, write-skill, and write-docs run via
fresh-context subagents (HOTL). All process steps verified correct.
Caveman defects surfaced during testing logged in 0028 for upgrade-skill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 19:19:08 +00:00
737397ebec chore: reformat data classification table in ai-constitution
Whitespace-only change — padded columns for readability. No content change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 20:25:28 +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