Skip to content

Architecture Decisions

<TrackedFiles paths="crates/supersigil-core/src/component_defs.rs, crates/supersigil-verify/src/rules/decision.rs" />

Specifications capture what the system does (criteria), how it is built (designs), and whether it works (evidence). But they often miss why the system is shaped the way it is. When architectural rationale lives in wikis, chat threads, or people’s heads, it disconnects from the specs it explains and drifts silently as the system evolves.

Supersigil solves this with three components — <Decision>, <Rationale>, and <Alternative> — that make the “why” a first-class citizen of the specification graph. Decisions are referenceable, queryable via supersigil context, and checkable by verification rules.

A recorded architectural choice. Referenceable by ID, so other documents can link to it.

<Decision id="unidirectional-refs">
References always point from concrete to abstract.
Designs point at requirements, not the reverse.
<Rationale>
Bidirectional references create a synchronization burden.
Adding a new design doc should never require editing the
requirement it implements.
</Rationale>
<Alternative id="bidirectional" status="rejected">
Maintain forward and reverse refs in both documents.
Rejected because synchronization cost is not proportional
to the benefit.
</Alternative>
<Alternative id="derived-both" status="deferred">
Store forward refs only, compute reverse at query time.
Deferred — this is close to what Supersigil already does
internally, but not yet exposed as an authoring option.
</Alternative>
<References refs="document-graph/req" />
</Decision>

The justification for a decision. Must be a direct child of <Decision>. At most one per decision — if the rationale has multiple facets, they belong in a single cohesive argument.

No attributes. The body text is the content.

A considered option that was not chosen. Must be a direct child of <Decision>. Zero or more per decision. Referenceable by ID, so other decisions can cross-link to rejected alternatives.

AttributeRequiredDescription
idyesUnique identifier within the document
statusyesrejected, deferred, or superseded

Decisions can live in any document type. Two common patterns:

Dedicated ADR documents — for cross-cutting decisions that span multiple features or affect the project’s architecture. Scaffold one with:

Terminal window
supersigil new adr auth

This creates a document with type: adr and a Decision component placeholder.

Inline in design docs — for feature-specific decisions that are best understood alongside the design they explain. A design doc can contain both <Implements> and <Decision> components.

Decisions become most useful when they are connected to the specs they explain. Use nested <References> inside a Decision to link it to specific criteria or documents:

<Decision id="graduated-verification">
Verification rules default to different severities to
allow incremental adoption.
<References refs="verification-engine/req#req-5-1, verification-engine/req#req-5-3" />
<Rationale>
Teams adopt rationale tracking at different speeds. Forcing
full decision coverage from day one creates friction that
discourages adoption.
</Rationale>
</Decision>

When you run supersigil context on a document that is referenced by a Decision, the output includes a Linked decisions section:

# requirements: auth/req
Status: implemented
## Linked decisions (from other documents):
- arch/adr#unidirectional-refs: References always point from concrete to abstract.
## Verification targets:
...

This gives agents and developers the architectural context behind the criteria they are working with.

Decisions can track the source files that embody them using nested <TrackedFiles>:

<Decision id="single-binary">
Supersigil is distributed as a single binary.
<TrackedFiles paths="Cargo.toml, crates/*/Cargo.toml" />
<Rationale>
Single-binary distribution eliminates dependency management
for users and simplifies CI setup.
</Rationale>
</Decision>

When those files change, supersigil affected flags the decision’s document — prompting a review of whether the rationale still holds.

Decisions also benefit from transitive staleness: if a Decision references a document via <References>, and that document’s tracked files change, the Decision’s document is flagged as transitively affected.

Supersigil includes verification rules that nudge teams toward complete, connected decisions. All are configurable — override their severity in supersigil.toml.

incomplete_decision — A <Decision> has no <Rationale> child. A decision without a rationale is just an assertion.

orphan_decision — A <Decision> has no outward connections (no <References>, <TrackedFiles>, or <DependsOn> children) and is not referenced by any other component. An orphan decision is disconnected from the graph. Use the standalone attribute to exempt intentionally unconnected decisions:

<Decision id="rust-toolchain" standalone="Project-level technology choice with no corresponding requirement">
Use Rust for single-binary distribution.
</Decision>

invalid_rationale_placement — A <Rationale> placed outside a <Decision>.

invalid_alternative_placement — An <Alternative> placed outside a <Decision>.

duplicate_rationale — A <Decision> has more than one <Rationale> child.

invalid_alternative_status — An <Alternative> has a status value that is not rejected, deferred, or superseded.

missing_decision_coverage — A design document has no <Decision> referencing it, either from another document or embedded within the design itself. Enable this when your team has adopted decision tracking and wants to ensure every design has recorded rationale:

supersigil.toml
[verify.rules]
missing_decision_coverage = "warning"

The adr type provides a conventional home for Architecture Decision Records. It supports four statuses:

StatusMeaning
draftDecision is being discussed
reviewDecision is proposed and awaiting feedback
acceptedDecision is in effect
supersededDecision has been replaced by a newer one