Skip to content

feat(elixir): add native static module and arity resolution (#81, with the review round) - #207

Open
joyful-ii-V-I wants to merge 23 commits into
mainfrom
feat/elixir-native-resolution
Open

feat(elixir): add native static module and arity resolution (#81, with the review round)#207
joyful-ii-V-I wants to merge 23 commits into
mainfrom
feat/elixir-native-resolution

Conversation

@joyful-ii-V-I

Copy link
Copy Markdown
Collaborator

This is @henry-hz's Elixir work from #81, finished with the review round. GitHub refuses maintainer pushes to the fork's branch, so the finished branch comes from this repository instead. Henry's commits are unchanged and keep their authorship; the maintainer commits sit on top as merges and fixes, with no rebase and no squash. Because #81's head commit is part of this branch, #81 shows as merged when this one merges.

From #81 (@henry-hz)

Elixir calls resolve natively by module, name and arity through the existing tree-sitter pipeline, with no Elixir, Mix or language-server dependency.

  • Extraction: scoped modules, structs and exceptions, protocols and implementations, public and private functions, macros, guards, delegates, types, callbacks and attributes.
  • Resolution: lexical aliases and imports, static module receivers, defaults, pipes and named captures. alias Real.Work, as: W followed by W.run(x) resolves to Real.Work::run/1, never to an unrelated module's run/1.
  • A semantic gate with decoys, lexical boundaries, cache mutation and CLI/MCP parity.

Macro expansion and runtime dispatch stay static-analysis limits, documented in docs/ARCHITECTURE.md#elixir-extraction.

The review round (maintainer commits)

Evidence

  • New gate test/elixirnamearitycheck.sh (26 rows): red on the pre-review binary on exactly the reviewed rows, green on every control.
  • Elixir gates: elixircheck 8/8, eliximportcheck 22/22, elixirsemanticcheck 1/1, elixirnamearitycheck 26/26, with the same counts under ASan and no sanitizer output. LeakSanitizer is clean on the repo and the Elixir fixtures.
  • Merged tree: 63 targeted gates pass, plus the capture, public-name, docs, gate-count and manifest gates after the re-record. Two runs are byte-identical, cold matches warm, and xmllint is clean. CI runs the full suite.
  • Not measured: before/after numbers on a real Elixir project.

🤖 Generated with Claude Code

henry-hz and others added 23 commits September 9, 2026 19:53
Preserve upstream's Hermes, Git hardening, and document-indexing changes
alongside native Elixir resolution. Register all four added gates and
derive the published loop count as 567 from the merged runner.

Both branches independently used parser revision 85. Assign revision 86
and update the quality mirror and documentation so caches from either
branch are rejected. Preserve both extraction histories in the tripwire
log; refresh its hash in a separate golden-only commit.

Keep README source locations from the correct side of each merge.
Upstream advanced past this branch's previous merge with the ChaConeMemo warm-floor
fix, the tgrep --regex line-anchor harvest and the --for --detail max_tokens
disclosure. Five files conflicted, all of them counters or captures:

- test/regression.sh: the gate loop is the sorted UNION — this branch's
  elixirsemanticcheck plus upstream's chaconecheck, formaxtokenscheck and
  grepanchorcheck. 570 gates, derived from the merged runner, never carried.
- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: the published gate
  count follows that loop to 570.
- README.md's --callers example rows were stale on BOTH sides after graph.h moved;
  re-captured from the merged binary (readmeexamplecheck passes).
- CHANGELOG.md: both Unreleased entries kept. The Elixir entry said parser version
  85, the revision this branch used before integration; the integrated extractor is
  86 (src/ingest_cache.h, mirrored in src/quality.h, logged in qschemetripcheck).
  Corrected — the CHANGELOG is where a cache-compatibility reader looks first.

Verified on the merged tree: clean rebuild, 570-gate suite (576 pass / 4 skip / 4
fail, every failure reproduced as environmental or pre-existing — clang 14 rejecting
a C++20 structured-binding capture in graph.h, a missing /usr/bin/time, and
recallpassagecheck's P10 arm which its own header declares expected-red), a clean
ASan/LSan run, byte-identical repeat maps and well-formed XML.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUC4dGmaT2bFJvPJtsjvf
…-uses on Elixir defs

Three of the six actionable review findings on #81 reproduced; this is those three.

1. src/ingest_model.h — expandElixirImplementationReferences appended a multi-target
   defimpl's cloned references to the TAIL of ing.references, whose contract is
   (fileId, startByte, name, role, isInherit) order. A clone carries its original's
   coordinates, so the tail was full of earlier bytes and earlier files. Two consumers
   read that order rather than re-deriving it: graph.h's chaUpDeclared records a
   derived type's direct bases in source order (Elixir's Extends refs from defimpl ARE
   cloned), and editpreview.h splices a re-parsed file in by partitioning on fileId,
   which only reproduces a real re-ingest while each file's refs are one ascending run.
   Each clone is now spliced in beside the reference it came from — the same position a
   re-sort would give it, at no sorting cost.

2. src/mcpverbs.h — the MCP uses verb gated the Elixir resolver path on `defs`, which
   resolveAllByName fills for EVERY language, while the CLI gates on the same list
   filtered to Lang::Elixir. An Elixir reference whose calleeName matched a definition
   in another language therefore took the resolver path in MCP, matched nothing, and
   vanished — while the CLI still reported it through the name filter. That is the
   divergence mcpclidiffcheck exists to prevent. Now filtered the same way, off the raw
   selector, exactly as resolveUsesSelector does.

3. docs/ARCHITECTURE.md — the Elixir prose claimed resolution the tree does not do.
   Four gaps reproduce on this tip and are now disclosed in Static limits rather than
   left to contradict the PR notes: a later `import M, except:` replaces an earlier
   `only:` selection instead of subtracting; a dotted nested `defmodule Inner.Deep`
   registers no implicit prefix alias, so `Inner.Deep.target()` resolves to nothing;
   `alias __MODULE__, as: Current` in a multi-target defimpl binds every implementation
   to the FIRST target; and `&_seed/0` is dropped by the underscore filter. Honesty in
   output is a feature (CLAUDE.md non-negotiable #3) — these are floors, and the
   document now says so.

The three remaining findings did not reproduce and are unchanged: reachesAny's exact
name compare is correct because no non-Call Elixir reference carries an arity suffix
(they are module names and @attributes, matched against symbols whose scope is empty
or the enclosing module), and eliximportcheck.sh sets `set -u`, not `set -e`, so its
FAIL branch and fail=1 accounting do run.

Verified: elixircheck, eliximportcheck, elixirsemanticcheck, mcpclidiffcheck,
editpreviewcheck, editroundtripcheck, qschemetripcheck and qextractionkeycheck pass;
multi-target defimpl output is unchanged; ASan/LSan clean on the Elixir fixtures and
on the repo; repeat maps byte-identical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUC4dGmaT2bFJvPJtsjvf
Real conflicts (5 files) and their resolution:

- test/regression.sh: both branches independently extended the gate-name
  loop (570 vs 572 entries). Took the UNION (573) after confirming neither
  side deleted a gate script that the other kept — the 3 upstream-only
  gates (grepignorecheck, helpbudgetcheck, rustanccheck) plus this branch's
  elixirsemanticcheck all exist on disk.

- src/ingest_cache.h / src/quality.h: both branches independently bumped
  kParserVer to 86 (this branch for Elixir module/name/arity resolution,
  main for a Ruby receiver-dedupe fix that landed the same day). Per this
  codebase's own documented convention — rebasing a fork's parser version
  onto main means re-bumping to the next free number, never keeping the
  fork's value — the Elixir bump moves to 87. Rebuilt and re-pinned
  test/qschemetrip.hash; test/qextractionkeycheck.sh confirms the mirror.

- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every
  570/572 gate-count mention reconciled to 573 (verified consistent by
  test/manifestcheck.sh). One deck hunk also carried an unrelated adjacent
  edit (43 vs 46 surveyed repos) — kept 46, the value docs/LINEAGE.md and
  test/readmedriftcheck.sh already treat as authoritative.

Also fixed two merge-caused consequences the gate suite caught:

- docs/ARCHITECTURE.md's "parser revision 86 (rich 87)" line and the
  CHANGELOG heading/note now read 87 (rich 88), matching the re-bump above.

- The merge shifted line numbers in src/graph.h enough that the newest
  showcase capture's pinned seed (src/graph.h:3112) no longer resolved to
  rankGraphTeleport (showcasecapturecheck.sh arm H). Regenerated the
  capture via test/showcase_capture.py rather than hand-editing the seed.
  Regeneration surfaced a separate latent bug already described by the
  file's own "wave-3 close" comment: two --stray-content demos were still
  hard-coded to a "lane" branch substring instead of using the existing
  _refFamily fallback, so they break on any checkout without a live
  lane/* branch (the common case once a PR's branch is merged and
  deleted). Moved both onto _refFamily, matching the pattern already used
  two lines below them. Regenerated docs/COMMANDS.md from the fresh
  capture to match (test/docscommandscheck.sh arm G).

Verified: test/manifestcheck.sh, test/readmedriftcheck.sh,
test/qextractionkeycheck.sh, test/showcasecapturecheck.sh,
test/docscommandscheck.sh, test/ripwirepubliccheck.sh,
test/printffmtparitycheck.sh all ALL PASS. Full suite via
test/pargates.py: 579 pass / 4 skip (all environment gated, e.g. no
RIPWIRE_BASE reference binary) / 4 fail, and every failure confirmed
pre-existing and unrelated to this merge by reproducing it against a
pristine build of upstream/main or of this branch's own pre-merge tip:
columnarcommacheck.sh (a Clang-14-specific structured-binding-capture
rejection already present on upstream/main), recallpassagecheck.sh (P10
natural-language parity, already red on this branch before the merge,
tracked as concurrent lane F1 work), padscalecheck.sh (a timing-sensitive
scaling run, already red on upstream/main), and g1freshcheck.sh (a local,
gitignored asan/ build directory predating this session, not part of the
tree).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
…eview)

upstream/main gained PR #99 (an opt-remarks lane, test/optremarkshotcheck.sh)
while the first merge round was under review. Same union treatment as the
first round:

- test/regression.sh: union of both gate lists (573 + optremarkshotcheck =
  574), confirmed the new script exists on disk and neither side dropped a
  gate the other kept.
- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 573
  gate-count mention bumped to 574, reverified by test/manifestcheck.sh.

No graph.h changes this round, so the showcase-capture seed did not drift
again; test/showcasecapturecheck.sh and test/docscommandscheck.sh stayed
green without regenerating anything.

Verified: test/manifestcheck.sh, test/qschemetripcheck.sh,
test/readmedriftcheck.sh, test/docscommandscheck.sh all ALL PASS. Full
suite via test/pargates.py: 580 pass / 4 skip (environment-gated) / 4 fail,
the same four pre-existing, merge-unrelated failures already root-caused
in the prior commit (columnarcommacheck.sh, recallpassagecheck.sh,
padscalecheck.sh, g1freshcheck.sh).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
upstream/main is under continuous automated merge activity (a new
lane/* PR landing roughly every 15-20 minutes); it gained
test/callsrankordercheck.sh while round two was being verified and
pushed. Same mechanical resolution as the prior two rounds:

- test/regression.sh: union of both gate lists (574 + callsrankordercheck
  = 575), confirmed the new script exists on disk and no gate was
  dropped by either side.
- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 574
  gate-count mention bumped to 575, reverified by test/manifestcheck.sh.

Verified: test/manifestcheck.sh, test/qschemetripcheck.sh,
test/showcasecapturecheck.sh, test/docscommandscheck.sh,
test/readmedriftcheck.sh all ALL PASS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
upstream/main gained a new MCP capability-disclosure lane
(test/capdisclosurecheck.sh, touching src/mcpverbs.h and
src/verbs_navigate.h) while round three was being verified and pushed.
Both source files auto-merged cleanly (no textual overlap); only the
usual two hot spots needed hand resolution:

- test/regression.sh: union of both gate lists (575 + capdisclosurecheck
  = 576), confirmed the new script exists on disk and no gate was
  dropped by either side.
- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 575
  gate-count mention bumped to 576, reverified by test/manifestcheck.sh.

Verified: test/manifestcheck.sh, test/qschemetripcheck.sh,
test/showcasecapturecheck.sh, test/docscommandscheck.sh,
test/readmedriftcheck.sh, test/capdisclosurecheck.sh (the new gate
itself), test/mcpverbscheck.sh, test/mcpcontractcheck.sh and
test/usesselectorcheck.sh (covering the two auto-merged source files)
all ALL PASS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
…/arity resolution) — parser version 95

REHEARSAL ONLY — local branch pr81-rehearsal, never pushed. Resolves the 15 conflicted files of
merging main into @henry-hz's head 9046edc, assuming PR #139 (kParserVer 93, kCacheVersion 21) and
PR #172 (kParserVer 94) land first:

- src/ingest_cache.h, src/quality.h: kParserVer / kIngestParserVerMirror 95 (branch carried 87, main 92);
  kCacheVersion / kIngestCacheVersionMirror 21 (#139's format; #81 changes no record shape).
- src/ingest_elixir.h, src/ingest_sidecap.h: the branch's semantics kept (ElixirContext scopeOf/moduleOf,
  attribute refs, alias/atom/dot/__MODULE__ receivers, the refined @-attribute filter); converted to
  main's #127 API (fieldChild/NodeField, kindIs) since the by-name nodeFieldText overload is gone on
  main. NodeField gains Operand (src/infra/fieldid.h). #include <charconv> added (review item 1).
- src/graph.h: PROVISIONAL accounting on the Elixir no-candidate drop — disposition Undefined/Unresolved
  instead of Unaccounted, so main's 6b8dc9d conservation alert stops firing on every Elixir corpus
  (it fired on test/elixirfix: 10 of 19 sites). No edge changes; review item 2's design choice stays open.
- test/regression.sh: gate-list union (606 + elixirsemanticcheck = 607); test/gateexitcheck.sh: both rows.
- test/qschemetrip.hash, test/printf_parity.manifest, gate-count sites, docs/COMMANDS.md: regenerated
  from the merged build. docs/captures/*: main's side (the 09-12 capture's graph.h seed now needs a
  ref-clean re-record: rankGraphTeleport moved 3357 -> 3371).
- CHANGELOG.md, README.md, docs/ARCHITECTURE.md: both sides, renumbered to 95/21/10.

Wanted gate set after this commit: gates=12 pass=11 fail=1 — the one failure is showcasecapturecheck
arm (H), the seed line, which only a re-recorded capture can fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eview items 2 to 5

A gate before the code it measures (CONTRIBUTING section 2). On b0bd2cf it is red on the
rows the PR #81 review named: a call delivered by `use` was dropped with no header count; a
variable bound on the right of `=` in a pattern became a zero-arity call of a same-named
function; --edit-check read run(x) -> run(x, y) as new-symbol with 0 callers; --for by an
exact function name routed name-exact and then scored nothing (no_candidates). Its controls
are green on the same binary: the lexical import that makes the same call resolve, the
body-match calls that must keep their edge, a clean-tree edit-check, the explicit name/N
spelling, and the nested-module import and attribute-read use-sites behind the reachesAny
finding. Listed in test/regression.sh; the gate count regenerates to 608. Red by design
until the commits that follow.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…pped without a count

With no lexical candidate the resolver continued out of the resolve loop; no edge was
minted (correct: a same-spelled function in an unrelated module is the false edge it exists
to refuse) but nothing recorded the drop, so a caller set could shrink 55 -> 3 with every
gauge reading zero. The rehearsal merge's provisional one-liner named a disposition and
nothing else, which declinecheck arm F now shows was internally inconsistent: census
unresolved=2 beside header unresolved=1.

Decision (review item 2): count, never guess. A spelling some in-repo definition carries
is unresolved (the header gauge and the caller's own unresolvedOut, the vocabulary the name
ladder already uses for a lang-filtered name); a spelling no definition carries is
undefined, which has no header surface by design; in a multi-root run a name defined only
in another root is that root's, OtherRoot. Modelling what __using__ injects stays open.

declinecheck's Elixir row is re-pinned to the same rule: its fixture called ex_hop(m)
against two `def ex_hop do` (arity 0), an arity no definition carries, so under name/N the
call was undefined rather than the two-candidate decline the arm meant to exercise. The
call is now ex_hop(); Elixir never reaches the tier-3 ladder, so the refusal reads as
unresolved=2 (header and every answer's graph_unresolved=) and declined= is 16, not 17.
The arm was already red on b0bd2cf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…came a zero-arity call

bindingScope answered "not a binding" the moment it met a `=` whose left side did not
contain the identifier, so in `def join(%Socket{} = socket, _)`, a `%S{} = s ->` clause
or a `{:ok, %{} = m} <- x` generator the right-hand variable was never recorded; its later
reads in the body were bare identifiers with no visible binding and resolved as calls of a
same-named zero-arity function (12 false callers of one socket/0 on a framework corpus).

The right of `=` binds exactly when the whole match sits in a pattern, and only the
construct above can say so: the walk now continues upward from such a `=` and lets the
def head, stab clause or generator decide. A body-level `x = y` reaches the def head, is
outside it, and stays a call, which the rhs/0 and bare_rhs/0 controls pin. `<-` and `\\`
are unchanged: their right sides are an expression and a default value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…o callers

Elixir keys a callable as name/N, so run(x) -> run(x, y) renamed run/1 to run/2: the
quality key (path, scope, name) no longer matched the HEAD baseline (new-symbol), the
in-edge walk found nothing (no reference spells run/2) and --quality-delta reported a dead
symbol beside a brand-new one. The callers the edit had just broken were the rows the verb
exists to print, and it printed none.

The quality key now folds the arity out of an Elixir name through one Symbol overload of
pathQualifiedKey, the single keying rule every site (quality, merge-scout, lanes) goes
through: run/1 and run/2 are two entities (canonicalId keeps the arity) but one piece of
source, as C++ overloads of f already are. That is a change of what a cached Snapshot
means, so kQSnapCacheScheme is 11 and the tripwire is re-pinned. --edit-check folds the
overload set and its ambiguity groups the same way, recovers the old arity's callers
through a fold-arity ElixirResolver (the caller's own aliases, imports and receiver, asked
about the function rather than one arity of it), and flags them: an Elixir clause's arity
is exact unless a default widens it, which arityExact now says (cc_paramArityExact's
language gate had left every Elixir definition unflaggable). run(x, y \\ 1) reports the
contract change and flags nobody.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ame/N

The router's whole-name index and the name-exact scorer compared the query token with the
symbol name byte for byte, so `generate_phoenix_app` routed name-exact on its snake shape,
matched no whole name, and the ranking came back empty (no_candidates); a plain word such
as `text` did not route at all. The arity-less spelling of an Elixir name/N is now a
second whole-name token in the index and the scorer (one document token either way, so
every other language scores byte-identically), and the body head's anchor test accepts it
too: the anchor resolved to the right file and then filtered its own definition out of the
head, leaving bodies="0" reason="no_candidates" beside a correct first row.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…us through `$?` after the fact

The gate runs under `set -u`, not `set -e`, so the FAIL branch was reachable; but the
verdict was taken from `$?` on the line after the heredoc in an `A && ok || no` chain
(ShellCheck SC2181/SC2015). The python block is now the condition of an if, so a failed
assertion is a FAIL row and fail=1 by construction. Proven live: with `def go` renamed in a
fixture copy the gate prints `FAIL alias call resolution failed` and exits 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The entry already names parser version 95 and cache format 21; it now records the four
review findings closed on the branch, the use-delivered drop's disclosure, the pattern
binding, the arity fold behind --edit-check (snapshot scheme 10 -> 11) and --for by exact
name, each with its row in test/elixirnamearitycheck.sh.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s 95 over #139's 93, absorb loop unioned, pins re-derived

Eight conflicts: version ladders, re-pin logs, the absorb loop and generated counts. No Elixir or Ruby
logic conflicted. #172 (kParserVer 94) is merged next, so this commit's 95 already sits over both.

- src/ingest_cache.h, src/quality.h: kParserVer and kIngestParserVerMirror stay 95; both notes kept, 95
  above 93. kCacheVersion 21 keeps main's description of #139's format change, plus the branch's note
  that #81 appends RecvKind / LocalBindKind enumerators to the existing u8 and changes no record shape.
- test/qschemetripcheck.sh: both RE-PIN LOG entries, the Elixir pair above #139's.
- test/qschemetrip.hash: re-derived on the merged tree (UPDATE_GOLDEN=1 starting from main's value). It
  equals the branch's pre-merge ce851b68: main changed no manifest function, and the branch already
  declared 95 over 21.
- test/regression.sh: main's loop order kept, elixirsemanticcheck and elixirnamearitycheck inserted where
  the branch had them (609).
- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: gate count regenerated by
  docs/gatecount_build.py (609 at 8 sites).
- CHANGELOG.md merged clean: the Elixir entry (parser version 95) and #139's Ruby entry both kept.

Binary-derived outputs (test/printf_parity.manifest, docs/COMMANDS.md, the showcase capture) are
re-derived after the #172 merge, from one clean build of the combined tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#172's 94, captureTagsFacts takes both parameters, pins re-derived

REHEARSAL, local only: #172 (the `#if 0` filter over every role and definition) is not merged yet. Its head
is based on main 558a2e0, which the previous commit already brought in, so once #172 lands the final
`git merge origin/main` has nothing left to resolve here. Ten conflicts; two are code.

- src/ingest_sidecap.h, src/ingest_parsepool.h: captureTagsFacts keeps both new parameters — #81's Elixir
  bind/include outputs and #172's decided-dead ranges, walked once per file by the worker — as
  (..., defs, refs, binds, includes, ppDead), and both call sites pass both. The function-local ppDead
  recompute the branch still carried is gone. #172's firstRefOfFile window is taken before
  ElixirContext::prepare, so it spans every ref the function appends. At the tail #172's filter runs
  first ("before anything else reads either one"), then #81's defimpl expansion, then foldFieldDefs.
  The order changes no output: preprocDeadRangesFor is empty for every non-C-family language, so the
  filter is a no-op on an Elixir file and the expansion never runs on a C-family one. One comment
  paragraph says why the bind/include windows the function now appends (Elixir only) are not filtered.
- src/ingest_cache.h, src/quality.h: kParserVer and kIngestParserVerMirror 95; notes kept 95 / 94 / 93.
  kCacheVersion 21: neither #172 nor #81 changes a record shape.
- test/qschemetripcheck.sh: #172's RE-PIN LOG entry kept under the Elixir pair, which records the second
  re-derivation.
- test/qschemetrip.hash: re-derived (UPDATE_GOLDEN=1 starting from #172's 045d24c5) = ce851b68, the
  branch's own value: neither #139 nor #172 touched a manifest function or kMergeDiffArgs, and the hashed
  declaration lines read 95 over 21.
- test/regression.sh: #172's loop order kept, elixirsemanticcheck and elixirnamearitycheck where the branch
  had them (610).
- README.md, docs/EVALS.md, present/deck5_ripwire_build.js: gate count regenerated by
  docs/gatecount_build.py (610 at 8 sites).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the changelog entry ran into Upgrade notes

The note beside kParserVer in src/ingest_cache.h was written for the rehearsal merge, before review
item 4 moved kQSnapCacheScheme 10 -> 11 for the arity-key fold. It now says that move belongs to
quality.h's key, not to the extraction change the note records. CHANGELOG.md: the Elixir entry's last
paragraph ran straight into `### Upgrade notes` with no blank line.

Comments and prose only: kParserVer 95, kCacheVersion 21 and kQSnapCacheScheme 11 do not move, and
test/qschemetripcheck.sh hashes only the declaration lines, so its pin stays ce851b68.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nkGraphTeleport seed moved to graph.h:3406

showcasecapturecheck arm (H) was red on the merged tree: the published --at=src/graph.h:3362 seed no
longer resolved to rankGraphTeleport once #81's graph.h lines landed above it. Recorded by
test/showcase_capture.py, which re-derives the seed via bodySeed, in a ref-clean clone: detached at
f92a54d, no remote configured, local refs limited to public main, the v* tags and the public lane/*
branches, TMPDIR empty. The generator reads the checkout's local branch names, so a machine's own lane
names would otherwise be published.

Checked by hand before copying back: the 8 lane/* names are all in main's capture or on the public
remote; no absolute home, temp or scratch path; no private corpus name, no email. 52 headings carry a
recorded exit code in both main's capture and this one, and none changed; the one renamed heading is
the --stray-content ref family the generator picks from local refs (`lane/` where main's says `lane`).
docs/COMMANDS.md regenerated from the new samples (175 flags, 161 samples, --check clean).

Gates: showcasecapturecheck, ripwirepubliccheck, docscommandscheck, gatecountcheck, manifestcheck —
gates=5 pass=5 skip=0 fail=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…free, the tree is unchanged

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 5 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 15bdc8ab-3876-4d29-a907-e65c363e3baf

📥 Commits

Reviewing files that changed from the base of the PR and between 48222d6 and 5a4e5e7.

📒 Files selected for processing (49)
  • CHANGELOG.md
  • README.md
  • docs/ARCHITECTURE.md
  • docs/COMMANDS.md
  • docs/EVALS.md
  • docs/captures/COMMANDS_showcase_2026-09-10.md
  • docs/captures/COMMANDS_showcase_2026-09-12.md
  • present/deck5_ripwire_build.js
  • queries/elixir/tags.scm
  • src/editcheck.h
  • src/editplan.h
  • src/elixir_resolve.h
  • src/graph.h
  • src/infra/fieldid.h
  • src/ingest_cache.h
  • src/ingest_elixir.h
  • src/ingest_model.h
  • src/ingest_parsepool.h
  • src/ingest_sidecap.h
  • src/lanes.h
  • src/lexical.h
  • src/mcpedit.h
  • src/mcpverbs.h
  • src/mergescout.h
  • src/model.h
  • src/quality.h
  • src/resolve.h
  • src/verbs_for.h
  • src/verbs_navigate.h
  • test/declinecheck.sh
  • test/declinefix/sweep/elixir/c/c.ex
  • test/eliximportcheck.sh
  • test/elixircheck.sh
  • test/elixirfix/run.exs
  • test/elixirnamearitycheck.sh
  • test/elixirnamearityfix/lib/channel.ex
  • test/elixirnamearityfix/lib/client.ex
  • test/elixirnamearityfix/lib/outer.ex
  • test/elixirnamearityfix/lib/page.ex
  • test/elixirnamearityfix/lib/user.ex
  • test/elixirnamearityfix/lib/web.ex
  • test/elixirnamearityfix/lib/work.ex
  • test/elixirsemanticcheck.sh
  • test/gateexitcheck.sh
  • test/qschemetrip.hash
  • test/qschemetripcheck.sh
  • test/regression.sh
  • test/selfcontainedcheck.sh
  • test/showcase_capture.py

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants