Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
383c748
test(ruby): a red gate for Ruby's bare-word call, with Ruby's own loc…
andriytyurnikov Oct 1, 2026
60ba5c0
feat(ruby): a bare-word call is a call wherever Ruby's own lexical ru…
andriytyurnikov Oct 1, 2026
72e9351
test(ruby): Ruby has no declarations — red arms for an own attr_reade…
andriytyurnikov Oct 1, 2026
69d39b2
fix(ruby): Ruby has no declarations — an attr accessor or an empty ho…
andriytyurnikov Oct 1, 2026
8aa316f
docs(changelog): Ruby bare-word calls and Ruby-has-no-declarations un…
andriytyurnikov Oct 1, 2026
28bd0e6
test(ruby): rubybarecallcheck wraps its three one-line `&& ok || no` …
andriytyurnikov Oct 1, 2026
4a072cb
test(callform): Ruby row 6 — the bare paren-less call is now a call; …
andriytyurnikov Oct 1, 2026
806e3f3
refactor(graph): the decl/def collapse family is collapseFamilyOf — c…
andriytyurnikov Oct 1, 2026
45dc9b4
test(ruby): a red gate for what a bare call can reach — mixins are an…
andriytyurnikov Oct 2, 2026
9899564
test(ruby): rubyreachcheck pins the include-narrow, concern, core-roo…
andriytyurnikov Oct 2, 2026
089e077
feat(ruby): a call to self reaches what Ruby's method lookup reaches …
andriytyurnikov Oct 2, 2026
02ed7ac
docs(changelog): a Ruby call to self reaches what Ruby's method looku…
andriytyurnikov Oct 2, 2026
8d82330
test(ruby): a red gate for a typed receiver — a call on a built objec…
andriytyurnikov Oct 2, 2026
5671f34
feat(ruby): a call on a receiver the code builds answers from that cl…
andriytyurnikov Oct 2, 2026
55eb738
docs(changelog): a Ruby call on a receiver the code builds answers fr…
andriytyurnikov Oct 2, 2026
2f5a3e6
test(ruby): a red gate for a call on RSpec's own target — expect( v )…
andriytyurnikov Oct 2, 2026
dd948d5
feat(ruby): a call on RSpec's own target is RSpec's — expect( v ).to …
andriytyurnikov Oct 2, 2026
c56a916
docs(changelog): a call on RSpec's own expectation target is RSpec's,…
andriytyurnikov Oct 2, 2026
64f4b84
test(ruby): a red gate for a method named by a symbol the framework c…
andriytyurnikov Oct 2, 2026
9a451c7
feat(ruby): a method a Rails declaration names by symbol has a caller…
andriytyurnikov Oct 2, 2026
a3eb23a
docs(changelog): a method a Rails declaration names by symbol has a c…
andriytyurnikov Oct 2, 2026
eecca7c
test(ruby): rubydeclrefcheck's absent arm reports through if/else, no…
andriytyurnikov Oct 2, 2026
e8e65e1
test(ruby): a red gate for Rake task files and Jbuilder views — crawl…
andriytyurnikov Oct 2, 2026
212f11f
feat(ruby): Rake task files and Jbuilder views are Ruby — main's and …
andriytyurnikov Oct 2, 2026
c48caf0
test(ruby): rubyrspectargetcheck's red arms for RSpec's matcher chain…
andriytyurnikov Oct 2, 2026
b3085fa
feat(ruby): a call on an RSpec matcher's chain is RSpec's — receive( …
andriytyurnikov Oct 2, 2026
d17db41
docs(changelog): Rake task files and Jbuilder views are Ruby, and a c…
andriytyurnikov Oct 2, 2026
bb6ec04
test(ruby): a red gate for a call on a class — the class object's loo…
andriytyurnikov Oct 2, 2026
57253a7
test(ruby): rubyclassrecvcheck's singleton, forwarding and qualified-…
andriytyurnikov Oct 2, 2026
d24c4b0
feat(ruby): a call on a class answers from the class object's lookup …
andriytyurnikov Oct 2, 2026
23ddede
docs(changelog): a Ruby call on a class answers from the class object…
andriytyurnikov Oct 2, 2026
b21d03b
test(builtin): builtinbindcheck's header external= counts the two C.n…
andriytyurnikov Oct 2, 2026
5a29f7d
chore(versions): the shared pins re-derived on main 2720d1c5 — kParse…
andriytyurnikov Oct 4, 2026
51dfeeb
test(ruby): the inverted absence arms fail on a missing row or a fail…
andriytyurnikov Oct 4, 2026
a493ca6
test(ruby): rubyreachcheck — an out-of-reach call is refused as exter…
andriytyurnikov Oct 4, 2026
f3ab168
test(ruby): rubyclassrecvcheck floor (h) — a mixin's own singleton me…
andriytyurnikov Oct 4, 2026
0b6118a
docs(changelog): floor (h) of the class-object entry, the accessors' …
andriytyurnikov Oct 4, 2026
b86a7a9
test(ruby): rubyclassrecvcheck — include is the instances' side, exte…
andriytyurnikov Oct 4, 2026
4fb6da2
feat(ruby): a class object's lookup tells include from extend, in Rub…
andriytyurnikov Oct 4, 2026
162255e
docs(changelog): a Ruby class object's lookup tells include from exte…
andriytyurnikov Oct 4, 2026
04a6c21
test(ruby): rubyclassrecvcheck — a call to self, or on a built instan…
andriytyurnikov Oct 4, 2026
70d9aba
feat(ruby): a call to self, or on a built instance, answers from its …
andriytyurnikov Oct 4, 2026
e55e7ae
docs(changelog): a Ruby call to self, or on a built instance, answers…
andriytyurnikov Oct 4, 2026
5abf901
fix(graph): kRubySideAcross is sized by its enums' counts, and RubyAn…
andriytyurnikov Oct 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
748 changes: 744 additions & 4 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2082,9 +2082,9 @@ wrong, and it has. These are the results that say so, all in-tree, all published
### In the tests

<details>
<summary><b>662 gate scripts</b>, five contracts no unit test can hold, and the house rule: write the gate before the code it measures</summary> <!-- gatecount -->
<summary><b>669 gate scripts</b>, five contracts no unit test can hold, and the house rule: write the gate before the code it measures</summary> <!-- gatecount -->

`test/regression.sh` names **662 gate scripts** and is the authoritative list; <!-- gatecount -->
`test/regression.sh` names **669 gate scripts** and is the authoritative list; <!-- gatecount -->
`python3 test/pargates.py . ./build/ripwire -j 6` runs the same set in parallel. On top of them sit the
contracts that do not fit a unit test: two runs byte-identical, warm output identical to cold, output
that pipes clean through `xmllint --noout`, a sanitizer build with `-fno-sanitize-recover=all`, and a
Expand Down
6 changes: 3 additions & 3 deletions docs/EVALS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ section, and it is not an afterthought.
| **Co-change / known-item evals** | `--eval`, `--eval-retrieval` (see `bench/ANSWERQUALITY.md`) | Whether the tool surfaces the other files a real historical commit touched; and known-item retrieval across four rankers. |
| **Ensemble calibration harness** | `bench/ensemblecal/` | Whether `--ensemble`'s four evidence families are actually orthogonal, how often each fires, how stable each is across commits — and the preset ladder derived from that (§9). |
| **Differential argv harness** | `test/argvdiffcheck.sh` | That a refactor changed *nothing observable*: two binaries, every argv vector, stdout + stderr + exit code byte-identical. |
| **The gate suite** | `test/regression.sh`, `test/pargates.py` | 662 gate scripts plus the determinism, cache-transparency and golden contracts. <!-- gatecount --> |
| **The gate suite** | `test/regression.sh`, `test/pargates.py` | 669 gate scripts plus the determinism, cache-transparency and golden contracts. <!-- gatecount --> |
| **`--quality-delta`** | `src/quality.h` | Ten measured code-quality failure modes, reported only where a change made them worse. |

### The labeling protocol (why the held-out eval is allowed to disagree with the ranker)
Expand Down Expand Up @@ -5866,7 +5866,7 @@ copy here would be exactly the dialect divergence that gate exists to catch. Com
tags, wrap, stable-order defaults), seven individually invoked standalone gates (`g1freshcheck`,
`skillscan`, `htmlexport`, `compresscheck`, `handoffcheck`, `releaseinstallcheck`,
`taskroutecheck`), and a single loop
naming **662 gate scripts**, all of which exist on disk. <!-- gatecount -->
naming **669 gate scripts**, all of which exist on disk. <!-- gatecount -->

`python3 test/pargates.py . ./build/ripwire -j 6` runs the same scripts in parallel so a full
verification fits in one sitting. It does not modify `regression.sh`.
Expand Down Expand Up @@ -6969,7 +6969,7 @@ Listed because the reason is more useful than the silence.
shipped**. See `bench/locbench/anchorhop_calib.json`. The mention anchor's reproducible numbers are
the ablations in §4.
- **A single round gate-count.** Two in-tree numbers disagree (`test/pargates.py`'s docstring says
~210; `test/argvdiffcheck.sh` says 200+), while the loop in `test/regression.sh` names 662. The <!-- gatecount -->
~210; `test/argvdiffcheck.sh` says 200+), while the loop in `test/regression.sh` names 669. The <!-- gatecount -->
loop is the authority; the stale docstrings are a known drift. Since 2026-09-10 the number is not
written by hand anywhere: `docs/gatecount_build.py` derives it from the loop and rewrites every
published site, `test/gatecountcheck.sh` fails if any of them drifts, and `test/manifestcheck.sh`
Expand Down
6 changes: 3 additions & 3 deletions present/deck5_ripwire_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ function storyCards(s, { kick, head, stories, footText }){
kicker(s, "// how it stays true", AMBER);
title(s, "Proven, not promised");
const cards = [
["662 gate scripts", "the suite runs on every push — plus determinism, cache-transparency and golden contracts; the gate count itself is gated against the runner's own loop"], // gatecount
["669 gate scripts", "the suite runs on every push — plus determinism, cache-transparency and golden contracts; the gate count itself is gated against the runner's own loop"], // gatecount
["byte-identical, always", "two runs over the same tree produce the same bytes; warm equals cold. Enforced in CI, twice — Release AND a plain flavour, because NDEBUG once blinded a whole class of checks"],
["differential refactoring", "a refactor must prove it changed nothing observable: two binaries, hundreds of argv vectors, stdout + stderr + exit codes byte-identical"],
["held-out labels, authored blind", "eval labels were written by reading source before the ranker ever ran on them — so the eval is allowed to say the ranker is wrong. It has."],
Expand All @@ -1238,7 +1238,7 @@ function storyCards(s, { kick, head, stories, footText }){
title(s, "Claims you can trust, because we publish what failed", { size: 32 });

card(s, MX, 1.72, 3.86, 1.72);
stat(s, "662", "gate scripts named by test/regression.sh — and the COUNT itself is gated against the runner's own loop, so it cannot go stale quietly", // gatecount
stat(s, "669", "gate scripts named by test/regression.sh — and the COUNT itself is gated against the runner's own loop, so it cannot go stale quietly", // gatecount
MX+0.15, 1.86, 3.56, CYAN, { bsize: 42, bh: 0.66, lsize: 9.5 });
card(s, 4.68, 1.72, 3.86, 1.72, CARD2);
stat(s, "8", "registered NEGATIVES — changes built, gated green, measured against a band written before the code, and reverted rather than tuned",
Expand Down Expand Up @@ -1540,7 +1540,7 @@ function storyCards(s, { kick, head, stories, footText }){
["185 long flags · 36 slides", "bash test/deckclaimcheck.sh"],
["every --flag named here exists", "bash test/deckcheck.sh"],
["74.7% fewer element bytes", "bash test/showcasecapturecheck.sh"],
["662 gate scripts", "bash test/manifestcheck.sh"], // gatecount
["669 gate scripts", "bash test/manifestcheck.sh"], // gatecount
["49 repos · 71 papers · 237 surveyed","bash test/readmedriftcheck.sh"],
["the ten moments, any row", "ripwire . --callers=SYM | wc -c"],
["the head-to-head table", "bench/headtohead/r4-2026-08-06/"],
Expand Down
8 changes: 5 additions & 3 deletions queries/ruby/tags.scm
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
; Ruby structure the call graph cares about:
; - class / module definitions → def nodes (containers; module is a namespace/mixin)
; - `def name` / `def self.name` method definitions → the def nodes calls resolve TO
; - method calls → the call references (edges). A bare `foo` with no receiver and no
; args parses as (identifier); `foo(..)` / `obj.foo` parses as (call). We capture the
; (call) form's method name — the reliable, unambiguous call site.
; - method calls → the call references (edges). `foo(..)` / `obj.foo` parses as (call), and
; this query captures the (call) form's method name. A bare `foo` with no receiver, args or
; parentheses parses as (identifier) — the same node a local-variable read is — and no query
; can tell the two apart: ingest_binds.h captureRubyBareCalls mints those calls by Ruby's own
; lexical local rule instead (parser version 130, test/rubybarecallcheck.sh).
; - require / require_relative → reference edges (they ARE plain (call) nodes, captured
; by the call rule below — no separate rule needed).
;
Expand Down
2 changes: 1 addition & 1 deletion src/darkflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ inline constexpr std::int32_t kTemplateText = -1;
inline constexpr std::string_view kShellExtTable[] = { ".sh", ".bash", ".zsh" };

inline constexpr std::string_view kHashCommentExtTable[] = {
".py", ".pyi", ".sh", ".bash", ".zsh", ".rb", ".pl", ".cmake", ".yml", ".yaml", ".toml", ".r", ".jl"
".py", ".pyi", ".sh", ".bash", ".zsh", ".rb", ".rake", ".jbuilder", ".pl", ".cmake", ".yml", ".yaml", ".toml", ".r", ".jl"
};

inline LineSyntax lineSyntaxFor( std::string_view path )
Expand Down
Loading