Workflow
How the series is made, as of session 09. This page changes when the workflow changes, and every change is noted in the journal.

Diagram source: site/assets/img/workflow.mmd, rendered with make diagrams.
The pieces
- The Codespace is the only workstation. Its devcontainer (
.devcontainer/devcontainer.json) installs Python 3.12, Node, the GitHub CLI and Claude Code.scripts/post-create.shinstalls a pinnedsbxand mermaid-cli, then prints a read-only environment report (make check-env). - Claude Code runs in the Codespace, not in a sandbox. The author’s answer to running it inside one was “absolutely not”; the honest answer would have been yes (ADR-0009). It reads
CLAUDE.mdat the start of every session: the project brief, the rules, and the record-keeping duties. - The author prompts, answers the open decisions, edits every article and approves every commit. Prompts may be in Italian; everything in the repository is English.
- Sandboxes are where the examples run.
make loginsignssbxin to Docker first, headless with theDOCKER_IDandDOCKER_PATCodespaces secrets. Every run goes throughscripts/sbx-run.sh, which creates a sandbox, copies the example in, runs it, copies results and aRUNINFO.jsonout, and removes the sandbox. The wrapper is designed to work the same way in the cloud (sbx --cloud) and locally (SBX_TARGET=local), but for now only the cloud tier is used and published: the local tier waits for a new laptop, because the author’s is too old to run local sandboxes. See ADR-0001 and ADR-0010. - Illustrations are AI-generated from the Codespace with
scripts/gen-header.py, which calls Google’s Nano Banana 2 through OpenRouter. The prompts live inillustrations/: the author’s style, cast and subjects verbatim, plus a separate file of corrections. Every call and its cost goes intoillustrations/log.jsonl. The script runs on the host, not in a sandbox: it’s trusted code that only calls one API. - Charts are drawn on the host with matplotlib (
make plots-NN), only from a recorded run’sresults.jsonandRUNINFO.json. Each figure’s footer names that run. - CI checks every push and pull request on the host: unit tests on Python 3.12 and 3.14,
shellcheck,actionlint,article-check,site-check, and a build of this site. After each merge that touches an example, a second workflow runs the deterministic pieces in a real cloud sandbox and fails unless the results match the runner’s byte for byte (ADR-0014). - The record is written as the work happens: one journal entry per session, an ADR per decision, notable prompts,
series.ymlfor status andmetrics.ymlfor the numbers article 06 will quote.
A session
- Claude reads
CLAUDE.md,site/_data/series.ymland the latest journal entry, then states what the session will do. - Work happens in small steps.
make testruns after any change to an example, and sandboxes run only through the wrapper. - Article prose is written only about runs that happened and left a
RUNINFO.json. /wrapwrites the journal entry, updates the data files, lists live cloud sandboxes and commits.
Current state
As of session 13, the overture and piece 1 are published on Medium, in Docker Captains Wisdom, and example 1 is frozen at the piece-01-v1 tag. A fresh Codespace built from the README badge runs piece 1 end to end. Next comes example 2, then a piece a week (ADR-0007). CI runs piece 1 in a real cloud sandbox after each merge that touches the code. Local sandboxes aren’t used yet: the author’s laptop is too old for them (ADR-0010).