Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
291 commits
Select commit Hold shift + click to select a range
27e4299
feat(graph): Phase 2c ResolveImportAware (Kuzu + DuckDB)
zzet May 25, 2026
c4acf26
feat(graph): Phase 3a ResolveRelativeImports (Kuzu + DuckDB)
zzet May 25, 2026
4224817
feat(graph): Phase 3b ResolveExternalCallStubs (Kuzu + DuckDB)
zzet May 25, 2026
c7f86ef
feat(graph): Phase 3c ResolveCrossRepo (Kuzu + DuckDB)
zzet May 25, 2026
c08e6c8
feat(graph/store_ladybug): Phase 4b BackendResolver port
zzet May 25, 2026
1e6d148
feat(graph/store_cozo): Phase 4a BackendResolver Datalog port
zzet May 25, 2026
14e7505
chore(graph): drop store_cozo backend
zzet May 25, 2026
15dbbb3
fix(indexer): redirect resolver graph through shadow swap
zzet May 25, 2026
3139290
perf(bench): per-MCP-tool latency breakdown in store-bench
zzet May 25, 2026
52d17c9
test(bench): node-diff + edge-diff harnesses for cross-backend confor…
zzet May 25, 2026
409761d
fix(resolver): rebind cross-file Go method receivers onto canonical type
zzet May 25, 2026
6f6f777
test(bench): kuzu-stubs diagnostic for cross-backend node-count audit
zzet May 25, 2026
d4a4c44
perf(go-extractor): encode local/closure IDs as function-relative off…
zzet May 25, 2026
3db5834
feat(go-extractor): materialise intra-function locals as KindLocal nodes
zzet May 25, 2026
3d3da48
feat(resolver): scope-aware bare-name binding (locals + params)
zzet May 25, 2026
6eb8fb7
feat(resolver): bind generic-type-param refs to KindGenericParam
zzet May 25, 2026
e64a841
feat(resolver): attribute Go language intrinsics to builtin::go::*
zzet May 25, 2026
f136387
feat(go-extractor): preserve package qualifier on dataflow selectors
zzet May 25, 2026
a2f4101
feat(resolver): materialize Go stdlib/dep/external call targets
zzet May 25, 2026
b84a611
feat(ts-extractor): materialize let/const/var bindings as KindLocal
zzet May 25, 2026
624a3b4
chore(graph): drop store_kuzu backend (upstream public-archived)
zzet May 25, 2026
c652383
feat(ladybug): native FTS via SymbolSearcher capability interface
zzet May 25, 2026
8365023
feat(indexer): drive backend SymbolSearcher through the shadow drain
zzet May 25, 2026
10e5241
feat(search): route Engine.SearchSymbols through Ladybug FTS
zzet May 25, 2026
b414767
perf(indexer): skip Bleve auto-upgrade when SymbolSearcher is active
zzet May 25, 2026
486d21e
perf(bench): add fts_search column to store-bench
zzet May 25, 2026
1fe080d
feat(ladybug): VectorSearcher capability via native HNSW
zzet May 25, 2026
66da687
feat(indexer): mirror embeddings into backend VectorSearcher
zzet May 25, 2026
163ea9f
perf(search): skip in-process HNSW build when backend has VectorSearcher
zzet May 25, 2026
e0b1c1e
bench(store): add vector_search column + in-process HNSW baseline
zzet May 25, 2026
36a728a
test(ladybug): probe ALGO extension surface (PROJECT_GRAPH + 6 algos)
zzet May 25, 2026
f266fe6
feat(algo): graph.PageRanker capability + ladybug impl + analyze kind…
zzet May 25, 2026
f80bfff
feat(algo): graph.CommunityDetector capability + ladybug Louvain + an…
zzet May 25, 2026
90e6561
feat(algo): graph.ComponentFinder + ladybug WCC/SCC + analyze kind=wc…
zzet May 25, 2026
9fc3fd6
feat(algo): graph.KCorer capability + ladybug k-core + analyze kind=k…
zzet May 25, 2026
b02e47d
bench(store): per-algo columns (pagerank, louvain, wcc, scc, kcore)
zzet May 25, 2026
68346f2
bench(multi-repo): harness that drives MultiIndexer across backends
zzet May 25, 2026
a3f5101
refactor: mcp.Server.graph + analysis/etc. take graph.Store, not *gra…
zzet May 25, 2026
b905507
feat(daemon): --backend memory|ladybug flag swaps the storage engine
zzet May 25, 2026
8d4f497
fix(ladybug): SymbolFTS bulk upsert .tsv → .csv
zzet May 25, 2026
f591b82
feat(daemon): smoke-test fixes — multi-repo gate, snapshot cache, wri…
zzet May 25, 2026
27a9c15
feat(multi-repo): per-repo prefix on stubs + per-Indexer shadow-swap …
zzet May 25, 2026
b2201e3
perf(ladybug): connection pool + per-repo unresolved-stub prefix
zzet May 25, 2026
8eb9ef3
feat(daemon): wire --backend / --backend-path into gortex daemon start
zzet May 25, 2026
d66dad6
fix(mcp): preserve full arguments through streamable->router->local-e…
zzet May 25, 2026
8eebcad
docs(graph): BulkLoader may be re-entered on a non-empty store
zzet May 25, 2026
4cf9a3b
perf(indexer): bulk-batch contracts commit through BulkLoader
zzet May 25, 2026
e30c711
fix(indexer): skip dep contracts in bulk commit to avoid PK collision
zzet May 25, 2026
49275c8
feat(graph): GetRepoEdges on Store + backend impls + conformance test
zzet May 25, 2026
0b84b9c
perf(indexer): replace per-node OutEdges walks with GetRepoEdges
zzet May 25, 2026
fef9ffc
fix(contracts): drop COPY bracket from bulkCommit; UNWIND-batch nodes…
zzet May 25, 2026
cdbc4a9
feat(graph): GetNodesByIDs on Reader + OverlaidView impl
zzet May 25, 2026
8ce8614
perf(query): batch-materialise search candidates via GetNodesByIDs
zzet May 25, 2026
8f2b4d8
perf(mcp): batch GetNode in analyze(pagerank) and check_references
zzet May 25, 2026
99e2c67
chore(graph): drop store_sqlite backend
zzet May 25, 2026
c1a19ff
chore(graph): drop store_duckdb backend
zzet May 25, 2026
af0c3db
chore(bench,cli): drop sqlite/duckdb branches from bench tools and co…
zzet May 25, 2026
42744ed
chore: tidy go.mod after backend removal
zzet May 25, 2026
2f6476b
perf(query,mcp): batch GetNode in find_usages and analyze(kcore)
zzet May 25, 2026
bdf05d3
perf(query): batch GetNode in FindUsages via GetNodesByIDs
zzet May 25, 2026
0b13b08
perf(mcp): batch GetNode in notes auto-link, replay_episode, tests_as…
zzet May 25, 2026
1958112
perf(ladybug): cache PROJECT_GRAPH across algo calls; rebuild on writ…
zzet May 25, 2026
356f6c6
feat(graph): batch edge fetch — GetInEdgesByNodeIDs + GetOutEdgesByNo…
zzet May 26, 2026
4f9ed9d
perf(rerank): batch edge fetches in prepare + signals + retriever
zzet May 26, 2026
d080585
test(bench): end-to-end daemon bench harness for memory vs ladybug
zzet May 26, 2026
ebf2988
chore: fix make lint — errcheck, staticcheck QF/ST, unused funcs
zzet May 26, 2026
8dbd7cc
perf(mcp): per-phase timing instrumentation in search_symbols
zzet May 26, 2026
94a1ea3
perf(search): combine expansion terms into one BM25 query
zzet May 26, 2026
dd5724b
perf(graph): FindNodesByNameContaining — push substring filter into b…
zzet May 26, 2026
b2b46cb
fix(ladybug): serialise concurrent BeginBulkLoad on shared Store
zzet May 26, 2026
15cbf54
feat(graph): SymbolBundle + SymbolBundleSearcher capability + ladybug…
zzet May 26, 2026
4d01cb4
perf(query): gather search candidates as backend bundles to skip rera…
zzet May 26, 2026
74a31fd
perf(rerank): skip Context.prepare's batched edge fetch when bundle-s…
zzet May 26, 2026
a6c6c6d
perf(query): inner per-call rerank inherits the bundle edge cache fro…
zzet May 26, 2026
d305ce0
perf(search): skip inner engine rerank + vector-only channel pull
zzet May 26, 2026
214a42b
perf(ladybug): parallelise SearchSymbolBundles' 3 post-FTS sub-cyphers
zzet May 26, 2026
ab1b52b
perf(search): identifier-shape fast path — skip expansion + vector fo…
zzet May 26, 2026
cee3e64
perf(search): dedupe FindNodesByName across fan-outs + tighten fetchL…
zzet May 26, 2026
cec4d3c
test(bench): all-tools-bench harness covering ~78 MCP tools end-to-end
zzet May 26, 2026
b711a54
fix(analyze): batch dead_code's per-node GetInEdges + drop AllEdges scan
zzet May 26, 2026
74ec6ca
feat(graph): DeadCodeCandidator + IfaceImplementsScanner capabilities…
zzet May 26, 2026
f63010d
perf(analyze): push dead_code candidate filter into the storage layer
zzet May 26, 2026
2652d0d
feat(graph): NodeDegreeAggregator + NodeFanAggregator capabilities + …
zzet May 26, 2026
2cda689
perf(analyze): push connectivity_health's per-node degree probe into …
zzet May 26, 2026
415ad28
perf(analyze): push find_clones' SimilarTo edge walk into the storage…
zzet May 26, 2026
90b3dff
perf(analyze): push find_co_changing_symbols' CoChange edge walk into…
zzet May 26, 2026
73e2839
perf(analyze): push cycles' AllEdges scan into per-kind streaming
zzet May 26, 2026
12ffb0f
fix(test): align test helpers with graph.Store interface drift
zzet May 26, 2026
1a96c69
perf(analyze): push hotspots' AllEdges scan into the storage layer
zzet May 26, 2026
84de0fe
perf(analyze): push health_score's AllEdges scan into the storage layer
zzet May 26, 2026
5b37b44
perf(analyze): push impact's AllEdges scan into the storage layer
zzet May 26, 2026
363f0e4
feat(graph): FileImporters + InEdgeCounter + NodesInFilesByKindFinder…
zzet May 26, 2026
3b3caca
perf(mcp): push check_references' importing-files scan into the stora…
zzet May 26, 2026
0153ae0
perf(mcp): push get_untested_symbols' fan-in scan into the storage layer
zzet May 26, 2026
f8b979c
perf(mcp): push find_declaration's file-symbol index into the storage…
zzet May 26, 2026
50fcb5d
perf(mcp): graph_completion_search seeder reuses FindNodesByNameConta…
zzet May 26, 2026
41a42ac
perf(mcp): push graph_query's seed scan into the storage layer
zzet May 26, 2026
e790979
perf(dataflow): push taint_paths candidate seed into the storage layer
zzet May 26, 2026
e8541cb
perf(mcp): push search_ast's file-target enumeration into the storage…
zzet May 26, 2026
396a13d
fix(dataflow): drop dead taintEligible helper left by taint_paths pus…
zzet May 26, 2026
b5f8efb
feat(graph): EdgesByKindsScanner capability + ladybug impl + conformance
zzet May 26, 2026
de168f9
perf(analyze): push edge-driven analyzers' kind filter into the stora…
zzet May 26, 2026
b71dcc6
perf(analyze): push string_emitters / log_events / sql_call_sites kin…
zzet May 26, 2026
b4b8b70
perf(analyze): push race_writes / unclosed_channels kind filter into …
zzet May 26, 2026
b791980
perf(analyze): push k8s_resources / images / kustomize kind filter in…
zzet May 26, 2026
90bdeba
perf(analyze): push routes / models / components / dbt_models kind fi…
zzet May 26, 2026
7bde699
perf(analyze): push tests_as_edges kind filter into the storage layer
zzet May 26, 2026
5e036ef
feat(graph): NodesByKindsScanner capability + ladybug impl + conformance
zzet May 26, 2026
f751a1b
perf(analyze): push metadata analyzers' candidate filter into the sto…
zzet May 26, 2026
8a36b2d
feat(graph): EdgeKindCounter + CrossRepoEdgeAggregator + FileImportAg…
zzet May 26, 2026
e9e1ced
perf(mcp): push overview-aggregate scans into the storage layer
zzet May 26, 2026
daf056b
perf(mcp): push per-node degree counts into the storage layer
zzet May 26, 2026
026d2b5
perf(mcp): push get_coupling_metrics's edge filter through EdgesByKind
zzet May 26, 2026
dbce3a8
perf(mcp): short-circuit unscoped edge counts via EdgeCount()
zzet May 26, 2026
f5028e8
feat(graph): InDegreeForNodes + ReachableForwardByKinds + ThrowerErro…
zzet May 26, 2026
7631dac
perf(analysis): push betweenness adjacency build through EdgesByKinds
zzet May 26, 2026
0710479
perf(mcp): push analyze(health_score)'s candidate scan into NodesByKi…
zzet May 26, 2026
ff4e4c9
perf(mcp): push get_knowledge_gaps's candidate scan into NodesByKinds…
zzet May 26, 2026
a72a320
perf(mcp): push get_untested_symbols' candidate scan + test-reachabil…
zzet May 26, 2026
10cebbb
perf(mcp): push get_surprising_connections's in-degree pass into the …
zzet May 26, 2026
ebdba4c
perf(mcp): push analyze(error_surface)'s thrower joins into the stora…
zzet May 26, 2026
8a8b584
perf(analysis): push FindHotspots + ComputeBetweenness node scans int…
zzet May 26, 2026
b85e0fb
perf(mcp): push get_repo_outline's full-graph scans into Stats() + Fi…
zzet May 26, 2026
5f33819
perf(mcp): push get_architecture's full-graph scans into Stats() + No…
zzet May 26, 2026
6b9f13e
perf(mcp): push gortex_wakeup's full-graph scans into Stats() + Nodes…
zzet May 26, 2026
1e06f4a
perf(mcp): revert get_surprising_connections to AllEdges-driven in-de…
zzet May 26, 2026
3cee99b
perf(mcp): cache default-threshold hotspots in RunAnalysis
zzet May 26, 2026
f64eda8
style: clean up lint findings from pushdown wave
zzet May 26, 2026
d4e0556
feat(graph): EdgeAdjacencyForKinds capability + ladybug impl + confor…
zzet May 27, 2026
4ca5a55
perf(analysis): use EdgeAdjacencyForKinds in ComputeBetweenness
zzet May 27, 2026
66a441f
feat(graph): CommunityCrossingsByKind capability + ladybug impl + con…
zzet May 27, 2026
ec4ab8a
perf(analysis): use CommunityCrossingsByKind in FindHotspots
zzet May 27, 2026
3b47ef3
feat(graph): NodeIDsByKinds capability + ladybug impl + conformance
zzet May 27, 2026
a7aecfc
perf(analysis): use NodeIDsByKinds in betweenness + hotspots node ite…
zzet May 27, 2026
af11c8a
perf(ladybug): malloc pressure relief after large query / drain batches
zzet May 27, 2026
a21f37d
chore: vendor go-ladybug v0.13.1 into internal/thirdparty/
zzet May 27, 2026
e78e738
fix(ladybug-go): destroy lbug_value in FlatTuple.GetValue + audit Get…
zzet May 27, 2026
820b9bd
fix(ladybug-go): free CString after lbug_value_create_string + struct…
zzet May 27, 2026
c091159
chore(ladybug-go): drop test-only deps + unused helper + unused ctx p…
zzet May 27, 2026
e58a941
feat(ladybug): cap buffer pool at 4 GiB by default + --backend-buffer…
zzet May 27, 2026
9c35444
feat(graph): MemberMethodsByType + StructuralParentEdges + CrossRepoC…
zzet May 27, 2026
896d985
perf(resolver): push InferImplements + InferOverrides global walks in…
zzet May 27, 2026
20700fb
perf(resolver): push DetectCrossRepoEdges scan into CrossRepoCandidates
zzet May 27, 2026
36539d8
feat(graph): carry RepoPrefix on MemberMethodInfo
zzet May 27, 2026
05ae8e3
perf(resolver): push ResolveGRPCStubCalls + buildGRPCHandlerIndex N+1…
zzet May 27, 2026
3d866b9
perf(resolver): drop AllNodes scans + per-edge GetNode loops in Resol…
zzet May 27, 2026
ebf47a2
perf(resolver): narrow SynthesizeExternalCalls to call-like kinds + b…
zzet May 27, 2026
b0eb4e7
perf(indexer): drop per-edge GetNode in markTestSymbolsAndEmitEdges
zzet May 27, 2026
3871f17
chore: drop now-dead helpers left behind by the pushdown wave
zzet May 27, 2026
c41ebec
perf(mcp): short-circuit analyze[clusters] when the graph token is un…
zzet May 27, 2026
95132a6
feat(graph): ExtractCandidates + FileSymbolNamesByPaths + ClassHierar…
zzet May 27, 2026
76a6eb5
perf(mcp): push get_extraction_candidates's AllNodes+per-node loop in…
zzet May 27, 2026
50ddc8b
perf(mcp): push get_class_hierarchy BFS into ClassHierarchyTraverser
zzet May 27, 2026
dfe49b9
perf(mcp): push get_editing_context and GetFileSymbols into batched l…
zzet May 27, 2026
71c9b4e
perf(mcp): batch symbol-name lookups in find_co_changing_symbols via …
zzet May 27, 2026
0d5a946
perf(mcp): push get_knowledge_gaps degree aggregate through NodeDegre…
zzet May 27, 2026
99533c2
perf(mcp): widen analyze[clusters] cache hit to graph-token parity alone
zzet May 27, 2026
36aa7a2
perf(mcp): unblock find_co_changing_symbols by mining co-change async…
zzet May 27, 2026
e829b45
perf(mcp): cap per-cluster member fetch in analyze[clusters]
zzet May 27, 2026
89ae709
feat(mcp): pre-compute churn data so get_churn_rate stops blaming on …
zzet May 27, 2026
48c02e2
feat(mcp): pre-compute releases timeline so analyze[releases] stops w…
zzet May 27, 2026
5cf322f
perf(mcp): stream computeETag + structural etagSubGraph for file_summary
zzet May 27, 2026
93c82b8
feat(graph): EdgeContains kind for file → side-band children
zzet May 27, 2026
ab5dc43
feat(graph,mcp): GetFileSubGraph(Counts) capabilities + tighter file_…
zzet May 27, 2026
83d00f7
perf(ladybug): file→nodeIDs accelerator + native FileSubGraph(Counts)
zzet May 27, 2026
10955a3
feat(daemon): persist file mtimes for warm-restart reconcile
zzet May 28, 2026
594a1b0
fix(ladybug): multi-repo correctness + perf, get_file_summary
zzet May 28, 2026
40c8c22
fix(ladybug): survive a poisoned pooled connection
zzet May 28, 2026
d217216
fix(mcp): get_file_summary returns definitions, not body-internal nodes
zzet May 28, 2026
f516947
fix(daemon,ladybug): make warm restart fast and crash-free
zzet May 28, 2026
aa42e2e
fix(resolver): go module stub id uses single-colon ecosystem separator
zzet May 29, 2026
fee3fe9
fix(resolver): resolve receiver-method-call stubs to concrete methods
zzet May 29, 2026
445a33a
fix(resolver): method-call rule matches bare method name (indexed =)
zzet May 29, 2026
ddc50a1
fix(resolver): ResolveAllBulk continues past a rule error (was aborting)
zzet May 29, 2026
a29e703
fix(reach): batch the impact live-walk and persist the lazy cache on …
zzet May 29, 2026
758f780
fix(coverage,blame): persist enriched node Meta on disk backends
zzet May 29, 2026
e821f91
fix(semantic,resolver): persist enriched node Meta on disk backends
zzet May 29, 2026
d1a89de
chore: fix make lint — staticcheck QF/SA + remove unused funcs
zzet May 29, 2026
c0fd7e1
build(release): fetch liblbug at build time; static unix, dynamic win…
zzet May 29, 2026
39e9e43
fix(install): windows one-line installer ships the runtime DLLs
zzet May 29, 2026
09af007
chore: drop ad-hoc bench/probe tooling from the repo
zzet May 29, 2026
6d9c3b8
fix(ladybug): -rdynamic so the dlopen'd FTS extension resolves on sta…
zzet May 29, 2026
df6fea8
refactor(store_ladybug): split store.go into purpose-named files
zzet May 29, 2026
1eb468b
feat(store_ladybug): schema_version + forward-only migration ladder
zzet May 29, 2026
6d783a6
perf(query,store_ladybug): bound bfs fan-out via single-query Frontie…
zzet May 29, 2026
87b9103
fix(store_ladybug): sanitize node id in vector bulk TSV so a tab/newl…
zzet May 29, 2026
10d7281
fix(store_ladybug): drop+recreate SymbolVec on bulk upsert so re-COPY…
zzet May 29, 2026
28e65a9
update the release flow
zzet May 29, 2026
2af5f41
feat(daemon): force full re-index when the backend NeedsRebuild
zzet May 29, 2026
6339a02
fix(store_ladybug): load SymbolFTS re-bulk via LOAD FROM ... MERGE so…
zzet May 29, 2026
fc1aa09
fix(codeowners): precompile rule matcher in Parse so concurrent Match…
zzet May 30, 2026
52c1835
fix(ladybug): --whole-archive forces liblbug's weak C++ RTTI into sta…
zzet May 30, 2026
d27850a
ci(security): allow -Wl,--whole-archive so govulncheck can load the c…
zzet May 30, 2026
6836f3a
fix(daemon): block stop/restart on old-process exit so warm restart c…
zzet May 30, 2026
df8b840
fix(resolver): resolve multi-repo <repo>::unresolved:: stubs
zzet May 30, 2026
2df5820
fix(resolver): kind-gate the in-engine resolver rules
zzet May 30, 2026
d1e0200
perf(ladybug): bulk resolve-apply via COPY + batch qual-name lookup
zzet May 30, 2026
41414a5
perf(resolver): cache-route per-edge store lookups + pass progress lo…
zzet May 30, 2026
6434cd7
perf(resolver): batch helper-pass endpoint lookups
zzet May 30, 2026
5d77f08
fix(resolver): cross-repo resolveEdge must strip the multi-repo stub …
zzet May 30, 2026
040a0e5
perf(resolver): parallelize cross-repo resolve + hoist reachability +…
zzet May 30, 2026
27cfc31
fix(resolver): guard cross-repo worker pool against empty pending
zzet May 31, 2026
c6d5201
test(store_ladybug): skip 80k bulk-reindex scale test under -race
zzet May 31, 2026
a02ea15
fix(resolver): scope cross-repo candidates by reachable repo + language
zzet May 31, 2026
28a5899
perf(store_ladybug): serve FindNodesByNames from the in-memory name i…
zzet May 31, 2026
fd60832
fix(store_ladybug): only stub synthetic endpoints in the bulk reindex
zzet May 31, 2026
0333abd
perf(resolver): language-gate the Go/Python post-resolution passes
zzet May 31, 2026
c3dd663
correct comments
zzet May 31, 2026
0a23e86
test(store_ladybug): probe confirming secondary hash indexes are PK-only
zzet May 31, 2026
bf27222
perf(store_ladybug): buffer-pool RSS reopen backstop + connpool rebui…
zzet May 31, 2026
fca1784
fix(analysis): exclude synthetic external/stub nodes from dead_code
zzet May 31, 2026
09c7a3a
test(analysis,store_ladybug): regression tests for dead_code edge int…
zzet May 31, 2026
c35fd4b
spike(store_cobalt): experimental pure-Go CobaltDB graph backend + bench
zzet May 31, 2026
cabcd60
revert(store_cobalt): drop CobaltDB backend — unsuitable for the graph
zzet May 31, 2026
5abe7de
feat(store_sqlite): restore and default the pure-Go SQLite backend
zzet May 31, 2026
a4975c1
feat(store_sqlite): implement optional capability interfaces
zzet May 31, 2026
9c979d2
feat(store_sqlite): FTS5-backed symbol search (SymbolSearcher + bundles)
zzet Jun 1, 2026
3158e6a
chore(graph): remove the ladybug (Kuzu) backend
zzet Jun 1, 2026
6166fea
chore(build): remove liblbug fetch/link machinery
zzet Jun 1, 2026
eec5b86
chore(cleanup): scrub stale ladybug/Kuzu references from comments
zzet Jun 1, 2026
cd1f9ad
fix(store_sqlite): check Close() returns, drop unused test const
zzet Jun 1, 2026
6f22dab
Actualise comments
zzet Jun 1, 2026
02d9b3a
docs(release): note libstdc++ is required by tree-sitter C++ scanners
zzet Jun 1, 2026
963afe4
build(release): statically link the windows .exe, drop DLL bundling
zzet Jun 1, 2026
a5e0ca1
build(release): publish a Scoop manifest on windows release
zzet Jun 1, 2026
431c0b2
feat(paths): unify per-user state under ~/.gortex
zzet Jun 1, 2026
4dec936
docs(paths): refresh help text, comments, and docs for the ~/.gortex …
zzet Jun 1, 2026
fbcc91e
ci(install-script): drop the retired macos-13 (Intel) runner
zzet Jun 1, 2026
17d9531
perf(indexer): scope per-file dataflow materialization to the edited …
zzet Jun 1, 2026
c661a81
feat(clones): incremental LSH-index primitives (maintained CMS + Stra…
zzet Jun 1, 2026
26a8f6e
feat(graph): clone_shingles sidecar Store capability
zzet Jun 1, 2026
c3c89a0
feat(indexer): per-repository incremental clone detection
zzet Jun 1, 2026
2db62d4
fix(indexer): reliable real-time re-index — no node loss, recover dro…
zzet Jun 1, 2026
d951185
fix(indexer): scan newly-created directories so pre-watch files aren'…
zzet Jun 1, 2026
215a2f8
fix(indexer,resolver): preserve + rebind caller edges on incremental …
zzet Jun 1, 2026
48d598b
fix(indexer): panic-firewall the watcher's background goroutines
zzet Jun 1, 2026
c660af2
fix(indexer,graph): prune deleted files from persisted mtimes so warm…
zzet Jun 1, 2026
5d19188
perf(graph,churn): move git-churn enrichment out of nodes.meta into a…
zzet Jun 1, 2026
c25d306
perf(graph,coverage): move coverage enrichment out of nodes.meta into…
zzet Jun 2, 2026
d9e0bca
perf(graph,releases): move release "added_in" enrichment out of nodes…
zzet Jun 2, 2026
fa8c268
perf(graph,blame): move last-author enrichment out of nodes.meta into…
zzet Jun 2, 2026
65636cc
perf(indexer): cascade enrichment-sidecar deletes on file evict
zzet Jun 2, 2026
144981b
feat(daemon): EnrichBlame/Coverage/Cochange control RPCs
zzet Jun 2, 2026
7f03164
feat(cli): enrich forwards to daemon, errors without one
zzet Jun 2, 2026
55465b6
perf(mcp): persist daemon-mined co-change so restarts skip the git re…
zzet Jun 2, 2026
d03453a
feat(persistence): SQLite sidecar for session notes + development mem…
zzet Jun 2, 2026
9bf868e
feat(persistence): move saved scopes + repo notebooks to the SQLite s…
zzet Jun 2, 2026
a875a88
test(persistence): fix TestFileStore_ConcurrentReadWrite deadlock
zzet Jun 2, 2026
0f55ede
feat(mcp): log when co-change is served from persisted edges (not re-…
zzet Jun 2, 2026
1ee4643
style: resolve golangci-lint findings from the storage-unification work
zzet Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 6 additions & 4 deletions .github/workflows/install-script.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Smoke-test scripts/install.sh on Linux + macOS against the latest published
# release. The script is the public install path served at get.gortex.dev, so
# any change must prove it still produces a working `gortex` binary on both
# OSes and both architectures GitHub-hosted runners cover (x64 always; arm64
# darwin via the macos-14 runner — Linux arm64 is exercised in C5 release).
# any change must prove it still produces a working `gortex` binary. Coverage:
# Linux x64 (ubuntu-latest) and macOS arm64 (macos-14). Intel macOS is not
# tested here — GitHub retired its Intel (macos-13) runners, and install.sh is
# arch-agnostic (only the downloaded artifact differs). Linux arm64 is
# exercised in the release flow.
name: install-script

on:
Expand Down Expand Up @@ -35,7 +37,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, macos-14]
os: [ubuntu-latest, macos-14]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
Expand Down
166 changes: 161 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,16 @@ jobs:
-w /go/src/gortex \
-e GITHUB_TOKEN \
-e HOMEBREW_TAP_TOKEN \
-e SCOOP_BUCKET_TOKEN \
ghcr.io/goreleaser/goreleaser-cross:v1.26 \
release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Personal access token with `repo` scope on zzet/homebrew-tap.
# GITHUB_TOKEN can only push to the source repo, not the tap.
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
# Same story for the Scoop bucket — a PAT with `repo` scope on
# gortexhq/scoop-bucket. Required for the `scoops` block in
# .goreleaser.yml to push the Windows manifest.
SCOOP_BUCKET_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}
# (SCOOP_BUCKET_TOKEN is consumed by the release-windows job's
# "Publish Scoop manifest" step, not here — goreleaser builds no
# windows artifact, so it has no scoop manifest to push.)

# goreleaser-cross runs as root inside the container, so everything
# in dist/ is owned by root:root on the host. The subsequent cosign
Expand Down Expand Up @@ -208,6 +206,164 @@ jobs:
rm -rf /tmp/macos-signing
fi

# Windows is built on a NATIVE windows runner: the CGo tree-sitter
# bindings need a real C/C++ toolchain (mingw-w64 ships on PATH there),
# and goreleaser-cross targets unix only. This job builds a statically
# linked, self-contained .exe (no runtime DLLs to ship), zips it,
# cosign-signs, and appends the zip to the release the `release` job
# already created.
release-windows:
needs: release
runs-on: windows-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version: '1.26'

- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
with:
cosign-release: v2.4.1

- name: Build gortex.exe (static mingw runtime)
shell: bash
env:
CGO_ENABLED: "1"
run: |
set -euo pipefail
VER="${GITHUB_REF#refs/tags/}"
# -extldflags=-static folds the mingw C/C++ runtime (libstdc++,
# libgcc, libwinpthread) into the .exe so it ships as a single
# self-contained binary — nothing to bundle alongside. The C++
# stdlib is in the link at all because some tree-sitter grammars
# carry C++ external scanners (e.g. go-sitter-forest norg); static
# linking just puts it inside the .exe instead of a DLL.
go build \
-ldflags "-s -w -X main.version=${VER} -X main.commit=$(git rev-parse --short HEAD) -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ) -extldflags=-static" \
-o gortex.exe ./cmd/gortex/

- name: Verify gortex.exe is self-contained
shell: bash
run: |
set -euo pipefail
# The static link must leave no dependency on a mingw runtime DLL;
# a partially static .exe would fail to start where that DLL is
# absent. If objdump is available, fail the release on any leaked
# mingw runtime import.
objdump=""
for cand in objdump x86_64-w64-mingw32-objdump; do
command -v "$cand" >/dev/null 2>&1 && { objdump="$cand"; break; }
done
if [ -n "$objdump" ]; then
echo "imported DLLs:"; "$objdump" -p gortex.exe | grep -i 'DLL Name' || true
if "$objdump" -p gortex.exe | grep -iqE 'libstdc\+\+|libgcc_s|libwinpthread'; then
echo "FATAL: gortex.exe still imports a mingw runtime DLL — static link incomplete"
exit 1
fi
echo "ok: no mingw runtime DLL imports"
else
echo "WARN: objdump not found; skipping self-containment check"
fi

- name: Zip (gortex_windows_amd64.zip)
shell: pwsh
run: Compress-Archive -Path gortex.exe -DestinationPath gortex_windows_amd64.zip -Force

- name: Sign + upload to release
shell: bash
env:
COSIGN_YES: "true"
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
cosign sign-blob \
--output-signature gortex_windows_amd64.zip.sig \
--output-certificate gortex_windows_amd64.zip.pem \
gortex_windows_amd64.zip
TAG="${GITHUB_REF#refs/tags/}"
gh release upload "$TAG" \
gortex_windows_amd64.zip \
gortex_windows_amd64.zip.sig \
gortex_windows_amd64.zip.pem \
--clobber

# Append the windows zip's sha256 to the release checksums.txt so
# the one-line installer (scripts/install.ps1, which verifies
# against checksums.txt) covers windows too — the unix goreleaser
# run only hashed its own artifacts. needs:release guarantees
# checksums.txt already exists.
sha="$(sha256sum gortex_windows_amd64.zip | awk '{print $1}')"
gh release download "$TAG" --pattern checksums.txt --clobber 2>/dev/null || : > checksums.txt
if ! grep -q "gortex_windows_amd64.zip" checksums.txt; then
printf '%s gortex_windows_amd64.zip\n' "$sha" >> checksums.txt
gh release upload "$TAG" checksums.txt --clobber
fi

- name: Publish Scoop manifest
# Push a refreshed `gortex` manifest to gortexhq/scoop-bucket so
# `scoop install gortex` resolves this release. SCOOP_BUCKET_TOKEN is
# a PAT with `repo` scope on that bucket (GITHUB_TOKEN can only push
# to the source repo). Non-blocking + self-skipping: a bucket hiccup
# must not fail a release whose binary already shipped, and a
# token-less fork just skips it.
continue-on-error: true
shell: bash
env:
SCOOP_BUCKET_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}
run: |
set -euo pipefail
if [ -z "${SCOOP_BUCKET_TOKEN:-}" ]; then
echo "SCOOP_BUCKET_TOKEN not set; skipping scoop manifest publish"
exit 0
fi
TAG="${GITHUB_REF#refs/tags/}"
VER="${TAG#v}"
URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/gortex_windows_amd64.zip"
SHA="$(sha256sum gortex_windows_amd64.zip | awk '{print $1}')"

# Build the manifest with jq so escaping + validity are guaranteed.
# `bin` shims gortex.exe; checkver/autoupdate let scoop's tooling
# track future releases (the $version token is literal on purpose).
jq -n \
--arg version "$VER" \
--arg url "$URL" \
--arg hash "$SHA" \
--arg homepage "https://github.com/${GITHUB_REPOSITORY}" \
--arg autourl "https://github.com/${GITHUB_REPOSITORY}/releases/download/v\$version/gortex_windows_amd64.zip" \
'{
version: $version,
description: "Code intelligence engine that indexes repositories into an in-memory knowledge graph.",
homepage: $homepage,
license: "Apache-2.0",
architecture: { "64bit": { url: $url, hash: $hash } },
bin: "gortex.exe",
checkver: "github",
autoupdate: { architecture: { "64bit": { url: $autourl } } }
}' > gortex.json

# Token in the clone URL — GitHub Actions masks the secret in logs.
git clone "https://x-access-token:${SCOOP_BUCKET_TOKEN}@github.com/gortexhq/scoop-bucket.git" scoop-bucket
cd scoop-bucket
# Honour the bucket's layout: scoop reads manifests from the repo
# root or a bucket/ subdir. Update in place if one exists, else use
# the conventional bucket/ subdir.
if [ -f gortex.json ]; then dest="gortex.json"; else mkdir -p bucket; dest="bucket/gortex.json"; fi
cp ../gortex.json "$dest"
git add "$dest"
if git diff --cached --quiet; then
echo "scoop manifest already current for ${VER}"
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -m "gortex: ${VER}"
git push
echo "published scoop manifest ${VER} -> $dest"
fi

# SLSA-3 provenance via the OpenSSF reusable workflow. This runs in a
# separate, isolated job that the `release` job can't tamper with —
# that isolation is what elevates us from SLSA-2 to SLSA-3. Output is
Expand Down
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,14 @@ eval/scripts/
eval/logs/

internal_docs/

# Ad-hoc bench/probe tooling — kept locally, not part of the repo.
bench/all-tools-bench/
bench/daemon-bench/
bench/edge-diff/
bench/multi-repo-bench/
bench/node-diff/
bench/store-bench/
bench/unresolved-audit/
bench/run-linux.sh
bench/run-linux-rest.sh
50 changes: 10 additions & 40 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
version: 2

# Run inside ghcr.io/goreleaser/goreleaser-cross — the Docker image ships
# cross-compile toolchains for all four targets below so CGO (tree-sitter)
# links cleanly on a single Linux runner. See .github/workflows/release.yml.
# cross-compile toolchains so CGO (tree-sitter) links cleanly on a single
# Linux runner. This config builds the UNIX targets only (linux + darwin).
# Windows is built separately on a native windows runner (see the
# `release-windows` job in release.yml) because the CGo tree-sitter
# bindings need a real C/C++ toolchain there.
before:
hooks:
- go mod tidy
Expand All @@ -19,30 +22,14 @@ builds:
# Version (see internal/version). Commit lands in the +build slot so
# `gortex version` output round-trips as canonical semver.
- -s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{.Date}}
# Statically link the mingw-w64 C/C++ runtime (libstdc++, libgcc,
# winpthread) into the Windows binary. CGO is on for tree-sitter and
# some grammar scanners ship C++; without -static the released
# gortex.exe dynamically links libstdc++-6.dll et al., which are not
# present on a stock Windows box — the binary fails to start with a
# missing-DLL error. No-op on linux/darwin, which keep their normal
# dynamic libc/libc++.
- '{{ if eq .Os "windows" }}-extldflags "-static"{{ end }}'
env:
- CGO_ENABLED=1
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
ignore:
# windows/arm64 needs an aarch64-w64-mingw32 cross-toolchain that
# the goreleaser-cross image doesn't ship; windows/amd64 covers
# every mainstream Windows dev box. Revisit when the image gains
# the llvm-mingw arm64 target.
- goos: windows
goarch: arm64
# Per-target CC + CXX. goreleaser-cross exposes these cross-toolchains
# on PATH; CGO needs both set per target triple because some deps
# (tree-sitter yaml scanner, etc.) ship C++. Without CXX, the system
Expand All @@ -69,11 +56,6 @@ builds:
env:
- CC=aarch64-linux-gnu-gcc
- CXX=aarch64-linux-gnu-g++
- goos: windows
goarch: amd64
env:
- CC=x86_64-w64-mingw32-gcc
- CXX=x86_64-w64-mingw32-g++
# Per-target build hook. Fires after each Mach-O / ELF is linked,
# before the archive step. The script is a no-op for non-darwin
# targets, so we don't need a per-override hook list.
Expand Down Expand Up @@ -151,20 +133,8 @@ homebrew_casks:
executable: gortex
shell_parameter_format: cobra

# Scoop manifest — `scoop install gortex` on Windows. goreleaser commits
# the generated manifest (pointing at the signed windows/amd64 .zip in
# this release) to a separate bucket repo on every tagged release,
# exactly like the Homebrew cask above.
scoops:
- name: gortex
repository:
owner: gortexhq
name: scoop-bucket
# GITHUB_TOKEN can only push to the source repo, so the bucket
# needs its own PAT with `repo` scope on gortexhq/scoop-bucket,
# stored as SCOOP_BUCKET_TOKEN in repo secrets. release.yml wires
# it in.
token: "{{ .Env.SCOOP_BUCKET_TOKEN }}"
homepage: "https://github.com/zzet/gortex"
description: "Code intelligence engine that indexes repositories into an in-memory knowledge graph."
license: "Custom"
# NOTE: goreleaser does NOT generate the Scoop manifest — windows is built by
# the separate `release-windows` job (native runner) and isn't an artifact of
# this goreleaser-cross run, so goreleaser has no windows zip to point at. That
# job publishes the manifest to gortexhq/scoop-bucket itself (see its "Publish
# Scoop manifest" step in release.yml).
2 changes: 1 addition & 1 deletion bench/perf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var benchCacheDir string
func main() {
repos := flag.String("repos", "gin,nestjs,react", "comma-separated repo set. Forms: preset slug (gin/nestjs/react/linux), owner/repo, https URL, or local:/path")
includeLinux := flag.Bool("include-linux", false, "include the linux kernel preset (multi-GB clone; skipped by default)")
cacheDir := flag.String("cache-dir", "", "cache directory for clones (default ~/.cache/gortex/bench)")
cacheDir := flag.String("cache-dir", "", "cache directory for clones (default ~/.gortex/cache/bench)")
queriesPath := flag.String("queries", "bench/perf/queries.json", "JSON file with the search-bench query set")
out := flag.String("out", "", "output table path (default stdout)")
format := flag.String("format", "markdown", "markdown | csv | json")
Expand Down
73 changes: 73 additions & 0 deletions cmd/gortex/backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package main

import (
"fmt"
"os"
"path/filepath"
"strings"

"go.uber.org/zap"

"github.com/zzet/gortex/internal/graph"
"github.com/zzet/gortex/internal/platform"
)

// openBackend constructs the graph.Store the daemon will run
// against. Picks the implementation by the --backend flag:
//
// - "memory" (default) — in-process *graph.Graph; nothing
// persists across runs; matches every existing test fixture.
//
// Returns the store, a cleanup func the caller must defer (closes
// the underlying handle on disk-backed stores), and any error
// constructing or opening the store.
//
// The actual per-backend Open* helpers live in their own
// build-tagged files (backend_memory.go is always built; the
// disk-backed ones are gated by build tags). This file is the
// shared dispatch.
func openBackend(name, path string, bufferPoolMB uint64, logger *zap.Logger) (graph.Store, func(), error) {
switch strings.ToLower(strings.TrimSpace(name)) {
case "", "memory", "mem", "in-memory":
s := graph.New()
return s, func() {}, nil
case "sqlite", "sqlite3":
resolved, err := resolveBackendPath(path, "store.sqlite")
if err != nil {
return nil, nil, err
}
logger.Info("opening sqlite backend", zap.String("path", resolved))
return openSqliteBackend(resolved, bufferPoolMB)
default:
return nil, nil, fmt.Errorf("unknown --backend %q (expected: memory, sqlite)", name)
}
}

// resolveBackendPath turns an empty --backend-path into a default
// under the unified store directory (~/.gortex/store/<filename>, or the
// XDG_DATA_HOME equivalent). Otherwise expands ~ and returns the
// absolute path. Creates the parent directory if missing — the
// disk-backed stores expect the parent dir to exist.
func resolveBackendPath(in, filename string) (string, error) {
in = strings.TrimSpace(in)
if in == "" {
in = filepath.Join(platform.StoreDir(), filename)
} else if strings.HasPrefix(in, "~/") {
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("resolve home dir: %w", err)
}
in = filepath.Join(home, in[2:])
}
abs, err := filepath.Abs(in)
if err != nil {
return "", fmt.Errorf("abs path %q: %w", in, err)
}
// The on-disk store opens the leaf path (file or directory). We
// MkdirAll the parent so the path is reachable; the store itself
// creates the leaf.
if err := os.MkdirAll(filepath.Dir(abs), 0o755); err != nil {
return "", fmt.Errorf("mkdir parent %q: %w", filepath.Dir(abs), err)
}
return abs, nil
}
Loading
Loading