Agent tickets stay open until a human replays the claim. Green text from a model is not proof. A second person must rerun the named command on the claimed commit. Only that receipt may close the ticket.
Cheap drafts make this gate feel slow. It is the opposite of waste. Volume without replay turns a sprint into theater. The floor looks busy. The branch still lies.
Modern agent sessions write tests, logs, and tidy summaries. They paste a passing trace into the ticket. Reviewers skim the story and move on. Nobody reruns the path on the claimed SHA. The bug returns on Monday like a bounced check.
A bank teller does not accept a handwritten total. The teller counts the drawer again. Agent work needs the same second count. Call that count a replay receipt.
The replay desk is a short shift, not a ceremony. One human owns the claim. A different human owns the replay. A desk lead can freeze closes when receipts go missing. Those three roles keep the lane honest.
The claimant never replays their own agent run. Familiarity hides skipped setup and quiet flags. A teammate checks out the SHA instead. They run the exact command written on the card. They file the receipt beside the ticket before anyone hits close.
Handoff is a card, not a chat ping. Chat evaporates after standup and shift change. The wiki keeps the SHA, the command, and the clock. The next replay owner can start cold without hunting scrollback.
Kitchen passes work the same way during a rush. The expo does not plate from a shouted status. The ticket stays in the window until the dish matches the order. Agent tickets deserve that same window. Generated narrative is the shout. Replay is the plate.
Paste this one-page run into the team wiki. Keep the wording boring and identical on every close. Novelty here is a defect, not a craft.
# Replay Desk — Close Gate
Ticket: T-____
Claimed SHA: ________
Claimed command (copy exactly):
________
Expected signal: exit 0 and the named test file
Claimant (ran the agent): @____
Replay owner (must be a different human): @____
Desk lead (may freeze closes): @____
Replay steps
1. Refuse a dirty worktree.
2. Detach at the claimed SHA.
3. Run only the claimed command.
4. Write replay-receipt.txt beside the ticket.
5. Close only if the receipt shows exit 0.
Freeze
If the SHA, command, or owner is blank, do not close.
If claimant equals replay owner, do not close.
If the command differs from the card, do not close.
The card is the contract. The script is the counter. Teams that skip the script start negotiating with memory. Memory is how fake-green work survives a busy afternoon.
Run the replay from a clean clone, not the claimant laptop. Shared laptops hide env files and leftover daemons. A throwaway worktree makes the second count mean something.
#!/usr/bin/env bash
# replay-receipt.sh — second count for an agent claim
set -euo pipefail
SHA="${1:?claimed sha}"
CMD="${2:?claimed command}"
TICKET="${3:?ticket id}"
OUT="${TICKET}-replay-receipt.txt"
if [[ -n "$(git status --porcelain)" ]]; then
echo "dirty worktree; refuse replay" >&2
exit 2
fi
git cat-file -t "$SHA" >/dev/null
git switch --detach "$SHA"
START="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
HOST="$(hostname)"
USER_NAME="$(id -un)"
set +e
bash -lc "$CMD"
STATUS=$?
set -e
{
echo "ticket=$TICKET"
echo "sha=$SHA"
echo "cmd=$CMD"
echo "started_utc=$START"
echo "host=$HOST"
echo "replay_user=$USER_NAME"
echo "exit=$STATUS"
} > "$OUT"
git hash-object "$OUT" >> "$OUT"
echo "wrote $OUT with exit $STATUS"
exit "$STATUS"
Call it with three arguments and nothing else. Extra flags become a second story. Second stories are how tickets close on hope.
chmod +x replay-receipt.sh
./replay-receipt.sh 9f3c1aa "npm test -- src/billing.test.ts" T-1842
A Python helper can refuse a self-signed close. It reads the card fields from the environment. It exits nonzero when the claimant and replay owner match. Put it in the same directory as the shell script.
#!/usr/bin/env python3
import os
import sys
claimant = os.environ.get("CLAIMANT", "").strip()
replay = os.environ.get("REPLAY_OWNER", "").strip()
sha = os.environ.get("CLAIMED_SHA", "").strip()
cmd = os.environ.get("CLAIMED_CMD", "").strip()
problems = []
if not sha or not cmd:
problems.append("blank sha or command")
if not claimant or not replay:
problems.append("blank owners")
if claimant and claimant == replay:
problems.append("claimant cannot replay")
if problems:
print("refuse close: " + "; ".join(problems))
sys.exit(2)
print("owners and claim fields look complete")
Wire the helper in front of the close button, not after. After is decoration. Before is a gate. A one-line check in CI can read the receipt file and fail the close job when exit= is missing.
test -f T-1842-replay-receipt.txt
grep -q '^exit=0$' T-1842-replay-receipt.txt
Desk lead duty is narrow on purpose. The lead does not rerun every claim. The lead watches for missing receipts and frozen cards. Two missing receipts in a day is a freeze, not a scolding. Freeze means closes stop until the card is filled.
Announce the freeze in the same wiki page. Do not bury it in a private message. Private freezes create a second floor with different rules. Two floors is how agent theater returns.
FREEZE 2026-09-19T16:00Z
Reason: two closes lacked replay receipts
Owner: desk lead
Lift when: next two tickets carry exit=0 receipts
This SOP is for teams that already generate a lot of agent drafts. Free model access and a free server option raise that volume without raising proof. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Teams drafting on MonkeyCode can keep that lane and still stamp the receipt on close.
The receipt does not certify product quality. It certifies that a named command ran on a named commit. Flaky tests will fail the honest replay. That failure is useful. It stops a story from standing in for a run.
Nondeterministic suites need a tighter command. Point the card at one file, not the whole repository. Broad commands hide the skip. Narrow commands make the second count cheap enough to keep.
Do not treat the receipt as a security review. Secrets, auth, and data deletes need their own owners. A green unit file can still wreck a tenant. Replay is a close gate, not a launch gate.
Do not run secret-bearing jobs on a shared free server under this card alone. The card assumes the command is safe to replay. Unsafe commands belong in an isolated job with their own owners. This playbook will not invent that isolation for you.
Solo developers should not fake a second owner. A rubber-stamp alias is worse than no card. The whole point is a different pair of hands. If those hands do not exist, leave the ticket open.
Incident commanders should not open a replay desk mid-fire. Restore service first. After the fire, replay the claimed fix on the SHA that actually shipped. Dating the receipt after the incident is honest. Dating it before is fiction.
Hardware-only checks may not replay on a laptop. Say that on the card in one line. Name the bench, the fixture, and the person who stood there. A missing bench line is a freeze, not a workaround.
The common failure is a rewritten command. The claimant trims flags after the agent run. The replay then tests a different path. Lock the command string at claim time. If the command must change, open a new ticket.
Another failure is SHA drift. The agent amends after the paste. The ticket still shows the old hash. Replay then proves yesterday. Require git rev-parse HEAD in the agent log and on the card. Mismatched hashes refuse the close.
A third failure is receipt theater. Someone copies an old file and changes the ticket id. The hash-object line makes that noisier. It is not cryptography for a court. It is friction against a sleepy paste.
Keep the desk on a weekday hour with overlap. Overnight agent bursts can wait for the morning replay. Speed of draft is not speed of done. Done is the second count.
Train the roles with one dry run on a throwaway ticket. Use a known failing test first. Confirm the script refuses the close. Then use a known passing test. Confirm the receipt file appears. Skip this drill and the freeze will feel personal later.
# dry run: expect nonzero, no close
./replay-receipt.sh "$SHA" "npm test -- src/known-fail.test.ts" T-DRY
# dry run: expect exit 0 and a receipt
./replay-receipt.sh "$SHA" "npm test -- src/known-pass.test.ts" T-DRY2
Write the drill date on the wiki page. A card nobody has run is costume. Costume is how vibe output gets called engineering. The floor does not need more costume.
Limit the SOP to agent-touched tickets. Human-only changes can keep the old close path. Mixing both paths on day one creates loopholes. Loopholes become the real process by Friday.
Review the freeze log once a week, not daily. Daily review turns the desk into surveillance. Weekly review catches a pattern. Patterns mean the claimed commands are too wide, or the owners are the same person.
The close gate will annoy people who ship stories. That annoyance is the signal. If closes feel identical to agent paste, the desk is dead. Revive it by refusing one ticket in public and filing the receipt that should have been there.
Agent labor did not remove the engineering work. It made a green paste easier to confuse with a run. Stamp the replay receipt anyway. Then close the ticket.
Top comments (0)