You sit down Saturday with a half-built coding helper. The model prints a warm, finished-sounding summary. You almost paste that summary into README.md.
Then you run git status and the story collapses. Twelve paths changed under the working tree. One test file is simply gone.
The helper praised a change that never actually landed. This log rebuilds the demo around git status. You cut scope until one command remains.
The helper may write two paths, then it must stop. Prose cannot be your merge gate this weekend. The working tree has to stay the judge.
The Failure You Can Reproduce
Open a throwaway repo and ask for a small cleanup. Watch the model narrate a perfect, tidy patch. Do not trust that narration yet.
Run this command before you smile at the terminal:
git status --porcelain
If the list is long, the demo already failed. English success is not a merge gate. The working tree is the only honest log you have.
You do not need a larger prompt for this lesson. You need a smaller surface and a local checker. That local checker should fail loudly on leaks.
Cut Scope Until One Command Remains
Keep a single public command named make demo. That target packs input, runs one helper, then checks the tree. Anything else waits for a later weekend.
The helper may write only these two paths:
out/verdict.txtout/note.md
verdict.txt holds one token: PASS, FAIL, or SKIP. note.md holds a short human note. No third path is allowed to appear.
You skip a chat window on purpose this weekend. A window hides dirty files behind friendly prose. A Makefile target cannot hide a dirty tree.
The Exit Code Table
Do not parse the model's tone or hedges. Parse exit codes, file bytes, and paths. Pin this table in the repository root.
| Code | Meaning | What you do next |
|---|---|---|
| 0 | Allowed files exist; no extra dirty paths | Keep the demo |
| 2 | Helper refused the job | Read out/note.md
|
| 3 | Input exceeded the byte budget | Cut the fixture |
| 4 | Git status shows a forbidden path | Fail the weekend demo |
| other | Wrapper bug | Fix the script, not the prompt |
Print that table in README.md after the first green run. Future you will need it after coffee. The table is the contract, not the chat transcript.
Build It as Four Files
Create an isolated folder for the experiment. Do not practice inside a real work repo. Cleanup should cost one rm -rf command.
mkdir -p weekend-gate/{out,src,fixtures}
cd weekend-gate
git init
touch out/.gitkeep src/.gitkeep
printf 'sample input for a one-line verdict\n' > fixtures/sample.txt
git add .
git commit -m "start weekend gate"
You now have a clean tree to measure against. The helper must keep that tree almost clean. Only the two output paths may show up later.
1. Freeze the path allowlist
Create src/allowlist.txt with exactly two lines. Use no globs, comments, or blank lines. Two literal paths fit in a review.
out/verdict.txt
out/note.md
You can review that file without a meeting. A glob would hide a surprise write. Literal paths keep the weekend honest.
2. Pack a bounded fixture
Add src/pack_input.py. This script reads one fixture file. It refuses to pass a blob over 32768 bytes.
#!/usr/bin/env python3
"""Proposed local packer. Not a hosted service."""
from pathlib import Path
import sys
BUDGET = 32768
def main() -> int:
if len(sys.argv) != 2:
print("usage: pack_input.py FIXTURE", file=sys.stderr)
return 2
path = Path(sys.argv[1])
data = path.read_bytes()
if len(data) > BUDGET:
print(f"input {len(data)} exceeds {BUDGET}", file=sys.stderr)
return 3
sys.stdout.buffer.write(data)
return 0
if __name__ == "__main__":
raise SystemExit(main())
Label this script as a proposed local packer. You should run it on your machine. It does not call a network by itself.
3. Wrap the helper once
Add src/run_helper.sh. This wrapper is a local proposal, not a vendor SDK. It reads stdin and writes the two allowed files.
#!/usr/bin/env bash
set -euo pipefail
# Proposed one-shot wrapper. No retry loop lives here.
mkdir -p out
input="$(cat)"
if [[ "${FORCE_EXTRA_WRITE:-}" == "1" ]]; then
printf 'oops\n' > out/extra.log
fi
if [[ "${FORCE_REFUSE:-}" == "1" ]]; then
printf 'SKIP\n' > out/verdict.txt
printf 'fixture looked unsafe\n' > out/note.md
exit 2
fi
printf 'PASS\n' > out/verdict.txt
printf 'stdin bytes: %s\n' "${#input}" > out/note.md
The FORCE_EXTRA_WRITE switch exists for the failure drill. Do not ship that switch in production code. You want a reproducible bad path this weekend.
Swap the stub later for one real completion call. Keep the rest of the wrapper tiny. A second call would hide the first failure.
4. Check the working tree
Add src/check_tree.py. This checker file is the actual weekend product. The script stays boring on purpose here.
#!/usr/bin/env python3
"""Fail the demo when git status leaves the allowlist."""
from pathlib import Path
import subprocess
import sys
ALLOWED = {
line.strip()
for line in Path("src/allowlist.txt").read_text().splitlines()
if line.strip()
}
VERDICT_VALUES = {"PASS", "FAIL", "SKIP"}
NOTE_BUDGET = 4000
def porcelain() -> list[str]:
raw = subprocess.check_output(
["git", "status", "--porcelain", "-uall"],
text=True,
)
paths = []
for line in raw.splitlines():
if not line:
continue
path = line[3:]
if " -> " in path:
path = path.split(" -> ", 1)[1]
paths.append(path)
return paths
def main() -> int:
verdict = Path("out/verdict.txt")
note = Path("out/note.md")
if not verdict.is_file() or not note.is_file():
print("missing allowed output file", file=sys.stderr)
return 4
token = verdict.read_text().strip()
if token not in VERDICT_VALUES:
print(f"bad verdict {token!r}", file=sys.stderr)
return 4
if note.stat().st_size > NOTE_BUDGET:
print("note.md exceeds byte budget", file=sys.stderr)
return 4
dirty = porcelain()
extra = [p for p in dirty if p not in ALLOWED]
if extra:
print("forbidden paths:", *extra, sep="\n", file=sys.stderr)
return 4
print(f"gate ok verdict={token} dirty={dirty}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
The checker never reads the model prose. It reads files and git status --porcelain. That split is the whole point of the weekend.
Wire make demo
Add a Makefile with three targets. Humans run make demo and stop there. The other targets exist for the failure drill.
.PHONY: demo refuse dirty
demo:
python3 src/pack_input.py fixtures/sample.txt | bash src/run_helper.sh
python3 src/check_tree.py
refuse:
python3 src/pack_input.py fixtures/sample.txt | FORCE_REFUSE=1 bash src/run_helper.sh
python3 src/check_tree.py
dirty:
python3 src/pack_input.py fixtures/sample.txt | FORCE_EXTRA_WRITE=1 bash src/run_helper.sh
python3 src/check_tree.py
make demo is the definition of done. A screenshot in a chat window does not count. If this target fails, you are not finished.
Run the Happy Path
Make the scripts executable, then run the happy path. You should see gate ok and exit code 0.
chmod +x src/pack_input.py src/run_helper.sh src/check_tree.py
make demo
echo $?
git status --porcelain
Expected porcelain is only the two allowed files. Anything else means the wrapper leaked a write. Stop and inspect before you add features.
If out/.gitkeep also appears as dirty, commit it first. The allowlist should name every path you accept. Hidden extra files are still extra files.
Run the Failure Path
Now plant a forbidden file on purpose. This is the drill that trains your eye. A green verdict must not outrank a dirty tree.
make dirty
echo $?
You want exit code 4 from this drill. out/extra.log sits outside the allowlist. The demo must fail, even if verdict.txt says PASS.
Reset the tree and try the refuse path too:
git clean -fd
make refuse
echo $?
A planned SKIP can still pass the tree gate. A surprise extra path must never pass it. That difference is the whole product this weekend.
What You Skipped On Purpose
You skipped a web UI for the helper. You skipped token streaming in the terminal. You skipped a public HTTP endpoint.
You skipped multi-file refactors across the app. You skipped an "explain this patch" mode. You skipped retry storms after a vague failure.
You also skipped hosting this as a shared service. A weekend demo should not become an auth problem. Keep it local until the gate is boring.
Those skips are not laziness in disguise. They are how the demo stays honest. Extra surface area gives the helper more places to lie.
Where a Free Model Call Fits
You still need somewhere to try a real one-shot completion later. Billing should not become the weekend's main plot. A free model path keeps the experiment about the gate.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. It offers free model access and a free server option. Use that pair for the one-command loop above.
Swap the stub in run_helper.sh for one completion call. Keep the allowlist checker unchanged after the swap. If the model writes a third path, the gate still fails.
Do not treat free access as a production SLA. This article does not claim quotas, model names, or uptime numbers. The working tree remains the judge either way.
Limitations
This gate is not a sandbox for untrusted code. A helper that runs destructive commands can still win. You are checking leftovers, not intercepting every syscall.
git status misses ignored files by design. Do not add broad gitignore rules for out/. If you ignore outputs, the checker goes blind.
The byte budgets are local constants in scripts. They are not security boundaries around the model. They only stop accidental huge fixtures and huge notes.
The stub helper does not prove any vendor. It proves your Makefile and your allowlist. Wire a real model only after make dirty fails.
Renames can still fool a sloppy porcelain parser. The sample checker splits -> on purpose. Read git status docs before you copy this into a larger repo.
Who Should Skip This Approach
Skip this if you must ship a multi-file refactor today. Two output paths will not hold that work. Cut a different weekend, or drop the model.
Skip this during a production incident on call. You need humans and known runbooks then. A fresh git gate is the wrong tool.
Skip this if you cannot isolate a throwaway repo. Running the helper against payroll code is unsafe. Copy a fixture out instead of pointing at secrets.
Skip this if your team needs audit logs, SSO, or signed artifacts. This Makefile will not satisfy that bar. It is a side-project receipt, not a platform.
Keep the Demo Small
Ship the gate when make demo is green. Ship it when make dirty is red. That pair is enough for Sunday night.
Do not add a dashboard after the gate works. Do not add a second helper "just in case." The dirty tree was the original bug.
If you later connect a free server, keep this same contract. One command. Two paths. Git status as the demo gate.
Top comments (0)