You reopen a ticket on Monday and the only attachment is a cropped terminal screenshot that ends in green. The agent that produced the change ran over the weekend on a shared server, and nobody saved the prompt that steered it. A teammate already moved the card to done because the log looked calm and the branch exists. You cannot tell whether the tests that ran were the contract tests, a subset, or a command the agent invented.
That gap is not a model-quality debate, and it is not fixed by a smarter assistant next month. The missing object is a run packet: the prompt file, the diff, the exact commands, and the exit status, bound by hashes. Without that packet, a later reviewer cannot replay the claim or explain a failure to the person who owns the service. This playbook gives you roles, a handoff, and a one-page run you can paste into the team wiki.
What breaks when the log is the only proof
A green log is a picture of one moment, not a contract you can audit next week. Agents rewrite commands when a step fails, and a retry can hide the first exit code unless you capture it before the shell exits. Free shared capacity also disappears mid-run, which means the host that produced the screenshot may not exist when you ask for a rerun. You need a packet that survives the host, not a feeling that the card looks finished.
People also paste the model reply straight into the ticket and call that the design note. The reply can omit a constraint that was scrolled out of the window, and the ticket then preserves the omission. A file you hashed before the call is harder to quietly replace than a paragraph someone edited in the comment box. You want the input frozen first, then the output, and only then a human decision on the card.
Roles you name before the run
Name three roles before anyone starts a shared agent job, and write those names into the wiki rather than into chat. The packet clerk saves every input and output, while the reviewer accepts or rejects the finished packet. The service owner is the only person who may allow the proposed change to touch the real environment. One person may hold two roles on a small team, but the reviewer must not be the only human who read the prompt.
If any role is vacant when the job starts, you leave the run in draft and you leave the ticket open. A missing clerk means the prompt lived only in a browser tab that nobody on the team can reopen. A missing reviewer means a green log can close work that the service owner never inspected. Do not invent a fourth role for ceremony; three names are enough if each name has a backup.
Handoff steps
1. Freeze inputs before the first model call
You write the task in a file named task.md, and you list the commands you expect in commands.txt. You do not paste secrets, customer records, or production tokens into either of those two files. You record who may call the model and which server is allowed to execute commands, using the names your platform shows today. If the docs do not name a limit, you write "unconfirmed" instead of guessing a quota from memory.
2. Run the listed commands, then capture status
You execute only the commands listed in commands.txt, and you append both stdout and stderr to run.log. You save the exit status in a separate file before any cleanup script runs, because a later step can replace a failure with zero. If the host is temporary, you copy the log off the host before you stop it. You do not rerun a failed command until the first status is already in the packet.
3. Bind the files with hashes
You hash task.md, commands.txt, run.log, and the diff, then you store those digests in packet.json beside them. A reviewer who was not in the session can compare each digest to the files you attached to the ticket. If a hash does not match, the packet is rejected and the ticket does not move. The script below is a local proposal you can run yourself; it is not a measured result from a lab.
4. Hand the packet to the reviewer
The clerk posts the packet link in the ticket and names the reviewer in the same comment. The reviewer checks that the diff matches the task, that stray files are absent, and that the saved exit status is first. The reviewer does not fix forward inside the same session, because that erases the packet you just sealed. Approval is a short comment that quotes the packet digest, not a reaction emoji on the card.
5. Hand the decision to the service owner
Only after that approval does the service owner decide where the proposed change is allowed to land. A sandbox or a free server result is not permission to touch production, even when every check is green. The owner writes the target environment and a short rollback note into that same ticket comment. If the owner is out, the change waits; you do not borrow their name from a previous ticket.
6. Replay only when it is safe
You copy the packet to a clean directory and confirm each hash with sha256sum or the script printed digest. You run the same command from commands.txt only if the service owner says the replay is safe and cheap. You do not replay the command against production merely to satisfy curiosity about an earlier green log. If replay is unsafe, the reviewer records that it was skipped and the owner accepts that limit in the ticket.
One-page run for the wiki
Copy the block below into the wiki page for the service, and replace the bracketed names before the first run. Keep the page short enough that a new clerk can finish it without scheduling a meeting. Update the platform note when the docs change, and delete any number you cannot point to a current page. Treat the block as the run itself, not as a slogan you pin once and then forget.
# Run packet — one-page run
Roles
- Packet clerk: [name, backup]
- Reviewer: [name, backup]
- Service owner: [name, backup]
Before the model call
- [ ] task.md has the change, the tests, and the out-of-scope list
- [ ] commands.txt lists every command the host may run
- [ ] no secrets, customer records, or production tokens are in those files
- [ ] model access note: [platform label or "unconfirmed"]
- [ ] server note: [allowed host label or "unconfirmed"]
- [ ] docs checked on: [YYYY-MM-DD]
After the run
- [ ] run.log has stdout and stderr
- [ ] exit_status.txt was written before cleanup
- [ ] diff.patch matches the branch you will review
- [ ] packet.json hashes match the files in this folder
- [ ] reviewer comment quotes the task.md digest
- [ ] service owner names the target environment and a rollback note
- [ ] replay: done / skipped (reason)
Decision
- Reject the packet if any required file is missing or any hash mismatches.
- Do not move the ticket to done from a screenshot alone.
Decision rows when the packet is messy
When the packet is incomplete, you follow the same row every time instead of debating it in chat. The table is a rule for the clerk and the reviewer, not a score you publish outside the team. Use it on the next incomplete run, and change a row only by editing the wiki page. If a case is not listed, you stop and ask the service owner rather than inventing a softer path.
| What you see | What you do | Who acts |
|---|---|---|
| Prompt exists only in chat | Stop, write task.md, start a new packet | Clerk |
| Exit status missing | Do not rerun yet; mark the packet incomplete | Clerk |
| Hash mismatch | Reject the packet; do not edit files in place | Reviewer |
| Extra files in the diff | Reject until the owner explains each path | Reviewer |
| Host already gone | Keep the copied log; do not claim a rerun you cannot make | Clerk |
| Replay would touch production | Record "replay skipped" and wait | Owner |
A mismatch is a stop, not a prompt to regenerate the log until the hash looks convenient. Editing run.log after you hashed it creates a second story that the ticket can no longer reconcile. You attach the rejected packet anyway, so the next person sees why the card stayed open. That kind of convenience is how a green screenshot replaced the evidence the last time around.
A proposal script to seal the folder
The following Python is a proposal for a scratch directory you control, and it was not executed as a benchmark for this article. It refuses to write packet.json when a required file is missing, which is the behavior you want on a tired Friday. It does not call a network, install a package, or decide whether your tests were meaningful. You still read the diff yourself after the digest exists, because the script will never do that for you.
#!/usr/bin/env python3
"""Proposal only: hash a local run folder into packet.json. Not a benchmark."""
import hashlib
import json
import sys
from pathlib import Path
REQUIRED = ["task.md", "commands.txt", "run.log", "exit_status.txt"]
def sha256(path: Path) -> str:
digest = hashlib.sha256()
digest.update(path.read_bytes())
return digest.hexdigest()
def main() -> int:
root = Path(sys.argv[1] if len(sys.argv) > 1 else ".")
missing = [name for name in REQUIRED if not (root / name).is_file()]
if missing:
print("missing:", ", ".join(missing), file=sys.stderr)
return 2
names = list(REQUIRED)
if (root / "diff.patch").is_file():
names.append("diff.patch")
packet = {
"files": {name: sha256(root / name) for name in names},
"exit_status": (root / "exit_status.txt").read_text(encoding="utf-8").strip(),
"note": "hashes only; keep secrets out of these files",
}
(root / "packet.json").write_text(json.dumps(packet, indent=2) + "\n", encoding="utf-8")
print(packet["files"]["task.md"])
return 0
if __name__ == "__main__":
raise SystemExit(main())
You can exercise the script with fake files before you point it at a real branch. The commands below are only a local sketch, not a transcript taken from a shared server. Replace the pytest line with the command your repo actually uses, or the check will teach you nothing. If a command would mutate data, leave it out of commands.txt until the service owner agrees.
mkdir -p "$HOME/scratch/run-packet" && cd "$HOME/scratch/run-packet"
printf '%s\n' "State the change, the tests, and what is out of scope." > task.md
printf '%s\n' "python -m pytest tests/test_contract.py -q" > commands.txt
printf '%s\n' "proposal log, not a real run" > run.log
printf '%s\n' "0" > exit_status.txt
python seal_packet.py .
sha256sum task.md commands.txt run.log exit_status.txt
You compare the printed digest with packet.json before you upload any file from that folder. If you later add diff.patch, run the script again and treat the new file as a new packet. Do not hand-edit the JSON so that it matches a story you would rather tell in the ticket. A reviewer who recomputes even one hash and finds a mismatch should reject the whole folder.
Where a free model and a free server fit
MonkeyCode enters this playbook only as an optional place to draft the task and to run the allowed commands. Disclosure: This article was prepared as part of MonkeyCode's product outreach. You may use free model access to shape the task file when the current docs still offer that access. You may use the free server option to execute the command list when that option is still offered to you.
If a page does not state a quota, a machine size, or a time limit, you leave those fields blank. The packet is still valid when you swap in another editor and another host you already trust. Do not treat a free option as a promise that the same capacity will exist next week. Write the date you checked the docs into the wiki note so the next clerk does not inherit a stale assumption.
Keep the model call inside the files you already froze, and do not paste the raw ticket if it holds private data. A free server is still a host you must be allowed to use, with the same ban on production tokens in the prompt. When the session ends, you copy run.log and exit_status.txt off the host before you release it. The wiki run fails closed if that copy never arrives, even if the browser tab still looks successful.
Limits, and who should not use this
The hashes prove that the files you stored match each other, not that the tests were the right tests. A clerk can hash a log from the wrong directory and still produce a clean packet.json. The reviewer has to read the task and the diff, because a digest cannot judge intent. If your team needs signed provenance or a compliance archive, this one-page run is too small for that job.
Skip this playbook if you are working alone on a toy branch and you will delete the branch the same day. Skip it if the change touches production data, billing, or credentials, because a wiki checklist is not an access review. Skip it if your company already has a required evidence system, and use that system instead of a parallel packet. The script is a local proposal for files you own, and it has not been timed, load-tested, or certified here.
Close on the packet, not the screenshot
After the reviewer quotes the digest, you can close the ticket with a sentence that points at the packet rather than at a screenshot. If you want to try those free options, confirm them in the current docs before you copy any number into the wiki. The sealed packet still matters even if your team never opens that product again after this week. Next time the log looks green, you open the packet and read it before you move the card.
Top comments (0)