Releases: amos-labs/plumbline
Release list
v0.7.2 — producer-side #69: npm-10-safe npx, gate-pin skew warning, version-stamped receipts
- npm ≤ 10 trap documented and routed around:
github:owner/repo@tagis silently mis-parsed (exit 128, no output). All docs now usenpx -y "git+https://github.com/amos-labs/plumbline#v0.7.2". plumb checkwarns on version skew between the local CLI and the repo's pinned gate version, with the exact fix command.plumb receipt --writestamps_stamped_by(CLI version) so producer/gate skew is readable off the receipt.- 325/325 tests. Includes v0.7.1's hermetic diff binding (#74).
Consumers: bump workflow pins amos-labs/plumbline@v0.7.1 → @v0.7.2.
v0.7.1
The diff binding no longer depends on local git config.
Fixed
-
The receipt binding is now hermetic (#69).
diff_sha256was a sha256 over
rawgit diffoutput, and that output is not a pure function of the tree —
it varies with the stamping machine's git configuration. A different
core.abbrev,diff.algorithm,diff.context,diff.noprefix, … produced a
hash the gate could not reproduce, so a PR whose content was byte-identical was
failed withdiff_sha256 mismatchand routed to REWORK. Local pre-flight
passed, CI failed, and it presented as a generic "receipt fumble".Measured on
NuvolaNetworks/cuspr: the stamped hasha973ec40…is exactly what
core.abbrev=7yields for a tree the gate hashed as401688b5…. One config
knob blocked six PRs across two days and cost two REWORK loops to diagnose.
The earlier hypothesis in #69 — that the CLI's diff command changed between the
tag and a dev build — was wrong:src/shape.tsis byte-identical atv0.7.0
andmaster. The variable was always the environment, never the version.The binding diff now neutralises user/system config via env, pins every
output-affecting knob with-c(which outranks repo-local.git/config), and
prints full blob SHAs socore.abbrevcannot matter at all. Both the pinned
2-dot and legacy 3-dot paths are normalised, preserving their equality — and the
verdict cache key that rests on it.
Added
diff_algoin the receipt. Records which normalisationdiff_sha256was
computed under, so the gate verifies with the same algorithm instead of
assuming.plumb receipt --write/stamp/generatestampv1.
Back-compat: a receipt withoutdiff_algois accepted against either the
hermetic or the legacy hash, so hardening the binding does not itself become a
fleet-wide REWORK event. A legacy-only match passes with a warning to re-stamp.plumb diff-hash— prints the authoritative binding for a base (and the
legacy value when local config makes them differ). A baregit diff | sha256
never reproduced the binding; this does.- The diff-mismatch error now names the algorithm and the gate version, and says
outright that a baregit diffwill not reproduce the hash — so a config skew
is diagnosable in one read rather than two REWORK loops.
v0.7.0 — proof-carrying code lifecycle + gate precision
- plumb receipt generate — auto-synthesize an honest, conformant receipt from base+diff+intent (ci_covered validation, self_modifying auto-detected from protected_paths, diff_sha256). Makes MCP-authored code changes proof-carrying by construction.
- lifecycle config (policy.json): review | auto_merge. auto_merge enables GitHub-native auto-merge on a terminal PASS only.
- protected_paths — conservative default (gate/workflows/auth/migrations/billing/proof; NOT broad src/**), user-tweakable per repo; a set value replaces the default. So REVIEW/self_modifying fires on genuinely high-consequence surfaces, not everything.
- follow-up consolidation — min_confidence threshold + ONE checklist issue per PR (updated in place) + auto-close on merge.
318 tests. Enables the non-coder code lifecycle + fixes gate over-firing.
v0.6.2 — REVIEW is terminal-only (phase 1 blocks only on REWORK)
Fixes a phased-gate verdict-routing bug (v0.6.0/v0.6.1): --phase quality treated a semantic review outcome as a blocking failure, which skipped the tests and cascaded into a contradictory second REWORK from --phase verify.
- Phase 1 (quality) now blocks ONLY on REWORK (shape fail / semantic rework). A
revieworpassoutcome → green (exit 0), tests proceed. - REVIEW is emitted ONLY at the terminal phase (
verify/full), after ci-evidence — re-derived from policy + model findings, with the diff_sha256 review cache making it a zero-cost cache hit (no extra LLM call). - No consumer workflow change needed beyond the version pin. 299/299 tests.
v0.6.1 — infra-error state (transient GitHub failures don't become REWORK)
Adds a distinct INDETERMINATE gate outcome (🔌, action_required) for when the gate cannot evaluate due to a transient GitHub failure — separate from REWORK/REVIEW/PASS. Blocks merge (non-zero exit) but reads as 'could not evaluate — infra, not a code verdict; re-run when GitHub recovers,' never a fake REWORK or a green PASS.
- Retry wrapper on the GitHub API calls behind ci-evidence (PR + check-runs fetch): 4 attempts, exp backoff + jitter (~<30s worst case); retries 5xx/429/network errors; never 401/403/404.
- Motivated by the 2026-07-16 GitHub API degradation that wedged three amos-platform PRs at the final approval step.
- 292/292 tests. Includes v0.6.0 phased gate.
Bootstrapped-merged (#61) during the outage it fixes — locally verified 292/292.
v0.6.0 — phased gate (fail-cheap-first)
Phased gate: plumb run --phase quality|verify|full.
- quality (phase 1): shape + semantic only, ci-evidence skipped — the cheap iterate loop (~2 min). REWORK exits non-zero to block the
needs:gate. - verify (phase 2): ci-evidence + terminal verdict, run once on known-solid code.
- full (default): unchanged all-in-one — back-compat for non-staged consumers.
Ships templates/workflow-staged.yml (quality → tests[needs:quality] → gate[needs:tests], with checks/issues perms). Reuses the v0.5.0 REWORK/REVIEW surfaces. 274/274 tests.
Known follow-up (v0.6.1): distinguish transient-infra failure (GitHub 5xx) from REWORK — retry + a distinct 'could not evaluate' state.
v0.5.0
Gate-trust: make the three verdicts unmistakable end-to-end, tighten REWORK vs
REVIEW routing, and stop losing good-but-optional findings. Folds #55 (local
shape parity #53 + unambiguous REWORK vs REVIEW #54) and #57 (verdict
classification #56 + check first-run ergonomics #49 + doc refresh #48).
Added
-
Distinct per-verdict surfaces (#54). A single verdict-presentation table
(src/verdict.ts) is now the sole source of how every surface renders a
verdict, so REWORK and REVIEW can never again collapse into one identical red
"failure" check. The CI gate publishes a per-verdict check-run with a
distinct NAME and CONCLUSION:Plumbline: PASS—successPlumbline: REWORK — blocked, do not merge—failure(agent's turn)Plumbline: REVIEW — awaiting human approval—action_required(human's
turn; renders distinctly from a plain failure in the PR UI)
The PR-comment title and the Checks-tab annotation are derived from the same
table. Motivated by amos-platform#211, where a REWORK was merged by accident
because it looked identical to a REVIEW. -
Materiality axis + 3-way classification (#56). Findings gain a
material / optional / noiseaxis on top ofclass+actor. Routing is now
deterministic and sequential: any material, agent-fixable finding ⇒
REWORK (even on a protected /self_modifyingsurface); REVIEW is
emitted only when no agent-fixable items remain (a pure human decision list);
noise is dropped. -
Optional-but-good findings become tracked follow-up issues (#56).
Optional findings are no longer silently skipped as advisory notes — the gate
files a deduped follow-up GitHub issue for each (deduplicated by a stable
per-finding fingerprint via issue search). Best-effort: filing never throws,
so a repo withoutissues: writedegrades gracefully rather than failing the
gate. Requiresissues: write(andchecks: writefor the per-verdict
check-run) on the gate job. -
plumb checkfinds an untracked receipt (#49). Local pre-flight
auto-discovery now consultsgit status --porcelain, soplumb checkworks
beforegit add. LOCAL only — CI stays diff-based.
Changed
- Doc refresh (#48). README Status updated to the v0.4.x/v0.5 shape; both
AGENTS.md TL;DRs rewritten around the single idempotentreceipt --writestep.
Compatibility
- Back-compatible for consumers. The new check-runs and follow-up-issue
filing requirechecks: write/issues: writeon the gate job; without them
the gate degrades gracefully (no per-verdict check-run / no follow-up issues)
rather than failing. No receipt-schema or gate exit-code change.
v0.4.1
What's Changed
- v0.4.1: accept pinned-OR-rederived diff base (kill the clean-rebase re-stamp tax) by @rickbarkley in #52
Full Changelog: v0...v0.4.1
v0.4.0
Added
base_shareceipt field — the diff base is now PINNED, killing the
recurringdiff_sha256staleness REWORKs. The binding hash is
sha256(git diff <base>...HEAD), a 3-dot diff whose base is the merge-base
of the branch andorigin/main. In a high-merge-velocity repo that merge-base
drifts: an agent stamps against a slightly stale localorigin/mainwhile
the gate fetches a fresher one → a different merge-base → a different hash →
a spurious REWORK on a content-clean PR. The fix:plumb receipt --write
(andstamp/new) now recordbase_sha= the exact merge-base commit and
computediff_sha256as the 2-dotgit diff <base_sha>..HEAD(byte-for-byte
identical to the old 3-dot, but deterministic — it names the base commit
instead of re-deriving it). The gate verifies against that pinned commit and
does not re-derive the base from the liveorigin/main, so concurrent
merges / a stale local main / the synthetic GitHub merge-ref checkout can no
longer move the hash.
Security
- Pinned-base ancestry backstop. The gate asserts
base_shais a real
ancestor of the default branch (git merge-base --is-ancestor). A forged or
unrelated-history base — which could otherwise hide changes by diffing against
the wrong commit — is rejected. The receipt still attests the branch's true
diff off a legitimate fork point.
Compatibility
- Fully back-compatible. A receipt without
base_sha(old-format receipts,
consumers still on@v0.3.0) verifies via the originalorigin/main-derived
3-dot path — nothing breaks during rollout.base_shais optional in the
schema. Consumer repos can re-pin to@v0.4.0at their own pace.
v0.3.0
⚠️ BREAKING
-
The gate now fails CLOSED when the semantic review is required but can't run
(trust-integrity). Previously, if the review provider was absent or
unreachable (no API key, provider/API error, timeout) the gate could fall back
to the deterministic shape checks alone and still PASS. A proof-carrying trust
gate that fails open is a bug in the thesis. Now, when the semantic review is
required and cannot run, the verdict is a BLOCK (review) with a loud
"semantic review unavailable — failing closed" capsule — never a silent
shape-only pass. Governed by the newrequire_semantic_reviewpolicy flag,
which defaults totrue.Why this is BREAKING: any repo that was (perhaps unknowingly) relying on
the old shape-only fallback with no provider key configured will now see
theplumblinecheck go red (BLOCK) instead of passing. Repos that already
provide a provider key (ANTHROPIC_API_KEY/PLUMBLINE_API_KEY) are
unaffected — the review runs exactly as before.Migration. Either (a) add a provider key (recommended — you get the
semantic half of the gate you were missing), or (b) for a deliberately
offline / self-hosted / air-gapped repo, set
"require_semantic_review": falseinpolicy.json— the shape gate may then
PASS, but the verdict and PR comment state loudly that the semantic review
did not run (never a silent pass). This is exactly why consumers should pin a
released tag, not@master: a breaking change like this arrives as a
deliberate, CHANGELOG-noted upgrade rather than shifting under a floating ref.
Added
require_semantic_reviewpolicy flag (defaulttrue) — the fail-closed
switch above. See "How it works" and the cost-controls section in the README.
Enforced at both unavailability points (provider construction with no key, and
a runtime provider-call failure — API error / network / timeout), via a single
sharedresolveUnavailableVerdictdecision so the two paths cannot drift.- README honesty note on what "proof" means. "Proof-carrying" here =
diff-binding (diff_sha256) + CI evidence corroboration + a probabilistic
semantic review, gated on that review actually having run — not a
cryptographic attestation of the agent's work. Receipt signing is planned, not
shipped; the README keeps that distinction explicit.