Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
39d1164
fix(lsp): add completeness note — LSP shows parse diagnostics only
avrabe Mar 21, 2026
c3c1dfe
fix(cli): warn about hierarchical model limitation in --apply
avrabe Mar 21, 2026
7026129
docs: update README for v0.3.0
avrabe Mar 21, 2026
4310e5d
fix(diff): detect property value changes in structural comparison
avrabe Mar 21, 2026
ae20398
fix: STPA v0.3.0 audit — 4 critical findings fixed
avrabe Mar 21, 2026
bc9c5f7
docs(rivet): competitive analysis + gap requirements for v0.4.0+
avrabe Mar 21, 2026
5ddd17b
docs(rivet): MBSE ecosystem analysis + interoperability requirements
avrabe Mar 21, 2026
a3f37c9
test(analysis): kill 39 mutation survivors — arinc653, scheduling, la…
avrabe Mar 22, 2026
acf76d3
test(analysis): kill 80+ mutation survivors — name verification + bou…
avrabe Mar 22, 2026
fd6a6ab
test(analysis): kill mutation survivors — legality, property_rules, c…
avrabe Mar 22, 2026
8bf123d
test(analysis): fix feature_group_check — replace ignored tests with …
avrabe Mar 22, 2026
163d6cc
test(analysis): kill mutation survivors across 19 analysis passes
avrabe Mar 22, 2026
563eb8c
ci: mutation testing as hard gate — zero surviving mutants required
avrabe Mar 22, 2026
5d6d98a
ci: mutation testing ratchet gate (≤142) + coverage badge in README
avrabe Mar 22, 2026
327b437
test: OSATE conformance results — 3/7 models match, 4 have known diffs
avrabe Mar 22, 2026
15ce217
fix(instance): feature inheritance from types + semantic connection t…
avrabe Mar 22, 2026
988704e
fix(instance): feature inheritance + semantic connections — 7/7 OSATE…
avrabe Mar 22, 2026
636cd93
feat(render): AADL-standard component shapes + refined visual style
avrabe Mar 22, 2026
874a047
feat(render): AADL-standard shapes via etch shape provider (GLSP-style)
avrabe Mar 22, 2026
bb25bfd
feat(vscode): self-contained per-platform VSIX with bundled spar binary
avrabe Mar 22, 2026
6be5518
chore: final pre-release — retag deferred items, STPA audit, artifact…
avrabe Mar 22, 2026
c5195a0
fix(rivet): resolve all validation errors — 0 errors, 73 warnings
avrabe Mar 22, 2026
f857fe9
chore: final pre-release — retag deferred items, STPA audit, artifact…
avrabe Mar 22, 2026
695aaf0
fix: clippy + fmt — too_many_arguments, items after test module, empt…
avrabe Mar 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ jobs:
name: Mutation Testing
needs: [test]
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
Expand All @@ -152,7 +151,23 @@ jobs:
with:
tool: cargo-mutants
- name: Run cargo-mutants on spar-analysis
run: cargo mutants -p spar-analysis --timeout 120 --jobs 4 --output mutants-out -- --lib
run: cargo mutants -p spar-analysis --timeout 120 --jobs 4 --output mutants-out -- --lib || true
- name: Check surviving mutants
run: |
MISSED=$(grep -c '^MISSED' mutants-out/caught.txt 2>/dev/null || echo 0)
if [ -f mutants-out/missed.txt ]; then
MISSED=$(wc -l < mutants-out/missed.txt | tr -d ' ')
fi
echo "Surviving mutants: $MISSED"
# Ratchet gate: fail if more mutants survive than the threshold.
# Lower this number as tests improve. Target: 0.
MAX_MISSED=142
if [ "$MISSED" -gt "$MAX_MISSED" ]; then
echo "::error::$MISSED mutant(s) survived (threshold: $MAX_MISSED) — add tests to kill them"
cat mutants-out/missed.txt 2>/dev/null | head -30
exit 1
fi
echo "Mutant survivors ($MISSED) within threshold ($MAX_MISSED). Target: 0."
- name: Upload mutants report
if: always()
uses: actions/upload-artifact@v4
Expand Down
48 changes: 42 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,24 +203,59 @@ jobs:
name: test-evidence
path: spar-*-test-evidence.tar.gz

# ── VS Code Extension ────────────────────────────────────────────────
# ── VS Code Extension (per-platform) ─────────────────────────────────
build-vsix:
name: Build VS Code Extension
name: Build VS Code Extension (${{ matrix.target }})
needs: [build-binaries]
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: darwin-arm64
rust-target: aarch64-apple-darwin
binary: spar
- target: darwin-x64
rust-target: x86_64-apple-darwin
binary: spar
- target: linux-x64
rust-target: x86_64-unknown-linux-gnu
binary: spar
- target: linux-arm64
rust-target: aarch64-unknown-linux-gnu
binary: spar
- target: win32-x64
rust-target: x86_64-pc-windows-msvc
binary: spar.exe
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Download binary for ${{ matrix.rust-target }}
uses: actions/download-artifact@v4
with:
name: binary-${{ matrix.rust-target }}
path: binary-artifact
- name: Extract and place binary
run: |
mkdir -p vscode-spar/bin
cd binary-artifact
if ls *.tar.gz 1>/dev/null 2>&1; then
tar -xzf *.tar.gz
elif ls *.zip 1>/dev/null 2>&1; then
unzip *.zip
fi
cp ${{ matrix.binary }} ../vscode-spar/bin/${{ matrix.binary }}
chmod +x ../vscode-spar/bin/${{ matrix.binary }} 2>/dev/null || true
- name: Install and compile extension
working-directory: vscode-spar
run: npm install && npm run compile
- name: Package VSIX
- name: Package platform VSIX
working-directory: vscode-spar
run: npx @vscode/vsce package --no-dependencies
run: npx @vscode/vsce package --target ${{ matrix.target }} --no-dependencies
- uses: actions/upload-artifact@v4
with:
name: vsix
name: vsix-${{ matrix.target }}
path: vscode-spar/*.vsix

# ── Publish to VS Code Marketplace ──────────────────────────────────
Expand All @@ -231,8 +266,9 @@ jobs:
steps:
- uses: actions/download-artifact@v4
with:
name: vsix
pattern: vsix-*
path: vsix
merge-multiple: true
- uses: actions/setup-node@v4
with:
node-version: 20
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ serde_json = "1"
toml = "0.8"
smol_str = "0.3"
petgraph = "0.7"
etch = { git = "https://github.com/pulseengine/rivet.git", rev = "d80b36b", package = "etch" }
etch = { git = "https://github.com/pulseengine/rivet.git", rev = "4c067093ac34fc9e32227bc5bc853d47e9220540", package = "etch" }
proptest = "1"
132 changes: 78 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Spar

<sup>Architecture analysis and design language toolchain</sup>
<sup>AADL v2.2/v2.3 toolchain + deployment solver</sup>

&nbsp;

Expand All @@ -11,6 +11,9 @@
![AADL](https://img.shields.io/badge/AADL_v2.2-AS5506D-654FF0?style=flat-square&labelColor=1a1b27)
![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square&labelColor=1a1b27)

[![CI](https://github.com/pulseengine/spar/actions/workflows/ci.yml/badge.svg)](https://github.com/pulseengine/spar/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/pulseengine/spar/graph/badge.svg)](https://codecov.io/gh/pulseengine/spar)

&nbsp;

<h6>
Expand All @@ -31,92 +34,113 @@

&nbsp;

Meld fuses. Loom weaves. Synth transpiles. Kiln fires. Sigil seals. **Spar structures.**

A Rust implementation of a complete AADL (Architecture Analysis and Design Language) toolchain. Parses, validates, analyzes, transforms, and visualizes system architectures per SAE AS5506D. Designed for safety-critical systems modeling — vehicle software, avionics, WASM component architectures, and AI agent workflows.
A Rust implementation of a complete AADL (Architecture Analysis and Design Language) toolchain. Parses, validates, analyzes, transforms, and visualizes system architectures per SAE AS5506D. Includes a deployment solver for automated thread-to-processor allocation. Designed for safety-critical systems modeling -- avionics, vehicle software, WASM component architectures, and AI agent workflows.

Spar replaces the Eclipse/Java-based OSATE2 toolchain with a fast, embeddable, WASM-compilable alternative built on rust-analyzer's proven architecture patterns.

## Quick Start
## Installation

```bash
# Clone and build
git clone https://github.com/pulseengine/spar
cd spar
cargo build

# Parse an AADL model
./target/debug/spar parse vehicle.aadl
# From source
cargo install --git https://github.com/pulseengine/spar

# Validate a model
./target/debug/spar check vehicle.aadl
# Or download a pre-built binary from releases
# https://github.com/pulseengine/spar/releases
```

## Architecture
## Quick Start

- **`crates/spar-parser/`** — Hand-written recursive descent parser with error recovery
- **`crates/spar-syntax/`** — Lossless concrete syntax tree (rowan red-green trees)
- **`crates/spar-cli/`** — Command-line interface
```bash
# Parse an AADL model and show the syntax tree
spar parse vehicle.aadl --tree

### Planned
# List all declared items
spar items vehicle.aadl

- **`spar-hir`** — Semantic model with incremental computation (salsa)
- **`spar-analysis`** — Pluggable analyses (scheduling, latency, resource budgets, EMV2)
- **`spar-transform`** — Format transforms (AADL ↔ WIT, JSON, SVG)
- **`spar-mcp`** — Model Context Protocol server for AI agent integration
- **`spar-wasm`** — WebAssembly component for kiln deployment
# Instantiate a system hierarchy
spar instance --root Pkg::System.Impl vehicle.aadl platform.aadl

## Usage
# Run all analysis passes
spar analyze --root Pkg::System.Impl vehicle.aadl platform.aadl

```bash
# Parse and show syntax tree
spar parse model.aadl --tree
# Allocate threads to processors (deployment solver)
spar allocate --root Pkg::System.Impl vehicle.aadl platform.aadl

# Parse and show only errors
spar parse model.aadl --errors
```
# Render the architecture as SVG
spar render --root Pkg::System.Impl -o arch.svg vehicle.aadl platform.aadl

## Building
# Run verification assertions
spar verify --root Pkg::System.Impl --rules rules.toml vehicle.aadl
```

```bash
# Build all crates
cargo build --workspace
## CLI Commands

| Command | Description |
|------------|--------------------------------------------------------------|
| `parse` | Parse AADL files and show syntax tree or errors |
| `items` | List declared packages, types, implementations |
| `instance` | Build the system instance hierarchy |
| `analyze` | Run all analysis passes (SARIF/JSON/text output) |
| `allocate` | Solve thread-to-processor deployment bindings |
| `diff` | Compare two model versions for structural/diagnostic changes |
| `modes` | List operational modes and mode transitions |
| `render` | Generate SVG/HTML architecture diagrams |
| `verify` | Evaluate verification assertions against the model |
| `lsp` | Start the Language Server Protocol server |

# Run tests
cargo test --workspace
```
## Architecture

## Current Status
12 crates, layered from low-level parsing to high-level analysis:

**Early Development** — AADL v2.2 parsing is the current focus.
```
spar-syntax Lossless CST (rowan red-green trees)
spar-parser Recursive descent parser with error recovery
spar-annex AADL annex sublanguage parsing (EMV2, BLESS, BA)
spar-base-db Salsa database for incremental computation
spar-hir-def HIR definitions -- item tree, instance model, arenas
spar-hir Public semantic facade (name resolution, properties)
spar-analysis 27+ pluggable analysis passes
spar-transform Format transforms (AADL <-> WIT, WAC, Rust crates, wRPC)
spar-solver Deployment solver (thread-to-processor allocation)
spar-render SVG architecture diagrams (compound Sugiyama layout)
spar-cli Command-line interface
spar-wasm WebAssembly component (WASI P2)
```

### Working
## Key Features

- AADL lexer (all token types)
- Recursive descent parser with error recovery
- Lossless syntax tree (every byte preserved)
- CLI with parse command
- **27+ analysis passes** -- scheduling, latency, connectivity, resource budgets, ARINC 653, EMV2 fault trees, bus bandwidth, weight/power, mode reachability, and more
- **Assertion engine** -- declarative verification rules in TOML (`spar verify`)
- **Deployment solver** -- automated thread-to-processor allocation with constraint satisfaction
- **SARIF output** -- analysis results in SARIF format for CI integration
- **VS Code extension** -- live AADL rendering and diagnostics via LSP
- **WASM component** -- compiles to a 1.3 MB wasm32-wasip2 component
- **Incremental** -- salsa-based memoization for fast re-analysis
- **Lossless parsing** -- every byte preserved in the syntax tree

### In Progress
## Documentation

- Complete AADL v2.2 grammar coverage
- Typed AST layer
- Semantic model (name resolution, property evaluation)
- [Integration plan](docs/plans/2026-03-08-spar-rivet-integration.md) -- rivet lifecycle integration
- [WASM-as-architecture design](docs/plans/2026-03-10-wasm-as-architecture-design.md) -- WIT/WAC/wRPC transforms
- [VS Code extension design](docs/plans/2026-03-18-vscode-extension-design.md) -- editor integration
- [Deployment solver plan](docs/plans/2026-03-21-deployment-solver-plan.md) -- allocation algorithm

## AADL
## Safety

AADL (Architecture Analysis and Design Language) is an SAE aerospace standard (AS5506) for modeling real-time, safety-critical embedded systems. It describes software architecture, hardware platforms, and deployment bindings in a single analyzable notation.
Full STPA (System-Theoretic Process Analysis) safety analysis:

Component categories: `system` · `process` · `thread` · `processor` · `memory` · `bus` · `device` · `data` · `subprogram` · and more.
- [STPA analysis](safety/stpa/analysis.yaml) -- losses, hazards, UCAs, loss scenarios
- [Safety requirements](safety/stpa/requirements.yaml) -- 23 STPA-derived requirements
- [Rivet artifacts](artifacts/) -- requirements, architecture decisions, verification records

## License

MIT License see [LICENSE](LICENSE).
MIT License -- see [LICENSE](LICENSE).

---

<div align="center">

<sub>Part of <a href="https://github.com/pulseengine">PulseEngine</a> formally verified WebAssembly toolchain for safety-critical systems</sub>
<sub>Part of <a href="https://github.com/pulseengine">PulseEngine</a> -- formally verified WebAssembly toolchain for safety-critical systems</sub>

</div>
52 changes: 48 additions & 4 deletions artifacts/architecture.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,17 @@ artifacts:
for in-process diagram rendering. WASI filesystem calls are
shimmed to read workspace files. Webview panel shows interactive
HTML from etch with ports, orthogonal routing, and pan/zoom.
fields:
rationale: >
Bundling the native binary per platform ensures zero-config
installation. WASM renderer provides in-process rendering
without spawning a child process.
tags: [architecture, tooling, vscode]
links:
- type: satisfies
target: REQ-LSP-001
- type: satisfies
target: RENDER-REQ-003

# ── v0.3.0 Architecture Decisions ──────────────────────────────────────

Expand Down Expand Up @@ -399,7 +409,7 @@ artifacts:
interfaces:
provides: [spar mcp command, MCP tools, MCP resources]
requires: [spar-hir Database, spar-analysis AnalysisRunner]
tags: [architecture, mcp, v030]
tags: [architecture, mcp, v040]
links:
- type: satisfies
target: REQ-MCP-001
Expand Down Expand Up @@ -447,7 +457,7 @@ artifacts:
interfaces:
provides: [QueryExpression, QueryResult, spar query command]
requires: [spar-hir instance model]
tags: [architecture, query, v030]
tags: [architecture, query, v040]
links:
- type: satisfies
target: REQ-QUERY-001
Expand All @@ -471,9 +481,9 @@ artifacts:
interfaces:
provides: [unified knowledge base]
requires: [spar-hir-def SystemInstance, spar-hir facade]
tags: [architecture, knowledge, v030]
tags: [architecture, knowledge, v040]
links:
- type: traces-to
- type: satisfies
target: REQ-QUERY-001
- type: traces-to
target: REQ-MCP-001
Expand Down Expand Up @@ -605,3 +615,37 @@ artifacts:
target: REQ-SOLVER-005
- type: satisfies
target: REQ-SOLVER-006

# ── SysML v2 Integration (v0.5.0) ───────────────────────────────────

- id: ARCH-SYSML2-001
type: design-decision
status: planned
title: "SysML v2 rowan-based parser (spar-sysml2 crate)"
description: >
New spar-sysml2 crate implementing a rowan-based parser for SysML v2
textual notation (KerML grammar). Same architecture as spar-parser:
hand-written recursive descent, lossless CST, error recovery. No Rust
SysML v2 parser exists — the pilot implementation is Java-only.
SysML v2 spec: github.com/Systems-Modeling/SysML-v2-Release.
Three-layer pipeline: SysML v2 (system-level) → AADL (deployment-level)
→ WIT/code (implementation-level). Lowering implements the SEI mapping
rules from sei.cmu.edu/annual-reviews/2023-year-in-review/extending-
sysml-v2-with-aadl-concepts. SysML v2 requirement elements flow
directly into rivet artifacts.
fields:
rationale: >
KerML is just another grammar — parseable with rowan the same way
AADL is parsed. The SysML v2 → AADL lowering maps system models
to execution platform models where timing/scheduling semantics exist.
This is exactly what the SEI is specifying. Requirements extraction
bridges SysML v2 requirements with rivet traceability. Result: one
tool analyzing architecture from system design through deployment
through implementation.
interfaces:
provides: [parse_sysml2, lower_to_aadl, extract_requirements]
requires: [spar-parser pattern, spar-transform, rivet YAML]
tags: [architecture, sysml, v050]
links:
- type: satisfies
target: REQ-INTEROP-001
Loading
Loading