Ballot
Durable decision artefact for decisions that happen async — reviewed over chat, on a pull request, after the agent session ends. Tiered into Must / Should / Could horizons, with an empty checkbox per option. One file per decider (per reviewer when there are several). Reconciliation happens in the sessionlog; the ballot is what survives.
Extracted from the dossier skill — pairs with it when SYNTHESIZE produces decisions needing extraction, and stands alone anywhere a decision leaves the immediate session: ADRs, architecture calls, hiring panels, vendor selection, household decisions, PR review handoffs.
When to Use
- Decider(s) look at the decision outside the agent session — chat handoff, PR review, async sign-off, remote collaboration. Single-decider async is still ballot-worthy; the structure survives 12-hour-later reading and multi-dossier listings. Multiple reviewers get per-reviewer files; a single async decider gets one file.
- The decision has a durable consequence worth capturing in version control — ADRs, architecture calls, hiring panels, vendor selection, PR review, household commitments.
- Decisions have mixed urgency — some block delivery, some are directional, some are informational. The Must/Should/Could tiers encode that.
- The decision surface benefits from a format that reads sensibly on a phone: empty checkboxes, one question per DEC, tiered by urgency rather than time-horizon.
When NOT to Use
- Decider is in the session right now and the decision fits in chat. Ask and write the outcome in a sessionlog.
- Low-stakes vote with no durable consequence (lunch options).
- Decision surface is not yet framed. Frame first; ballot once options are real.
- Ongoing reconciliation. Ballots are point-in-time; ongoing discussion lives in its own venue (sessionlog, meeting notes).
Workflow
- Frame the decisions. For each DEC, one decision surface, one time-horizon, at least two real options. Tag Must / Should / Could.
- Create one ballot file per decider. Filename:
DOSSIER-<slug>-BALLOT-<Reviewer>.md. Multiple reviewers → one file each. Single async decider → one file (the reviewer field holds that decider's name). The DOSSIER- prefix keeps the ballot next to any companion context doc in a file listing even when the ballot is standalone — see §Standalone vs. Dossier-invoked.
- Prose-recommend per DEC, but leave checkboxes empty. A pre-ticked box is pressure, not a recommendation.
- Hand off the ballot. Post the link in the channel the decider(s) will see it; commit the file so it survives the session.
- Reconcile in the sessionlog. Walk each DEC, note where decider(s) ticked or where reviewers split, record the decided outcome. Reconciliation is a session output, not a third ballot file.
Template: ${CLAUDE_SKILL_DIR}/templates/ballot-per-reviewer.md.
Conventions
These rules are empirical — each came from a concrete ballot that went wrong before it was fixed. Full rationale: ${CLAUDE_SKILL_DIR}/references/ballot-conventions.md.
- One file per decider. Do NOT create a single-file multi-column ballot. For multi-reviewer ballots, scrolling past peer columns on a phone is cramped. For single-decider async, a multi-column layout is just noise. Enforced by
ballot-filename.sh — the filename must end -BALLOT-<Reviewer>.md.
- Clean cover block. Reviewer, role, (peer-ballot link if multi-reviewer), dossier/context link. Nothing else. No "updated 2026-04-18" paragraph, no changelog, no "changes since previous version". Archaeology belongs in the commit log and sessionlog.
- Recommended-but-not-pre-ticked. A DEC can have a prose recommendation (
*Recommended: Option B — one-line why.*), but checkboxes stay empty. The reviewer's tick is the decision.
- One DEC = one decision surface = one time-horizon. Do not mix "launch-day channels" with "next year's CFP commitments" in a single multi-select.
- No anti-options. If you added an option labelled "not recommended" or "for completeness", either add a
<!-- justify: ... --> comment (e.g. the option has political visibility) or delete it. Anti-options cost reviewer ticking-time without changing outcomes.
- Must / Should / Could tiers. Must blocks delivery. Should blocks only if reviewers disagree (or a single async decider flags dissent). Could is informational. If the Must tier has unresolved disagreement at delivery time, flag in the sessionlog — the ballot skill does not ship a hard gate for this (too fragile to parse).
- Reconciliation in the sessionlog. Not in a third file. Ballots are durable; reconciliation is session-scoped.
Use Cases
Each is a 2-3 line sketch of how the template adapts.
- ADR voting. Senior engineers approve an architectural decision. Must tier = the chosen architecture; Could tier = migration preferences. Dossier optional; the ADR itself can be the context doc.
- Architecture call reconciliation. Whiteboard session ended contested. Ballot captures the surviving options per sub-decision, each reviewer ticks over the following week, reconciliation at the next standup.
- PR review handoff. Agent session produces a change set; reviewer will look at the PR after hours. Ballot captures the decision surfaces (approve / request-changes per thread, merge strategy, release-note wording). Reviewer ticks on the train; reconciliation lands in the sessionlog once the PR merges.
- Hiring panel. Must = ship offer / reject / more-interview. Should = role scoping (seniority band, onboarding pairing). Could = onboarding prefs. Compensation stays out of the ballot body — keep it in the offer doc.
- Vendor selection. Must = which vendor (one option per vendor). Should = contract term, payment schedule. Could = optional add-ons. Dossier provides the comparison table; ballot captures commitments.
- Household decision. Max + partner choosing among options (holiday, appliance, move-date). Low-stakes but the ballot mechanism scales down — two Must items is plenty.
Reviewing a ballot
Ballots are reviewed against ${CLAUDE_SKILL_DIR}/references/review-checklist.md. The checklist covers filename pattern, cover-block cleanliness, anti-options, time-horizon-per-DEC, recommended-but-not-pre-ticked, tier discipline, async-readability, and reconciliation location.
One mechanical gate. ballot-filename.sh fires PostToolUse on Write|Edit for files matching DOSSIER-*BALLOT*.md and fails on anything not matching DOSSIER-<slug>-BALLOT-<Reviewer>.md. Alerting level, not true blocking — the file is already on disk when the hook fires; exit 2 feeds stderr back to Claude, which usually corrects. Everything else is reviewed by checklist, not by grep: the other concerns (cover-block archaeology, anti-options, dated claims, scope coherence) don't generalize cleanly across dossier styles, and a judgement-capable reviewer catches them more reliably than a pattern match.
Must-tier "blocks delivery" is a convention, not a gate. A ballot-state parser to detect final-status-with-unticked-Must would be too fragile (requires reconstructing reviewer intent). Flag in the sessionlog if a Must item is unresolved at delivery time.
Standalone vs. Dossier-invoked
Standalone. For ADRs, architecture calls, hiring, vendor selection, household decisions. The DOSSIER- filename prefix stays — it keeps ballots grouped with any companion documents and makes the gates fire. No dossier file needs to exist; the cover-block "Full dossier" link can point to a meeting notes doc, an ADR markdown file, or be omitted.
Dossier-invoked. When a dossier SYNTHESIZE surfaces decisions needing per-reviewer sign-off, the dossier skill points at this skill's template and conventions. The dossier owns the research; the ballot owns the decision surface. See skills/dossier/SKILL.md §SYNTHESIZE.
Related Skills
| Skill |
Integration |
dossier |
Primary caller. Dossier research produces decisions; ballot extracts them. |
bye |
Reconciliation lives in the sessionlog — same sessionlog /bye builds at session end. |
commit-notation |
D: prefix for ballot commits when delivered with a dossier; otherwise commit-intention matches the parent artefact (e.g. F: for an ADR, D: for a hiring decision doc). |
Common Mistakes
| Mistake |
Fix |
| Single-file ballot with two reviewer columns |
One file per reviewer — DOSSIER-*-BALLOT-<Reviewer>.md |
| Cover block with "updated 2026-…" or changelog paragraph |
Commit log holds history; cover block holds reviewer/role/links only |
| Pre-ticked checkbox as "recommendation" |
Use prose: *Recommended: Option B.* Checkboxes stay empty |
| Mixing time-horizons in one DEC |
Split into two DECs (e.g. DEC-003 launch-day, DEC-004 next-year) |
| Anti-option listed for completeness |
Either justify (<!-- justify: ... -->) or delete |
| Reconciliation as a third file |
Reconciliation lives in the sessionlog, not a DOSSIER-*-RECONCILE.md |
| Must-tier item unresolved, delivery called complete |
Flag in sessionlog; no gate enforces this |
1---2name: ballot3description: Use when decisions happen async — reviewer(s) look at it over chat, on a PR, on a train, or any time outside the agent session. Triggers: async decision, PR review, pull request, remote reviewer, handoff, away-from-keyboard, decision ballot, architecture call, architecture decision record, ADR, hiring panel, vendor selection, household decision, reconcile, per-reviewer, tick box, ballot.4license: MIT5---67# Ballot89Durable decision artefact for decisions that happen async — reviewed over chat, on a pull request, after the agent session ends. Tiered into Must / Should / Could horizons, with an empty checkbox per option. One file per decider (per reviewer when there are several). Reconciliation happens in the sessionlog; the ballot is what survives.1011Extracted from the `dossier` skill — pairs with it when SYNTHESIZE produces decisions needing extraction, and stands alone anywhere a decision leaves the immediate session: ADRs, architecture calls, hiring panels, vendor selection, household decisions, PR review handoffs.1213## When to Use1415- Decider(s) look at the decision outside the agent session — chat handoff, PR review, async sign-off, remote collaboration. Single-decider async is still ballot-worthy; the structure survives 12-hour-later reading and multi-dossier listings. Multiple reviewers get per-reviewer files; a single async decider gets one file.16- The decision has a durable consequence worth capturing in version control — ADRs, architecture calls, hiring panels, vendor selection, PR review, household commitments.17- Decisions have mixed urgency — some block delivery, some are directional, some are informational. The Must/Should/Could tiers encode that.18- The decision surface benefits from a format that reads sensibly on a phone: empty checkboxes, one question per DEC, tiered by urgency rather than time-horizon.1920## When NOT to Use2122- Decider is in the session right now and the decision fits in chat. Ask and write the outcome in a sessionlog.23- Low-stakes vote with no durable consequence (lunch options).24- Decision surface is not yet framed. Frame first; ballot once options are real.25- Ongoing reconciliation. Ballots are point-in-time; ongoing discussion lives in its own venue (sessionlog, meeting notes).2627## Workflow28291. **Frame the decisions.** For each DEC, one decision surface, one time-horizon, at least two real options. Tag Must / Should / Could.302. **Create one ballot file per decider.** Filename: `DOSSIER-<slug>-BALLOT-<Reviewer>.md`. Multiple reviewers → one file each. Single async decider → one file (the reviewer field holds that decider's name). The `DOSSIER-` prefix keeps the ballot next to any companion context doc in a file listing even when the ballot is standalone — see §Standalone vs. Dossier-invoked.313. **Prose-recommend per DEC, but leave checkboxes empty.** A pre-ticked box is pressure, not a recommendation.324. **Hand off the ballot.** Post the link in the channel the decider(s) will see it; commit the file so it survives the session.335. **Reconcile in the sessionlog.** Walk each DEC, note where decider(s) ticked or where reviewers split, record the decided outcome. Reconciliation is a session output, not a third ballot file.3435Template: `${CLAUDE_SKILL_DIR}/templates/ballot-per-reviewer.md`.3637## Conventions3839These rules are empirical — each came from a concrete ballot that went wrong before it was fixed. Full rationale: `${CLAUDE_SKILL_DIR}/references/ballot-conventions.md`.4041- **One file per decider.** Do NOT create a single-file multi-column ballot. For multi-reviewer ballots, scrolling past peer columns on a phone is cramped. For single-decider async, a multi-column layout is just noise. Enforced by `ballot-filename.sh` — the filename must end `-BALLOT-<Reviewer>.md`.42- **Clean cover block.** Reviewer, role, (peer-ballot link if multi-reviewer), dossier/context link. Nothing else. No "updated 2026-04-18" paragraph, no changelog, no "changes since previous version". Archaeology belongs in the commit log and sessionlog.43- **Recommended-but-not-pre-ticked.** A DEC can have a prose recommendation (`*Recommended: Option B — one-line why.*`), but checkboxes stay empty. The reviewer's tick is the decision.44- **One DEC = one decision surface = one time-horizon.** Do not mix "launch-day channels" with "next year's CFP commitments" in a single multi-select.45- **No anti-options.** If you added an option labelled "not recommended" or "for completeness", either add a `<!-- justify: ... -->` comment (e.g. the option has political visibility) or delete it. Anti-options cost reviewer ticking-time without changing outcomes.46- **Must / Should / Could tiers.** Must blocks delivery. Should blocks only if reviewers disagree (or a single async decider flags dissent). Could is informational. If the Must tier has unresolved disagreement at delivery time, flag in the sessionlog — the ballot skill does not ship a hard gate for this (too fragile to parse).47- **Reconciliation in the sessionlog.** Not in a third file. Ballots are durable; reconciliation is session-scoped.4849## Use Cases5051Each is a 2-3 line sketch of how the template adapts.5253- **ADR voting.** Senior engineers approve an architectural decision. Must tier = the chosen architecture; Could tier = migration preferences. Dossier optional; the ADR itself can be the context doc.54- **Architecture call reconciliation.** Whiteboard session ended contested. Ballot captures the surviving options per sub-decision, each reviewer ticks over the following week, reconciliation at the next standup.55- **PR review handoff.** Agent session produces a change set; reviewer will look at the PR after hours. Ballot captures the decision surfaces (approve / request-changes per thread, merge strategy, release-note wording). Reviewer ticks on the train; reconciliation lands in the sessionlog once the PR merges.56- **Hiring panel.** Must = ship offer / reject / more-interview. Should = role scoping (seniority band, onboarding pairing). Could = onboarding prefs. Compensation stays out of the ballot body — keep it in the offer doc.57- **Vendor selection.** Must = which vendor (one option per vendor). Should = contract term, payment schedule. Could = optional add-ons. Dossier provides the comparison table; ballot captures commitments.58- **Household decision.** Max + partner choosing among options (holiday, appliance, move-date). Low-stakes but the ballot mechanism scales down — two Must items is plenty.5960## Reviewing a ballot6162Ballots are reviewed against `${CLAUDE_SKILL_DIR}/references/review-checklist.md`. The checklist covers filename pattern, cover-block cleanliness, anti-options, time-horizon-per-DEC, recommended-but-not-pre-ticked, tier discipline, async-readability, and reconciliation location.6364**One mechanical gate.** `ballot-filename.sh` fires PostToolUse on `Write|Edit` for files matching `DOSSIER-*BALLOT*.md` and fails on anything not matching `DOSSIER-<slug>-BALLOT-<Reviewer>.md`. Alerting level, not true blocking — the file is already on disk when the hook fires; exit 2 feeds stderr back to Claude, which usually corrects. Everything else is reviewed by checklist, not by grep: the other concerns (cover-block archaeology, anti-options, dated claims, scope coherence) don't generalize cleanly across dossier styles, and a judgement-capable reviewer catches them more reliably than a pattern match.6566Must-tier "blocks delivery" is a convention, not a gate. A ballot-state parser to detect final-status-with-unticked-Must would be too fragile (requires reconstructing reviewer intent). Flag in the sessionlog if a Must item is unresolved at delivery time.6768## Standalone vs. Dossier-invoked6970**Standalone.** For ADRs, architecture calls, hiring, vendor selection, household decisions. The `DOSSIER-` filename prefix stays — it keeps ballots grouped with any companion documents and makes the gates fire. No dossier file needs to exist; the cover-block "Full dossier" link can point to a meeting notes doc, an ADR markdown file, or be omitted.7172**Dossier-invoked.** When a `dossier` SYNTHESIZE surfaces decisions needing per-reviewer sign-off, the dossier skill points at this skill's template and conventions. The dossier owns the research; the ballot owns the decision surface. See `skills/dossier/SKILL.md` §SYNTHESIZE.7374## Related Skills7576| Skill | Integration |77|-------|-------------|78| `dossier` | Primary caller. Dossier research produces decisions; ballot extracts them. |79| `bye` | Reconciliation lives in the sessionlog — same sessionlog `/bye` builds at session end. |80| `commit-notation` | `D:` prefix for ballot commits when delivered with a dossier; otherwise commit-intention matches the parent artefact (e.g. `F:` for an ADR, `D:` for a hiring decision doc). |8182## Common Mistakes8384| Mistake | Fix |85|---------|-----|86| Single-file ballot with two reviewer columns | One file per reviewer — `DOSSIER-*-BALLOT-<Reviewer>.md` |87| Cover block with "updated 2026-…" or changelog paragraph | Commit log holds history; cover block holds reviewer/role/links only |88| Pre-ticked checkbox as "recommendation" | Use prose: `*Recommended: Option B.*` Checkboxes stay empty |89| Mixing time-horizons in one DEC | Split into two DECs (e.g. DEC-003 launch-day, DEC-004 next-year) |90| Anti-option listed for completeness | Either justify (`<!-- justify: ... -->`) or delete |91| Reconciliation as a third file | Reconciliation lives in the sessionlog, not a `DOSSIER-*-RECONCILE.md` |92| Must-tier item unresolved, delivery called complete | Flag in sessionlog; no gate enforces this |