Skip to content

Promote testing -> main - #1046

Merged
tirth8205 merged 218 commits into
mainfrom
testing
Sep 18, 2026
Merged

tirth8205 merged 218 commits into
mainfrom
testing

Conversation

@tirth8205

Copy link
Copy Markdown
Owner

Pull Request

Linked issue

Closes #

What & why

How it was tested

uv run pytest tests/ --tb=short -q
uv run ruff check code_review_graph/
uv run mypy code_review_graph/ --ignore-missing-imports --no-strict-optional

Checklist

  • Tests added for new functionality
  • All tests pass: uv run pytest tests/ --tb=short -q
  • Linting passes: uv run ruff check code_review_graph/
  • Type checking passes: uv run mypy code_review_graph/ --ignore-missing-imports --no-strict-optional
  • Lines are at most 100 characters
  • Docs updated where behavior changed (README, docs/, docstrings)

dependabot Bot and others added 30 commits August 27, 2026 10:35
Updates the requirements on [sentence-transformers](https://github.com/huggingface/sentence-transformers) to permit the latest version.
- [Release notes](https://github.com/huggingface/sentence-transformers/releases)
- [Commits](huggingface/sentence-transformers@v3.0.0...v6.0.0)

---
updated-dependencies:
- dependency-name: sentence-transformers
  dependency-version: 6.0.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
…nguage-pack path (#807)

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #810
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #872
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #873
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #875
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #955
…int resolution

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #858
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #860
Maintainer corrections and scope extraction applied where needed.
…l_files

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #870
…t of the registry

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #915
Maintainer corrections and scope extraction applied where needed.
… an indexed tail lookup

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #942
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #952
… endpoint evidence (#903)

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #960
…stored paths

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #962
…andidates

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #966
Maintainer corrections and scope extraction applied where needed.
…n references_to

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #969
Maintainer corrections and scope extraction applied where needed.
…ctor workflows

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #821
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #847
Maintainer corrections and scope extraction applied where needed.
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #874
Maintainer corrections and scope extraction applied where needed.
…em locale

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #928
Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #959
…nguage-pack path (#807)

Port the reviewed token-efficiency implementation with targeted regression coverage.

Source-PR: #810
Maintainer corrections and scope extraction applied where needed.
tirth8205 and others added 28 commits September 17, 2026 02:15
Spend the review source budget on whole changed regions, and make churn degrade once
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(search): build FTS5 queries from tokens and index node docstrings
Draw a neighbourhood instead of a repository
cli.py collided on the same function: staging split main() into
build_parser() plus main() so tests can read the flag surface without
running a command, and this branch split main() into a lock-catching
main() plus _dispatch(). The two splits compose: main() keeps the
sqlite lock wrapper, _dispatch() is staging's parse-and-run body, and
build_parser() stays the parser. The seed-flag helpers, _SUBCOMMANDS
and the neighbourhood visualize wiring are unchanged from staging; the
build-state reporting in status and postprocess is unchanged from this
branch.

Also fix the v1 seed in the migration-race test. It hand-rolls a nodes
table, and parent_name and extra are in the base CREATE TABLE that no
migration adds, so a real v1 database has both. Migration v13, which
arrived from staging after that test was written, backfills from them,
so the seed failed on a missing column instead of exercising the
check-then-act window it gates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two conflicts, both resolved by keeping what each side meant.

code_review_graph/cli.py: staging split the parser out of main() into
build_parser() and added the visualize seed-flag helpers; this branch added
_open_graph_store(), the corrupt-cache recovery wrapper. Both are kept:
_open_graph_store() stays where it was, staging's helpers and build_parser()
follow it, and the stale main() stub the conflict duplicated is gone. The two
_open_graph_store() call sites main() already had merged cleanly.

tests/test_action_e2e.py: both sides added this suite independently. This
branch's copy is staging's plus the four strict-xfail markers it retires
(corrupt cache recovery, the truncation budget, git-quoted diff paths, the
sticky comment author filter) and the tests that replace them. Kept that copy,
and restored staging's assertion that the unescaped markdown link is absent
alongside this branch's assertion that the escaped span survives; neither
literal is a bare URL, so tests/test_codeql_url_substring.py stays green.

The five strict xfails that remain record bugs this branch does not fix:
malformed and non-finite risk scores, and line_start escaping.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Six files collided. Resolutions:

pyproject.toml: the pytest markers list. Union of both sides; the
cli_surface entry was identical on each.

tests/conftest.py: three pytest_collection_modifyitems definitions would
have met here (staging already carried two, so its own packaging gate was
dead: pytest resolves the hook by name and only the last definition runs).
Folded into staging's single _OPT_IN_MARKERS hook, with packaging added to
the set and its CRG_RUN_PACKAGING_TESTS escape hatch preserved as a
per-marker override. tests/test_conftest_gates.py now fails if a second
hook is ever added.

code_review_graph/changes.py: both sides kept. The require_vcs path and the
diff_ranges_unavailable summary line sit alongside staging's churn cache,
churn_status and is_test_file-based test-gap detection. Staging's two new
numeric settings (CRG_CHURN_TIMEOUT, CRG_CHURN_MAX_COMMITS) were bare
int()/float() of os.environ.get, which is exactly what #912 removed, so
they now read through constants.env_float / env_int and are covered by the
numeric env var table in tests/test_cli_surface.py.

code_review_graph/graph.py: both sides kept. The GraphStore.__init__ guard
(_assert_usable_database plus the GraphStoreError wrapper) wraps staging's
schema, which now reaches v13; `import os` is gone because env_int replaced
its only use, and `import re` came in for staging's identifier tokenizer.

code_review_graph/cli.py: staging split main() into build_parser() + main();
this branch split it into main() + _run(). Merged as
build_parser() + main() (the CodeReviewGraphError reporter) + _run() (the
dispatch body), so the parser is still importable for tests and every
self-explaining failure still becomes one Error: line and exit 1.

tests/test_cli_surface.py: add/add. Staging's copy is byte-identical to this
branch's own first commit, so this branch's later version supersedes it.

All five fixes re-probed end to end against the merged tree: absent git and
CRG_GIT_TIMEOUT=0 both exit 1 with a named cause instead of "No changes
detected"; four kinds of unusable graph.db each report one line; an
unwritable data directory reports one line for status, detect-changes, wiki
and build; eight numeric variables set to "" and "abc" exit 0 with a warning
naming the variable; a donor repository's graph.db is refused by both the
CLI and _get_store.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…this branch

An independent re-measurement found the kubernetes build-time row wrong in
the direction that favoured this change. It read 149.4s on staging against
129.0s here, which says this branch is faster than staging. Measured isolated
and alternating on one idle machine it is not: staging 115.1s and 122.8s
against 148.7s and 146.5s here, and 4.41 GB of database against 5.36 GB. The
branch is about 24% slower to build and 21.5% larger, never faster.

The CHANGELOG now says that plainly, alongside what the cost buys: on cli/cli
the CALLS edges bound to an indexed node go from 5503 to 22564 of the same
67503, because a bound import gives the call resolver a file to attribute a
cross-file call to.

The comparisons that do hold are against the pre-fix revision of this branch,
which emitted one edge per member file: 524.6s of build against about 146s,
588,972 IMPORTS_FROM edges against 93,650, 73,512 edges naming an unindexed
path against 5, and a 189,163-token get_impact_radius against 23,669. Those
are kept and labelled as what they are.

Also re-measured and corrected, on clean alternating builds of cli/cli,
cobra, gin, jekyll and rubocop against origin/staging:

- the grouped-block line defect is 8636 of cli/cli's 8687 import edges, not
  8648 of 8690
- jekyll's non-require import edges are 31 of 227 (14%), not 34 (15%)
- internal/ is 1317 of the 3495 cli/cli go import edges that bind in-repo,
  not "3493 of 8687"

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Stop the graph and the daemon from corrupting quietly
graph.py was the only overlap. Staging added a read-transaction helper
(contextlib.contextmanager, _active_read_txn, _read_transaction,
_get_stats_locked) and migration-safety retries; this branch added the
package-scoped import resolver and the pinned impact traversal, which
needs collections.abc.Iterable. The import block now carries both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Staging brought the three-state build marker in build_state.py and the
state-aware reporting that `status` and `postprocess` print from it, along
with the contention wrapper that renamed main() to _dispatch() and put a
new main() in front of it to report a locked database instead of raising.

cli.py was the only conflict, and only because both sides inserted a
different block at the same point above _SUBCOMMANDS. Both are kept:
_open_graph_store() stays exactly where it was and is still what both
store-opening sites call, so a corrupt CI cache is discarded by `build`
and reported as one line by everything else; the lock classifier and the
main()/_dispatch() split are taken from staging unchanged, so the two
store-opening sites now sit inside _dispatch() and a contended open is
reported by the wrapper. The _SUBCOMMANDS and build_parser comments take
staging's wording, which names _dispatch.

Verified by probe rather than by reading the diff: a not-a-database file
and a valid SQLite file holding a foreign `nodes` table each produce one
line and exit 1 from a read-only command, and `build` discards and
rebuilds both with no traceback; `status` prints nothing extra for
complete, the missing-files line for in-progress and the post-processing
line for postprocess-pending, with build_incomplete matching in --json;
`postprocess` keeps the marker and prints the "cannot add them" line for
in-progress, and clears it to complete for postprocess-pending. The
branch's own fixes still hold: GraphML carries the graphdrawing namespace
with synthetic NMTOKEN ids and names in <data>, _cypher_props emits true
rather than True, and get_all_tracked_files reads a C-quoted path back as
src/café.py.

Gates: pytest 3981 passed, 793 skipped; the opt-in exports (69 passed),
action_e2e (88 passed) and concurrency (40 passed) suites; ruff clean;
mypy clean over 76 files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both sides wrapped the CLI's dispatch function to report a class of failure
as one line instead of a traceback, and both named their wrapper main().

cli.py: one main() catching both. A CodeReviewGraphError is printed in the
house style (one Error line, exit 1); lock contention keeps its own message
and its own advice. The dispatch function keeps staging's _dispatch name, so
the branch's _run is gone and its tests follow.

graph.py: the two failures meet inside GraphStore.__init__, where the branch
turns any sqlite3.Error into a GraphStoreError. run_migrations re-raises a
held write lock once its retries are spent, so a contended open was being
described as an unreadable database and answered with "delete it and
rebuild". Lock errors are now re-raised untouched and reach main()'s
contention report. The classifier moved to errors.py so cli.py and graph.py
cannot drift apart on what counts as contention.

incremental.py: the import conflict keeps both sides. Staging's new
CRG_MAX_UNWATCHED_TRACKED was parsed with a bare int(os.environ.get(...)),
which is the import-time crash the branch removed from 22 other settings; it
reads through env_int now and joins the coverage table.

Also fixed while probing the branch's five cases: a data directory that
cannot be created still tracebacked out of pathlib.mkdir, because
get_data_dir creates it while the path is being resolved, before any
GraphStore exists. It is now the same one-line GraphStoreError as a
directory that cannot be written to.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix: make the GraphML export readable, and a corrupt CI cache recoverable
One conflict, in GraphStore.__init__ of code_review_graph/graph.py. Staging
wrapped the schema init and migration run in a guard that turns an unreadable
or wrongly shaped database into CorruptGraphDatabaseError; this branch added
the crg_parent_dir SQLite function that the directory-scoped import traversal
joins on. Both are kept: the guard keeps its original scope, and the function
is registered after it, because a failure to register a function is not a
corrupt file and must not reach the code path that deletes a database.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both sides handled a corrupt graph.db and they had to become one thing.

This branch turned every failure the tool understands about itself into a
single `Error: ...` line: a corrupt or foreign database, a data directory it
may not write to, a graph built for another repository root, a git it could
not run, and 22 numeric environment variables that used to raise at import.
Staging added `_open_graph_store`, which lets `build` discard a database it
cannot open and rebuild it, so a restored CI cache stops failing every run.

Resolution:

* `CorruptGraphDatabaseError` now subclasses `GraphStoreError` instead of
  `sqlite3.DatabaseError`. It keeps staging's job (naming the one unusable
  shape a rebuild can fix by itself) and gains this branch's contract
  (nothing the tool can explain reaches a caller as a raw SQLite error). Its
  message is the house line, so `main` reports it and no second message in
  `_open_graph_store` can drift from it.
* `GraphStore.__init__` keeps this branch's structure (mkdir inside the try,
  the connection closed on every failure path, `_assert_usable_database`
  refusing a foreign file or a newer schema before any DDL runs) and gains
  staging's classification step, in an order that protects a healthy graph:
  an already-classified `GraphStoreError` first, contention second,
  corruption only then, and the described failure last.
* A foreign SQLite file and a newer-schema graph stay plain
  `GraphStoreError`s, so `build` never deletes somebody else's data or a
  graph this build is merely too old to read. `_assert_usable_database`
  catches the foreign file before staging's classifiers see it; a readable
  graph.db whose own tables are the wrong shape still reaches them and is
  still recovered.
* cli.py drops staging's second copy of the lock classifier; `is_lock_error`
  in errors.py is the single one.
* Docs say what `build` now does by itself, and that contention is never in
  the discardable list.

Also fixes a canary that was stale on this branch: action.yml's "Fail when
the analysis did not run" step was missing from the expected step list.

Probed, not just read: detect-changes with no git on PATH exits 1 naming the
cause; a read command reports a corrupt database in one line while `build`
discards and rebuilds it; a wrong-shape schema recovers the same way; an
invoices database survives `build` untouched; an unwritable data directory
gives one line; an invalid numeric env var warns and falls back; a donor
repository's graph is refused; and a held write lock is reported as
contention with the database present and byte-identical afterwards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(parser): resolve Go and Ruby imports to files, not bare strings
One conflict, in GraphStore.__init__. Staging (via #1027) registers the
SQLite function crg_parent_dir after the open/migrate guard; this branch
ends that guard with a described GraphStoreError fallback. Kept both: the
fallback stays the last arm of the except, the registration stays after
it, so a failure registering the helper is still not mistaken for a
corrupt database.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix: report what is wrong instead of a false all-clear or a traceback
The release gate on `testing` failed its own coverage assertion: schema v12
added `nodes_fts_state` and no dump section read it, so a table the build
writes was never compared between two rebuilds.

It is not cosmetic. `nodes_fts` is an external-content table, so removing an
entry needs the column values that were indexed, and those are gone once the
node row is. `nodes_fts_state` is the mirror kept for exactly that, which
makes a disagreement here a disagreement about what the next incremental
update will be able to delete.

The section resolves the row's own `node_id` to the node's identity, the way
`flow_memberships` already does, because raw numbering is pinned separately
by `node_id_order`. Columns come from `NODES_FTS_COLUMNS` rather than a
literal list, intersected with what the database actually has, so widening
the mirror widens the comparison with it and an older database still dumps.

Declares a row floor alongside it, since the harness also refuses a section
that could compare empty to empty forever.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…erage

test(determinism): compare the FTS mirror table instead of ignoring it
@github-actions

Copy link
Copy Markdown

code-review-graph review

Overall risk: 0.85 (CRITICAL) — 500 changed function(s)/class(es), 146 affected flow(s), 380 test gap(s)

Risk-scored changes

Risk Level Symbol Location Tested
0.85 critical 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/daemon.py::_signal_until_dead code_review_graph/daemon.py:831 no
0.80 high code_review_graph/search.py::_QueryTerm code_review_graph/search.py:553 no
0.80 high code_review_graph/search.py::_split_query_terms code_review_graph/search.py:561 no
0.75 high code_review_graph/main.py::query_graph_tool code_review_graph/main.py:264 no
0.75 high code_review_graph/search.py::detect_query_kind_boost code_review_graph/search.py:425 yes
0.65 medium code_review_graph/cli.py::_open_graph_store code_review_graph/cli.py:699 no
0.65 medium code_review_graph/cli.py::_check_visualize_flags code_review_graph/cli.py:802 yes
0.65 medium code_review_graph/cli.py::_print_seed_budget code_review_graph/cli.py:848 yes
0.65 medium code_review_graph/constants.py::_warn_invalid_env code_review_graph/constants.py:26 no

Affected execution flows

  • activate — criticality 0.76, 37 node(s) across 8 file(s)
  • registerBlastRadiusCommand — criticality 0.65, 12 node(s) across 3 file(s)
  • main — criticality 0.65, 52 node(s) across 6 file(s)
  • run — criticality 0.64, 28 node(s) across 3 file(s)
  • registerReviewCommand — criticality 0.64, 12 node(s) across 3 file(s)
  • ...and 141 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/build_state.py::read_build_state (code_review_graph/build_state.py:52)
  • code_review_graph/build_state.py::graph_contents_are_complete (code_review_graph/build_state.py:60)
  • code_review_graph/build_state.py::advance_to_postprocess_pending (code_review_graph/build_state.py:72)
  • ...and 375 more without direct tests

Token savings: this graph-backed report used ~1,444,810 fewer tokens (~89%) 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.

@tirth8205
tirth8205 merged commit d5461d6 into main Sep 18, 2026
47 checks passed
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.