Skip to content

Commit d53eb1f

Browse files
authored
fix: STPA v0.3.0 audit, OSATE conformance, AADL shapes, VS Code, supply chain (#76)
fix: STPA v0.3.0 audit — 4 critical findings + README
2 parents e95e133 + 695aaf0 commit d53eb1f

71 files changed

Lines changed: 11489 additions & 1050 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ jobs:
142142
name: Mutation Testing
143143
needs: [test]
144144
runs-on: ubuntu-latest
145-
continue-on-error: true
146145
steps:
147146
- uses: actions/checkout@v4
148147
- uses: dtolnay/rust-toolchain@nightly
@@ -152,7 +151,23 @@ jobs:
152151
with:
153152
tool: cargo-mutants
154153
- name: Run cargo-mutants on spar-analysis
155-
run: cargo mutants -p spar-analysis --timeout 120 --jobs 4 --output mutants-out -- --lib
154+
run: cargo mutants -p spar-analysis --timeout 120 --jobs 4 --output mutants-out -- --lib || true
155+
- name: Check surviving mutants
156+
run: |
157+
MISSED=$(grep -c '^MISSED' mutants-out/caught.txt 2>/dev/null || echo 0)
158+
if [ -f mutants-out/missed.txt ]; then
159+
MISSED=$(wc -l < mutants-out/missed.txt | tr -d ' ')
160+
fi
161+
echo "Surviving mutants: $MISSED"
162+
# Ratchet gate: fail if more mutants survive than the threshold.
163+
# Lower this number as tests improve. Target: 0.
164+
MAX_MISSED=142
165+
if [ "$MISSED" -gt "$MAX_MISSED" ]; then
166+
echo "::error::$MISSED mutant(s) survived (threshold: $MAX_MISSED) — add tests to kill them"
167+
cat mutants-out/missed.txt 2>/dev/null | head -30
168+
exit 1
169+
fi
170+
echo "Mutant survivors ($MISSED) within threshold ($MAX_MISSED). Target: 0."
156171
- name: Upload mutants report
157172
if: always()
158173
uses: actions/upload-artifact@v4

.github/workflows/release.yml

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,24 +203,59 @@ jobs:
203203
name: test-evidence
204204
path: spar-*-test-evidence.tar.gz
205205

206-
# ── VS Code Extension ────────────────────────────────────────────────
206+
# ── VS Code Extension (per-platform) ─────────────────────────────────
207207
build-vsix:
208-
name: Build VS Code Extension
208+
name: Build VS Code Extension (${{ matrix.target }})
209+
needs: [build-binaries]
209210
runs-on: ubuntu-latest
211+
strategy:
212+
matrix:
213+
include:
214+
- target: darwin-arm64
215+
rust-target: aarch64-apple-darwin
216+
binary: spar
217+
- target: darwin-x64
218+
rust-target: x86_64-apple-darwin
219+
binary: spar
220+
- target: linux-x64
221+
rust-target: x86_64-unknown-linux-gnu
222+
binary: spar
223+
- target: linux-arm64
224+
rust-target: aarch64-unknown-linux-gnu
225+
binary: spar
226+
- target: win32-x64
227+
rust-target: x86_64-pc-windows-msvc
228+
binary: spar.exe
210229
steps:
211230
- uses: actions/checkout@v4
212231
- uses: actions/setup-node@v4
213232
with:
214233
node-version: 20
234+
- name: Download binary for ${{ matrix.rust-target }}
235+
uses: actions/download-artifact@v4
236+
with:
237+
name: binary-${{ matrix.rust-target }}
238+
path: binary-artifact
239+
- name: Extract and place binary
240+
run: |
241+
mkdir -p vscode-spar/bin
242+
cd binary-artifact
243+
if ls *.tar.gz 1>/dev/null 2>&1; then
244+
tar -xzf *.tar.gz
245+
elif ls *.zip 1>/dev/null 2>&1; then
246+
unzip *.zip
247+
fi
248+
cp ${{ matrix.binary }} ../vscode-spar/bin/${{ matrix.binary }}
249+
chmod +x ../vscode-spar/bin/${{ matrix.binary }} 2>/dev/null || true
215250
- name: Install and compile extension
216251
working-directory: vscode-spar
217252
run: npm install && npm run compile
218-
- name: Package VSIX
253+
- name: Package platform VSIX
219254
working-directory: vscode-spar
220-
run: npx @vscode/vsce package --no-dependencies
255+
run: npx @vscode/vsce package --target ${{ matrix.target }} --no-dependencies
221256
- uses: actions/upload-artifact@v4
222257
with:
223-
name: vsix
258+
name: vsix-${{ matrix.target }}
224259
path: vscode-spar/*.vsix
225260

226261
# ── Publish to VS Code Marketplace ──────────────────────────────────
@@ -231,8 +266,9 @@ jobs:
231266
steps:
232267
- uses: actions/download-artifact@v4
233268
with:
234-
name: vsix
269+
pattern: vsix-*
235270
path: vsix
271+
merge-multiple: true
236272
- uses: actions/setup-node@v4
237273
with:
238274
node-version: 20

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,5 @@ serde_json = "1"
4141
toml = "0.8"
4242
smol_str = "0.3"
4343
petgraph = "0.7"
44-
etch = { git = "https://github.com/pulseengine/rivet.git", rev = "d80b36b", package = "etch" }
44+
etch = { git = "https://github.com/pulseengine/rivet.git", rev = "4c067093ac34fc9e32227bc5bc853d47e9220540", package = "etch" }
4545
proptest = "1"

README.md

Lines changed: 78 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Spar
44

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

77
&nbsp;
88

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

14+
[![CI](https://github.com/pulseengine/spar/actions/workflows/ci.yml/badge.svg)](https://github.com/pulseengine/spar/actions/workflows/ci.yml)
15+
[![codecov](https://codecov.io/gh/pulseengine/spar/graph/badge.svg)](https://codecov.io/gh/pulseengine/spar)
16+
1417
&nbsp;
1518

1619
<h6>
@@ -31,92 +34,113 @@
3134

3235
&nbsp;
3336

34-
Meld fuses. Loom weaves. Synth transpiles. Kiln fires. Sigil seals. **Spar structures.**
35-
36-
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.
37+
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.
3738

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

40-
## Quick Start
41+
## Installation
4142

4243
```bash
43-
# Clone and build
44-
git clone https://github.com/pulseengine/spar
45-
cd spar
46-
cargo build
47-
48-
# Parse an AADL model
49-
./target/debug/spar parse vehicle.aadl
44+
# From source
45+
cargo install --git https://github.com/pulseengine/spar
5046

51-
# Validate a model
52-
./target/debug/spar check vehicle.aadl
47+
# Or download a pre-built binary from releases
48+
# https://github.com/pulseengine/spar/releases
5349
```
5450

55-
## Architecture
51+
## Quick Start
5652

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

61-
### Planned
57+
# List all declared items
58+
spar items vehicle.aadl
6259

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

69-
## Usage
63+
# Run all analysis passes
64+
spar analyze --root Pkg::System.Impl vehicle.aadl platform.aadl
7065

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

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

79-
## Building
72+
# Run verification assertions
73+
spar verify --root Pkg::System.Impl --rules rules.toml vehicle.aadl
74+
```
8075

81-
```bash
82-
# Build all crates
83-
cargo build --workspace
76+
## CLI Commands
77+
78+
| Command | Description |
79+
|------------|--------------------------------------------------------------|
80+
| `parse` | Parse AADL files and show syntax tree or errors |
81+
| `items` | List declared packages, types, implementations |
82+
| `instance` | Build the system instance hierarchy |
83+
| `analyze` | Run all analysis passes (SARIF/JSON/text output) |
84+
| `allocate` | Solve thread-to-processor deployment bindings |
85+
| `diff` | Compare two model versions for structural/diagnostic changes |
86+
| `modes` | List operational modes and mode transitions |
87+
| `render` | Generate SVG/HTML architecture diagrams |
88+
| `verify` | Evaluate verification assertions against the model |
89+
| `lsp` | Start the Language Server Protocol server |
8490

85-
# Run tests
86-
cargo test --workspace
87-
```
91+
## Architecture
8892

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

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

93-
### Working
110+
## Key Features
94111

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

100-
### In Progress
121+
## Documentation
101122

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

106-
## AADL
128+
## Safety
107129

108-
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.
130+
Full STPA (System-Theoretic Process Analysis) safety analysis:
109131

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

112136
## License
113137

114-
MIT License see [LICENSE](LICENSE).
138+
MIT License -- see [LICENSE](LICENSE).
115139

116140
---
117141

118142
<div align="center">
119143

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

122146
</div>

artifacts/architecture.yaml

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,17 @@ artifacts:
321321
for in-process diagram rendering. WASI filesystem calls are
322322
shimmed to read workspace files. Webview panel shows interactive
323323
HTML from etch with ports, orthogonal routing, and pan/zoom.
324+
fields:
325+
rationale: >
326+
Bundling the native binary per platform ensures zero-config
327+
installation. WASM renderer provides in-process rendering
328+
without spawning a child process.
324329
tags: [architecture, tooling, vscode]
330+
links:
331+
- type: satisfies
332+
target: REQ-LSP-001
333+
- type: satisfies
334+
target: RENDER-REQ-003
325335

326336
# ── v0.3.0 Architecture Decisions ──────────────────────────────────────
327337

@@ -399,7 +409,7 @@ artifacts:
399409
interfaces:
400410
provides: [spar mcp command, MCP tools, MCP resources]
401411
requires: [spar-hir Database, spar-analysis AnalysisRunner]
402-
tags: [architecture, mcp, v030]
412+
tags: [architecture, mcp, v040]
403413
links:
404414
- type: satisfies
405415
target: REQ-MCP-001
@@ -447,7 +457,7 @@ artifacts:
447457
interfaces:
448458
provides: [QueryExpression, QueryResult, spar query command]
449459
requires: [spar-hir instance model]
450-
tags: [architecture, query, v030]
460+
tags: [architecture, query, v040]
451461
links:
452462
- type: satisfies
453463
target: REQ-QUERY-001
@@ -471,9 +481,9 @@ artifacts:
471481
interfaces:
472482
provides: [unified knowledge base]
473483
requires: [spar-hir-def SystemInstance, spar-hir facade]
474-
tags: [architecture, knowledge, v030]
484+
tags: [architecture, knowledge, v040]
475485
links:
476-
- type: traces-to
486+
- type: satisfies
477487
target: REQ-QUERY-001
478488
- type: traces-to
479489
target: REQ-MCP-001
@@ -605,3 +615,37 @@ artifacts:
605615
target: REQ-SOLVER-005
606616
- type: satisfies
607617
target: REQ-SOLVER-006
618+
619+
# ── SysML v2 Integration (v0.5.0) ───────────────────────────────────
620+
621+
- id: ARCH-SYSML2-001
622+
type: design-decision
623+
status: planned
624+
title: "SysML v2 rowan-based parser (spar-sysml2 crate)"
625+
description: >
626+
New spar-sysml2 crate implementing a rowan-based parser for SysML v2
627+
textual notation (KerML grammar). Same architecture as spar-parser:
628+
hand-written recursive descent, lossless CST, error recovery. No Rust
629+
SysML v2 parser exists — the pilot implementation is Java-only.
630+
SysML v2 spec: github.com/Systems-Modeling/SysML-v2-Release.
631+
Three-layer pipeline: SysML v2 (system-level) → AADL (deployment-level)
632+
→ WIT/code (implementation-level). Lowering implements the SEI mapping
633+
rules from sei.cmu.edu/annual-reviews/2023-year-in-review/extending-
634+
sysml-v2-with-aadl-concepts. SysML v2 requirement elements flow
635+
directly into rivet artifacts.
636+
fields:
637+
rationale: >
638+
KerML is just another grammar — parseable with rowan the same way
639+
AADL is parsed. The SysML v2 → AADL lowering maps system models
640+
to execution platform models where timing/scheduling semantics exist.
641+
This is exactly what the SEI is specifying. Requirements extraction
642+
bridges SysML v2 requirements with rivet traceability. Result: one
643+
tool analyzing architecture from system design through deployment
644+
through implementation.
645+
interfaces:
646+
provides: [parse_sysml2, lower_to_aadl, extract_requirements]
647+
requires: [spar-parser pattern, spar-transform, rivet YAML]
648+
tags: [architecture, sysml, v050]
649+
links:
650+
- type: satisfies
651+
target: REQ-INTEROP-001

0 commit comments

Comments
 (0)