From grill-each-other
Use when the fleet must formally sign off on an artifact — a converged grill result, a vault doc, an ADR, a convention, or a proposition — and one agent's or a pair's approval is not enough and you need fleet-wide consensus. Use when chaining ratification onto a finished grill, or when a decision needs N-agent attestation or approval with dissent recorded rather than overruled.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grill-each-other:fleet-ratifyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`fleet-ratify` gets N fleet agents to formally attest to an artifact. The
fleet-ratify gets N fleet agents to formally attest to an artifact. The
rule: nothing is ratified while a substantive objection stands — but
dissent does not kill the artifact, it triggers decomposition. The artifact is
immutable; ratification is an attestation layer over it, never a
re-sliced document.
It is the capstone of the grill-each-other pack. For two agents reconciling
state, use peer-grill. For fleet visibility without consensus, use
agent-show-and-tell. Reach for fleet-ratify only when a decision genuinely
needs the whole roster's signature.
grill-me, peer-grill, grill-with-docs) needs
fleet sign-off before it binds.Do not use for 2-agent reconciliation (peer-grill), for visibility
(agent-show-and-tell), or to manufacture agreement by headcount — quorum
voting is explicitly rejected (see 2026-05-16-fleet-ratification-design.md).
All state lives in .fleet-ratify/<topic>/ under the vault root. <topic> is
a kebab slug (default: the artifact filename stem; collisions get -b, -c).
| File | Writer | Purpose |
|---|---|---|
manifest.yaml | initiator | artifact ref + sha256, roster, expires_at, mode, status |
artifact.md | initiator | frozen verbatim snapshot — one file, one sha256, never edited |
<agent>.vote.yaml | only that agent | SIGN / DISSENT, attested sha256, dissent atom-refs |
decomposition.md | merge writer | aggregated dissent atom-refs + the human preview |
human-decision.yaml | the human | the grain-gate choice |
ratified.md | merge writer | terminal signed attestation manifest |
log.md | append-only, all | timestamped event log with agent identity |
Hard rules: an agent never edits another agent's vote.yaml; append-only
files are never rewritten; artifact.md is frozen at initiation.
Status ownership: the initiator writes status: open once. Thereafter
only the merge writer transitions it (open → pending-human → ratified | rejected). No other agent touches manifest.yaml.
One canonical kebab slug per agent (claude-code, neo, kimi-mbp,
opencode, …) — used identically in the agent: field, the vote.yaml
filename, and the roster. Source of truth: the fleet roster in
~/Documents/Coordination/. A group is not a voter — roster a specific
instance.
artifact.md (for an inline
proposition with no source file, write the proposition straight into
artifact.md — that file is the artifact). Hash it
(shasum -a 256 artifact.md); write manifest.yaml with the roster and
expires_at (default +72h, UTC). Log OPENED. Notify the roster (Discovery).artifact.md, verifies the sha256,
writes <agent>.vote.yaml — SIGN, or DISSENT with self-proposed
atom-refs. Agents do not read peers' votes first.expires_at passes. Non-voters become ABSTAIN_BY_TIMEOUT.SIGN → write ratified.md, log RATIFIED. Any dissent
or abstain → write decomposition.md, set status: pending-human, ping the
human.human-decision.yaml (see below).supersedes: <old-topic> in its manifest.ratified.md is written and
status: ratified. A reject (grain-gate choice, or any dissent under
mode: fast) writes no ratified.md — the terminal record is
status: rejected plus a REJECTED line in log.md.Merge writer = the agent whose slug sorts first alphabetically among
agents who actually voted (a no-show cannot deadlock the tally). The role is
determined at tally time, not reserved: any rostered agent that, on its
check, sees a complete roster (or a passed expires_at) computes the merge
writer and — if that is itself — runs the tally.
SIGN → ratified.DISSENT / ABSTAIN_BY_TIMEOUT → do not auto-recurse. The merge
writer aggregates dissenters' atom-refs into a decomposition preview and
hands it to the human. Atom-refs come only from dissenters' votes — the
merge writer never invents a split. It assigns stable A# (atom) / C#
(caveat) IDs during aggregation; votes carry only section+anchor.mode: fast (low-stakes): any dissent sets status: rejected directly — no
decomposition.md, no human-decision.yaml, no grain-gate. All-SIGN
still ratifies normally.On DECOMPOSED, the merge writer writes decomposition.md + a blank
human-decision.yaml stub, then sends a Telegram ping (alert only — no
state on the wire). The human sets decision: to one of:
accept-split · decompose-further · rewrite-with-caveats · reject.
The merge writer detects the filled file and resumes at step 6.
fleet-ratify check globs
.fleet-ratify/*/manifest.yaml for open ratifications where this agent is
rostered and has not voted. This always works; an agent that runs check
cannot miss a ratification. The merge writer runs tally on its own
check, so a run reaches a terminal state even with zero notifications.check still catches everything.Every protocol step appends one line to log.md:
[<ISO8601 UTC>] <agent> | <EVENT>: <detail>
Events: OPENED, NOTIFY, VOTE, TALLY, DECOMPOSED, PENDING-HUMAN,
CONVERGE, RATIFIED, REJECTED — plus the failure events in design-doc §11
(TIMEOUT, PARSE-FAIL, IDENTITY-COLLISION, SHA-MISMATCH,
HUMAN-TIMEOUT).
| Command | Does |
|---|---|
fleet-ratify init <artifact> --roster a,b,c | freeze artifact, open ratification |
fleet-ratify check | find ratifications awaiting this agent's vote |
fleet-ratify vote <topic> sign / dissent | cast this agent's vote |
fleet-ratify tally <topic> | merge writer: tally, decompose, or finalize |
The CLI is a convenience wrapper, not a dependency. If the fleet-ratify
commands are not installed (they ship as the JAC-22 helper scripts),
perform each Protocol step by hand — write the files directly per templates/.
The protocol, not the CLI, is the contract.
A signed manifest, not a sliced copy: the artifact_sha256; the ratified
atom-refs; a signature block (per signer: identity, timestamp, the one
artifact_sha256); and a caveat appendix where every caveat carries a
runnable verifier: or a tracked ticket:. A caveat with neither blocks
finalization. When the run passed through decomposition, ratified.md also
records the human-decision that produced it — so a contested-then-carved
ratification is never indistinguishable from an all-SIGN one.
| Mistake | Fix |
|---|---|
Editing artifact.md after initiation | It is frozen. Re-opening the topic is the only path to a changed artifact. |
| Signing "the gist" of a long doc | The signature attests an exact sha256. A mismatched hash is void — you cannot sign a vibe. |
| Merge writer slicing the artifact to build a "core" | Never. Atoms are span-refs; ratified.md references them. |
| Caveat written as a prose warning | Every caveat needs a runnable verifier: or a ticket:, or the artifact will not finalize. |
| Treating a quiet roster as consensus | A no-show is ABSTAIN_BY_TIMEOUT — a caveat for the human to weigh, never a silent yes. |
Full design + rationale: =notes/docs/plans/2026-05-16-fleet-ratification-design.md.
Templates: templates/. Run fleet-ratify --help for command detail.
Builds accessible UIs with shadcn/ui components on Radix UI + Tailwind CSS, plus canvas visuals. For React apps (Next.js, Vite, Remix, Astro), design systems, responsive layouts, themes, dark mode, prototypes.
2plugins reuse this skill
First indexed May 17, 2026
npx claudepluginhub jackreis/arbiter