Repository navigation
Releases: schalermthai/redproof
Release list
Redproof plugin 0.3.0 — early access
Redproof plugin releases
Independent of the Redproof npm library. Release versions are immutable.
0.3.0
- Discover writes every answer for a reader new to Redproof, in chat as well as
in files. It opens with the decision, defines Redproof terms once, and keeps
internal status labels out of the prose. - Every discovery request except a time-boxed one produces a Markdown summary
and an HTML report. The chat message summarises the handoff; it no longer
replaces it. - The review page from the bundled helper is the only HTML report. Discover no
longer writes its own HTML page. - Discover ranks recommendations by the uncovered gap. A promise that existing
tests already guard stays visible as existing protection and is offered at most
as a one-time proof. A top recommendation names the case no test exercises.
Finding no uncovered case is a valid result. - design, build, challenge, review-pr, the review UI and the Stop hook are
unchanged from 0.2.0.
Measured on a headless discover eval with Claude Sonnet 5.5 and Claude Opus 5.5
against pinned open-source repositories (ky, Express, Click, chi), with Express
and chi held out of every skill edit. Limitations: about one Sonnet
recommendation in eight still claims a case is untested when a test covers it.
Opus 5.5 was checked only on Express for the ranking change.
Redproof plugin 0.2.0 — early access
Redproof plugin releases
Independent of the Redproof npm library. Release versions are immutable.
0.2.0
- Claude Code Stop hook: runs the project's own
redproof checkwhen the agent
ends a turn and keeps the turn open while a Gate fails. - The hook stays silent in projects without a Redproof config, checks only the
configs that own changed files, and reports a check that could not run. - REFUSE reports remain unverified regardless of the configured CLI exit code.
- A silent, bounded session-start check records pre-existing located Breaches;
unchanged ones warn without blocking unrelated work. New or touched Breaches
still block, and fixed failures lose their exemptions. - The five public skills and the review UI are unchanged from 0.1.0.
Limitations: Codex does not load hooks from this plugin. The hook needs git and
Node.js on the session's PATH; without Node the host reports a hook error and
nothing is checked. The hook was developed against Redproof 0.12.0 and runs the
library installed in the project; it does not install or upgrade one.
Redproof plugin 0.1.0 — early access
Redproof plugin releases
Independent of the Redproof npm library. Release versions are immutable.
0.1.0
Initial early-access package. The GitHub release records publication status.
- Five public skills: discover, design, build, challenge, review-pr.
- Shared routing and review UI remain internal resources.
- Discovery, design and build retain explicit human approval boundaries.
- One canonical skill source, portable/Codex/Claude manifests and standalone UI.
- Git-backed marketplace distribution with versioned snapshots.
Limitations: see the release readiness record before claiming host compatibility.
The instructions were developed against Redproof 0.12.0; that is not a promise
of compatibility with all library, adapter, model or host versions. Installation
does not install or upgrade the Redproof npm library.
Redproof 0.12.0
Redproof turns a quality tool into a Gate: Rules, a Check that runs the real
tool, and Proofs that the Check catches the defect it claims to catch.
New Adapters
@redproof/knip turns unused code into a Gate. Seven Rules cover unused
files, exports, dependencies, development dependencies, undeclared
dependencies, unresolved imports, and duplicate exports. It runs Knip through a
bundled reporter, so the evidence is structured rather than parsed from text.
@redproof/istanbul turns test coverage into a Gate. nyc() collects
natively. istanbul() reads any producer of a full Istanbul coverage map, and
the repository proves that path with real c8. Four Rules cover statements,
branches, functions, and lines, each with a minimum percentage and optional
per-file enforcement. Counting, line semantics, and percentage truncation match
istanbul-lib-coverage exactly.
Both are first releases, so npm install finds them at 0.12.0.
Every Adapter now has a functional core
All six Adapter packages moved their decisions into src/core/ and their
effects into src/shell/ or the package entry point. Public exports did not
change.
Two dependency-cruiser rules enforce the split by path: an Adapter core cannot
import an effectful Node module, and it cannot import anything in its own
package outside src/core/. A third rule forbids one Adapter from importing
another. Each rule carries a proof that plants the violation and requires the
Gate to name it.
stryker() gained an optional second parameter, a mutation-run port. Existing
calls are unchanged. The port let five refusal paths gain end-to-end tests that
were previously unreachable.
New Rules
repository/lockfile-resolves-declared-optional-dependencies requires every
optional dependency a lockfile package declares to resolve to a lockfile entry.
A regenerated lockfile can silently drop the platform binaries for every
platform except the one that regenerated it. Nothing caught that before.
The self-hosted test-health Gate now collects {tests,packages/*/test}, the
same 86 files the test command runs. Thirteen package test files were read by
no Gate.
Fixes
- ESLint directive notices no longer refuse a healthy project.
- An allowed dependency-cruiser boundary disabled by
allowedSeveritynow
REFUSES instead of passing silently. - Stryker adapter reporting, dependency-cruiser evidence handling, and ESLint
evidence handling are each hardened. - Each published tarball is derived from the package it belongs to, so a
per-package table can no longer pair a package with another package's
tarball. - Publishable Adapter source cannot import the test kit.
- npm publishing is resumable, and a new package's first publish explains its
own bootstrap failure.
Verified
858 tests pass, 0 fail, 0 skipped. 6 Gates hold 38 Rules. 60 proofs established,
0 failed. All 8 packages pass clean-consumer verification at one shared version.
Redproof 0.11.0
What's Changed
- Support nested Vitest projects and configured reports by @schalermthai in #44
- Detect flaky tests from retry evidence by @schalermthai in #45
- Refuse instead of throw when the configured Vitest report cannot be set aside or restored by @schalermthai in #48
- Refuse contradictory Jest-compatible reports by @schalermthai in #52
- Reject invalid configured Vitest report paths by @schalermthai in #53
- Add a custom adapter guide and keep each doc to one subject by @schalermthai in #55
- Rename the adapter docs and lead the custom adapter guide with the simpler options by @schalermthai in #56
- Rewrite the self-hosting page as Red proving Redproof by @schalermthai in #57
- Support missing Vitest report directories by @schalermthai in #54
- Integrate PRs #58, #59, #60, #63, #64 and #65 with their review fixes by @schalermthai in #62
- Tidy the tests into deep module tests, one directory per context by @schalermthai in #67
- Fix command lifecycle races by @schalermthai in #66
- Gate built-in adapters and publish their compatibility kit by @schalermthai in #68
- Rewrite the Redproof dogfooding showcase by @schalermthai in #69
Full Changelog: v0.10.0...v0.11.0
v0.10.0
Stryker runs from a package directory
@redproof/stryker takes a cwd option, relative to the Gate root. Stryker runs from that directory, and configFile and Stryker's own relative paths resolve from it. The directory cannot leave the Gate root, lexically or through a symbolic link. A cwd that resolves outside refuses with stryker-cwd-outside-root. Real monorepos need this: a mutation-test target is usually one package, not the repository root.
Accepted-mutant baselines
@redproof/stryker gains a noNewUndetectedMutants Rule, id stryker/no-new-undetected-mutants. It reads a checked-in JSON array, acceptedMutantsFile, resolved from the working directory. Each entry names a mutant by file, full start and end location, mutator, and replacement. This is the same key Stryker uses in stryker-incremental.json, so an entry can be copied from that report.
The Rule matches identities, not counts. A new surviving mutant breaches even when the total survivor count is unchanged. Three cases refuse. A malformed, duplicate, or escaping entry refuses before Stryker runs, with stryker-accepted-mutants-invalid or stryker-accepted-mutants-outside-root. An accepted mutant that the tests now detect refuses with stryker-accepted-mutants-stale. An undetected mutant without a stable identity refuses with stryker-mutant-identity-unavailable, or stryker-mutant-identity-ambiguous when two mutants share one identity.
Select noNewUndetectedMutants in place of mutantsDetected. With both, every accepted mutant still breaches mutantsDetected.
Stryker temp files
The adapter runs Stryker with cleanTempDir: 'always'. A failing initial test run no longer leaves .stryker-tmp inside the Gate copy. Before this release that turned a REFUSE into an unrestored-workspace error during prove.
API
StrykerAdapterOptions.cwd?: string.StrykerRuleOptions.noNewUndetectedMutants?: { acceptedMutantsFile: string }.AcceptedStrykerMutantis exported.- The
Known optionslist in the unknown-rule error now names three options.
v0.9.0
Proof outcomes are states, not flags
A proof outcome now has one of three statuses. completed means the Check returned and the proof was judged. aborted means infrastructure failed before the Check returned, so there is no result. unrestored means the Check returned but the workspace did not return to its baseline, so there is a result and only a restoration error code.
The ok field is gone. proofEstablished(outcome) replaces it and is exported. A completed outcome is a union keyed by expected, and each proof kind has its own evaluation type. A proved RED always names its target. A GREEN proof cannot carry a RED-only reason. A verdict mismatch cannot report the verdict it expected.
Terminal and JSON prove output is unchanged.
Report Rules keep their breaches inside the breached state
RuleReportState puts the breaches inside the breached case as a NonEmptyList<Breach>. A held, unknown, or undecided Rule carries no list. The stored counts are gone; countBreachedRules(model) and countBreaches(model) replace them. RunSummary.breaches is a BreachTotal: exact with a count, or not-countable.
The JSON check report is unchanged.
Breaking API changes
InfrastructureProofOutcomeis nowAbortedProofOutcome | UnrestoredProofOutcome.status: 'error'is'aborted'or'unrestored'.okis removed from every outcome. UseproofEstablished(outcome).ProofEvaluationis the union ofRedProofEvaluation,GreenProofEvaluation, andRefuseProofEvaluation.proved.targetis required on a RED.RuleReport.breachesis removed. Readstate.breacheswhenstate.kind === 'breached'.GateReportModel.breachedRulesandbreachCountare removed. UsecountBreachedRulesandcountBreaches.RunSummary.exactBreachCountis removed. Readbreaches.kind.baselineBlocksProofandbaselineOutcometake aRedProof.
Skill
The redproof skill links the README and the docs by GitHub URL, so the links work after the skill is installed elsewhere.
v0.8.0
Prove reports say why
redproof prove now adds one indented line under each proof. A proved RED names the Rule that breached and what the Check said. A proved REFUSE names the refusal. A proof that did not prove says why: the wrong Rule breached, the Check passed, the verdict did not match, or the target was already breached before the mutation.
✓ no-todo / detects a TODO comment expected=red actual=fail
breached source/no-todo: src/checkout.ts:12: TODO left in source
✗ lint / a var is flagged expected=red actual=fail
target lint/no-var not breached; breached lint/no-let
The first line of each proof is unchanged. The JSON prove report adds reason and, under check, the breaches or the refusal in the shape the check report already uses. The report stays version 1, and the schema declares the new field.
API
CompletedProofOutcomegains a requiredreason: ProofEvaluationfield. Code that builds outcomes by hand must set it.okis unchanged.ProofEvaluationis exported. A proved RED carries itstarget. A new kind,target-already-breached, marks a RED blocked by its baseline.
Self-hosting
The composition dependency Rule is now an allowlist: composition may import only composition, domain, and inspect.
v0.7.0
Behaviour changes
A wrong reporter option now prints one line and exits with 2, the same as every other usage mistake. Before, it printed a stack trace and exited with 1. This covers an unknown reporter name, a missing --reporter or --outputFile value, two reporters on stdout, and a prove reporter that prove does not support.
An unknown command is now reported before the config search. redproof lint says "Unknown command: lint" whether or not a config file exists.
API
renderRunandSourceExcerptsrender the terminal report from values.formatRunstill reads the source excerpts for you.ReporterArgumentErroris thrown byparseReporterArgs, so a caller can catch a bad reporter option by type.- The
redproof/commandsubpath is unchanged. Its file moved todist/command/index.js.
Structure
The package is now organised into bounded contexts, each with a pure core and an effectful shell: project, proof, workspace, run, command, inspect, reporter, cli, and composition. Every context exposes two surfaces, core/index.ts for other cores and index.ts for everyone else. The self-hosted architecture Gate guards both the purity of every core directory and the use of those surfaces, with 22 Rules and 27 proofs.
v0.6.0
Behaviour change
The default execution mode is now copies, not in-place.
Each Gate now works on its own copy, outside your project. A proof cannot touch
your real source tree, and Gates can run at the same time. To keep the old
behaviour, set it in redproof.config.ts:
export default defineConfig({
execution: { mode: 'in-place' },
});Fixes
- Gate copies are created outside the project. A copy inside the project let
tools such as ESLint find the project's own config by searching parent
directories, so arefuseproof could report a false PASS. - The dependency-cruiser adapter now reads the JSON string that
dependency-cruiser 18 returns. It previously refused every check. - The Stryker adapter no longer passes
NODE_TEST_CONTEXTto the test suite it
runs. An inherited value made anode --testchild exit 0 on failure, so every
mutant looked like it survived.
Packaging
- Every package now ships a README, so the npm page is no longer blank.
redproofnow ships the JSON reporter schemas underschema/.- Every package declares a top-level
typesfield.