Releases: smixs/code-quality
Release list
1.3.3 — advice, never a block
The plugin now advises and never blocks. It trusts the agent the way a good reviewer trusts a colleague: it measures, shows its work and says loudly when something is dangerous; the agent decides and says why.
What's new in 1.3.3
- No hook stops the agent.
pre-commit,commit-msgandpre-pushprint their report and let git go on; only an interrupt (Ctrl-C) stops it. The shell guard no longer denies--no-verify,commit -norcore.hooksPath: the command runs and a red flag sits next to its output. - Red flags first. Dangerous moves open every output as one line:
RED FLAG: <what you are doing> -- <why it is dangerous>; check: <what to verify>. They cover a secret in the change or the pushed history, a deleted, skipped or weakened test, a baseline refreshed with the code, red touched tests on push, and a git command that skips the hooks. Secret checks stay. - The Stop hook never holds the turn. The user sees the red flags at once; the agent gets the full report once, with its next message (
agent-noteson UserPromptSubmit in Claude Code and Codex, the next-turn channel in pi and omp, a message without a reply in OpenCode). Grok drops UserPromptSubmit context, so there the report reaches the user only. - Findings are advice. CRAP, complexity, diff coverage, cycles, dead code, clones, glossary, AI attribution and Jev appear under
FINDINGS (n), advice, nothing blocked:or as notes.check, the full run andmutantstill exit 1 on findings, so a script or CI can decide for itself. [hooks] flag_bypassreplacesblock_bypass(still read);falsesilences the shell guard's flag.
Verified: 407 tests; live git hooks in a scratch repository (a commit with a secret, a deleted test, a push with red tests all go through with the flags first); a live Claude Code session where the turn ended after one answer and the next message carried the red flag verbatim.
Upgrade: claude plugin update code-quality@code-quality, or your agent's plugin update. Running install-hooks again is not needed: the hooks pick up the new copy the next time an agent runs. No config change is needed.
1.3.2
Touched-test acceptance now finds every test that can break: check --tests and mutant follow the project's imports to the end, resolve modules the way the project does, and keep the coverage that tests write from child processes.
What's new in 1.3.2
- Every test that reaches the change.
check --testsandmutantselect the whole chain of importers (imports, re-exports, dynamic imports,require, and path strings in tests), not two steps. On a real bun monorepo a change to a shared utility now selects 109 of the 109 tests that depend on it (1.3.1: 23). pre-push is unchanged. - Modules resolve like the project resolves them. The nearest
tsconfig.jsonpaths(throughextends, TypeScript key precedence),package.json#imports(#lib/*), and workspace packages by name (exports, including the string form,module,main). - Coverage from child processes counts. The built-in node, bun, vitest and pytest commands write their report under
$QG_DIRand append it to$QG_LCOVinstead of replacing the file; the exit code stays the tests'. - Broken lcov is refused everywhere. The full gate, a plain
checkand--skip-testscheck the lcov structure before any CRAP number; an orphan or repeatedend_of_recordis invalid coverage. mutant_timeout_sdefaults to 900 s, astouched_timeout_s: a mutant on a shared module now runs every dependent test.
Verified: 404 tests; live runs on two real consumer repositories (a TypeScript agent and a bun monorepo), including a shared module with 576 dependent test files (check --tests GATE PASS, mutant KILLED).
Upgrade: claude plugin update code-quality@code-quality, or your agent's plugin update. No config change is needed.
1.3.1 — accept a change by its own tests
A lead can now accept an agent's change by the tests that change touches, prove that a test catches a real bug, and trust that the pushed commit, not the local checkout, is what the gate judged.
What's new
1.3.0
check --since <base> --testsruns the tests the change touches (by name, by import, and one more hop through a test harness) with coverage in a private run folder, then judges only the changed functions. Old debt does not block.mutant --file <path> --find <text> --replace <text> [--test <path>]makes one exact mutation, runs the tests, and prints KILLED, SURVIVED or ERROR. The file is restored byte for byte after every outcome, Ctrl-C included; a mutant left by a killed run is restored on the next start.- One test executor for the full gate,
check --tests, pre-push andmutant: it waits while the machine is busy (1-minute load above 2 × CPU, up to 10 minutes, then runs) and kills the whole test process group on a timeout or Ctrl-C. - pre-push judges the pushed commit: when the push has touched tests to run, pushing a commit other than the checked-out one, or with uncommitted changes in the files the touched tests read, is refused with the reason.
- New
[tests]keys (touched_cmd,mutant_cmd,max_load,load_wait_s,touched_timeout_s,mutant_timeout_s) are protected like the rest of.quality.toml. - New
acceptanceskill: the runbook for accepting a change — a spec with a failure table, one parallel pass on a frozen candidate, one batched repair, two rounds.
1.3.1
- Touched tests include
X.<anything>.test.tsforX.tsxand test files that name a repository file by a path string, so render tests that load a harness by path are selected. - A
bun.lockorbun.lockbat the root makes apackage.jsonproject a bun project for touched runs andmutant. - Only the agent entry points (
agent-stop,guard-bash) move the machine's git hook pointers; a copy run by hand never takes them. mutantreports a malformed state file asMUTANT ERRORwith the state paths; lcovDAlines count only inside theirSFrecord.
Verified: 381 tests; live runs on two real consumer repositories (a TypeScript agent and a bun monorepo).
Upgrade: claude plugin update code-quality@code-quality, or your agent's plugin update. No config change is needed.
1.0.0 — one gate, every agent
code-quality is now a plugin, not only a skill. One repository installs into Claude Code, Codex, Grok, pi, omp and opencode; the agent hooks run without the model having to remember the skill.
What's new
- Plugin packaging:
.claude-plugin/(Claude Code, Grok, omp),.codex-plugin/+ marketplace (Codex), pi/omp package, opencode plugin (V1 and V2). The skill lives inskills/code-quality/. - Stop hook in every harness: the agent is sent back once with the gate's reasons.
- Bypass guard:
git commit --no-verify/-n(alsoFOO=1 git …, bundled-nm),-c core.hooksPath=…andgit config core.hooksPathare refused in repositories with.quality.toml. Switch:[hooks] block_bypass = false. - Inline suppressions no longer hide gate rules:
eslint-disable complexity,# noqa: C901,//nolint:gocycloand friends are ignored by the analyzers, and a new suppression in the diff is itself a tamper finding. - Git hooks install into a stable shim (
~/.local/share/code-quality, override withCODE_QUALITY_HOME), so plugin updates don't break them. - Grok 1.0.40 does not run plugin hooks yet:
bun scripts/quality.ts install-grok-hookswires them globally.
Verified live: Claude Code, Codex and Grok (stop, bypass refusal, switch). pi fully, omp partly, opencode via adapter handlers. 218 tests.
Breaking: SKILL.md moved to skills/code-quality/, git hooks moved from hooks/ to git-hooks/; rerun install-hooks in your repositories.