astria 1.0.8: provenance you can see, agents that can't answer from the past
1.0.8 makes the graph honest about what it knows and what it's guessing, tells you when it's stale, embeds with a code-aware model, and installs into sixteen agent platforms — including several it now drives as native tools. Install or upgrade with npm install -g @nodesify/astria.
Trust markings on every edge
A call edge was previously either source-verified (EXTRACTED) or reconstructed (INFERRED) — but a bare call name that binds to exactly one definition in the graph is much more than a co-occurrence guess. 1.0.8 introduces the RESOLVED tier: uniquely-bound call edges are upgraded above inference and deliberately kept below source extraction, so --detail high (compiler-grade facts) and the health checks still exclude them. On this repo, 3,013 of 11,828 call edges became RESOLVED; the rest stay honestly INFERRED, and affected now labels the tier of every hop in a blast radius instead of presenting inference as fact.
The same audit fixed direction: explain used to render the explained node as the source of every arrow, inverting caller/callee on incoming edges. Connections now render --> (this node calls/imports the neighbor) versus <-- (the neighbor calls/imports this node). And astria health's file-cycle detection consumes only edges the source literally contains — the old INFERRED-inclusive version chained 82 unrelated files into one phantom "cycle", and ten health points rested on that artifact.
The graph discloses its own staleness
Edits that arrive through paths without hooks — print-mode sessions, editors, plain typing — used to leave an agent confidently answering from a stale graph unless it noticed a raw timestamp. Every query header now reports how many manifest files changed since the build (# 3 file(s) changed since this build — run astria update before trusting answers). The check is stat-only, costs milliseconds, and clears itself on the next update. The MCP tool descriptions teach the same discipline: query_graph explains the file:line anchors and provenance tiers, affected says to run it before changing a shared symbol, and "No confident match" is documented as a rephrase hint, not an error.
Code-aware embeddings, one measured calibration
astria-embed swaps bge-small-en-v1.5 for jina-embeddings-v2-base-code (768 dims, 8k-token context, still fully local — no API key, offline after a one-time ~615 MB download). Every cosine threshold that used to be a scattered bge-scale constant now lives in one measured calibration table (astria_core::calibration), anchored by the calibrate example rather than inherited: jina's noise p95 sits at 0.24–0.44 where bge compressed half of all nodes above 0.55. Model-swap separability improved structurally — 0.79% of node pairs clear cosine 0.60 under jina versus 23.1% under bge.
Rust /// doc comments are extracted now too (extraction rules v12 — previously Rust had zero docstrings), feeding the doc-evidence ranking and the embedding text. Combined with a description-shaped semantic path that lets strong embeddings rank when a question shares no vocabulary with the graph ("auth flow"), the self-corpus golden moved: MRR 0.636 → 0.682, hit@1 51.4% → 60.0%, hit@10 unchanged at 91.4%. The embedder loads once per process, dropping the MCP server's steady-state embedded query from ~1.4 s to ~140 ms.
Sixteen platforms, one command
astria install --all wires every supported platform in one run. New since 1.0.7: VS Code (workspace-native MCP), Codex (user-global TOML, merge-safe), Trae, Windsurf, Kiro (its documented .kiro/settings/mcp.json), OpenCode, plus cline, roo, amp — and pi, which gets native astria_query/astria_map/astria_explain/astria_path/astria_affected tools through an auto-discovered extension, a few hundred context tokens instead of 10k+ of MCP definitions. Every flavor was verified against the real vendor CLIs and vendor docs, not just schemas — that process caught and fixed install-path bugs in Kiro, OpenCode, and VS Code configs before release.
Measured against targeted search
The external runner's deterministic baseline — question-derived rg terms, term-occurrence ranking, source windows — now has a checked-in comparison (worked/external-baseline/). Across eight Click/Express/ripgrep golden questions, structural astria retrieval ranked the defining file first 8/8 at every budget from 250 to 4,000 tokens (184–234 delivered tokens per response at the 250 budget); the single-pass baseline never ranked it first at any budget, with best ranks 4–12. Boundaries are stated in the write-up: deterministic baseline, not an expert iterative searcher; n=8 symbol-heavy questions.
Smaller and steadier
- No-confident-match floor — when no node matches any of a question's answer-identifying terms and nothing covers even half of them,
queryreturns an explicit miss naming the missing vocabulary instead of traversing 445 nodes of unrelated code. Weak-but-on-topic matches still traverse, andASTRIA_QUERY_SEED_FLOOR=offrestores always-traverse. - Rust constants are nodes (rules v11) — value questions ("which embedding model") were structurally unanswerable before; the answer's carrier wasn't a node.
- Model swaps self-heal on
update— foreign-model vectors re-embed through the ordinary refresh, or print the one-time--embedmigration command instead of stranding silently. - Entry-intent matching requires intact phrases — "domain files" no longer contains its way into matching "main file", killing a class of false entry-point overrides that won outright, not nudged.
- Corpus mode is explicit — the hidden
prose_share > 0.95switch is nowASTRIA_CORPUS_MODE=docs|code, disclosed in the query header. astria add --transcript <file|->— pipe any transcription tool straight into the graph:whisper ... | astria add --transcript -.- A judge-layer A/B harness (
scripts/bench/quality/judge-ab.mjs) productizes the mode experiment; LoCoMo QA accuracy is decomposed into retrieval vs reader vs ceiling legs, and Graphify's structural substrate is now a measured null result on prose.
Full detail in the changelog.