Thank you for your interest in contributing to Spanda — an Autonomous Systems Platform with a safety-first programming language at its core.
- Bug reports — use the bug report template
- Feature requests — use the feature request template
- Language proposals — use the language proposal template
- Package proposals — use the package proposal template
- Architecture proposals — use the architecture proposal template for new platform capabilities, crates, services, APIs, or cross-cutting design changes
- Documentation — fix typos, improve guides, add examples
- Examples — add
.sdprograms that demonstrate real use cases - Tests — expand coverage for CLI, safety, verification, communication
- Node.js 18+
- Rust stable
- npm
git clone https://github.com/Davalgi/Spanda.git
cd Spanda
npm install
npm run build:rust# TypeScript / Vitest
npm test
# Rust
cargo test --workspace
# Full PR gate (matches CI Fast workflow)
./scripts/ci-fast.shOptional pre-push hook (fmt + cross-surface check):
./scripts/setup-githooks.shSee docs/ci-architecture.md for tiered CI (Fast / Integration / Nightly).
cargo fmt --all
cargo clippy --workspace -- -D warnings
npm run lintAfter bulk inline documentation edits, run:
python3 scripts/normalize_inline_docs.pyEvery module and function in Rust (crates/), TypeScript (src/, packages/), Python
(scripts/), and Spanda (.sd) must follow the structured docstring standard in
docs/coding-standards.md.
- Rust:
//!block at the top of the file describing module purpose. - TypeScript:
/** ... @module */block at the top of the file.
Place API documentation inside the function body (or /// / JSDoc above the signature when
required for rustdoc). Required sections: Description, Inputs, Outputs, Example.
Before each meaningful logic block (if, match, loops, error paths), add a plain-English //
comment explaining what that block does. Do not use generic placeholders like "Process each item" or
prefix with Logic:.
| Script | Purpose |
|---|---|
scripts/validate_documentation.py |
Audit coverage; CI warnings |
scripts/validate_architecture.py |
Layer classification, zero-waiver baseline, manifest sync (CI Fast lint-rust) |
scripts/sync_architecture_manifest.sh |
Regenerate architecture-manifest.json after YAML edits |
scripts/add_structured_api_docs.py |
Generate structured API doc blocks |
scripts/fix_structured_doc_gaps.py |
Fix empty Inputs and legacy single-line comments |
scripts/repair_doc_param_typos.py |
Repair truncated parameter names in generated docs |
scripts/add_inline_docs.py |
Legacy API doc generator |
scripts/add_logic_block_docs.py |
Generate contextual block comments |
scripts/normalize_inline_docs.py |
Fix spacing and indentation after bulk edits |
After bulk documentation edits, run:
python3 scripts/normalize_inline_docs.py
python3 scripts/validate_documentation.py --reportAlways run cargo fmt --all before committing — inline doc insertion can affect brace indentation.
crates/ Rust workspace — see crates/README.md
spanda-core/ Public facade (re-exports, hardware_verify, shims)
spanda-driver/ compile, check, run pipeline
spanda-cli/ Native spanda binary
spanda-interpreter/ Tree-walking runtime
spanda-parser/ Parser
spanda-package/ Package manager (no spanda-core dep)
… See crates/README.md for full list
src/ TypeScript mirror (tests, CLI wrapper, LSP helpers)
packages/lsp/ Language Server
packages/web/ Web playground
examples/ Sample .sd programs
tests/ Vitest test suite
docs/ Documentation
Rule of thumb: Language semantics changes land in the owning workspace crate (spanda-parser,
spanda-typecheck, spanda-interpreter, …). Update spanda-core shims/re-exports when the public
spanda_core:: API changes. TypeScript mirror (src/) should stay in parity for parsing, types,
and runtime behavior used in tests.
Crate dependency rule: first-party apps (spanda-cli, spanda-node, spanda-wasm, spanda-dap,
spanda-llvm) import workspace crates directly; only external embedders need spanda-core.
- Run
cargo fmt --allbefore committing - Fix all
cargo clippy --workspace -- -D warningswarnings - Add tests in the owning crate (
crates/spanda-*/tests/,crates/spanda-core/tests/) or inline#[test]for new behavior - Keep changes focused — one logical change per commit
- Match existing module organization and naming
- Run
npm run lint(TypeScript--noEmit) - Add Vitest tests in
tests/for mirror changes - Follow existing patterns in
src/parser/,src/runtime/, etc.
- Use physical units (
m/s,rad,ms) - Include safety blocks for motion examples
- AI examples must use
safety.validate()beforeactuator.execute() - Add showcase examples to
examples/showcase/for high-visibility demos - Ensure examples pass
spanda check(andspanda runwhere applicable)
Permanent governance for platform coherence and non-duplication. Every architectural change must pass Architecture Review before merge.
Start here: docs/architecture-governance.md
Architecture Review is mandatory before implementing or merging:
- New platform services or runtime components
- New communication layers or transport abstractions
- New or breaking APIs (REST, gRPC, CLI JSON)
- New SDK surfaces (Rust, Python, TypeScript together)
- New workspace crates under
crates/ - New architecture diagrams or layer changes
- New roadmap items with platform scope
- New Control Center features with platform impact
- Provider, plugin, or official package changes that expand platform contracts
Bug fixes, typos, and internal refactors with no contract change do not require a formal proposal — but the PR template still applies when in doubt.
- Open an architecture proposal before large implementation work.
- Complete the twelve gates in docs/architecture-review-checklist.md.
- Perform duplication search per docs/non-duplication-policy.md.
- Wait for Architecture Review outcome (Recommend or better) before large builds.
- For significant decisions, add an ADR under docs/adr/ using docs/adr/template.md.
Process details: docs/design-review-process.md.
All PRs use .github/PULL_REQUEST_TEMPLATE.md. Architecture-affecting PRs must link the approved issue or ADR and confirm the quality gate:
- Architecture Review completed
- Duplication Analysis completed
- Security Review completed (when applicable)
- Compatibility Review completed
- Entity Integration documented
- Tests planned or added
- Documentation updated
- ADR created (major changes)
New items in ROADMAP.md must include: Problem, Architecture Fit, Entity Integration, Existing Capability Extended, Duplication Analysis, Security Review, Test Plan, Demo Plan, and Release Impact. See architecture-governance.md#roadmap-rule.
Extend before creating · Reuse before duplicating · Prefer providers and packages over core expansion · Prefer Entity integration · Prefer additive API changes · Every feature demonstrable · Every capability testable · Every significant decision documented in an ADR.
Full list: docs/architecture-governance.md#architecture-principles.
- Propose first — open a language proposal for non-trivial syntax or semantics changes
- Implement in Rust — lexer → parser → AST → type checker → runtime (in that order)
- Add tests — Rust integration tests + Vitest mirror tests
- Update docs — see Keeping documentation in sync below
- Add an example — demonstrate the feature in
examples/
For v0.1.0-alpha, we are not adding large new language features. Focus on stability, tests, and documentation unless the proposal is critical.
Rule: Any long, big, or major update must include documentation updates in the same change set. Do not merge feature work with stale README or docs.
- New language syntax, runtime behavior, or CLI commands/flags
- Architecture, crate layout, or CI workflow changes
- New integrations (ROS2, FFI, fleet, triggers, concurrency, etc.)
- Feature status or roadmap shifts
- New showcase or reference examples
Typos, internal refactors with no user-visible effect, and test-only changes usually do not need doc updates.
After major work, review and update every file that applies:
| File | When |
|---|---|
README.md |
Capabilities, CLI, examples, differentiators, roadmap |
CHANGELOG.md |
User-visible additions, fixes, or breaking changes |
docs/feature-status.md |
Stability or capability matrix changes |
docs/getting-started.md |
New commands, workflows, or demo paths |
docs/README.md |
New guides or doc index changes |
docs/platform-architecture.md |
Layer rules, CI governance, dependency policy |
docs/architecture-governance.md |
Architecture Review gate, principles, quality gate |
docs/architecture-waiver-burn-down.md |
Waiver baseline changes (should remain at 0) |
Topic-specific docs (update when the area changed):
- Language:
docs/spanda-language.md(+ dedicated guide if one exists, e.g.docs/triggers.md) - Runtime / compiler:
docs/architecture.md,docs/lean-core.md - Platform layers / dependencies:
docs/platform-architecture.md,docs/dependency-rules.md - Concurrency / fleet / triggers:
docs/concurrency.md,docs/triggers.md - Hardware / verify:
docs/hardware-compatibility.md - Packages:
docs/packages.md,docs/spanda-toml.md - FFI / ROS2:
docs/ffi-and-ecosystem.md - Roadmap / strategy:
docs/roadmap.md,docs/product-strategy.md - Contributor workflow: this file (
CONTRIBUTING.md)
Also add a runnable example and link it from README.md or docs/getting-started.md when it is a
key demo.
The Cursor rule .cursor/rules/documentation-sync.mdc enforces this for agent-assisted sessions.
- Create
examples/your_example.sd(orexamples/showcase/for curated demos) - Verify locally:
spanda check examples/your_example.sd
spanda run examples/your_example.sd # if it has runnable behavior
spanda verify examples/your_example.sd # if it has deploy targets- Add to golden fixtures if it should stay runnable in CI (
tests/golden/manifest.json). Mission trace files (.trace) may live underexamples/ortests/golden/; other runtime traces stay gitignored. - For tutorial-style programs, prefer numbered files under
examples/basics/or topic dirs (integration/,end_to_end/,features/); see examples/features/README.md and examples/basics/README.md. - Reference it in README or
docs/getting-started.mdif it is a key demo
Spanda uses Semantic Versioning. User-facing changes belong in CHANGELOG.md
under ## [Unreleased] in the same PR as the feature or fix.
When to bump: See docs/versioning.md — each stream (workspace, SDKs, desktop) has its own semver; bump only the stream whose area changed.
After CI Integration passes on main, the Auto release workflow bumps the workspace version
and pushes a vX.Y.Z tag when the merged pull request has one of these labels:
| Label | When to use |
|---|---|
release:major |
v1.0 positioning or breaking language/API/SDK changes |
release:minor |
Roadmap release milestone complete (v0.5, …) or substantial additive platform release |
release:patch |
Bug fixes, stable promotions, and small updates within the current release line |
Create the labels in the GitHub repo if they do not exist yet (release:major, release:minor,
release:patch). Apply one release label before merging. The workflow bumps the workspace
stream and pushes a v* tag that triggers cargo-dist Release. When the merged PR also changed
Control Center paths (packages/web, packages/control-center-desktop, Control Center API/CLI),
Auto release bumps the desktop stream too and pushes desktop-v*, which triggers the Tauri
GitHub Release workflow. SDK releases still use --stream sdk locally — see
docs/versioning.md and
docs/control-center-versioning.md.
| Control Center path check (local) | ./scripts/control_center_paths_changed.sh origin/main — exit 0 when the diff touches Control Center |
| Version display | Sidebar vX.Y.Z; spanda control-center --version; GET /v1/version → control_center_ui_version |
Use Actions → Bump version when you need an ad-hoc semver bump without a labeled PR. Choose workspace or desktop stream; pick patch, minor, or major; leave Push release tag enabled to publish.
python3 scripts/bump_version.py minor --dry-run
python3 scripts/bump_version.py patch --stream desktop --dry-run- Fork the repository and create a feature branch
- For platform or architectural changes, complete Architecture review first
- Make focused changes with tests
- Run
./scripts/ci-fast.shlocally (or the individual commands in docs/ci-architecture.md) - Open a PR against
mainusing the PR template - CI Fast must pass (lint-rust, test-rust, test-typescript, test-python-sdk, test-ts-sdk, cross-surface-check, cross-interface)
- Architecture-affecting PRs must pass the quality gate
- After merge to
main, CI Integration runs automatically — keepmaingreen before stacking more work
Cross-surface API changes: follow the checklist in docs/ci-architecture.md#cross-surface-change-protocol.
- Use clear, descriptive summaries
- Explain why in the body when non-obvious
- Split unrelated changes into separate commits
- Do not include agent or tool attribution in commit messages
This project follows the Contributor Covenant. Be respectful and constructive.
Open a GitHub Discussion or issue if you are unsure where to start. We are happy to help newcomers find a good first contribution.