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
3 changes: 0 additions & 3 deletions .ripwire_quality_acks
Original file line number Diff line number Diff line change
Expand Up @@ -1567,10 +1567,7 @@ ack verbosity 6302e2e27e23bcde 64 cid=7202bbc7db7cc1da C1 F-06/F-07/F-10 (the li
ack verbosity 639de1c3670999f9 185 cid=ffcb81de788c329a C1 F-06/F-07/F-10 (the listing-paging round): three listing verbs learn to disclose and page their row listings, and every gating row is that one change. api-surface 14 = ONE trailing DEFAULTED parameter each (an int pageOffset, an McpPageArgs window, a SituPageArgs, or the next= invocation a header now carries) on the emitters that must be TOLD their window — writeFlags/writeGate, writeCappedRows/writeCappedList/writeFlip/writeFlipHeader/writeFlipLights, computeFlip, nearestGateNames (which gains its cap and its TOTAL, the disclosure itself), situShowingNote/writeSituation, and the three MCP twins flagsText/flipText/situationDiffJson; additive by construction, every pre-existing call site compiles unchanged, and the alternative — a second capped emitter per verb — is the drift this repo removes rather than adds, because two emitters that disagree about a window can drop the row that IS the answer. verbosity 3 = kDocDriftLegend +20 lines and writeDocDriftPage +10 are the in-band vocabulary a reader needs to read shown_failed=/failed_capped=/failed_total= where they meet it (the rationale and the next= scan were already hoisted OUT of the body into their own function and comment, which took the complexity row to zero and the LOC row from +48 to +10); dispatchMcpLine +12 is two pagedResult wrappers on a pre-existing 1376-line dispatcher this lane adds to rather than creates. complexity 1 = the same dispatcher, +9 on a base of 518. duplication 1 = flagsText | flipText at 110 tokens, down from 131 after the shared mcpRowCap fold; the residual is getIndex + compute + captureXml, the shape EVERY index-backed MCP twin in this file has, and merging two verbs that return different results behind one entry point would be worse code than the clone. short-horizon-churn 19 = this lane's own footprint across cli.h/docdrift.h/darkflags.h/flipimpact.h/situ.h/mcp*, plus cli.h symbols three other lanes touched the same day; none foreign, none thrash. | prior: wave-3 close, H7 hosts: runCrossRef hosts the --plan and --stray-content refusal sites the fix routes through the shared sentence (verify-wave2 lanes edited it days earlier — the churn is the fix's, self)
ack verbosity 685ade09a168535e 96 cid=124bb29c88050ae1 Same three sites as the complexity rows and the same reason: LOC grew where a disclosure or a real computation landed (dispatchMcpLine +71 over five pagedResult arms and the legend refusal; symbolQueryJson +26 for the attributes the CLI twin has always carried). None of it is repetition a helper would absorb. | prior: T1 completeness claims (complete= on grep/whereis): the +1 on streamBlobs is the deliberate DEFAULTED StreamBlobStats* param (null-object sink inside, no per-site null test; every existing caller byte-identical) so whereis can prove its scan exhaustive before claiming; cx/LOC on streamBlobs/computeWhereis/writeWhereisPage/emitGrepReport is the claim computation plus its in-band legend (the honesty text IS the feature); churn=self on those plus grepCollect/dispatchMcpLine is this lane own edit window. Gated red-first by test/completecheck.sh (24 arms, 10 red pre-fix; mutation arms force cap/offset/budget/unreadable-file/regex-mode/oversized-blob and assert the attribute VANISHES); full plain suite green, 21 touched-family gates green under ASan+LSan, determinism x3, xmllint clean
ack verbosity 6979fa794f2a5154 423 cid=9132efbcc6dfcbb7 now=423 was=420 p=src/ingest_sidecap.h:1706 fn-literal bodies: captureTagsFacts gains the defBodyNodeOf call that hands a literal-bound name its literal (the @name and Lang ride along) and reads params/cx from it: a +3 cx / +3 verbosity call site at the def-extraction seam | prior: ruby-attr class-DSL lane (review round; kParserVer 119->120): duplication/new-clone elixirArguments|elixirTarget is token-shape coincidence only - elixirTarget is the shared fieldIdentifierText primitive plus a null guard, elixirArguments reads a different field with no identifier gate; no shared logic to lift. captureTagsFacts +1cx/+4verb is the two-line gated call site of the inline-visibility lift.
ack verbosity 6a38d70787d09e64 74 cid=f6a0c09dfc153ece Kotlin port (PR #126): the leading whitespace sample is walked by codepoint (jsonesc::utf8SeqLen) so invalid UTF-8 folds into errNodes/errBytes, deduplicated against the ERROR spans tree-sitter recovery already counted; without it a garbage byte run swallowed by recovery reads as a healthy file in --skipped.
ack verbosity 6acbcaa854eada23 289 cid=e5c009ae9a0d8393 preloaded-corpus hoist: lexicalScores/lexicalScoresTiered gain one optional defaulted preloadedFileText param so a caller scoring many queries against one tree reads the corpus once instead of per call (--eval-retrieval was ~11.8M file opens/run, 48% of its CPU in the kernel). api-surface rows ARE the intended additive change; short-horizon-churn is this session's own edits to those two functions, not instability. Scores proven byte-identical on an identical tree.
ack verbosity 7004309695fb79f1 265 2026-08-15 harvest wave-level pass (orchestrator): 12-lane wave measured as one delta vs origin/main 4b9386c per verifier finding 6. All 21 gating rows triaged individually: emitGrepReport/grepHitsJson/runCallHierarchy/runDefaultMap/collectSources/printUsage/Config/runMcpHttp = feature absorption by design (grouping+boolean+corpus disclosure, file-root, bodyless_defs+legend, estimator guard, new flags), each converged and gate-verified at lane level; short-horizon-churn rows = single-wave multi-lane edits of shared hubs, process artifact; sym=main rows are main.cpp::main growth mislabeled to analyze.py by the bare-name canonId collision (path-qualified keying fix d593de3 still unpushed). emitGrepReport cx 25->63 flagged as W2 split candidate in PLAN round record.
ack verbosity 7051b3950aaf4c14 82 cid=7919a3d486bba416 lane B1 cap disclosure: doc_mentions_capped= is contracted to be PROVABLE, never guessed, and that proof is the +6/+16. It is the in-loop test that a doc below its anchor's lift target was the one a cap turned away, plus docLiftWasRefused for the other half of the total cap, which ends the OUTER loop over anchors already consulted. A one-line flag would instead say 'there might be more', which is the fabricated fact in the other direction.
ack verbosity 719e8441be665024 959 cid=e508c8076e15f8e3 lane win-build-green (review F1/F2/F4): ci.yml's jobs key grows because the windows job stopped asserting exit codes and started asserting answers — a --version SHAPE check (semver + emit= + built_from=), fixture-map floors that separate a real crawl from the 951-byte empty one a Windows path bug produces, ctest --no-tests=error, and the cl leg's own expectation (configure must succeed, build must fail, no D8xxx flag regression hiding behind the seam, every erroring file ours, first error one of the extension codes) built with -k 0 so its log is the inventory. Every added line is an assertion or the reason for one; shrinking this key means deleting the checks the review asked for. Same shape as the release.yml jobs acks above.
ack verbosity 73ac37ff2580b0b0 86 cid=b07db8431c1b7c18 R1 identity round (harvest Wave-2 R1, 2026-08-24). Five gating rows, ONE change: finding identity now survives a rename or a move. (1) runQualityDelta complexity 201->205 and verbosity 419->462: the +43 lines are overwhelmingly the LEGEND this repo requires — the identity mechanism is a claim about what an ack means, so the report has to say what it rested on (both mechanisms, both truncation caps, the two per-route counters), and legendcoveragecheck arm (A) requires every new attribute be named there. The code added to this dispatcher is three lines: the ledger is now taken from the already-healed basis instead of re-read (re-reading it here would undo the healing), one countAckRescues call, and one call to quality::identityDisclosure — which is itself an EXTRACTION made in this lane precisely because --quality-delta flagged the inline version. The residual +4 complexity is the cid ternary at the ack-write site. Decomposing runQualityDelta is its own round, recorded as such by the W2-E ack above and unchanged by this one. (2) resolveDeltaBasis verbosity 73->86 + churn=self: the two healIdentity calls (ref-pair and working-tree arms) and the comment explaining why the healing must precede computeDelta — heal the baseline after the delta is taken and the delta has already been computed against the stale identity. churn=self on it and on mergescout::injectFileLevelFallback is this one edit window, not a history signal. (3) injectFileLevelFallback: its hand-rolled fopen/fseek/fread/fclose block was retired onto docparse::detail::readWholeFile, the canonical whole-file read, after this lane extracted quality.h's copy and the reuse-decline kind reported the pair as a 320-token clone. Re-read before the swap: short read or ftell failure clears the buffer and the file contributes nothing, byte-identical to what it replaced. Gate: test/identitycheck.sh, 19 arms, 9 RED on the pre-lane binary.
ack verbosity 763ff87870373241 84 cid=0f3e66f03f7be1f1 round ec5e3c3..HEAD, the MCP door across L6 (batch two-grammar), L8 P9 (post_check on the edit verbs), V2 F3/F7/F8/F9 (receipt keys, batch attribution, top-level array reader, legend present-but-empty) and L7 P1 (legend on 16 verbs): dispatchMcpLine/runBatchSub/runCliEdit are the one dispatch each of those lanes had to pass through | prior: capture-audit 2026-09-04 wave-1 close, lane L5 (refusal population, lane-L5.md) + lane L0 H13: guard code and its reasoning, not accidental growth — H6 file-list refusal (writeSituation/dispatchMcpLine/runChangeViews), H7 empty-selection refusals (runCrossRef flags/stray-content, evalStray badRefs, writeWhereisPage line-seed + near-miss), M7 named-file inputs + M8 --since validated once before any verb (main), M9 edit-verb refusals (runCliEdit/nearestNames/resolveOneForEdit), M20 seed disclosure (serialize + MapAnnotations::SeedDisclosure, packLego defs=, packConnect terminal defs=), F10/F14 empty list items (runPath/packConnect). L5 left these un-acked on purpose (shared-ledger race, H10); acked at close against the lane's own ec5e3c3 measurement
Expand Down
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,56 @@ not published here — see `docs/EVALS.md` for the instruments behind the headli

## [Unreleased]

### Added — a Ruby `db/schema.rb` renders its columns as Section definitions
A Rails schema is recognized BY CONTENT, never by path: a Ruby file whose tree holds a
`create_table "x", … do |t| … end` call — the call's do-block carries one block parameter — is a
rendered schema, wherever it lives. Each `t.<type> "name"` / `t.<type> :name` in a table block mints
ONE `SymKind::Section` def at `Lang::Ruby` — the data-kind slot a doc heading or YAML key already
occupies (model.h: a Section's isolation is a language property; the Ruby ones are still no call
edges) — span = the name token, both quote spellings and the `:symbol` form. Rails-generated attribute
uses (`product.price`) then resolve to the column as a definition: it appears in `--uses`, `--grep`,
`--whereis` and the map. THE COLUMNS ARE DEFINITIONS ONLY, by maintainer decision: buildGraph's
byName skips Section-Ruby, so a column admits NO call edge and no PageRank weight — an untyped
`response.code` must not become a table's caller, and 200 `name` columns must not damp a model's real
`def name` (both measured at review; edges may return behind an evidence rule, e.g. a receiver proven
to be the owning model). The id rule covers the grounded spellings: no id column/spelling → an
implicit `id` def (the anchor is the table-name string — no `id` token exists there); `id: false` →
no id def; `id: :uuid` → an `id` def at the pair key (the uuid is a TYPE of the id column, never a
column of its own; the type is not modelled); `primary_key: "x"` → a def named the string instead.
An ARRAY or symbol `primary_key` (a composite key, or a hand-written migration) mints NO implicit id —
the rendered composite columns are the block's own explicit `t.<type>` lines. `t.timestamps` mints
`created_at` AND `updated_at` (the DSL names them literally, symmetric with the id rule) — the two
defs anchor at the method token's edges. The DSL CALLS keep their reference posture exactly like the
attr family: `string`/`datetime`/`create_table` stay external-surface names. Duplicate columns across
tables stay SEPARATE defs (same name, distinct identity bytes): `id` on N tables is `defs="N"`, and
the map row merges them with `overloads`, never hiding the multiplicity. MIGRATIONS never interfere: a
class-wrapped create_table — the migration shape, string- or symbol-named — is refused by a
class/module-nest gate (a rendered schema's tables live at file level or under `Schema[].define`, never
inside a class body), so the rendered `db/schema.rb` stays the ONE source of column names and indexing
the migration beside its schema cannot double any def; `add_column` / `remove_column` /
`change_column` are argument data and read nowhere — a column added then dropped never registers
(pinned by the three migration fixtures). Rails 8's `db/queue_schema.rb`, `db/cache_schema.rb` and
`db/cable_schema.rb` are matched by the same content gate. kParserVer lands at 144 — carried as 126
(extraction facts changed; carried 122 pre-rebase and renumbered for the train-20 `.astro` collision,
then to 126 at review; the 0e5fdcd2 merge kept 126 per the maintainer, but trains 22-25 landed
128-143, so this merge renumbers to 144; no record layout change — kCacheVersion stays 28 and
kQSnapCacheScheme stays 17).
Gate: `test/rubyschemacheck.sh` on `test/rubyschemafix/` — schema text from a real, running Rails
8.1 app's `bin/rails db:schema:dump` (verified `db:schema:load`-able), original domain tables scrubbed
to `spike_*` names; two spellings no dump emits are restored by hand and marked in-file (`id: :uuid`,
which that dump actually failed on, and a literal `t.timestamps`). Stated capture floors, each pinned
by a gate arm: `t.index` / `t.references` / `t.belongs_to` / `t.polymorphic` / `t.check_constraint` /
`t.exclusion_constraint` / `t.unique_constraint` name no column (a `t.references`/`t.belongs_to` mints
no `<x>_id`, and a `create_join_table` mints nothing — raws dumps render these as explicit columns);
a column call must be ON the block parameter (`helper.string "x"` names nothing); a symbol-named table
(`create_table :users`) is a migration spelling, not a schema surface; `where("price > ?")` string
fragments stay opaque; the picker splits honestly (`rec.name` on a plain local and a rich `X.new.name`
receiver are `graph_ambiguous`, `self.name` inside the defining class pins its own def). The
before-evidence: on the pre-change binary every column was `defs=0 external=1` — the fixture's
`--uses=name` read `defs="10"` (9 attr/def defs plus the YAML key) with the schema columns invisible; it
now reads `defs="19" external="0"` and the column uses resolve to definitions only.


### Changed — a Ruby call to self, or on an instance the code builds, answers from its own side: an instance never reaches `def self.m`

The entry below left one floor open, (i). A call to self, or on a receiver the code builds, read a class's defs from both
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2082,9 +2082,14 @@ wrong, and it has. These are the results that say so, all in-tree, all published
### In the tests

<details>
<summary><b>671 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>672 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 **671 gate scripts** and is the authoritative list; <!-- gatecount -->
`test/regression.sh` names **672 gate scripts** and is the authoritative list; <!-- gatecount -->


<summary><b>672 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 **672 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
Loading
Loading