Releases: fusebase-dev/fusebase-flow
v3.26.0 — context-compression discipline
FuseBase Flow v3.26.0 — FR-26 context-compression discipline (large-output / repeat-output audit, MCP coverage)
Release date: 2026-06-15
Previous version: 3.25.1
Type: MINOR (feature — additive)
Summary
Extends FR-26 (token-efficient execution) from read-side hygiene to large context and large output — the case where loading a big input or tool result whole is itself the waste. Adds a new ## Context compression discipline section to the token-economy skill plus two new candidate classes in /token-waste-audit: large-output (oversized results from any output-producing tool) and repeat-output (the same large body re-sent across turns). Clean-room original, MIT, stdlib-only, no new dependency. No new FR rule and no new skill — this extends the existing FR-26 / token-economy carrier, so the FR range (FR-01..FR-26) and the skill count (31) are unchanged.
The discipline is routing, not a budget: it slices and points to large artifacts and keeps compressed context honest. The Guardrail still governs — quality outranks tokens, and nothing here authorizes skipping a needed read or thinning verification.
What ships
| Piece | What it does |
|---|---|
## Context compression discipline in flow-skills/token-economy/SKILL.md |
Behavioral rules with per-row quality guards: content-route-before-consuming, extract-before-reasoning, preserve-the-retrieval-path (every summary carries a handle back to ground truth), original-before-edit, summary-is-not-authority, stable-context-floor, cross-agent dedupe, reference-an-in-context-body-once, large-output hygiene (anticipate then narrow), generated/vendored restraint, and compression-is-not-verification. |
large-output audit class |
Flags tool results ≥20k chars from any output-producing tool — built-in and MCP (write tools excluded via a generic predicate). Corrects a real coverage gap: the prior allowlist silently missed MCP tools, so oversized MCP results were never surfaced. |
repeat-output audit class |
Flags the same large body re-sent across turns, fingerprinted by a one-way stdlib hash — the body is never emitted into the report. A fresh first inclusion or a deliberately re-run command's new output is not a re-send. |
All findings are reported as candidates that MAY indicate an FR-26 rule (the report header lists the known false-positive classes) — never verdicts.
Clean-room
Clean-room original FuseBase Flow content: FuseBase-native behavioral rules + deterministic, stdlib-only audit heuristics. No third-party code, prompts, skill/command/hook text, docs, benchmark language, or dependency is copied or vendored. No third-party tool is named in any shipped artifact. Attestation recorded in docs/source-map.md (§ FR-26 context-compression discipline, dated 2026-06-15).
Validation
Triple-validated before ship: a gap-analysis workflow pass, two independent Codex SHIP reviews, and a name/license firewall audit (the conceptual reference is Apache-2.0; nothing was copied; the firewall-term grep over the repo returns 0).
Verified
preflight 0/0 (committed tree) · python -m py_compile hooks/local/token-waste-audit.py OK · check-module-size --all exit 0 (parser ~479 lines) · mirror-skills 31 skills / 0 drift (manifest byte-identical) · firewall-term grep over the repo = 0 · LICENSE untouched (MIT) · plugin == VERSION == 3.26.0 · GEMINI.md = v3.26.0 · README badge = 3.26.0 · sync --dry-run framework-scoped (no consumer doc touched; under-reach guard passes) · FR-07 clean (version-string attestation sweep only; no FR rule rows, no deploy-policy rule semantics, no ratchet-governance.yml). FR-range FR-01..FR-26, 31 skills unchanged. Feature commit 6d97829.
Feature smoke (post-deploy)
A synthetic transcript built outside the repo with an oversized mcp__-tool result and an identical large body sent twice: the audit fires large-output ≥1 (including the MCP tool) and repeat-output ≥1, and a unique content marker planted in the bodies appears 0 times in the report (the one-way hash never emits the body).
Rollback
git revert <release commit> — additive (skill section + two audit classes + docs); behavior-preserving for the existing audit classes; no new dependency. Re-push; re-mirror. Tag v3.26.0.
v3.25.1 — adoption-hop baseline merge-preserve
FuseBase Flow v3.25.1 — adoption-hop baseline merge-preserve (the v3.25.0 U3/W2 merge now runs on the FIRST upgrade adopting v3.25.x)
Release date: 2026-06-15
Previous version: 3.25.0
Type: PATCH (hotfix)
Summary
Hotfix — baseline merge-preserve now runs on the first upgrade adopting v3.25.x. v3.25.0 shipped the U3/W2 module-size-baseline.txt + policy-state merge-preserve rule, but a post-ship Codex adversarial review found it was skipped on the adoption hop — the very first upgrade that brings a project onto v3.25.x. Root cause: upgrade.sh sourced the merge lib from the local (pre-upgrade) tree before hooks/ was refreshed, and bootstrap-upgrade.sh did not stage hooks/local/lib/, so the new merge code was never on disk when the merge had to run. Result: a project's own module-size-baseline.txt rows were clobbered on adoption — exactly the WorkHub Managed failure U3 was meant to fix, just one hop earlier than the gate caught.
This release is bounded to how/when the merge lib is sourced plus bootstrap staging, routing docs, and a new RED-then-GREEN adoption-hop test. The LOCKED merge rule itself is unchanged (ownership = upstream-baseline membership; project rows absent upstream preserved verbatim) — only the source-ordering that lets that rule actually execute on the adoption hop.
Why this is a hotfix, not speculative
The blocker was found by a post-ship Codex adversarial review of v3.25.0 and reproduced with a RED-then-GREEN integration test: the pre-fix engine loses the project baseline row on the adoption hop (RED), the fixed engine preserves it (GREEN). Codex re-review verdict: SHIP.
What ships
| ID | Piece | What it does |
|---|---|---|
| P1 | bootstrap-upgrade.sh stages hooks/local/lib/ |
The bootstrap path now stages the merge lib so the new upgrade.sh finds its merge code before handoff. Commit 49f335c. |
| P2 | upgrade.sh sources the merge lib from the authoritative target tree |
Sources from $SOURCE_CLONE/hooks/local/lib/ (the version being adopted) with a local fallback, re-sources before Step 1a, and prints a loud no-skip warning if the merge lib can't be loaded — so a silent skip can never recur. Commit b562166. |
| P3 | README routing | Pre-v3.25 installs are routed through bootstrap-upgrade.sh for the v3.25.x hop (the merge ships in the target version; a clobbered baseline is recoverable from the .pre-upgrade backup). Commit 5324358. |
| P4 | RED-then-GREEN adoption-hop integration test | New hooks/tests/test-bootstrap-baseline-hop.sh (13 cases) wired into run-tests: proves the pre-fix engine loses the row and the fixed engine preserves it, plus the P1 bootstrap-staging preconditions. Commit 28fe2ea. |
ACCEPTED-RISK
An old, already-installed upgrade.sh run directly (not via bootstrap) still cannot run the target-version merge code — it predates the fix and sources its own old lib. This residual is mitigated by routing pre-v3.25 installs through bootstrap-upgrade.sh (P3 docs) and is the only residual Codex flagged. Use bootstrap-upgrade.sh for the v3.25.x hop.
Verified
preflight 0/0 · run-tests 92/92 PASS (79 + 13 new adoption-hop cases) · check-module-size --all exit 0 · mirror-skills 31 skills / 0 drift (manifest byte-identical) · sync --dry-run framework-scoped (consumer docs excluded; under-reach guard passes) · plugin == VERSION == 3.25.1 · GEMINI.md synced to v3.25.1 · recovery-sim 31/31 exit 0 (state/audit/recovery-sim-v3.25.1-2026-06-15.log) · health no PARTIAL_UPGRADE false-positive · bash hooks/tests/test-bootstrap-baseline-hop.sh PASS on the released tree · FR-07 clean (version-string sweep only; no FR rule rows, no deploy-policy rule semantics, no ratchet-governance.yml, and the LOCKED merge rule untouched — only how/when the lib is sourced). FR-range FR-01..FR-26, 31 skills unchanged.
Credit
Found by post-ship Codex adversarial review of v3.25.0. The discipline of running an independent adversarial review of the shipped code caught a real adoption-hop blocker the self gate-report missed.
Rollback
git revert <SHA range 49f335c..28fe2ea + release commit> — additive (script source-ordering + bootstrap staging + docs + test); steady-state behavior is unchanged (the merge rule and content model are untouched). Re-push; re-mirror. Tag v3.25.1.
v3.25.0 — upgrade-tooling hardening
FuseBase Flow v3.25.0 — upgrade-tooling hardening (Windows perf, baseline/policy merge-preserve, sync allowlist, GEMINI sync, PARTIAL_UPGRADE)
Release date: 2026-06-15
Previous version: 3.24.0
Summary
The v3.23.x content model is correct and well-guarded — but the refresh/upgrade scripts forced manual intervention on Windows. Two independent consumer projects filed the same friction during a v3.21.1 → v3.23.1 upgrade on Windows/Git-Bash:
- paperclip+hermes-v1 —
upgrade.shstalled mid-mirror (operator killed it and finished by hand), churned 11 consumer docs on an EOF-newline strip, and rewrote FR references inside historical consumer docs. (I1–I9, plus a proven hash-spawn-batch patch.) - WorkHub Managed — the upgrade clobbered a project-state file (
policies/module-size-baseline.txt), breakingcheck-module-size --allpost-upgrade; tag fetch failed on Windows schannel. (W1–W5, commit2504584.)
This release is a reactive, bounded hardening of the three refresh scripts (mirror-skills.sh, sync-version-strings.sh, upgrade.sh) plus the GEMINI adapter, .gitattributes, and the health check. The content model, the byte-exact copy contract, and the marker-anchored overlay refresh are unchanged. Codex adversarial design review (verdict RESCOPE) flagged the biggest risk — a sync allowlist that under-reaches would recreate the GEMINI drift in reverse — so the allowlist ships with an executable under-reach guard test.
The version bump for this very release was run through the new tooling as a live self-test: the new in-script sync allowlist swept every framework adapter to v3.25.0, and the U5 regex fix finally un-stuck GEMINI.md (it had been stranded at an older header for several releases).
What ships
| ID | Piece | What it does |
|---|---|---|
| U1 | Batched mirror/sync spawns (Windows perf) | mirror-skills.sh and sync-version-strings.sh spawned a process per file; on Windows Git-Bash each spawn is ≈0.8–1.4s, so a 6,974-.md sync scan stalled into minutes. Now a single sha256sum/shasum call (ARG_MAX-chunked via xargs) primes an associative-array cache; the loop is fork-free (fixed-offset hash slicing, direct cache reads). Copy scope is unchanged — still only SKILL.md + references/* per the mirror contract (a bounded copy, NOT a blind cp -R), so the manifest stays byte-identical. Windows ~5 min → seconds. |
| U2 | Portable EOF-newline-preserving sync | sync-version-strings.sh used printf '%s' "$after" > "$f", which strips the trailing newline → 11 consumer docs churned. Replaced with the consumer's committed approach: capture each file's trailing-newline state and restore it exactly (NOT a bare sed -i, which differs GNU vs BSD). A grep -lE superset pre-filter (chunked) skips files with no token. Fixtures prove both trailing-newline and no-trailing-newline files round-trip on Git-Bash (macOS noted). |
| U3 | module-size-baseline.txt + policy-state merge-preserve on upgrade |
upgrade.sh copied policies/ wholesale, overwriting project state and breaking check-module-size --all. New merge rule (LOCKED): ownership = upstream-baseline membership (not path prefixes). Upstream Flow rows get the upstream line-count; project rows absent from the upstream baseline are preserved verbatim; a Flow row dropped upstream is removed locally; malformed local rows warn (never silently drop). Also guards approval-policy.yml:workflow_mode and protected-paths.yml worker_undisturbed — project values must live in *.local.yml (deep-merged by policy_loader.py), backed by a policy-state-preserve test. |
| U4 | Executable framework-owned sync allowlist + under-reach guard | Replaced the broad find+prune with an in-script SYNC_ROOTS/SYNC_FILES allowlist (adapters, FLOW_RULES.md, agents/**/AGENT.md, flow-skills/**, workflows/, templates/, overlays, framework docs; plugin metadata via a parity check, not sed). The under-reach guard is a test that scans those roots for syncable tokens and FAILS if any token-bearing framework file is not in the allowlist (the anti-GEMINI). Consumer roots (docs/product-backlog, problem-catalog, product-execution, client-workflows/**) are NEVER synced. |
| U5 | GEMINI version regex | The sync regex required a literal Fusebase Flow v + 3-part semver; GEMINI ships Fusebase Flow **Local** v2.1, so it stayed stuck for releases. Regex now matches Fusebase Flow (Local )?v[0-9]+(\.[0-9]+){1,2}. GEMINI.md now syncs with every release (confirmed live: v3.25.0). |
| U7 | Upgrade trap recovery + health-check PARTIAL_UPGRADE |
upgrade.sh now traps interruption/failure and prints the exact recovery command(s) to finish by hand. The health check compares derived facts (VERSION, plugin manifest, root + cursor/copilot adapters, canonical agents/workflows/templates/overlays version/FR/skill-count) against the live strings and reports PARTIAL_UPGRADE + the repair command on mismatch. Builds on the v3.24.0 health-check engine. |
| U9 | Progress output | mirroring N/31…, scanning N files…, upgrade-phase progress — the silent multi-minute window that made operators think it hung is gone. |
| U11 | .gitattributes LF pins |
VERSION text eol=lf, *.sh text eol=lf (plus the no-extension hook scripts and config/doc formats). A Windows clone could rewrite VERSION CRLF on checkout, churning it in every diff. |
| U8 | Windows docs (docs only) | README / install docs: Git-Bash invocation, detect-unusable-WSL-bash message, and the git -c http.sslBackend=openssl fallback for tag/clone failures on schannel-impaired Windows hosts. |
Deferred follow-up
- U6 — full GEMINI/copilot/cursor overlay-refresh parity (marker-anchored blocks + a refresh path). It needs a marker-strategy design of its own, so per the RESCOPE verdict it ships as a separate ticket:
docs/backlog/adapter-overlay-refresh-parity/. U5 (version sync) ships now; U6 (full overlay refresh) is the follow-up.
Why this is reactive, not speculative
Two unrelated teams hit the same refresh-script failures on the same upgrade. The fix is bounded to how the upgrade/refresh scripts handle files — not what content ships. Credit and thanks to paperclip+hermes-v1 and WorkHub Managed for the grounded, reproducible reports.
Verified
preflight 0/0 · run-tests 79/79 PASS (incl. new AC2 newline / AC3 baseline-merge / AC4 under-reach-guard + consumer-not-synced / AC7 policy-state fixtures) · check-module-size --all exit 0 · mirror-skills 31 skills / 0 drift · agent mirrors byte-identical / 0 drift · recovery-sim 31/31 exit 0 (the strongest guard — exercises both refresh scripts; captured state/audit/recovery-sim-2026-06-15.log) · plugin == VERSION == 3.25.0 · GEMINI.md synced to v3.25.0 (U5) · .gitattributes present (U11) · health PARTIAL_UPGRADE no false-positive on the synced repo · FR-07/FR-25 clean (version-string sweep only; no FR rule rows, deploy-policy semantics, or ratchet-governance.yml touched). FR-range FR-01..FR-26, 31 skills unchanged.
Rollback
git revert <SHA range> — the changes are to tooling scripts + tests + docs; additive/behavior-preserving where it counts (manifest byte-identical, content model untouched). Re-push; re-mirror. Tag v3.25.0.
v3.24.0 — health-check fast/timeout hardening
Fusebase Flow v3.24.0 — health check fast/bounded execution + PARTIAL_UNVERIFIED (exit 4)
Release date: 2026-06-15
Previous version: 3.23.1
Summary
hooks/local/fusebase-flow-health-check.sh — the read-only diagnostic operators trust for recovery — could exceed two minutes and appear to hang during installs on a network-impaired (Windows/schannel-impaired) or large-repo host. The unbounded, verdict-affecting operations were the upstream git fetch and the preflight / run-tests / check-cli-flow-conflicts sub-invocations.
The naive fix (bound/skip and move on) creates a false HEALTHY — the design review's blocker — because an empty LOCAL_BROKEN already meant HEALTHY/0, and a run-tests crash read OK via || true. So this release intentionally changes verdict semantics: a critical check that didn't run is now distinct from "ran clean."
What ships
| Piece | What it does |
|---|---|
PARTIAL_UNVERIFIED verdict + exit code 4 |
New LOCAL_UNVERIFIED tracking array. Exit 0 only when every CRITICAL check (preflight, hook tests, conflict reporter) actually ran and passed. A timed-out/skipped critical ⇒ PARTIAL_UNVERIFIED/exit 4 — never HEALTHY/0. Precedence: BROKEN > real drift > EXCEPTION > PARTIAL_UNVERIFIED > HEALTHY. |
| Optional upstream comparison | The git fetch timing out is a "upstream not verified (fetch timed out)" note only — never UNVERIFIED, never exit 4. GIT_TERMINAL_PROMPT=0 + low-speed config make it fail fast, not block on a prompt. |
run_with_timeout helper (hooks/local/lib/run-with-timeout.sh) |
Extracted per FR-25 (keeps the engine under the 800-line ceiling). Detects timeout → gtimeout; -k grace; rc 124 = timeout; preserves the wrapped command's own rc otherwise. No timeout binary ⇒ bounded ops skipped ⇒ PARTIAL_UNVERIFIED (opt into unbounded with FFHC_ALLOW_UNBOUNDED=1). A missing lib is a loud BROKEN, never a silent degrade. |
| H6 run-tests rc fix | A harness crash (rc≠0, no parsable FAIL:) previously read OK via ` |
| Flags | --no-upstream = full local verdict (exit 0 OK). --fast = skips the slow hook tests (keeps preflight + inventory + conflict reporter) for a quick verdict, but is explicitly partial: exit 4, never 0, and prints "fast mode — not a full health verdict." |
| SLO-budgeted timeouts (env-overridable) | FFHC_FETCH_TIMEOUT (15s), FFHC_PREFLIGHT_TIMEOUT (30s), FFHC_CONFLICT_TIMEOUT (30s), FFHC_TESTS_TIMEOUT (60s); worst-case bounded full run ≈ 155s. The conflict reporter's wildcard matcher now scopes its scan to the static path prefix instead of walking the whole tree — behavior-preserving (--json output byte-identical), measured ~1.8s. |
The false-HEALTHY blocker (why this matters)
This diagnostic is what operators run to decide whether to repair after a fusebase update. If a critical check silently doesn't run and the engine still says HEALTHY, an operator skips a needed recovery. Exit 4 makes "I couldn't verify" a first-class, distinct outcome from both "all good" (0) and "drift/breakage" (1/2).
Exit-code contract (callers, AC8)
| Exit | Verdict | Caller treats as |
|---|---|---|
| 0 | HEALTHY |
full health (every critical ran clean) |
| 1 | *_DRIFT |
drift |
| 2 | BROKEN |
breakage |
| 3 | EXCEPTION_IN_EFFECT |
drift covered by an operator artifact |
| 4 | PARTIAL_UNVERIFIED |
partial/unverified — re-run; NOT healthy, NOT a hard failure |
Swept for callers: no script/hook branches on the engine's exit code (the recovery test harness keys off the Verdict: line, with || true). The skill, README, and docs/health-check-deferrals.md exit-code tables now carry exit 4.
Verified
preflight 0/0 · recovery suite incl. 7 new health-check timeout fixtures (AC1 fetch-timeout-not-hang→exit0; AC2 critical-timeout→exit4; AC4a preflight-fail→BROKEN; AC4b harness-crash→BROKEN; AC4c --fast→exit4; AC6 no-timeout-binary→partial; AC6 unbounded-opt-in→HEALTHY) · existing U/F engine drift tests unchanged · AC3 full reachable run → HEALTHY/0 · mirrors 0 drift · module-size: engine + new lib both under the 800-line ceiling.
Rollback
git revert <SHA> — additive (a new verdict/exit code + flags + a sourced helper lib + tests + docs); no schema/data, no deploy-authority change, fully reversible. Tag v3.24.0.
v3.23.1 — find-wasted-effort containment hardening
FuseBase Flow v3.23.1 — /find-wasted-effort containment hardening
Release date: 2026-06-14
Previous version: 3.23.0
Deploy hash: 08940a4
Summary
Patch hardening of the /find-wasted-effort audit's on-disk write path (additive; the analyzer stays read-only to the project). The audit's report/proposals write is now an atomic temp-file + os.replace() into the contained state/audit/ directory, and it rejects hardlinked/symlinked targets up front (fail-closed) — defeating a pre-planted-alias write-through that could otherwise have modified a file outside state/audit/. The at-rest threat model is now documented in the write path: containment defends pre-planted symlink/hardlink/traversal targets at rest; active concurrent filesystem races mid-run are explicitly out of scope for a local, single-operator, read-only audit tool. No behavior change to verdicts or proposals; the read-only-to-the-project invariant is unchanged.
What ships
| Piece | What it does |
|---|---|
| Atomic contained write | write_audit_file() writes to a fresh temp file inside the resolved state/audit/ dir, then os.replace()s it onto the target. The replace rebinds the directory entry to a NEW inode, so any pre-planted hardlink/alias at the target is severed and the outside file it aliased is never modified. Same-filesystem temp keeps the rename atomic and contained. |
| Hardlink/symlink fail-closed | Before writing, the target is rejected outright if it is a symlink (is_symlink()) or a hardlink alias (lstat().st_nlink > 1) — the audit refuses to write through a planted alias, raising RootError. Loud, not silent. |
| Honest fail-closed fixture | The g2 selftest now asserts the TRUE contract: a pre-planted-at-rest hardlink at the target ⇒ RootError (fail-closed) AND the outside aliased file is byte-unchanged. It drops the prior dishonest "report still lands despite planted hardlink" claim (which masked the fail-closed reality by removing the alias first). The severed-alias / new-inode happy path stays proven by the g3 normal-write fixture (st_nlink == 1, no temp turd left behind). |
| Documented at-rest threat model | A concise FR-22 threat-model note at write_audit_file() (with a pointer from contained_audit_path()): containment defends pre-planted symlink/hardlink/traversal targets AT REST; active concurrent FS races mid-run (e.g. renaming state/audit/ between temp-create and replace) are OUT OF SCOPE for a local single-operator read-only audit tool. |
Still read-only to the project (unchanged invariant)
The analyzer writes nothing outside the gitignored state/audit/ directory and applies nothing. This patch only hardens how that single contained write happens; verdicts, proposals, and the Phase-2A descope (write-apply Phase 2B and the Middle Lane Phase 3 remain deferred to the paperclip+hermes-v1 consumer repo) are unchanged.
Live proof
python hooks/local/find-wasted-effort.py on this repo: 34 artifacts scanned, 6 rounds, window 20. The run wrote ONLY the contained state/audit/find-wasted-effort-<date>.md report + the gitignored proposals JSON; git status showed no edits outside state/audit/. --selftest: 155 passed, 2 skipped (skips = host lacks symlink/hardlink privilege; the now-honest g2 fail-closed assertions run on a capable host).
Verified
preflight 0/0 · --selftest 155 passed, 2 skipped · run-tests 24/24 · mirrors 0 drift · health HEALTHY · plugin valid · counts unchanged (FR-01..FR-26, 31 skills — patch hardens find-wasted-effort, no new skill/rule).
Rollback
git revert 08940a4 (and 2ee0a2c / 1e36b8b if the containment fix itself must come out too) — additive and read-only-safe; a clean revert (no schema/data, no deploy-authority change, no protected-path edit). Tag v3.23.1.
v3.23.0 — find-wasted-effort proposal output
Fusebase Flow v3.23.0 — /find-wasted-effort proposal output (ceremony-efficiency Phase 2A)
Release date: 2026-06-14
Previous version: 3.22.0
Deploy hash: __DEPLOY_HASH__
Summary
Phase 2A of the ceremony-efficiency-middle-lane ticket — additive, read-only-safe. /find-wasted-effort now emits schema'd proposals (a Proposed memory entries report section + an optional gitignored state/audit/ JSON), so a human can see the exact change each finding would justify. The analyzer stays read-only to the project — it writes nothing outside the gitignored state/audit/ directory; it applies nothing.
Per the Codex Phase-2 design review (2026-06-14), the read-only→write flip was descoped from the framework: the actual memory write-apply (Phase 2B) and the Middle Lane (Phase 3) are routed to the paperclip+hermes-v1 consumer repo as hard-gated prototypes, upstreamed only once proven (the Lightweight-lane pattern). The framework side stays proposal-output-only until then.
What ships
| Piece | What it does |
|---|---|
| Proposal output (read-only-safe) | A Proposed memory entries section in the contained state/audit/<date>.md report + an optional sibling gitignored state/audit/find-wasted-effort-proposals-<date>.json (--no-proposals-json skips the JSON; the report section is always written). A confirmed finding → a recommendation proposal; a rule-6 review-candidate → a prune_review_candidate; inconclusive/dismissed findings emit none. |
| Defined proposal schema | Each proposal carries proposal_id, rule, verdict, raw_evidence_refs, target_kind, target_path, exact_patch, operator_confirmation_required: true, source: "audit". The audit proposes the change a human could apply — it never applies it. |
| Self-output quarantine (Codex finding 5) | Proposals cite raw on-disk artifacts as evidence, never a prior audit report/proposal; the evidence collectors do not read state/audit/, so the audit cannot cite itself (no self-reinforcement loop). |
prune_review_candidate only |
A rule-6 element is a review candidate for a PO-owned subtraction under the policies/ratchet-governance.yml prune protocol — never an auto-prune or a recorded prune decision. |
| Containment hardening (Codex Phase-2A LOW) | contained_audit_path now resolves the target before the relative check and rejects an absolute / .. / path-separator basename at the boundary (raises RootError). Both real callers pass fixed flat basenames — a no-op for them; it closes internal-misuse traversal in the containment helper. |
Still read-only to the project (the load-bearing invariant)
Phase 2A enriches the output only. The analyzer writes nothing outside the gitignored state/audit/ directory — a hard test asserts a full run modifies no memory / overlay / spec / provider / policy file. Findings remain review candidates; the PO owns subtraction. This is NOT the read-only→write flip (that is Phase 2B, deferred to the consumer repo behind AC2b's hard gates).
Live proof (this repo as the first consumer)
python hooks/local/find-wasted-effort.py on this repo: 33 artifacts scanned, 6 rounds, window 20. Report carries the new "Proposed memory entries" section; the gitignored proposals JSON is written under state/audit/. The run made no edits outside state/audit/ (git status clean). --selftest 151 passed, 2 skipped (skips = host-symlink fixtures; +6 over v3.22.0 = the new basename-hardening containment fixtures).
Verified
preflight 0/0 · --selftest 151 passed, 2 skipped · run-tests 24/24 · mirrors 0 drift · health HEALTHY · plugin valid · counts unchanged (31 skills — Phase 2A extends find-wasted-effort, no new skill).
Deferred (consumer-repo prototypes → upstream when proven)
- Phase 2B — memory write-apply — behind AC2b: operator-authored approval artifact · per-target containment · self-output quarantine · ≥1 real confirmed + 1 dismissed counterexample · security-permissions-review. Prototyped in
paperclip+hermes-v1. - Phase 3 — Middle Lane /
middle_deploy— prototyped as aFLOW:PRESERVEoverlay inpaperclip+hermes-v1, proven on real rounds, then upstreamed (Full lane, AC7). - Overlay-edit apply — dropped to a later ticket (Phase 2A emits a diff only).
Rollback
git revert <SHA> — Phase 2A is additive and read-only-safe (a clean revert; no schema/data, no deploy-authority change, no protected-path edit). Tag v3.23.0.
v3.22.0 — find-wasted-effort + ratchet governance
Fusebase Flow v3.22.0 — ratchet governance (A3) + /find-wasted-effort read-only audit (A2)
Release date: 2026-06-13
Previous version: 3.21.1
Summary
Phase 1 of the ceremony-efficiency-middle-lane ticket — the low-risk, reversible, no-deploy-risk wins that earn the evidence for the risky lane later. It solves two of the three reported problems:
- PR-2 (ceremony ratchets) — incidents ADD steps; success never removes them; no role owns pruning → A3 ratchet governance: every safety-bearing ceremony element carries
prevents: <incident-class>; the PO owns subtraction. - PR-3 (can't diagnose outcome-neutral ceremony) — no instrument separated safety-bearing from waste → A2
/find-wasted-effort: the process-per-outcome sibling of/token-waste-audit.
PR-1 (the Middle Lane) is Phase 3 and is not in this release (it changes deploy authority and ships via the Full lane on its own gate). Phase 2 (audit write phase) is also separate.
What ships
| Piece | What it does |
|---|---|
A3 — policies/ratchet-governance.yml |
The prevents: <incident-class> annotation convention + the catastrophic-low-frequency severity tag (rare-but-severe controls are HARDER to prune — a clean window is expected, not evidence of waste). A 9-class incident taxonomy (false-green-deploy, unattended-prod-cutover, unauthorized-deploy, irreversible-loss, silent-protected-path-drift, …) is the WHY-home; a D5-scoped coverage map (deploy/gate controls + the elements rule 6 reads) states its own scope so the audit reports coverage rather than implying full-framework annotation. PO-owned, never-automatic prune protocol. |
| A3 scoped annotations | prevents: markers (tripwire + pointer, FR-22) on the deploy/gate control set: templates/{handoff-deploy,handoff-implement,gate-report,verification-gate}.md + workflows/{greenlight-deploy,eight-phase-flow}.md. |
A2 — find-wasted-effort skill (31st) |
Process-per-outcome ceremony audit. Distinct AXIS from /token-waste-audit (tokens-per-rule, transcripts); distinct INPUTS (Flow artifacts on disk); shared DISCIPLINE (FP header, read-only-first, state/audit/ output — reused from token-economy, not reinvented). 6 active rules — rule 4 CUT (token-waste-audit's v3.21.0 cross-session aggregate covers context-rebuild), rule 7 scoped to the cross-session ceremony layer only (no overlap with FR-26's execution-layer polling). Each rule emits confirmed / dismissed / inconclusive with the contrary evidence it searched for. |
hooks/local/find-wasted-effort.py + find_wasted_effort/ package |
Deterministic, stdlib-only, READ-ONLY analyzer (thin CLI orchestrator + a 6-module package split along the per-rule + test-layer seam; every module under the FR-25 800-line ceiling). Writes only its own gitignored state/audit/find-wasted-effort-<date>.md; NO memory/overlay/spec edits, NO prune/reclassify (D4 — those are Phase 2/3, gated on per-rule FP fixtures). Mirrors token-waste-audit.py's substrate. --selftest = synthetic + evidence-sourcing/scoping + end-to-end + path-containment + prevents:-parser fixtures (116 passed, 2 skipped — skips = host-symlink fixtures). |
/find-wasted-effort (6th command) |
Command file + recovery snapshot (preflight §8 + 5d enforced); skill mirrored to .claude/skills/ + .agents/skills/. |
Read-only is load-bearing (D4)
Phase 1 ships the audit read-only: it describes review candidates; it never removes ceremony, edits memory/overlays, or reclassifies a lane. A confirmed finding is a candidate for a PO review under the ratchet-governance.yml prune protocol — never an auto-prune. A catastrophic-low-frequency control on a clean window is reported inconclusive, never confirmed.
Live proof (this repo as the first consumer)
python hooks/local/find-wasted-effort.py on this repo: 30 artifacts scanned, well-formed report with the FP header, per-rule confirmed/dismissed/inconclusive, and a coverage section listing all 17 governed controls. Rule 6 detected prevents: markers in all 6 annotated files. --selftest 116 passed, 2 skipped (skips = host-symlink fixtures). No tracked changes beyond the analyzer (report is gitignored).
Verified
preflight 0/0 · --selftest 116 passed, 2 skipped · mirrors 0 drift · counts swept 30 → 31 skills / 8 → 9 policies / 5 → 6 commands.
Rollback
git revert <SHA> — Phase 1 is additive (a new skill + analyzer + policy + annotations + a command); no schema/data, no deploy-authority change, fully reversible. Tag v3.22.0.
v3.21.1 — delegation residuals (recovery surfacing, deploy push, report pointers, ground-truth returns)
Fusebase Flow v3.21.1 — delegation residuals
Release date: 2026-06-12
Previous version: 3.21.0
Summary
Downstream (paperclip+hermes-v1) verified v3.20.1 + v3.21.0 — all 10 prior asks confirmed delivered — and reported 4 second-order residuals from continued live use. All four verified real against this repo and fixed: one silent-failure surfacing, three rules that existed but didn't reach the surface that needed them.
Fixes
| # | Fix |
|---|---|
| 1 | Recovery call surfaced (upgrade.sh step 4). The overlay/command recovery ran fully silenced — a mid-run crash half-applied (downstream: 2 of 5 command files stale) with the root cause masked. Now: success prints the recovery's actions-taken summary ([upgrade] recovery: …); non-zero exit prints a loud HALF-APPLIED warning + last output lines + the literal re-run command. Note: the recovery exits 1 on warnings as well as crashes — the WARN says "review", it does not fail the upgrade. |
| 2 | Deploy sessions inherit the delegation contract. The v3.21.0 push-not-pull fix reached implement handoffs but not templates/handoff-deploy.md — the prompt a delegated Deploy session actually reads. It now carries the turn-completion + progress-ledger + BLOCKED-AT-<gate> invariant bullet, and workflows/greenlight-deploy.md joins its mandatory-reads list. |
| 3 | Self-recording clause for reports (gate-report + deploy-report headers + validation-and-qa): if the system under test has durable evidence surfaces (journals, run records, logs, snapshots), report fields carry POINTERS to them — transcribe only what no system records. Extends the v3.21.0 pointers rule from returns to reports (FR-23). |
| 4 | Ground-truth rule in the return shape (task-delegation + push block + implement-handoff quote): any claim that system state changed names the verification performed — the system surface read and what it showed. An attempted action or an observed look-alike artifact is not evidence (downstream: a false "launched" claim survived ~19 hours). |
Verified
Sim (real v3.19.1 consumer, git-inited, v3.21.1 engine): success path shows the surfaced recovery summary + post-upgrade preflight 0/0; stubbed-crash source shows the HALF-APPLIED warning block with re-run command. Upstream gates: preflight 0/0 · run-tests 24/24 · mirrors 78/0 drift · overlays byte-match · history guard intact. Independent post-implementation review before tag.
Rollback
git revert <SHA> — one script block + template/skill text; no rule, gate, or hook-handler change. Tag v3.21.1.
v3.21.0 — delegation resilience + return contracts
Fusebase Flow v3.21.0 — delegation resilience + return contracts
Release date: 2026-06-12
Previous version: 3.20.1
Summary
Closes the six evidence-backed residuals from live delegated-run experience (downstream proposal, paperclip+hermes-v1): sessions that die mid-work lose end-loaded reports; unbounded waits had no honest exit; returns re-pasted artifact bodies; reused templates propagated superseded procedures; one file served two confusing masters (restart artifact vs run ledger); cross-session recurring costs were invisible to the per-session audit. Built under the double-review protocol — the plan review caught two genuine design blockers before implementation.
What ships
| Piece | What it does |
|---|---|
| Progress-ledger contract | task-delegation §3 + greenlight-deploy step 7: durable facts written AS THEY OCCUR (deploy hash at deploy moment, probe rows as earned, skeleton first) — never end-loaded. Successor contract: resume from records, never redo verified steps. |
| Blocked-return semantics | At an UNBOUNDED wait (human gate, no-ETA event): return BLOCKED-AT-<gate> + what-cleared-looks-like + state pointer. Never fake-complete; never burn an open watch. |
| Delegated return shape | Verdict (DONE|BLOCKED-AT-<gate>|FAILED-<reason>) · per-task SHAs · count deltas · artifact POINTERS · residual risk. Never re-paste what an artifact already holds. Delegated returns only — gate reports keep PASS/FAIL. |
| Delegation contract push block | The plan-review blocker fix: workers never load skills, so the whole contract rides the delegating prompt — a named, quotable ≤4-line block; templates/handoff-implement.md's push line upgraded to it. |
| Restart vs run-ledger split | docs/tmp/handoff.md header gains Mode: restart | run-ledger. Restart stays operator-triggered; run-ledger is the sole sanctioned autonomous write (announced in chat). Run-ledger updates supersede IN PLACE — archive fires on restart supersede / mode transition only (plan review killed the archive-flood + same-minute filename collision). Legacy files without Mode: = restart. |
| Procedure freshness | One line in handoff Procedure + handoff-implement + handoff-deploy headers: check whether a shipped capability supersedes a reused procedural block before executing it. |
Cross-session aggregate (/token-waste-audit) |
New report section when ≥2 sessions parsed: files/commands recurring across sessions, top-N capped. Framing header maps recurring rules/handoff reads + session-initiation Bash floor to FR-23 session-floor discipline (by-design), NOT FR-26 violations, and states the Read-tool-only visibility limit. |
Review provenance
Plan review: REVISE-FIRST, 13 findings, all folded into the locked spec — including two blockers: (1) the contract text would bind nobody (workers don't load orchestrator skills) → push block; (2) archive-on-every-ledger-update floods docs/tmp/handoff/archive/ and <YYYY-MM-DD-HHMM> filenames clobber within a minute → in-place supersede. Implementation review ran before ship; findings fixed pre-tag.
Verified
preflight 0/0 · run-tests 24/24 · module-size --all green · mirrors 78 files / 0 drift (count unchanged — no new skill) · AGENTS/CLAUDE inline overlays byte-match · live self-run: aggregate section produced from 3 real transcripts; degraded paths (empty dir, nonexistent dir) exit 0; parser 397 lines (stdlib-only).
Rollback
git revert <SHA> — skill/template/workflow text + one parser section; no rule, gate, or hook change. Tag v3.21.0.
v3.20.1 — upgrade installer parity + self-overwrite-safe engine
Fusebase Flow v3.20.1 — upgrade installer parity + self-overwrite-safe engine
Release date: 2026-06-12
Previous version: 3.20.0
Summary
Defect-fix release driven by two downstream reports (paperclip+hermes-v1): in-place upgrades crossing a command-adding release landed BROKEN by their own preflight (/handoff at 3.14.x, recurred with /token-waste-audit at 3.20.0). The E2E verification then exposed a second, worse latent defect: pre-3.20.1 engines can abort mid-upgrade by overwriting their own running script. Both are fixed, with a write-time gate so the first class cannot recur.
What was wrong
| Defect | Root cause |
|---|---|
| New slash commands never install on upgrade | The installer chain existed all along (upgrade.sh step 4 → post-fusebase-update.sh Step 8, a data-driven loop) — but its source, the recovery snapshot hooks/local/fusebase-flow-overlays/commands/, held 3 of 5 commands and nothing enforced completeness (preflight checked snapshot→live only; live commands absent from the snapshot were invisible). |
Upgrade aborts mid-run with syntax error (found by this release's E2E sim) |
upgrade.sh refreshes hooks/ — overwriting its own running file; bash streams scripts incrementally, so execution resumes at a stale byte offset inside the replaced content. Offset-dependent (nondeterministic luck on past hops; deterministic on 3.19.1→3.20.1), stranding the consumer half-upgraded: content new, VERSION old, mirrors stale, commands missing. |
Fixes
- Snapshot backfilled to 5/5 commands, byte-identical to
.claude/commands/(preflight 5dcmpenforces). - Write-time gate: preflight §8 refactored data-driven over one
FLOW_COMMANDSarray — per command, three ERROR checks: live file · recovery-snapshot copy · CLAUDE.md reference. A command surface may only ship with its installer step (the downstream report's sharpened ask, made deterministic). PUBLISHING.md carries the matching release rule. main()-wrapped engine: the wholeupgrade.shbody is parsed before step 1 executes — v3.20.1+ engines are immune to self-overwrite.- Upgrading FROM ≤3.20.0 (old engines are unfixable retroactively — README documents both recoveries):
bash hooks/local/bootstrap-upgrade.sh -- --auto-yes(stages the new engine first; the self-overwrite becomes byte-identical → harmless; works on any 3.8.0+ install) — or simply re-runupgrade.shafter an abort (the refreshed engine completes idempotently). - Actionable, not silent: upgrade.sh step 4b WARNs when CLAUDE.md still lacks a
/commandreference after the overlay refresh; the plan output names the command-restore step; stale enumerating comments de-hardcoded.
Verified (against the real v3.19.1 engine, not a synthetic consumer)
Consumer = git archive v3.19.1 extract, git-inited; source = this release's final tree. All rows observed, not inferred.
| Path | Result |
|---|---|
Old upgrade.sh direct |
Run 1 aborts mid-run (the latent defect, reproduced: syntax error, exit 2) → run 2 completes: preflight 0 errors / 0 warnings, /token-waste-audit installed, CLAUDE.md ref present, plugin.json 3.20.1 == VERSION |
Old bootstrap-upgrade.sh -- --auto-yes |
One-shot: preflight 0/0, command installed, plugin parity, zero manual wiring |
| New wrapped engine, source bytes differ mid-run | Single run completes — zero syntax errors (immunity observed) |
| Negative (gate) | Deleting a snapshot command file ⇒ preflight ERROR naming the installer-step rule |
Plus: preflight 0/0 · run-tests 24/24 · upstream gates green.
Review provenance
Shipped after an independent FIX-FIRST review: every mechanical claim verified (gate refactor strictly supersets the old checks; wrapper semantics; byte-identical snapshot; dated-history guard). The review also forced the evidence re-run above (first sim predated the plugin.json fix), caught a pre-existing backup-corruption bug — the attestation sweep rewrote version strings inside *.pre-upgrade-*/*.pre-bootstrap-* rollback backups (fixed here; backups stay pristine) — and tightened command-ref matching to word boundaries.
Rollback
git revert <SHA> — script + docs + snapshot additions; no rule, skill, or hook-handler change. Tag v3.20.1.