v0.2.0
Correctness and context. Twelve defects are fixed — including one that made a correct harness fail the skill's own delivery gate — and the context a session pays for before its first prompt is cut in half. Every product mechanic asserted by the skill was re-verified against live documentation, because the previous release shipped one that was wrong.
Breaking
audit_harness.py --json:inventory.claude_mdis now an array, not an object. A project CLAUDE.md can live at./CLAUDE.mdor./.claude/CLAUDE.md, and./CLAUDE.local.mdloads alongside either, so a single slot could not represent reality. If you readinventory.claude_md.lines, readinventory.claude_md[0].lines— or iterate, which is the point of the change. An absent CLAUDE.md is now[]rather thannull.
Fixed
@importdetection no longer rejects correct harnesses.maintainer: ops@acme.comwas read as an import ofacme.comandreact@18.2.0as an import of18.2.0, each raising an error and a non-zero exit — so a CLAUDE.md that named a maintainer or pinned a version could never satisfyvalidate_harness.py. Import parsing now skips fenced blocks and code spans, requires a path boundary, and supports the documented extensionless@READMEform. Relative targets resolve against the importing file rather than the repo root, and@~/…imports are recognized as external rather than reported missing.- A project using
.claude/CLAUDE.mdis no longer reported as having no harness. Both scripts hardcoded./CLAUDE.md, which fed the mode suggestion and classified an established harness asnew. - Rules and agents are discovered recursively. A nested
.claude/rules/frontend/style.mdwithoutpaths:loads at launch but was invisible to the linter, the inventory, and the drift check. - Spec drift is detected in both directions. The audit only reported components on disk that the spec omitted; it now also reports spec rows whose
statusclaims a file that isn't there, andin_spec_not_on_diskis present in--jsonwhether or not a spec exists. - The workflow syntax check accepts top-level
return, which the workflow runtime supports and which the skill's own examples use — it was reported as a syntax error. SessionEnd's 1.5-second timeout is documented correctly as a budget shared across allSessionEndhooks, not a per-hook default; two reference files also disagreed about which event had the shortest timeout.- Wrap-up now validates after the edits it is meant to check, rather than before them.
- Dead-link checking covers a skill's pointers written as prose, markdown links, or
${CLAUDE_SKILL_DIR}invocations — previously only backtick-wrapped forms in one file, one pointer out of thirty-two. - Three dangling cross-references and an unclosed code fence.
Added
- An always-loaded budget report, printed on every
validate_harness.pyrun: CLAUDE.md plus expanded@importsplus every rule withoutpaths:, with an explicit list of the surfaces it cannot count (user scope, ancestor directories, auto memory, managed policy). - Three lint warnings, each with a fixture proving it stays quiet on correct input: generic advice anchored to whole sentences, a deny rule that swallows an allow rule, and a catch-all
paths:glob. references/re-entry.md— the extend/improve/sync modes and the full drift-resolution procedure, loaded only when re-entering an existing harness.- Auto memory and the personal-vs-team scope axis. The routing framework now asks who needs a fact and who writes it, with
CLAUDE.local.mdas the destination for per-developer facts; auto memory enters the budget model but is explicitly never a routing destination, being nondeterministic and disableable. - Mechanics whose absence leaves a generated harness silently inert: what workspace trust gates beyond allow rules, why
Edit(.claude/**)cannot pre-approve a protected-path write, thatdefaultMode: "auto"is ignored in project settings, thatWrite(path)permission rules are never consulted, and that enabling a subagent'smemoryre-enablesRead/Write/Edit. - A compaction survival matrix — root CLAUDE.md and unscoped rules are re-injected, subdirectory CLAUDE.md and
paths:-scoped rules are not — which qualifies the monorepo guidance in the same file. declinedandretiredspec statuses, so a harness records what was deliberately not built.- This repository now carries its own
.claude/harness-spec.md.
Changed
- The always-loaded surface is 4,833 → 2,411 words.
SKILL.mdinstructed an unconditional load ofinterview.md, so the split between them bought nothing; Phase 0 now branches by mode and the sync path never opens the interview file. - Principles are stated once rather than elaborated, and examples no longer carry domain narrative that pulled generated components toward the example's subject matter.
Known limitations
- Headless authentication propagated correctly during this release's verification, but
run_e2e.py's permission handling remains a documented best guess rather than a broad confirmation. - The interview still cannot be end-to-end tested;
AskUserQuestiondoes not exist in headless or subagent contexts. - A generated harness does not yet mention that workflow agents run in
acceptEditsmode and inherit the session allowlist, though the reference prose covers it.