Files
Paul HittandClaude Opus 5.5 3f264f72e9 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:56 -04:00

3.3 KiB

HandOff

Decides whether a capability can be operated by someone other than the person who built it, by looking at what it depends on.

What it does and why

Handover is usually treated as a documentation problem, but documentation is the smaller part of it. Operability is the absence of dependence on a specific person or machine. A thorough runbook does not remove a dependency. It describes one.

HandOff takes the list of things a capability depends on (credentials, runtimes, knowledge, access, data), what each one is bound to, and what the recipient would use instead. It checks them for three failures.

  1. A personal credential doing institutional work. For example, several products deploy with one engineer's personal access token. No runbook transfers that: the recipient cannot obtain it, and it stops working when the account goes away. It is reported as a critical blocker, not a gap in the docs.
  2. A dependency on a machine instead of a role. A script that hard-codes a path on one laptop runs on that laptop. It works perfectly, forever, for one person.
  3. A substitute nobody has exercised. This one survives every review, because it is written down and so looks done. A runbook nobody but its author has followed is a draft, so it is reported as not assessed.

An account binding with no recorded way for the recipient to get their own account fails at high severity. Operating knowledge that exists only in someone's head fails too.

Readiness is the worst dependency, never the average

One personal credential blocks a transfer however good everything else is. Averaging is how that blocker disappears behind nine green rows.

Readiness When
transferable Every dependency is unbound or has a substitute someone else has exercised.
blocked At least one dependency cannot be handed over.
unproven Nothing is blocked, but at least one substitute has never been exercised.
unknown No dependencies were listed. The capability was assumed, not examined.

Usage

import { assess, formatHandOff, type Capability } from '@extant2000/hand-off'

const capability: Capability = {
  name: 'release pipeline',
  recipient: 'the partner ops team',
  dependencies: [{
    name: 'deploy-token', kind: 'credential',
    coupling: 'person', boundTo: 'alice',
    substitute: 'a group deploy token per project',
    substituteVerified: true,
    where: 'config/deploy.env',
  }],
}

const { readiness, reason, blockers, unproven } = assess(capability)
console.log(formatHandOff(capability))   // report in the evidence-record format

substituteVerified means someone other than the author has followed the substitute. Leaving it out counts as false, because an unexercised substitute is a claim. The example above is transferable; drop the substitute and it becomes blocked.

coupling is one of person, machine, account or none. kind is one of credential, runtime, knowledge, access or data. Every finding cites the dependency's where. The library is pure: no clock and no I/O.

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/hand-off

License

MIT. See LICENSE.