What to test
This candidate collapses every durable owner of an active review into one record, and changes how a review ends. Exercise these against real repositories rather than fixtures:
- Run a full negotiated review to approval. Approval no longer burns on its own: the final capture returns
review.acknowledge-approvedwith an exact token, and only that invocation burns the authority and its artifacts. Restart STATUS before acknowledging and confirm it replays the same operation, arguments, token and revision. Then run a wrong, stale or repeated acknowledgement and confirm it refuses without leaving a receipt, tombstone or delivery authority behind. - Exercise the zero-lens path: a passive documentation candidate that needs no lenses is approved at START and carries its acknowledgement there. A host that ignores it strands the lineage as approved, so confirm your runtime runs it.
- Drive a correction and leave an artifact behind while you edit: a test output, a build product, a coverage profile. The review must route to the untracked selection the new file requires and, once you declare it, return to the same pending validation. Report any correction that cannot be driven forward.
- Inspect the
repository_contexthandle your runtime receives. It is an opaquerctx2_digest and must carry no filesystem path. Capture from an unrelated working directory by naming the repository with--cwd, and confirm a handle from another repository, lineage, target or revision is refused. - Ask a reviewer for findings that cite files by name rather than by repository-relative path. An unambiguous citation is admitted against the frozen changed-path manifest; two candidate files sharing a name are still refused. Report any citation that names a file of the candidate and is rejected as outside it.
- Exercise refusals for what they claim. An over-budget pre-edit correction forecast reports that nothing started rather than an unknown outcome, and writes no defect report. A replayed acknowledgement refuses with a typed message that carries no path.
- On Pi, run the relay end to end. Pi decodes the acknowledgement, runs it, and only then is the authority burned.
- Verify
gentle-ai-review-provider-contract-1.1.0.tar.gzfrom the tagged source withgo run ./internal/providercontractbundlecmd verify --archive <bundle>, then inspect it withtar -tzf <bundle>.
The change whose argument is verified in tests and unproven in the field is acknowledgement-before-burn. Its replay, staleness and burn paths are covered, but no field evidence yet shows what a host does when it decodes the acknowledgement and never runs it. That lineage stays approved and unburnable by design. Finding a runtime that reaches that state is the most useful thing this candidate can learn.
What the previous candidate taught us
rc.1 closed review at its last causal event instead of producing a second delivery decision. Running it revealed that "last event" still left several durable owners of the same truth: a persisted context locator, effect markers, readiness artifacts, result-disposition projections, and caller-reconstructed selectors. A crash between publications could leave authority present while its context, digest or terminal response was absent.
This candidate collapses those into one replacement-version CAS record per host cwd + lineage, and adds the acknowledgement that rc.1 was missing: approval that burns immediately cannot tell the host it was received. The line it stays within is unchanged. No public Go API widens, admission stays fail-closed, and retired projections load through historical compatibility rather than regaining authority.
One record owns the active review
START, STATUS, capture, correction, restart and closure used to consult different representations of the same candidate. The compact authority record is now the sole durable owner of lifecycle truth: frozen binding, epoch and revision, admitted lens, refuter and validator results, replay identity, correction state and terminal disposition. The retired owners cannot be removed one at a time, because a lifecycle that reads two representations mid-series is the defect itself.
The refusal surface shrank with them: the ratchet baseline went from 130 entries to 9.
Approval waits to be acknowledged
Approval burned its authority and returned. If the host never received that response, the review was over and nothing said so. A final approved capture now commits one pending acknowledgement token and returns review.acknowledge-approved; restarted STATUS returns the same operation, arguments, token and live revision. Only that exact invocation burns. A wrong, stale or replayed one refuses and creates nothing.
The repository context is a digest again
The self-contained context carried its repository root, common directory and git directory as base64 JSON, under a capability the contract calls opaque. Measured on a live review it was 1017 bytes and appeared three times in one STATUS response: 35 percent of the payload. It is a 70-byte digest again, its preimage never leaves the package, and resolution takes the repository from the caller and re-derives the digest from the live identity. The previous check opened the repository at the path the token named and then asserted the opened path equalled it.
Refusals describe what happened
Three refusals said the wrong thing about themselves. An over-budget pre-edit forecast reported an unknown outcome and auto-filed a defect report for ordinary caller input, when nothing had been written. A replayed acknowledgement surfaced a raw filesystem error carrying an absolute path. A reviewer citation naming a candidate file by basename was refused as outside the frozen repository, and the refusal advertised a retry that reproduced forever because the reviewer is locked down.
A correction also became unresolvable when any untracked file appeared while it was made. The transition it switched to legitimately carries no validation request while the status still reports one, and the consistency check read that as a provider bug. The read-only failure envelope is content-free by design, so the lineage was stranded with a refusal that named nothing.
Also in this candidate
The SDD runtime narrows further: the declared artifact store is authoritative, phase agents read injected locators instead of detecting the store, the changed-line budget and phase result contract each gained one Go owner, and the ledger self-defence taxonomy collapsed to one typed refusal. Doctor classifies dangling ancestor symlinks, managed config symlink loops and unreadable managed paths. OpenCode bounds validator permissions and removes managed legacy tool grants. Release provenance is deterministic, and the trademark policy is written down.
Numbers
At publication, 702 issues are open: 52 opened and 39 closed since rc.1. Inflow exceeds outflow by 13; this candidate does not call that progress. Fifteen non-draft pull requests are open and none is included here.
Install
go install github.com/gentleman-programming/gentle-ai/v2/cmd/gentle-ai@v2.5.0-rc.2Or use the platform binaries: gentle-ai_2.5.0-rc.2_linux_amd64, gentle-ai_2.5.0-rc.2_linux_arm64, gentle-ai_2.5.0-rc.2_darwin_amd64, gentle-ai_2.5.0-rc.2_darwin_arm64, and gentle-ai_2.5.0-rc.2_windows_amd64.exe, plus gentle-ai-review-provider-contract-1.1.0.tar.gz. SHA256SUMS.txt covers all six payload artifacts.