Skip to content

Merge train: 53 reviewed PRs (2026-11-06) - #1146

Merged
tirth8205 merged 407 commits into
stagingfrom
train/2026-11-06
Nov 6, 2026
Merged

tirth8205 merged 407 commits into
stagingfrom
train/2026-11-06

Conversation

@tirth8205

@tirth8205 tirth8205 commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

This merges 53 reviewed PRs into staging in one CI run. Merge it with a merge commit, so each PR is marked as merged under its author's name.

This is not a release. The version stays 2.3.9, with no tag and nothing sent to testing or main.

Included

Other tools and install

Imports and registry

Review and query

Languages

Build, update and watch

Dependencies, tests and speed

How it was checked

Each PR was read in full, merged with current staging, tested and probed for faults, and Copilot's comments were checked against the code. Real faults were fixed on the train as separate commits. Those commits carry the maintainer's git name with a Claude co-author line.

On the combined branch, on macOS only:

  • Full suite: 6,422 passed. 3 token-budget tests fail, and the same 3 fail on plain staging here. The check found the output is byte-identical to staging and the cost comes from a long temp path, so CI is the real answer for those three.

  • Packaging gate: 17 passed, run before the last fix commit.

  • Installed wheel on real repositories: this repo, devise, apollo and documenso. An incremental update matches a fresh build, except for criticality on 15 of 874 documenso flows. No file lost. Graphs from v2.3.9 and staging upgrade to schema 14.

  • MCP through the real client: 30 tools and 5 prompts, cancel, --multi-worktree and --auto-watch.

  • All 16 platforms: install, reinstall and uninstall in a throwaway HOME. Real codex and claude were run. claude plugin validate passes.

  • Browser tests: 17 passed on real Chromium.

  • Upgrade suite with 2.3.9 added to the release list: 42 passed, 0 failed, 4 expected failures on 2.3.7 and 2.3.8.

CI on the first push found what the Mac run could not: a test tied to Python 3.11 or newer, a Windows path check, and legend icons stretched to 104px by a page-wide CSS rule. That last one is older than this train, and all three are fixed here.

The end-to-end run found one bug the test suite missed: #933 with #1087 lost same-file Ruby calls (23 sites on devise, 71 on sidekiq). It is fixed, and both now lose none against staging.

Not tested

  • Windows and Linux on this exact branch: CI covers part of that.
  • Real OpenCode, Cursor, Windsurf, Zed, Antigravity, Gemini CLI, Qwen, Kiro, Qoder, Hermes and CodeBuddy clients: not installed here.

Worth knowing

  • Generic YAML can grow a graph a lot: sidekiq goes from 1,693 to 5,085 nodes, mostly locale files.
  • Nested Ruby methods now carry their full scope, such as Auth.User.to_s. The schema 14 migration makes the next update re-key Ruby files.
  • After upgrading, run build once to pick up generic YAML and workspace imports.
  • Install now also writes post-checkout, post-merge and post-rewrite hooks. --no-hooks skips them.
  • fix: scope Codex graph hooks to event cwd #1061 and Fix incremental caller loss after re-exported symbol rename #1062 were aimed at main, and were retargeted to staging.

🤖 Generated with Claude Code

azizur100389 and others added 30 commits October 15, 2026 14:26
`class ::Root` inside `module Outer` qualified to `Outer.Root`, and a
leading `::` left an empty segment behind (`Outer..A.B`, `.X.Y`). A
leading `::` anchors the name at the top level, so the enclosing scope
is now dropped instead of stacked, and the separator is stripped.

Also correct the comment that still said "immediate scope only": the
code stacks the full enclosing chain. Two test comments said the same.
… into pr/code-review-graph-1104

# Conflicts:
#	code_review_graph/tools/build.py
…king

Translate the AspectJ '..' wildcard to \.(?:[^.]+\.)* instead of a bare
'.*', so repeated '..' segments in an execution() pointcut can no longer
stall build/update through regex backtracking.

Add the edge-case tests from review/pr-916 and drop the xfail marker on
test_pathological_double_dot_pointcut_resolves_in_bounded_time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Start the filesystem observer before startup reconciliation so
edits made during post-processing are captured.

Serialize startup work and event batches through the same
processor lock, and prevent the initial debouncer wake-up
from being lost.

Add regression coverage for startup edits, event serialization,
and first-event delivery.
Double-quoted keys and values in Route::group options were not read as
literals, so the "prefix" key was dropped and the endpoint got a path
Laravel does not serve. Group options that are not a literal array
(a variable, config(), array_merge(), a spread element or a dynamic key)
were treated as empty; routes inside them are now skipped, as with
prefix($var). Arrow-function group bodies now count as groups, and
double-quoted route paths without interpolation produce endpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Capture and clear affected flows before file node IDs churn, remap
community assignments by qualified name, and normalize relative git
paths against absolute graph file_path values.

Fixes #569
Add maintainer-requested lifecycle parity cases for #569: relative
paths without repo_root, underscore/percent filename literals, suffix
collisions, deleted-community cleanup, and rename vs full-rebuild parity.
Escape the Windows backslash separator in expand_changed_file_paths so
relative matches stay boundary-anchored (b.py no longer hits ab.py).
Collapse duplicate lifecycle path expansion and flow ID queries, and
assert real community-assignment equality vs a clean rebuild.
Align expand_changed_file_paths with #774 so incremental matching uses the
same file_path identity as the graph store after rebase onto main.
Avoid clearing nested same-basename flows during incremental updates,
fix the mypy batch type reuse, and align ambient-transaction handling
with store_flows rollback convention.
Cover the reviewer repro where a failed incremental parse must keep
existing flow and node state until a later successful replacement.
Skip the no-op early return when base matches the stored HEAD so empty
commits still refresh git_head_sha. Add the PR #673 review lifecycle
suite and drop the temporary freshness xfail marks.
semantic_search_nodes_tool takes include_source, expand_neighbors and
max_source_lines. With include_source each hit carries its source lines;
with expand_neighbors the top hits also carry their direct callers and
callees with source. A shared line budget caps the response, and a stored
path that resolves outside the repository is never read.

Search ranks test code below production code unless the query asks about
tests, so a short test stub no longer outranks the implementation.

The installed instruction block points agents at the new options and still
says not to change code from graph output alone. The previous block is kept
in _legacy_instructions.py so upgrade and uninstall still recognise it.

The README and docs/REPRODUCING.md publish the 2026-09-22 agent_baseline
capture (median 6.65x across 18 questions on 6 repos). The 2026-05-25
impact_accuracy CSVs are removed; the 2026-08-02 captures replace them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tirth8205 and others added 15 commits November 6, 2026 14:39
# Conflicts:
#	code_review_graph/incremental.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruby methods always carry their full lexical scope (#933), so the leaf
collision index from #1087 now covers Python only, and the docs and tests say
so. Generators are not component wrappers' functions (#972 with #1131). Partial
graph coverage counts tracked files only (#881 with #1094). A pending marker
recomputes all derived data (#1105), so that test starts from a finished graph,
the deleted-seed case now passes (#1062 with #673), and hooks.json keeps its
events under a hooks key (#1102 with #1126).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…F-8 out of update and review (review of #1094)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1108)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both sides fixed fork inheritance and the flock wrapper docs. Keep the author's
versions, which also register the lock before the flock call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…accepting plain directories (review of #1126)

The new commit made a filesystem without flock crash every build with a
traceback, and made update and postprocess refuse a plain directory that they
accepted before. Neither is what the lock is for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	code_review_graph/tools/build.py
The #1087 guard read a dotted scope as a leaf collision. Every nested Ruby class
has one since #933, so same-file Ruby calls lost their targets: devise lost 23
call sites and sidekiq 71. A Ruby leaf now counts as ambiguous only when two
scopes share it, and both repositories lose none against staging.

Also: install leaves a pre-commit hook in another language alone, since a shell
block appended to it made every commit fail; uninstall removes the empty Codex
skills folder; the docs give the current schema version and say that Codex runs
hooks only once they are trusted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

code-review-graph review

Overall risk: 0.85 (CRITICAL) — 500 changed function(s)/class(es), 130 affected flow(s), 282 test gap(s) (140 with no tested caller found, 142 reached only through a caller)

Risk-scored changes

Risk Level Symbol Location Tested
0.85 critical code_review_graph/communities.py::capture_community_assignments code_review_graph/communities.py:850 yes
0.85 critical code_review_graph/communities.py::remap_community_assignments code_review_graph/communities.py:878 yes
0.85 critical code_review_graph/constants.py::read_only_requested code_review_graph/constants.py:15 indirect
0.85 critical code_review_graph/daemon.py::_WindowsJob.assign code_review_graph/daemon.py:181 yes
0.85 critical code_review_graph/graph.py::_impact_candidate_sql code_review_graph/graph.py:457 yes
0.85 critical code_review_graph/multi_worktree.py::_request_key code_review_graph/multi_worktree.py:46 indirect
0.85 critical code_review_graph/parser.py::CodeParser._plsql_member_signature code_review_graph/parser.py:5820 yes
0.85 critical code_review_graph/tools/query.py::_SourceBudget.attach code_review_graph/tools/query.py:1243 indirect
0.80 high code-review-graph-vscode/src/backend/sqlite.ts::SqliteReader.checkSchemaCompatibility code-review-graph-vscode/src/backend/sqlite.ts:194 no
0.80 high code_review_graph/embeddings.py::EmbeddingStore._vector_cache_token code_review_graph/embeddings.py:1469 indirect

Affected execution flows

  • activate — criticality 0.76, 37 node(s) across 8 file(s)
  • process — criticality 0.74, 655 node(s) across 18 file(s)
  • _run — criticality 0.74, 688 node(s) across 20 file(s)
  • build_or_update_graph_tool — criticality 0.73, 752 node(s) across 27 file(s)
  • refactor_tool — criticality 0.72, 165 node(s) across 12 file(s)
  • ...and 125 more affected flow(s)

Test gaps

  • code-review-graph-vscode/src/backend/sqlite.ts::SqliteReader (code-review-graph-vscode/src/backend/sqlite.ts:160)
  • code-review-graph-vscode/src/backend/sqlite.ts::SqliteReader.checkSchemaCompatibility (code-review-graph-vscode/src/backend/sqlite.ts:194)
  • code_review_graph/assets/code-review-graph/scripts/crg_readonly.py::_resolve_repo (code_review_graph/assets/code-review-graph/scripts/crg_readonly.py:40)
  • code_review_graph/assets/code-review-graph/scripts/crg_readonly.py::_crg_command (code_review_graph/assets/code-review-graph/scripts/crg_readonly.py:70)
  • code_review_graph/assets/code-review-graph/scripts/crg_readonly.py::_add_common (code_review_graph/assets/code-review-graph/scripts/crg_readonly.py:82)
  • ...and 135 more with no direct test

Reached only through a caller

No test names these directly, but a tested caller reaches them along the call path shown. That is a path in the call graph, not a record of execution -- the caller's tests may never take this branch. Treat it as where to look, not as coverage: these count as gaps and are scored as untested.

  • code_review_graph/aop_resolver.py::_extract_annotation_string_arg (code_review_graph/aop_resolver.py:135) — via code_review_graph/aop_resolver.py::resolve_aop_advice, 1 hop(s)
  • code_review_graph/aop_resolver.py::_annotation_head (code_review_graph/aop_resolver.py:159) — via code_review_graph/aop_resolver.py::resolve_aop_advice, 1 hop(s)
  • code_review_graph/aop_resolver.py::_glob_matches (code_review_graph/aop_resolver.py:169) — via code_review_graph/aop_resolver.py::_DottedPattern.match, 1 hop(s)
  • code_review_graph/aop_resolver.py::_resolve_pointcut_expr (code_review_graph/aop_resolver.py:277) — via code_review_graph/aop_resolver.py::resolve_aop_advice, 1 hop(s)
  • code_review_graph/aop_resolver.py::_load_extra (code_review_graph/aop_resolver.py:309) — via code_review_graph/aop_resolver.py::resolve_aop_advice, 1 hop(s)
  • ...and 137 more reached only through a caller

Token savings: this graph-backed report used ~1,186,192 fewer tokens (~66%) than reading every changed file in full (estimated, chars/4 approximation).

Note: analysis was capped at the configured maximum number of changed functions (set CRG_MAX_CHANGED_FUNCS to adjust).


Powered by code-review-graph — local-first analysis; no code leaves the CI runner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@HouMinXi

HouMinXi commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Checked #1132 on the train head (da989c5): the commit is present unchanged, tests/test_parser.py passes 225/225 there, and the seven dead-guard cases (C, Go, TS, Rust, nested declarations) all pass. Nothing needed from my side.

The four failing checks are in other areas. Failure names from the logs:

  • test (3.10) / test (3.12): tests/test_python_module_alias_shims.py::test_module_too_deep_for_ast_keeps_the_file_as_the_module — the file falls back to billing.py instead of deep.py (1 failed, 6452 passed).
  • Windows daemon and file handles: tests/test_watch_robustness.py::TestWatchLoop::test_event_queued_during_startup_cannot_write_to_a_refused_graph (1 failed, 836 passed).
  • Visualization browser tests: tests/test_neighbourhood_browser.py::test_existing_interaction_surface_still_works — Playwright Locator.click timeout.

@HouMinXi

HouMinXi commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Follow-up on the test (3.10) / test (3.12) failure, since the "not tested" section lists Windows and Linux but not this one.

tests/test_python_module_alias_shims.py does not exist on staging (3.10/staging is d72e8fb), so the failure is introduced by the train, and it does not reproduce on Python 3.14 locally: 33 passed here.

The reason looks like the test's premise, not the feature. test_module_too_deep_for_ast_keeps_the_file_as_the_module builds x = 1+1+... with 60,000 terms and relies on that defeating ast.parse:

3.14: RecursionError: Stack overflow (used 8152 kB) during compilation

On 3.10/3.12 the same source evidently parses, so the parser does not take the "file defeats ast.parse" branch, the shim is not followed, and the assertion sees deep.py instead of services/billing.py. That makes the test's outcome depend on the interpreter's recursion limit rather than on the code under test.

A deterministic version would force the failure (patch ast.parse to raise, or assert whichever branch holds on that interpreter) instead of hoping a 60k-term expression overflows. Worth fixing on the train since it is the only red in the test matrix that is not on your untested list.

tirth8205 and others added 2 commits November 6, 2026 17:16
Legend icons were stretched to 104px by the page-wide svg rule, so the legend
filled the screen and a sixth node kind pushed it under the filter panel. This
is older than the train, and the icons are now 16px. Two tests also depended on
their platform: Python 3.10 accepts the deep expression (#1133), and Windows
paths have backslashes (#1108).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tirth8205
tirth8205 merged commit 0160eb0 into staging Nov 6, 2026
22 checks passed
gowrishacv pushed a commit to gowrishacv/code-review-graph that referenced this pull request Nov 6, 2026
test_thousands_of_wrapped_components_in_one_scope took 24.6s against a 20s limit
on the staging push run for tirth8205#1146, on the same tree that had passed on the PR.
The bound is there to catch a blow-up, so 90s still does that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.