Releases: simplecore-inc/coregraph
Releases · simplecore-inc/coregraph
Release list
v0.2.9
Fixed
- Atlas edge total now matches the project picker. Since the bridge omits
Resolvesfrom the graph payload, the loaded atlas showed only the shipped
edge subset (e.g. ~93k) while the picker showed the daemon's fulledge_count
(e.g. 341,776) — the same project appeared to have two different sizes. The
json-graph export now carriestotal_nodes/total_edges(the unfiltered
graph size) and the atlas uses them for the project total in the header,
footer and load toast, so the number is consistent everywhere while the
payload stays small. Exports without the fields fall back to the loaded counts.
v0.2.8
Fixed
- Incremental rebuilds no longer diverge from a clean build. After 0.2.7
stopped the synthetic-Moduleratchet, the watcher'sbuild_graph_incremental
still inflated a daemon's graph by ~6% per rebuild because two derive stages
were not idempotent when re-run on an already-built graph:structural_pass
wrapped nodes added by later passes (DocComment/DocSectionand synthetic
Modulenodes) inContains/BelongsTo, andresolve_references
re-resolvedCalls/Referencesonto theExternalPackagestubs a previous
run had minted. Both now exclude those nodes (containers and doc-layer nodes
are not containment children;ExternalPackagestubs are not resolution
candidates and are reused from the cache), and the Java/KotlinInherits
derivation moved into its own stage afterresolve_referencesso it covers
the resolver's cross-fileExtendsidentically on every run. Re-running the
whole derive pipeline on an unchanged graph is now a no-op, so a long-lived
daemon stays at its clean edge count instead of ballooning over time.
v0.2.7
Fixed
- Daemon no longer ratchets its edge count upward over its lifetime. The
watcher's incremental-rebuild path (build_graph_incremental) re-runs
structural_passon the already-structured cached graph. That pass reused
Filenodes by path but allocated a fresh syntheticModulenode on every
call, so each rebuild re-emitted aBelongsToedge for every symbol while the
old edges survived (their symbols are not invalidated). The containment layer
therefore duplicated on each rebuild and the result was persisted to the
snapshot, so the graph grew further on every restart — a long-lived daemon
reached roughly 3x its clean edge count on a large Java project (e.g. ~917k vs
the true ~341k edges, withBelongsToalone at ~6.5x).structural_passnow
reuses existingModulenodes by name, making it idempotent like theFile
pass; repeated rebuilds hold steady. This is the edge-level counterpart to the
0.2.6 fix for symbol-level heal duplication.
Added
- Atlas (
coregraph viz) omitsResolvesedges from the graph payload.
Name-resolution edges are the bulk of a large graph and are already hidden
from the rendered view, so shipping them only inflated the browser's parse,
memory and filter cost.export_graphgains an optionalexclude_edge_kinds
parameter (absent = full graph, so the CLIexport --format json-graphis
unchanged); the viewer bridges default it to["Resolves"], overridable via
COREGRAPH_VIZ_EXCLUDE_EDGE_KINDS. Cuts the viz payload roughly 3x.
v0.2.6
Fixed
- Daemon no longer inflates symbol and orphan counts over its lifetime. The
on-demand heal path re-extracted changed files with a bareextractor.extract
that never removed the file's existing nodes; becauseinsert_nodealways
allocates a fresh id, every heal duplicated the file's symbols, accumulating
edge-less phantom orphans. A daemon-served graph therefore drifted away from a
clean in-process build the longer it ran (e.g.orphansreporting 933 vs the
true 177 on a 921-file Spring monorepo). The heal loop now shares the surgical
single-file reindex used by thereindexIPC fast-path
(reindex_file_in_place_core: remove the file's old nodes, re-extract, re-link
cross-file edges), which is idempotent on an unchanged file — so repeated heals
leave the graph's symbol and edge counts stable.
v0.2.5
Performance
- Doc-comment indexing no longer recompiles its tree-sitter query per file.
extract_block_doc_commentscompiled its per-language (static) query via
Query::newon every file — thousands of redundant compilations on a large
monorepo (a profiled hot spot after the 0.2.4 resolver fix). The compiled
query is now cached per thread (keyed by the query string, 1:1 with the
language across all callers), shaving ~0.5s off a ~900-file index and more on
doc-comment-heavy trees. Behaviour is unchanged.
v0.2.4
Fixed
- Release builds no longer index large projects pathologically slowly. The
stack-graphs resolver's shadow-suppression step compared every stitched
partial path against every other (O(n²)). Because path stitching is
wall-clock bounded, an optimized (release) build finds far more paths than a
debug build in the same time budget, so the O(n²) post-pass exploded —
release indexing of a ~1k-file monorepo took 8m46s vs 26s for an
unoptimized debug build, with runaway memory. Paths from different
references can never shadow each other, so the comparison is now grouped by
reference and runs only within each (tiny) group, restoring effectively
linear behaviour (~10s on the same project). Affected every prior release
on sufficiently large/interconnected codebases.
v0.2.3
Fixed
- Daemon serves requests during its initial index. The daemon bound its IPC
socket and then indexed the default project synchronously before entering
the accept loop, so a client connecting mid-index (e.g. thevizatlas
bridge probingstatus) was accepted into the listen backlog but never
answered until indexing finished — its receive timeout surfaced as a cryptic
Resource temporarily unavailable (os error 35)"bridge error". The default
project now preloads on a background thread and the accept loop starts
immediately. IPC receive timeouts also report an actionable message
("daemon did not reply … it may still be indexing") instead of the raw OS
errno. - Single daemon instance. Several
server starts firing at once (multiple
MCP/LSP/viz bridges auto-spawning the daemon on a fresh boot) could race
remove_file+bind: losers crashed withAddress already in use, and a
late binder could orphan a second live daemon that held a graph in memory but
owned no socket. A process-lifetime advisory lock now guarantees exactly one
daemon; losers exit cleanly.
Changed
- Indexing always honors
.gitignoreand the default exclude set. The index
walk now applies the universal build-output / dependency excludes (build/,
node_modules/,.gradle/,target/,dist/,out/, …) it already shared
with analysis — previously these were skipped only by.gitignore, so a
project without a (complete).gitignoreindexed and parsed thousands of
generated/vendored files..gitignoreis now honored even outside a git
repository, and excluded directories are pruned at the walk level so large
build/andnode_modules/trees are never descended into.
v0.2.2
Added
coregraph viz --detach/--stop.--detachruns the atlas server in
the background, detached from the terminal session (it survives the terminal
closing), and returns once the port answers; output goes toviz.login the
daemon runtime directory and the instance is recorded inviz.pid. It
refuses to start when the port is already serving.--stopterminates the
recorded instance and cleans up; a record whose port no longer answers is
treated as stale and removed without signaling anything.
v0.2.1
Added
coregraph config recommend [--write]. Derives suggestedconfig.toml
tuning from the indexed graph through four measured signals:[index].exclude
candidates (files dominated by data-kind symbols), astring_match_max_files
cap picked from a projection over candidate caps,[inconsistencies] disable = ["api-path"]when every near-miss pair is same-language-family
(a frontend-only repo has no cross-language contract to drift), and
[analysis].excludecandidates for generated files detected by content
markers (@generated,DO NOT EDIT,Code generated by). Prints a
paste-ready TOML block with per-recommendation reasons (human/json/llm);
--writeapplies it with a comment-preserving merge that aborts before
writing anything when an existing value has an incompatible shape. Also a
daemon method and a sixth MCP tool (recommend).- Config keys
[index] string_match_max_files(default 8,0= unlimited)
and[inconsistencies] disable/api_path_min_segments(default 2). - Config lint.
coregraph index(stderr) andconfig show(inline ⚠)
now warn about TOML parse failures, unknown sections, and unknown keys in
.coregraph/config.tomlinstead of silently ignoring them. - Post-index noise note. Human-format
indexoutput suggests
[index].excludecandidates when a few data-dominated files (config keys /
string literals / doc sections) hold an outsized share of all symbols.
Changed
stats --breakdownis monorepo-aware. Per-package counts come from the
project's own manifests (Cargo workspaces, npm/pnpm workspaces, Maven,
Gradle, …) instead of assuming acrates/directory layout; the
most-referenced table now counts only impact-bearing edges between real
symbols (file/doc containers excluded), so structural edges no longer bury
the actual hubs; synthetic external-package nodes are shown as a labeled
(external)row.- Cross-file StringMatch pairing is capped per string value
(string_match_max_files, default 8): a literal occurring in more distinct
files is treated as a convention string and no longer emits O(k²) edges.
Measured on a real React monorepo this removed roughly half of all
ApiPathMatch edges (previously 27% of the graph). - api-path near-miss reports require two path segments on both sides by
default (api_path_min_segments); single-segment pairs like/authvs
/authsare route-name conventions, not typos. - doc-drift is rename-aware. A single-underscore unused-marker rename
(namedocumented,_namein the signature) is no longer reported;
destructured shorthand parameters ({ a, b }) are recognized; genuine
mismatches now carry closest-signature rename candidates in the detail line
and acandidatesarray in the JSON output.
Fixed
- A malformed glob in
[index].excludeno longer silently disables every
exclude pattern (built-in defaults included); the bad pattern is skipped
with a stderr warning and everything else keeps applying. - JSX component usage across npm-workspace packages now produces symbol-level
Calls edges: bare import specifiers (@scope/pkg,@scope/pkg/subpath)
resolve through the workspace's own manifest (packageexports/module/
main, thensrc/index.*), so cross-package component hubs are visible to
impactinstead of being dropped to the file-level fallback. stats --breakdownno longer prints a nameless top-files row for synthetic
external-package nodes.
v0.2.0
Added
coregraph viz— the atlas viewer. Serves an interactive 3D view of the
symbol graph on127.0.0.1:7321(per-process token guard), fed directly from
daemon memory: project picker with daemon auto-start, fuzzy search,
neighborhood isolate, per-symbol detail with a source preview, analysis
overlays (impact blast-radius gradient with risk and affected tests, dead
code, cross-file inconsistency pairs, git-diff impact, shortest path),
cluster-by-unit with translucent boundary hulls, degree/hub/kind/confidence
filters, share links that restore the exact view, PNG / json-graph export,
and a change poll that offers a one-click reload when the daemon's graph
moves on.- Macro-body call extraction (Rust). Call references inside macro token
trees (json!,format!,assert!, …) are now recovered lexically;
tree-sitter's call patterns never fire inside raw token trees, so these
references were previously missing from the graph. - Daemon IPC methods
export_graph(json-graph dump of the in-memory graph)
andreload_project(forced rebuild from source, bypassing the snapshot).
Changed
impactnow counts transitive dependents only — the symbols that would
break if the seed changed (callers, their callers, …), following incoming
impact-bearing edges. The previous bidirectional walk madereachablea
connectivity count: a depth-5 sweep from a 3-caller helper reached 74% of
this repo's graph through shared callees. File/doc container nodes are
excluded from the cone. Expect substantially smaller (and now meaningful)
reachablenumbers.impactseed disambiguation — among same-name definitions the seed is
now the one with the most incoming dependents, instead of the first match
(which could land on an uncalled twin and report zero impact).