Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .agents/plans/06-patch-release/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Baseline-qualified patch releases

This policy adds a limited path alongside full qualification. The operator
explicitly authorized it on 2026-09-14. It does not change historical grades.

## Eligibility

A stable version must advance within a fully qualified baseline's major/minor.
Every candidate is compared directly with that baseline's measured source, never
just the previous patch. The baseline tag must resolve to the recorded commit,
contain the measured source commit, and be an ancestor of the candidate.

Runtime source, lockfiles, dependencies, package exports, package scripts,
engines, build configuration, and all guides other than flow-run must remain
unchanged. Package metadata may change only its version. Only enumerated release
scripts/workflows, offline evals, tests, plan records, documentation, and .gitignore
may otherwise differ. Unknown paths fail. Only adding the sealed patch-baseline directory to formatter exclusions is
allowed in biome.json; all other settings must match. The build and packaging helpers are
outside the allowlist. A new category requires an explicit reviewed policy change.

The only shipped guide exception is a reviewed flow-run clarification. Its exact
content digest and rationale must be recorded. The reviewer must confirm that it
clarifies an existing obligation without changing permissions, workflow gates,
validation, review requirements, or closure guarantees. Code cannot infer that
semantic judgment from a path or a patch version. A content change invalidates
that approval. This is a maintainer review control, not a sandbox against someone
who can rewrite the policy and its approvals together.

## Evidence

A record at evals/qualification/patches/VERSION.json uses schemaVersion 1 and kind
baseline-qualified-patch. It contains the candidate's exact tarball and unpacked
manifest hashes, its version, the baseline artifact identity, tag commit, canary
path and regraded bundle hash, approvedBy, rationale, and any guidance approval.
The PatchReleaseSchema in scripts/patch-release.ts is the executable format.

The baseline must independently pass the full verifier at release time. Existing
seven-day campaign and 72-hour canary limits remain unchanged. A patch record
cannot stand in for a fully qualified baseline, extend freshness, or invent runs.
An expired baseline blocks; it never starts a paid campaign automatically.

The candidate has no new model eval or live model canary. Required assurance is
clean source, strict diff eligibility, matching package bytes, review of the
clarification, deterministic checks, replay, package smoke, provider-free pinned
OpenCode smoke, and green CI. These checks do not establish model behavior on the
new candidate. This reduced assurance must be visible in release notes.

Offline verifier changes may require resealing the original retained baseline
campaign under current verifier authority. Keep original provider evidence and
seals unchanged; place the new seal alongside them in a separate bundle directory.
Only that new directory is passed to patch verification, avoiding ambiguous seals.

## Publication

The release workflow chooses --patch only when the version's explicit record
exists; otherwise it uses --canary and the original full route. A malformed patch
record fails; it never silently falls back. Both flags together are rejected.

release.ts init and resume independently recheck the same evidence choice. The
persistent release record binds the patch file's digest through bundleSha256 and
stores its path in the optional patch field. Existing full records stay valid.
Candidate notes identify the policy, prior version, prior package/bundle/canary,
and state that prior passes are not candidate measurements. Recovery still checks
exact payloads, Git refs, remote assets, and npm integrity before mutations.

No --skip-evals flag, environment bypass, altered old report, or fake candidate
canary is used. Updating this policy does not itself publish or authorize spend.

## Current candidate

8.3.1 contains the reviewed baseline capture/inventory clarification from PR #75.
The independent reviewer already required that inventory. Core source, dependencies,
build settings, and review authority are unchanged. PRs #73/#74 improve release
recovery and spending guards; #76 adds offline reporting. The intended release
notes must describe the spending guard as a top-level dispatch limit, not a token
or billing ceiling. The 8.3.0 matrix's 76/76 result belongs to 8.3.0 only.

The regression suite checks version boundaries, protected paths, dependency
changes, guide hash substitution, dirty source, changed runtime, moved baseline
tags, stale evidence, and mismatched seals. Existing publication recovery tests
continue to exercise unchanged transport convergence. No paid runs are authorized.
30 changes: 30 additions & 0 deletions .agents/plans/06-patch-release/verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 8.3.1 patch verification

The original 8.3.0 campaign was independently regraded offline into the new seal
qb1-c61abd32788d84b1950e7908cf3b96bc57e4dad1a6af26c950a6d3124bd2e6a4.
Original reports, model transcripts, canary, and seals are unchanged. The copied
content-addressed baseline bundle retains its own verifier source evidence.

Candidate tarball SHA-256:
29c7a3c1a4a652b5e3b95f9966d502556d944317bc73b820e2e048067e3df14c.
Candidate unpacked manifest SHA-256:
53f731df696d1a20c5ed181580ef841d73eecffab32820725291242a95e200d2.

The real release initializer verified eligibility, package identity, guidance
content, and full baseline evidence, then generated the durable local release
record and notes. This was initialization only; no publication resume was run.
The draft output lives under ignored .release-artifacts/8.3.1-readiness/.

Focused release tests passed (10), existing metadata/documentation tests passed,
all 13 gated cassettes reproduced, package smoke passed, actionlint passed, and
pinned OpenCode 1.18.6 provider-free smoke passed (21 tests). These do not run
models. The canary readiness dry-run correctly says the candidate has no canary;
the explicit patch policy accounts for that absence.

An initial initializer invocation used an abbreviated commit and was rejected by
the release-record schema. Repeating it with the full commit passed. No evidence
was weakened or replaced to resolve this input error.

The patch baseline retains the existing 72-hour canary and seven-day campaign
freshness limits. Before a later publication attempt, verify it has not expired.
CI and PR review remain required before merging/releasing the new policy.
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,43 @@ jobs:

- name: Run live OpenCode smoke
run: bun run smoke:live

patch-qualification:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out full release history
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Set up Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
- name: Set up Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
- name: Verify patch candidate offline when declared
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
shell: bash
run: |
set -euo pipefail
version="$(node -p "require('./package.json').version")"
patch="evals/qualification/patches/${version}.json"
if [ ! -f "$patch" ]; then
echo "No baseline-qualified patch declared. Full qualification remains required for release."
exit 0
fi
if [ -n "$BASE_SHA" ] && git diff --quiet "$BASE_SHA" HEAD -- "$patch" package.json; then
echo "No new patch release declaration; candidate qualification deferred until release preparation."
exit 0
fi
bun install --frozen-lockfile
bun run build
mkdir -p .release-artifacts/patch-ci
bun pm pack --destination .release-artifacts/patch-ci
bun scripts/release.ts init .release-artifacts/patch-ci/record \
--artifact ".release-artifacts/patch-ci/opencode-plugin-flow-${version}.tgz" \
--patch "$patch" --commit "$GITHUB_SHA"
8 changes: 6 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,20 @@ jobs:
exit 1
fi

- name: Verify independently regraded qualification bundle and fresh canary
- name: Verify full or baseline-qualified patch evidence
timeout-minutes: 5
shell: bash
run: |
set -euo pipefail
version="$(node -p "require('./package.json').version")"
tarball="$(ls opencode-plugin-flow-*.tgz)"
evidence=(--canary "evals/canary/${version}.json")
if [ -f "evals/qualification/patches/${version}.json" ]; then
evidence=(--patch "evals/qualification/patches/${version}.json")
fi
bun run scripts/release.ts init .release-state \
--artifact "$tarball" \
--canary "evals/canary/${version}.json" \
"${evidence[@]}" \
--commit "${GITHUB_SHA}"

- name: Persist release record before publication
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

One short entry per release, written for users deciding whether to upgrade.

## [8.3.1] - 2026-09-14

Clarify review handoffs and make release operations recoverable.

- Capture the feature baseline before edits and include its inventory in review.
Recover retained observations on resume and identify missing evidence explicitly.
- Resume publication from a durable release record without repeating uncertain
GitHub draft creation. Verify existing assets and npm integrity on recovery.
- Require persistent authorization for supported paid eval and canary launchers.
Consumed top-level dispatches survive failure and restart; this is not a token
or billing ceiling.
- Report review observations, missing evidence, and attributed finding categories
offline. Advisory findings may omit optional evidence without losing the review.
- Add a restricted baseline-qualified patch route. This candidate has no new live
model eval or canary; prior 8.3.0 results describe 8.3.0 only. Offline checks and
reviewed scope support this release, without claims of improved model accuracy
or measured cost savings.
- Schema impact: Session v5 schema, runtime tool schemas, and package exports are unchanged.

Upgrade with `opencode plugin opencode-plugin-flow@8.3.1 --global --force`.

## [8.3.0] - 2026-09-13

Flow preserves native model settings across continuation, keeps full sessions
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ expensive, and it is overhead when it is not.
Install the exact npm release through OpenCode:

```bash
opencode plugin opencode-plugin-flow@8.3.0 --global --force
opencode plugin opencode-plugin-flow@8.3.1 --global --force
```

Omit `--global` for project scope. Version pins are exact and never update on
Expand All @@ -51,7 +51,7 @@ The equivalent manual project configuration is:
```json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-plugin-flow@8.3.0"]
"plugin": ["opencode-plugin-flow@8.3.1"]
}
```

Expand All @@ -62,7 +62,7 @@ For an explicit reviewer model, use OpenCode's plugin tuple options:
"$schema": "https://opencode.ai/config.json",
"plugin": [
[
"opencode-plugin-flow@8.3.0",
"opencode-plugin-flow@8.3.1",
{ "reviewer": { "model": "provider/model", "steps": 80 } }
]
]
Expand Down
3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"!evals/results",
"!evals/canary",
"!evals/decisions",
"!evals/qualification/bundles"
"!evals/qualification/bundles",
"!evals/qualification/patch-baselines"
]
},
"formatter": {
Expand Down
22 changes: 11 additions & 11 deletions docs/release-qualification.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,15 @@ This page owns release thresholds, candidate freezing, and publication order.
| `project-gate-discovery` | ungated | Report-only until two provider baselines show whether planning selects the explicit whole-repository command over a narrower script. |
| `task-risk-lenses` | ungated | Measures whether the manager supplies the relevant full review questions. It does not measure defect detection or false blockers. |

Offline verification fixes do not require new provider runs when the measured
package bytes and frozen case policy remain unchanged. Qualification preserves
the original report and evaluator identity, verifies that identity against the
exact recorded Git commit without executing historical code (that commit must
be available in local Git history), and retains those
execution sources separately from the current verifier sources. The current
verifier independently recomputes every retained outcome before publication.
Missing or mismatched execution sources, changed outcomes, and altered package
bytes remain failures. Canary review retries may use multiple reviewer sessions
when all are linked to the same observed manager with consistent identities.
Offline verifier fixes may reuse runs only for unchanged package bytes and frozen
case policy. Current code regrades retained outcomes without executing historical
code; execution sources must match the recorded Git commit. Missing sources or
changed outcomes fail. Canary retries must retain consistent manager/reviewer identity.

Eligible patches may instead use the [baseline-qualified patch policy](../.agents/plans/06-patch-release/README.md).
This explicitly permits no new model eval or canary, binds the new artifact, and
labels prior results as baseline evidence only. Full qualification remains the
default; patch version numbers alone grant no exception.

A new scenario needs an explicit release-policy decision. Any required canonical
case missing from the report fails qualification.
Expand Down Expand Up @@ -72,7 +71,8 @@ Finish or close active sessions before changing Flow versions in either directio
- **Freeze on the public surface** while the guarantees are being measured: tools,
commands, guides, agents, and the Session v5 shape. Additive optional fields are
allowed; removals and renames are not.
- **No release** without a sealed V2 qualification bundle and fresh canary.
- **Full qualification** requires a sealed V2 bundle and fresh canary; eligible
baseline-qualified patches use the explicit policy above.
The bundle retains every attempt, transcript, grader source, and exact artifact
needed to reproduce its decision. Release metadata independently regrades those
bytes before publication and derives the provider-count evidence table added to
Expand Down

Large diffs are not rendered by default.

Loading