# Requirements Traceability

abi-spec v0.2.0+ supports REQ-ID traceability to map requirements to test results and generate coverage reports.

## Overview

Requirements traceability enables:
1. **Unique REQ-IDs** for every requirement (format: `REQ-NNN`)
2. **Structured acceptance criteria** in Given/When/Then format
3. **Requirements index** with enhanced metadata
4. **Traceability matrix** mapping REQ-IDs to test results
5. **Coverage reports** identifying untested requirements

## REQ-ID Format

All requirements must have a unique REQ-ID following the pattern:
- `REQ-001`, `REQ-002`, ... `REQ-999`, `REQ-1000`, etc.
- Prefix: `REQ-`
- Suffix: 3+ digit zero-padded number

Example:
```json
{
  "id": "REQ-001",
  "title": "OAuth2 Authentication",
  "text": "The system shall authenticate users via OAuth2",
  "acceptance": [
    "Given valid OAuth2 token, When request is made, Then access is granted"
  ],
  "source_prd_section": "Security.Authentication"
}
```

## Acceptance Criteria Format

Acceptance criteria should follow the Given/When/Then (GWT) pattern:

### Structured Format
```
Given [precondition], When [action], Then [expected outcome]
```

### Examples

**Structured:**
```json
"acceptance": [
  "Given valid OAuth2 token, When request is made, Then access is granted",
  "Given expired token, When request is made, Then 401 is returned"
]
```

**Plain text (auto-converted):**
```json
"acceptance": [
  "Valid OAuth2 token grants access",
  "Expired token returns 401"
]
```

Plain text is automatically converted to:
- **Given**: "system is operational"
- **When**: "requirement is evaluated"
- **Then**: [original text]

## Requirements Index

The `requirements_index` field in the SpecPack manifest provides enhanced metadata:

```json
{
  "requirements_index": [
    {
      "req_id": "REQ-001",
      "title": "OAuth2 Authentication",
      "acceptance_criteria": {
        "given": ["valid OAuth2 token"],
        "when": ["request is made"],
        "then": ["access is granted"]
      },
      "source_prd_section": "Security.Authentication"
    }
  ]
}
```

## Generating Traceability Matrix

### Basic Usage

Generate a traceability matrix from a compiled SpecPack:

```bash
uv run python -m abi_spec traceability path/to/specpack
```

This outputs:
- **JSON matrix** to stdout
- **Summary statistics** to stderr

### With Test Results

Map requirements to test results:

```bash
uv run python -m abi_spec traceability path/to/specpack \
  --test-results test_results.json
```

#### Test Results Format

```json
{
  "test_auth_valid_token": {
    "req_ids": ["REQ-001"],
    "status": "passed"
  },
  "test_auth_expired_token": {
    "req_ids": ["REQ-001"],
    "status": "passed"
  },
  "test_api_logging": {
    "req_ids": ["REQ-002"],
    "status": "failed"
  }
}
```

Status values: `"passed"`, `"failed"`, `"pending"`

### Save to File

```bash
uv run python -m abi_spec traceability path/to/specpack \
  --test-results test_results.json \
  --output traceability_matrix.json
```

## Traceability Matrix Output

```json
{
  "matrix_version": "1.0",
  "requirements": [
    {
      "req_id": "REQ-001",
      "title": "OAuth2 Authentication",
      "tests": [
        {
          "test_id": "test_auth_valid_token",
          "status": "passed"
        },
        {
          "test_id": "test_auth_expired_token",
          "status": "passed"
        }
      ],
      "coverage_status": "covered",
      "verification_status": "passed"
    },
    {
      "req_id": "REQ-002",
      "title": "API Call Logging",
      "tests": [],
      "coverage_status": "uncovered",
      "verification_status": "untested"
    }
  ],
  "summary": {
    "total_requirements": 2,
    "covered_requirements": 1,
    "uncovered_requirements": 1,
    "passed_requirements": 1,
    "failed_requirements": 0,
    "pending_requirements": 0
  }
}
```

## Verification Status

Each requirement has a `verification_status`:

| Status | Meaning |
|--------|---------|
| `passed` | All tests for this requirement passed |
| `failed` | At least one test for this requirement failed |
| `pending` | Tests exist but some are pending/in-progress |
| `untested` | No tests map to this requirement |

## Coverage Status

Each requirement has a `coverage_status`:

| Status | Meaning |
|--------|---------|
| `covered` | At least one test maps to this requirement |
| `uncovered` | No tests map to this requirement |

## Integration with Orchestrator

To wire abi-spec into the orchestrator (T-0210):

1. **Compile SpecPack** from PRD:
   ```python
   from abi_spec.compiler import compile_prd_json_to_specpack

   result = compile_prd_json_to_specpack("prd.json", "specpack_output")
   # result = {"manifest_hash": "...", "prd_hash": "..."}
   ```

2. **Load Requirements Index**:
   ```python
   import json
   from pathlib import Path

   manifest = json.loads(Path("specpack_output/spec_manifest.json").read_text())
   requirements_index = manifest["requirements_index"]
   ```

3. **Generate Traceability Matrix**:
   ```python
   from abi_spec.traceability import generate_traceability_matrix

   test_results = {
       "test_id_1": {"req_ids": ["REQ-001"], "status": "passed"},
       # ... more test results
   }

   matrix = generate_traceability_matrix(requirements_index, test_results)
   ```

4. **Include in Evidence Pack**:
   ```python
   evidence_pack = {
       "generated_at": "2026-03-04T12:00:00Z",
       "spec_manifest_hash": result["manifest_hash"],
       "requirements_verification": matrix,
       # ... other evidence
   }
   ```

## API Reference

### `generate_requirements_index(requirements: list) -> list`

Generate a requirements index with enhanced metadata.

**Args:**
- `requirements`: List of requirement dicts from PRD

**Returns:**
- List of requirement index entries with `req_id`, `title`, `acceptance_criteria`, `source_prd_section`

### `generate_traceability_matrix(requirements_index: list, test_results: dict) -> dict`

Generate a requirements traceability matrix.

**Args:**
- `requirements_index`: List of requirement index entries
- `test_results`: Dict mapping test IDs to `{"req_ids": [...], "status": "..."}`

**Returns:**
- Dict with `matrix_version`, `requirements`, and `summary`

### `validate_req_id(req_id: str) -> bool`

Validate that a REQ-ID follows the correct format.

**Args:**
- `req_id`: The requirement ID to validate

**Returns:**
- `True` if valid

**Raises:**
- `ValueError`: If the REQ-ID format is invalid

### `generate_req_id(index: int) -> str`

Generate a REQ-ID from an index number.

**Args:**
- `index`: Zero-based index of the requirement

**Returns:**
- REQ-ID in format "REQ-NNN"

## Schema Validation

The SpecPack schema enforces:
- ✅ `requirements_index` is required
- ✅ Each requirement has valid REQ-ID pattern `^REQ-[0-9]{3,}$`
- ✅ Acceptance criteria has `given`, `when`, `then` arrays
- ✅ All strings have `minLength: 1`
- ✅ No additional properties allowed

## Examples

See:
- `fixtures/prd.json` - Example PRD with REQ-IDs and GWT acceptance criteria
- `tests/test_traceability.py` - Comprehensive test suite
- `tests/test_acceptance.py` - Acceptance criteria parsing tests
