diagnose read its feedback-loops reference unconditionally, so every
invocation paid for guidance most runs never used; the read is conditional
again and the per-invocation cost drops from 1,278 to 831 words. Its HITL
template moves to assets/ because it is copied out, not read as reference.
prototype's two branch flows move into references/ for the same reason —
only one branch is ever taken.
research could not search the codebase it was asked to research without Grep
and Glob. caveman's description had grown into a paragraph where one sentence
carries the trigger. Four references pointed at things that do not exist: a
to-prd skill, a /setup-matt-pocock-skills command, two cross-skill ../ links
that only resolve in the source tree, and two places calling this project's
Gitea host GitHub.
Addresses #114.
00c1e6b (the ADR-0020 retrofit of diagnose) moved a bullet referencing
scripts/hitl-loop.template.sh out of SKILL.md and into the new
references/feedback-loops.md, and in the move flipped the correct
skill-root-relative path into an incorrect parent-relative one
(../scripts/...) -- despite that commit's own message claiming to fix
"a script path that did not resolve." References in this skill are
written relative to the skill root regardless of which file carries
them, matching the convention used throughout SKILL.md.
Found via an independent post-closure audit of issue #99; validated
clean via skill-audit afterward.
Refs #99
Sets `disable-model-invocation: true`, so the host withholds caveman from
the model-visible skill listing. It stops paying preload tax and can only
be reached by typing /caveman.
The reason is not the 287 characters. caveman's description was almost
entirely a trigger list -- "caveman mode", "talk like caveman", "less
tokens", "be brief" -- and "be brief" is a false-positive magnet: a user
asking for brevity wants short answers, not dropped articles and
`Respond terse like smart caveman`. Removing the skill from the router
deletes the bad trigger. User's call, made explicitly.
Safe to flag because the flag also hard-blocks the Skill tool, so any
inbound route from another skill would break. Re-checked all 39
descriptions and bodies after four waves of retrofit rewrites: every
mention of caveman is documentation, research notes or the lockfile.
Nothing routes to it.
The description is rewritten as human-facing text, since it is no longer
a routing surface -- it now says how to turn the mode on and off rather
than listing phrases for a reader that can no longer see it.
The two remaining SUGGESTIONs are #108: the boundary-clause check fires on
hand-invoked skills, which ADR-0020 contractually exempts. Advisory, and
not to be "fixed" in the skill.
Preload tax 10,002 -> 9,732 chars across 37 model-visible skills.
Refs #99
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWb5RQgCL1ye7cGp2RPb2u
Body 1126 -> 808 words, clearing the FAIL tier, and description 290 ->
220 chars. Phase 1's depth moves to references/feedback-loops.md; the
six-phase spine stays in the body, since a linear procedure is not a
dispatch case.
The description rewrite was not originally in scope, which was an error:
adding a mandatory boundary clause to a 290-char description cannot land
under 400. The dropped capability chain was also inaccurate -- it named
'minimise' as a phase that does not exist while omitting the one phase
the body calls 'This is the skill'.
A clean-context audit found no text lost but three reachability defects,
all fixed: content stranded behind an inverted trigger, Phase 2's
reproduction-rate threshold defined only in a file that path never
loaded, and a script path that did not resolve from the file carrying it.
The two reference files are merged into one, since the split is what
created the first two.
Refs #99
Description 426 -> 286 chars, with a boundary clause added. The body was
already compliant at 467 words and is untouched.
A clean-context audit caught the first pass trading away the LOGIC
branch's routing vocabulary for characters it did not need to save: both
'data model' and 'business logic' had gone, though LOGIC.md defines its
own scope with exactly those words. Restored, so 'does this data model
feel right?' routes here again.
Accepts 286 over the 250 target -- the hard tier is 400, and the
alternative was leaving half the dispatch reachable by one phrase.
Leaves LOGIC.md and UI.md at the skill root; moving them into references/
is tracked as #114.
Refs #99
Description 583 -> 231 chars and body 854 -> 519 words. Deletes the
neuledge-context boundary clause outright: commit 6146120 deleted that
skill and no skill has owned MCP-server installation since. That was the
last dangling routing target in the corpus.
Removes META.md, which file-structure.md:20 forbids at a skill root. Its
when: field duplicated the description and its references: entry pointed
at .agents/skills/context7-mcp/SKILL.md, which does not exist.
Restores two rules a clean-context audit found had lost their force: the
starting-URLs branch in step 3, which the retrofit had reduced to a
condition with no behaviour, and the references/file-format.md pointer at
step 6. The second matters downstream -- validate-provenance.sh parses
sources.md with anchored regexes and check 8 short-circuits silently when
the Status field is absent, so a sources.md written from step 6 alone
broke the provenance chain with no error anywhere.
Rewrites steps 4-5 as serial WebFetch reads. They mandated spawning
subagents that allowed-tools never granted; no tool was added because the
name differs across the three compile targets. Tracked as #116.
Updates the two test pins and the eval case that asserted the dead route.
Refs #99
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
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
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
The deep-module split in plugins/gitea/ (ADR 0011) already covers every
domain the old plugins/bin/skills/gitea/ flat skill handled. Move its
token-access.md into plugins/gitea/references/ first, since it held
empirical scope-test results (Actions/CI, Wiki, Notifications, Packages,
User/Org) not reproduced anywhere in the new plugin, then drop the old
skill and fix a stale cross-reference pointing at it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The gotcha claimed Gitea never auto-closes issues on merge. Confirmed
empirically (issue #63 / PR #64) that a regular merge preserving an
original commit's closing keyword does auto-close — only squash merges
(this skill's default) are unreliable. Also drops search_issues from
allowed-tools since no dispatch route calls it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
## Why
Without this guard, the agent could bypass the skill and call Gitea MCP
tools directly, skipping owner/repo resolution and label-ID normalization.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Skills and evals migrated from .agents/ to plugins/bin/ plugin directory.
Remove .mcp.json, provider-manifest.sh, and skills-lock.json legacy artifacts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>