Four gates that were documented but unenforced, plus the flaky test that made a full-suite run untrustworthy. Rust lint/format: CLAUDE.md has required `cargo fmt` and `cargo clippy` before every commit for as long as the rule existed, yet neither ran anywhere in CI — the requirement rested on memory alone. Both now run in build-and-test.yml and build-release.yml. rustfmt and clippy are already baked into the builder image, so nothing is installed at job time. `cargo fmt --all -- --check` is strict immediately (the tree is clean). Clippy is advisory for now: ~51 pre-existing warnings mean `-D warnings` would fail on unrelated work, so the step carries a TODO to flip the flag once the backlog clears. A compile error still fails it, so it is not a no-op. Traceability threshold: MIN_THRESHOLD sat at 50 while real coverage was 86%, so nearly half the matrix could rot before the gate objected. Ratcheted to 82 with the policy written down — it only ever goes up, and is never lowered to make a red build pass. The same figure lives in MIN_COVERAGE_PERCENT so `traces:coverage` gates locally on the same bar, and a test fails if the two drift. Dangling IDs: a TRACES comment could name any well-formed ID and the extractor accepted it silently, so typos and renames that missed a call site passed unnoticed. `bun run traces:validate` cross-checks every traced ID against the table rows in requirements.md and fails with the referencing files listed. It spans UT/IT as well, which the coverage orphan list ignores by design. This currently reports DR-189 and UT-188, which are being defined separately. Flaky offlineCatalog test: the first dynamic import of the service paid ~1s to transform its dependency graph, charged to a test body against vitest's 5s default. Alone it passed; under suite-wide contention it timed out. The import is now warmed at collection time, so no test is timing the compiler — the timeout is deliberately unchanged. The store shim also drops subscribers from module instances discarded by resetModules, which previously leaked across tests.
214 lines
5.0 KiB
Markdown
214 lines
5.0 KiB
Markdown
# TRACES Quick Reference Guide
|
|
|
|
## What are TRACES?
|
|
|
|
TRACES are requirement identifiers embedded in code comments to track which requirements are implemented where.
|
|
|
|
Format: `// TRACES: UR-001, UR-002 | DR-003`
|
|
|
|
## Quick Examples
|
|
|
|
### TypeScript
|
|
```typescript
|
|
// TRACES: UR-005, UR-026 | DR-029
|
|
export function handlePlayback() { }
|
|
|
|
/**
|
|
* Resume playback from saved position
|
|
* TRACES: UR-019 | DR-022
|
|
*/
|
|
export async function resumePlayback(itemId: string) { }
|
|
```
|
|
|
|
### Svelte
|
|
```svelte
|
|
<!-- TRACES: UR-007, UR-008 | DR-007 -->
|
|
<script>
|
|
export let items = [];
|
|
</script>
|
|
```
|
|
|
|
### Rust
|
|
```rust
|
|
/// TRACES: UR-005 | DR-001
|
|
pub enum PlayerState { ... }
|
|
|
|
#[test]
|
|
fn test_queue_next() {
|
|
// TRACES: UR-005 | DR-005 | UT-003
|
|
}
|
|
```
|
|
|
|
## Requirement Types
|
|
|
|
| Type | Meaning | Example |
|
|
|------|---------|---------|
|
|
| **UR** | User Requirement | UR-005: Control media playback |
|
|
| **IR** | Integration Requirement | IR-003: LibMPV integration |
|
|
| **DR** | Development Requirement | DR-001: Player state machine |
|
|
| **JA** | Jellyfin API Requirement | JA-007: Get playback info |
|
|
| **UT** | Unit Test | UT-001: Player state transitions |
|
|
| **IT** | Integration Test | IT-003: Audio playback via libmpv |
|
|
|
|
## Where to Find Requirements
|
|
|
|
1. **User Requirements (UR):** [README.md](README.md#1-user-requirements)
|
|
2. **Integration Requirements (IR):** [README.md](README.md#21-integration-requirements)
|
|
3. **Development Requirements (DR):** [README.md](README.md#23-development-requirements)
|
|
4. **Jellyfin API (JA):** [README.md](README.md#22-jellyfin-api-requirements)
|
|
|
|
## How to Add TRACES
|
|
|
|
### Step 1: Find the Requirement
|
|
Look up the requirement in README.md or the traceability matrix.
|
|
|
|
Example: `UR-005: Control media playback (pause, play, skip, scrub)`
|
|
|
|
### Step 2: Add Comment
|
|
Add TRACES comment at the top of the function/type/module:
|
|
|
|
```typescript
|
|
// TRACES: UR-005
|
|
export async function playMedia(itemId: string) {
|
|
// Implementation
|
|
}
|
|
```
|
|
|
|
### Step 3: Run Extraction
|
|
Verify the trace is captured:
|
|
|
|
```bash
|
|
bun run traces:json | jq '.requirements | keys | grep "UR-005"'
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Single Requirement
|
|
```typescript
|
|
// TRACES: UR-005
|
|
function handlePlay() { }
|
|
```
|
|
|
|
### Multiple Requirements, Same Type
|
|
```typescript
|
|
// TRACES: UR-005, UR-026, UR-019
|
|
function handlePlaybackState() { }
|
|
```
|
|
|
|
### Multiple Types
|
|
```typescript
|
|
// TRACES: UR-005, UR-026 | DR-029
|
|
function autoplayNextEpisode() { }
|
|
```
|
|
|
|
### Test Coverage
|
|
```typescript
|
|
// TRACES: UR-005 | UT-001
|
|
#[test]
|
|
fn test_player_state_transition() { }
|
|
```
|
|
|
|
### Modules/Files
|
|
```typescript
|
|
/**
|
|
* Player event handling
|
|
* TRACES: UR-005, UR-019, UR-023 | DR-001, DR-028
|
|
*/
|
|
```
|
|
|
|
## Validation
|
|
|
|
### Check Your Changes
|
|
```bash
|
|
# View current coverage
|
|
bun run traces:json | jq '.byType'
|
|
|
|
# Generate full report
|
|
bun run traces:markdown
|
|
|
|
# Check specific requirement
|
|
bun run traces:json | jq '.requirements."UR-005"'
|
|
```
|
|
|
|
### Before Committing
|
|
1. Ensure all new code has TRACES
|
|
2. Format is correct: `// TRACES: ...`
|
|
3. Requirements exist in `docs/requirements.md` — `bun run traces:validate`
|
|
4. No typos in requirement IDs (same command catches them)
|
|
|
|
## CI/CD Validation
|
|
|
|
The workflow automatically checks:
|
|
- ✅ Coverage stays >= 82% (a ratchet — raise it, never lower it)
|
|
- ✅ Every traced ID is defined in `docs/requirements.md`
|
|
- ✅ New files have TRACES
|
|
- ✅ JSON format is valid
|
|
- ✅ Reports are generated
|
|
|
|
See [traceability-ci.md](docs/traceability-ci.md) for details.
|
|
|
|
## Tips & Tricks
|
|
|
|
### Find Related Code
|
|
```bash
|
|
# Find all code tracing to UR-005
|
|
bun run traces:json | jq '.requirements."UR-005"'
|
|
|
|
# List all tests
|
|
bun run traces:json | jq '.requirements | keys | map(select(startswith("UT")))'
|
|
```
|
|
|
|
### Update Your Editor
|
|
|
|
**VS Code:**
|
|
```json
|
|
{
|
|
"editor.wordBasedSuggestions": false,
|
|
"editor.suggest.custom": [
|
|
{
|
|
"name": "TRACES Format",
|
|
"insertText": "// TRACES: $1",
|
|
"insertTextRules": "InsertAsSnippet"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Find Untraced Code
|
|
```bash
|
|
# Files modified without TRACES
|
|
git diff --name-only | xargs grep -L "TRACES:" | head -10
|
|
```
|
|
|
|
## FAQ
|
|
|
|
**Q: Do I need TRACES on every function?**
|
|
A: Only for code that implements requirements. Internal helpers don't need TRACES.
|
|
|
|
**Q: Can I use TRACES on multiple related functions?**
|
|
A: Yes! Add at the file/module level or on individual functions.
|
|
|
|
**Q: What if code doesn't relate to any requirement?**
|
|
A: Leave it untraced. TRACES are for requirement-driven development.
|
|
|
|
**Q: How often should I regenerate reports?**
|
|
A: Automatically on push (CI/CD). Manually after changes: `bun run traces:markdown`
|
|
|
|
**Q: Can I trace to requirements that aren't implemented yet?**
|
|
A: Yes! TRACES show your implementation plan.
|
|
|
|
## See Also
|
|
|
|
- [Full Traceability Matrix](docs/traceability.md)
|
|
- [CI/CD Pipeline Guide](docs/traceability-ci.md)
|
|
- [Requirements Specification](README.md)
|
|
- [Extraction Script](scripts/README.md#extract-tracests)
|
|
|
|
---
|
|
|
|
**Quick Start:**
|
|
1. Add `// TRACES: UR-XXX` to new code
|
|
2. Run `bun run traces:markdown`
|
|
3. Check `docs/traceability.md`
|
|
4. Submit PR - workflow validates automatically!
|