Files
DarkRoom/docs/traceability.md
T
dtourolle 0f202fd3f9 Add requirements traceability gate and Gitea pipelines
Ports JellyTau's traceability tooling to Rust, carrying across the bug it
was repaired for. That gate divided a traced count by frozen literal
denominators; the requirements file outgrew them and it reported 158%
coverage, so it could never fail its own threshold.

Two rules, both enforced by the extractor's own tests:

  - denominators parsed from docs/requirements.md at run time
  - coverage is |traced ∩ defined| / |defined|, never a raw traced count

The gate additionally fails hard on a misconfigured run — zero
requirements parsed or zero files scanned — rather than reporting a
plausible 0%, and on any orphan tag naming a requirement that does not
exist.

Adapted for DarkRoom: IDs are FR-CAT-1 / NFR-P13 / FR-DEV-3a shapes
rather than JellyTau's fixed three digits, and decisions (D), spikes (S),
milestone items (M) and test ids remain taggable while being excluded
from the denominator — counting them inflated it by 25.

Also adds dr-sync: the RemoteBackend trait and capability model, so the
Nextcloud connector is one implementation rather than the only shape the
engine understands. No mature Nextcloud crate exists (reqwest_dav is too
thin), so the connector will be hand-rolled over reqwest per D7.

Gitea workflows follow the same style: containerised, commented with the
reasoning, desktop and Android on every push, plus a CI check that no
core/ crate depends on the UI toolkit (ARCH §6.5a).

Coverage today: 13.3% (19/143). 50 tests passing.
2026-08-09 08:01:32 +02:00

4.2 KiB

Requirements traceability matrix

Denominators are parsed from requirements.md at run time, never hardcoded. Coverage is the intersection of tagged and defined IDs over defined IDs, so it cannot exceed 100%.

Summary

Metric Value
Source files scanned 16
TRACES tags found 16
Requirements defined 143
Requirements covered 19
Coverage 13.3% (19/143)

By type

Type Covered Defined
FR 13 90
NFR 4 47
R 2 6

Orphan tags

A tag naming an ID requirements.md does not define — what renumbering produces, and what a typo produces.

None.

Tagged requirements

ID Tagged in
FR-CAT-1 tools/traceability/src/lib.rs:473, tools/traceability/src/lib.rs:505
FR-CAT-1a core/dr-types/src/lib.rs:23
FR-CAT-2 tools/traceability/src/lib.rs:473
FR-DEV-4 core/dr-gpu/src/lib.rs:119
FR-DSP-1 ui/dr-ui/src/lib.rs:167
FR-NC-12 core/dr-sync/src/lib.rs:127, core/dr-sync/src/lib.rs:33
FR-NC-3 core/dr-sync/src/capability.rs:41
FR-NC-4 core/dr-sync/src/capability.rs:6, core/dr-sync/src/lib.rs:127
FR-NC-6c core/dr-types/src/lib.rs:111
FR-PLAT-AND-1 core/dr-types/src/lib.rs:23
FR-RAW-1 core/dr-types/src/lib.rs:70
FR-UI-1 ui/dr-ui/src/lib.rs:188
FR-UI-2 ui/dr-ui/src/lib.rs:188
NFR-OPS-1 tools/traceability/src/lib.rs:266
NFR-P1 tools/traceability/src/lib.rs:473
NFR-R7 core/dr-gpu/src/error.rs:1
NFR-R8 core/dr-gpu/src/error.rs:1
R1 tools/traceability/src/lib.rs:489, tools/traceability/src/lib.rs:493
R4 core/dr-gpu/src/lib.rs:119

Not yet tagged

124 of 143 requirements have no implementation tag. Expected while the codebase is young; each should gain one as it is built.

Show untagged requirements
  • FR-CAT-10
  • FR-CAT-11
  • FR-CAT-12
  • FR-CAT-13
  • FR-CAT-14
  • FR-CAT-3
  • FR-CAT-4
  • FR-CAT-5
  • FR-CAT-6
  • FR-CAT-7
  • FR-CAT-8
  • FR-CAT-9
  • FR-CULL-1
  • FR-CULL-2
  • FR-CULL-3
  • FR-CULL-4
  • FR-CULL-5
  • FR-CULL-6
  • FR-CULL-7
  • FR-DEV-1
  • FR-DEV-2
  • FR-DEV-3
  • FR-DEV-3a
  • FR-DEV-3b
  • FR-DEV-3c
  • FR-DEV-3d
  • FR-DEV-3e
  • FR-DEV-3f
  • FR-DEV-3g
  • FR-DEV-5
  • FR-DEV-6
  • FR-DEV-7
  • FR-DEV-8
  • FR-DSP-2
  • FR-DSP-3
  • FR-DSP-4
  • FR-DSP-5
  • FR-DSP-6
  • FR-DSP-7
  • FR-DSP-8
  • FR-EXP-1
  • FR-EXP-2
  • FR-EXP-3
  • FR-EXP-4
  • FR-EXP-5
  • FR-EXP-6
  • FR-EXP-7
  • FR-EXP-8
  • FR-EXP-9
  • FR-NC-1
  • FR-NC-10
  • FR-NC-11
  • FR-NC-2
  • FR-NC-5
  • FR-NC-6
  • FR-NC-6a
  • FR-NC-6b
  • FR-NC-7
  • FR-NC-8
  • FR-NC-9
  • FR-PLAT-AND-2
  • FR-PLAT-AND-3
  • FR-PLAT-AND-4
  • FR-PLAT-AND-5
  • FR-PLAT-AND-6
  • FR-PLAT-LIN-1
  • FR-PLAT-LIN-2
  • FR-PLAT-LIN-3
  • FR-RAW-2
  • FR-RAW-3
  • FR-RAW-4
  • FR-RAW-5
  • FR-UI-3
  • FR-UI-4
  • FR-UI-5
  • FR-UI-6
  • FR-UI-7
  • NFR-A11Y-1
  • NFR-A11Y-2
  • NFR-A11Y-3
  • NFR-ARCH-1
  • NFR-ARCH-2
  • NFR-ARCH-3
  • NFR-ARCH-4
  • NFR-COMPAT-1
  • NFR-COMPAT-2
  • NFR-OPS-2
  • NFR-OPS-3
  • NFR-OPS-4
  • NFR-P10
  • NFR-P11
  • NFR-P12
  • NFR-P13
  • NFR-P14
  • NFR-P15
  • NFR-P2
  • NFR-P3
  • NFR-P4
  • NFR-P5
  • NFR-P6
  • NFR-P7
  • NFR-P8
  • NFR-P9
  • NFR-PORT-1
  • NFR-PORT-2
  • NFR-PORT-3
  • NFR-R1
  • NFR-R2
  • NFR-R3
  • NFR-R4
  • NFR-R5
  • NFR-R6
  • NFR-RES-1
  • NFR-RES-2
  • NFR-RES-3
  • NFR-RES-4
  • NFR-SEC-1
  • NFR-SEC-2
  • NFR-SEC-3
  • NFR-SEC-4
  • R2
  • R3
  • R5
  • R6