Skip to content

feat(cross-repo): report run status and skipped legacy stores (#2133) - #2346

Merged
DeusData merged 5 commits into
mainfrom
feat/cross-repo-status
Oct 7, 2026
Merged

DeusData merged 5 commits into
mainfrom
feat/cross-repo-status

Conversation

@DeusData

Copy link
Copy Markdown
Owner

Two follow-ups to the #2133 wildcard fix, both about what cross-repo
intelligence tells the caller.

  1. "Never run" vs "ran, no links". An empty CROSS_* set used to mean
    either one, and no output surface could tell them apart. Every run now
    records a marker in the SOURCE store's store_meta
    (key cross_repo_last_run:, same per-project key pattern as
    coverage_shadow_fp:) once the previous CROSS_* generation has
    been cleaned: last_run_at, outcome (complete|cancelled|failed),
    targets, projects_scanned, total_cross_edges, skipped_projects.
    index_status and the UI layout (next to linked_projects) now carry a
    cross_repo object: {"status":"never_run"} or {"status":"ran", ...}.
    The marker lives beside the edges it describes, so a reindex that
    rebuilds the store drops both together. No new database files and no
    new freshness key.

    New store API cbm_store_meta_get/put. put seeds a missing store_meta
    through the generation path, because creating the table without
    db_uid/mutation_gen would make cbm_store_generation() report malformed
    metadata.

  2. ["*"] skips a pre-Multiple named imports from one specifier produce only a single IMPORTS edge — sibling symbols are invisible to the graph #768 store (since fix(cross-repo): a pre-#768 store no longer aborts ["*"] or wipes edges (#2133) #2343) but only logged it. The
    result now names each one, and the MCP response lists them:
    skipped_projects: [{name, reason:"pre_768_schema",
    hint:"reindex this project"}] (only emitted when non-empty). The
    cross_repo.project_unusable log line is unchanged.

cr_project_exists() is split into cr_project_state() (usable / missing /
legacy) so that the enumerator can tell a legacy store apart from a
foreign .db file. New allocations go through mem_core.

Refs #2133

Two follow-ups to the #2133 wildcard fix, both about what cross-repo
intelligence tells the caller.

1. "Never run" vs "ran, no links". An empty CROSS_* set used to mean
   either one, and no output surface could tell them apart. Every run now
   records a marker in the SOURCE store's store_meta
   (key cross_repo_last_run:<project>, same per-project key pattern as
   coverage_shadow_fp:<project>) once the previous CROSS_* generation has
   been cleaned: last_run_at, outcome (complete|cancelled|failed),
   targets, projects_scanned, total_cross_edges, skipped_projects.
   index_status and the UI layout (next to linked_projects) now carry a
   `cross_repo` object: {"status":"never_run"} or {"status":"ran", ...}.
   The marker lives beside the edges it describes, so a reindex that
   rebuilds the store drops both together. No new database files and no
   new freshness key.

   New store API cbm_store_meta_get/put. put seeds a missing store_meta
   through the generation path, because creating the table without
   db_uid/mutation_gen would make cbm_store_generation() report malformed
   metadata.

2. ["*"] skips a pre-#768 store (since #2343) but only logged it. The
   result now names each one, and the MCP response lists them:
   skipped_projects: [{name, reason:"pre_768_schema",
   hint:"reindex this project"}] (only emitted when non-empty). The
   cross_repo.project_unusable log line is unchanged.

cr_project_exists() is split into cr_project_state() (usable / missing /
legacy) so that the enumerator can tell a legacy store apart from a
foreign .db file. New allocations go through mem_core.

Refs #2133
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData force-pushed the feat/cross-repo-status branch from 5facd38 to e4f9735 Compare September 30, 2026 22:34
CI's cppcheck flags `total` in the cross-repo status writer
(variableScope): it is only read inside the `len < cap` branch. Move
the declaration into that branch. No behaviour change.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Since #2133 a cross-repo result owns heap memory: a wildcard run records
each store it skips in result.skipped_projects, and the caller releases
it with cbm_cross_repo_result_free(). Fifteen tests in test_cross_repo.c
received a result and never released it. The one that seeds a pre-#768
store next to a wildcard target records a skip, so it leaked the skip
array and the skipped project name: 32 bytes in 2 allocations, allocated
in cr_record_skip.

Every assertion still passed. The macOS leak lane (test-lsan-macos) was
the run that reported it, because it builds with Homebrew LLVM and sets
detect_leaks=1. The ordinary macOS runs, the local ones included, are
built with Apple clang, where leak detection is off and cannot be
turned on, so they stayed green.

Each test now releases its result right after the fixture is torn down
and before the first assertion, which is the shape the two tests that
already released theirs use. The release therefore also runs when an
assertion fails, and the scalar fields the assertions read stay valid
after it. The repro_issue523 cases release their results the same way.
They name their targets, so they record no skip and did not leak, but
they hold a result and follow the same ownership rule.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData merged commit 1b581f1 into main Oct 7, 2026
62 of 67 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.

1 participant