Agent skill

Ripwire Quality Bar

by redhat-et in redhat-et/ripwire

Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 11 kinds and exits 2 only when pre-existing code got materially…

Apache-2.0Auto-check: notesDevelopment

Install Ripwire Quality Bar

skills CLI
$ npx skills add redhat-et/ripwire --skill ripwire-quality-bar -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install redhat-et/ripwire ripwire-quality-bar --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/redhat-et/ripwire.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ripwire-quality-bar .claude/skills/ripwire-quality-bar && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ripwire-quality-bar
GitHub stars
2.4k
Token cost
~8.4k tokens
SKILL.md length
4,743 words
Files
2
Skills in repo
19
Repo updated
First seen
Licence
Apache-2.0

At a glance

Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 11 kinds and exits 2 only when pre-existing code got materially…

  • Works in 5 steps: Zero-setup path: just make your change,… → Make your change. → Measure the delta — ripwire… → …
  • Tasks that involve Code quality
  • SKILL.md covers Before you converge: the…, The loop, When the delta flags… and The shape → refactor playbook, plus 5 more sections
  • Calls git

What it does

Ripwire Quality Bar is an agent skill from redhat-et/ripwire. Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 11 kinds and exits 2 only when pre-existing code got materially worse; which restructuring a measured shape (humps/deep, a tangle) calls for. Merge safety → change-check. Even a single-line leaf fix runs it.

Its SKILL.md is about 8.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `quality-metrics.md`).

It sits in Development, covering Code quality. The repository describes itself as: The ripgrep of AI context: a zero-dependency C++23 CLI + MCP server for coding agents. Find what you want without reading the repo, then check you built what you meant — blast… The licence is Apache-2.0.

When your agent uses it

  • Tasks that involve Code quality

Example prompts

  • “/ripwire-quality-bar”

Requirements

  • Pre-approved tools (allowed-tools): Bash, Read

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. Zero-setup path: just make your change, then run ripwire --quality-delta --legend=compact
  2. Make your change.
  3. Measure the delta — ripwire --quality-delta --legend=compact → only the regressions you
  4. Fix the REAL ones, re-run, converge. Which fix a row calls for is the shape → refactor playbook
  5. Want ONE number instead of a list — ripwire --dmm --legend=compact. --quality-delta says which kinds got

What it can do on your machine

Read from SKILL.md and the folder at commit 60dd3b3. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Bash
    • Read

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • git

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use git, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ripwire Quality Bar loads about 8.4k tokens when it runs. Until then it costs about 90 tokens; SKILL.md has 4,743 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~90
When it runs · the whole SKILL.md, loaded when a task matches
~8.4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Bash, Read

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from redhat-et/ripwire at commit 60dd3b3, republished under its Apache-2.0 licence (© redhat-et). 4,743 words, ~8,390 tokens.

Download SKILL.mdSave it as .claude/skills/ripwire-quality-bar/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
ripwire-quality-bar
description
Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 11 kinds and exits 2 only when pre-existing code got materially worse; which restructuring a measured shape (humps/deep, a tangle) calls for. Merge safety → change-check. Even a single-line leaf fix runs it.
allowed-tools
Bash, Read

The quality-bar convergence loop

Routing: • PR-submission readiness — tests to run, blast radius, "safe to merge?" → ripwire-change-check — run --quality-delta FIRST, then its --test-gate: clean code that runs the wrong tests still regresses. • Reusing before you write the code in the first place → ripwire-reuse-first. • Wide-angle "where does this still look rotten" read across a whole file/subsystem (not a before/after delta) → the panel below, or ripwire-fresh-eyes for the full six-family breakdown. • You have the measurement and need the FIX — for your own diff or for a subsystem ripwire-fresh-eyes just measured → the shape → refactor playbook, the closed fix loop and the debt fix loop are all on this page, below. • The regression is a MEMORY-layout hypothesis, not one of the 11 quality kinds — --lint's built-in cache-* pack (8 static data-layout checks) is a normal part of a lint pass; --field-affinity[=STRUCT] is the deeper struct-level lens once a profile implicates a specific aggregate → ripwire-perf-target. • Not sure which skill? → ripwire-router.

Don't eyeball quality — measure the delta your change introduced, with a deterministic oracle, in a bounded loop. A file that was already complex is not your regression.

Apply the "non-trivial work" trigger to the LOOP, not the check. --quality-delta warm-runs in well under a second — cheaper than deciding by eye whether a fix "counts" as trivial, and that eyeball judgment is precisely where a leaf-looking edit that quietly changed a signature or added a branch slips through unmeasured. Run it. What a single-line leaf fix that preserves the signature and adds no branch, symbol, dependency, or abstraction gets to skip is everything AFTER a clean run: the drill-down table, --dmm, acking, a second round. This skill (and this file) earns its cost when the one-shot delta actually reports something — a clean gating="0" run on a leaf fix is confirmation, not ceremony you were right to skip.

Before you converge: the wide-angle read — --quality-panel

ripwire <dir> --quality-panel[=strict|default|lenient] --legend=compact is THE SINGLE COMMAND for "does what I just touched still look rotten" — one ranked report over six evidence families (the four --ensemble joins — structural, lexical, confusion, historical — plus colocation and state; the full per-family breakdown lives in ripwire-fresh-eyes). Point it at the file or symbol you just edited for a multi-angle second opinion the single --quality-delta number can't give you on its own.

Read it correctly: it is a lens, never a gate. --help says so in the flag's own text and the contract is enforced in code — --quality-panel exits 0 unconditionally, on every preset, on every repo. It does not compare against a baseline and it cannot fail a commit. The gate for "did MY change make this WORSE" is Step 3 below (--quality-delta) — that is the only pass in this skill (or in ripwire) with an exit code that means something. Run --quality-panel for the wide-angle read, converge with --quality-delta, never the other way round.

Pick the preset by what "rotten" needs to mean right now: lenient (all six families, 1 must agree) is a reading order, roughly a third of any tree; default (all six, 2 must agree) is a review list; strict (only the four families measured stable enough to stand behind repeatedly — historical and colocation are fixed-size worst-40 cuts over a ranking whose population moves, so both re-shuffle release to release on code that never changed) is the rung closest to something CI-shaped, but it is still a lens — nothing here plugs into an exit code the way --quality-delta does.

Read the structural row as a PROFILE — nest= alone is a max, and misleads solo

nest= reports the single deepest line in a function. One line at depth 9 and a thousand lines at depth 9 report the same number, so nest=9 cannot tell a tangled body from a long blocked-sequential one whose max was set by one inner loop nobody has to hold in their head. Acting on nest= alone is how an agent guard-clauses a dispatch table. --metrics (and the structural family's why= string in --quality-panel / --ensemble) now carry the profile beside the max:

<e f="structural" counted="1" why="ccx=724 loc=1244 nest=9 humps=30 deep=308 rrank=1"/>

Every concrete number on this page is ILLUSTRATIVE OF A SHAPE, never a value to expect. The counters themselves are under active calibration — an else-clause over-count fix in flight moves humps= down by a large fraction, and ccx=/nest= with it, on else-heavy functions. What is durable is what you do with the row: humps=1 vs many, the two ratios below, and the semantics (regions vs lines, absence below the bar, deep < humps legal). Read the row in front of you; never carry a remembered number to it.

  • humps= — how many maximal control-nesting regions reach the nesting bar (bar_nest= on the panel root; CodeScene's "bumpy road": a rise above the threshold then a fall). One deep tangle is 1; repeated missing abstractions are many. EXACT, not a floor.
  • deep= — how many LINES lie inside those regions, read against the loc= already on the row. A disclosed FLOOR (deep_floor="1").
  • Both are absent exactly when nest < the bar — not-deep, never a hidden 0.
  • deep below humps is legal output, not a defect. deep counts lines and humps counts regions, and two regions can share a line: a one-line if(c){x;}else{y;} at the bar is 2 regions on 1 line. Three reviewers have read that shape as a bug; it isn't.

Two ratios do the actual discriminating, and you compute them yourself from the row:

RatioHigh saysLow says
deep/loctangled — the body sustains depth, so most of what you read is nestedblocked-sequential — a long run of shallow steps (a dispatch table, a switch, a setup block); the max is one inner loop
deep/humpsfew giant tangles — one region holds depth for a long stretch; the expensive fixmany tiny touches — repeated missing abstractions, each hump its own cheap extraction

Three shapes off this repo's own source — read the pattern, not the digits, which move with calibration: a ~1000-line function at a low deep/loc (main, roughly a tenth) sits beside one at ~2.5× that fraction (buildGraph) once loc/nest have declared them equivalent; and a function far too small for any size bar to fire can carry the highest deep/loc in the table (ur_walkTree, loc=87, near half its body deep in a single hump). The first is blocked-sequential, the second tangled, the third dense — three different fixes, one indistinguishable nest=.

locals= rides the same row: the count of local-variable declarations, a FLOOR (locals_floor="1"), C/C++ only and absent — never a bare 0 — for every other language. It measures the working set a reader must hold at once, which is the thing extraction is actually supposed to shrink; a "split" that leaves locals where it was mostly moved braces.

join="deep+untested" on a --quality-panel row is a conjunction of two facts the report already holds — this row carries deep= and no indexed test reaches it — annotated, not a seventh family. It changes nothing: not fam=, not of=, not the ordering, not which rows appear. It is the pair where a refactor is most wanted and least safe, so it routes straight to test first, refactor second in the playbook below. It is suppressed on every row when tested_scope="0", because on a corpus whose tests were never crawled "untested" would be a fact about the crawl, not about the code — read tested_scope= on the root before you read the absence of the annotation as good news. deep_untested= on the root counts them across the WHOLE row set, which the limit= window does not change.

The per-file churn caveat. The historical family's churn= and hrank= are FILE facts, inherited verbatim by every symbol in the file — a symbol in a churny file collects that family without any property of its own. Discount it accordingly: on a row whose other evidence is thin, historical may be saying only "this file is busy", not "this function is." (hrank= is also a relative decile cut over this corpus, so something always fires.)

The loop

  1. Zero-setup path: just make your change, then run ripwire <dir> --quality-delta --legend=compact before you call it done — add --legend=compact every time you run this in a loop: on a CLEAN report the legend is nearly the whole payload (2,776 B to 454 B measured on a small fixture, 15,601 B to 8,775 B on a mid-change repo), the rows are byte-identical either way, and you have already read the dictionary — in a git repo it auto-compares the working tree vs git HEAD (<quality-delta baseline="git-HEAD"> confirms it), no start-of-task action needed. Tighter loop on a long change: run ripwire <dir> --quality-baseline FIRST — on a clean tree — to pin an explicit floor (takes precedence over HEAD) so each edit deltas against the original start, not the last commit. On a tree that already differs from HEAD the pin refuses, naming the gating findings it would have swallowed into the floor: commit first, or pass --allow-dirty to pin anyway, which stamps the absorbed count so every later report carries baseline_absorbed="N" and a green exit beside it reads "clean since the pin".

  2. Make your change.

  3. Measure the delta — ripwire <dir> --quality-delta --legend=compact → only the regressions you introduced, across the 11 kinds in the table below. Each emits <r kind="…" sym=… was=… now=…> (members= for duplication). Test-fixture dirs are exempt from dead-code; short-horizon-churn ignores your own current edit and exempts brand-new symbols/markdown/fixtures. Two exemptions are DISCLOSED on the report rather than silent, and both change how you read a zero: a symbol defined by a self-registering test/benchmark macro (doctest TEST_CASE, gtest TEST/TEST_F/TEST_P, Catch2, Google Benchmark, plus anything in .ripwire_config's register_macros) is never dead-code — a static initializer is invisible to a name-based call graph — and the header's register-macro-excluded="N" counts how many were dropped that way, printed even at 0. A duplication row whose members share only a recognized idiom — a scalar threshold ladder, an enum-to-string switch table, a builder chain — and share no domain identifiers across different scopes is demoted to sev="minor" with idiom="…" and stops gating. The idiom name is there so you can overrule it by reading: a demotion is a judgement the tool is showing its work on, not a row it hid. Watch verbosity hardest — LOC growth is the single most-measured agent failure mode, the one most likely to hide in an otherwise-clean diff.

    Read the exit code correctly — it is narrower than it looks. Findings are sorted on three independent axes, and only one combination gates:

    • acked — suppressed entirely (counted honestly in acked="N").
    • ORIGIN — a symbol that EXISTED at the baseline and got worse is preexisting-worse (no origin= attribute on the row); one that exists only because the code is NEW carries origin="new-symbol".
    • MATERIALITY — a small numeric delta is additionally sev="minor".

    --quality-delta exits 2 ONLY on preexisting-worse AND major AND unacked — exactly the gating="N" count in the header. Read gating=, not regressions=. A real header looks like:

    <quality-delta baseline="git-HEAD" regressions="0" minor="0" acked="0"
                   preexisting-worse="0" new-symbol="0" gating="0" at="f0a45e43d">

    origin="new-symbol" rows are PRINTED but NEVER gate. They are the debt you are adding — read them; nothing else will make you. And --help is explicit that exit 0 means "nothing that already existed got worse", NOT "clean": a change that is entirely new code can add unbounded new-symbol debt and still exit 0. Never report "quality-delta passed" as "no new debt" — open the rows.

    Two more contract details worth knowing: clone kinds classify by member set (a group is new-symbol only if EVERY member is new), and short-horizon-churn is preexisting by construction. LIMIT: origin is canonId (path::scope::name) identity, so a RENAMED or MOVED symbol reads as new — a genuine regression carried in with a move classifies new-symbol and will not gate. If your diff moves code, the exit code is especially weak evidence; read the rows.

  4. Fix the REAL ones, re-run, converge. Which fix a row calls for is the shape → refactor playbook below; proving the fix landed is the closed fix loop below that. Repeat until clean or the remainder are conscious trade-offs. Record a trade-off instead of re-reading it forever: ripwire <dir> --quality-ack="why it's accepted" writes the currently-visible findings into .ripwire_quality_acks (committable) — later runs suppress them honestly (acked="N") and a finding REAPPEARS the moment it worsens past its acked size.

    Ack a SUBSET, never the screen. Bare --quality-ack accepts every finding currently visible, so using it to accept one deliberate change silently accepts the rest too — that is how a ratchet turns into a rubber stamp. Narrow it with --ack-only=SUBSTR[,SUBSTR], which matches a finding's kind, its canonical id, or its facet:

    bash
    ripwire <dir> --quality-delta --ack-only=contract-change --quality-ack="arity change required by <fix>"

    Prefer the facet over the kind when one exists: api-surface also covers the never-gating new-symbol rows, so acking by kind can sweep in dozens of findings to accept a handful. --ack-only=gating selects exactly what would exit 2. A pattern matching nothing refuses (exit 1) rather than acking everything. Whatever you leave unacked stays visible — that is the point; an exit 2 you have explained in a commit message is worth more than an exit 0 you bought with a blanket ack.

    Sharing the working tree with other sessions? Then --ack-only is not enough — add --scope=. --quality-delta compares the working tree against HEAD, so in a checkout several agents are editing at once, every sibling's uncommitted rows land in your report. Bare --quality-ack there accepts the whole screen, which writes another session's debt into a committed ledger under your reason string: that is how the ratchet becomes a rubber stamp, and no amount of care reading the report prevents it. --scope=GLOB[,GLOB...] files each finding by its p= path:

    bash
    ripwire <dir> --quality-delta --legend=compact --scope=src/render,src/render_gl.h             # gate on MY subtree only
    ripwire <dir> --quality-delta --scope=src/render --quality-ack="deliberate"  # …and ack only my rows

    Rows outside the scope are still printed, under an <out-of-scope> element with a do-not-ack banner, and never gate; the header's scoped-out-gating= says how many of them would have gated, so a scoped exit 0 means "nothing of mine is broken", never "the tree is clean". The ack cannot write an out-of-scope row at all, and an --ack-only= that names one refuses (exit 1). Each row you write records by=<scope>, so a later run can flag an ack that suppressed a path its author never owned (foreign-acks=). A pattern with no wildcard is a root-anchored path prefix; */? match the whole path, with * spanning /. A scope that names nothing indexed refuses rather than reporting you clean. One reserved word: --scope=diff is whatever the working tree changed vs the baseline, expanded to one path per changed indexed file. It is sugar for the single-writer case — in the shared tree this flag exists for, a sibling's edits are "changed" too, so name your own paths there.

  5. Want ONE number instead of a list — ripwire <dir> --dmm --legend=compact. --quality-delta says which kinds got worse; it has no scale, so "is this change better than my last one?" has no answer. --dmm is that scale: the Delta Maintainability Model (di Biase, Rastogi, Bruntink & van Deursen, TechDebt 2019; thresholds and arithmetic from PyDriller's reference implementation) scores the share of the volume your change moved that landed in — or freed from — risky units.

    <dmm base="2edbb46c…" target="working-tree" available="1" combine="pooled" size_metric="physical-loc"
         dmm="0.436" good="462" bad="597" base_units="4759" target_units="4780">
      <p k="size" dmm="0.184" good="65" bad="288" d_low="65" d_high="288"/>…

    A unit (a function/method definition with a body) is low risk iff loc<=15 (size), cyclomatic<=5 (complexity), params<=2 (interfacing). good = low-risk volume added plus high-risk volume removed; bad = the reverse; dmm = good/(good+bad). Deleting a god function scores 1.000; growing one scores 0.000. The three sub-scores are separately actionable — a low size with a healthy interfacing says split the function, not change the signature.

    Three things to carry. It is a DELTA, never a level: editing bad code without changing its size, complexity or parameter count contributes nothing — you are not punished for touching a mess, which is deliberate. dmm="UNAVAILABLE" is not a score of 1.0 or 0.0 — it means good+bad was 0 (a rename, a literal edit, a comment reflow), i.e. the change is outside what the model measures; the same token can appear per property. And it never gates (always exit 0): use it to trend — --dmm=REV scores one commit against its parent and --dmm=A..B scores a range, so a series of commits is a series of numbers.

Show full SKILL.md (2,124 more words)Show less

When the delta flags something, zoom in

Thresholds/definitions are the catalog in quality-metrics.md — this is just drill-down + fix:

RegressionDrill-downFix
complexity--expand=SYMsplit the fn · early-return · lift the nested branch out
verbosity--expand=SYMthe #1 agent failure mode (below) — cut boilerplate, don't just reformat
nesting--expand=SYM · --metrics for the humps=/deep= profileguard clauses · invert the condition · extract the nested block — but read the profile first: which of those three it is depends on deep/loc and deep/humps (playbook below)
params--expand=SYMbundle related params into a struct, or split the function
duplication--clonesreuse the existing body — Rule of Three; wrong abstraction beats two honest copies
dead-code—delete what you orphaned, or wire the caller you forgot
api-surface (new public symbol)--callers=SYMintentional? keep it. Accidental? narrow it (should've been file-local)
error-masking (empty catch / bare except: pass / swallowed .catch; a broad handler that only logs and never names the error; a sole handler that re-throws it unchanged)--expand=SYMhandle it, log the error itself, or drop the try — AI code adds these +47% vs human (GitClear 2026). The two widened shapes gate only in Python (measured precision); elsewhere sev="minor"
short-horizon-churn--hotspots · git log -p <file>rewritten again inside 2 weeks (+15% AI) — is the design unsettled? consolidate
new-clone-of-reused-helper--clones · --callers=HELPERcall the existing well-reused helper — reuse is declining in AI code (GitClear)
placeholder (an added stub or TODO: todo!(), NotImplementedException, a "not implemented" throw/panic, a TODO/FIXME naming no issue)--expand=SYMfinish it, or name the issue that tracks it — never gates, but do not call the work done over it

These 11 kinds aren't a generic lint list — ten target a large-N-validated agent-code degradation mode (the eleventh, placeholder, is an honesty check on your own "done") (verbosity, structural erosion, smell rate, contract drift; passing tests ≠ clean design). Numbers + why the loop must be continuous, not a one-time prompt → quality-metrics.md.

Read the Fix column as DIRECTION, not a computed answer. None of these 11 kinds has a corpus-derivable correct replacement — "split the fn" names a move, not a target function shape, and you still judge it. That is deliberate: complexity, coupling, and colocation don't have a computable right answer the way a naming CONVENTION does. The one exception in this whole tool is --naming-consistency (→ ripwire-fresh-eyes), which proposes an actual propose= value because case-style consistency is Tier A — the corpus's own majority IS the answer, mechanically recombined from the name's own subtokens, no judgment call involved. Don't expect that anywhere else, and don't invent a "the fix is X" claim here that this tool doesn't itself compute.

The shape → refactor playbook

The table above maps a regression kind to a direction. This maps a measured shape to the named refactor and — the part agents skip — that refactor's precondition. Same doctrine as everything else here: these are facts plus options, never verdicts. The tool measures the shape; which option is right is still your call, and "leave it alone" is always on the menu.

Measured shapeThe named fixIts precondition — check this FIRST
Many shallow humps — humps high, deep/humps small, deep/loc lowExtract each hump. The bumpy-road fix: every region that rises to the bar and falls back is one missing abstraction with its own name. Cheap, mechanical, one hump at a time.Nothing structural blocks it — but each extraction is a new symbol, so re-run the loop below: extraction that lands as origin="new-symbol" api-surface debt should be file-local, not public.
One deep tangle — humps=1 (or few) with high deep/locGuard-clause inversion, then state extraction: invert the conditions that hold the depth, return early, and lift the sustained region's working set into a named struct or its own function. Expensive and genuinely risky — a rewrite, not a move.locals= tells you what you're really moving; a big locals means the region's working set, not just its braces, has to travel. Check --callers=SYM/--impact=SYM before starting, and never do it in the same diff as a behavior change.
Deciding whether an extract-method is mechanical or a rewrite — check ev= before picking a fix off this tableev= absent (or ev="1") on a cx= row means every region is single-entry/single-exit: extract-method applies mechanically, anywhere. ev>=2 means a jump gave some region a second exit — the same extraction is now the "one deep tangle" row above, not a cheap lift.ev_why=tag:count (guard-return, loop-escape, goto, ...) names which jumps raised it — a guard-return-heavy row is visibly not a knot. A FLOOR (ev_floor="1"): noreturn calls and macro-hidden exits can only push the true value higher.
Small AND dense — small loc, but deep is a large fraction of it (roughly half or more), typically in one humpRead it before you prescribe anything. Numeric kernels, tree walks, and state machines are legitimately dense: the depth is the algorithm. Often the right fix is a comment or a named constant, not a split.This row is where a metric-driven agent does the most damage. --expand=SYM first. If the density is the algorithm, ack it (--ack-only=) and move on.
High fan-in AND untested — big in=/amp=, tested="0", or a --quality-panel row carrying join="deep+untested"Test first, refactor second. The safety net is the fix's precondition, not its follow-up. → ripwire-write-tests (--seams, the tested= lens, --callers=SYM for the outside contract).Confirm the annotation is real: join= is suppressed entirely at tested_scope="0", so on an uncrawled-test corpus its absence proves nothing.
Duplication — a --quality-delta duplication / new-clone-of-reused-helper row, or a --clones groupConsolidate through the repo's own exemplar — ripwire <dir> --exemplar="<what this code does>" --legend=compact names the best-in-class instance to converge on (chosen by ROLE, not text similarity), so the survivor matches house patterns instead of being whichever copy you happened to open.Rule of Three — extract on the third occurrence, not the second; a wrong abstraction is worse than two honest copies. Check type= on the clone group: type="3" members are gapped near-misses and may differ on purpose.
Churn-flagged, structurally quiet — historical fires with thin other evidenceProbably nothing here. churn=/hrank= are FILE facts inherited by every symbol in the file.Confirm at the symbol before acting: git log -p <file> or --hotspots --since= to see whether this function is what keeps moving.

None of these has a corpus-derivable "correct" answer — see the paragraph above the table. The playbook names a move and the condition that makes the move safe; it does not compute a target shape, and any of these rows can honestly end in "measured, understood, left alone."

The closed fix loop — fix it, then PROVE the fix landed

Fixing without verifying is how a refactor trades one regression for two. Four steps, in this order; each answers a question the previous one cannot:

bash
# 1. make the fix (playbook above)
ripwire <dir> --quality-delta --legend=compact        # 2. did the TARGETED kind improve, and did nothing else regress?
ripwire <dir> --edit-check=SYM --legend=compact       # 3. is the CONTRACT intact?
ripwire <dir> --affected=F1,F2 --legend=compact       # 4. which tests PROVE it? (then run them)
  1. --quality-delta — the only step with a meaningful exit code, and it is doing two jobs here, not one: the row you were chasing should be gone, and nothing new should have appeared. A "split the function" fix that drops complexity while adding api-surface + duplication is a lateral move. Read gating=, but also read the origin="new-symbol" rows — extraction always creates new symbols and those never gate, so exit 0 is not the same as "the fix was free."
  2. --edit-check=SYM — unchanged / new-symbol / contract-change for the symbol you just edited: param count and publicness NOW vs git HEAD, plus its 1-hop callers with any call site provably incompatible with the new arity flagged. A refactor is supposed to be unchanged here; a contract-change you did not intend is the finding. Cheap enough (~ms warm) that skipping it is never the economical choice. It refuses (exit 1) if SYM matches several definition sites — a contract is per definition, so pass the file:name spelling it lists.
  3. --affected=F1,F2 (or --affected=SYM) — the test files that transitively reach what you changed. Metrics improving is not evidence the code still works; this names what to run, and then you run it. Mid-task, --situ is the same answer over the whole git diff plus co-change partners; at PR time --test-gate is the gating form (exit 4 when tests-to-run or the untested blast radius is non-empty).

Done means: the targeted kind is gone from --quality-delta, nothing else regressed, --edit-check reports the contract you intended, and the --affected tests pass. Anything short of all four and the fix is still a hypothesis.

The fix loop — paying down EXISTING debt, one finding per commit

The loop above converges on debt you just added. When the task is debt that was already there ("clean up this module", "fix the worst of it"), run this instead — bounded, one finding at a time:

  1. Pick the top finding. Your own open rows first (gating=, then origin="new-symbol"); otherwise row 1 of ripwire <dir> --quality-panel=strict --legend=compact pointed at the area you were asked about. The panel orders by how many independent families agree, not by payoff — no validated value × cost ranking ships yet — so between near-ties take the cheapest: small, tested, few --callers=SYM.
  2. Untested? Write the test first. join="deep+untested" on the row, or ripwire <dir> --affected=SYM --legend=compact naming no <test> row that carries hops= (a partner="1" row without hops= is co-change, not reach), means the refactor has no safety net. Write one against the UNCHANGED code (→ ripwire-write-tests), see it pass, commit it alone. A test written after the refactor pins the new behavior, not the old.
  3. Apply the recipe the shape calls for — the drill-down table's Fix column for a regression kind, the playbook row (precondition first) for a measured shape. The one recipe neither table carries: a --lint --lint-select=magic-number finding (C/C++/ObjC) → a named constant. "Leave it alone" is still on the menu.
  4. Prove it — the closed fix loop above, all four steps, with one rule stricter than its step 2 (anti-gaming): the fix must not worsen ANY other kind. Measure BEFORE you commit, one fix per commit, so a bare --quality-delta (working tree vs git HEAD; re-pin after each commit if you pinned --quality-baseline) covers exactly this fix — after the commit it reads regressions="0" trivially (head_basis="identity"); to check a fix already committed, run ripwire <dir> --quality-delta=HEAD --legend=compact (that commit vs its parent). Then regressions= must be 0, not just gating=, and acked= must not rise (a pre-ack hides a row). The one exemption: a kind="short-horizon-churn" row with churn="self" on a function this session already fixed is the loop's own commits, not a regression — better, take the next row from a different function. A fix that trades its target for a row of any other kind — a duplication, a params, a public api-surface helper that should have been file-local — is a lateral move: revert it, don't ack it. --quality-delta only lists what got worse, so confirm the target moved by re-running the command that ranked it.
  5. Stop at 3 fixes per session (a default, not a measured optimum). Guardrail 3 bounds each fix to 1–2 rounds; this bounds the session. End by naming the next row, not starting it — a long unreviewed chain of mechanical refactors is where gaming hides.

The four guardrails (why this loop converges instead of degrading)

  1. Deterministic oracle, not self-critique. The delta is computed — it cannot hallucinate or reinforce a bad regression. Trust it over a vibe.
  2. Descriptive, never a target. Fix the regression for the right reason. Never split a function or delete a "duplicate" just to move the number, and never edit a test to make the bar pass — metric-gaming: the score improves while the code gets worse.
  3. Bounded — 1–2 rounds. A 2nd or 3rd blind refinement round often degrades code. Stop when clean or the rest are conscious trade-offs; don't chase zero.
  4. Persist the bar. Re-baseline after you commit, so the next change measures against the new floor.

Wire it into CI / pre-commit

--quality-delta exits 2 only when a finding is preexisting-worse AND major AND unacked — the gating="N" header count. Minor-tier, acked, and origin="new-symbol" findings all report but never gate, so a green hook does not mean the diff added no debt — it means nothing that already existed got worse. Non-zero is the hook contract, no wrapper needed: ripwire <dir> --quality-delta --legend=compact || exit 1. If you want CI to also block on the debt a change ADDS, exit 2 will not do it for you — parse new-symbol="N" from the header (--json is supported for this verb) and apply your own policy. Chain the other deterministic gates in the same hook: det-gate (diff <(ripwire <dir>) <(ripwire <dir>), must be byte-identical) and ripwire <dir> | xmllint --noout - (valid XML) — any non-zero exit blocks the commit.

Honesty

ripwire measures STRUCTURE (complexity / duplication / reachability), not data flow — it cedes use-after-move / taint / type / null errors to the compiler. A high amb= symbol can be a dispatch hub, not a bug. Thresholds are heuristics: trust coupling/churn hardest, complexity as size-correlated (not independent), and Martin I/A/D/nccd as descriptive only — never proof. Full catalog (definition · why it predicts defects · evidence tier · the verb) → quality-metrics.md.

© redhat-et, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in skills/ripwire-quality-bar of redhat-et/ripwire.

  • SKILL.md
  • quality-metrics.md

Open the folder on GitHubat commit 60dd3b3

Compare with similar skills

Ripwire Quality Bar next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Ripwire Quality Bar compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ripwire Quality Bar this skillredhat-et/ripwire2.4k—~8.4kAutomated safety check: NotesApache-2.0
WooCommerce Code Reviewwoocommerce/woocommerce11k3 repos~1.1kAutomated safety check: PassCustom licence
Systematic Code Refactoringluongnv89/claude-howto42k—~3kAutomated safety check: PassMIT
Install Anti-Slop Oxlint Rulesdmmulroy/anti-slop5.3k—~2.2kAutomated safety check: PassMIT
Constraint-Driven Developmentaddyosmani/agent-skills103k2 repos~5.2kAutomated safety check: PassMIT
Skill Doli Code ReviewDolibarr/dolibarr7.7k1 repos~1.1kAutomated safety check: PassMIT

Similar skills

  • WooCommerce Code Review

    woocommerce/woocommerce

    Reviews WooCommerce code changes against the project's standards, flagging backend PHP architecture, naming, documentation, data integrity and testing violations.

    11k GitHub starsUsed in 3 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Systematic Code Refactoring

    luongnv89/claude-howto

    Guides refactoring in phases based on Martin Fowler's method: research, test coverage check, planning and small tested steps, with your approval at each phase.

    42k GitHub stars~3k tokensUpdated 9 days ago
    DevelopmentAuto-check passed
  • Installs, updates or migrates the vendored anti-slop Oxlint plugin in a repository, keeping local rule changes and the plugin's license and provenance files.

    5.3k GitHub stars~2.2k tokensUpdated 29 days ago
    DevelopmentAuto-check passed
  • Constraint-Driven Development

    addyosmani/agent-skills

    Records a project's quality bar in CONSTRAINTS.md and watches diffs for signs an agent quietly weakened it, such as suppressions, skipped tests or lowered thresholds.

    103k GitHub starsUsed in 2 repos~5.2k tokens
    DevelopmentAuto-check passed
  • Skill Doli Code Review

    Dolibarr/dolibarr

    Reviews Dolibarr PHP code for compliance with coding standards and security best practices, and fixes identified issues.

    7.7k GitHub starsUsed in 1 repo~1.1k tokens
    DevelopmentAuto-check passed
  • Ponytail Lazy Developer Mode

    DietrichGebert/ponytail

    Makes the agent pick the laziest solution that works: skip unneeded work, reuse what exists, prefer the standard library and platform features, and keep diffs small.

    159k GitHub stars~873 tokensUpdated yesterday
    DevelopmentAuto-check passed

More from redhat-et/ripwire

All 19 skills in this repo
  • Ripwire Output Emission

    redhat-et/ripwire

    Rules for writing and converting formatted output in ripwire's C++ source with its emit helpers, keeping every printed byte identical to the old printf output.

    2.4k GitHub stars~1k tokensUpdated today
    Auto-check passed
  • Ripwire Change Check

    redhat-et/ripwire

    Checks whether a working-tree diff or a pull request is safe to merge: blast radius, tests to run, contract breaks, branch conflicts and stranded work.

    2.4k GitHub stars~4.3k tokensUpdated today
    Auto-check: notes
  • Ripwire Graph Query

    redhat-et/ripwire

    Answers call-graph questions that combine several conditions, such as complex functions that reach a target or untested symbols near main, using ripwire's graph-query mode.

    2.4k GitHub stars~1.1k tokensUpdated today
    Auto-check: notes
  • Ripwire Subsystem Handoff

    redhat-et/ripwire

    Produces a short brief for handing a code subsystem to a teammate or fresh session, using ripwire to rank symbols, expand bodies and surface design docs.

    2.4k GitHub stars~1.8k tokensUpdated today
    Auto-check: notes
  • Ripwire Code Navigation

    redhat-et/ripwire

    Answers questions about a named symbol, such as its callers, what it calls, the path between two symbols or the downstream impact of changing it, using the ripwire CLI.

    2.4k GitHub stars~4.8k tokensUpdated today
    Auto-check: notes
  • Contributor guide for reading clang optimization remarks while editing ripwire's own C++, deciding between a source change and a build change such as LTO or PGO.

    2.4k GitHub stars~3.1k tokensUpdated today
    Auto-check: notes

Categories

Questions about Ripwire Quality Bar

What does Ripwire Quality Bar do?

Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 11 kinds and exits 2 only when pre-existing code got materially…. Ripwire Quality Bar is an agent skill from redhat-et/ripwire. Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 11 kinds and exits 2 only when pre-existing code got materially worse; which restructuring a measured shape (humps/deep, a tangle) calls for.

When should I use Ripwire Quality Bar?

Ripwire Quality Bar fits situations like: tasks that involve Code quality.

How do I install Ripwire Quality Bar in Claude Code?

Run `npx skills add redhat-et/ripwire --skill ripwire-quality-bar -a claude-code`. Or copy the skill folder (skills/ripwire-quality-bar in redhat-et/ripwire) into .claude/skills/ripwire-quality-bar in your project. Claude Code loads it when a task matches its description.

How do I install Ripwire Quality Bar in Codex?

Run `npx skills add redhat-et/ripwire --skill ripwire-quality-bar -a codex`. Or copy the skill folder (skills/ripwire-quality-bar in redhat-et/ripwire) into .agents/skills/ripwire-quality-bar in your project. Codex loads it when a task matches its description.

Can I use Ripwire Quality Bar in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add redhat-et/ripwire --skill ripwire-quality-bar -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ripwire-quality-bar, .gemini/skills/ripwire-quality-bar, .github/skills/ripwire-quality-bar and .opencode/skills/ripwire-quality-bar in your project.

What does Ripwire Quality Bar need to run?

Going by SKILL.md and its folder, Ripwire Quality Bar needs the command-line tools its instructions call (git). Its frontmatter pre-approves these tools: Bash, Read.

Does Ripwire Quality Bar access the network?

SKILL.md contains no URLs. Its commands use git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Ripwire Quality Bar safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Ripwire Quality Bar use?

Ripwire Quality Bar is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ripwire Quality Bar use?

About 8.4k tokens (SKILL.md is roughly 34k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Ripwire Quality Bar?

Skills that share tags, products or a category with Ripwire Quality Bar: WooCommerce Code Review (woocommerce/woocommerce, 11k stars), Systematic Code Refactoring (luongnv89/claude-howto, 42k stars), Install Anti-Slop Oxlint Rules (dmmulroy/anti-slop, 5.3k stars) and Constraint-Driven Development (addyosmani/agent-skills, 103k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Ripwire Quality Bar?

redhat-et (a GitHub organization) maintains it in redhat-et/ripwire, which has 2,428 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on October 9, 2026.

Source: redhat-et/ripwire on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.