Releases: emyann/repolore
v0.4.7 — byte-aware audit cost model (first production run)
The audit met the real world, and the real world corrected the cost model
The audit workflow's first production run — a 40-page production wiki, 5 pages audited — validated the design in the wild: due-list selection (parse log.md → never-audited first → tie-break), covers-overlap clustering, the negative-space rule, the invariant sweep, the SHA-vs-line-drift discipline, and the strict journal grammar all executed correctly; 11 stale citations fixed, clean one-commit consent.
It also processed ~15× the modeled tokens (~100K/page, not ~5.1K). Root cause: the §7 cost model was calibrated on this repo's small covered files, but real audit cost is dominated by covered-file bytes, not page count — the production project's pages cover 2,000-line C# files; one covers 23 files.
Corrected model:
session tokens ≈ (Σ covered-file bytes read) / 4 × R(R ≈ 2–4)
where the bytes/4 floor is model-independent (all Claude models share the tokenizer) and the multiplier R is model-dependent (reasoning/thinking output + per-turn cache re-serve) — so a cheaper model that lowers R by skipping the negative-space enumeration buys a cheaper, less-sound audit.
Shipped: a byte-aware planning rule in references/audit.md Phase 0 (budget by covered bytes; lower K for heavy clusters — K is a cost dial, not a fixed 5); a dated §7 field correction in RESEARCH-AUDIT.md; a dated Correction on ADR-010. A cross-model × repo-size consumption benchmark (to decompose the floor from the multiplier) is recorded as a deferred roadmap item.
Docs/procedure only — no tooling change. The journal-clock design is unaffected; only the planning numbers move.
v0.4.6 — the update census (drift the file loop can't see)
Update becomes a convergence guarantee
The live case that motivated this: a repo migrated to repolore (its wiki predates the tool — the very repo repolore was extracted from) whose AGENTS.md was never manifest-tracked. update only heals tracked files, so the contract doc froze at migration: findings inbox, flows rules, the audited verb — none of it ever arrived, and no workflow could even see the gap.
New census class in update.mjs:
wikiRoot/AGENTS.mdpresent-but-untracked (or missing) →ADOPTreport, exit 1. Reporting never adopts by itself.--adopt <path>records the manifest entry against the clean template instantiation's sha — a customized contract then classifies locally-modified on every future run: visible, protected, never silently regenerated over (the same protection edited files always had).- The new-file add pass is now no-clobber: an untracked file that differs from the master is reported for review (
--adopt/--force), never overwritten; identical content is adopted record-only.
references/update.md gains the drift census: the consented contract-merge procedure (preserve scope + custom sections, bring in missing conventions, then --adopt), category-dirs awareness (git drops empty dirs — normal), the CLAUDE.md copy → @AGENTS.md import swap, and the _audit/ findings-mining offer for pre-repolore artifacts.
The toolchain caught its own release
Adding the census dispositions to update.mjs made the set-validated extractor hard-fail the flow page before it was touched (the omitted-branch catch, v0.4.3), and wiki-flow-refresh (v0.4.4) auto-fixed 14 shifted citations across the edit passes, leaving exactly 2 genuine re-verifies for the human. 3 new tests; 63/63 green.
v0.4.5 — the audit workflow + findings-inbox v2 (the Journal-Clock Audit)
The drift class hashes can't see, now owned
Freshness proves the bytes a page cites haven't moved; nothing proved the claims were true. Wrongness behind unchanged bytes — the freshness model's openly-admitted blind spot — is live, not theoretical: this release's design tournament found a fresh-stamped page in repolore's own wiki claiming "five masters" where there were ten, surviving four re-stamps.
The architecture was chosen by a 23-agent adversarial design tournament (docs/RESEARCH-AUDIT.md): 5 biased designs, 3 attack lenses each (token-cost, soundness vs a seeded answer key, ADR contract), 2 independent judges, 1 synthesis. The minimalist prompt-contract design won on every axis; its one critical (hot-page starvation via the last_refreshed clock) is fixed by the defining graft — the audit clock is a journal line (ADR-010).
What shipped — zero new vendored scripts
references/audit.md+/repolore:audit(plugin) + the sixth umbrella routing row (standalone parity): K-page sessions oldest-audited-first; per-claim verdicts (CONFIRMED = entailment, never "consistent with"); the negative-space rule (always/never claims require grep-enumerating the deciding tokens — comments are never evidence); the byte-capped invariant sweep (catches uncited wrongness); hard budgets (evidence ≤3× page bytes; exhaustion never demotes).- The one record:
## date — audited <category/slug> (N claims: …)inlog.md— committed at bless time; due-list and the check workflow's dust line are parsed from it per run, written nowhere (ADR-002's split). Hook, exit codes, CI: byte-for-byte untouched. - Findings-inbox v2: invisible per-item blob-SHA anchors (
<!-- repolore:sha=… captured=… -->),unanchoredabsence findings, recording-commit backfill, four deleting triage exits. Thefindings-checkscript stays deferred behind ADR-009's own revisit gate — ratified explicitly in ADR-010. - Honest cost (measured): ~65–70K tokens for a full 15-page audit (~100K ceiling), ~45–55K/month steady-state at 50 pages, linear scaling.
Dogfooded before shipping
The tournament's dry-runs caught 3/3 seeded falsehoods with zero false positives and found two genuine defects in this repo's wiki (fixed in v0.4.4→v0.4.5 interim). This release ships with the first real audited page: decisions/adr-002-computed-status, 10/10 claims confirmed via the full protocol, one ±10 silent citation repair, journal line minted — and the dust line parses it.
v0.4.4 — diff-scoped flow refresh
The per-file stale signal becomes a per-span worklist
A flow page's claims are per-span, but staleness fired per-file: one line added to a covered file made every citation anchored to it fail wiki-flow-check with "moved — re-verify", forcing a choice between re-verifying everything and blind re-stamping (the trust-eroding "refresh-by-rote").
New vendored script: wiki-flow-refresh.mjs (node + git stdlib, offline — ADR-003/006). It diffs each recorded blob against the working tree and classifies every citation:
| Class | Meaning | On --apply |
|---|---|---|
current |
recorded SHA matches | — |
untouched |
cited span byte-identical | SHA re-recorded |
shifted |
span identical, moved ±N lines | lines + SHA rewritten, region re-rendered |
touched |
the diff intersects the span | left at old SHA — re-verify |
gone |
a match string vanished | left at old SHA — re-research |
unknown |
recorded blob unavailable | left at old SHA — re-verify |
The key design choice: unsafe classes are deliberately not fixed, so after an apply, wiki-flow-check fails on exactly the citations that still need a human — the checker becomes the live worklist. covers: is never touched; page-level blessing stays wiki-stamp's.
Dogfood-proven: a mixed edit to update.mjs (3 inserted lines + 1 real change inside a cited span) auto-fixed 13 of 14 citations and left exactly the touched one failing.
Honesty line: this proves byte-level safety only — semantic drift behind dodged spans remains the audit workflow's territory (ROADMAP).
8 new tests pin the contract (touched-is-never-auto-fixed, insertion-inside-a-span, covers-untouched, idempotency). The refresh procedure, references/flow.md, and the vendored AGENTS.md teach the loop.
v0.4.3 — set-validated tier made real + roadmap doc
The top of the verification ladder, made real
flows v2 begins. The set-validated tier shipped as a seam in v0.4.0 (ADR-007: set-equality is non-vendorable, so it lives in user space) — but nothing demonstrated it. Now repolore dogfoods it:
- Reference extractor —
.repolore/validators/update-classification-seteq.mjs(plain Node stdlib, ~70 lines) rebuildsupdate.mjs's disposition set from code: everyreport.<key>.pushcall site, mapped to the flow step it folds into, emitted as the{steps, edges, branches}JSON the contract specifies. flows/update-classificationreachesset-validated— the page flipsflow_asserts_complete: true, so a new disposition added toupdate.mjsthat nobody writes into the flow is now a hard fail: the omitted-branch catch no lower tier can do.- Copyable worked example —
references/flow.mddocuments the extractor as the starting shape for your own closed-world tool flows (open-world request/async flows honestly stay atbranch-audited). - 5 new tests pin the chain: exact set reconstruction, the new-disposition catch, the live page at the top tier, hard-fail with
asserts_complete, graceful degrade without it.
A readable roadmap
The README's roadmap had grown into a 20-entry wall of prose. It now lives in docs/ROADMAP.md: Now (flows v2, extractor ticked) / Next (v0.5+) / tooling debt / version history, newest first. The README keeps a pointer.
v0.4.2 — flow authoring loop fixed + second dogfood flow page
The flow authoring loop, fixed end-to-end
templates/flow.md, references/flow.md, and the vendored AGENTS.md all promise that wiki-stamp.mjs writes every inline flow *_sha — but the shipped script only stamped covers:. So a freshly authored flow page failed wiki-flow-check on every WRITTEN-BY-wiki-stamp placeholder (anchor_sha / call_anchor_sha / cite_sha). Caught by two independent dogfood runs (repolore-on-repolore and repolore-on-pipao), each forced to hand-fill the SHAs.
Fix: wiki-stamp.mjs gained a stampFlowShas pass that fills each *_sha from its sibling *_path in the same list item, reset at every - boundary so a SHA can never adopt a neighbouring step's path. New tests/wiki-stamp.test.mjs pins own-sibling correctness (no cross-bleed), idempotency, and the orphan-sha case.
Second dogfood flow page
flows/update-classification — how update classifies every tracked file from its (recorded, current, master) SHA triplet into one safe action (never overwriting a local edit by default). 9 steps, 1 verified directional edge + 6 cited branches, tier branch-audited. Proves flow-meta generalises past the near-linear bootstrap flow to a branchy decision tree.
To pick it up in an existing repo: refresh the plugin/skill channel, then run the update workflow (repolore:update) — the vendored wiki-stamp.mjs is pristine-but-outdated, so it regenerates cleanly.
v0.4.1 — sequence diagrams + self-contained flow authoring
flows v1 finished for every harness: a sequence diagram projection (flow_render: sequence — same flow-meta, actors→participants, edges→messages; verification unchanged), and the flow authoring loop + verified-vs-inferred rule folded into the vendored AGENTS.md so a target repo can draft a flow without the plugin-side references/flow.md (it becomes the optional deep reference).
v0.4.0 — flows v1 — generated diagrams, directional verified edges
flows v1 — a new page category (docs/RESEARCH-FLOWS.md, design chosen by an adversarial 5-approach build-off): a flow is line-parseable flow-meta from which wiki-flow-render.mjs generates a GitHub-safe Mermaid diagram + anchored tables; wiki-flow-check.mjs computes the tier (structural → anchored → directional edge-cited → branch-audited → set-validated). The directional graft — a verified edge must cite the call site in the caller's own code and name the callee — closes the edge-existence hole that broke all five prototypes; set-equality is proven non-vendorable and lives in a user-space validators: seam (ADR-007). Folded into wiki-check; dogfood: flows/bootstrap-vendoring.
v0.3.9 — the findings inbox actually works
The findings inbox actually works: wiki-check/-index/the page budget now skip FINDINGS.md (added to lib.mjs SKIP_FILES), so the inbox stops being flagged MALFORMED. ADR-009's v1 "zero scripts" was wrong by one line — caught by the first real migration (pipao's 28-item backlog).
v0.3.8 — update closes the stale-plugin loop
update closes the stale-plugin loop: a repo can only sync to the installed plugin version, so "nothing to do" could mask a stale install. update.mjs now names the installed version, and the workflow probes the marketplace clone on disk (zero network) and offers the consented channel refresh (claude plugin marketplace update / npx skills update), ending with the user-only reload step.