Skip to content

FUG-89: requirements-driven development workflow - #61

Open
issuefleet[bot] wants to merge 7 commits into
mainfrom
agent/fug-89-build-requirements-driven-develo
Open

FUG-89: requirements-driven development workflow#61
issuefleet[bot] wants to merge 7 commits into
mainfrom
agent/fug-89-build-requirements-driven-develo

Conversation

@issuefleet

@issuefleet issuefleet Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

FUG-89 — requirements-driven development workflow

Builds the end-to-end requirements-driven-development workflow: a machine-readable
requirements/risk model, inline traceability annotations across modules and tests,
per-testcase jUnit traceability tags for all suites (software-only and HITL),
and a CI action that aggregates every jUnit XML into an HTML report showing
PASS/FAIL validation and verification of the whole UN/PR/RISK listing.

Model content (FUG-88)

requirements/requirements.yaml is the FUG-88 "Draft requirements and risk
assessment for Splanc" baseline translated verbatim:

  • UN-1..8 — user needs.
  • PR-1..25 — direct product requirements, each satisfies FUG-88's traced
    user needs.
  • RISK-1..12 — risks with FUG-88's severities.
  • PR-26..37 — derived PRs (kind: derived) capturing each risk's mitigation
    (FUG-88 states these as prose); each mitigates its risk and the risk's
    mitigated_by names it back. //requirements:requirements_valid_test enforces
    the bidirectional trace.

Requirements describing product areas this repo doesn't implement yet (e.g. some
AI-workflow surfaces) intentionally have no verifying test and surface as
UNVERIFIED in the report — that gap is the point of the report.

Machinery

  • Toolkit (//tools/traceability): @requirements("PR-…") pytest marker →
    per-testcase jUnit <property name="requirement"> tags; a shared runner writes
    jUnit to $XML_OUTPUT_FILE so every py_test carries its tags into CI; a
    JUnitWriter lets the non-pytest HITL e2e harness emit the same tags; a jUnit
    parser + HTML report generator + aggregate CLI produce the matrix.
  • Inline docs: every top-level module's BUILD documents the PRs it
    implements (inverted from the model).
  • Test annotations: all Python suites (HITL, server, reconstruction,
    simulator, led_driver) tag the PRs they verify; the on-hardware HITL e2e
    harness emits per-phase tagged jUnit (flash_boot, improv_provision,
    websocket_checks). C++/Rust/Go/TS suites trace at target granularity via each
    PR's verified_by, with a documented path to per-case tags.
  • Drift guard: //requirements:check_annotations fails on any source/test/
    module reference to an unknown PR id (94 references today, all resolve).
  • CI: a traceability-report job validates the model + annotations, runs the
    suites, aggregates bazel-testlogs/**/test.xml, and uploads
    traceability-report.html.
  • Docs: docs/requirements-driven-development.md.

Verification

  • Passing under Bazel: //tools/traceability:traceability_test,
    //requirements:requirements_valid_test, //pi/hitl/tests:hitl_test,
    //pi/led_driver:led_driver_test, //pi/server:{server,server_integration}_test,
    //pi/reconstruction:{reconstruct,vio,rust_parity}_test,
    //shared/simulator:sim_recon_roundtrip_test; //pi/hitl/harness:e2e builds.
  • bazel-testlogs/**/test.xml confirmed to carry per-testcase
    <property name="requirement"> tags.
  • prek run --all-files and whole-repo bazel build --nobuild //... both pass.
  • A partial local aggregate (Python suites only) parses 10 jUnit files / 226
    cases → 14/37 PRs VERIFIED, 0 FAILED; the full CI run adds the firmware/web/
    solver verified_by targets.

Closes-Linear: FUG-89 (https://linear.app/fughilli/issue/FUG-89/build-requirements-driven-development-workflow)

@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown
FUG-89 Build requirements driven development workflow

Following the analysis in FUG-88, translate all of the identified UNs, PRs, and RISKs into a machine-readable yaml format. Within the software implementation, include inline documentation in each module that references the PRs satisfied by the implementation. If there are mitigations for RISKs, they should each trace to derived PRs that describe the mitigation (those derived PRs in turn reference the RISKs mitigated). Within the test suite, annotate all test cases by the PRs (whether direct PRs or derived PRs) verified. Implement test traceability; all tests (software-only and HITL) output jUnit XML that contains extra tags that contain the traceability information. A final action in the workflow aggregates all jUnit XMLs into an HTML report that shows the entire UN/PR listing with the PASS/FAIL for validation/verification of each given the traceability information and the test results.

Review in Linear

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://fughilli.github.io/splanc/pr-preview/pr-61/

Built to branch gh-pages at 2026-08-10 21:24 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Claude Agent and others added 7 commits August 10, 2026 21:12
Add the machine-readable requirements model (requirements/requirements.yaml
+ JSON schema) capturing UNs, PRs, RISKs and derived-PR risk mitigations
seeded from the repo design docs, plus the traceability toolkit
(//tools/traceability):

- model.py: load + validate the model (structure + bidirectional
  satisfies/mitigates/mitigated_by cross-references).
- pytest_requirements.py: @requirements marker -> per-testcase jUnit
  <property name=requirement> traceability tags.
- pytest_runner.py: shared py_test entry writing jUnit to XML_OUTPUT_FILE.
- junit.py / report.py / cli.py: parse tagged jUnit, join to the model, and
  render the HTML validation/verification/mitigation matrix (aggregate CLI).
- annotations.py + //requirements:check_annotations: fail on any source
  annotation referencing an unknown PR id.

Includes dogfooding unit tests and the //requirements:requirements_valid_test
guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Route each Python py_test through the shared traceability runner (jUnit to
XML_OUTPUT_FILE with the @requirements plugin) and tag each suite with the
PRs it verifies via a module-level pytestmark:

- pi/hitl, pi/server, pi/led_driver, pi/reconstruction, shared/simulator
  pytest_main.py -> traceability.pytest_runner shim; //tools/traceability dep.
- HITL: sync (PR-5,35), improv (PR-9), mapping_trigger (PR-36), fx_bench
  (PR-7), map_upload (PR-13). Server: codebook (PR-1,30), proto_wire
  (PR-12,37), handler (PR-12), session (PR-6), app_integration (PR-2,6,12).
  Reconstruction: reconstruct (PR-2,32), rust_parity (PR-3), vio (PR-2).
  Simulator: roundtrip (PR-4). led_driver: graycode (PR-1,31,33).

Verified under Bazel: bazel-testlogs test.xml now carries per-testcase
requirement tags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a 'Requirements: PR-…' line to every top-level module's BUILD docstring
(firmware, pi/led_driver, web, pi/reconstruction, solver, shared/simulator,
pi/hitl/harness, pi/server, fx_compiler, shared/protocol, tools), inverted
from the model's per-PR 'modules' field. Extend the annotation scanner to
cover BUILD/.bzl files so these module docs are validated against the model
by //requirements:check_annotations too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the traceability-report CI job (final workflow action): validate the
model, fail on any unknown-PR annotation (check_annotations), run the software
suites to populate tagged jUnit, aggregate every bazel-testlogs XML into
traceability-report.html (UN/PR/RISK validation/verification/mitigation
matrix), and upload it as an artifact. Add
docs/requirements-driven-development.md documenting the model, the annotation
conventions, the two traceability mechanisms, and how to extend per-case tags
to the other languages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add traceability.junit_writer (JUnitWriter) so non-pytest runners can emit the
same requirement-tagged jUnit the aggregator consumes, and wire it into
//pi/hitl/harness:e2e: each phase is a testcase tagged with the PRs it verifies
(flash_boot -> PR-9,34; improv_provision -> PR-9; websocket_checks ->
PR-5,35,11,12,34), written to XML_OUTPUT_FILE (or --junit-xml). This closes the
'all tests (software-only and HITL) output jUnit XML with traceability tags'
requirement for the hardware path too. Round-trip test included.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the design-doc-seeded model with FUG-88's baseline verbatim: UN-1..8,
PR-1..25 (direct, with FUG-88's traces), RISK-1..12. Capture each risk's
mitigation (stated as prose in FUG-88) as a derived PR (PR-26..37) that
mitigates the risk, with mitigated_by naming it back.

Re-map every annotation to the new ids: each product suite's pytestmark, the
HITL e2e phase tags, every module BUILD's Requirements line (inverted from the
model), the toolkit's own self-references (-> PR-23 validation infra / PR-25 CI
quality gates), and the docs examples. check_annotations + requirements_valid_test
enforce consistency (94 references, all resolve).

Also harden the aggregate CLI so a missing/empty jUnit path can never crash the
report job (skip empty/nonexistent inputs; parse_file swallows OSError).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebased onto current main (video-streaming HITL suite, UI rebrand, deploy
changes). Annotate the merged-in pi/hitl test_video_bench (TouchDesigner video
-> device-texture effect) with PR-10, PR-17, and tie the new Rust
//tools/touchdesigner/stream_bench:stream_bench_test to PR-10 as coarse
verification. check_annotations resolves all 96 references; the toolkit,
validator, and all annotated suites (incl. the merged hitl suite) pass under
Bazel; prek --all-files clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@issuefleet
issuefleet Bot force-pushed the agent/fug-89-build-requirements-driven-develo branch from cac9795 to 58005eb Compare August 10, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants