Repository navigation
integration: train 2 — param receiver binding (#248), untyped receiver locality + final-segment disclosure (#254), std:: field compose (#257) - #265
Conversation
…he caller's own class
`int Decoy::plainCaller( Target& other ) { return other.pick( 1 ); }` answered
--callees=plainCaller with ONE edge to Decoy::pick: precise, no amb=, wrong. Rule 2 narrowed
a receiver only through a typed local (LocalBindKind::Type); a parameter's written type
(ParamType) was captured but read only by collectFieldUseSites, so the call fell through to
the name ladder and the S6-C locality tie-break gave the caller's own class the scope credit
(pin census: mech=locality, 2 -> 1).
The fix: Rule 2, and CHA-lite through the same lookup (Narrower::recvVarTypeName), reads
ParamType records LEXICALLY. graph.h buildScopedRecvDecls lists, for every name with a
ParamType record, all its declarations in the definition (each VarDecl with its scope span)
and attaches each Type/ParamType record to the declaration whose VarDecl shares its record
position (Binding::startByte, new, in the padding after `kind`: sizeof unchanged, pinned).
The innermost declaration covering the call site decides; an untyped one, a tie, or no
covering declaration answers nothing. Names with no ParamType record keep the flat varType
table byte-identically.
Why not the obvious fold into varType: measured first. It fixed arms 7/8/11/15 and minted
three NEW precise wrong edges on the gate fixture (arms 12-14: a range-for variable's type
reaching a later `auto` loop of the same name, a same-named field read after the loop, a
parameter hidden by an untyped loop variable), and arm 10's tombstone kept the locality pin.
Qualifier guard: a written type is its final segment and class names carry no namespace, so
`const std::map<K, V>& ref; ref.lower_bound( q )` narrowed to an unrelated in-repo `map` —
three such edges on a private 129,759-call-site C++/ObjC++ corpus. A declaration's qualified
written type now rides its Type/ParamType RawBind (importedName, ingest_binds.h
qualifiedNameText) and the lexical lookup refuses it: removes all three, forgoes 11 correct
narrows through qualified in-repo types (those keep main's answer). kParserVer 96 -> 97 (+
quality.h mirror): the record format is unchanged, its content is not, and a warm 96 blob
would narrow a qualified type. An include-visibility guard was measured first and rejected:
path-precise includes miss include-root spellings and it refused ~150 correct narrows there.
Measured, --pin-census --no-cache, main f8e6087 binary vs this change:
private corpus: 587 of 129,759 sites change target — 373 splits narrow (300 Rule 2,
73 CHA cone), 147 declined calls gain an edge (bound 80,432 -> 80,583), 66 pins/splits
move to the parameter's type, 1 edge lost (a friend function scoped inside its class
self-loops); 956 more keep their target, now decided by Rule 2. Every category sampled
and read against the source. Wall time within noise (3 cold runs each, 1.66-2.51 s).
this repo src/: 53 splits -> one Rule-2 pin; nothing else moves target.
Gate: test/narrowcheck.sh arms 7-18 (generated fixture). RED on main: 10 rows (7, 8, 10 x2,
11, 12, 13, 14, 15). RED on the flat-table fold: 10 x2, 12, 13, 14. RED on the lexical lookup
without the qualifier guard: 17. GREEN on this commit: 23 PASS, and under ASan.
Controls that encoded "a parameter has no binding" moved to an untyped `auto` receiver:
narrowcheck (control/param.cpp -> control/untyped.cpp), chacheck, chaconecheck g5,
localitycheck (its call no longer reached the tie-break it tests), resolverhonestycheck F9
(check_signal had gone vacuous on one edge). fieldnarrowcheck (h) 7 -> 6: shadowParam(
Decoy& m_x ) now resolves to the parameter's type; (s1) also asserts Pool::acquire is not
linked (red on main).
Out of scope, stated: an untyped receiver still reaches the locality tie-break; typed locals
keep the flat table and its qualified-type collision. The reported arity split on a typed
local (pick(int) + pick(int,int) for a 1-arg call) is B2.2's documented argCount > params
rule and reproduces identically on the bare-name ladder.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CHANGELOG.md: both Unreleased entries kept (#240's Changed, this lane's Fixed). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ument constructor and a 30-complexity builder
quality-delta over the merge-base range reported gating=3 on this lane's own rows: ctorTypeOf's
byte-bounds tail cloned nodeTextOf (duplication + new-clone-of-reused-helper), and Narrower's
constructor went 4 -> 6 parameters against a bar of 5. Non-gating but real: the new
buildScopedRecvDecls at cognitive complexity 30, and bindsVisitNode 88 -> 94 with three new
parameters across pushRawBind/emitBind/emitDeclBinds.
- ctorTypeOf and qualifiedNameText read through nodeTextOf.
- ScopedRecvDecls is one struct holding the table and the bindings its indices point into, so the
Narrower takes one argument for both (5 parameters).
- buildScopedRecvDecls is three single-loop steps: addParamTypedNames, addRecvDeclScopes,
attachRecvDeclTypes.
- DeclType { name, qualified } travels as one argument. pushTypedBind is now the ONE record body
and pushRawBind a one-line wrapper with no qualified text, so pushRawBind and emitBind keep
their signatures, and declaredTypeOf takes the declaration branch's two ternaries out of
bindsVisitNode. (A first cut stamped importedName after the push, emitFnBind's shape — and
quality-delta reported it as a 70-token clone of emitFnBind.)
Zero behaviour change, measured: --pin-census and the default map on the private corpus are
byte-identical (cmp) to the previous commit's binary, as is the census over src/; narrowcheck,
chacheck, fieldnarrowcheck, resolverhonestycheck, fieldusescheck, shadowcheck and
cacheidentitycheck ALL PASS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
quality-delta --quality-delta=$(git merge-base origin/main HEAD)..HEAD reported gating=2 after the refactor: api-surface contract-change on Narrower::Narrower and its one call site in buildGraph (4 -> 5 parameters). That is the fix itself — the Narrower has to be handed the lexical declaration table — so it is acked through the binary (--quality-ack --ack-only=api-surface), which wrote exactly two +ack rows, one per symbol, and nothing else. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…d, a moved parser-version pin, two one-line verdicts Full suite at 17a9f5f: gates=632 pass=627 skip=2 fail=3, all three this lane's own. showcasecapturecheck (H): the 0.6.1 release capture publishes --at=src/graph.h:3406 as the FIRST body line of rankGraphTeleport, so it has zero slack — the ~100 lines this lane added to graph.h above it made 3406 resolve to buildGraph. The capture is the release PR's to regenerate (a lane recording it publishes local branch names), and the code had a better home anyway: the lexical table builder (buildScopedRecvDecls and its three steps) moves from graph.h to resolve.h, beside the ScopedRecvDecls type and Narrower::recvVarTypeName that reads it. graph.h's diff is now five lines in, five out, at the Narrower construction; rankGraphTeleport is back at 3404 on this tree. qschemetripcheck: its manifest hashes ingest_cache.h's kParserVer declaration, which moved 96 -> 97 with the quality.h mirror in the same diff (qextractionkeycheck green), so this is the gate's own re-pin case: UPDATE_GOLDEN=1, and the new pin equals the current= hash the suite printed. gateexitcheck (G2): narrowcheck's expectRows helper and arm 18 reported through a one-line 'A && ok || no'; both are if/else now. No behaviour change: --pin-census and the default map over the private corpus are byte-identical (cmp) to the fix commit's binary. qschemetripcheck, gateexitcheck, showcasecapturecheck, narrowcheck, chacheck, chaconecheck, localitycheck, fieldnarrowcheck, resolverhonestycheck, fieldusescheck, shadowcheck, fnptrcheck, cacheidentitycheck, qextractionkeycheck, manifestcheck ALL PASS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…caller's own class
`auto other = make(); return other->pick( 1 );` inside Decoy answered --callees with one
precise edge to Decoy::pick, no amb=. The S6-C locality tie-break excluded field-of-this,
field-of-var and super() receivers but kept every NamedVar receiver on the premise "a typed
var already narrowed above" — and a receiver no rule typed never narrowed. The scope-segment
credit then handed the same-file tie to the caller's own class.
The fix: a NamedVar receiver whose type no receiver rule (2, 2c, 2b) established keeps the
tie-break's credit only up to the end of the caller's FILE segment (`path::`), so same-file
and same-directory locality still count and the class segment does not. That covers an
untyped local, a member Rule 2b cannot read (`std::unique_ptr<Target> rep_; rep_->pick()`)
and a typed variable whose type defines no such method. `this->` and bare calls keep the
whole tie-break.
Measured first, with --pin-census --no-cache, the lane tip's binary against this logic built
behind a temporary environment switch (removed; the final binary is measured in the next
commit): rocksdb 121 call sites change target (114 locality pins -> splits, 7 splits widen),
a private C++ corpus 71 (51 + 20), django 72, rails 145 (119 + 26), this repo's src/, vue-core
and go/net 0. Samples read against the source: 14 of 14 rocksdb pins wrong, 14 of 16 on the
private corpus — mostly delegation (`rep_->Name()` in Wrapper::Name, `tree_.upper_bound( key )`
in btree_container::upper_bound); one right pin is now a 3-way split that keeps it.
Skipping the tie-break entirely for these receivers moved NO target on any of the seven
corpora, but relabelled every {caller itself, X} tier from locality to unique (262 rocksdb,
53 private, 24 django, 101 rails) and dropped its lpin= disclosure — so the file credit stays.
Stated floor, not closed: tier 1 still admits same-file candidates alone, so a delegation
whose true target lives in another file lands on a same-file namesake before the tie-break.
Gate: test/localitycheck.sh arms 5-9 on a generated fixture. RED on the lane tip: 5
(untyped local), 6 (member of an unreadable type), 7 (typed, no such method) — each a
locality pin to the caller's class. Arm 8 (file credit kept, mech=locality) is RED on the
skip-the-tie-break variant; arm 9 is the Rule-2 control. GREEN on this commit.
Controls moved for the reason the fix exists: localitycheck's HIGH-1 probe was an untyped
local that no longer earns scope credit, so it could not tell a byte-prefix tie-break from a
segment-aware one; it is `this->go()` in a class template with a dependent base now, plus a
census liveness row (pre=2). clsrecvcheck (B)/(C)/(E) asserted the caller-own-class pin
STANDS for `item.validate( v )`; they assert the honest two-way split now (the contrast with
the firing route is unchanged) and (F) reads ambiguous=3 with no locality pin. canoncheck's
comment describing the fixture is updated. chacheck, chaconecheck, resolverhonestycheck and
fieldnarrowcheck pass unchanged: their untyped controls are scope-less free functions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…esake, and an in-repo qualifier refused a parameter `std::map<int, int> table; table.find( k )` pinned an in-repo map::find: Rule 2's flat per-function table records a written type's final segment, and class names carry no namespace. The parameter-receiver lane refused every QUALIFIED parameter type for the same reason; typed locals, constructor-inferred locals and C++ assignments kept narrowing. Measured before choosing the rule, --pin-census --no-cache, lane tip vs switches (removed): refusing ANY qualifier on locals moved rocksdb 424 sites, a private C++ corpus 27, src/ 9. Joined to each receiver's qualified text: every rocksdb and src/ one was a non-std qualifier (ROCKSDB_NAMESPACE::Status, test::SleepingBackgroundTask, rw::notes::NoteIndex), every sampled one read correct, and it minted new wrong ladder pins where the refused narrow fell to a same-dir namesake (`value_slice.data()` -> MultiGetJNIKeys::data). The only wrong narrows it removed on the three corpora were six `std::map` locals on the private corpus. The same join on the lane's parameter guard: refusing only std:: instead moves rocksdb 94 sites (e.g. `WriteBatch::Handler* handler; handler->MarkCommit( xid )` off WriteBatchInternal::MarkCommit), private 12, src/ 5, all sampled correct but ONE: an `ankerl::unordered_dense::map<…>&` alias template that narrows to the in-repo map again. The fix: `std` is reserved to the implementation, so no in-repo class IS a std:: type. resolve.h namesStdType is the one predicate: the lexical (parameter) lookup refuses a std:: written type, and the flat table tombstones the variable on one (a tombstone, because the flat table cannot tell which declaration of the name is in scope). Every other qualifier narrows on its final segment again, parameters included. The C++ assignment `x = std::map<K, V>()` recorded no qualified text; it goes through pushTypedBind with declaredTypeOf's constructor DeclType now, so kParserVer 97 -> 98 (+ quality.h mirror): format unchanged, content changed. Stated floor, pinned by narrowcheck arm 24: a qualifier that is neither std nor the class's own namespace still narrows by name; closing it needs the namespace chain in Symbol::scope. Final binary (this commit, both fixes) vs the lane tip, --pin-census --no-cache: rocksdb 211 sites change target (117 locality, 94 qualified parameters; bound= 200,009 -> 200,036), private 88 (70 locality, 6 std::map locals stop narrowing, 12 qualified parameters), django 72, rails 145, src/ 5, vue-core 0, go/net 0. The assignment capture moved no site on these corpora. Wall time on rocksdb within noise (3 cold runs each, load avg 42: 1.69-2.19 s vs 1.73-2.80 s). Gate: test/narrowcheck.sh arms 17-24. RED on the lane tip: 19 (typed local), 20 (constructor local), 21 (assignment), 23 (in-repo qualified parameter), 24 (the floor: the lane refused it). RED without the assignment capture: 21. GREEN on this commit. Arm 17 moves from `ext::map` to `std::map` (the refused shape) and 22 is the in-repo qualified local control. quality-delta (working tree vs the previous commit): gating=0; a first cut's prefix-strip loop cloned lintdetail::ltrim and is gone (qualifiedNameText already strips a leading `::`). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…yped-locality The lane pushed a fix commit for three full-suite reds after this branch was cut; two of them bind this branch's change as well, and the resolution keeps both sides' intent. src/graph.h: the lane moved the lexical receiver-table builder to resolve.h so graph.h stays line-neutral above rankGraphTeleport (the 0.6.1 showcase capture seeds --at=src/graph.h:3406 with zero slack). Took theirs, re-applied this branch's std-guard comment to the moved block, and made this branch's own graph.h change line-neutral too (+9/-9 against the lane tip, rankGraphTeleport back at 3404): the tie-break rationale moves into resolve.h receiverLocalityCap (the cap itself, beside sharedLocality), the flat varType key uses the existing buildShadowKey (identical bytes), and the flat-table tombstone note joins namesStdType's comment. No behaviour change: --pin-census over src/, rocksdb and the private corpus is byte-identical (cmp) to f346283's binary. test/narrowcheck.sh: took this branch's arms 17-24 with expectNarrow's verdict as if/else (gateexitcheck G2, the lane's same fix to expectRows and arm 18). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… line this branch moved qschemetripcheck hashes ingest_cache.h's kParserVer declaration; f346283 moved it 97 -> 98 with the quality.h mirror in the same diff (qextractionkeycheck green). This is the gate's own re-pin case: UPDATE_GOLDEN=1, and the new pin (8ca11f67…) equals the current= hash the red run printed. kQSnapCacheScheme stays 12 and kCacheVersion 22 — record layouts and snapshot semantics are unchanged. The RE-PIN LOG entry says so, and names the 96 -> 97 move the parameter-receiver lane re-pinned without one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… class named string
`struct Record { std::string name_; int nameLength() { return name_.size(); } };`
pinned name_.size() to an in-repo `string::size` (census mech=receiver-rule, no
amb=). The field capture (ingest_relations.h captureFields) keeps a qualified
type's final segment, and all three readers of that record took `string` for
any in-repo class of the name: Rule 2b's field-type table, the HAS-A edges
(Record -> string), and the member index (--uses=string.len pinned name_.len and
this->name_.len). The previous commit refused a std:: written type for locals
and parameters; fields were the third place a written type is read.
The fix: a field's compose record carries the namespace its type was written in
as its qualifier (writtenTypeNamespace) — the (name, immediate qualifier) pair a
call ref already carries, so `std::string` is `string` in `std`. resolve.h
fieldTypeWrittenInStd is the one predicate; buildFieldNarrowTables records ""
for such a field and the HAS-A loop draws no edge. The member index reads the
same table, so it needs no change of its own. Every other qualifier narrows as
before (`store::Text body_; body_.size()` still reaches Text::size).
kParserVer 98 -> 99 + the quality.h mirror: format unchanged, content changed.
It records "" rather than skipping the field, because a skip is a measured
wrong answer: rocksdb's test_util/testutil.h `StringSource { std::string
contents_; }` and db/log_test.cc `StringSource { Slice& contents_; }` share the
key StringSource#contents_ (class names carry no namespace), the disagreement
tombstones it, and dropping the std record at capture pinned four testutil.h
contents_.size() calls to Slice::size. An empty type tombstones the entry
exactly as a second real type does.
Audit before touching a compose ref's fields: every reader of
Reference::qualifier excludes compose refs — the resolve loop and pin census
(isResolvableCallReference), model.h macro retag and shadow suppression
(isCompose filters), the inherit-only loops (graph.h isInherit), and the
Python/Rust/Elixir-only readers (quality.h, keepRustQualifiedCandidates,
elixir_resolve.h, expandElixirImplementationReferences). The other loops over
ing.references that do not filter isCompose never read qualifier (eval.h,
main.cpp byte stats, impurity and LCOM4 name scans, scip/filter/workspace
copies); the ref sort key is (fileId, startByte, name, role, isInherit). The
qualifier already rides the cache record, so no layout change.
Measured, --pin-census --no-cache and the default map, cfa5792's binary vs
this commit: rocksdb, a private C++ corpus and src/ (a frozen copy, one tree
for both binaries) are byte-identical, and rocksdb's --metrics is too. Counted
with --match, the corpora have 1,258 / 143 / 1,987 fields written `std::X`;
only rocksdb's 1,116 std::string/wstring fields share a name with an in-repo
type (gtest's `typedef ::std::string string`, no members, no HAS-A edge). So a
probe measured the reach: rocksdb plus one `namespace shim { struct string {
size empty data c_str clear append len } }`. The previous binary pins 384 call
sites to shim::string by receiver-rule; this commit leaves 7, all gtest
parameters written `const ::string&` (global namespace, not std, not fields).
357 sites move: 279 land on exactly the unmodified rocksdb census row, 78 are
c_str calls the probe's own second c_str makes ambiguous. --metrics: 455 class
rows lose a composed type from cbo= (446 by one, 9 by two).
Gate: test/fieldnarrowcheck.sh arm q (new fixtures, so (h)'s gauge is
untouched). RED on cfa5792 and on f346283: q1 (Rule 2b), q3 (HAS-A), q5 x2
(--uses, bare and this->). RED on a refuse-every-qualifier capture variant:
controls q2, q4, q6 and the four q7 tombstone rows. RED on the skip-at-capture
variant: exactly the four q7 rows — StringSource/StringSink collisions in both
record orders. (Variants measured on the f346283-based tree; the rebase onto
cfa5792 touched neither captureFields nor the two readers.) GREEN here, 44
PASS. qschemetripcheck re-pinned for the parser version with a dated note, as
its message directs (new pin == the current= it printed).
graph.h stays line-neutral above rankGraphTeleport (3404), so the 0.6.1
capture's published seed still resolves (showcasecapturecheck green). A first
cut hoisted the std-qualified call guard's lambda into a shared function;
--quality-delta read it as a 47-token clone of docparse.h's extension
lookups (gating=3), so the call guard keeps its lambda and the field readers
use a Reference-level predicate. quality-delta (working tree vs HEAD):
gating=0, six minor rows (churn; captureFields LOC 120 -> 121).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t-parameter floor was unstated Review of #248 (CI coordinator, 2026-09-16) found two text defects in this lane's entry; both re-measured here rather than copied. Count: test/narrowcheck.sh at this branch against the main binary (f8e6087) exits rc=1 with NINE FAIL rows — (7) (8) (10)x2 (11) (12) (13) (14) (15). The fix commit's own list named nine; 'ten' was a miscount. Floor: a parameter typed as an interface whose methods are pure-virtual declarations cannot narrow to it (Rule 2 resolves against definitions only), and the narrow lands on unrelated classes that share the final name segment. rocksdb @ 0e2801ac3, --pin-census --no-cache, main f8e6087 vs eaadb9d: 79 sites (88 rows) through an Iterator* parameter now split five ways over the nested memtable/ Iterator classes, none right — 25 were a unique override pin, 26 a split over overrides, 28 had no edge. Receivers read at the source are all 'Iterator* iter' parameters. (The review's 32 counts unique->disjoint-split only, main 31e788c against the #254 tip.) Also stated: a member-initializer call through a typed parameter is outside the body span and keeps main's answer — measured on this binary as main's own wrong locality pin. CHANGELOG-reading gates (anchorbodycheck, deckcheck, docdemotecheck, prcontextcheck, recallevalcheck, ripwirepubliccheck, rubysettercheck, traceminecheck) ALL PASS. No code, pin, kParserVer or qschemetrip.hash change; main is deliberately not merged (integration train 2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s a uniquely resolved edge Relaxing the parameter guard to refuse only std:: types keeps 111 correct narrows through qualified in-repo types (rocksdb 94, a private C++ corpus 12, src/ 5) and one known wrong one: narrowcheck arm 24's `ext::map<int, int>& table; table.find( 1 )` pins an unrelated in-repo map::find where main declines. The typed local twin (`ext::map<int, int> m; m.find()`) did the same on main already. Nothing on either edge said the qualifier was never checked against the class's namespace, so a guess read exactly like a uniquely resolved name. The fix (owner decision relayed by the CI coordinator, scope B): every edge a receiver's QUALIFIED, non-std written type chose — Rule 2's narrow, parameter or local, or CHA-lite's cone prune by that type — carries prov="final-segment". The flat per-function table records whether a declaration wrote the type qualified (resolve.h FlatRecvType / recordFlatRecvType); the lexical table reads it off the declaration; Narrower::finalSegmentTypeAt answers it per site. The value takes precedence below split (resolve.h edgeProvenance, which now owns the whole scip > binding > import > split > final-segment chain graph.h spelled inline), and both the map legend and the compact legend define it. graph.h stays line-neutral (+32/-32 against #248; rankGraphTeleport at 3404), so the showcase seed --at=src/graph.h:3406 still resolves. Gate: narrowcheck arm 25 — RED before: (25a) arm 24's wrong edge, (25b) arm 23's correct qualified parameter narrow, (25c) arm 22's local twin, (25f) map legend, (25g) compact legend. Controls green before and after: (25d) arm 18's unqualified narrow and (25e) a uniquely named call carry no prov=. localitycheck, clsrecvcheck, chacheck, chaconecheck, fieldnarrowcheck, resolverhonestycheck and showcasecapturecheck pass. Byte cost is measured with the collision guard that follows, on the final binary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…d locality pins, and supersede #248's parameter rule by name Only the C++ precision of the removed locality pins was published (14 of 14 rocksdb, 14 of 16 private), which invites that reading for every language. An independent review sampled the dynamic-language sites: django 8 of 14 wrong and 6 right, rails 8 of 12 wrong and 4 right, every right target kept inside the split that replaces it. Both rates are in the entry now, with Python's `cls` receivers (2 of django's 72) named. The entry also overturns #248's parameter rule in the same Unreleased section; it now says so explicitly ("only a written, unqualified type narrows" and "keep their previous answer" are superseded: a parameter refuses only a std:: type, as a local does). #248's own paragraph is left to that lane. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…yped-locality #248's docs-only follow-up (nine rows red on main, not ten; the abstract-parameter and member-initializer floors stated). CHANGELOG.md: union — #248's new floors paragraph closes its own entry, this branch's entry follows unchanged. No #248 line is removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ap; a shorter reading lands it at 1.10% Measured on rocksdb @ 0e2801ac3 against cfa5792's binary: the default map grew 31,366 -> 31,770 B (+404), of which ~110 B was the legend term and the rest 14 marked edges. The map legend reading shrinks to final-segment(last-name-match;namespace-unchecked) and the compact one to "a qualified type matched by last name only": default map 31,711 B (+345, +1.10%), --for bundle unchanged at 8,746 B, whole graph (--top-k=100000) +7,506 B (+0.14%, 355 marked edges), a private corpus's default map +51 B (legend only). A normalised diff confirms the attribute, the legend term and est_tokens are the only differences. Coordinator decision: keep the value name, take the shorter reading, accept the cost — disclosure is the owner's rule. CHANGELOG: the disclosure paragraph with that before/after table, arm 25 in the gates paragraph, and one sentence on the name-only collision guard, measured and rejected (967 rocksdb rows fixed; 58 platform-alternate splits and 8 correct log::Writer narrows declined, 10 new wrong unique pins, 132 correct django Template.render splits declined). Gates: narrowcheck (arm 25 still reads final-segment( in the map legend), compactlegendcheck, legendcoveragecheck, legendcostcheck, legenddriftcheck, printffmtparitycheck, docscommandscheck, mcpclidiffcheck, mcpattrparitycheck, floormarkcheck, testgatelegendbudgetcheck, xmlwellformed, jsoncheck, attrvocabcheck, connectcheck, connectjoincheck: all rc=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ain-2 on main 9f44a36 # Conflicts: # CHANGELOG.md # test/qschemetrip.hash
…in-2 # Conflicts: # test/qschemetrip.hash # test/qschemetripcheck.sh
# Conflicts: # src/resolve.h # test/qschemetrip.hash # test/qschemetripcheck.sh
…no side hashed the merged manifest Main's pin (37dac79a) hashed parserVer 96 over #249's new deserializeSnapshot; #248 (db0e8cce, 97), #254 (8ca11f67, 98) and #257 (01ea4c63, 99) each hashed their own number over the manifest before #249. The merged tree declares 99 over #249's function, which none of them hashed. kParserVer is assigned in merge order and equals what each lane already declared (#248 97, #254 98, #257 99); kCacheVersion stays 22, kQSnapCacheScheme 12. New pin 95818fe5 == the current= the gate printed before UPDATE_GOLDEN; qschemetripcheck and qextractionkeycheck ALL PASS on this tree. RE-PIN LOG entry added. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (28)
💤 Files with no reviewable changes (1)
Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review. 📝 WalkthroughWalkthroughChangesThe change adds lexically scoped receiver-type resolution for parameters and locals. It preserves qualified type text, excludes Receiver declaration capture Lexical receiver resolution Field and graph handling Tests and documentation Priority: ⬇️ Low Estimated code review effort: 4 (Complex) | ~60 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The resolver, cache-version, provenance, and regression-test changes are consistent with the stated behavior and are ready for normal merge checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 52.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 72 functions across 24 files. (3 skipped: 3 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
…n/train-1 Train 2 landed first, per the orchestrator's order; merged once with rerere disabled. Conflicts: - test/qschemetrip.hash: NEITHER side. Train 1 had a37d1539 (scheme 14, parserVer 96) and main had 95818fe5 (parserVer 99, scheme 12). Re-derived with UPDATE_GOLDEN=1 on the merged tree = 72f930b8171166d0a605cf27b610d1b3ade194f7703bd976904df78f350c38f3; qschemetripcheck ALL PASS. - test/qschemetripcheck.sh re-pin log, newest-first: a new 2026-09-17 TRAIN 1 x TRAIN 2 entry explaining the re-derivation, then train 2's 09-17 entry and its lane entries, then train 1's 09-16 entries (#255 v14, #253 v13), then #249's. Auto-merged (no markers): src/graph.h, src/resolve.h, src/model.h, src/serialize.h, src/quality.h (kParserVer mirror 99 from train 2, kQSnapCacheScheme 14 / kQBodyCacheScheme 4 from train 1), CHANGELOG.md, docs/EVALS.md. docs/gatecount_build.py --check and docs/limits_build.py --check are clean on the merged tree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ype, arms renumbered after #254's 25, identity claims carry no prov="final-segment" origin/main bcd3b01 brings #248, #254 and #257. Two files conflicted; rerere was off and no recorded resolution was used. - src/resolve.h: #254 added a namespace-level RecvVarType {name, writtenQualified}, and this lane added a nested Narrower::RecvVarType {name, declared}. Git merged the second in beside the first, so it would have shadowed it. Both are now ONE namespace-level struct {name, writtenQualified, declared}; recvVarType fills all three, and finalSegmentTypeAt is #254's own. - test/narrowcheck.sh: #254's arm 25 (prov="final-segment") keeps its number. This lane's arms 25-34 become 26-35; expectProv/provOf take an optional map file ("${5:-}" under set -u). - src/graph.h (line-neutral; rankGraphTeleport stays at 3404): an identity CLAIM verified its one class before answering, so its edges are not a last-name guess. Two lines change in place: `&& !identityClaim` joins the finalSegmentType condition, and its comment is reworded. A class-qualified step-1 narrow keeps the disclosure. - Arm 36, `hs::DiskHealth& d; d.fine()` claiming the inherited HealthBase::fine through namespace evidence: (36a) the edge, (36b) no prov=, (36c) `Skip::Iterator& it; it.key()` keeps prov="final-segment". A build without the graph.h condition fails (36b) with prov=[final-segment]. - CHANGELOG entry and ack text: the arm numbers only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts, and the default window's oracle was the wall clock The live audit passed --since="2 weeks ago" to ripwire and "2 weeks ago" to the git oracle, and each evaluated it when it ran. A commit on the edge fell inside one window and outside the other: redhat-et#265 went red on src/slice.h churn 15 vs 14 (commit 16efdbc at the two-week boundary), a rerun cause and not a defect. The default-window oracles had a slower version of the same bug. ripwire anchors its default churn window on HEAD's committer epoch minus 12 calendar months (gitmine.h defaultWindowSince, stamped 12mo@HEAD), but all ten oracles asked git for wall-clock "12 months ago". That is a different window which holds the same commits today and stops on 2027-06-01, when the fixtures' 2026-06 commits leave the wall clock's year. The fix, test-only: - One clock read (NOW_EPOCH) gives SINCE_2W as an ISO-8601 UTC instant, and that identical string goes to both ripwire and git. - defaultWindowStart REPO computes the HEAD-anchored start by monthsBeforeEpoch's rule, and every default-window oracle uses it. - New arm 4b pins both rules to the second: - a commit dated exactly on the two-week edge is in on both sides, and out on both sides one second later; - a commit exactly on the anchored edge is counted, and one a second earlier is not; - two controls stay red on purpose. "2 weeks ago" read by ripwire at N and by git at N+1 (GIT_TEST_DATE_NOW, which ripwire's git child inherits) disagrees, and the wall-clock oracle already drops the anchored edge commit. - The offset arm (10) still selected the retired p="./..." spelling. It read 0 rows and passed "all 0 rows re-derive". It now reads 163 rows, and the row count must equal ranked=. Red first, on main's gate with GIT_TEST_DATE_NOW staging: - ripwire at 8083ea9's epoch + 14 d and git one second later: rc=1 with 4 FAIL (src/slice.h churn 12 vs 11, verbs_report.h 36 vs 35, sortutil.h 2 vs 1, "3 of 406 rows disagree"). - git's clock at 2027-07-01: rc=1 with 12 FAIL. Green under the same stagings and unstaged: rc=0, 78 PASS, 0 FAIL, 0 SKIP (main's gate had 72 PASS). gateexitcheck, manifestcheck, skipclassifycheck and gatecountcheck pass. No other gate reads a relative date twice: the sweep of test/ found labels, exit codes and dates computed once (sincecheck, hotspotsincecheck, modifierguardcheck, recentscopecheck, gitstampcheck, qddialscheck). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Integration train 2. It lands three reviewed resolver PRs together, so the shared parser version, the extraction-manifest hash and CHANGELOG are reconciled once and CI runs once.
lane/param-receiver-binding@186fcb84: a member call through a typed parameter is no longer pinned to the caller's own class. Parser version 97.lane/recv-untyped-locality@0585b2f3: an explicit receiver of unknown type is no longer pinned to the caller's own class, and astd::type no longer narrows to an in-repo namesake. Narrows decided by a non-stdqualified written type now carryprov="final-segment". Parser version 98.lane/std-field-compose@50129f8c:std::-qualified field types are refused in Rule 2b composition. Parser version 99.Each had an independent review (#254 re-reviewed after its disclosure rework). #257's CodeRabbit review covered the stack's full range and had 0 actionable findings.
Resolutions (each is explained in its commit):
src/resolve.h: fix(resolve): a member field typed std::string narrowed to an in-repo class named string #257'sfieldTypeWrittenInStdand fix(resolve): an explicit receiver of unknown type was pinned to the caller's own class, and a std:: type narrowed to an in-repo namesake #254's helpers both inserted afternamesStdType; both are kept.kParserVer: 97 → 98 → 99 in merge order, with the mirror and the RE-PIN LOG entries in order.test/qschemetrip.hash: re-derived once on the merged tree (a62a36e2). No lane's pin hashed the merged manifest.main's first.mainmerged throughf57a9df3. fix: a deep or odd-shaped argument, source file or skills tree could crash or stall a verb — six fixes, each red-first #252 (316dbf26) merges clean against this branch.Verification on
92b4c91d:--quality-delta(merge-base range) reportsgating="0".Train 1 (#263) is ahead of this train. When it merges, this branch merges
mainonce more and re-derives the hash.🤖 Generated with Claude Code
Summary by CodeRabbit