Skip to content

feat: sync portable fixes from upstream colby v1.5.0 - #173

Merged
sunerpy merged 91 commits into
mainfrom
feat/upstream-v1.5-portable-fixes
Jul 30, 2026
Merged

feat: sync portable fixes from upstream colby v1.5.0#173
sunerpy merged 91 commits into
mainfrom
feat/upstream-v1.5-portable-fixes

Conversation

@sunerpy

@sunerpy sunerpy commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

Ports every portable fix from upstream colby/codegraph v1.5.0 (86-commit range), plus the correctness defects found while verifying them.

Upstream ports — 15 behavioral landings across four batches:

  • Batch B — C/C++ extraction: explicit operator calls, template-arg stripping on out-of-line method receivers, namespace prefix composition, and evidence-gated C attribute-macro blanking.
  • Batch C — resolution: imported-singleton member resolution, literal-receiver/nested-local suppression, and row-id keyed unresolved-ref cleanup.
  • Batch A — retrieval/CLI: Unicode search scoring, multi-segment field-name seeding, find_path enqueue-once, and node <symbol> --file returning the pinned overload's source.
  • Batch D — extractors: bounded React opening-tag and data-router object scans, DFM end_line, MyBatis dialect + qualified refids.

Release integrity — deterministic SHA256SUMS published with every release and fail-closed verification in both installers; a drift guard asserting the asset-name contract across the workflow and both installers; KNOWN_DIFFS.md wired into the equivalence oracle as a fail-closed executable allowlist; and a CI Success gate that now requires every job to conclude success rather than merely not failure.

Correctness fixes found during verification:

  • Lossless SQLite sidecar detection — Path::display() lossily replaced non-UTF-8 bytes, so a hard-killed daemon's committed WAL went undetected and a stale index was served as Current.
  • Hard-kill WAL recovery under proven-dead ownership.
  • Rendezvous cleanup ownership: both the owned path and the stale-heal path now claim the namespace before deleting anything in it.
  • Test isolation: one env lock per crate with an active escape detector, replacing three non-exclusive locks and three unlocked env mutations.

Verification

  • make ci CARGO='cargo --locked' green at default parallelism, run repeatedly.
  • Equivalence oracle 28/28; reference/golden/ changes confined to cpp/ and purely additive, with every pre-existing node ID preserved object-for-object.
  • Cargo.lock unchanged (750ee84b…); no hand-bumped versions.
  • Every behavioral change carries a negative control proving its test reddens without the fix.
  • Four independent review passes (invariants/determinism, security/lifecycle, port fidelity/scope, release readiness/documentation honesty) reviewed the branch and their findings were resolved or adjudicated in the ledger.

Known limitations

  • Windows targets are validated by code inspection only; this is their first real CI run.
  • One ETXTBSY test flake (stub written then immediately exec'd) remains unfixed; it has not reproduced recently.

sunerpy added 30 commits July 25, 2026 04:29
Run cargo metadata from the workspace root so its argv is exactly
'metadata --locked --no-deps --format-version 1' with no --manifest-path,
while still accepting any caller cwd. Make the EXIT trap treat a
deleted/unreadable Cargo.lock as changed so it deterministically exits 90
under set -e. Commit the Scenario B exclude fix and add argv-exactness and
trap mutation/deletion regressions. Correct the evidence ledger transcript.
Add the initial black-box behavioral Red for Batch M: `codegraph init`
must build the index in the isolated sibling `.codegraph-v2` namespace,
never the fixed legacy `.codegraph` root. The test uses only the shipped
public CLI surface and filesystem artifacts and imports no proposed Green
API. On the v0.40.4 base it fails behaviorally because init still writes
the legacy namespace. Record the pre-Red provenance/base gates, exact
command/exit status, and failing assertion in the evidence ledger.
Introduce codegraph-core::IndexPaths as the single path authority for the
isolated v2 index namespace (frozen plan Batch M, lines 236-338). It resolves,
for a project and optional CODEGRAPH_DIR override:

- the physical projectIdentity (full lowercase SHA-256 of a versioned binary
  payload: st_dev/st_ino on Unix, volume serial + 128-bit FileIdInfo on
  Windows), failing closed on unsupported filesystems with no lexical fallback;
- the normalized legacy-root set (fixed .codegraph plus the configured old CLI
  root) that new binaries never open;
- the isolated current root (.codegraph-v2 by default; a <name>-v2-<identity>
  sibling of a configured legacy root), plus every current-root artifact path
  (db, permanent lock, two fixed state slots, tombstone, config.toml,
  codegraph.json, daemon pid/log/socket).

Path identity is physical: canonicalize the project and legacy roots, anchor a
not-yet-created root on its nearest existing ancestor, and fail closed on
empty/root/dot/parent aliases, symlink/reparse components below that ancestor,
legacy equality, and ancestor/descendant overlap. Two distinct projects sharing
a configured root receive distinct identity-suffixed current roots.

Also adds infallible transitional helpers (current_root_lenient,
current_db_lenient) and is_reserved_index_dir for the data-plane wiring in the
next slice. This commit is the path layer only; the state-slot/lease/Store open
protocol that consumes these paths lands in a later Batch M task.
…Paths

Move the default index storage root that public `codegraph init` writes from
the fixed legacy <project>/.codegraph to the isolated sibling
<project>/.codegraph-v2, turning the initial Batch M black-box Red
init_writes_isolated_v2_namespace_not_legacy_codegraph green.

Data-plane consumers routed through the codegraph-core::IndexPaths authority
(current_root_lenient / current_db_lenient) so no code reconstructs the
.codegraph-v2 literal and the read/write sites all agree:
- codegraph-cli main.rs codegraph_dir/db_path (central helper for init, index,
  sync, status, unlock, open_store, is_initialized, remove_db_files, spill);
- codegraph-mcp CodeGraphEngine::open + roots::db_path_for, so the
  stdio/HTTP/daemon MCP request path reads the same namespace init writes;
- codegraph-watch sync::default_db_path for watcher/catch-up sync;
- codegraph-extract scan_dir now skips the whole .codegraph/.codegraph-*
  family via IndexPaths::is_reserved_index_dir, so a project never scans its
  own v2 index storage back into the graph.

Directly-affected staging/read tests move the DB (and CLI-owned lock/uninit
root) from .codegraph to .codegraph-v2. Daemon rendezvous paths
(daemon.pid/sock/log) and the MCP must-not-self-index assertions stay on
.codegraph; Config::discover, the codegraph.json ancestor walkers, and the
benchmark oracle are deliberately unchanged and recorded as remaining Batch M
consumers for the next integration task.
Close the transitional configured-root bypass rejected in verification and
tighten the Batch M path authority:

- Delete current_root_lenient/current_db_lenient. CLI codegraph_dir/db_path,
  codegraph-mcp CodeGraphEngine::open, and codegraph-watch default_db_path now
  resolve through fail-closed IndexPaths::resolve, honoring the configured
  CODEGRAPH_DIR identity-suffixed sibling. CODEGRAPH_DIR=. / .. / root / overlap
  / symlink aliases now error before any root or DB creation and never mutate
  the legacy namespace; two projects sharing one configured root get distinct
  identity roots. Existence-probes that must stay infallible (CLI is_initialized
  and status, mcp roots::db_path_for) degrade to the safe default and never open
  a reconstructed configured-root path; the authoritative rejection is in
  CodeGraphEngine::open.
- Replace the over-broad is_reserved_index_dir(".codegraph-" prefix) with
  IndexPaths::reserved_child_dir_names, the exact resolved root set matched only
  as direct children of the project root, so a user .codegraph-sources/ stays
  scannable while .codegraph and .codegraph-v2 are excluded.
- Detect Windows junctions/reparse points via FILE_ATTRIBUTE_REPARSE_POINT in
  addition to FileType::is_symlink.
- Capture GetFileInformationByHandleEx's OS error before CloseHandle so the
  diagnostic is not masked.
- Remove the state_slot(usize) modulo-alias API; state_slots() is the exact
  0/1 contract for this slice.
- Create the .codegraph rendezvous parent before opening daemon.log in the
  parent-side detached-spawn redirect, since the current namespace is the
  sibling .codegraph-v2 and .codegraph may not exist yet.

Adds real public-surface CLI regressions (configured relative/absolute root
sibling, two-project collision, CODEGRAPH_DIR=. fails closed byte-nonmutating)
and a scanner regression proving .codegraph-sources is indexed. The initial
black-box Red stays green; cargo test --workspace --locked passes.
…via MCP

Correction #3 for Batch M IndexPaths verification. Two claims of 7652267 were
overclaims and are superseded here (no amend; prior commits preserved).

Byte-proof snapshots: the CLI nonmutation oracle captured (path, byte LENGTH),
so an equal-length in-place write was invisible. tree_snapshot now captures the
COMPLETE bytes per file via symlink_metadata, comparison moved into
assert_tree_bytes_unchanged (reports only changed paths), and a harness self-test
flips one byte at constant length to prove the assertion fails.

Reachable invalid-config state: db_exists_for collapsed unsafe-configured-root
and absent-DB into one bool that both MCP front-ends consumed before
CodeGraphEngine::open, so CODEGRAPH_DIR=. emitted the generic "No indexed
project" and the actionable IndexPaths diagnostic was unreachable. roots.rs now
carries typed RootStatus/ProjectArg states discriminated by error VARIANT (never
by parsing rendered strings), with one shared resolve_project_arg both front-ends
delegate to; candidate order is unchanged and an indexed candidate still wins
over an earlier invalid one.

New public-surface regressions stage a trap DB at the default .codegraph-v2
namespace under a refused CODEGRAPH_DIR=. and prove both the hand-rolled and the
shipped rmcp tool call fail closed with the stable reason, serve no trap symbol,
and mutate zero project bytes. Test env mutation is now panic-safe via an RAII
EnvGuard holding the serializing lock.

No dependency, schema, node-id, or golden change; Cargo.lock byte-identical.
The nonmutation oracle added in 7d95634 stat'd entries with
symlink_metadata but read them with fs::read, which follows the link, so
the "never follows links" claim was false. It also converted I/O errors
into false "unchanged" results (read_dir early-return, entry
filter_map(Result::ok), read().unwrap_or_default()) and recorded only
files, hiding empty-directory mutations.

Both oracles now build typed entries: an OS-native relative PathBuf plus
Directory | RegularFile(complete bytes) | Symlink(read_link target).
Every I/O step panics with a path-naming message instead of skipping or
defaulting, and an entry kind without a deterministic exact
representation panics rather than being omitted. Failure messages stay
bounded, naming paths and kind labels but never file bytes.

New cfg(unix)-gated self-tests prove the properties mechanically:
empty-directory creation/removal is detected, a symlink retarget is
detected while an out-of-tree write to its target is not (proving no
follow), and a special entry kind makes the snapshot panic.

Also removes the stale documentation left by the previous correction:
roots::db_path_for and McpServer::engine_for no longer claim
CodeGraphEngine::open surfaces the authoritative invalid-config error,
which the shared typed resolver now raises before any engine is opened,
and the MCP test module doc describes both server front-ends.

Test-only plus comments; no production behavior, dependency, schema,
node-id, or golden change.
…gate evidence

The Batch M classifier validation evidence was appended after the last oxfmt
pass, so the committed ledger was not formatter-clean and the next `make ci`
failed at `fmt-check` before any test ran.

Reformat the ledger with oxfmt and append a dated correction that keeps both
historical daemon_single_watcher_fires_once attempts as history, records the
doc-format failure observed after 224e762, and states the authoritative
post-format gate result.

Documentation only: no Rust, manifest, schema, golden, or Cargo.lock change.
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.35492% with 142 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/codegraph-cli/src/main.rs 87.23% 61 Missing ⚠️
crates/codegraph-core/src/index_paths.rs 94.73% 27 Missing ⚠️
crates/codegraph-daemon/src/lock.rs 93.39% 21 Missing ⚠️
crates/codegraph-daemon/src/control.rs 96.66% 7 Missing ⚠️
crates/codegraph-daemon/src/lib.rs 96.44% 7 Missing ⚠️
crates/codegraph-core/src/config.rs 97.84% 5 Missing ⚠️
crates/codegraph-daemon/src/session.rs 97.56% 3 Missing ⚠️
crates/codegraph-extract/src/lang/c.rs 97.61% 3 Missing ⚠️
crates/codegraph-extract/src/lang/cpp.rs 94.64% 3 Missing ⚠️
crates/codegraph-daemon/src/paths.rs 98.11% 2 Missing ⚠️
... and 3 more

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #173      +/-   ##
==========================================
- Coverage   95.27%   95.03%   -0.24%     
==========================================
  Files         124      135      +11     
  Lines       61316    69512    +8196     
==========================================
+ Hits        58416    66061    +7645     
- Misses       2900     3451     +551     
Files with missing lines Coverage Δ
crates/codegraph-cli/src/installer/mod.rs 95.66% <100.00%> (+0.75%) ⬆️
crates/codegraph-cli/src/installer/registry.rs 98.57% <100.00%> (+0.01%) ⬆️
crates/codegraph-cli/src/installer/shared.rs 95.00% <100.00%> (+<0.01%) ⬆️
...ates/codegraph-cli/src/installer/targets/claude.rs 95.40% <100.00%> (+0.01%) ⬆️
crates/codegraph-daemon/src/proxy.rs 95.87% <100.00%> (+1.38%) ⬆️
crates/codegraph-daemon/src/spawn.rs 95.62% <100.00%> (+1.63%) ⬆️
crates/codegraph-daemon/src/transport.rs 100.00% <ø> (ø)
crates/codegraph-extract/src/embedded/dfm.rs 97.14% <100.00%> (+0.30%) ⬆️
crates/codegraph-extract/src/embedded/mybatis.rs 96.66% <100.00%> (+0.89%) ⬆️
crates/codegraph-extract/src/lang/mod.rs 100.00% <ø> (ø)
... and 49 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

sunerpy added 22 commits July 29, 2026 13:57
@sunerpy
sunerpy merged commit 5d795a5 into main Jul 30, 2026
7 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