Conformance and evidence
How do you know a release is good? The 3.0.0 release shipped with test evidence: 31 out of 31 checks passed on both live hosts, 18 out of 18 planted refusal controls refused, and the record is signed and tied to the exact source commit.
Try it. The evidence record ships in the Guild Stack repo at the release tag. Read it yourself:
git clone -q https://github.com/lookatitude/guild.git guild
git -C guild checkout -q v3.0.0
head -20 guild/.guild/artifacts/release/v3.0.0/conformance.json
This page shows the whole chain. The Power layer is the release model — how a version moves from beta to stable. The Architect layer is the evidence itself: what it proves, who signs it, and the identity records.
As a user you rarely touch any of this directly: its results reach you as the version you install and the evidence behind it. The process below is how the release is produced.
The release model
Guild Stack ships from two branches of the plugin repository. main holds the stable version; next holds the dev version.
| Branch | Version shape | Channel |
|---|---|---|
main | bare X.Y.Z | stable |
next | X.Y.Z-beta.N | beta |
A release needs no extra operator branch, no App credential, no environment gate, and no manual sync-back.
Current state. v3.0.0 is the current stable release. Tag v3.0.0 peels to the next→main merge commit fbb3ac880cb8, and the five version-bearing manifests on main carry bare 3.0.0. After the release, next reopened at 3.1.0-beta.1, with the whole version surface regenerated.
The cycle: cut → evidence → promotion → dev bump
1. Cut
A release starts with a release-cut PR into next. It changes only the version surface, to bare X.Y.Z. The merge SHA of that PR is the evidence source commit.
One command covers the whole version surface. Edit .claude-plugin/plugin.json, then run npm run sync:claude-install. It regenerates every version-bearing file, including .codex-plugin/plugin.json. When the surface is stale, the gate names that command.
For v3.0.0, one follow-up fix landed after the cut, so the evidence source commit is 9ad483d6.
2. Evidence
Evidence is built at the cut and lands through an evidence-only PR. Before promotion, that PR needs green CI, a reconciled internal design set, and a PR body confirmed as the release notes. What the evidence contains is in Conformance evidence, below.
3. Promotion
The promotion gate refuses two things:
- a beta manifest, with
manifest_version_not_release; - evidence not built at that exact bare version, with
source_version_not_release.
One legacy exception remains: a version that is exactly 2.7.0-beta.N is still checked against the frozen v2.7.0 evidence, not against its own.
The release PR goes from the same-repository, exact next branch to main. It merges with a merge commit. Squash and rebase are invalid, because the evidence-bound source commit must stay an ancestor of main.
On that PR, CI:
- requires the merged tree to equal the reviewed
nexttree; - re-runs the promotion evidence;
- reads the tag from the bare manifest;
- tags the exact merge commit;
- publishes the PR body as the GitHub Release.
CI never commits or pushes to main or next.
A bare release derives a non-empty release-id suffix from the version itself. Bare 3.0.0 gives rel-<day>-300. The source-twin re-derivation uses the same helper.
4. Dev bump
A dev-version bump PR reopens next at the next dev target, for example X.(Y+1).0-beta.1 or the next major. Until it merges, channel-integrity accepts a shared bare version only while main is tagged and the next tree equals it. So code PRs into next are blocked until the bump lands. For v3.0.0 that bump has already landed.
Mechanical enforcement
For Guild Stack maintainers. You do not need to do any of this to use Guild Stack.
branch-policy.ymlrejects any PR intomainwhose head is not the same-repository, exactnextbranch. All forks are rejected.- The checked-in
.githooks/pre-pushhook refuses direct pushes tomainandnext. Enable it withgit config core.hooksPath .githooks. The emergency bypass isGUILD_ALLOW_PUSH_MAIN=1.
Operator runbook (maintainers only)
These are the steps a Guild Stack maintainer follows to cut a release. Users do not run them.
- Cut:
prepare,build:inventory,sync:claude-install,build:hosts --sync-native-identity; commit the five version-bearing files. - Open the evidence-only PR. Confirm green CI, a reconciled internal design set, and the PR body as release notes.
- Run the channel-integrity check in promotion mode.
- Open the next→main merge-commit PR.
- Verify the tag and the GitHub Release.
- Open the dev bump PR.
Conformance evidence
This section says what the v3.0.0 evidence contains and what the conformance decision accepts.
The v3.0.0 evidence record
The promotion evidence lives on plugin main at:
.guild/artifacts/release/v3.0.0/conformance.json
.guild/artifacts/release/v3.0.0/promotion.jsonIt records:
- genuine 31/31 activated-host captures on both live hosts, Claude Code and Codex;
- 18/18 planted refusal controls refusing;
- signatures from all three rotated attestors, each made with a single-use signing key (named
k1); - a hash binding to source commit
9ad483d6.
It reached main through the evidence-only PR described in Evidence. Who held the signing keys is in Attestation and custody, below.
The conformance decision
The production conformance decision admits the full fixed set of 31 conformance scenarios: the list cannot change between capture and promotion. It re-judges outcome type and disposition across the whole suite.
- "Passed or explicitly refused" is the only conformant outcome for an extension scenario.
- Recognized runtime majors are the closed set
{2, 3}. Aguild-4.xruntime is refused.
Source identity
Each activated-host capture stages a blob-verified plugin-source twin at exactly the attested commit. The record type is guild.plugin_source_identity.v1, and verify enforces it.
The module-boundary check (the evaluator that owns 4 of the 31 scenarios and checks that dependencies respect public module interfaces and policy-ownership boundaries) models the post-fold src/domains tree. It fails closed on a mixed tree.
Host activation
- Claude Code. The capture launcher declares
GUILD_ACTIVATION_CHANNEL=betafrom the attested release. The SessionStart hook mints a launcher-declared beta receipt only under that declaration. The verifier no longer accepts the retired check that guessed the channel from the version string alone. - Codex. The activation probe targets the reshaped
guild:guild-qualityskill. The oldverify-doneprobe path no longer exists. The probe tolerates exactly one trailing newline.
Attestation and custody
This section says what the three attestor signatures in the evidence record show, and what they do not show.
The trust root
The attestor trust root is rotated to three production verification roots. The attestor ids are unchanged.
The old test-era roots are kept only as a record of the trust root that came before. They can no longer admit new evidence.
Custody deviation
The repository records a custody deviation for these keys:
principal: operator-sole-principal
external_custody_verified: falseRead this literally. One operator is the sole principal, and independent custody of the attestor keys is not verified. So the three signatures in the evidence record do not, on their own, show that three independent parties held those keys.
No private key material is in the repository.
Dependency posture at release
js-yaml ^4.3.2 clears GHSA-2883-xcg3-v3hh. npm audit --audit-level=high exits 0 in all five workspaces. All committed bundles were rebuilt from the new lockfiles.
Identity records
Each identity record verified for v3.0.0 is stated once on this page:
- Which code: Source identity.
- Which host: Host activation.
- Which runtime: the runtime majors in The conformance decision.
- Which release: the release-id suffix in Promotion.
Dispatch
Lane dispatch is covered on Teams and specialists, and the run record layout on Runs and operations. Their v3.0.0 behavior is not yet verified at this level, so this section states only the verified identity records.