DEV Community

Riley Zhang
Riley Zhang

Posted on

Weekend Build Log: Git Status Is the Demo Gate

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. out/verdict.txt
  2. out/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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 $?
Enter fullscreen mode Exit fullscreen mode

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 $?
Enter fullscreen mode Exit fullscreen mode

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)