First public release
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# PivotOps
|
||||
|
||||
Decide whether a plan still holds when conditions change, and name the
|
||||
assumption that broke.
|
||||
|
||||
PivotOps is a pure function over a plan and its current readings. It has no
|
||||
clock and does no I/O, and it executes nothing. It tells you whether to
|
||||
proceed, pivot to a fallback, stop, or hold.
|
||||
|
||||
## What it checks and why
|
||||
|
||||
Conditions changing is not the real failure. The failure is a plan that never
|
||||
wrote down what it assumed, so nobody can tell whether a change matters.
|
||||
PivotOps is built against three versions of that.
|
||||
|
||||
1. A plan whose assumptions are implicit cannot be invalidated. Say a rollout
|
||||
assumes a host has disk headroom, a registry is reachable and a
|
||||
maintenance window is open. If none of that is recorded, a full disk only
|
||||
shows up as the failure at the end. A plan with no recorded assumptions
|
||||
returns `hold`, never `proceed`.
|
||||
2. A stale reading is worse than no reading. Replanning against a condition
|
||||
nobody re-measured gives a confident decision from an old fact. An
|
||||
assumption with `observed: null` is NOT ASSESSED and blocks. "We did not
|
||||
look" is not "it is fine".
|
||||
3. Degradation without a floor is optimism. "Reduce concurrency and continue"
|
||||
is a plan. "Continue at reduced capacity" with no point at which capacity
|
||||
becomes unacceptable is a way of never stopping. A broken assumption whose
|
||||
fallback has no `floor` makes the decision `stop`, not `pivot`.
|
||||
|
||||
## Four decisions, not two
|
||||
|
||||
| Decision | When |
|
||||
|---|---|
|
||||
| `proceed` | every assumption was re-checked and holds |
|
||||
| `pivot` | something broke, and each broken assumption has a fallback with a floor |
|
||||
| `stop` | something broke with no fallback, or with a fallback that has no floor |
|
||||
| `hold` | nothing broke, but at least one condition was never re-measured |
|
||||
|
||||
`hold` gives "we do not know" its own outcome, separate from "carry on" and
|
||||
"abandon". Folding it into either one leads to the two mistakes this library
|
||||
exists to prevent: proceeding on unread conditions, or killing a viable
|
||||
rollout because one probe was missing. A broken assumption outranks an unread
|
||||
one, so `stop` wins over `hold`.
|
||||
|
||||
Non-numeric values are never ordered. An `at-least` comparison of `"closing"`
|
||||
against `"open"` reports NOT ASSESSED instead of comparing the strings, which
|
||||
would pass or fail on alphabetical order. `equals` works on any value.
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { replan, formatReplan, type Plan } from '@extant2000/pivot-ops'
|
||||
|
||||
const plan: Plan = {
|
||||
name: 'nightly rollout',
|
||||
assumptions: [
|
||||
{
|
||||
id: 'disk-headroom',
|
||||
description: 'the host has room for the new image',
|
||||
condition: 'disk free bytes',
|
||||
comparison: 'at-least',
|
||||
required: 5e9,
|
||||
observed: 2e9,
|
||||
where: 'df -P /var/lib/docker',
|
||||
fallback: { description: 'reduce concurrency to 1', floor: 'stop below 500 MB free' },
|
||||
},
|
||||
{
|
||||
id: 'window',
|
||||
description: 'the maintenance window is open',
|
||||
condition: 'window state',
|
||||
comparison: 'equals',
|
||||
required: 'open',
|
||||
observed: 'open',
|
||||
where: 'change calendar',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const { decision, reason, broken, unverified } = replan(plan)
|
||||
console.log(decision)
|
||||
console.log(reason)
|
||||
|
||||
// The full report, for a terminal or CI log
|
||||
console.log(formatReplan(plan))
|
||||
```
|
||||
|
||||
`toReport(plan)` returns the same result as a `CapabilityReport` from
|
||||
`@extant2000/evidence-record`, where every finding cites the reading it was
|
||||
based on.
|
||||
|
||||
## Sample output
|
||||
|
||||
Produced by running the example above and printing `decision` and `reason`:
|
||||
|
||||
```
|
||||
pivot
|
||||
1 assumption(s) broken, each with a fallback and a floor: disk-headroom → reduce concurrency to 1.
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install @extant2000/pivot-ops
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT. Copyright (c) 2026 Extant 2000 LLC. See [LICENSE](LICENSE).
|
||||
Reference in New Issue
Block a user