Changelog

Every released change, generated from CHANGELOG.md. Any change to a public surface (the commands, exit codes or artifact schemas) is a major version.

1.0.0

first major release, proprietary licence, compiled binaries only

  • The licence is now proprietary (SEE LICENSE IN LICENSE), copyright Arkash Jain.
  • repository, homepage and bugs are removed from package.json.
  • Retired commands now exit 2 and name the replacement, for example "qa run loop was retired in 1.0.0; use qa run <repo> --once".
  • The Rust kernel now requires counts.writersWithNoReaderSurface in the coherence counts.
  • qa setup [--dry-run] [--yes] [--json] [--no-browser] [--no-skills] [--mcp] (a public command: MINOR) gets a fresh install ready.
  • qa show graph <repo> [--format mermaid|dot|json] (a public command: MINOR) renders the kernel's .verify/autonomous/{nodes,edges}.jsonl.

30 more changes in this release

0.9.0

three declaration surfaces, honest denominators

  • a11y.label-association-broken (P3, atlas L9.88): a visible <label for=x> whose HTMLLabelElement.control resolves to a hidden control while a visible labelable control with zero labels carries the same id.
  • a11y.aria-attr-not-allowed (P3, atlas L9.94, a new class): an ARIA state attribute the element's role does not support, such as aria-selected on a button.
  • --capture photographs every measured cell (role × route × width) into .verify/capture/index.html through the sweep's own browser, with --capture-full and --capture-dir.
  • <repo>/verify.read-only.json, a committed declaration of literal POST paths the repository declares read-only, each with a written justification and no wildcard, query string or relative path accepted.
  • <repo>/verify.identity-adapter.mjs, a committed host-owned adapter: one default-exported function, handed the persona's authenticated fetch, returning the app's current-user response in the identity shape.
  • A private, origin-scoped sessionStorage sidecar for real-lane personas, written at 0600 in the lease and restored before the app's own scripts run.

59 more changes in this release

0.8.0

typed causal observations, single operating skill

  • An optional, bounded coherence causal sample: an app-owned driver reads before a write, computes the expected post-state, binds the write to an isolated fixture and supplies authoritative readbacks, typed as schemaVersion 4 with schemaVersion 1–3 archives still readable.
  • CLI-launched fixer execution and automatic source commit/revert are removed; retired fixer flags and saved fixer configurations fail closed.
  • The operating boundary is corrected: qa measures, plans and reports; the host agent inspects source, fixes root causes and reruns the CLI.
  • Bounded verification and sustained QA are consolidated into the root SKILL.md; installation registers only frontend-verify.
  • The verify kernel shares one snapshot-bound reduction between the agent result and graph artifacts, and the Rust fixture is regenerated by the real Node producer, closing the gap tracked by.
  • A reproducible discrete-math audit ships an independent bounded subset oracle, an 18-section ledger, 30 positive checks plus one expected negative control and six figures, covering finite mathematics only.

3 more changes in this release

0.7.0

integration, retired command names

  • BREAKING: the command surface is seven top-level verbs — init, verify, measure, show, run, fix, dev — and all 25 pre-consolidation names are retired rather than deprecated, each exiting 2 naming its replacement.
  • A held-out, judge-labelled coherence corpus plants four ground-truth shapes in every generated fixture and scores precision and recall of 1.0, kept out of overall/gates because both candidate kinds stay P3 under the runtime-confirmation policy whatever their static precision.
  • One semantic graph behind the coherence IR: inventory.json's coherence block is IR v4 with a semantic graph v2 root (19 node kinds, 22 relations, storage IDs recomputed from JCS material), and every compatibility array is a byte-identical checked projection, so array and graph cannot disagree.
  • A single-flight persona coordinator gives one launch per persona per run, with the lease borrowed by child runners over an inherited descriptor (--auth-lease-fd, never argv or env values).
  • Runtime false-positive adjudication: qa fix fp add for a finding with no source line, scoped to the same repository, rule, route, persona, selector and measurement identity, and refused for an invalid or unmeasured sweep.
  • The ratchet is keyed per measurement scope: ratchet.json is schema_version: 2 with one best/last per scope id, so a wider or narrower runtime scope opens its own baseline instead of overwriting another's.

4 more changes in this release

0.6.1

coherence, post-merge reconciliation

  • The obligation universe carries an invariant axis and is sparse by declared contract, O ⊆ M × S × P × C × I, with every excluded tuple counted under a named reason so possible − Σexcluded == discovered is checkable.
  • Per-obligation runtime evidence: coherence-observed.json records one observation per (persona, context) with the invariant it proves, plan.coverage gains disagreed, and the monotone gate additionally requires agreed + disagreed == compared.
  • Schema-v2 canonical entity aliases, entity families with a per-family report block, causes (confirmed by runtime disagreement, not-reproduced by agreement, otherwise unmeasured with the reason), and coherence-risk.json scheduling which family to measure again first.
  • The Rust kernel could silently not run under a report that still said PASS, through three stacking paths — missing cargo graded a warn even under --strict, the marathon dropped --autonomous with no named skip, and --plan fell back to declaration order — now a hard fail, a recorded kernel decision, and an exit 2.
  • Atlas coverage now requires a current producer, not only a historical kind mapping: recomputed to 72 of 96 classes and 74 of 99 mode obligations for v1, 74 of 103 and 76 of 106 for v2, with static reach 21 of 74.
  • Evidence could drift between the gate and the Rust reduction, so qa verify now snapshots normalized roles and the exact validated verify.crud.json bytes and passes only those paths to both Rust products.

2 more changes in this release

0.6.0

coherence

  • qa coherence <repo> builds additive inventory.coherence evidence over the static IR and records writer/observer/fresh-context comparisons with verified cleanup; invalidation coverage is three-valued — covered, not covered, unresolved — so an unresolvable key is never folded into "missing".
  • Obligation-universe planning in the Rust kernel enumerates M×S×P×C and runs weighted maximum-coverage planning over it, exposed as the coherenceObligations dimension of agent-result.json, with static candidates grouped by structural root cause so one missing invalidation across five surfaces is one group.
  • Executable plan join and bounded parallel flows: qa coherence --plan <agent-result.json> joins the kernel's selected obligations to declared flows before running them, and --flow-workers N (default 1, clamped 1–4) bounds parallelism.
  • qa marathon and qa triage consume this evidence every run, runtime coherence being a named skip carrying the enabling steps unless the repo declares a schema-v2 crosscheck flow and both provenance modules exist.
  • One fail-closed mutation policy shared by every write path requires explicit --mutate, a committed literal production: false flow, a safe base, an allowed evidence lane, a positive budget, an isolated fixture namespace, and cleanup capability reserved separately from the write budget.
  • Static source snapshot and content-identity cache: qa inventory and qa classify read the repo once and cache their reports on that snapshot's content digest, not file mtimes; the hit is visible in the artifact and --no-cache forces a fresh scan.

4 more changes in this release

0.5.0

lanes

  • qa marathon <repo> --status reports phase, running/stopped/finished, minutes left, lane, writes, depth rung and last command, exiting 0 running or finished, 1 stopped mid-run, 2 nothing has run.
  • SKILL.md split: the contract, command table, roles, precision and marathon mode stay (5.6k words, down from 11.1k); the long-form sections moved verbatim to references/operating-manual.md.
0.4.0

one command, no flags

  • The graph is a finite, validated ten-kind/nine-relation schema with no other kind, misc relation or free-form attrs escape hatch, so a Tailwind class string does not merely get discouraged, it does not compile; on one real run this replaced 28 non-conforming node kinds, one of them 69.5% of the graph.
  • qa marathon enables its deep phases from what the repo declares, not from flags — writes when verify.crud.json declares every flow "production": false and the base is loopback, real identity when verify.auth-launcher.mjs exists and every persona declares expect — so --crud and --shadow-trace are removed and qa marathon /abs/repo is the whole invocation.
  • An unknown flag is a usage error (exit 2), not a silently discarded argument: qa verify /repo --widht 390 previously exited 0 PASS at a width nobody asked for, and a drift guard now re-derives the downstream set so a new flag('foo') cannot reopen the hole.
  • The immutable run boundary: qa verify opens a private 0700 pending directory, snapshots exactly the bytes this invocation produced with their sha256 digests, and renames it into place only after everything downstream is verified, so a reader sees no run or a complete run, never a partial one.
  • Five evidence lanes, required and recorded (source, public-runtime, mock-contract, real-integration, mfa-integration), with qa diff across two lanes now an invalid boundary (exit 2), and a host-harness launcher replacing --login/--auth so secrets never appear in argv, environment, run.json, an archive, a log or model context: qa spawns a target-owned launcher by persona name only over fd 3, verify.roles.json rejects any credential-shaped key loudly, and a target-owned identity oracle invalidates the run before a single route is swept if one persona fails.
  • Atlas v2 makes every finding's coordinate (atlasVersion, atlas), freezes references/atlas-v1.md and computes v2 forward through one remapV1ToV2(), with a strict parser rejecting duplicate, malformed or misplaced ids by line number and coverage printing two denominators rather than one.

1 more changes in this release

0.3.0

tie it together

  • Three measurement modes were dead ends — qa crud, qa shadow replay and qa experiments drove a real browser and wrote real P0/P1 findings nothing read again — and now feed the same pipeline, only status: "measured" contributing.
  • qa marathon skipped four of the six measurement modes, and now runs them behind explicit preconditions, each unmet one a named skip carrying the command that would enable it.
  • Five artifacts claimed results nobody measured: priors-validation.json wrote accepted: true while the deciding function was never called, mission-state.json wrote iteration: 1, stop: "completed" verbatim, authorization-matrix.json hardcoded "unverified", flake-governance.json derived stability from a confidence float, and temporal-alerts.json called every finding an alert with no baseline.
  • A zero-cell sweep reported distinctRatio: 1 — 100% distinct surfaces over a run that rendered none — and is now null, while route confidence no longer conflates "never attempted" with "attempted and failed everywhere".
  • Four more router conventions (Remix and React Router 7 flat routes, SvelteKit, Astro, Nuxt), plus the matcher bug that made every React Router data-router repo inventory zero routes: the field is Component, capital C.
  • Eleven new atlas classes and five new static rules move coverage from 59 of 85 S/R classes to 76 of 96, with qa atlas --strict exiting 0.

3 more changes in this release

0.2.0

the qa researcher CLI

  • qa stability implements the two-of-three rule: N serial sweeps classify each finding stable, intermittent or ghost, with ghosts listed but never gating and an invalid run invalidating the measurement.
  • qa crud --mutate reconciles create/read/update/delete per persona, refusing without --mutate, without production: false, or against a prod-looking base, and filing crud.write-lost as P0 when a 2xx did not survive a reload.
  • qa invariants is an independent promotion authority: mine from archived runs with content-addressed proofs, approve into the committed verify.invariants.json (≥ 2 runs, 0 counterexamples, digests verified), and enforce as a rule pack that throws on a tampered archive.
  • qa triage groups by (kind, selector), ranks by severity → leverage → determinism and prints every denominator; qa next reduces that to one finding as a brief with atlas entry, hint, repro command and waiver syntax.
  • --dark on sweep seeds the theme before first navigation, grades theme.tokens-not-applied and theme.light-hardcoded, and joins the resume signature.
  • bin/bench-generate.mjs / bin/bench-score.mjs build a seeded corpus with a judge-only oracle, measuring precision 1.000 and recall 1.000 across all 18 planted kinds; Rust also records sha256 output digests in run-manifest.json that verify-manifest.mjs verifies, stale ⇒ exit 2.

2 more changes in this release