Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ around and reading whole files.
***Paddle out with a map.***

<details>
<summary><b>Fifty years of software-engineering results, and research from last month.</b> 43 repositories and 69 papers folded — McCabe (1976) through to <b>seven papers published in the last two months</b> — each row in <a href="docs/LINEAGE.md"><b>docs/LINEAGE.md</b></a> naming the lesson taken and the file it lives in, all of it put into a single blazing-fast compiled executable</summary>
<summary><b>Fifty years of software-engineering results, and research from last month.</b> 46 repositories and 69 papers folded — McCabe (1976) through to <b>seven papers published in the last two months</b> — each row in <a href="docs/LINEAGE.md"><b>docs/LINEAGE.md</b></a> naming the lesson taken and the file it lives in, all of it put into a single blazing-fast compiled executable</summary>

Beside those sits a labelled survey of **237 tools** that contributed nothing and says so. The two
sets are disjoint by construction, so they add rather than nest — a tool that gave a lesson is never
Expand Down Expand Up @@ -1647,7 +1647,7 @@ timing-only, and `pmccheck`'s inactive arm now proves that was truly the case.
<summary>43 repositories, 69 papers and a 237-tool survey — and the study where search over a pre-built index beats a delegating planner <b>65.2% to 46.2%</b>, at under half the cost</summary>

Almost none of the ideas here are new; the combination and the constraints are. Lessons folded from
**43 repositories and 69 papers** into one deterministic executable, alongside a labelled
**46 repositories and 69 papers** into one deterministic executable, alongside a labelled
survey of 237 tools that folded nothing and are catalogued separately — the two sets are disjoint,
so they add rather than nest. The row-by-row ledger, each with the lesson taken and where it lives, is
[`docs/LINEAGE.md`](docs/LINEAGE.md). Those three counts are derived from that document's own tables
Expand Down
10 changes: 7 additions & 3 deletions docs/LINEAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ licence in [`THIRD_PARTY.md`](../THIRD_PARTY.md). First-party code under `src/`
third-party code lives under `third_party/` and keeps its own licence. Citing a paper means the idea
was read and applied, not that any of its text or code is here.

**The counts, derived from the tables below:** **43 repositories** and **69 papers** are folded, and
**The counts, derived from the tables below:** **46 repositories** and **69 papers** are folded, and
a labelled survey of **237 tools** contributed nothing and says so. **The two sets are disjoint by
construction, so they add rather than nest:** a tool that contributed a lesson gets a row in §3a and
is never repeated in §3b, which makes the field study 43 folded *plus* 237 surveyed — not 43 picked
is never repeated in §3b, which makes the field study 46 folded *plus* 237 surveyed — not 46 picked
out of 237. `test/readmedriftcheck.sh` re-derives all three numbers from these tables on every run,
fails if the README's sentence disagrees, and proves the disjointness itself (arm E6) rather than
taking this paragraph's word for it. Arm E9 checks this second restatement of the pair independently
Expand Down Expand Up @@ -205,7 +205,7 @@ shipped target links, and it is named in the near-miss paragraph below rather th
| [aider repo-map](https://aider.chat/2023/10/22/repomap.html) | Rank a whole-repository symbol map with PageRank over the reference graph, and hand an agent the map rather than the files. This is the direct ancestor of the default run. | The default ranked map; also the interpreted-versus-compiled comparison arm in the head-to-head ([`EVALS.md`](EVALS.md) §2) |
| [ctags](https://ctags.io/) | The durable unit of code navigation is a tiny fixed record — name, kind, and where it is — not a document. | The `<s t= n= id= k=>` symbol row: kind, name, canonical id, and a rank, nested inside its `<f p=>` file element so the path is written once per file. Line numbers are the one part of the ctags record deliberately dropped from the map — a line number goes stale on the next edit, and the map is a thing an agent rebuilds per turn |
| [PyDriller](https://pydriller.readthedocs.io/en/latest/deltamaintainability.html) | The DMM paper states the model; the reference implementation states the CONSTANTS. The three low-risk boundaries (15 lines, cyclomatic 5, 2 parameters) and the exact good/bad asymmetry were read out of `pydriller/domain/commit.py` rather than re-derived from prose, and the 0/0 case returning `None` is where `--dmm`'s UNAVAILABLE token comes from. | `--dmm`'s thresholds and `scoreProperty` (`src/dmm.h`); the deviation — volume is physical line span where PyDriller uses lizard's non-comment `nloc` — is disclosed on every report as `size_metric="physical-loc"` |
| [Zoekt](https://github.com/sourcegraph/zoekt/blob/main/doc/design.md) | Index trigrams and intersect posting lists: pick the rarest trigrams first, then verify candidates, instead of scanning files. | The substring and regex index behind `--grep` and `--regex` (`src/search.h`) |
| [Zoekt](https://github.com/sourcegraph/zoekt/blob/main/doc/design.md) | Index trigrams and intersect posting lists: pick the rarest trigrams first, then verify candidates, instead of scanning files. | Cox's regex→trigram query, evaluated per FILE as a sound prefilter for `--regex` (`src/search.h`). The posting-list index itself was built, measured — 1860 ms / 814 MB to index a 2,815-file tree for ONE query — and removed (P3, 2026-07-27); the persisted form was priced again in the tgrep row below and refuted a second way |
| [ripgrep](https://github.com/BurntSushi/ripgrep) | A scanner fast enough stops being something you run and becomes something that is always on — and smart committed defaults beat configuration. | The name; the committed crawl skip-list rather than a per-repository ignore file (`src/ingest.h`); the warm-run latency target |
| [ast-grep](https://github.com/ast-grep/ast-grep) | Metavariable patterns over the syntax tree are a better query surface for code shape than regular expressions, and they make lint rules user-authorable. | `--match=QUERY`, and the YAML rule shape read by `--lint-rules=DIR` (`src/lintrules.h`) |
| [Semgrep](https://semgrep.dev/blog/2024/modernizing-static-analysis-for-c/) | Useful analysis is possible without include resolution or type information — own that band explicitly rather than apologising for it. | The syntax-only scope of `--lint`, stated as a limit rather than implied |
Expand Down Expand Up @@ -243,6 +243,10 @@ shipped target links, and it is named in the near-miss paragraph below rather th
| [codesight](https://github.com/Houseofmvps/codesight) | A per-facet write budget sized to roughly one screen of prose (~300 tokens per generated article) generalises to a SHARE floor: the least a document can be given and still be worth serving when one fixed budget is divided among several competing documents — distinct from the absolute last-resort minimum, which is a different, smaller number. | `kRecallShareFloorBytes = 900` in the water-filling recall budget (`src/recall.h`) |
| [cocoindex-code](https://github.com/cocoindex-io/cocoindex-code) | Staleness is not only "does the index still describe the tree" — already solved here — it is also "can THIS BINARY read this artifact": a foreign format, parser, or architecture version has to refuse cleanly and NAME why, not misread silently. | `--doctor` check 7's `<c n="index-cache">` row and the named `CacheReject` refusal enum (`src/ingest_cache.h`). **Second lesson, same repo, taken 2026-09-06:** when the question names a file, that file's own declaration/definition partner is the answer far more often than the largest thing that transitively depends on it — measured, cocoindex returned `db/wal_manager.h` as result #1 in 55 B where `--situ` missed it entirely in 3,104 B. Now surfaced ahead of the transitive list in `--situ`. **codanna** reached the same incremental-as-a-contract framing independently and is credited here rather than given a duplicate row, because the lesson and the artifact it points at are the same one |

| [tgrep](https://github.com/microsoft/tgrep) | Two lessons, and the first is the one an agent feels: **a search tool must not make you learn a second grep.** tgrep enforces ripgrep parity with a 2,530-line parity suite and a 5,768-line compatibility suite and documents every remaining divergence by name. Measured against that standard, `--regex`'s `^` and `$` were FILE anchors in a verb whose every answer is a line — `--regex='^#include'` returned 1 hit over `src/` where `rg` returned 1,648. The obvious repair, `std::regex::multiline`, faults inside libc++ (it reads one byte before the buffer at offset 0; 8 of 10 runs crashed, and twenty plain-build gates passed on the crashing binary where one ASan run would have named it), so the scanner now searches one LINE at a time, which is what grep, rg and tgrep do; post-fix parity with `rg` is exact on five anchored patterns. Second lesson, from tgrep's 64 MiB size cap: **state what a cut COST, not only that one happened** — tgrep prices its cap in the same paragraph as its benefit, where `--grep` printed `complete="1"` over a corpus whose built-in denylist had silently removed `third_party/` (33 hits served against `rg`'s 78 on this repository). Taken from the 2026-09-09 head-to-head (`bench/tgrep-h2h/`, five rungs from 159 to 182,555 files), which also priced the RESIDENT form of the Zoekt row above: the crossover Q* is 9.5 queries against `rg` at 2,240 files and 2.5 at 182,555 against a measured median of 26 grep-class calls per session — decisive — and yet neither half of tgrep's margin is available here: the larger half is a resident file-CONTENT cache a one-shot CLI cannot have (G5; on a query whose plan narrows nothing, the server still beats `rg` 15×), and the portable half, posting lists in the warm cache, is **refuted by measurement**, because `startGrepScanPrefetch` already runs the scan concurrent with the graph build and the ingest wins that race at every rung. What that measurement pointed at instead was ripwire's own: a warm-ingest floor that was super-linear (40 µs/file at 15,865 files, 938 µs/file at 182,555) — answered the same day by the profiling lane as the CHA-lite cone rebuilt per call and memoised (`ChaConeMemo`, `src/graph.h`; warm llvm `--grep` 159.7 s → 9.2 s), which moves this row's Q\* against ripwire-warm at the top rung from 0.1 to ≈1.7. | `src/search.h` (`grepScanText` line-at-a-time, `kGrepRegexSyntax`), `src/verbs_grep.h` + `src/mcpverbs.h` (`corpus_pruned_dirs=` on the `<grep>` root, CLI and MCP), gate `test/grepanchorcheck.sh` (arm I is the crash regression); the harness and crossover table in `bench/tgrep-h2h/` and [`EVALS.md`](EVALS.md) |
| [codeburn](https://github.com/getagentseal/codeburn) | Measure the thing you claim to optimise, in the unit you claim it in, and mark every place the number is an estimate rather than a reading. codeburn prices 41 agents' token usage from their own logs, carries a per-call `costIsEstimated` flag end-to-end through its cache, and surfaces an unpriced model rather than rendering `$0` as free; its own defect is the same shape it exposed here — the flag reaches three of its ~eight rendering surfaces. ripwire's `est_tokens` had the identical gap: gated for determinism and monotonicity, never for accuracy, and absent on 16 of 25 verbs including every navigation verb. Folded as the missing instrument, not as code: `est_tokens` against a real tokenizer per verb (median +15.9% / +18.5% over-read, range −18.4% to +41.7%, driven by document SHAPE — rows at 2.4 bytes per token, legend prose at 4.7 — not by the corpus language the rate is keyed on), the legend's share in TOKENS beside the byte claim `--help` publishes (`--impact`'s ≥50% saving holds in bytes and is 39.4% in tokens), and a whole-loop ledger over 78 local transcripts: ripwire answers are 42% of retrieval calls and 4.3% of retrieval tokens, and cache reads are 98% of everything billed, so an answer is re-paid once per remaining turn and a per-call price sees only the first payment. The negative lesson is load-bearing: codeburn prints COST, and cost is the wrong unit here — its price table is an unpinned network fetch and a number that goes stale in the artifact — so `est_tokens` stays the unit and no cost surface was built. | `bench/tokenaudit/` (`sweep.py`, `pin.py`, `loop_ledger.py`); the calibration band `test/tokenbudgetcheck.sh` #18 over the frozen `test/estcalibfix/` and `test/estcalib.manifest` (no tokenizer at gate time); the corrected §H7 sentence in `src/serialize.h`; [`EVALS.md`](EVALS.md) "`est_tokens` against a real tokenizer, and the loop the per-call number cannot see" |
| [markitdown](https://github.com/microsoft/markitdown) | Its README states the privilege model of a converter that shells out — it runs "with the privileges of the current process" — and tells callers to use the narrowest entry point. Applied to ripwire's OWN shell-outs rather than to the markitdown bridge it already carries: a PATH shim logged 82 read-only `git` calls across a 13-verb sweep, all inside the analysed checkout, where a hook-form `core.fsmonitor` in that checkout's `.git/config` is a command git runs on every one of them — a fixture hook fired three times per `--situ`. Neutralised at one site before any thread, disclosed on stderr and in `--doctor`, git's builtin boolean daemon left alone, and a tiered local-config pre-scan keeps the warm map at 52.7 ms where one git config probe per run cost 9.9 ms of it. Surveyed and NOT folded for the plain-text prose tier that landed beside it: markitdown has no `.rst`/`.adoc`/`.org` converter either, and its `.txt` acceptance is the generic catch-all a three-corpus census refuted (14–23% prose) — `.rst/.adoc/.org/.mdx` joined the markdown grammar tier on ripwire's own measurement (rst title underlines are setext; heading-tiled served 15/15 against 9/15 for one whole-file unit on the astropy docs), not on markitdown's. Turning its bridge on for binary formats was REFUTED with a design of what would have to be true first: the extractor's version in the cache key, `prov=` on the row, a named `extractor_missing=` instead of the silent zero the live bridge produces today, and opt-in. | `src/githarden.h`, `src/main.cpp` (one call after `parseArgs`), `src/verbs_doctor.h` (`git-config-trust`), `SECURITY.md`, gate `test/githardencheck.sh`; the prose tier's one vocabulary in `src/docparse.h` and its grammar rows in `src/ingest_crawl.h`, gate `test/textdocscheck.sh` |

**Read and not folded, and worth naming because they are the near misses.** A scoped-snippet view
with scope breadcrumbs — the one rung of the detail ladder that is still missing here — was designed
against `grep-ast`'s TreeContext and never shipped. `graphify` contributed a measured head-to-head
Expand Down
4 changes: 2 additions & 2 deletions present/deck5_ripwire_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ function row(s, y, h, cols, opts={}){
kicker(s, "// standing on giants", AMBER);
title(s, "The research inside — classic and current");
s.addText([
{ text: "43 repositories + 69 papers folded", options: { color: TEXT, bold: true } },
{ text: "46 repositories + 69 papers folded", options: { color: TEXT, bold: true } },
{ text: " · and a labelled survey of 237 tools that contributed nothing, which says so — every row with the lesson taken and where it lives: docs/LINEAGE.md", options: { color: MUTED } },
], { x: MX, y: 1.58, w: 12.0, h: 0.34, fontFace: SANS, fontSize: 13, margin: 0 });
const classics = [
Expand Down Expand Up @@ -972,7 +972,7 @@ function row(s, y, h, cols, opts={}){
["every --flag named here exists", "bash test/deckcheck.sh"],
["74.7% fewer element bytes", "bash test/showcasecapturecheck.sh"],
["569 gate scripts", "bash test/manifestcheck.sh"],
["43 repos · 69 papers · 237 surveyed","bash test/readmedriftcheck.sh"],
["46 repos · 69 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/"],
["the oracle round", "bench/headtohead/r9-2026-08-09/RESULTS.md"],
Expand Down
38 changes: 38 additions & 0 deletions test/readmedriftcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,44 @@ else
ok "(E4) mutation control: a fabricated repository count ($bad_repos) is correctly seen as disagreeing with the derived count ($d_folded)"
fi

# (E2b) EVERY copy of the README pair must agree — one distinct value, however many times it is printed.
# (E2) extracts the FIRST "<M> repositories and <P> papers" and stops (`head -1`). README carries the pair
# TWICE (the <summary> line near the top, and the bolded sentence in the honesty section ~1,600 lines
# down), so a second copy that drifted was a published number with NO instrument on it — the exact
# merge-clean-but-wrong shape the 2026-09-09 landing round hit four times over (a gate count carried by
# two lanes, a stacked count conflicting outright, a printf-parity row, shapingflagcheck's read-site
# pin). `sort -u` over ALL matches asserts one distinct pair, which also catches a FUTURE third copy
# that disagrees; the copy count is reported, never pinned, so adding a copy is free and drifting one
# is not.
pairs_from() { # $1 = file → every distinct "<M> repositories and <P> papers", one per line
sed 's/\*//g' "$1" | tr '\n' ' ' | tr -s ' ' | grep -oE '[0-9]+ repositories and [0-9]+ papers' | sort -u
}
readme_pairs="$( pairs_from "$README" )"
readme_pair_copies="$( sed 's/\*//g' "$README" | tr '\n' ' ' | tr -s ' ' | grep -oE '[0-9]+ repositories and [0-9]+ papers' | wc -l | tr -d ' ' )"
readme_distinct="$( printf '%s\n' "$readme_pairs" | grep -c . )"
if [ "$readme_distinct" -eq 1 ]; then
ok "(E2b) README.md's $readme_pair_copies copies of the lineage pair agree on one value ($readme_pairs)"
else
no "(E2b) README.md prints $readme_distinct DIFFERENT lineage pairs across $readme_pair_copies copies — every copy must agree: $( printf '%s' "$readme_pairs" | tr '\n' ';' )"
fi

# (E2c) mutation control for (E2b): mutate ONLY THE SECOND copy in a temp copy — the one (E2)'s `head -1`
# can never see — assert the mutation took, and re-run the identical extraction; it must now report two
# distinct pairs. A control that mutated the first copy would be caught by (E2) and prove nothing about
# this arm.
first_pair="$( printf '%s\n' "$readme_pairs" | head -1 )"
wrong_pair="$( printf '%s' "$first_pair" | sed -E "s/^[0-9]+/$(( d_folded + 7 ))/" )"
awk -v pat="$first_pair" -v rep="$wrong_pair" 'BEGIN{c=0} { if (index($0, pat) > 0) { c++; if (c == 2) { sub(pat, rep) } } print }' "$README" > "$TMP/README_second_copy_bad.md"
if [ "$readme_pair_copies" -lt 2 ]; then
no "(E2c) mutation control: README.md carries only $readme_pair_copies copy of the pair, so a second-copy mutation cannot be staged — the control is void, not passed"
elif [ "$( grep -c -F "$wrong_pair" "$TMP/README_second_copy_bad.md" )" -ne 1 ]; then
no "(E2c) mutation control: the second-copy mutation did not take ($wrong_pair not found exactly once in the mutated copy)"
elif [ "$( pairs_from "$TMP/README_second_copy_bad.md" | grep -c . )" -eq 2 ]; then
ok "(E2c) mutation control: a drifted SECOND copy ($wrong_pair) is seen as a second distinct pair — the arm fires where (E2) alone would stay green ((E2) on the mutated copy still reads: $( counts_from "$TMP/README_second_copy_bad.md" | awk '{print $1}' ) repositories)"
else
no "(E2c) mutation control: a drifted second copy was NOT seen as a distinct pair — the arm cannot fail"
fi

# (E10) LINEAGE's DISJOINTNESS SENTENCE must carry the same numbers as its own header.
# E5 checks the header. Nothing checked the sentence two lines below it that EXPLAINS the header --
# and it had drifted a full round behind: the header read 36 repositories / 231 tools while the
Expand Down
Loading