Disclosure: Nodesify builds and maintains Astria. This article explains the released 1.4.0 implementation and its limits. The architecture diagram is illustrative; it is not a benchmark or a captured repository graph.
A coding agent asking “who calls save?” first needs to know which save the question means. Two declarations with the same name can live in different classes, files, or lexical scopes. Choosing one silently can produce a convincing answer about the wrong code.
Astria 1.4.0 tightens supported source bindings and makes uncertainty easier to inspect. Scoped receiver evidence, explicit seed candidates, complete merge refreshes, and per-file semantic coverage help an agent decide what to read and what still needs verification.
Follow the evidence from source to answer
Teams should consider this release when an ambiguous symbol, evidence classification or incomplete refresh could affect a change decision. After upgrading, rebuild or refresh as directed by the release documentation, replace installed hooks as documented, then rerun one known query and inspect its source. A successful command alone does not demonstrate that every semantic or derived stage completed.
Here is a synthetic reading exercise, not captured Astria output: a query for save finds src/orders/store.ts:42 and src/profile/store.ts:18. Select the exact order declaration ID returned by your current graph, inspect its incoming caller and reported evidence class, then read both source locations. If the relationship is inferred, retain that uncertainty. If the candidate ID changed after rebuilding, resolve it again rather than reusing a remembered ID. This is the decision the command examples below are intended to support.
The illustration above summarizes the source-to-answer architecture. Evidence classes describe how a relationship was established; they do not prove runtime behavior. Optional enrichment and derived publication stages are summarized in the diagram and explained in the linked reference.
The indexing path and the query path have different jobs:
- Discover source and project metadata. File discovery and parser selection share the language registry. Supported extensionless scripts can be identified from a bounded shebang read, including supported versioned interpreters. Configuration inputs help determine how imports bind.
- Extract symbols and reconcile references. Tree-sitter records declarations, source locations, signatures, and syntax relationships. A reference pass considers the current corpus, including references from files whose parsing results were reused from cache.
- Publish the graph in SQLite. Validated core facts, the file manifest, and publication metadata commit together. Derived passes and exported artifacts follow their own publication steps.
- Select seeds and traverse. Queries resolve explicit entry points or rank relevant candidates, then discover graph context through BFS or DFS under evidence and direction filters.
- Deliver bounded context. CLI and MCP reach the same Rust query engine. Results carry source evidence and freshness information; rendered text respects its token budget and can return a continuation cursor.
The architecture reference covers the omitted details, including optional embeddings, model enrichment, generation-keyed read snapshots, and recovery boundaries.
Keep type evidence inside its scope
Type-aware receiver resolution was introduced before 1.4. This release corrects cases where the evidence could cross boundaries it should not cross.
A local variable named service in one function must not establish the receiver type of an unrelated service in another function. Typed bindings now stay within their function or block, annotated locals parse correctly, and exact TypeScript path aliases resolve to authored source files.
Unambiguous instance-field assignments can also provide type evidence. Conflicting assignments, deleted fields, unknown computed properties, static access, and shadowed bindings cannot establish that unique receiver. Uncertainty remains visible instead of becoming an invented call target.
The same precision matters for names: punctuation-sensitive symbol identity and exact member spelling help distinguish declarations that search normalization might otherwise collapse.
Ask for an exact declaration
Explicit seeds let an agent anchor a query at a known symbol. In 1.4, a name that matches multiple declarations returns candidates instead of selecting one.
astria query "who calls save" --seed save --json
Inspect ambiguousSeeds for candidate IDs and source locations. Choose the declaration that matches the task, then copy its returned ID into the next query:
astria query "who calls this declaration" --seed '<candidate-id>' --json
astria affected '<candidate-id>' --json
<candidate-id> is a placeholder, not a literal node name. MCP callers use the seeds array on query_graph, followed by affected for potential consumers. If no supplied seed resolves uniquely, Astria returns a miss without substituting keyword results.
Structured responses retain complete candidate lists. The token budget bounds rendered query text; clients still need to budget the surrounding JSON and metadata. Follow continuation cursors when the task requires more context.
Read a relationship’s evidence class
| Evidence | Useful interpretation | Limit |
|---|---|---|
EXTRACTED / DECLARED |
A source structure or declaration was recorded | Parsing is not runtime verification |
RESOLVED |
Supported source evidence selected a unique endpoint | A name/type-derived binding is not compiler proof of runtime dispatch |
INFERRED |
A possible or heuristic relationship exists | Verify before describing it as a concrete execution path |
SEMANTIC |
Optional model enrichment proposed the relationship | Preserve its model-derived status |
--detail high keeps only EXTRACTED and DECLARED relationships. It excludes even a high-scoring RESOLVED binding: the filter concerns provenance, not just numeric confidence. Ambiguous evidence must also stay ambiguous in the agent’s answer.
An unresolved stub has no owning source file. An agent should not turn the file that mentions it into its definition. We previously investigated how that mistake created phantom dependencies. A missing graph path likewise does not prove there is no runtime dependency.
Refresh the whole incoming change
The post-merge hook now examines the complete ORIG_HEAD..HEAD range, including a fast-forward pull. A source change earlier in the incoming range must not be missed merely because the final commit only changes documentation. Changed project configuration and other graph inputs can also require reconciliation.
After upgrading an existing installation:
npm install -g @nodesify/astria@1.4.0
astria update .
astria hook install
For a repository without a graph, start with astria run .. Refreshing reconciles extraction-rule and symbol-identity changes; reinstalling hooks replaces the local scripts. Use IDs returned by the refreshed graph. The rename investigation remains a dated example of the difference between detecting staleness and having current stored facts.
See coverage and failure boundaries
The release adds handling for Kotlin type aliases, C# delegates, Dart typedefs, and Swift macros. Registration still does not guarantee complete language semantics. Type references and macro calls resolve only with uniquely supported evidence; check the language support reference for scope.
For optional semantic extraction, astria diagnose --graph . reports processed/total chunks, cache status, and incomplete reasons for each file’s last attempt. A chunk-limit or provider failure does not publish or cache partial semantic output as a complete result. Correct the cause and retry.
Core extraction failures leave the graph and successful manifest unadvanced. A later derived-stage failure can occur after a successful core commit, so clients should inspect freshness and publication metadata rather than assume every artifact represents the same completed stage.
Credential-shaped source text is redacted before retention and semantic requests, and credential literals are excluded from reference identities. This is pattern detection, not a guarantee that arbitrary private data is safe to transmit. Explicitly choose the content and backend appropriate for the repository.
Give the agent an operating procedure
The AI workflow and evidence contract specifies the sequence: orient, query, disambiguate, read source, check impact, edit, and refresh. It also explains how to handle stale graphs, incomplete extraction, and untrusted repository text.
Agents can read llms.txt for the released documentation index, llms-full.txt for the combined content, or individual Markdown pages linked from the index. The version header identifies the released snapshot. Blog measurements remain tied to their dates, corpora, and methods.
This release article makes no new retrieval or token-saving claim. Our evaluation article documents a separate historical comparison. The practical test here is narrower: choose a declaration you know, inspect one reported relationship, and verify its source before relying on it for a change.
Astria is MIT-licensed. Read the full 1.4.0 changelog and source repository for the release details.
Frequently asked questions
Can we evaluate locally, and what does optional enrichment send?
Start with the documented local AST workflow. Optional semantic extraction uses the configured backend and selected source material; review its data handling before enabling it. Pattern redaction cannot guarantee removal of arbitrary confidential content. Follow the workflow and evidence contract.
Does registered language support mean complete coverage?
No. Check the linked language-support reference and diagnose incomplete files. A useful team trial names one known relationship, verifies it against source and assigns refresh ownership before broader adoption. The self-service documentation is the starting point; request an architecture review only when you need help evaluating that workflow.




