Repository navigation
Lore v0.8.0
Post-release correctness and the tests that would have caught it. 0.7.0 shipped the
evidence gates; this is the follow-up the roadmap deferred out of it — the generated-site
defects that predate the release, the hook-layer duplication that let one bug exist in
seven places, and the first tests in this project that check the model's prescribed
workflow rather than a hand-written fixture.
The generated site was never deployable as generated
-
urlwas the framework's own example domain. Every site Lore scaffolded shipped
url: 'https://your-docusaurus-site.example.com'— the origin of every canonical
<link>, everyog:tag and every entry insitemap.xml. Wrong, and wrong in a way
that looks deliberate, so nothing ever flagged it. It is now a{{SITE_URL}}
placeholder the wizard must fill: it asks where the docs will be deployed, and
writeshttp://localhost:3000when the answer is "not yet" — obviously provisional
beats plausibly wrong. -
onBrokenLinkswas'warn'. DoD §6 names the production build as its
authoritative link check and the install guide repeated that promise, while the build
went green with dead links in it. Now'throw'.⚠️ Behaviour change for consumer projects. A site with pre-existing broken links
will now fail its build. That is the point, but it will surface on the first build
after a scaffold refresh rather than at a time of your choosing.
One bug, seven copies
hooks/lib/common.sh. The JSON-extraction ladder, project-root resolution, the
Lore-marker guard and the carve-out were copy-pasted into seven of the nine hooks —
about a third of the hook layer. They now live in one sourced library. Hooks resolve it
through$(dirname "$0"), never${CLAUDE_PLUGIN_ROOT}:hooks.jsoninterpolates
that into the command string, which does not guarantee it reaches the hook's
environment. A test asserts no hook gets this wrong.- The text fallback returned the wrong file. With neither
jqnorpython3
available,json_fieldfell back tosed -n 's/.*"file_path".*/\1/p..*is greedy,
so it returned the last match in the payload — thetool_responseecho rather than
tool_input— on everyWrite, and thehead -n 1after it was decoration. It now
anchors to the parent key and takes the first match. - …and it could not read a boolean.
stop_hook_activeis a JSON boolean, and the
string-only scan returned empty for it. On a machine with no JSON parser, the Stop
hook's loop guard was silently disabled — the one failure mode that can trap a user in
a loop. The fallback now reads unquoted scalars. json_fieldtakes one argument (a key path) instead of three dialect-specific
ones, so a call site can no longer describe the same field three inconsistent ways.
Statements that contradicted their own implementation
- Rule 5 claimed a blocking tier it never had. The methodology listed
Claude/Anthropic/Playwright alongsidelore:*and.claude/paths as forbidden, while
both the hook and the validator deliberately treat the former as warnings — a product
may legitimately document an integration. The rule now states the two tiers it actually
has. doc-validatorforbade and required the same command. One bullet granted Bash "for
npm run build" and forbade "any command that modifies the filesystem". The build
writesbuild/and.docusaurus/. Split into a grant and a constraint, with the build
named as the one explicit carve-out. Its Rule-4 line also still pointed rule citations
atCLAUDE.md, which stopped being where the methodology lives in 0.6.0.remind-census.shstripped every§. The just-in-time reminder — whose entire job
is to point at §0.1–§0.4 — readDoD 0,CLAUDE.md 1,(0.4).brief-to-doccited "§2 step 6" for the readiness gate, which is step 7.detect-project.shcalled the model-written.claude/lore.json"authoritative".
scaffold.sh failed silently
--target X with no --layer printed done (layers:) and exited 0 — a wizard step
that dropped its layer flag reported success over an empty directory. --target with no
value died on shift 2 under set -e with no message at all. Both are now exit 2 with
an actionable message, and an unknown layer is rejected during argument parsing rather
than mid-copy (where it triggered a "already-copied files were kept" warning describing
a copy that never began).
Tests: 173 → 233 assertions
The strategic item, and the reason this release is worth its size. Every defect in the
0.7.0 audit coexisted with a green suite, because each assertion tested a hook against a
fixture written by whoever wrote the hook — so they agreed by construction.
- The skills' own census skeletons are now parsed out of the
SKILL.mdfiles and
checked against what the hooks actually read — that thestatuscell is in the
columnverify-docs.shreads by position, that every Figma manifest source type has a
row, that every zero-case phrase a skill teaches is one the hook recognises. This is
the class of defect that shipped in 0.7.0: a skill prescribing a census its own gate
rejects. - A complete, receipted census per input type — real raw payloads on disk, real
verifiedevidence-log entries — proven to pass both the write-time and Stop gates.
Every prior test proved a gate blocks; none proved they can all be satisfied at once. - A defect corpus mutated from that same green census, one defect at a time, so a
block can only be attributed to the defect introduced. Each mutation is asserted to
have actually landed first — asedthat matches nothing exits 0 and copies the file
through, after which "it blocks" would have been a lie. - CI now lints with
shellcheck -xso the shared library is checked in the context of
each hook that sources it, and asserts the library ships and is not executable.