Releases: anlor1002-alt/regressionledger
Release list
v0.10.2 — close live fuzz-review findings (scoped classification, hits guard, md injection)
v0.10.2 — closing the live fuzz-review findings
A 46-agent fuzz/review pass ran against a 0.9.0 checkout, so most of its HIGH findings (failCount mixing, positional eviction, mtime locks, recordHit-before-deny, settings clobber, unpinned CI) were already fixed in 0.10.0/0.10.1 — re-confirmed fixed, not re-patched. Four findings genuinely reproduced on HEAD and are closed here, each with an adversarial test:
- Cross-toolchain false FAIL. A passing pytest run whose log contained a jest-style
FAILbanner — orRetrying 1 failed attemptprose — was misclassified as a failure (and would have wrongly blocked the correct fix on a later session). Classification is now scoped to the runner's own patterns via the command. loadHitscrash. A valid-JSON-but-not-arrayhits.json(e.g.{}) crashedrl stats/rl report; now coerced to[].- Markdown report injection.
rl reportmarkdown embedded ledger text verbatim; headings/code-fences from a crafted preview are now neutralized (the HTML renderer already escaped).
100 tests - benchmark green - zero dependencies. The honest pattern holds: ship fast, review adversarially, and let the changelog keep its own ledger.
v0.10.1 — security review fixes
v0.10.1 — security review
An independent security pass (separate from the correctness gate). HIGH-1 (prompt-injection neutralization) was already mitigated in 0.10.0; the rest land here.
- HIGH-2 —
rl initcan no longer clobbersettings.json. An existing-but-unparseable file was previously swallowed and overwritten, destroying the user's hooks/permissions/env.initnow parses first, backs the file up tosettings.json.broken-<ts>.bak, and aborts with a clear message rather than writing. - MED-3 — ReDoS fixed. The Java/C# enclosing-symbol regex backtracked super-linearly on long whitespace (and ran on every edit). Rewritten bounded; 5000 spaces resolve in <1ms.
- MED-4 — CI supply chain pinned. The demo workflow (
contents: write) no longer installsttyd/vhsatlatest. - LOW-5 —
recordHitis throw-proof. It runs right before a deny; a throw would fail-open and silently drop the block. Its I/O is now fully swallowed.
96 tests (5 new security tests) - zero dependencies.
v0.10.0 — the gate review: acquittal, raw-only gating, PID locks
v0.10.0 — the gate review
The same community reviewer who found v0.9's literal-collapse flaw came back in full gate mode: every accusation with a line number and a repro — and two accusations retracted when their own repros failed to break the code. That standard is now law in CONTRIBUTING.md ("Release gate — four adversarial questions").
Fixed
- P0 — proven-good code gets total silence. Code with a recorded PASS was still receiving "expect the same failure" notes from old sibling-variant failures. An acquittal check now silences every channel (collapsed AND structural) for code that has passed. The happy path is sacred.
- P1 —
minFailurescounts only THIS exact code. Previously5000failing once +7000failing once could arm a "failed 2 times" hard block against5000. The gate now counts raw-channel failures exclusively. - P1 — locks can't be stolen from live holders. mtime-staleness is gone: locks record
{pid, token}, stealing requires a dead holder, release is token-checked (can never unlink someone else's lock), and waiters wait 15s before the documented last resort. - P3 — eviction by value. Cap pressure now evicts pass/retired/pending first; load-bearing failures survive churn.
Security
- P2 — imported ledger text is neutralized and labeled.
rl importis a cross-machine channel; imported signatures/previews are now structurally neutralized (control chars stripped, newline structure flattened) at import and at render, and tagged[imported verdict]in briefings and block messages. Honest framing: structural neutralization, not content filtering — treat shared ledgers like dependencies.
91 tests (5 new adversarial gate tests, one per finding) - zero dependencies.
v0.9.0 — the right to retry (community stress-test fix)
v0.9.0 — the right to retry
A community member cloned this repo, read all ~2,400 lines, reproduced the benchmark, and then broke the design with two lines of experiment:
Fix changing timeout 5000 -> 30000: same fingerprint? true
Fix changing "admin" -> "superuser": same fingerprint? true
Because literals collapsed to STR/NUM, a legitimate parameter retry shared a fingerprint with the failed attempt — so the tool hard-blocked the correct fix with "change strategy" (when changing the constant WAS the strategy). Worse: the benchmark's own disguise list defined literal changes as matches, making its "0 false blocks" structurally circular. The biggest false-positive class lived outside the measurement.
They proposed the fix. It's shipped, exactly as designed:
Changed
- Hard blocks now require a raw-channel match — same code, constants included (only whitespace/comments stripped). Changing a constant or string is never denied.
- Collapsed-only matches (same shape, different values) get an advisory note and one hearing. A variant that fails earns its own record — its verbatim repeat then blocks.
- Retire-on-pass is raw-keyed:
timeout: 30000passing does not acquittimeout: 5000's failure. - Batch attribution disclosed: when one run fails N edits, block messages admit "attribution is approximate" with an
rl unblockpointer. - Benchmark rewritten in three honest categories: 60/60 cosmetic re-applies hard-matched - 40/40 literal variants routed to note-not-block (0 wrongly blocked) - 0/190 distinct fixes matched.
86 tests - zero dependencies - this changelog keeps its own ledger honest.
v0.8.1 — hardening: 7 review findings fixed, 9 regression tests
v0.8.1 — the review release
Before launch week, an independent adversarial review went over everything shipped in v0.6-v0.8. It found 7 major bugs — every one verified by execution before being fixed. This release fixes all of them, plus the minor findings, with 9 new regression tests (84 total).
Highlights
- Thrash escalation actually fires now — one old large wall no longer silences every new wall forever.
rl importis hardened — strict validation, field truncation, ledger cap enforcement. A hostile export can no longer kill the guardrail, grow a 44 MB ledger, or inject unbounded text into your agent's context.- Type-unsafe ledger reads fixed — a single malformed entry could previously disable blocking AND briefing for a file, silently (fail-open hid it).
- Classifier regressions fixed —
error:prose in passing runs,mvn dependency:tree, "200 OK", "0 passed" all misclassified; explicit toolchain pass evidence now outranks generic fail substrings. rspec/phpunit restored,node --testadded. - Structural channel: 15-token floor (no more guard-clause noise), 3000-token cap (no more multi-second Writes).
Honest accounting: 5 of the 7 majors were introduced by features shipped earlier today. Shipping fast creates bugs; reviewing adversarially catches them. Both halves matter — this project tracks failed fixes for a living, so the changelog keeps its own ledger honest.
84 tests - benchmark 120/120 caught, 0/190 false blocks - zero dependencies.
v0.8.0 — Sixth Sense: session briefing, thrash escalation, herd immunity
v0.8.0 — Sixth Sense
Three capabilities that, as far as we can tell, no other agent tool ships.
🧠 Session briefing
A SessionStart hook injects a compact "what already failed here" brief every time a session starts — including right after context compaction wipes the agent's memory (source=compact). The agent wakes up already knowing its dead ends, per file, with error signatures and walls. Failures get blocked before they're re-conceived, not just before they're re-applied. Silent when the ledger is empty — zero context waste.
🌀 Thrash escalation
Blocking identical fixes catches one doom loop. The other one: different fixes all dying on the same error. When 3+ distinct approaches hit one wall, the post-test hook escalates:
"3 distinct approaches have now failed with the same error. The patches differ; the error doesn't. The DIAGNOSIS is wrong, not the patches. STOP editing. State 2-3 root-cause hypotheses, verify one, then fix."
🤝 Herd immunity
rl export / rl import — settled verdicts travel between machines and teammates. Your agent inherits the dead ends my agent already paid for. Imported failures block locally and stay attributed (importedFrom); pendings and duplicates never travel.
75 tests - benchmark 120/120 caught, 0/190 false blocks - zero dependencies - plugin + rl init both wire the new SessionStart hook automatically.
v0.7.0 — signature registry, rl why, doctor --explain
v0.7.0 — max settings
The load-bearing heuristic gets armor, and the ledger learns to talk.
Added
- Test-runner signature registry — the pass/fail parser is now a per-toolchain registry covering jest/vitest, mocha/ava, pytest, go, cargo, tsc, eslint/ruff/mypy, gradle/maven, dotnet, playwright/cypress, and generic builds — backed by 18 real-output fixtures and a table-driven test. Adding YOUR runner is now the canonical first PR: one registry entry + one fixture + one table row.
rl doctor --explain "<output>"— paste any test output, see exactly how it classifies (pass / fail / "ambiguous, left pending") and which pattern decided. No more guessing why the ledger marked something failed.rl why <file>— the roadmapped natural-language query, shipped: blocking failures with reasons, walls ("2 different attempts died on the same error — question the diagnosis"), retirements with receipts, passes.
Fixed
- Cargo/gradle failures caught by a generic counter now get their real error signature (
panicked at...,BUILD FAILED) instead of a placeholder.
68 tests - benchmark still 120/120 caught, 0/190 false blocks - zero dependencies.
v0.6.0 — paraphrase notes (dual-channel fingerprinting)
v0.6.0 — the shape doesn't lie
Added
- Paraphrase notes (dual-channel fingerprinting). Renaming every variable used to be a clean escape from the matcher. Now a second, structure-only fingerprint (identifiers erased, shape kept) runs whenever the semantic channel finds no match. If the edit is >=95% structurally identical to a recorded failure — the signature of the same fix, renamed — the hook never blocks, but injects a note: "this may be the same fix, renamed; if the approach is the same, change strategy."
Zero added false-block risk by construction: the structural channel can only annotate, never deny. Born in a Moltbook thread — credit to @evil_robot_jas (the dual-hash insight: "the structure doesn't lie the way surface content can") and @NexaAgent (the miss-rate question it answers).
rl statsnow reports paraphrase-note counts alongside blocks and warns.
49 tests - benchmark still 120/120 caught, 0/190 false blocks - zero dependencies.
v0.5.0 — reproducible benchmark, stats card, LLM Quickstart
v0.5.0 — prove it, then share it
New
- Reproducible benchmark (
npm run bench) — a deterministic 310-case corpus: 120/120 cosmetically-disguised repeat fixes caught (100%), 0/190 false blocks on distinct fixes (0%) at the default threshold. Check the claim yourself in seconds. rl stats --card— a clean, screenshot-able terminal card of your blocked-fix counts.- LLM Quickstart README section — coding agents reading the README can now self-install the tool for their humans (and are told that being blocked is intended behavior, not an error).
47 tests - CI green on 9 environments - zero dependencies.
v0.4.0 — rl unblock + retirement receipts
v0.4.0 — the human-priced override
Two changes that came straight out of community critique on Moltbook, shipped same-day.
Added
rl unblock <file> [hash-prefix]— when the context genuinely changed (postgres -> aurora, new dependency major), a human can retire the recorded failures so they stop blocking. Deliberately explicit and human-priced: an agent asserting "it's different this time" is exactly the confidence loop this tool exists to break. (Raised by @evil_robot_jas.)
Changed
- Retirement keeps a receipt. Superseded failures are no longer deleted — they become
retiredentries carryingretiredBy(passorhuman), a timestamp, and asupersededBylink to the passing attempt. "Tried shape X, observed Y, later superseded by Z" stays auditable inrl show(shown as ∅ retired). (Design point from @jarvis-snipara: outcome-linked invalidation needs its own provenance.)
47 tests - CI green on Node 18/20/22 x Linux/macOS/Windows - zero dependencies.