Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
911d7bf
docs: add release process to CLAUDE.md
SimplyLiz Apr 16, 2026
7b445c9
feat(lip): enrich blast radius with LIP semantic coupling
SimplyLiz Apr 17, 2026
fd28e20
refactor(lip): wire BlastRadiusEnricher into AnalyzeImpact, centralis…
SimplyLiz Apr 20, 2026
1ce495b
fix(impact): drop unused CouplingStatic constant
SimplyLiz Apr 20, 2026
78dbdb7
feat(mcp): renderArchitecture tool + tree-sitter symbol fix
SimplyLiz Apr 21, 2026
10335c4
feat(impact): weight analyzeImpact risk by bridge centrality
SimplyLiz Apr 21, 2026
c3929ab
feat(lip): distinguish not-indexed from zero-callers; add v2.3 symbol…
SimplyLiz Apr 21, 2026
dccc2fc
feat(cartographer): sync vendored diagram.rs with overlays; fix local…
SimplyLiz Apr 21, 2026
111e761
chore(vendor): full sync of Cartographer + add sync-cartographer.sh
SimplyLiz Apr 21, 2026
ddb90eb
chore: gitignore mcp .cartographer_cache.json
SimplyLiz Apr 21, 2026
2e1a908
fix(cartographer): resolve rebuild_graph mutex deadlock
SimplyLiz Apr 21, 2026
02ee82c
feat(lip): fold LIP tier-1 static callers into impact items
SimplyLiz Apr 24, 2026
e2678fd
feat(lip): wire static-item fold into analyzeImpact
SimplyLiz Apr 24, 2026
85fc898
feat(lip): wire register_project_root on handshake
SimplyLiz Apr 24, 2026
cf7ff98
feat(lip): add QueryOutgoingImpact client against v2.3.3 shape
SimplyLiz Apr 24, 2026
136a7d8
feat(query): add symbolExists — exact-match boolean oracle for LLM gr…
SimplyLiz Apr 24, 2026
f89cff7
feat(lip): wire query_outgoing_impact through engine, CLI, and MCP
SimplyLiz Apr 24, 2026
e113870
release: v9.2.0 — analyzeOutgoingImpact, symbolExists, Cartographer 3…
SimplyLiz Apr 25, 2026
f63ed9a
ci: gofmt 9 source files and migrate scip-go install path
SimplyLiz Apr 25, 2026
acece7f
fix(test): mutex-protect request recorder in outgoing impact fake
SimplyLiz Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
cache: true

- name: Install scip-go
run: go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
run: go install github.com/scip-code/scip-go/cmd/scip-go@latest

- name: Run tests
run: go test -v -race ./...
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ckb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ jobs:
run: go build -ldflags="-s -w" -o ckb ./cmd/ckb

- name: Install SCIP indexer
run: go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
run: go install github.com/scip-code/scip-go/cmd/scip-go@latest

# ───────────────────────────────────────────────────────────────────────
# Cache & Index
Expand All @@ -114,7 +114,7 @@ jobs:
echo "╔═══════════════════════════════════════════════════════════════════════════════╗"
echo "║ INDEXER NOT FOUND ║"
echo "╠═══════════════════════════════════════════════════════════════════════════════╣"
echo "║ Go: go install github.com/sourcegraph/scip-go/cmd/scip-go@latest ║"
echo "║ Go: go install github.com/scip-code/scip-go/cmd/scip-go@latest ║"
echo "║ TypeScript: npm i -g @sourcegraph/scip-typescript ║"
echo "║ Python: pip install scip-python ║"
echo "║ Rust: cargo install scip ║"
Expand Down Expand Up @@ -989,7 +989,7 @@ jobs:
run: go build -ldflags="-s -w" -o ckb ./cmd/ckb

- name: Install SCIP indexer
run: go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
run: go install github.com/scip-code/scip-go/cmd/scip-go@latest

- name: Cache
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
cache: true

- name: Install scip-go
run: go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
run: go install github.com/scip-code/scip-go/cmd/scip-go@latest

- name: Run tests with coverage
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ testdata/**/pubspec.lock

# Vendored Cartographer Rust build artifacts
third_party/cartographer/mapper-core/cartographer/target/

# MCP runtime caches (pinned to commit hash, regenerated on startup)
internal/mcp/.cartographer_cache.json
126 changes: 126 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,135 @@
# Changelog

All notable changes to CKB will be documented in this file.

## [Unreleased]

## [9.2.0] - 2026-04-25

### Added

- **`analyzeOutgoingImpact` — forward call graph** (MCP + CLI) — mirror
of `analyzeImpact` answering *"what does this symbol call?"* instead of
*"who calls it?"*. New `Engine.AnalyzeOutgoingImpact` drives off LIP
v2.3.5's `query_outgoing_impact` RPC, folds the result through the same
`ImpactItem` pipeline as the incoming side (with `direct-callee` /
`transitive-callee` kinds), and surfaces semantically coupled callees
alongside the static graph. Degrades cleanly when LIP isn't running:
the response is empty with a provenance warning, never an error.
Surfaces include `ckb impact outgoing <symbolId>` (with `--min-score`
for the semantic threshold), the `analyzeOutgoingImpact` MCP tool, and
a new `ProvenanceCLI.Warnings` field so LIP-degradation messages reach
JSON consumers.
- **`symbolExists` MCP tool** — exact-match boolean oracle that returns
`{exists, kind, location?}` for a fully-qualified symbol ID. Built for
LLMs to ground references *before* they cite them in code, without
spending tokens on a 20-result `searchSymbols` payload. Cheaper than
`getSymbol` for the "does this thing actually exist" check.
- **LIP enrichment folds into `analyzeImpact`** — tier-1 tree-sitter
callers that LIP discovers (when `scip-go` emits no `Call` roles, e.g.
Go method dispatch) are now folded into the same `directImpact` /
`transitiveImpact` lists as SCIP's own results, deduplicated by
`(file, name)`. Driven by a new `BlastRadiusEnricher` interface so the
fold path is the single source of truth for both incoming and outgoing
impact analysis. Items LIP marks `edges_source=empty` are skipped (LIP
signalling no static evidence); `tier1`, `scip_with_tier1_edges`, and
`scip_only` all fold the same way. Risk score now picks up
semantic-coupling signals via the same enricher pipeline.
- **`register_project_root` on LIP handshake** — Engine startup now
registers the repo root with the daemon so LIP canonicalises file URIs
against a known anchor, matching the v2.3.1 contract. Eliminates the
URI-shape drift that previously caused tier-1 callers to dedup
incorrectly against SCIP results.

### Changed

- **`analyzeImpact` risk score now weighted by bridge centrality** —
`calculateAggregatedRisk` multiplies the weighted-mean score by
`1 + max(BridgeScore)/1000` (capped at 2.0) over the changed files, so a
change landing on a critical architectural path (high betweenness) is
reported as riskier than the same-shape change in a leaf module. Implements
the behaviour that `CARTOGRAPHER_STRATEGY.md` had already documented but
the code was not actually doing. Bridge lookups match by both `Path` and
`ModuleID`; if no changed file matches the graph, the multiplier is 1.0
and no informational factor is appended. Only runs when the binary was
built with `-tags cartographer` (graph is a no-op otherwise). A new
`bridge_centrality` informational factor surfaces in `RiskScore.Factors`
when the multiplier fires; its `Weight` is 0 because it applies
multiplicatively, not as a weighted-mean input.

### Cartographer

- **Vendored Cartographer fully synced to upstream 3.0.0** — the
vendored tree under `third_party/cartographer/mapper-core/cartographer/`
was 391 lines behind on `diagram.rs` alone, and 10 `.rs` files plus
`Cargo.toml` had drifted. Full sync brings in doc-node graph support
(`cartographer_doc_index`, `cartographer_doc_context`, `cartographer_query_docs`
FFI entry points — Go bindings can be added as a follow-up),
LIP-style `Range` / `at_range` on `GraphEdge`, PascalCase bare-identifier
resolution for doc backtick refs, and the overlays feature on diagrams.
New `scripts/sync-cartographer.sh` is now the supported path for future
syncs — rsync-based, explicit path list, emits next-step commands. No
local patches needed against upstream.
- **Diagram overlays in `renderArchitecture` / `ckb diagram`** — the
vendored `diagram.rs` was synced from upstream Cartographer, so the
Mermaid/DOT output now decorates the base import graph with
architectural signals: cycle members get a thick red border (pivots
dashed), cycle-internal edges a heavy red arrow, layer violations pick
up per-type dashed/dotted edge styling, and hot nodes
(`hotspot_score ≥ 70`) get an orange border plus DOT size scaling.
Mermaid is border-only for hot nodes (no sizing primitive). Cycle red
takes precedence over hot orange on the same node — architectural
signal wins over performance signal.
- **`renderArchitecture` MCP tool** — returns the project's module-level
import graph as Mermaid or Graphviz (DOT), ready to paste into IDEs
that render Mermaid inline (Cursor, Claude Desktop, VS Code markdown
preview, GitHub). With `focus` set, returns an undirected BFS
neighborhood around the anchor module to `depth` (default 2); without,
returns the top-N most-connected nodes (default cap 40). Response
includes `truncated: true` when the node cap kicked in. Backed by the
new `cartographer_render_architecture` FFI export; CLI and MCP outputs
are produced by the same shared renderer.
- Go binding `cartographer.RenderArchitecture()` in `internal/cartographer/bridge.go` (+ no-op stub for the no-tag build).

### Fixed

- **Vendored Cartographer `rebuild_graph` deadlock** — upstream
`ApiState::rebuild_graph` held the `mapped_files` Mutex across its
loop and then called `resolve_import_target`, which re-acquired the
same non-reentrant `std::sync::Mutex`. Any project with a resolvable
import deadlocked — the `cartographer diagram` / `cartographer health`
CLIs hung, and the Go bridge's `cartographer.MapProject` would block
any time CKB fed it a repo with imports. Fixed in the vendored tree
(and contributed back upstream) by splitting the resolver: a public
method that locks, and a private helper that takes the already-held
map; `rebuild_graph` now calls the helper. Discovered during
end-to-end smoke testing against CKB itself (1093 files). Regression
test added upstream.
- **`localize-tree-sitter-symbols.sh` dropped grammar C parsers** — the
script extracted archive members via `ar x`, which silently clobbers
files when multiple members share a name. Cargo emits a `parser.o`
and `scanner.o` per grammar crate (tree-sitter-c, -cpp, -rust, -go,
etc.), so `ar x` left only the *last* grammar's C parser on disk,
producing a localized archive missing `_tree_sitter_c` / `_tree_sitter_cpp`.
The script now feeds the archive directly to `ld -r` with
`-force_load` (Mach-O) / `--whole-archive` (ELF), which pulls every
member in without touching the filesystem. The `rust_tree_sitter` C
ABI refs to `_tree_sitter_c` and `_tree_sitter_cpp` now resolve
inside the combined object as expected.
- **Tree-sitter symbol collisions at link time** — `libcartographer.a`
previously exported its bundled tree-sitter runtime and grammar
symbols, which collided with `go-tree-sitter` when building CKB with
`-tags cartographer` (`ld: 246 duplicate symbols`). `make build-cartographer`
now post-processes the archive via
`scripts/localize-tree-sitter-symbols.sh` (vendored under
`third_party/cartographer/mapper-core/cartographer/scripts/`), which
partial-links archive members into one combined object and localizes
`ts_*` / `tree_sitter_*`. `cartographer_*` FFI exports stay global.
Beyond the duplicate-symbol error, this also rules out a silent
memory-corruption class of bug where Cartographer's Rust code could
have bound to the consumer's tree-sitter copy at global resolution
time if the two versions' struct layouts ever drifted.

## [9.1.0] - 2026-04-16

### Added
Expand Down
16 changes: 16 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@ golangci-lint run
./ckb setup --tool=vscode
```

## Release Process

Releases are fully automated via `.github/workflows/release.yml`, triggered by pushing a `v*` tag.

**Steps to release:**
1. Bump version in `internal/version/version.go`, `npm/package.json`, `testdata/review/sarif.json`
2. Update `CHANGELOG.md`
3. Merge to main, tag `vX.Y.Z`, push the tag
4. The pipeline handles everything else:
- Runs `go test -race ./...`
- GoReleaser builds cross-platform binaries and uploads to GitHub Releases
- Updates Homebrew tap (`SimplyLiz/homebrew-ckb`)
- Publishes `@tastehub/ckb` + 5 platform packages to npm

**Do not manually `npm publish`** — the pipeline does it with checksummed binaries from GoReleaser.

## npm Distribution (v7.0)

CKB is also available via npm:
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ build: build-cartographer
build-cartographer:
@echo "Building Cartographer static library..."
@cd $(CARTOGRAPHER_DIR) && cargo build --release
@echo "Localizing tree-sitter symbols (prevents link-time collisions with go-tree-sitter)..."
@cd $(CARTOGRAPHER_DIR) && scripts/localize-tree-sitter-symbols.sh target/release/libcartographer.a
@echo "Library: $(CARTOGRAPHER_LIB)"

## Build without Cartographer (no Rust toolchain required — for CI and contributors)
Expand Down
Loading
Loading