Files
Paul HittandClaude Opus 5.5 23d09feedd 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:41:34 -04:00

80 lines
3.2 KiB
Markdown

# BlastRadius
Detects when copies of the same function in different codebases drift apart,
and names which copies disagree. It is used in Hitt Hosting products.
## What it does and why
When the same logic lives in more than one place (two services, a vendored
copy, a CommonJS and a TypeScript version), a fix tends to land in only one of
them. Each copy looks fine on its own. Only a comparison shows that they no
longer agree, and by then the unfixed copy has been running for a while.
BlastRadius takes the source text of each copy and the name of the function to
compare. It extracts the function by brace matching, strips comments and
normalises whitespace, fingerprints the result, and groups the copies by
fingerprint. More than one group means drift. The largest group comes first,
which usually tells you which side has the fix and which side missed it.
Comments and formatting are ignored because copies may be documented
differently but must behave the same. Comparing raw text would fire on a typo
fix and train people to update the pinned value without reading, which brings
back the drift the check exists to catch. The extraction is not a parser, so
it works across CommonJS, ESM and TypeScript without a toolchain per dialect.
**A copy where the function cannot be found is a failure, not a pass.** It may
have been renamed, split or deleted, and a guard that cannot find its subject
is not passing. This holds even when only one copy was located.
Fewer than two located copies, with none missing, is reported as not
assessed: one copy cannot disagree with itself, and calling that "in sync"
would let a deleted sibling read as a clean result. An in-sync pass cites the
copies it compared, because a pass that cannot name what it compared is only
asserted.
The library is pure and has no filesystem access; you read the files. Reports
use the `@extant2000/evidence-record` format, and every copy is cited by its
path when you give one, or by its label.
## Usage
```ts
import { compareImplementations, toReport, formatDrift } from '@extant2000/blast-radius'
const withCheck = 'function canSend(c) {\n if (!c.postalAddress) return false\n return true\n}'
const withoutCheck = 'function canSend(c) {\n return true\n}'
const result = compareImplementations([
{ label: 'web', path: 'web/lib/send.ts', source: withCheck },
{ label: 'worker', path: 'worker/lib/send.ts', source: withCheck },
{ label: 'cli', path: 'cli/lib/send.ts', source: withoutCheck },
], 'canSend')
result.inSync // false
result.groups.map(g => g.labels) // [['web', 'worker'], ['cli']]
result.missing // []
const report = toReport(result) // evidence-record report
console.log(formatDrift(result, { evidence: 'full' }))
```
The report has one critical finding, "canSend has drifted across 2 variants",
citing all three files with the variant each belongs to (2 of 3 and 1 of 3).
`extractFunction()`, `codeOnly()` and `fingerprint()` (FNV-1a) are exported
for use on their own.
## 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/blast-radius
```
## License
MIT. See [LICENSE](LICENSE).