Releases: kannamma-labs/cie
Release list
0.1.5 — AST/file-index single source, input validation hardening, vulnerability ingestion
Rolls up everything merged to main since v0.1.4:
Added
- AST mirror +
get_meta/get_function— cie as the single source where the actual file and its AST stay in sync. Every write path (write_file,apply_patch, ...) refreshes the mirror in the same call; reads never touch disk. - File-path index —
ls/dir/file_hierarchy/file_names_like/path_prefix— one sorted, lazily-built path array per project root, same single-source discipline as the AST mirror. vision.md— the project's why, linked from the README title line.- README 30-second demo — a real recorded session, cie asked about itself.
- Vulnerability ingestion —
vulnerability_scan_run/vulnerabilities— cross-references already-extractedPACKAGEnodes against an externally-generated pip-audit/npm-audit JSON report intoVulnerabilitynodes +AFFECTSedges. Ingestion only: no scanner, no network call.report_pathis jailed under the project root; rescans correctly clear fixed findings and never wipe out a different ecosystem's last scan.
Fixed
search_symbol'skindandaffected_by'sdirectionare now validated against real values instead of silently returning a misleading empty or wrong result on a bad input — confirmed live on astropy__astropy-14995, where a downstream repair agent burned 8 queries chasing an uncertainty that was never real.
Suite: 348 passed; 10 pre-existing failures are unrelated missing optional tree-sitter grammar packages (tree_sitter_cpp/tree_sitter_c_sharp). Tool surface: 135 → 144.
No PyPI publish with this release — tag + GitHub Release only.
0.1.4 — direct-calls TESTS edges
What changed
Found by dogfooding cie on itself: a 308-test suite resolved exactly one TESTS edge. Behavioral test names (pytest best practice) starve the naming heuristic; monkeypatch starves the @patch heuristic.
New heuristic (4) — direct calls: a resolved calls edge from a test symbol to a production symbol (FUNC/METHOD/CLASS, non-test file, not conftest.py) now mints a TESTS edge directly — EXTRACTED, the same proof standard the naming-match upgrade uses, without the name gate.
Measured on cie itself:
- TESTS edges: 1 → 562 (total edges 5,992 → 6,553)
test_map(resolve_backend): 0 → 7 tests;run_init: 0 → 12;build_tool_service_embedded: 0 → 18
Still honestly not exhaustive: a test that only reaches its target through a helper gets no edge — the test_map hint says exactly that.
Suite: 312 passed (+4 ground-truth tests: behavioral link, test-file-helper skip, conftest skip, no-duplicate). Artifacts: sdist + wheel, twine PASSED.
0.1.3 — one storage-backend selection rule, every front-end
What changed
One rule for choosing storage, identical across front-ends — the product principle: least friction to users and their existing infrastructure.
cie-mcp /path/to/project # auto: serves .cie/graph.db if you indexed, else Neo4j
cie-mcp /path/to/project --backend neo4j # explicit — always honored
CIE_BACKEND=embedded # one env var, both `cie` and `cie-mcp` obey- Resolution: explicit
--backend {auto,embedded,neo4j}>CIE_BACKENDenv (stray values fall through, never fatal) >--embedded(permanent alias — every entrycie initever wrote keeps working) > auto. - The resolved choice is stated on stderr at startup (
backend=… storage=… policy=…) — never silent; stdout stays byte-clean (it is the JSON-RPC channel). Live-verified: a no-flag spawn on a freshly indexed project auto-picked embedded, full 135-tool handshake + real tool call clean over stdout. - Fixed: explicit
--backend autowas previously read as Neo4j (truthy-string bug) — an indexed project could query the wrong store; regression-pinned. cie initwrites the canonical--backend embedded; selection is orthogonal to configuration (NEO4J_*/ legacyCIE_NEO4J_*/--neo4j-*still configure Neo4j however selected). HTTP tool-mount remains Neo4j-only, documented as such.- README gained the per-front-end selection matrix under "Storage backends & config".
Suite: 308 passed. Artifacts: sdist + wheel, twine PASSED, clean-venv verified.
0.1.2 — native client compatibility + one-click install
What changed
Fixed — native client compatibility
Registered cie init entries carried a bare "cie-mcp" command, which only resolves if the MCP client's PATH includes the install bin — GUI-launched Claude Code/Cursor/Codex processes typically don't. cie init now writes a spawn-robust command everywhere (project .mcp.json, ~/.cursor/mcp.json, the Codex TOML snippet, the managed AGENTS.md/CLAUDE.md block): absolute console-script path, else the running interpreter via -m cie.mcp_server.
Verified with the real Claude Code CLI (2.1.251), not a mock client: cie init → claude mcp list shows cie … ✔ Connected → a one-shot claude -p agent call of search_symbol through the registered server returned the correct indexed file. Cursor/Codex: config formats verified against their documented shapes — those apps aren't on the test machine, so they're labeled format-verified, not claimed as live.
Added — one-click install (README top)
uv tool install "cie-mcp[mcp] @ git+https://github.com/kannamma-labs/cie.git@v0.1.2"
cie init . # per project: index, register client, write context filesThe whole chain was run end-to-end on 2026-08-31. Browser deep-link "one-click" is deliberately not claimed: cie is a local stdio server pointed at a specific project with a policy you choose — that's what cie init computes.
Carried in
R10 (first-party semantic retrieval — measured recall@8 = 1.0 on all 16 labeled questions) shipped in the v0.1.1 artifact; its changelog entry had stayed under [Unreleased] through the rename cut and lands here verbatim with an attribution note.
Suite: 294 passed (two new command-resolution tests; the real-client handshake test now spawns the entry exactly as written). Artifacts: sdist + wheel built, twine PASSED, clean-venv rehearsal (85 read tools under readonly policy).
cie 0.1.1 — PyPI distribution renamed to cie-mcp
[0.1.1] - 2026-08-31 — PyPI distribution renamed to cie-mcp
pypi.org/project/cie is an unrelated project (cluster311/cie10, ICD-10
codes) — the finding recorded in the 0.1.0 release notes becomes this
change: the distribution ships under cie-mcp from now on. The
import package, the cie CLI, the cie-mcp console script, the repo,
and the tags are unchanged; only the pip string moves:
pip install "cie-mcp[mcp]" (was pip install "cie[mcp] @ git+…"-only).
Added
- First PyPI artifact for the project, under the new distribution name
(core +mcp/httpextras; console scriptscieandcie-mcp). - GitHub install remains supported and pinned in README alongside the
PyPI line (same commit, so both routes verify identical code).
Changed
- Distribution name
cie→cie-mcpinpyproject.toml; version
0.1.0→0.1.1(the v0.1.0 GitHub release/tag stays as-is — dated
record under the old name). Extras migrate with the distribution:
cie-mcp[mcp],cie-mcp[http].
Install (updated)
pip install "cie-mcp[mcp]" # from PyPI once the 0.1.1 upload lands- The upload runs with the maintainer's PyPI token or a trusted-publisher
workflow — this release commit is the artifact source (wheel verified:
twine checkPASSED; clean-venv rehearsal: index 858/1822, MCP
handshake 85 read-only tools, callers(close) executes). - GitHub route, unchanged and equal:
pip install "cie-mcp[mcp] @ git+https://github.com/kannamma-labs/cie.git"
cie 0.1.0 — first stable
[0.1.0] - 2026-08-31 — first stable
Cut from the same tree as 0.1.0a3 plus everything below — the P0/P1
roadmap (R1–R9, R11–R17) landed between the last alpha and this cut: the
message bus is the same code base, now verified at 279 tests, a 135-tool
surface with 0 conformance crashes, and 9 languages. Released from GitHub
while a PyPI distribution-name decision is pending (cie on PyPI is an
unrelated project).
Added
- R15 —
cie init: one-command onboarding. Detects installed MCP
clients (Claude Code / Cursor by config presence; Codex detected and
given the exact TOML snippet — never auto-edited), registers cie's
stdio server idempotently (existing entries byte-preserved; invalid
JSON refused, not 'fixed'), writes managed context blocks into
AGENTS.md/CLAUDE.md(cie:initmarkers, user content outside
them untouched, re-run = refresh-in-place), and defaults the client's
policy to readonly — writes are an explicit--policy fullopt-
in, not an onboarding side effect. Verified end to end: the
registered entry, spawned exactly as a client would, handshakes over
real stdio and lists 85 read tools with zero write tools
(scripts/record_init.sh+tool-test-lab/dogfood_mcp_stdio_list.py).
13 tests.
Added
- R16 — the
run-tool isolation story made explicit. New
docs/security.mdstates the threat model precisely: the cwd jail +
hard-timeout/process-group kill + bounded output that IS there, and
equally plainly what is NOT (no fs sandbox beyond cwd, no network
restriction, no container isolation) — plus the surface-by-surface
matrix of what each caller can reach (HTTP default refusesrun
server-side before any process spawns, machine-checked by a test that
monkeypatches Popen to blow up on any invocation; MCPreadonly
never registers it). OptionalCIE_RUN_WRAPPERcontainer seam —
documented as convenience, not enforcement, with the pin that absent
the env var behavior is byte-identical.
Added
- R9 — reproducible benchmark harness + a third independent repo.
scripts/benchmark.sh+scripts/benchmark_tasks.pyturn the
benchmark-doc methodology into a script: clone at the pinned commit →
index → run the three canonical task shapes on BOTH sides (naive
grep/read vs tool calls), emitting the JSON the docs' tables are
pasted from — plus the requested token-per-query metric, measured as
response-payload chars (tokenizer-free, labeled as such — ours gets
measured, codebase-memory-mcp's "120× fewer tokens" stays a
vendor-claim). Third dataset: docs/benchmarks-urllib3.md (urllib3 @
85a8a9cf, 36 files / 667 nodes / 1,307 edges) — wins (receiver-wise
caller attribution: 12 graph edges vs 28 undifferentiated grep
matches; 2.24× file-skeleton compression) AND misses (28/40
unresolved call sites — the known heuristic-recall gap, bigger on
this repo, published as found). The psf/requests numbers regenerate
via the same harness and match the published doc.
Added
- R8 —
cie export-html: the shareable artifact. One static,
self-contained HTML snapshot of a project's graph, centered on what no
competitor renders: task→file→test chains (real TESTS edges from the
index pass), orphan symbols, the atomic-task list, indexed files, and
a text filter — no server, no auth surface, no network access, opens
viafile://(zero external references asserted in tests).
scripts/record_export_html.shreproduces end to end: clone psf/
requests at the pinned commit → index → export → headless-Chrome
screenshots straight fromfile://(committed todocs/images/).
CLI:cie export-html [PATH] --out FILE [--max-chains N].
Added
- R11 — streamable-HTTP transport for
cie-mcp. The--transport streamable-httpchoice is now actually usable end to end:--host
(default127.0.0.1) /--port(8000) kwargs wired into the SDK's
HTTP run path, the same server-sideToolPolicyapplies on every
transport. Live-verified with the official streamable-http client
against a real spawned server (tool-test-lab/dogfood_mcp_http.py):
HTTPtools/list== exactly the 85-tool inspector prediction, and a
write attempt is refused server-side (the tool is never registered —
never trusted to the client). Browser-mode Inspector is the human
path; the harness is its scriptable twin.
Added
- R7 — edge provenance tagging: callers/callees disclose HOW each
answer was reached. Every row incallers/calleescarries
provenance—"graph"(a persisted, confidence-tagged edge) vs
"heuristic-name-match"(the fallback served it, say so per row) —
and the envelope carriesresolution(CallResolutionStat, persisted
bycie index/cie loadin the edge-resolution pass): per-name
{total_call_sites, unresolved_call_sites, resolved_edges}. The
benchmark docs' honest miss ("resolved 3 of 6 real call sites on
requests") is now a field in tool output — live-verified on
psf/requests:resolution: {total: 19, unresolved: 16, resolved: 3}
(name-keyed; see benchmarks-requests.md's reconciliation note).
callgraph.resolve_call_edgesgained the same-pass stats companion
(resolution_stats); ground-truth provenance tests pin the labels
against known-by-inspection truth.
Added
- R14 — the PRD-hierarchy store lands on embedded SQLite. Its last
Neo4j-only feature is gone:cie/embedded_hierarchy_repository.py's
SQLiteHierarchyRepositoryimplements the sameHierarchyRepository
protocol (push_hierarchy/get_children/get_lineage/
get_hierarchy_node/get_project_tree) over one local file
(.cie/hierarchy.dbbeside the other embedded stores). Intentional,
documented backend differences: one HAS_CHILD edge direction (nothing
writes the host wide-schema's CHILD_OF on this path) and name-keyed,
unconditional REALIZED_BY edges (the task layer lives in a separate
file; Neo4j's write validates them against stored AtomicTask nodes).
The three hierarchy tools are realToolServicemethods now — the
last HTTP-only alias handlers;HTTP_WRITE_ALIASESis EMPTY
(permanently, pinned),push_hierarchyjoinedWRITE_TOOLS, and the
defaultcie-mcp --embeddedserves the full PRD tree (opt out with
--no-hierarchy/hierarchy_tracking=False; the tools then return
unavailable[HIERARCHY_STORE_NOT_CONFIGURED], never silent-empties).
CLIhierarchy:*commands also work against embedded now (R2's seam
extends to the hierarchy repo). 21 tests
(tests/test_embedded_hierarchy_repository.py, B1's bar) + the pinned
honest-unavailable-when-off test.cie/hierarchy.py's docstring
pointer to a nonexistent in-memory fake corrected in the same pass.
Added
-
R5 — the 503 surface shrinks 18 → 5, each with a machine-readable
reason. The four protobox-leftover modules
(cie/community_detect.py,cie/contracts.py,cie/state_machine.py,
cie/test_orchestration.py) no longer importcore.llmat module
level: the import (and thePrompt/LlmAgentdefinitions it fed)
moved into the one function per module that actually calls the LLM.
Everything whose logic was pure now runs standalone —
community_detect_run(label propagation),community_search,
contracts(query),validate_types,inject_assertions,
strip_assertions,test_plan,run_tests,test_results,
coverage_gaps,nook_and_corner_test,unified_coverage_report—
no shell LLM dependency at all. The five tools that genuinely need a host-only
backend (qa,contracts_run,state_machine_run,
community_summarize_run,decompose_page) now 503 with
error.reasonslugs (OPTIONAL_BACKEND_MISSING:core/
HOST_PLUGIN_MISSING:decompose-detector) instead of prose — the error
envelope grows the optionalreasonfield, the conformance
harness surfaces it, andtests/test_unavailable_reasons.py
pins the registry + a no-quiet-regrowth gate. Found and fixed en
route by the new bucket scan:failing_context("")crashed
(IsADirectoryError) through the heuristic fallback — now an honest
validation-hint envelope. Live conformance: 132 tools, 100
verified / 23 graceful / 5 unavailable / 4 backend-gated / 0
crashes (tool-test-lab/surface_results.json, fresh artifact). -
MCP write-side parity for the task/QA layer (roadmap R1). The six
task/QA write-back tools —push_tasks,set_task_status,
link_artifact,append_repair_events,record_coverage,
record_coverage_snapshot— are realToolServicemethods now, so
the defaultcie-mcp --embeddedinstall (which introspects only
ToolService) serves the full task/QA surface over MCP, instead of it
being HTTP-only alias handlers. Same kwargs, same envelope shapes,
same hints as the handlers they replace; they were added to
WRITE_TOOLSin the same commit (push_hierarchystays an HTTP alias
until its embedded backend lands in R14). The read-only HTTP/MCP
story is unchanged and pinned by tests — promoted writes are 403 by
default server-side, per tool. Surface: 126 → 132 tools, live
conformance 88 verified / 22 graceful / 18 unavailable-by-design / 4
backend-gated / 0 crashes (tool-test-lab/surface_results.json—
fresh artifact, this commit), with an execution check over a real MCP
stdio session against.cie/tasks.db.
Fixed
- The CLI answers the zero-config quickstart (roadmap R2). Query
commands (cie files,cie search-symbol,cie callers,cie skeleton,cie tasks:*, …) are no longer hardwired to build a Neo4j
connection: the same engine answers against the local SQLite graph
cie indexwrites. Selection rule:--backendflag ›CIE_BACKEND
env › auto (embedded when a.cie/graph.dbexists at--db/CIE_DB/
cwd, else Neo4j — unchanged for existing Neo4j users). Task commands
read/write the sibling.cie/tasks.dbvia the existing embedded task
re...
0.1.0a3 — dogfooded alpha
Third alpha, cut after dogfooding cie against itself (cie index . on this repo, then a live MCP conformance run across the full 126-tool surface).
Highlights
- Loader hygiene (
cie/extract.py): the tree walk behindcie index/reindex/graph_diffnow skips virtualenvs, dependency, cache, build and VCS directories. Indexing a venv holding a stale pip-installed copy of the project used to duplicate everycallers()answer (this repo: 1,779 files / ~28k nodes indexed → now 84 / 1,554). - Blast radius is now ground-truth-verified (
tests/test_graph_semantics_ground_truth.py): one fixture project where every true caller/callee is known by construction, asserted as exact sets. It caught and fixed two wrong-answer bugs:file_skeleton("app.py")leakedtest_app.py's symbols (substring path matching), andaffected_byomitted dependent TESTS edges — the test file was silently absent from its own blast radius. Both backends (SQLite + Neo4j) fixed. - Live MCP crash fixes: the embedded task repository is thread-safe (
get_task/list_pending_tasks/task_dependency_closure/blame_historycrashed because tool handlers run in worker threads); optional backends (core.llm, decompose plugins) now degrade as SPEC §0kind="unavailable"(HTTP 503) instead of raw crashes (qa,decompose_page+ 15 others). - Full-surface conformance, post-fix: 85 verified ok / 19 graceful error contracts / 18 unavailable-by-design / 4 backend-gated (need live Neo4j) — 0 crashes. Harness in
tool-test-lab/. - Repair transaction layer (
propose_patch/apply_patch/verify_patch) ships in this alpha, per the changelog it was drafted into.
Housekeeping
- 155/155 tests passing (was 129); test surface grew by 4 files, including exact-set ground truth.
- Versioning continues the documented PEP 440 ladder toward the eventual 0.1.0 stable (that stable cut remains a deliberate gate, per
goal.mdC1 — not faked by this alpha).
cie 0.1.0a2 — corrected alpha
cie 0.1.0a2 — corrected alpha. Supersedes 0.1.0a1.
⚠️ 0.1.0a1 is superseded. Its MCP server only ran on mcp 1.x; on mcp 2.x (whatpip install "cie[mcp]"resolves to today) the tests failed to import. Use 0.1.0a2.
What's fixed in 0.1.0a2
- The MCP server now runs on both mcp 1.x and 2.x.
build_mcp_serveris version-agnostic: it prefers mcp 2.x'smcp.server.mcpserver.MCPServerand falls back to mcp 1.x'smcp.server.fastmcp.FastMCP(in mcp 2.x,FastMCPwas renamed toMCPServerandmcp.server.fastmcpis a stub that raises). Thecall_tooltest normalizes the two return shapes (2.xCallToolResultvs 1.xlist[ContentBlock]). Verified on both with a real stdio JSON-RPC handshake. - Python 3.10 actually works.
cie/data_model.pyimportedtomllibunconditionally, buttomllibis 3.11+ stdlib — so it failed to import on 3.10, contradictingrequires-python = ">=3.10". Now uses atomlibackport fallback (conditional dependencytomli; python_version < "3.11").
CI
All green: pytest across Python 3.10 / 3.11 / 3.12 / 3.13, plus a real MCP stdio handshake smoke check on every push.
Quickstart (unchanged)
pip install "cie[mcp]"
cie index /path/to/your/project
cie-mcp /path/to/your/project --embedded # full (read+write) by default
cie-mcp /path/to/your/project --embedded --policy readonly # read-only clientSee CHANGELOG.md for the full history. 0.1.0.
cie 0.1.0a1 — first alpha
This tag's MCP server only ran on mcp 1.x; on mcp 2.x (what pip install "cie[mcp]" resolves to today) the tests fail to import, and its cie.data_model failed to import on Python 3.10. Both are fixed in 0.1.0a2 — use that.
Original 0.1.0a1 notes: first alpha release of cie — Code Insight Engine. See the CHANGELOG for what it shipped.