All notable changes to state-trace are documented here. The format roughly follows Keep a Changelog, and the project adheres to Semantic Versioning (with the usual pre-1.0 caveat that minor bumps may include breaking changes).
- Clarified MCP install docs to mirror Geometra's per-client syntax, with simple Codex install first and the absolute-path command labeled as a PATH-safe fallback.
0.3.3 — 2026-04-25
state-trace-mcp-confighelper command, pluspython -m state_trace.mcp_config, to generate project-scoped.mcp.jsonwith an absolute installedstate-trace-mcpcommand path. This makes Codex and other MCP clients more reliable when they launch servers with a minimal PATH.
- README MCP install docs now separate official PyPI installs from editable source installs and lead with per-repo Codex
.mcp.jsonsetup. server.jsonpackage metadata now matches the current0.3.3PyPI version.
0.3.2 — 2026-04-25
- iso-trace ingestion: O(N²) auto-link blowup.
extraction._extract_edge_candidatesran a per-node Jaccard scan against every existing node, generating ~70 spuriousdepends_on/related_toedges per node when fed an iso-trace transcript. The trajectory-source carve-out that disables this forswe-agentandopenhandswas missingiso_trace. Verified on a real Claude Code session (179 turns, 977 nodes): edges 76,123 → 10,578 (-86%). A 1,467-turn session that previously OOM'd at 4 GB during ingestion now completes cleanly (6,411 nodes / 61k edges) and retrieval correctly surfaces the expected files.
retrieve_brief~270× faster on large graphs. On the 6,411-node / 61,017-edge JobForgePersonal session: per-query wall time dropped from ~250 s to ~1 s warm-cache. Five behavior-preserving changes:graph.find_edgesuses networkx's indexedout_edges/in_edgeswhen an endpoint is pinned, instead of a full O(E) scan._supersession_bonuswas calling it twice per scored node — ~615 M edge tuple comparisons per retrieve.retrieval._build_causal_chainsbuilds a lightweightnx.Graphtopology instead ofgraph.to_undirected()(which deep-copies every PydanticNode/Edge, ~17 s on a 61k-edge graph).retrieval._seed_nodesmemoizestokenize_sequence(_document_text(node))per(node.id, len(content))— node BM25 tokens are deterministic, so recomputing on every retrieve was wasted work.graph.namespace_viewreturnsselfwhen every node already lives in the requested namespace, instead of rebuilding the full graph (~1.5 s on a 6.4k-node single-namespace engine)._artifact_bridge,_edge_semantic_bonus,_provenance_bonus,_supersession_bonusare now computed in single O(E) edge sweeps that update both endpoints in one pass, replacing 2×|scored| per-node neighbor walks. Cutsget_neighborscalls from ~5,800 to ~830 per retrieve.
All 52 tests pass. No public API changes.
0.3.1 — 2026-04-25
mcp-nameverification comment inREADME.mdandserver.jsonmanifest at the repo root, in preparation for publishing to the MCP Registry. No code changes.CHANGELOG.md(this file).
0.3.0 — 2026-04-24
- Module-to-path translator in
retrieve_brief's lexical fallback. Dotted Python module references (astropy.modeling.separable_matrix) now resolve to file path candidates (astropy/modeling/separable.py), with conservative filtering on capitalized segments. Pushed SWE-bench-Verified A@1 0.216 → 0.254 and A@5 0.322 → 0.376 at n=500. - iso-trace ingestion adapter at
state_trace/iso_trace_adapter.py. Reads@razroo/iso-trace's normalizedSession → Turn → Event[]JSON and converts it to state-trace'sagent_logformat. Lets users seed working memory with accumulated Claude Code / Cursor / Codex / opencode session history. Two tests cover the pure transform and end-to-end ingestion. - GitHub / GitLab blob URL extraction in the lexical fallback. Issue text containing URLs like
github.com/.../blob/main/astropy/io/ascii/html.pynow contributes the embedded path to file candidates.
- README headline benchmark: state_trace now leads every baseline (BM25 and Graphiti) with non-overlapping 95% CIs across both A@1 and A@5 at n=500.
- README adds a Live solve-rate section reporting the n=20 docker-harness result (35% both arms — see "Honest finding" below).
- Real solve-rate via swebench docker harness at n=20: state_trace 7/20, no_memory 7/20 (35% each). The two arms resolve different subsets (5 overlap, 2 unique each, union 9/20 = 45%). state_trace's localization wins do not translate to aggregate solve-rate wins when paired with Codex CLI as the downstream agent — Codex is already near-ceiling at file localization on its own. Published as a negative result rather than buried.
0.2.1 — 2026-04-23
retrieve_brief.target_filesno longer collapses to a single candidate. Three changes together:target_files[:4]→target_files[:5].- Lexical fallback when fewer than 5 file nodes exist in the graph: mines candidates from the query, top-scored node
issue_textmetadata, and embedded GitHub blob URLs. - The
fit_agent_briefbudget loop's floor fortarget_filesraised from 1 to 3, so the budget squeeze can't strip Artifact@5 candidates back down to a single file.
- The pre-fix collapse made A@5 ≡ A@1 by construction. Fix moved n=500 A@1 from 0.150 → 0.216 and A@5 from 0.150 → 0.322.
0.2.0 — 2026-04-23
MemoryEngine.current_state(session)— direct query for the live working-memory view (active task, latest observation/decision, non-stale active files). Filters out invalidated and superseded nodes.MemoryEngine.failed_hypotheses(session)— direct query for "do not propose again" memories. Four sources:invalid_atset,status="error"without later validation, nodes pointed at bysupersedesedges, and (added in this release) nodes withmetadata.rejected_angle=True.- MCP tools for both:
current_state,failed_hypothesesexposed viastate-trace-mcp. - Graphiti-on-Kuzu backend in
examples/swebench_verified_eval.pyfor an honest head-to-head at n=500 with deterministic stub embedder/reranker. examples/swebench_verified_solve_rate.pyscaffold for live solve-rate evaluation.ARCHITECTURE.mdexplaining the networkx + SQLite design choice vs Neo4j/Kuzu.BENCHMARKS.mdtranslating every metric into real-world terms.- vs-Graphiti README section with 13-row head-to-head table backed by benchmark numbers or concrete API calls.
retrieve_briefno longer forcespatch_filefor non-file-oriented queries.- Top two evidence lines now get a wider character budget so load-bearing detail (numbers, paths) survives small-model compaction.
failed_hypothesesrecognizesmetadata.rejected_angle=Trueas a fourth failure source.current_state.latest_observationsorts by actual recency (event_at,created_at,step_index) instead of step_index alone — fixed a bug where the oldest write surfaced as "latest" when multiple observations shared step_index=0.
- SWE-bench-Verified localization at n=500 (no_memory, BM25, state_trace, graphiti). state_trace beats Graphiti on Artifact@1 with non-overlapping CIs in this release; ties BM25 with overlapping CIs.
0.1.0 — 2026-04-23
- Initial PyPI release.
MemoryEnginecore API:store,retrieve,retrieve_brief,record_action,record_observation,record_test_result,ingest_text,store_agent_log[_file],step.GraphManagerovernetworkx.MultiDiGraphwith namespace-view filtering.- Hybrid retrieval (BM25-style lexical seed + edge-aware graph traversal + state-aware reranking).
- Bounded capacity with decay, compression, and lifecycle retention.
- WAL SQLite + FTS5 backend for durable working memory; auto-selected when
storage_pathends in.db/.sqlite/.sqlite3. - Stdio MCP server (
state-trace-mcpentry point) shipping in the[mcp]extra. - LangGraph and LlamaIndex framework adapters that don't import the host frameworks.
- FastAPI surface with
/store,/retrieve,/retrieve_brief,/graphendpoints. - Repo-local benchmark suite: held-out live, offline retrieval, Graphiti head-to-head, budgeted harness proxy, live harness replay, long-horizon memory pressure.