A weekend AI side project is not finished when the chat transcript sounds sure. It is finished when a clean clone prints the same fixture. This log cuts the product to one command, freezes that command’s stdout, and keeps every skipped path in a file the demo never imports.
The failure mode is familiar. Saturday’s agent session produces a UI, a config loader, a README, and three half-wired integrations. Sunday morning none of it runs on a second checkout. The fix is not more generation. The fix is an output freeze.
What this weekend kept
The kept product is a local CLI named pathcut. It reads a JSON task list, keeps only rows marked in_scope, and prints a stable table. No HTTP. No database. No auth. One stdin, one stdout, one exit code.
That is the entire demo. Anything that cannot be shown by that table is a skip, not a stretch goal.
Scope that survived Saturday
- One command:
python -m pathcut demo - One input fixture:
fixtures/tasks.json - One golden file:
golden/demo.txt - One skip register:
SKIPS.yml - Zero runtime calls to a remote model
The model may help write pathcut during the weekend. The demo must still run after the laptop is offline.
The artifact: freeze stdout, not the screenshot
A screenshot lies about imports, working directories, and missing lockfiles. A golden file does not. The check is mechanical: run the command, compare bytes, fail on drift.
Layout
pathcut/
pyproject.toml
Makefile
SKIPS.yml
fixtures/tasks.json
golden/demo.txt
pathcut/__init__.py
pathcut/__main__.py
pathcut/cli.py
pathcut/select.py
pyproject.toml stays tiny. No extra tools. No plugin stack.
[project]
name = "pathcut"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = []
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
include = ["pathcut*"]
Fixture
{
"weekend": "2026-09-11",
"tasks": [
{"id": "T1", "title": "parse task list", "in_scope": true},
{"id": "T2", "title": "print stable table", "in_scope": true},
{"id": "T3", "title": "add OAuth", "in_scope": false},
{"id": "T4", "title": "deploy preview UI", "in_scope": false},
{"id": "T5", "title": "write golden check", "in_scope": true}
]
}
False rows stay in the file on purpose. The skip register and the fixture must agree. If a row is in_scope: false and missing from SKIPS.yml, the check fails. Silent drops are how weekend demos rot.
Selector
# pathcut/select.py
from __future__ import annotations
from typing import Any
REQUIRED_KEYS = ("id", "title", "in_scope")
def load_tasks(payload: dict[str, Any]) -> list[dict[str, Any]]:
tasks = payload.get("tasks")
if not isinstance(tasks, list) or not tasks:
raise ValueError("tasks must be a non-empty list")
cleaned: list[dict[str, Any]] = []
for row in tasks:
if not isinstance(row, dict):
raise ValueError("each task must be an object")
missing = [k for k in REQUIRED_KEYS if k not in row]
if missing:
raise ValueError(f"task missing keys: {missing}")
if not isinstance(row["in_scope"], bool):
raise ValueError(f"{row['id']} in_scope must be bool")
cleaned.append(row)
return cleaned
def keep_in_scope(tasks: list[dict[str, Any]]) -> list[dict[str, Any]]:
return [row for row in tasks if row["in_scope"] is True]
def render(tasks: list[dict[str, Any]]) -> str:
lines = ["ID TITLE", "---- --------------------"]
for row in tasks:
lines.append(f"{row['id']:<4} {row['title']}")
lines.append(f"COUNT {len(tasks)}")
return "\n".join(lines) + "\n"
The renderer is boring on purpose. Column widths are fixed. No timestamps. No locale. No color codes. Golden files die when pretty-printers “help.”
CLI
# pathcut/cli.py
from __future__ import annotations
import argparse
import json
from pathlib import Path
from pathcut.select import keep_in_scope, load_tasks, render
def cmd_demo(root: Path) -> str:
payload = json.loads((root / "fixtures" / "tasks.json").read_text(encoding="utf-8"))
kept = keep_in_scope(load_tasks(payload))
if not kept:
raise SystemExit("demo has zero in-scope tasks")
return render(kept)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="pathcut")
parser.add_argument("command", choices=["demo"])
parser.add_argument("--root", default=".")
args = parser.parse_args(argv)
root = Path(args.root).resolve()
if args.command == "demo":
print(cmd_demo(root), end="")
return 0
raise SystemExit(2)
# pathcut/__main__.py
from pathcut.cli import main
raise SystemExit(main())
Golden file
ID TITLE
---- --------------------
T1 parse task list
T2 print stable table
T5 write golden check
COUNT 3
Update the golden file only after a human reads the new table. Do not let the model refresh goldens as a side effect of “fixing tests.”
Commands that prove the demo
PYTHON ?= python3
ROOT := $(abspath .)
.PHONY: demo check clone-test skips
demo:
$(PYTHON) -m pathcut demo --root $(ROOT)
check: demo
$(PYTHON) -m pathcut demo --root $(ROOT) > /tmp/pathcut-demo.txt
diff -u golden/demo.txt /tmp/pathcut-demo.txt
$(PYTHON) scripts/check_skips.py --root $(ROOT)
skips:
$(PYTHON) scripts/check_skips.py --root $(ROOT)
clone-test:
rm -rf /tmp/pathcut-clone
git clone --depth 1 file://$(ROOT) /tmp/pathcut-clone
$(MAKE) -C /tmp/pathcut-clone check PYTHON=$(PYTHON)
check is the Saturday target. clone-test is the Sunday target. Local success is not evidence. A second working tree is evidence.
If git clone file://... is awkward on the machine, the same idea holds with a tarball:
tar -C /tmp -xzf pathcut.tar.gz
make -C /tmp/pathcut check
The rule does not change. The demo is the command plus the diff. Not the original directory’s hidden state.
Skip register as a test, not a diary
# SKIPS.yml
weekend: "2026-09-11"
skipped:
- id: T3
reason: "OAuth is not required to prove the table"
- id: T4
reason: "preview UI is not the demo; stdout is"
never_import:
- oauth.py
- server.py
- ui/
# scripts/check_skips.py
from __future__ import annotations
import argparse
import json
from pathlib import Path
try:
import yaml # optional; fallback parser below if missing
except ImportError:
yaml = None
def parse_skips(text: str) -> dict:
if yaml is not None:
return yaml.safe_load(text)
# tiny fallback: the file above is small enough to require PyYAML in real use
raise SystemExit("install pyyaml or vendor a skip parser")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", default=".")
root = Path(parser.parse_args().root).resolve()
payload = json.loads((root / "fixtures" / "tasks.json").read_text(encoding="utf-8"))
skips = parse_skips((root / "SKIPS.yml").read_text(encoding="utf-8"))
skipped_ids = {row["id"] for row in skips["skipped"]}
fixture_out = {row["id"] for row in payload["tasks"] if row["in_scope"] is False}
if skipped_ids != fixture_out:
raise SystemExit(f"skip mismatch: yaml={sorted(skipped_ids)} fixture={sorted(fixture_out)}")
for name in skips["never_import"]:
if (root / "pathcut" / name).exists() or (root / name).exists():
raise SystemExit(f"skipped path present in tree: {name}")
print("skips ok")
return 0
if __name__ == "__main__":
raise SystemExit(main())
The skip register is part of make check. A markdown diary that nobody diffs is how scope crawls back in after midnight.
If PyYAML is not wanted this weekend, replace SKIPS.yml with skips.json and drop the import. The point is equality between fixture flags and skip IDs, not the file format.
Decision table used on Saturday afternoon
| Candidate change | Ships this weekend | Reason |
|---|---|---|
Parse tasks.json
|
Yes | Required for the table |
| Stable stdout table | Yes | This is the demo |
Golden diff -u
|
Yes | Clone-proof |
| Skip ID equality check | Yes | Stops silent drops |
| Colorized TTY output | No | Breaks the golden file |
| Remote model at runtime | No | Demo must run offline |
| OAuth / billed APIs | No | Not the path |
| Preview UI on a server | Optional later | Not required to freeze stdout |
| Auto-update goldens | No | Hides drift |
The table is the scope cut. New agent suggestions get a row, not a folder.
Where a free remote session fits
The coding session and the demo are different machines in the design, even when they share a laptop.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode’s operator-described free model access can sit on the Saturday side: drafting select.py, the Makefile, and the skip checker. The free server option can hold a throwaway preview later. Neither one is the demo. make clone-test still has to pass with no extra credentials and no extra hosts. If the preview is down, the golden file remains the ship artifact.
Use the remote session to write code. Do not use it as a hidden dependency of python -m pathcut demo.
A useful split looks like this:
- Freeze
fixtures/tasks.jsonandgolden/demo.txtbefore asking for code. - Allow the model to touch
pathcut/*.pyandscripts/check_skips.pyonly. - Reject patches that add network clients, timestamps, or golden rewrites.
- Run
make checklocally after every accepted patch. - Run
make clone-testonce before stopping for the weekend.
That order matters. Asking the model to invent the fixture after the fact produces a demo that matches the code instead of a code path that matches the demo.
What this weekend skipped, on purpose
- Packaging to PyPI
- A web UI and any CSS
- Live HTTP checks against the titles in the table
- Logging, metrics, tracing
- A second output format
- CI on a hosted runner
- Model-name routing, retries, and prompt logs inside the CLI
Those skips are not moral. They are how a Sunday checkout stays small enough to verify by eye. The skip register exists so the next weekend can pick one row without rediscovering why it was delayed.
Limitations
Golden stdout is a narrow proof. It does not prove concurrency, migrations, accessibility, or auth. It also fights any program whose useful result is a window, a binary, or a network side effect.
diff -u is brittle if the renderer prints times, random IDs, or 24-bit color. Keep those out of the demo path. Put them behind a flag that make check never passes.
git clone of a local path does not prove public clone instructions. It only proves the tree is not leaning on untracked files. A missing fixtures/ in git will fail. That is the point.
The skip checker as written needs a YAML library or a JSON rewrite. Do not pretend the fallback parser exists if it was not shipped.
This method also fails when the weekend goal is exploration rather than a receipt. If the point is to learn an API, freeze nothing yet. Freeze when the claim becomes “this runs.”
Who should not use this approach
- Teams shipping user-facing product this weekend
- Work that handles secrets, production data, or regulated records
- Binaries, GPU jobs, or anything whose result is not text
- Repos where generated goldens are already treated as disposable
- Anyone who needs a hosted preview in order to believe the demo
Those cases need real tests, staging, and review. A golden table is not a substitute.
Stop condition
The weekend stops when make clone-test is green and SKIPS.yml matches the fixture. Extra files in the tree are a failed stop, even if the table looks right.
If a free remote coding session is already in the loop, keep it on the draft side and let the clone-and-diff loop decide whether the demo exists. The table is the ship. Everything else waits for a later weekend.
Top comments (0)