* Add explicit rollback bootstrap and maintenance model * Certify alpha8 production and rollback tuples
10 KiB
Certification and promotion
Candidate gate
A candidate tuple is the complete set of client version or commit, Rails gem version or commit where applicable, exact OpenCode image, profile, and consumer commit. Changing any member invalidates the certification.
The gate requires:
- repository validation and the shared fixture corpus;
- exact
opencode-rubyandopencode-railscandidate checkouts, all Rails candidate tests on Ruby 3.2 through 4.0, an exact Rails-to-Ruby runtime dependency, and loaded Bundler provenance for the Ruby commit; - the public exact-image matrix against the deterministic model stub;
- an isolated custom-image canary for Ajent Rails and Mushu;
- the consumer's own focused and full required tests in its devcontainer;
- a user-visible canary turn for stream consumers;
- captured evidence including image ID/digest, server version, source commit, gem commits, timestamps, and probe outcome.
Health-only probes do not certify a tuple.
Client source provenance
Before publication, manifests/client-candidate.json must use
publication_state: unpublished and kind: commit for both clients. Each
provenance commit must equal its full 40-character checkout ref, and the Rails
Gemfile/runtime dependency must resolve the same exact Ruby commit and version.
Commit-only evidence is candidate evidence; it is not proof of a gem release.
The lockstep checkout fetches tags and fails unpublished mode if the matching
vVERSION tag appears, forcing the manifest through the published gate.
After publication, change the state to published and replace both commit
provenance objects with kind: annotated-tag, the exact tag, annotated tag
object ID, and peeled commit. The repository validator rejects a published
commit-only candidate. The lockstep job additionally verifies that each local
tag ref resolves to the declared annotated tag object and that both the object
and ref peel to the tested checkout. This transition is a reviewed manifest
change; CI does not create or publish tags.
The image matrix's active candidate coordinates must equal the client manifest.
Changing either commit resets the active matrix to pending. A
previous_certification preserves historical evidence but does not certify the
new candidate.
The shared live probe is intentionally strict: full_text must equal the
expected text byte-for-byte and the deterministic model must receive exactly
one request. A response that merely contains the expected text, including a
duplicated compat-ok\n\ncompat-ok, fails.
Promotion
Promotion is a reviewed manifest change that moves the old current tuple to
previous and the passing candidate to current. The consumer change is then
merged and deployed separately. Workflows in this repository have no deploy
credentials or deploy steps.
Use the repository promotion command; do not hand-edit the three tuple slots.
It binds evidence to a canonical SHA-256 of the complete tuple, requires full
consumer and gem commits, rejects mutable runtime image coordinates, and writes
the manifest with a same-filesystem atomic rename. The command only changes
manifests/runtime-tuples.json; it cannot deploy a consumer.
First inspect the fingerprints for both the candidate and rollback tuple:
ruby scripts/promote_runtime_tuple.rb fingerprint \
--consumer travelwolf \
--consumer-commit FULL_40_CHARACTER_CONSUMER_COMMIT
Commit one or more JSON evidence documents under evidence/. Each document
must explicitly contain values matching the promotion:
{
"schema_version": 1,
"consumer": "travelwolf",
"profile": "rails-persisted-turn",
"consumer_commit": "FULL_40_CHARACTER_CONSUMER_COMMIT",
"status": "pass",
"certified_at": "2026-07-18T12:00:00Z",
"tuple_sha256": "sha256:FULL_64_CHARACTER_FINGERPRINT"
}
The promotion command stores each accepted document as a hash-bound reference,
{"path":"evidence/...json","sha256":"sha256:..."}. Later transitions
re-read the bytes, verify that digest, and cross-check any detailed consumer
tree, client, and runtime coordinates against the tuple. Editing an evidence
document therefore invalidates the certification until it is reviewed and
promoted again; a copied tuple_sha256 alone is not sufficient.
Preview the exact manifest transition with --dry-run, then repeat without it
to write the manifest:
ruby scripts/promote_runtime_tuple.rb promote \
--consumer travelwolf \
--consumer-commit FULL_40_CHARACTER_CONSUMER_COMMIT \
--status pass \
--certified-at 2026-07-18T12:00:00Z \
--evidence evidence/travelwolf-candidate.json \
--previous-status pass \
--previous-certified-at 2026-07-17T12:00:00Z \
--previous-evidence evidence/travelwolf-rollback.json \
--dry-run
The --previous-* arguments are required while the old current tuple lacks a
valid certification record. Later promotions reuse and revalidate that record.
Both candidate and previous evidence must match the printed tuple fingerprint,
consumer, full consumer commit, timestamp, and pass status. A tag may be kept
only in a tag_provenance field; image, registry_ref, and base image fields
must use image@sha256:..., while a private local artifact may use an exact
docker_image_id.
An application canary and the shared deterministic contract prove different layers. For example, a consumer may instrument one application prompt without being able to observe the underlying model request. Record that distinction explicitly; do not infer a model request count from an application prompt count. The exact-image shared contract supplies the model-request proof.
Likewise, the public image job executes ruby-rest-sse; it does not silently
certify Rails persistence, plugin hooks, voice streaming, strict route gates,
or provider hooks. Those appear as required_consumer_profiles in the image
matrix and need their own consumer evidence before a full tuple can pass.
The companion lockstep job proves that the exact Rails candidate loads and tests against the exact Ruby candidate on every supported Ruby version. That still does not certify a consumer's ActiveRecord schema, persistence callbacks, container adapter, or application canary; those remain consumer-owned profile evidence.
GitHub CI writes canonical JSON artifacts for the shared fixture, lockstep client, and each exact-image target. Artifact retention is 30 days and supplies reviewable workflow provenance; it is not the long-term ledger. Gitea executes the same contracts, with its exact-image targets run sequentially from the full generated manifest, but its installed artifact service cannot accept the reviewed GitHub upload action. Gitea therefore keeps generated JSON transient and makes no artifact-evidence claim. After reviewing a GitHub artifact, copy the relevant facts into a repository evidence document bound to the complete tuple fingerprint. Automated workflows never update certified evidence or promote a tuple.
The command clears candidate after promotion. It sets the repository-wide
migration_state to certified only after every consumer has certified
current and previous tuples and no pending candidate.
Bootstrap with a failing baseline
If the observed production baseline fails the current contract, keep its full
coordinates for emergency recovery but mark it failed. Do not create passing
evidence for it and do not promote it into previous. The promoter rejects
known-failed baselines even if a document claims pass.
The safe bootstrap is two-stage: certify and roll out the new candidate, then
create and canary a distinct consumer rollback commit that preserves the same
known-good client and exact runtime. Only after both immutable consumer commits
have real passing evidence can the manifest honestly contain certified
current and previous tuples. Until then, promotion_readiness remains
non-certified (bootstrap-current-only or candidate) and the candidate PR
must not be treated as deploy authorization.
Use the explicit degraded-bootstrap transition for the first passing rollback
tuple. It requires passing evidence bound to the complete candidate fingerprint
and a literal acknowledgement; it preserves the failed baseline as uncertified
emergency_provenance, leaves previous null, and records the temporary
bootstrap-current-only state:
ruby scripts/promote_runtime_tuple.rb bootstrap-current \
--consumer travelwolf \
--consumer-commit FULL_40_CHARACTER_ROLLBACK_COMMIT \
--status pass \
--certified-at 2026-07-20T12:00:00Z \
--evidence evidence/travelwolf-rollback.json \
--acknowledge-degraded-rollback \
accept-degraded-rollback-with-failed-emergency-provenance \
--dry-run
Review the dry run, repeat without --dry-run, and then treat that passing
tuple as the base for a normal promotion. Normal promotion moves it into
previous, removes the degraded rollback marker, and keeps the original failed
baseline only as historical emergency provenance. The repository becomes
certified only when every consumer has exact passing current and previous
tuples. Never use bootstrap to replace an existing previous tuple or to certify
a baseline already known to fail.
Rollback
Rollback restores the whole previous tuple. Do not roll back only the gem or
only the runtime image: the wire contract is the unit of compatibility.
For a custom image, retain its immutable registry digest or Docker image ID and the source commit used to build it. A source tag alone is insufficient.
Custom-image canary
Run the shared live contract on a host that can pull the exact image:
BUNDLE_GEMFILE=/path/to/opencode-ruby/Gemfile \
OPENCODE_RUBY_PATH=/path/to/opencode-ruby \
OPENCODE_RUBY_COMMIT=FULL_40_HEX_COMMIT \
OPENCODE_IMAGE='registry.example/image@sha256:...' \
bundle exec scripts/run_image_contract.sh
The Ruby checkout must be clean and its HEAD must equal
OPENCODE_RUBY_COMMIT. Install Bundler dependencies outside that checkout when
the normal cache path would create untracked files.
If an older private registry cannot expose an OCI repository digest, set
ALLOW_EXACT_IMAGE_ID=1 and pass the locally present sha256:... image ID.
Record the registry tag, image ID, source commit, and reason a repository
digest was unavailable in the evidence.