Files
sustain-score/README.md
T
Paul HittandClaude Opus 5.5 9e61829edf 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:43 -04:00

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.