DEV Community

Charlie Hu
Charlie Hu

Posted on

Stdout Is the Demo: A Weekend Golden-File Build Log

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

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

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

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

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)
Enter fullscreen mode Exit fullscreen mode
# pathcut/__main__.py
from pathcut.cli import main

raise SystemExit(main())
Enter fullscreen mode Exit fullscreen mode

Golden file

ID    TITLE
----  --------------------
T1    parse task list
T2    print stable table
T5    write golden check
COUNT 3
Enter fullscreen mode Exit fullscreen mode

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

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

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

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:

  1. Freeze fixtures/tasks.json and golden/demo.txt before asking for code.
  2. Allow the model to touch pathcut/*.py and scripts/check_skips.py only.
  3. Reject patches that add network clients, timestamps, or golden rewrites.
  4. Run make check locally after every accepted patch.
  5. Run make clone-test once 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)