# 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#`, 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 ``` npm install @extant2000/trace-proof ``` ## License MIT. See [LICENSE](LICENSE).