Skip to content

S-expression query language + product line engineering (variant management) #128

@avrabe

Description

@avrabe

Summary

Add a unified s-expression query/constraint language and a three-layer product line engineering (PLE) system for variant management. Inspired by pure::variants' architecture and informed by gaps identified in X-as-Code/Sphinx-Needs analysis.

Motivation

Safety-critical products ship in multiple configurations (market × safety level × feature set). Today rivet validates the union of all artifacts. There's no way to ask "is traceability complete for the EU + ADAS + ASIL-D variant specifically?" — a question auditors in automotive (ISO 26262), aerospace (DO-178C), and medical (IEC 62304) domains routinely ask.

External input

Architecture: Three-Layer Separation

Layer 1 — Feature Model (logical, problem space)

# feature-model.yaml
kind: feature-model
root: vehicle-platform
features:
  market: { group: alternative, children: [eu, us, cn] }
  safety-level: { group: alternative, children: [qm, asil-a, asil-b, asil-c, asil-d] }
  feature-set: { group: or, children: [base, adas, autonomous] }
constraints:
  - (implies eu pedestrian-detection)
  - (implies autonomous (and adas asil-d))

Layer 2 — Variant Configurations (specific products)

# variants/eu-adas-c.yaml
kind: variant
name: eu-adas-c
selects: [eu, adas, asil-c]
# Solver derives effective features, validates constraints

Layer 3 — Binding Model (implementation, solution space)

# bindings.yaml
kind: feature-binding
bindings:
  pedestrian-detection:
    artifacts: [REQ-042, REQ-043, SPEC-021]
    source: ["src/perception/pedestrian/**"]

S-Expression Language

One canonical syntax for all expressions — no sugar, no alternatives.

; CLI filtering
(and (= type "requirement") (has-tag "eu") (= status "approved"))

; Feature constraints
(implies autonomous (and adas asil-d))

; Traceability rules
(forall (where type "requirement")
  (exists (linked-by satisfies) (where type "specification")))

; Graph traversal
(reachable-from "REQ-001" satisfies)

Internally compiles to Datalog (guaranteed termination, incremental via salsa).

Key Design Decisions

  • DD-048: S-expressions as single canonical syntax (no infix sugar)
  • DD-049: Datalog semantics with termination guarantee (not Prolog)
  • DD-050: Three-layer PLE architecture (feature model / variant / binding)
  • DD-051: Thin custom Datalog evaluator over salsa (not datafrog/crepe)

Implementation Phases

Phase Features Artifacts
1 — Filter language S-expr parser, predicate evaluator, CLI --filter FEAT-106, FEAT-107, FEAT-108
2 — Datalog engine Compiler, semi-naive evaluator, s-expr traceability rules FEAT-109
3 — PLE core Feature model schema, constraint solver, binding model FEAT-110, FEAT-111, FEAT-112
4 — Variant validation Per-variant validate/coverage, variant-aware impact FEAT-113, FEAT-114

STPA Safety Analysis

7 hazards, 7 system constraints, 5 UCAs, 5 controller constraints, 4 loss scenarios documented in safety/stpa/variant-hazards.yaml.

Key hazards:

  • H-VAR-001: Variant validation passes but traceability gaps exist in deployed config
  • H-VAR-002: Feature model constraints don't capture real-world exclusions
  • H-VAR-003: Binding model drifts from artifacts without detection
  • H-VAR-004: S-expression evaluator bug produces wrong query results

Requirements

REQ-041 through REQ-046 in artifacts/requirements.yaml.

References

  • pure::variants (pure-systems GmbH) — industrial PLE with Prolog constraints
  • FODA — Feature-Oriented Domain Analysis
  • datafrog/Polonius — Datalog in Rust borrow checker
  • Sphinx-Needs needs_variants — simpler tag-based approach (comparison baseline)

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions