3.8 KiB
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
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
npm install @extant2000/trace-proof
License
MIT. See LICENSE.