Files
Paul HittandClaude Opus 5.5 0781b21f12 Publish to the GitLab package registry on version tags
The README's install line failed: the package was never published, and
nothing told npm where the @extant2000 scope lives. A tag like v1.2.3 now
publishes to this project's registry with CI_JOB_TOKEN, and the README
sets the scope's registry before installing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:42:53 -04:00

103 lines
4.0 KiB
Markdown

# TraceProof
Builds a requirements-to-evidence traceability matrix from rows you load, and
reports the gaps and a quality score that leads back to those rows. It is
used in Hitt Hosting products.
## What it does and why
You load requirements, their links to verifications, risks, parents and
stakeholder needs, and the verification items themselves, from whatever
database you use. TraceProof takes the rows as plain objects and computes:
- coverage: how many requirements are traced to a test, verified, linked to a
risk, linked to a parent and linked to a stakeholder need;
- gaps: orphaned requirements, requirements with no test or no risk, suspect
links, and failed verifications;
- a composite quality score from 0 to 100 with a letter grade.
A few rules keep the numbers from flattering the programme.
**A requirement with no verifications is not verified.** `[].every(...)` is
`true`, so a naive check reports a requirement with no evidence at all as
fully verified. A requirement counts as verified only when it has at least one
verification and every one of them is `Passed` or `Waived`.
A requirement linked to a test both through a junction table and through a
foreign key on the verification item is counted once.
Absent evidence and evidence of failure are different claims. A missing test,
risk or parent is reported as not assessed. A failed verification is a
failure, and it is the only critical gap.
An empty requirement set is not assessed, not 0% with grade F. Zero next to an
F reads as "this programme traced nothing" when the truth is that nothing was
loaded. It is the same error as reporting 100% uptime from zero samples, in
the other direction.
A composite score is easy to assert and hard to check. The report splits it
into its four inputs, each with the count of requirements it was computed
over, so a reader can redo the arithmetic. Every gap cites the row that
produced it, for example `requirements#<id>`, with the table name set by
`requirementTable` and `verificationTable`.
## Scoring
The default weights are traced to a test 30%, verified 30%, linked to a risk
20% and linked to a parent 20%. Grades are A from 90, B from 75, C from 60 and
D from 40. `qualityScore()` accepts other weights and thresholds for a
different accreditation regime. Weights are not normalised: if they do not
sum to 1, the score will not span 0 to 100, which is a caller error worth
seeing. `toReport()` uses the default weights.
## Usage
```ts
import { computeCoverage, detectGaps, qualityScore, formatTrace, type TraceInput } from '@extant2000/trace-proof'
const input: TraceInput = {
requirements: [
{ id: 'r1', req_number: 'SYS-001', title: 'Deorbit within 25 years', parent_id: 'p1' },
{ id: 'r2', req_number: 'SYS-002', title: 'Survive launch loads', parent_id: 'p1' },
],
requirementVerifications: [{ requirement_id: 'r1' }],
requirementRisks: [{ requirement_id: 'r1' }, { requirement_id: 'r2' }],
verificationItems: [{ id: 'v1', requirement_id: 'r1', status: 'Passed', method: 'Test' }],
}
const coverage = computeCoverage(input) // pct_test 50, pct_verified 50, ...
const { gaps } = detectGaps(input) // SYS-002 has no test
const score = qualityScore(coverage) // { score: 70, grade: 'C', ... }
console.log(formatTrace(input, { requirementTable: 'requirements' }))
```
The score lines from that output:
```
· MEDIUM traced to a test: 1 of 2 (50%) [NOT MET]
· MEDIUM verified: 1 of 2 (50%) [NOT MET]
◦ info linked to a parent: 2 of 2 (100%) [MET]
◦ info linked to a risk: 2 of 2 (100%) [MET]
```
The report also lists SYS-002 as not assessed for having no linked test, and
notes the composite score of 70/100, grade C.
Gap ids (`gap-0`, `gap-1`, ...) are positional and only stable within one
call. Do not store them as entity keys.
## Install
The package is published to the GitLab package registry, so point the
`@extant2000` scope there first:
```
npm config set @extant2000:registry https://gitlab.com/api/v4/packages/npm/
npm install @extant2000/trace-proof
```
## License
MIT. See [LICENSE](LICENSE).