Skip to content

chore(main): release 0.1.0 - #3

Closed
github-actions[bot] wants to merge 4 commits into
mainfrom
release-please--branches--main--components--codegraph-rs
Closed

chore(main): release 0.1.0#3
github-actions[bot] wants to merge 4 commits into
mainfrom
release-please--branches--main--components--codegraph-rs

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

🤖 I have created a release beep boop

0.1.0 (2026-06-21)

Bug Fixes

  • release: drop Windows target; daemon is Unix-socket only (1d973ee)

This PR was generated with Release Please. See documentation.

sunerpy and others added 4 commits June 21, 2026 13:13
…de knowledge graph

CodeGraph-rs parses a codebase, extracts symbols and their relationships, persists
them to a per-project SQLite database (with an FTS5 search index), and exposes the
result through a CLI and an MCP (Model Context Protocol) stdio server. No AI / vector
/ LLM anywhere in the binary — output is deterministic and byte-stable.

Highlights:
- 10-crate workspace (core/store/extract/graph/resolve/mcp/daemon/watch/cli/bench);
  published crate codegraph-rs, binary codegraph.
- 28-language tree-sitter extraction (regular grammars + embedded + custom + file-level),
  deterministic node-id formula, golden byte-stable schema/edges.
- Graph traversal (callers/callees/impact/cycles) + FTS5 multi-signal search +
  whole-graph export with deterministic PageRank centrality.
- MCP stdio server (10 tools) and a CLI agent installer for 8 agents
  (Claude Code, Cursor, Codex CLI, opencode, Hermes, Gemini CLI, Antigravity, Kiro).
- Golden equivalence tests + scope guardrail (no AI/vector/LLM crates).
- Release engineering: pre-push hook, CI (test + audit), release-please with
  5-platform binaries (cargo-zigbuild musl + macOS + windows), git-cliff release
  notes, and topological crates.io publishing.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The Windows binary build failed with E0433 (codegraph-daemon uses
std::os::unix::net::{UnixListener,UnixStream} — a Unix daemon model that
does not compile on Windows). Making the daemon cross-platform (named pipes)
is out of scope, so drop x86_64-pc-windows-msvc from the release matrix and
the dead zip-packaging/upload steps. Document that prebuilt binaries target
Linux + macOS only; on Windows, build from source (CLI/MCP work, daemon does
not). Aligns README (EN/zh-CN) and AGENTS.md to the 4-platform reality.
@sunerpy sunerpy closed this Jun 21, 2026
sunerpy added a commit that referenced this pull request Jul 30, 2026
* docs(upstream): bootstrap v1.5 sync provenance

* test(release): add workspace version gate

* docs(release): record workspace version gate evidence

* fix(release): pin exact cargo metadata argv and harden lock trap

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.

* test(index): add Batch M black-box Red for isolated v2 namespace

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.

* feat(core): add IndexPaths v2 namespace path authority

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.

* feat(index): route init to isolated .codegraph-v2 namespace via IndexPaths

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.

* fix(index): enforce fail-closed IndexPaths in the v2 data plane

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.

* fix(index): close IndexPaths path-authority verification defects

* fix(index): prove byte nonmutation and surface invalid CODEGRAPH_DIR 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.

* fix(index): make the byte-nonmutation oracle fail-closed

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.

* feat(index): add read-only state classifier

* fix(index): harden read-only state classification

* docs(upstream-sync): format the Batch M ledger and correct its final 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.

* feat(store): add reusable index lease capability

* fix(store): harden index lease identity checks

* docs(upstream-sync): record the authoritative Batch M lease final gate

* fix(store): enforce atomic state publisher protocol

* feat(store): add state-gated Store opens

* fix(store): harden state-gated artifact checks

* feat(store): finalize full rebuild before publication

* feat(sync): migrate outdated indexes during incremental sync

* feat(store): make uninit crash recoverable

* test(store): cover writer process lifecycle

* fix(watch): retain watcher trigger paths

* test(store): cover lease owner drop ordering

* test(store): prove read opens never migrate

* fix(watch): resync removed directories

* feat(core): add project-scoped config loading

* docs(upstream-sync): record Batch M acceptance evidence

* fix(mcp): retain reader leases through requests

* test(index): add verified v0.40.4 legacy fixture

* test(mcp): prove long-lived server releases handles per request

* test(mcp): prove a failed engine open is not cached

* feat(config): scope configuration to the addressed project

* docs(upstream-sync): record project-scoped config evidence

* feat(daemon): drain the daemon under uninit through an owner-bound control frame

* fix(daemon): remove the rendezvous socket before releasing its ownership record

* revert(store): drop the out-of-scope daemon-startup sidecar relaxation

* fix(store): recover a killed daemon's leftover WAL on startup

* docs(cli): restore the daemon-startup gate doc comment

* fix(cpp): resolve explicit operator calls to the operator method

* fix(cpp): strip template args from out-of-line method receiver qualifiers

* fix(cpp): compose namespace prefix into out-of-line method qualified names

* fix(c): blank leading attribute macros so functions index under real names

* fix(c): blank only provably attribute-like leading macros

* fix(resolution): calls through an imported singleton resolve to the method

* fix(resolution): literal-receiver builtins and nested locals stop fabricating call edges

* fix(resolution): key resolved-ref cleanup on the row id so sibling call sites survive

* fix(retrieval): score non-ASCII query words so their definers outrank namesakes

* fix(retrieval): seed multi-segment field-name queries with their segment-boundary definers

* fix(graph): guard find_path with an enqueue-once set and expose its queue stats

* fix(cli): node <symbol> --file pins one overload and returns its source body

* fix(resolve): bound the React Route opening-tag scan to the tag itself

* fix(extract): close each DFM object at its own matching end line

* fix(extract): recognize both mapper dialects and resolve qualified refids

* feat(release): publish SHA256SUMS and verify it in both installers

* test(bench): parse KNOWN_DIFFS.md fail-closed and wire it into the golden oracle

* ci(release): gate release asset-name drift across workflow and installers

* docs(godot): record the gdext rejection and engine-free alternatives

* fix(ci): require every gated job to conclude success

`CI Success` rejected only a `failure` result, so a required job that was
`cancelled` or `skipped` still passed the gate. With `cancel-in-progress: true`
a run cancelled by a newer push therefore concluded `CI Success` successfully,
and release-please.yml's `verify-ci` gates the release on exactly that job — so
a release could be cut on a run whose tests never finished.

Read every result from `toJSON(needs)` and accept only `success`; `cancelled`,
`skipped`, and any undocumented future value now fail, and a degenerate needs
context fails closed. The failure output names each job and its actual result.

GitHub Actions cannot express "require every job" — the needs context holds only
what `needs:` lists — so scripts/check-ci-gate.sh asserts from outside the
workflow that the gated set is every job minus an explicitly justified
informational allow-list, and that `coverage` may stay excluded only while
codecov.yml keeps it informational. It also executes the shipped gate body over
a synthetic needs context and pins verify-ci's strict conclusion check, wired
through scripts/guardrail.sh so it runs in make ci, pre-push, and CI.
scripts/tests/ci-gate.test.sh adds a 12-scenario mutation harness including a
negative control showing the old expression admits cancelled/skipped.

* fix(store): detect SQLite sidecars losslessly on non-UTF-8 paths

Sidecar detection built its -wal/-shm names with Path::display(), which replaces
every byte that is not valid UTF-8 with U+FFFD. On a Unix project path carrying
arbitrary bytes those names pointed at files that do not exist, so a hard-killed
daemon's committed, un-checkpointed write-ahead log went unseen: the strict
Current read gate saw a sidecar-free namespace, admitted it, deserialized only
the main database file, and served a stale index missing every WAL-only row.

Route both detection functions through the existing lossless
database_sidecar_path helper (already used by the removal path), so detection and
removal agree on the native path. The Missing-state artifact guard shared the
same construction and is fixed with it. No gate is relaxed: open_for_read still
defaults to allow_live_sidecar = false, recovery still refuses to delete a
non-empty log, still revalidates its exclusive lease before each unlink, and
still keeps its bounded lease deadline.

* docs: point the index, config and rendezvous paths at .codegraph-v2

The index moved to an isolated `.codegraph-v2` root that new binaries never
open, migrate, or write, but the shipped docs still told users to use
`.codegraph`. Following them produced a silent no-op (a v0.40.4 index and
config are ignored) and the golden regeneration recipe copied from a path
that no longer exists.

Correct every stale site against the code: `IndexPaths` derives the DB,
`config.toml`, `codegraph.json` AND the daemon pid/socket/log from
`current_root`, so the rendezvous moved with the index. The watcher ignore
set legitimately covers both spellings (`policy.rs`), and the upgrade notes
name the old root deliberately.

Also correct three factual errors: `sync` is a hash-gated incremental path,
not a full rebuild; extension config is read from exactly one file with no
directory-tree walk; and the release ships six platform binaries, adding
`x86_64-pc-windows-msvc` and `aarch64-pc-windows-msvc`.

Add an "Upgrading from v0.40.4" section to both READMEs: the old index is
neither migrated nor read, a fresh `init` is required, and old config does
not carry over.

Document two reproducibility limits found by running the golden recipe end
to end: `colby.db` is not byte-reproducible (SQLite header counter) and
`schema.sql` records statement order, which shifts with the creating binary.

Docs only. No `.rs`, `Cargo.toml` or `Cargo.lock` change; `reference/golden/`
untouched; the `guardrail.sh` edit is one comment line.

* fix(resolve): bound the React data-router route-object walk to its own object

* docs(godot): correct the gdext build-time dependency claim

* docs: correct the KNOWN_DIFFS path and the retired index root

* docs: record the stale-heal pid-before-socket deletion order as a deferred defect

* test(cli,watch): serialize env-mutating tests behind one lock per crate

* fix(daemon): claim the rendezvous before healing its stale socket

* fix(store): drop needless return in cfg(windows) alias checks

* fix(cli): gate the lease-lifetime metadata helper off windows

* fix(daemon): decide a zero drain budget from the pre-signal session count

* test(daemon): scope the rendezvous socket-file assertions to unix

* docs: record the three PR #173 CI failures and their root causes

* fix(store): classify windows directory flush denial as unsupported

* fix(ci): emit the legacy fixture path in the consumer's path domain

* test(cli): build the nested status project path in the native separator domain

* test(daemon): serialize the idle-window env against the detached spawn

* docs: record the round-six windows path and daemon env-race diagnoses

* fix(daemon): bound the proxy teardown by owed replies, not peer close

* docs: record the round-seven windows proxy teardown diagnosis

* docs: record the round-seven windows proxy teardown diagnosis

* docs: record the codebuild windows verification of the proxy teardown fix

* test(store): tolerate windows mandatory lock refusal in snapshot oracles

* docs: record the round-eight windows snapshot lock-violation diagnosis

* test(store): assert lock length when windows refuses a locked-range read

* docs: record the codebuild round-eight confirmation and the tenth layer

* test(store): derive temp directory names from a monotonic per-process serial

* test(cli): derive installer temp directory names from a monotonic serial

* docs: record the round-nine windows temp-name collision diagnosis

* docs: record the first windows-green codebuild run for rounds eight and nine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant