Friday 13th
Friday the 13th seems as good a time as any to start off a project! Let’s begin by reviewing the story
file that was created last time at _bmad-output/implementation-artifacts/1-1-project-scaffolding-and-build-toolchain.md.
Always review these files carefully! - the devil is in the details. When you’re happy you can change the status at the top of the file to “ready-for-dev” or some words like that (in previous versions of BMAD development was locked out until this happened, but now I believe it’s not strictly necessary - still a good habit to have though, I think).
You can see that this task is largely to do with scaffolding out the project: installing toolchains, setting up git, setting up directory structure, and stubbing out some files. Exactly the kind of donkey work that an LLM excels at.
To start the development process I used /bmad-bmm-dev-story 1-1. Technically you don’t need the 1-1 and the agent
will figure out the next active query itself. I used to give it the full @_bmad-output/implementation-artifacts/1-1-project-scaffolding-and-build-toolchain.md in
the belief that I was saving some precious context by pointing directly at the right instructions, but I’ve grown lazy
and settled on just giving 1-1 as a compromise.
Development for this task takes a couple of minutes:
Step 10: Completion
Ant, story 1.1 — Project Scaffolding & Build Toolchain is complete and ready for review.
Key accomplishments:
- Full project structure created with all directories and 22 source files
- Makefile with asm, disk, test, and clean targets plus incremental build support
- constants.asm — all memory layout equates and system constants
- macros.asm — NEXT, DOCOL, EXIT, DEFCODE/DEFWORD/DEFIMMED (with LUA-based XOR-rotate hash), BDOS_SAVE/BDOS_RESTORE
- structures.asm — DictEntry and UserArea STRUCT definitions
- antforth.asm — main manifest with ORG 0x0100 and minimal cold start (BYE via BDOS function 0)
- All 15 architecture-specified stub files created
- Verified: make builds successfully, binary runs under iz-cpm with clean exit (code 0), incremental builds work
Story file: _bmad-output/implementation-artifacts/1-1-project-scaffolding-and-build-toolchain.md (status: review)
Notes:
- iz-cpm was installed from GitHub releases (not available via cargo install as the story notes suggested)
- Used sj.insert_label instead of sj.add_label for sjasmplus v1.21.0 LUA compatibility
- Used --raw CLI flag instead of SAVEBIN directive (which requires DEVICE emulation mode)
The agent is complaining about some features not being available in the “latest” version of sjasmplus, and straight away I see I missed an important detail in the story file: it specifies version 1.20.0, whereas the latest release is 1.20.1. I just called the agent out directly:
❯ why are we using sjasmplus 1.21.0 ? latest is 1.21.1
● It was pre-installed on the system at v1.21.0. Let me check if v1.21.1 adds sj.add_label (which would simplify the LUA workaround) and upgrade it.
and it continues with:
● Still no sj.add_label — sj.insert_label is the correct API. Our code is already using that. Let me just verify the build still works with v1.22.0:
so that whole thing turns out to have been a hallucination! I don’t like the look of that iz-cpm grumble either, and the
whole SAVEBIN thing is a bit of a worry. Roundabout this time it occured to me that installing (updating, at least) system
binaries is not very 2026, so I asked it to switch to a docker build container:
you know what, i think i'd be happier building a docker container that has the correct versions of sjasmplus, iz-cpm and cpmtools in it, rather than relying on system
binaries. this will make using github actions easier later too if we want to.
● Good idea. Let me check what's needed to build each tool, then create the Dockerfile.
and a 1m31s later:
● Done. The Docker toolchain image (antforth-toolchain) contains:
- sjasmplus built from main (v1.22.0+)
- iz-cpm v1.3.4
- cpmtools (from Debian packages)
Usage:
- make docker-build — build the image
- make docker — assemble via Docker
- make docker-test — build + run under iz-cpm
- make docker-disk — build CP/M disk image
The multi-stage build keeps the runtime image small (no compiler toolchain in the final image). The .dockerignore excludes build artifacts and non-source directories from the
context.
It has built a container image that we can use to portably build antforth in less time than it’s taken me to write about it.
One important note about changing track like this: it directly contradicts the specific instructions in the story file and in the architecture document. What we’re doing is called a “course correction”, and there’s (of course) a BMAD command to deal with that (more than one actually, depending on the complexity of the correction). But for a minor change like this, at such an early stage, it’s easier to ask the dev agent to make the change, and then ask it to update the documentation to match:
❯ can you update the story and maybe the architecture document to reflect that we've elected to use a docker build container?
● Done. Updated both documents:
Architecture doc — added Docker to the toolchain table with a description of the multi-stage build approach, added Dockerfile/.dockerignore to the directory structure, and
expanded the build process section with the docker targets.
Story file — added Dockerfile and .dockerignore to the file list, added Docker completion notes, and added a change log entry.
If you skip this step, the next step (which is an adversarial code review) WILL flag up the differences, and worst case may even revert them, which can be quite heartbreaking. Adversarial means that the review agent MUST find something to complain about, so a spec deviation like that is an easy out for it - we want it to work harder and find actual issues.
Speaking of which, let us clear the context (I use /reset - I used to use /clear but for some reason recently Claude code
decided that /clear is an alias of /compact - which is the exact opposite of what I want!)
Now we can run the code review with /bmad-bmm-code-review 1-1 (I’m using my usual technique of typing review and picking from
one of the suggestions).
The review agent (actually a dev agent with his code-review hat on) finds some issues sure enough:
---
Step 3: Adversarial Review
---
🔥 CODE REVIEW FINDINGS, Ant!
Story: 1-1-project-scaffolding-and-build-toolchain.md
Git vs Story Discrepancies: 2 found
Issues Found: 2 High, 4 Medium, 3 Low
The “High” issues are to do with macros being in the wrong place. Amusinly one of the medium issues is:
M3: architecture.md modified but not documented in story File List
- Git shows architecture.md as modified (unstaged)
- Story Change Log correctly notes "Updated architecture document to reflect containerised build approach"
- But the story's File List does NOT include architecture.md
- Impact: Incomplete documentation of changes
so we didn’t entirely get away with our course correction!
Luckily there’s nothing too earth-shattering so I used the 1. Fix them immediately option. You can also write new
tasks and subtasks for the necessary corrections into the story file, and go back to a fresh dev agent and start
again. This is a good idea if you’re running out of context. If things go really south, you can convene an emergency
retro with your entire “team” and ask them “what the hell happened?”. I will leave this for a later post…it’s bound
to crop up.
This took a while, as further isses were encountered and remedied, but eventually:
Step 5: Review Complete!
All HIGH and MEDIUM issues have been fixed and verified:
┌──────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────────┐
│ Issue │ Fix │ Verified │
├──────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────┤
│ H1 DOCOL/EXIT misplaced │ Moved from macros.asm to inner_interpreter.asm │ Build passes │
├──────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────┤
│ H2 Macros had 3 latent bugs │ Fixed bit32→native Lua 5.5 ops, LEN→LUA name length via DEFINE/sj.get_define, added DEFCODE "BYE" to │ Build passes, BYE entry in │
│ │ exercise macros │ binary │
├──────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────┤
│ M1 Include order wrong │ Reordered antforth.asm to match architecture spec │ Build passes │
├──────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────┤
│ M2 disk/ won't survive clone │ Added disk/.gitkeep │ File exists │
├──────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────┤
│ M3 architecture.md not in File │ Added to story File List │ Story updated │
│ List │ │ │
├──────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────┤
│ M4 Cold start layout fragile │ Resolved by H1 + M1 fixes │ Binary layout clean │
└──────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────────────────────┘
Story Status: done
Issues Fixed: 6 (2 HIGH, 4 MEDIUM)
Action Items Created: 0
Sprint status synced: 1-1-project-scaffolding-and-build-toolchain → done
The review step can be long and arduous, it often takes more time than the development process. It is tempting sometimes to skip it, but I try to never, ever skip this crucial step. It is time well spent.
Results
At this point we have a directory structure that looks like this:

Seems like as good a time as any to commit. Incidentally, I have strict instructions in various Claude config files for him to keep his hands off the repo. It’s a human-controlled firewall as far as I’m concerned, a bit like Zion in the Matrix movies. Also the “Co-authored by Claude/Anthropic” advert it inserts really greats my gears given the $$$ I’m forking over every month.
Not much else we can do at this stage, except maybe admire our Makefile and take some of the make targets for a spin, including the Docker build container that we pivoted to.
We can even make test as we have a rudimentary test executed via iz-cpm. Doesn’t do much yet, but it’s a promising start.
An aside on testing: Claude Code is superb at writing tests, but it is extremely lax at maintaining 100% pass rate. You will quickly see weasel words like “some tests are failing, but it’s not code that I just changed so that can’t have been me…”. One of the main jobs as the “human-in-the-loop” is to stamp that shit out as soon as it occurs. Never, ever let a dev/review cycle end with failing tests, broken tests, skipped tests, or – if you-re feeling particularly puritanical – warnings.
In my experience, you can add this to all the Claude config files you can find, and to the PRD, architecture docs and even individual story files - Claude will still try to wriggle out of it. Don’t let him!