2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:53:41 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00
2026-09-28 14:49:02 -04:00

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

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.

S
Description
Decides whether a plan still holds when its assumptions change.
Readme MIT
49 KiB
Languages
TypeScript 100%