Skip to content

Releases: Nodesify/astria

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 06 Oct 16:08
82687a4

1.1.1 — 2026-10-06

Maintenance release; no user-facing behavior changes.

  • Migrate the native-module packaging toolchain from @napi-rs/cli v2 to v3.10.8: the napi config moves from triples to flat targets (v3 rejects the duplicate target v2's defaults expansion produced) and the release workflow switches to the v3-only create-npm-dirs command. The generated platform packages were verified locally before the pipeline's first tagged run.
  • TypeScript 7.0.2 (native compiler) across packages/astria-cli and packages/viewer; typecheck, emit builds, the CLI test suite, and the viewer bundle were all verified on it.
  • Dependency and CI maintenance: @types/node 22.20.5, Rust crate and npm devDependency bumps, GitHub Actions pinned updates, and internal planning docs removed with dogfood output ignored.
  • The musl probe workflow now asserts the known rustc ≥ 1.99 condition (no cdylib without -crt-static) instead of failing permanently via continue-on-error, so its check run is green while the workaround is needed and red the day rustc fixes it.

What's Changed

New Contributors

Full Changelog: v1.1.0...v1.1.1

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 16:45
c778994

1.1.0 — 2026-10-06

  • Preserve qualified symbol boundaries and import paths when resolving references; ambiguous candidates remain unresolved and inferred bindings retain RESOLVED evidence. Extraction cache v15 refreshes previously flattened targets.
  • Prefer exact implementation definitions for code-oriented queries, with scope and source metadata contributing to ranking.
  • Name communities from source modules and packages; reports separately orient production code, documentation, and tests/benchmarks/examples, with source links and explicit relationship evidence.
  • Propagate authoritative database decoding errors in analysis, clustering, hyperedge construction, and reports rather than silently discarding rows.
  • Add 24 reserved questions on pinned Requests and Commander sources, a bounded iterative search baseline, and separate retrieval/build cost and provenance records. The new corpus and methods have not been evaluated.
  • Simplify the README workflow and align architecture documentation with snapshot caching and reference evidence.
  • Speculative graph nodes no longer claim a source file. A stub or reference node exists precisely because no file defined the name, so it has no source locus; it previously borrowed whichever file referenced it first. That fabricated a file location for unresolved globals (a lone import rusqlite became health.rs -> <first file to mention rusqlite>), producing 743 phantom file-to-file dependencies on this repo, four file "cycles" that do not exist in the source, and a false File: line in explain. A whole-graph invariant pass clears stale loci on every run, so an incremental update heals graphs built by earlier versions. explain now reports (no source locus — unresolved name, no single owner) instead of naming a file that does not own the symbol.
  • Fewer false positives from test files. is_test_file did not recognise __tests__/, .test.ts, or .spec.ts, so JS/TS test helpers were scored as production code: on this repo a test-only assert() ranked as the #3 hub and test_hubs_skipped stayed 0. Hub detection, dead-code candidacy, and file-cycle inputs now use the same corrected matcher.
  • astria health --min-score <n> exits non-zero when the score is below n, so the command works as a CI gate; it previously always exited 0, which made the obvious threshold check silently never fire.
  • astria merge-gate checks the extraction ruleset (extraction-current) alongside age and HEAD coverage. A graph reused from an older extraction cache passes both of those while reporting facts the current build would extract differently; the gate now fails and points at astria update ..
  • Ranking surfaces ignore non-code nodes. Hub concentration, file_cycles, report "Key Files", "surprising connections", and the local embedding layer all exclude speculative nodes, so similarity between two unresolved bare names is no longer presented as structure.
  • Ground-truth note: measured on this repository, the fix removes 743 fabricated file dependencies, 4 false cycles, and 1,302 similar_to edges that joined two non-symbols; retrieval quality on the golden set is unchanged by these edits (MRR 0.5979 before and after, byte-identical), so this is a correctness and honesty change, not a ranking change.

What's Changed

  • chore(release): lockfile entry for win32-x64-msvc@1.0.12 by @erictong0602 in #116
  • fix(release): restore musl cdylib under rustc 1.99 (-crt-static) + homebrew 1.0.12 by @erictong0602 in #117
  • chore(release): 1.1.0 — graph-evidence honesty and CI gates by @erictong0602 in #118

Full Changelog: v1.0.12...v1.1.0

v1.0.12

Choose a tag to compare

@github-actions github-actions released this 03 Oct 19:22
be43f86

[1.0.12] — 2026-10-04

Project-review backlog — 36 defects + 6 engineering improvements (3 October)

Source-backed review of every workspace crate and the CLI; findings and statuses in docs/project-review-2026-10-03.md.

  • Security boundaries — HTML exports escape every < in embedded graph JSON (mixed-case </SCRIPT> could terminate the data element); MCP configuration files are excluded from raw LLM enrichment (literal credentials can no longer leave the machine through a remote backend); bolt+s:///bolt+ssc:// now ride rustls with scheme-preserving transport instead of silently downgrading to plaintext TCP; HTTP MCP enforces a whole-request deadline with per-read recomputation and exact loopback matching (127.attacker.example is not loopback); yt-dlp media downloads are resolved and vetted through the SSRF policy (-J --simulate) before any byte moves; URL classification parses host/path instead of substring-matching the whole URL.
  • Graph identity & integrity — node ids are case-preserving (Foo/foo stay distinct; matching stays case-folded), with duplicate-id disambiguation rewiring edges to the surviving definition and the extraction cache version advanced to v14 so pre-fix caches invalidate cleanly; automatic global tags check existing names before allocating (no more repo duplication/replacement); merge is atomic — edges reconcile, the database swaps with rollback, artifacts stage as .new and flip only after the swap, and the generation is stamped inside the transaction; global replace runs fully transactionally with relation reconciliation after commit.
  • Freshness & publication trust — every publication mints a generation stamp (_meta.graph_generation, generation.txt, _meta in graph.json, report footer) so database, JSON, and report of one build are matchable and snapshot caches key on it; unchanged Google Workspace shortcuts re-check their remote revision instead of trusting shortcut bytes; the merge gate fails on git-detection errors instead of silently skipping its checks.
  • Semantic backend honesty — token reservations span the whole request+response with guard-based release and per-backend max_tokens sharing the same constants (the advertised budget is reserved before the call, not audited after); content needing more than the chunk cap fails loudly (ASTRIA_LLM_MAX_CHUNKS) instead of truncating and caching as success; Bedrock stopReason is checked before accepting text; derived-text lookup validates against the extraction-hash family (config-hash lookups that never matched what extraction wrote are gone); malformed LLM replies never become cached empty successes.
  • Dependency advisories (release day) — quick-xml 0.37/0.39 → 0.41 and calamine 0.34 → 0.36 close RUSTSEC-2026-0194/0195 (quadratic attribute-check and unbounded namespace-declaration DoS in XML parsing, fresh in the advisory database when the release CI first ran); office-crate call sites moved to the 0.41 decoder API.
  • Everywhere else — XLSX decompression bounds are pre-checked via a bounded <dimension> zip scan before allocation; non-ASCII document titles can't panic filename creation; watch mode covers every supported file type and directory renames; database decode errors surface instead of silently truncating graphs; Bolt 3 RUN carries its third (extra) field per the official spec; risk traversal propagates errors; the viewer bundle is drift-checked in CI; a version-to-version A/B harness ships in scripts/bench/ab/.

Follow-up review — publication, coverage, health, cache (3–4 October)

  • Cache invalidation is part of graph publication — the generation advances inside the core transaction and immediately after every derived pass that commits a content change; unchanged runs reuse the previous generation; cluster-only republishes through the same artifact workflow as full pipelines.
  • Merge-gate coverage is commit identity, not timestamps — the pipeline records _meta.git_head at publication and verifySourceCommit compares it with the current HEAD while re-hashing every manifest file (the graph's own versioned scheme); query headers disclose source drift (modified / deleted / size-changed) separately from graph age, and relative manifest paths resolve against the project root so probes work from any cwd.
  • Health-score heuristics corrected — containment and co-occurrence edges no longer count as reachability (dead-code detection finds real candidates again); hubs must clear max(10, the graph's own 95th-percentile usage degree), and test-file hubs are reported, not scored.
  • Multi-project snapshot cache — the process-wide graph cache becomes a bounded LRU keyed by database path + generation (default 3 entries, ASTRIA_SNAPSHOT_CACHE_ENTRIES 1–16); alternating MCP projects share snapshots instead of evicting each other.
  • Retrieval evidence — the paired runner's report emits exact-symbol ranking (definition recall@5 + MRR) beside file recall and delivered tokens, plus a per-case definition-miss triage list; known failure modes are ranked as evaluation priorities.
  • Documentation — architecture claims derive from the registry (language counts drift-checked by scripts/check-docs-sync.mjs), the snapshot-cache description matches the LRU, and the review backlog carries per-finding status tables.

Platform & integration — team serving, cloud backends, CI artifacts (#B1–B5)

  • MCP over HTTP + multi-project serving — astria mcp --http serves one or many project graphs over MCP Streamable HTTP (JSON responses; GET /healthz for liveness) from a single process, complementing the stdio transport. Clients select a project with the x-astria-project header or ?project= query (unknown names 404 — no silent fallback); --graph is the default project and --projects name=path adds more. Bearer auth (--token / ASTRIA_MCP_TOKEN) is mandatory whenever the server binds a non-loopback host — unauthenticated remote serving is refused at startup. No async runtime: thread-per-connection, a fresh SQLite handle per request. Transport routing, auth, and project resolution are tested without sockets.
  • First-class Azure OpenAI, AWS Bedrock, and Kimi backends — --backend azure authenticates with Azure's api-key header against {endpoint}/openai/deployments/{deployment} (+ mandatory api-version query), --backend bedrock calls the Bedrock Converse API with real SigV4 request signing (self-contained HMAC-SHA256 implementation pinned to independently computed reference signatures; static keys and AWS_SESSION_TOKEN temporary credentials both work), and --backend kimi is the OpenAI-compatible surface pointed at Moonshot with Kimi's key variables and default model. Bedrock's Converse usage format (inputTokens/outputTokens) joins the usage counter's understood wire formats. All three are documented in env-vars.md with their ASTRIA_* and vendor env names.
  • Rich PR dashboard — astria prs now pulls CI state (statusCheckRollup), review decision, mergeability, author, and diff size in one gh pr list call, maps PR branches onto git worktree list locations, ranks the review queue by urgency (failing CI, requested changes, conflicts, graph blast radius, draft penalty), and prints merge-order risk on --conflicts. --triage gives compact per-PR lines; --json emits the ranked queue with every signal.
  • Git merge driver for the graph file — astria merge-driver install wires a three-way union-merge driver into .gitattributes + merge.astria.* git config so parallel branches that both commit .astria/graph.json merge instead of conflicting: additions from both sides survive, deletions are respected, fields resolve 3-way (unchanged side takes the changed side), and communities (derived data) resolve to whichever side moved. .astria/graph_report.md gets git's built-in union driver. uninstall removes the wiring; run is the git-invoked entry point.
  • Docker distribution — a multi-stage Dockerfile in the repo root (Rust+Node builder → slim Node runtime) ships the full CLI with no toolchain inside; analyze a mounted repo or serve the HTTP MCP on exposed port 8620; --build-arg NAPI_FEATURES=--no-default-features produces a smaller image without the embedding runtime.
  • Hosted-tier OSS surface — astria merge-gate is a CI check that fails on missing/stale graphs (publish timestamp vs wall clock and last commit), health-score floors, and diff blast-radius ceilings (--json for pipelines); astria digest renders a deterministic markdown engineering brief (overview, health, hub concentration, largest communities, LLM spend) for stdout, --out, or cron. These are the same primitives the hosted tier (app.graphify.com) operates for teams.
  • Deep-clean uninstall — astria uninstall --purge removes every platform install plus the artifacts plain uninstall deliberately leaves: git hooks, merge-driver wiring, the project .astria/ data directory, and the ~/.astria global store. Explicit-flag consent, no prompt, CI-safe.

Query & graph features (#C1, #C3, #C4)

  • CJK query segmentation — the retrieval tokenizer now segments Chinese/Japanese/Korean runs with jieba (dictionary + HMM, built once per process), so "用户登录怎么处理" matches the labels that say 用户 and 登录 instead of arriving as one unmatchable character run. Non-CJK tokenization is byte-for-byte unchanged; nearest_labels suggestions now share the tokenizer (with stopword filtering), so did-you-mean works for CJK too.
  • Clustering controls — astria cluster-only --resolution <0.0–1.0> requires a minimum share of a node's neighbors to agree on the winning community before the node joins it (default 0.0 = classic propagation; higher values → more, smaller communities, same direction as Louvain's resolution), and --exclude-hubs holds high-degree hub nodes (degree ≥ max(12, 4× mean)) out of label propagation entirely so they can...
Read more

v1.0.11

Choose a tag to compare

@github-actions github-actions released this 01 Oct 16:59
b3e3ee3

[1.0.11] — 2026-10-02

Code audit — data safety, installer ownership, native loading, CI and site

  • DB migrations are atomic and self-healing — each schema step now commits its DDL and its schema_version bump in one transaction (SQLite DDL is transactional), and ALTER steps check PRAGMA table_info first. Before, a crash between an ALTER and its version stamp left a database whose next open re-ran the ALTER, failed with duplicate column name, and bricked every later command against that repo; the idempotent guard also repairs databases the old code had already stranded. Regression-tested (interrupted_migration_is_repaired_not_fatal).
  • The installer no longer wipes unparseable configs — readJson used to swallow any JSON parse error and return {}, which the subsequent rewrite made permanent. A non-empty unparseable file now aborts the install with a refusal naming the path; a UTF-8 BOM is tolerated; and .vscode/mcp.json (officially JSONC — comments and trailing commas are legal) is parsed with a conservative comment/trailing-comma stripper so commented team configs install without losing their servers. All installer config rewrites (JSON, the Codex TOML, markdown sections, git hooks) now write via temp-file + rename, so a crash mid-write can never leave a truncated file — which is what previously turned into a wipe on the next install.
  • Uninstall removes only what install wrote — three ownership gaps closed: removeAgentMcp deleted any astria/graphify MCP entry regardless of authorship (a user-written entry with those names survived install's own preserve check only to be deleted on uninstall); removeSection deleted unmanaged ## astria markdown sections that install correctly treats as user-owned, and its heading match was prefix-based, so ## astria-guide was caught too; and hook entries were claimed by bare substring — a user's own astria hook-guard read --strict PreToolUse hook (the command our own docs suggest) was deleted by astria uninstall claude. MCP ownership now uses one isInstallerServer predicate across install/uninstall/legacy cleanup; markdown removal requires the managed marker; hook matching keys on the structural fingerprints every installer template carries (a quoted .astria/.graphify path segment, or the pre-1.0 package name).
  • The updater hook is no longer appended to shell hooks — appending the JavaScript updater to a #!/bin/sh hook (a user hook, or a husky-style hook under core.hooksPath) broke that hook with syntax errors on every commit while the graph refresh silently never ran; the old test asserted the appended file content but never executed the hook. Install now appends only to Node-script hooks and skips others with an explicit notice (a foreign Node hook still merges cleanly — both paths tested).
  • A missing native binary no longer kills the whole CLI — the platform-package require had no try/catch (the crafted diagnostic was unreachable in exactly its target scenario), the musl switch arms require packages that were never published (Alpine was a guaranteed raw MODULE_NOT_FOUND), and the binding loaded at module scope, so even astria install, astria uninstall, and --version crashed before Commander ran. Every require is guarded, the binding loads lazily on first native call, and the diagnostic names the resolved platform target and the musl limitation.
  • Bolt decoding bounds server-controlled sizes — PackStream list/struct lengths from a Neo4j server fed Vec::with_capacity unbounded (a hostile LIST_32 length was an allocator abort, uncatchable across the napi boundary), and message deframing had no total-size cap; both are now bounded (element count clamped to remaining bytes, messages capped at 256 MiB with an InvalidData error). Hostile-input tests added for all three decoders and the frame cap.
  • Copilot's skill file installs where Copilot reads it — repo-scoped .github/skills/ in the project (docs.github.com), not ~/.github/skills/; the test's own comment already said project-scoped while asserting the home path. Installs clean up the 1.0.9/1.0.10-era home-dir copy, and file-stem layouts (cline/roo) keep their identity guard so a second install still never deletes its own skill.
  • Smaller correctness fixes — unknown --platform now exits 1 (it printed Unknown platform and exited 0, so scripts could not detect the failure); uninstall reads CLAUDE_CONFIG_DIR through the same sanitizer install uses and removes both candidate skill roots (the raw env var previously reached an unlinkSync unvalidated); npm run napi:dev -- --debug builds no longer lose to a stale release artifact (candidate order follows the profile just built); bench-snapshot's two pushing jobs are serialized (needs: — the concurrency group serializes runs, not jobs within a run, so one push used to lose the race) with permissions narrowed per job; promptfoo is pinned (@0.123.1) instead of npx promptfoo@latest with the judge API key in env.
  • Website truthiness — homepage language count corrected to 25 (the registry has 25; README already said 25); the 1.0.10 docs version cut and lastVersion refresh (default /docs was five releases stale at 1.0.5); release-notes blog posts for 1.0.9 and 1.0.10, which the sidebar's "Release notes" feed stopped at 1.0.8.

Distribution audit — four fixes

  • Homebrew formula installed no executable — std_npm_args installs global-style into libexec (package at libexec/lib/node_modules, executables linked at libexec/bin), but the 1.0.10 formula symlinked libexec/node_modules/.bin/astria — a local-install path that never exists under libexec — and Homebrew's install_symlink over an empty glob is a silent no-op, so brew install nodesify/tap/astria "succeeded" with no astria command. The formula now symlinks libexec/bin/* (homebrew-core's idiom for npm packages) at revision 1; the live tap carries the same fix.
  • The Claude Code plugin shipped without its MCP server — the plugin root is the repo root (marketplace source: "./"), and its only MCP registration was the root .mcp.json, which is machine-local and gitignored — so marketplace installs delivered the skill, commands, and subagent but zero MCP servers, despite 1.0.9's "the tracked .mcp.json" changelog claim and the plugin's own description. .claude-plugin/plugin.json now declares the astria stdio server inline via mcpServers (the same astria mcp entry astria install writes), which ships with the tracked tree. Plugin and marketplace metadata move to 1.0.11 ahead of the npm package so version-caching plugin managers register the changed plugin — the npm package, server.json, and the registry listing stay at 1.0.10 until the next tagged release.
  • The release verify step checked versions only — the field that actually broke v1.0.9 (mcpName vs server.json name, the 403 namespace case mismatch) was never compared, so a future drift would again surface only at the post-npm registry step where immutability makes it unfixable without burning a version. The step now verifies name vs mcpName, the npm entry's identifier vs the package name, and the per-package version, alongside the top-level version.
  • mcp-publisher is pinned and checksum-verified — the registry publish step downloaded releases/latest and executed it with the job's OIDC and GitHub tokens, the only unpinned external code in a workflow where every action is SHA-pinned. Now pinned to v1.8.1 with a sha256 check; moving to a newer publisher is a deliberate tag+checksum bump.

What's Changed

  • docs: update documentation for astria 1.0.5 by @nodesify-technology in #86
  • chore(bench): publish 1.0.5 benchmark snapshots by @erictong0602 in #87
  • Release 1.0.6 — chunked document retrieval, cross-conversation ranking, introspection commands by @erictong0602 in #88
  • ci: Node 24 action upgrades + runner label pinning by @nodesify-technology in #89
  • Release 1.0.7 — judged semantics, drill-down viewer, scoped retrieval by @erictong0602 in #90
  • Release 1.0.8 — RESOLVED provenance, code-aware embeddings, sixteen platforms by @erictong0602 in #91
  • Release 1.0.9 — official MCP Registry publishing, Claude Code plugin marketplace, Homebrew tap by @nodesify-technology in #92
  • Sync main with 1.0.10 — registry namespace fix, hardened release workflow by @erictong0602 in #93
  • Sync main — distribution audit fixes: plugin MCP server, brew binary, release gates, pinned publisher by @erictong0602 in #94
  • Sync main — full-repo audit: atomic migrations, installer data safety, lazy native loading, bolt bounds by @erictong0602 in ht...
Read more

v1.0.10

Choose a tag to compare

@github-actions github-actions released this 30 Sep 18:45
54246bf

[1.0.10] — 2026-10-01

Distribution fix — MCP Registry namespace case

  • v1.0.9 reached npm but not the registry — the official MCP Registry publish failed with 403: the GitHub OIDC grant is io.github.Nodesify/* (the org login's case is significant) while server.json declared io.github.nodesify/astria. npm is immutable, and registry validation compares the published package's mcpName against the server name exactly — so both move to io.github.Nodesify/astria in this release; 1.0.9's lowercase mcpName can never validate. Automated registry publishing, the Claude Code plugin marketplace, the Homebrew tap, and smithery.yaml are unchanged from 1.0.9.

What's Changed

  • Release 1.0.8 — RESOLVED provenance, code-aware embeddings, sixteen platforms by @erictong0602 in #91

Full Changelog: v1.0.9...v1.0.10

v1.0.9

Choose a tag to compare

@erictong0602 erictong0602 released this 01 Oct 02:01
b442f45

[1.0.9] — 2026-10-01

Distribution — official MCP Registry, Claude Code plugin marketplace, Homebrew tap, Smithery

  • Official MCP Registry publishing is automated — the repo now carries a registry server.json (io.github.nodesify/astria, stdio transport over the npm package) and release.yml publishes it via mcp-publisher with GitHub OIDC after the npm publishes succeed; the verify job fails fast when server.json's version drifts from the package version. npm packages must declare the matching mcpName for registry validation — added to packages/astria-cli/package.json. The first listing goes live on the next tagged release.
  • The repository is a Claude Code plugin marketplace — /plugin marketplace add Nodesify/astria then /plugin install astria@nodesify installs, in one plugin: the MCP server (the tracked .mcp.json), the graph-first skill (skills/astria/), two slash commands (/astria graph queries, /astria-risk PR-ready risk report), and an astria-architect subagent — wired through .claude-plugin/marketplace.json + .claude-plugin/plugin.json.
  • Homebrew tap — brew install nodesify/tap/astria installs the published npm package; the formula ships in the new Nodesify/homebrew-tap repo, with per-release update instructions in packaging/homebrew/README.md.
  • Smithery registry config — smithery.yaml (stdio start command over the published npm package, optional projectPath) so smithery.ai lists the server once the repo is connected there.
  • Discovery metadata — GitHub topics gained claude-code and agent-skills alongside the existing mcp-server/model-context-protocol set.

What's Changed

  • Release 1.0.7 — judged semantics, drill-down viewer, scoped retrieval by @erictong0602 in #90

Full Changelog: v1.0.8...v1.0.9

v1.0.8

Choose a tag to compare

@github-actions github-actions released this 30 Sep 17:12
fc7f8b4

[1.0.8] — 2026-10-01

Agent experience — staleness disclosure and MCP tools that teach their use

  • Queries disclose a stale graph — the header now reports how many manifest files changed since the build (# 3 file(s) changed since this build — run astria update before trusting answers), next to the existing # graph built at line. Edits through paths without hooks (Claude Code print-mode sessions — which provably do not run PostToolUse hooks — editors without them, plain typing) previously left agents confidently answering from the past unless they noticed a raw timestamp. The check is stat-only against the file manifest (no re-hashing): milliseconds per query even on large repos, and it clears itself on the next update. Verified live: touch a file → disclosure appears; update → fresh timestamp, silent header.
  • MCP tool descriptions now teach usage — the descriptions agents see when choosing tools: query_graph explains the file:line anchors, the provenance tiers, what "No confident match" means (rephrase toward symbol names — not an error), and that the header discloses staleness; explain documents the -->/<-- real-direction arrows; affected says to run it before changing a shared symbol and how to read RESOLVED vs INFERRED hops. Verified through a live MCP handshake that the served descriptions carry the guidance.

Full ecosystem coverage — MCP for every coding tool, five new platforms, install --all

  • MCP registration everywhere it is supported — joining claude/cursor/gemini/zcode: VS Code (.vscode/mcp.json, native workspace MCP — covers every VS Code-based editor including Copilot inside it), Codex (~/.codex/config.toml, user-global TOML — the installer appends a managed [mcp_servers.astria] table and never touches a hand-written one), Trae, Windsurf, Kiro (.kiro/settings/mcp.json — Kiro's documented workspace-scope config), and OpenCode (.opencode/opencode.json). The Copilot coding agent gets skill + instructions only: it has no committed repo MCP file — repository-level MCP is JSON pasted into the repository Settings on github.com. All JSON flavors are project-scoped, idempotent, and merge-safe like the originals; uninstall removes each, and configs an earlier build wrote at a since-corrected path are migrated away, never duplicated.
  • Verified against the real vendor CLIs and vendor docs, not just schemas: codex mcp list shows astria … enabled (Codex 0.140.0 parsing the appended TOML); gemini mcp list resolves the settings entry; opencode mcp list reports ✓ astria connected — it actually launched the server; claude mcp list reaches the project .mcp.json server (⏸ pending Claude Code's documented one-time project approval). Real-tool testing caught two OpenCode bugs schema-following would have shipped: opencode 1.17+ rejects a plugins key in opencode.json (the pre-existing plugin injector wrote one — plugins now drop into the auto-discovered .opencode/plugins/ — the convention in opencode's current docs, and verified loadable by probing opencode debug config on 1.17.8, which resolves plugins from both the plural and singular directories — with no config key, and installs upgrade away both earlier layouts), and its MCP schema requires servers directly under mcp with {type: "local", command: [...], enabled: true} — not mcp.servers with a stdio shape. It caught one in ours too: VS Code 1.137's own --add-mcp writer uses a bare servers map (no mcpServers key, no type field), so the vscode flavor now matches the vendor's writer exactly, migrating 1.0.8-era entries. User-customized entries are never touched in any flavor. The exact commands every config runs were also proven end-to-end: an MCP stdio handshake against astria mcp (initialize → 10 tools → real query_graph/affected calls).
  • Three install-path corrections from a docs audit of this repo's own agent integration (all caught before release, against vendor documentation): Kiro's workspace MCP config is .kiro/settings/mcp.json per kiro.dev's configuration docs — not a bare root mcp.json, which no Kiro version reads (the dead file a dev build had written is deleted on install/uninstall when it only carries our entry); OpenCode's documented project plugin directory is .opencode/plugins/ (plural) — the singular plugin/ still loads on 1.17.8 but is not the documented convention, so the installer writes the plural directory and migrates both legacy layouts; and the Copilot coding agent reads repository-level MCP only from repository Settings on github.com (confirmed in github/docs: "Configure MCP servers for your repository" — JSON entered in the Settings UI, mcpServers shape) — the .github/copilot-mcp.json a dev build wrote is read by nothing and is cleaned up. The injected ## astria instruction block also caught up with the tool surface: it now names all ten MCP tools (it still said six, omitting god_nodes, list_communities, graph_stats, health), and this repo's tracked AGENTS.md is now itself a managed section (<!-- astria:managed -->) so astria install keeps it in sync instead of treating it as user-owned forever. The repository's own tracked dead copies (root mcp.json, .github/copilot-mcp.json) are dropped in the same change — every working per-tool config stays machine-local behind astria install, with AGENTS.md and .github/copilot-instructions.md (GitHub's documented repo instructions file) the only tracked agent artifacts.
  • Six new platforms: vscode and windsurf (MCP-only — no skill-file mechanism to target), cline (skill → ~/.clinerules/, AGENTS.md), roo (skill → ~/.roo/rules/, AGENTS.md), amp (AGENTS.md — Amp reads it natively), and pi — the Pi coding agent gets an auto-discovered extension (~/.pi/agent/extensions/astria.mjs, every API surface verified against pi 0.87's types) that registers the graph as native pi tools (astria_query, astria_map, astria_explain, astria_path, astria_affected, CLI-backed — pi's own philosophy is registered tools over MCP definitions: a few hundred context tokens vs 10k+), plus automatic graph refresh around tool calls and an /astria guidance command. Freshness is mode-independent by measurement: pi 0.87 print-mode sessions never deliver tool_result events to extensions (an instrumented listener captured zero events — not even for the extension's own tool calls), so every graph tool call itself triggers the throttled refresh, awaited until the update process exists before returning — the session exits the instant a tool returns, and an un-awaited detached child never materializes (both failure shapes measured). Verified end-to-end: the parent exiting immediately after the tool returns does not kill the update — graph_published_at advances. The standard .mcp.json stays registered for pi-mcp-adapter users at zero extra cost — the adapter reads it natively and was observed discovering the astria server. Fully standalone — no adapter required: verified in a pristine pi (--no-extensions -e astria.mjs, every other extension including pi-mcp-adapter disabled) where the extension loads and registers cleanly; pi's own provider serialization consumes plain JSON-schema parameters, which is exactly what the extension registers. All five tools executed through pi's AgentToolResult contract returning real graph data (the MODEL const, RESOLVED-tier blast radii, ranked repo map), and a project without .astria/ gets a build-one-first hint instead of a raw CLI error. The full chain was then verified live with a real pi session (glm-4.7): the model called the native astria_query tool on its own and answered from the graph — jinaai/jina-embeddings-v2-base-code at crates/astria-embed/src/lib.rs:13-15, file:line anchor and all. The platform roster is now sixteen.
  • astria install --all / uninstall --all — one run wires every supported platform; a single-platform install now prints the remaining platforms so multi-tool users discover the rest. Previously the command silently defaulted to claude-only, and a Codex or Trae user who ran astria install got the wrong layout without a hint.
  • Tests: the MCP flavor matrix grew from 4 to 9 parametrized JSON flavors (shape, idempotence, preserve-others, removal) plus dedicated OpenCode-shape/migration, Kiro legacy-path migration, Copilot legacy-file cleanup, Codex TOML round-trip (user-config preservation, never-clobber), and file-stem layout tests; install suite 292 assertions green.

Answer trust and first-rank retrieval — RESOLVED edges, honest directions, Rust docstrings, adaptive semantic ranking

  • RESOLVED edge tier for uniquely-bound calls — a call expression is extracted from source, but its binding (which definition the bare name means) is name inference; the graph previously called the whole edge INFERRED, so affected marked all 12 depth-1 callers of score_nodes as untrusted. Reference resolution now upgrades a call whose name binds to exactly one definition to RESOLVED (strength 0.85): above co-occurrence inference, deliberately below EXTRACTED/DECLARED so --detail high (compiler-grade facts) and health's EXTRACTED-only cycle detection still exclude it. On this repo: 3,013 of 11,828 call edges are RESOLVED; the remaining 8,815 (is_some, join, unbindable names) stay honestly INFERRED. affected shows tiers per hop and saves the legend line for genuinely untrusted hops.
  • explain/neighbors show real edge direction — the explained node was rendered as the source of every connection arrow, inverting caller/callee for incoming edges (the very artifact that made model_cached() look like it called its callers). Connections now render --> (this node calls/imports the neighbor) vs <-- (the neighbor calls/imports this node), on CLI and MCP; --json carries outgoing.
  • **Rust /// doc com...
Read more

v1.0.7

Choose a tag to compare

@github-actions github-actions released this 28 Sep 16:31
b0a9c2e

[1.0.7] — 2026-09-28

Jev judge layer — calibrated second opinion over any backend

  • New --judge jev flag (run/update) layers TypeSafe's Jev — a System One decision model that returns typed judgments with calibrated probabilities, not generated text — on top of the selected --backend (claude, openai-compatible, or gemini). The engine still generates every extraction; the judge re-judges it. --backend jev is not accepted and errors with a pointer to --judge (ASTRIA_LLM_JUDGE=jev selects it via env).
  • Trivial-file gate (on by default, bounded batch sizes) — before a file's first extraction, batched keep/drop judgments (≈1 billed request per 50 files, files >64 KB presumed rich) skip files the judge finds empty or trivial, so they never cost an engine call. Gated files keep their structural extraction; the run summary reports them ("N files gated by Jev").
  • Per-file verification — one request per file re-chooses node types and relations from the schema allowlists (replacing the lossy relates_to/concept clamps) and gets a keep/drop existence verdict per edge. Spurious edges are dropped (ASTRIA_LLM_JEV_MIN_EDGE_PROBABILITY, default 0.40); kept edges carry the judge's keep probability as a calibrated confidence_score in the edges table — semantic edges previously left it null.
  • Suggested-question ranking — on runs that rebuilt the graph, the report's suggested questions are re-ordered by judge keep-scores so the most useful one leads. Best-effort: any judge failure keeps the generated order.
  • Judge calls count toward ASTRIA_LLM_BUDGET like every other response, and the judge configuration (model, thresholds, gate settings, prompt text) fingerprints into the semantic extraction cache — changing it invalidates cached extractions. --judge without --backend errors: the judge wraps an engine, it cannot generate extractions.
  • Configuration: ASTRIA_LLM_JUDGE_API_KEY (or TYPESAFE_API_KEY) and ASTRIA_LLM_JUDGE_MODEL (default jev-latest) are vendor-generic; behavior knobs keep the honest ASTRIA_LLM_JEV_* names (_VERIFY, _MIN_EDGE_PROBABILITY, _GATE, _GATE_MAX_BYTES, _GATE_DROP_THRESHOLD, _GATE_BATCH).

HTML visualization rewritten around drill-down

  • astria export --format html now ships a self-contained canvas viewer (no vis-network, no network access required) that opens as community bubbles — one per community, sized by membership, with edge-weighted links between bubbles. Click a bubble to expand it into member nodes, click a member to focus its 1-hop neighborhood, and search to jump straight to any symbol; "All nodes" expands everything with level-of-detail labels.
  • The exported layout stays fully precomputed (physics-free), and the viewer draws only what is on screen, so large graphs open and zoom instantly even in sandboxed HTML previewers.
  • Viewer source lives in packages/viewer (TypeScript, npm run build); the minified bundle is embedded at crates/astria-napi/src/assets/viewer.js. Community bubbles use themed labels from the communities table when --label-communities produced them.
  • Relation-aware focus — the exported edge payload now carries the edge kind (calls, imports, …): the focus panel lists a selected node's neighbors with their relation, and the highlighted 1-hop edges gain direction arrowheads (direction shown where it matters, not on the hairball).
  • Community search — search matches community names as well as symbols and files; picking a community expands and centers its bubble.
  • Accessibility floor — the canvas exposes a role="img" label with node/community/edge counts plus a visually hidden summary of the controls, so screen readers get a usable description of the export.
  • Quiet, throttled git hooks — astria hook install now writes v4 hooks that invoke update . --quiet --if-stale 10: hook-driven rebuilds print nothing (no progress lines, no token benchmark), and skip entirely when the graph was published less than 10 minutes ago, so a burst of commits rebuilds once instead of per commit. astria update gained matching --quiet / --if-stale <minutes> flags; hooks retry plain update . against any CLI version that predates the flags, and still never break a commit.

Skills and MCP updated for the new features

  • The shipped skills (packages/astria-cli/skills/skill*.md, full + per-assistant variants) now teach agents the new capabilities: the interactive bubble-viewer export (export --format html, --mode standard|large, the tree view, and --neo4j-push/--redis-push), the full update flag set (--no-dedup, --embed, --label-communities, --deep, --quiet, --if-stale), and the git hooks (astria hook install|uninstall|status, hook-guard) with their automatic post-commit refresh. Existing installs refresh by re-running astria install.
  • The MCP server's client instructions now point agents at the hooks (astria hook install) for automatic post-edit freshness, and the skill's MCP tool list is corrected to include health.

Retrieval ranking tightened for prose corpora

  • Chunk labels are a truncated first line of the chunk's own body; scoring no longer amplifies that prefix at label weight for chunk nodes, so a later session whose opening line re-mentions a topic cannot outrank the chunk whose body actually answers the question.
  • The IDF pre-pass now counts document bodies as well as labels, so terms that are common in bodies but rare in first lines ("group", "friends" in transcripts) stop acting as near-max discriminators, and rare proper nouns carry the ranking.
  • Measured on the full LoCoMo set (1,977 questions, structural, no embeddings): recall@1 63.5% → 66.1%, recall@3 79.3% → 80.7%, MRR 0.717 → 0.736, with recall@5/10 at 85.0%. The 35-question code self-check (quality harness) holds recall@5 at 82.9% with MRR 0.636 → 0.659 (a different series from the paired-runner self numbers below — different harness, pinned graphs).

Qualified-name retrieval and the first blind answer-correctness run

  • Question terms now score against each node's scope-qualified id (BaseCommand.get_usage reaches src_click_core_basecommand::get_usage through the id even though every same-name symbol shares one bare label), and id tokens join the IDF pre-pass so ubiquitous scope words ("src", "core") cannot act as rare discriminators.
  • The seed reservation honors qualified names too: an explicitly named qualified symbol reserves its node a traversal seed instead of losing the slot to a label-tie stranger. Click's additional validation went from 0% to 2/2 exact definitions surfaced, additional ripgrep from 25% to 3/4, and the paired-runner self set's MRR from 0.618 to 0.687 at unchanged file recall; LoCoMo is unchanged.
  • Blind answer-correctness judging finally ran (TypeSafe System One judge, scripts/bench/quality/blind-judge.mjs): both tools answered the same 35 rubric-grounded questions, graded without tool identity — astria 100% PASS, Graphify 77.1% PASS / 2.9% PARTIAL / 20% FAIL. First generated-answer-correctness measurement in the project (single judge, single run, 35 self-corpus questions — not a statistical claim). The same pairs re-graded by the independent promptfoo/OpenRouter judge (gpt-4o-mini) agreed on the ordering at 77.1% vs 65.7% pass.
  • The paired runner's budgets are configurable (budgets array). A four-point budget-response curve (250/500/1000/2000) shows astria's 250-token answers outscoring Graphify's 2,000-token answers (MRR 0.680 vs 0.531, recall@5 74% vs 69%) while Graphify exceeds each of the two smallest budgets on 48/50 raw responses and astria stays inside budget on all 200 (structural only, one observation per condition).
  • Two reserved golden tracks exist, authored from pinned source and unused during development: click.doc-intent-v1.jsonl (8 doc-intent cases) and click.reserved-v1.jsonl (12 cases, doc- and code-intent, line-exact definitions). First use must be an evaluation run; afterwards they count as exercised.
  • Held-out evidence grew: scripts/bench/paired/*.heldout-v2.jsonl adds 14 separately authored, line-exact grounded cases (5 Click, 5 Express, 4 ripgrep); current runtime retrieves 5/5, 5/5, 2/4 files and 11/13 v2 definitions in the top five.

Fixed

  • Tree export hardening — the symbol-tree hover inspector builds its panel with DOM textContent instead of innerHTML, and the embedded JSON escapes </script/<!-- breakout sequences: the tree viewer now upholds the bubble viewer's labels-as-text safety property, with matching tests.
  • Docs drift — reference pages corrected against the code: query-log env semantics (ASTRIA_QUERY_LOG is a literal path; ASTRIA_QUERY_LOG_ENABLE selects the default), the --json 20-neighbor cap, --detail high as an EXTRACTED/DECLARED class filter, --label-communities/--deep/update --embed flags, missing env-var rows (ASTRIA_LLM_BUDGET, ASTRIA_LLM_COMMUNITY_MAX, NEO4J_*), the real scip_* relations replacing the never-emitted method/inherits/forks, schema table columns, memory ingestion timing, and same_type_as label-based grouping. The docs-sync guard no longer counts #[cfg(test)] fixtures as relation emitters (a clamp-test relation: "forks" had been satisfying the check for a documented relation that does not exist).
  • Docs drift guard, both directions — the docs-sync check now also fails when ARCHITECTURE.md documents a relation that no production code emits or references (with an explicit (external only) escape), when an ASTRIA_* variable is read but undocumented or documented but never read, when a registered CLI command/flag or MCP tool is missing from its reference page, and when the new generated SQLite schema block is stale. The schema block is generated from db.rs into the architecture page by scripts/generate-schema-docs.mjs (column lists can no longer drift — the first generated block surfaced five previously u...
Read more

v1.0.6

Choose a tag to compare

@github-actions github-actions released this 27 Sep 16:44
443aabc

What's Changed

  • [GPF-1] Add pre-publish CI guard for @napi-rs/cli drift

Goal

CI f... by @nodesify-technology in #56

  • [GPF-2] Define 1.0.0 readiness

Goal

One decision document. No cod... by @nodesify-technology in #57

Full Changelog: v1.0.5...v1.0.6

astria v1.0.5

Choose a tag to compare

@nodesify-technology nodesify-technology released this 27 Sep 10:08
ef9fef1

What's Changed

Full Changelog: v1.0.4...v1.0.5

What's Changed

Full Changelog: v1.0.4...v1.0.5