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
6.9 KiB
Vale audit prefilter expands into a plugin-content harness, scoped to prose-pattern rules only
Issue #84 wired Vale as a deterministic prefilter for skill-audit/agent-audit, scoped to
exactly four pattern-matchable checks (imperative description opener, vague capability wording,
generic reference-pointer padding, Copilot's dead Use proactively phrasing), documented only in
CONTEXT.md's "Vale audit prefilter" section — never its own ADR — and explicitly excluding body
discipline, near-miss exclusion strength, and control calibration as non-goals. This ADR records a
deferred PR #85 review item to broaden that coverage, retroactively captures #84's own rationale
(since it was never recorded as a decision in its own right), and layers the expansion on top
without reversing or weakening the original four rules.
File scope stays the same. SKILL.md plus agent files (plugins/*/agents/*.md,
plugins/*/agents/*.agent.md) only — matching the existing prefilter's globs. Skill-level
README.md files and plugin.json manifests are not added: README.md files are navigational, not
spec-governed content, and plugin.json is JSON, not prose Vale can meaningfully lint.
Rule categories are prose-pattern-matchable only. Structural, schema, and security concerns
stay out of this Vale-based harness because this repo already has dedicated tools for them:
skill-frontmatter (required frontmatter fields), validate-plugins/validate-marketplace
(claude plugin validate --strict, schema), and gitleaks/detect-private-key (secrets).
Duplicating those concerns as Vale rules would fight tools that already own them better.
Governance docs are excluded as a rule source. docs/research/governance_principles/CONTROLS.md
and governance.md were investigated and found to contribute nothing minable: CONTROLS.md is
org/CI-infrastructure controls (secret scanning, dependency/license scanning, agent permission
scoping, audit logging, human approval gates, periodic reviews) — none of it is a prose pattern
expressible as a Vale rule against SKILL.md/agent-file text, and what it does cover is either
already handled elsewhere (gitleaks) or genuinely out of scope for a plugin-content prose harness
(dependency/license scanning is a code-dependency concern, not skill authoring).
Spec-derived custom rules stay mostly as-is. Re-reading agentskills.io's
optimizing-descriptions.md and skill-authoring.md, plus claude-code-plugins/agent-definition.md
and github-copilot-plugins/agent-definition.md, found that the existing four Kyberforge rules
already cover the pattern-matchable surface those specs describe. The remaining spec guidance —
calibrating control vs. giving freedom, avoiding menus of options, coherent skill scope, moderate
detail level — is semantic judgment, already skill-audit's job via LLM review, not new lintable
rules. One confirmation surfaced: Claude Code's Use proactively phrasing is meaningful for .md
agent files (it triggers auto-invocation), unlike Copilot's .agent.md files where it's dead
phrasing — so KyberforgeCopilot/ProactivePhrase's existing .agent.md-only scope is correct and
must not be extended to .md files.
write-good/alex are trialed, not adopted wholesale. These built-in/third-party Vale
packages are tuned for general blog-style prose (passive voice, weasel words, wordy phrases) and
are expected to be noisy against this repo's terse, imperative instruction-file corpus. Only
individual rules proven low-noise against the existing corpus get cherry-picked into
styles/Kyberforge; the packages are never referenced wholesale in BasedOnStyles.
A new non-Vale check closes a real gap. skill-authoring.md states SKILL.md should stay
under 500 lines / 5,000 tokens — currently unenforced anywhere in this repo. This is a whole-file
length ceiling, not a text pattern, so it isn't a Vale rule — it becomes a new deterministic script
and pre-commit hook, sibling to the existing skill-frontmatter hook.
Rules land directly in styles/Kyberforge, enforcing immediately. No trial/report-only tier
is introduced (see Considered Options). The implementation pass finalizes the cherry-picked
write-good/alex rules and any new spec-derived rule wording, runs the full set against the
existing SKILL.md/agent-file corpus, fixes any resulting violations across that corpus, and lands
the rule changes and the corpus fixes as one atomic commit — the same enforcement model as the
original four rules, never a partial or opt-in state.
Considered options
Phased rollout via a separate trial style + config (rejected). A styles/KyberforgeTrial/
directory plus a parallel .vale.trial.ini (mirroring the root config's globs but with
BasedOnStyles = Kyberforge, KyberforgeTrial) would let new rules be swept report-only via
lint-runner/vale-run before promotion into the enforcing styles/Kyberforge + root
.vale.ini. This was considered because BasedOnStyles = Kyberforge activates every rule file
under that directory automatically — there's no partial/opt-in application within a style, so a
rule dropped straight into styles/Kyberforge goes live in the blocking pre-commit hook
immediately. Rejected in favor of finalizing rules directly and fixing violations via subagent
before committing: simpler, no new trial-config machinery to build or maintain — at the cost of no
standing report-only tier for future candidate rules.
Consequences
styles/Kyberforge/gained two new rule files, cherry-picked fromwrite-good/alexas low-noise against this repo's corpus:VagueQualifier.ymlandSentenceOpenerThereIs.yml.- A new pre-commit hook,
skill-size-check(scripts/skill-size-check.sh), enforces the 500-line/5,000-tokenSKILL.mdceiling, sibling toskill-frontmatter. styles/KyberforgeTrial/and.vale.trial.iniwere deliberately not created — noted here so a future reader doesn't wonder if a trial tier was forgotten.- The styles-portability question — whether
styles/and.vale.inishould move intoplugins/lint/so the prefilter also works for repos that installkyberforge@holocronas an external plugin, rather than living at this repo's root — was deliberately deferred, not fixed, in this pass. This repo-root placement remains intentional: this ADR's "File scope stays the same" framing is specific to Kyberforge's own authoring conventions in this repo, not a genericlint-plugin feature. Portability is a known limitation, tracked for a separate future session, not silently forgotten.
What this ADR's implementation pass did: synced and trialed write-good/alex against the
existing SKILL.md/agent-file corpus, cherry-picked the two low-noise rules above into
styles/Kyberforge, wrote scripts/skill-size-check.sh and its pre-commit hook, fixed the
resulting corpus violations, and landed the rule changes and corpus fixes as one atomic commit —
matching the enforcement model described above (no partial or opt-in state).