Skip to main content

ripwire-quality-bar

Code QUALITY of what YOU just wrote, before you commit or say 'done', or verifying a cleanup: --quality-delta lists what got WORSE in 10 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.

설치로 이동

소스 정보

저장소
redhat-et/ripwire
최근 소스 활동
2026년 9월 20일 20:45
감지된 SKILL.md 언어
영어
스타
2,312
포크
149

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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 10 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 and the closed fix loop are both on this page, below. > • **The regression is a MEMORY-layout hypothesis, not one of the 10 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: | Ratio | High says | Low says | |---|---|---| | **`deep/loc`** | **tangled** — the body *sustains* depth, so most of what you read is nested | **blocked-sequential** — a long run of shallow steps (a dispatch table, a switch, a setup block); the max is one inner loop | | **`deep/humps`** | **few giant tangles** — one region holds depth for a long stretch; the expensive fix | **many 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 10 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
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기