Files
jellytau/docs/traceability-ci.md
T
dtourolle 4567c63797 docs: raise the documented traceability gate to 88%
The spec review checklist still asked for >= 50%, the figure the gate sat
at before it was found to be unreachable; traceability-ci.md carried 82%
throughout. Both now read 88%, matching the ratchet, and the checklist
points at `bun run traces:coverage` rather than inviting anyone to trust a
number written in a document.

Also refreshes the two stale coverage snapshots in traceability-ci.md
(~86% from July 2026, and targets of 70% and 90% that the current 90%
already passes) and records the 50 -> 82 -> 88 ratchet history.
2026-08-20 19:30:48 +02:00

336 lines
10 KiB
Markdown

# Requirement Traceability CI/CD Pipeline
This document explains the automated requirement traceability validation system for JellyTau.
## Overview
The CI/CD pipeline automatically validates that code changes are properly traced to requirements. This ensures:
- ✅ Requirements are implemented with clear traceability
- ✅ No requirement coverage regressions
- ✅ Code changes are linked to specific requirements
- ✅ Quality metrics are tracked over time
## Gitea Actions Workflows
Traceability validation lives in `.gitea/workflows/traceability-check.yml`:
- ✅ Automatic trace extraction
- ✅ Coverage validation against minimum threshold (88%, ratcheted)
- ✅ Modified file checking
- ✅ Artifact preservation
- ✅ Summary reports
**Runs on:** Every push and pull request to `master`/`main`/`develop`
A second workflow, `traceability.yml`, previously duplicated this one as a
"GitHub-compatible alternative". It was removed: CI here is Gitea Actions, and
its only unique step (PR comments via `actions/github-script`) depended on the
GitHub REST client, which Gitea does not provide. To add PR comments, post to
Gitea's `/api/v1/repos/{owner}/{repo}/issues/{index}/comments` from
`traceability-check.yml` rather than reviving the old file.
## What Gets Validated
### 1. Trace Extraction
```bash
bun run traces:json > traces-report.json
```
Extracts all TRACES comments from:
- TypeScript files (`src/**/*.ts`)
- Svelte components (`src/**/*.svelte`)
- Rust code (`src-tauri/src/**/*.rs`)
- Test files
### 2. Coverage Thresholds
The workflow checks:
- **Minimum overall coverage:** 88% (`MIN_THRESHOLD`)
Denominators are **derived from `docs/requirements.md` at run time** — they are
never hardcoded here or in the workflow. Run `bun run traces:coverage` for the
current per-type breakdown; any number written into this document is a snapshot
that will drift.
> **Why this matters.** The workflow used to divide by frozen literals
> (UR/39, IR/24, DR/48, JA/3, total 114) while `requirements.md` had grown past
> 200. It reported **158%** coverage, so the 50% threshold was unreachable and
> the job could not fail regardless of how far coverage dropped. See
> [specs/traceability-gate-repair.md](specs/traceability-gate-repair.md).
Coverage is the *intersection* of traced and defined IDs: an ID that appears in
a `TRACES:` comment but is not defined in `requirements.md` is reported as
**orphaned** and does not count toward coverage. UT/IT test identifiers are a
separate taxonomy and are excluded entirely.
The workflow **fails** and blocks merge if coverage drops below the threshold —
or if it computes above 100%, which can only mean the gate is miscounting.
#### Ratchet policy
`MIN_THRESHOLD` **only ever goes up.** It is deliberately set a few points below
the coverage actually achieved (88 against a real ~90%), so a genuine regression
trips it. It previously sat at 50 while true coverage was 86%: nearly half the
matrix could have rotted before CI objected. It was ratcheted 50 → 82 when that
was found, and 82 → 88 once coverage had held above 88% for several releases.
When coverage rises durably, raise the threshold to just under the new figure.
**Never lower it to make a red build pass** — add the missing TRACES comments
instead. The same number lives in `MIN_COVERAGE_PERCENT` in
`scripts/extract-traces.ts` (so `bun run traces:coverage` gates locally on the
same bar); `scripts/extract-traces.test.ts` fails if the two drift apart.
### 2b. Dangling requirement IDs
```bash
bun run traces:validate
```
Every ID named by a `TRACES:` comment must be defined as a table row in
`docs/requirements.md`. The extractor used to accept any well-formed ID
silently, so a typo or a rename that missed a call site passed unnoticed —
`DR-189` and `UT-188` were referenced from three source files, defined nowhere,
for months.
This check spans **all six** ID types (UR/IR/DR/JA/UT/IT), unlike the coverage
`orphaned` list above, which considers only the four requirement types so that
UT/IT noise cannot bury a real typo in the ratio's reporting. The workflow step
**fails the build** on any dangling ID and prints each offender with the files
that reference it.
### 3. Modified File Checking
On pull requests, the workflow:
1. Detects all changed TypeScript/Svelte/Rust files
2. Warns if new/modified files lack TRACES comments
3. Suggests the TRACES format for missing comments
## How to Add Traces to New Code
When you add new code or modify existing code, include TRACES comments:
### TypeScript/Svelte Example
```typescript
// TRACES: UR-005, UR-026 | DR-029
export function handlePlayback() {
// Implementation...
}
```
### Rust Example
```rust
/// TRACES: UR-005 | DR-001
pub fn player_state_changed(state: PlayerState) {
// Implementation...
}
```
### Test Example
```rust
// TRACES: UR-005 | DR-001 | UT-026, UT-027
#[cfg(test)]
mod tests {
// Tests...
}
```
## TRACES Format
```
TRACES: [UR-###, ...] | [IR-###, ...] | [DR-###, ...] | [JA-###, ...]
```
- `UR-###` - User Requirements (features users see)
- `IR-###` - Integration Requirements (API/platform integration)
- `DR-###` - Development Requirements (internal architecture)
- `JA-###` - Jellyfin API Requirements (Jellyfin API usage)
**Examples:**
- `// TRACES: UR-005` - Single requirement
- `// TRACES: UR-005, UR-026` - Multiple of same type
- `// TRACES: UR-005 | DR-029` - Multiple types
- `// TRACES: UR-005, UR-026 | DR-001, DR-029 | UT-001` - Complex
## Workflow Behavior
### On Push to Main Branch
1. ✅ Extracts all traces from code
2. ✅ Validates coverage is >= 88%
3. ✅ Generates full traceability report
4. ✅ Saves report as artifact
### On Pull Request
1. ✅ Extracts all traces
2. ✅ Validates coverage >= 88%
3. ✅ Checks modified files for TRACES
4. ✅ Warns if new code lacks TRACES
5. ✅ Suggests proper format
6. ✅ Generates report artifact
### Failure Scenarios
The workflow **fails** (blocks merge) if:
- Coverage drops below 88%
- A `TRACES:` comment names an ID `docs/requirements.md` does not define
- JSON extraction fails
- Invalid trace format
The workflow **warns** (but doesn't block) if:
- New files lack TRACES comments
- Coverage drops (but still above threshold)
## Viewing Reports
### In Gitea Actions UI
1. Go to **Actions** tab
2. Click the **Traceability Validation** workflow run
3. Download **traceability-reports** artifact
4. View:
- `traces-report.json` - Raw trace data
- `docs/traceability.md` - Formatted report
### Locally
```bash
# Extract current traces
bun run traces:json | jq '.byType'
# Generate full report
bun run traces:markdown
cat docs/traceability.md
```
## Coverage Goals
### Current Status
Run `bun run traces:coverage` — it prints the live figure and exits non-zero
below threshold. Numbers are deliberately not pinned here; the previous snapshot
in this section (51%, 56/114) was stale by roughly 100 requirements and was what
made the broken CI arithmetic look plausible for so long.
As of August 2026 overall coverage is ~90%.
### Targets
- **Short term** (Sprint): Maintain ≥88% overall (the current ratchet)
- **Medium term** (Month): Hold above 90% and ratchet the gate to match
- **Long term** (Release): Reach 95% coverage with focus on:
- IR requirements (API clients)
- JA requirements (Jellyfin API endpoints)
- Remaining UR/DR requirements
## Improving Coverage
### For Missing User Requirements (UR)
1. Review [README.md](../README.md) for unimplemented features
2. Add TRACES to code that implements them
3. Focus on high-priority features (High/Medium priority)
### For Missing Integration Requirements (IR)
1. Add TRACES to Jellyfin API client methods
2. Add TRACES to platform-specific backends (Android/Linux)
3. Link to corresponding Jellyfin API endpoints
### For Missing Development Requirements (DR)
1. Add TRACES to UI components in `src/lib/components/`
2. Add TRACES to composables in `src/lib/composables/`
3. Add TRACES to player backend in `src-tauri/src/player/`
### For Jellyfin API Requirements (JA)
1. Add TRACES to Jellyfin API wrapper methods
2. Document which endpoints map to which requirements
3. Link to Jellyfin API documentation
## Example PR Checklist
When submitting a pull request:
- [ ] All new code has TRACES comments linking to requirements
- [ ] TRACES format is correct: `// TRACES: UR-001 | DR-002`
- [ ] Workflow passes (coverage ≥ 88%)
- [ ] No coverage regressions
- [ ] Artifact traceability report was generated
## Troubleshooting
### "Coverage below minimum threshold"
**Problem:** Workflow fails with coverage < 88%
**Solution:**
1. Run `bun run traces:json` locally
2. Check which requirements are traced
3. Add TRACES to untraced code sections
4. Re-run extraction to verify
### "New files without TRACES"
**Problem:** Workflow warns about new files lacking TRACES
**Solution:**
1. Add TRACES comments to all new code
2. Format: `// TRACES: UR-001 | DR-002`
3. Map code to specific requirements from README.md
4. Re-push
### "Invalid JSON format"
**Problem:** Trace extraction produces invalid JSON
**Solution:**
1. Check for malformed TRACES comments
2. Run locally: `bun run traces:json`
3. Look for parsing errors
4. Fix and retry
## Integration with Development
### Before Committing
```bash
# Check your traces
bun run traces:json | jq '.byType'
# Regenerate report
bun run traces:markdown
# Verify traces syntax
grep "TRACES:" src/**/*.ts src/**/*.rs
```
### In Your IDE
Add a file watcher to regenerate traces on save:
```json
{
"fileWatcher.watchPatterns": [
"src/**/*.ts",
"src/**/*.svelte",
"src-tauri/src/**/*.rs"
],
"fileWatcher.command": "bun run traces:markdown"
}
```
### Git Hooks
Add a pre-push hook to validate traces:
```bash
#!/bin/bash
# .git/hooks/pre-push
bun run traces:json > /dev/null
if [ $? -ne 0 ]; then
echo "❌ Invalid TRACES format"
exit 1
fi
```
## References
- [Extract Traces Script](../scripts/README.md#extract-tracests)
- [Requirements Specification](../README.md#requirements-specification)
- [Traceability Matrix](./traceability.md)
- [Gitea Actions Documentation](https://docs.gitea.io/en-us/actions/)
## Support
For issues or questions:
1. Check this document
2. Review example traces in `src/lib/stores/`
3. Check existing TRACES comments for format
4. Review workflow logs in Gitea Actions
---
**Last Updated:** 2026-02-13