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>
4.2 KiB
SustainScore
A production-readiness score that separates demo-ware from software that is ready to hand over, with the rubric's caps enforced in code.
SustainScore encodes a five-dimension readiness rubric (security, bugs, compliance, consistency, usability) with six bands from Prototype to Mature and a table of hard caps. You supply the scorer's raw judgement per dimension, the defects that are currently open, and the evidence. It returns scores that apply the rubric's anti-inflation rules mechanically.
Why
A rubric kept as prose gets applied charitably. A scorer can write down, in the same row, that an open defect caps Security at 45 and still record 70. Nothing in a document stops that. Encoding the rubric does.
The worked example in examples/cap-by-worst-defect.ts scores a fictional
product whose security review notes an exposed API key that was never
rotated. Run it with npx tsx examples/cap-by-worst-defect.ts:
Hand-scored vs rubric-enforced
security raw 70 -> 45 Beta <- CAPPED by sec.leaked-secret (45)
bugs raw 68 -> 68 Launch-capable, with debt
compliance raw 73 -> 73 Launch-capable, with debt
consistency raw 68 -> 68 Launch-capable, with debt
usability raw 68 -> 68 Launch-capable, with debt
hand-scored overall : ~69
enforced overall : 45 (Beta)
weakest : security
average : 64.4 (reported, never the headline)
delta : -24
A 24-point overstatement and a band change, from one cap a human reader skipped.
What it enforces
| Rule | Enforcement |
|---|---|
| Cap by the worst defect | The lowest open cap on a dimension wins. One serious hole is not averaged away by ten strengths. |
| Evidence required above 70 | A score above 70 with no cited evidence is held at 70 and reported as NOT ASSESSED, not as a pass. Unverified is treated as absent. |
| Overall is the lowest dimension | overall is the minimum. The average is reported alongside it and labelled so it cannot be read as the headline. |
| Suite caps apply before averaging | A shared platform flaw hits every product. Averaging first would let healthy products dilute it. |
An unknown cap id throws. Dropping a mistyped cap without a word would inflate the score, which is the failure this library prevents. A cap assigned to the wrong dimension also throws, and so does a product with a missing dimension.
Caps can cite what establishes them: openCaps takes a bare id or
{ id, evidence }. A cap that cites nothing is still applied, and the report
says it cited nothing. An unproven cap is a smaller error than an unapplied
one.
The full cap table is exported as CAP_RULES, the bands as BANDS.
Usage
import { scoreProduct, scoreSuite, formatProduct } from '@extant2000/sustain-score'
const result = scoreProduct({
product: 'example-app',
tier: 'A',
dimensions: {
security: { raw: 70, openCaps: ['sec.leaked-secret'], evidence: [{ ref: 'docs/security-review.md:14' }] },
bugs: { raw: 68, evidence: [{ ref: 'test/api.test.ts' }] },
compliance: { raw: 73, evidence: [{ ref: 'docs/compliance-checklist.md' }] },
consistency: { raw: 68, evidence: [{ ref: 'shared/ui/' }] },
usability: { raw: 68, evidence: [{ ref: 'reports/accessibility-scan.json' }] },
},
})
result.overall // 45, the lowest dimension
result.weakest // 'security'
result.band.name // 'Beta'
console.log(formatProduct(result))
scoreSuite(products, { suiteCaps }) rolls several products up with tier
weighting (A = 2, B = 1.5, C = 1). productReport() and suiteReport()
return a CapabilityReport from @extant2000/evidence-record, and
formatProduct() and formatSuite() render one. Evidence can be the
evidence-record shape or a plain { ref, note }, where a path:line ref
becomes a file citation.
To rank several scored products by what to fix next, see
@extant2000/portfolio-advisor.
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/sustain-score
License
MIT. Copyright (c) 2026 Extant 2000 LLC. See LICENSE.