ADR 0008: Workspace-native ruststa command line and rusteda.v1 envelopes¶
- Status: accepted
- Date: 2026-10-17
Context¶
In Phase 1, ruststa operated as a standalone file-oriented command (ruststa sta --lib ... --netlist ... --sdc ..., ruststa check sta, ruststa show) that parsed raw Verilog, Liberty, and SDC files on every invocation and wrote ad-hoc run records (run.json, report.json, events.jsonl) under --runs-root or --run-dir (ADR 0002). That model had three structural limitations at scale:
- Redundant front-end parsing on every command: inspecting a path, pin, or endpoint table required re-reading the full JSON report or re-running analysis, and multi-tool flows with
rustedahad no shared revision history or carry-forward invalidation. - Ad-hoc output schemas: Phase 1 text and JSON outputs differed between
sta,check sta, andshow, and did not provide the uniformrusteda.v1envelope (schema,ok,command,workspace,base_rev,rev,new_rev,scope,completeness,metrics,diagnostics,error,next_actions) or stable object handles (path<N>,inst<N>,net<N>,pin<N>,port<N>,mm<N>,sel<N>). - Unverified incremental and multi-method checking: Phase 1 had no workspace revision mutation for incremental updates (
ruststa update) or dual-method verification (ruststa check --method independent|full|both) committingsta_check.jsonalongsidesta.rbin(ADR 0007).
Decision¶
We replace the Phase 1 file-and-run-record CLI (sta, check sta, show, --runs-root, @ run references) with a workspace-native ruststa command line (crates/apps/ruststa-cli) governed by docs/specs/cli/README.md and docs/specs/sta/cli.md:
- Workspace-only mutations and queries:
- Generic workspace lifecycle commands (
init,import,log,show,diff,revert,export) live inrusteda(crates/apps/rusteda-cli). ruststaprovides three workspace-mutating commands that require--base-rev <revN>(neverHEAD), acquire the workspace lock (rusteda_workspace::Workspace::begin), and append tohistory.jsonl:ruststa run: runs multi-corner timing analysis onnetlist.rbin,.rlib, andconstraints, stagessta.rbin(STA v1,--sta-store full|summary), and populatesmeta.jsonsummary.staandstatus.sta(timing = "met" | "violated").ruststa update: resolves the nearest ancestor revision with a validstatable; returnsincremental.mode = "up_to_date"(new_rev: null) whenbase_revalready carries a validstatable, runs cone-scoped incremental timing when<= 25%of instances changed and constraints/libraries are unchanged, and falls back to a full run otherwise. Supports--verify-fulland--check.ruststa check: verifies a revision'ssta.rbinvia--method independent(ruststa_check::revreadingcache/*.lib, round-tripped Verilog, and canonical SDC without depending on the engine),--method full(fresh full engine recomputation), or--method both, committingsta_check.json(ruststa.sta_check.v1) andstatus.sta_check(verdict = "agree" | "disagree" | "undecided").
ruststaprovides three read-only mapped query commands (--rev <REV|HEAD>, defaultHEAD, never logging tohistory.jsonl) that opensta.rbininO(1)time viaStaStore::open_rev:ruststa path: queries paths by--target path<N>|pin<N>|port<N>or--to <NAME>.ruststa inspect: inspects--target sel<N>|inst<N>|net<N>|pin<N>|port<N>|path<N>or--inst/--net/--pinacross tags.ruststa report: renders tabular sections (summary,paths,endpoints,pins,clocks,checks,unconstrained,notes) with--filter,--sort,--reverse, and--limit.
- Pre-scanned
--format jsonand deterministicrusteda.v1envelopes: - Raw
argvis pre-scanned before Clap parsing so--format jsonwraps usage errors (USAGE,A0003),--help, and--versionin a singlerusteda.v1JSON envelope onstdout. - Every envelope preserves the exact top-level and nested (
scope,completeness,metrics) key order, canonicalizes-0.0to+0.0, rounds percentages to0.1, and emits POSIX-quotednext_actions(quoting leading=tokens forzsh). - Deterministic 1-based handles and underscore typo hints:
- Handles follow
[A-Za-z0-9_-]+:path<N>(1-based rank over setup then hold checks),inst<N>/net<N>/pin<N>/port<N>(1 +canonicalNETLIST v1row),mm<N>(checker mismatch rank), andsel<N>(ui_state.jsonselection tied to its revision). - Malformed underscore handles such as
inst_1fail withUNKNOWN_HANDLE(exit 1,W0007/T0008) and adid you mean 'inst1'?diagnostic hint. - Exit code contract:
0(OK),1(REJECTED:USAGE,INPUT_REJECTED,NOT_A_WORKSPACE,WORKSPACE_EXISTS,UNKNOWN_REVISION,MISSING_TABLE,UNKNOWN_HANDLE,SCHEMA_TOO_NEW,IO_ERROR,BACKEND_UNAVAILABLEwithA0501),2(INTERNAL/CORRUPT_TABLE),3(NEGATIVE_VERDICT:verdict == "disagree"withok: true),4(REVISION_CONFLICT),5(INCONCLUSIVE:verdict == "undecided"withok: true), and130(CANCELLED).
Consequences¶
- Read-only queries (
ruststa path,ruststa inspect,ruststa report) execute directly againstmmap'dsta.rbinsections without parsing Verilog, Liberty, or SDC files, meeting the sub-10 ms cold and sub-1.5 ms warm query latency targets on 1M-cell designs. --threads 1and--threads 32produce byte-for-byte identicalsta.rbintables andstdoutpayloads.- End-to-end phase wall times and RSS (
open,graph,lower,propagate,backward,checks,paths,sta.rbin write,commit) are continuously benchmarked bycrates/apps/ruststa-cli/benches/run_e2e.rs.