docs: fix the fresh-clone recipe — it was missing make ip65-blob - #89
Merged
Conversation
#86 documented a fresh-clone build recipe that does not work. Verified 2026-08-14 against a clean `git clone` of master: - plain `make` -> FAILS - after `make ip65-libs`, `make` -> FAILS, identically - after `make ip65-blob`, `make` -> succeeds `make` cannot build the blob: `ip65-blob` is phony, and ip65_blob.s pulls the file in via a ca65 `.incbin` that make's dependency graph never sees, so no rule connects them. The recipe now includes the step. The documented failure mode was also wrong. #86 quoted `ld65: Input file '../ip65/ip65/ip65_tcp.lib' not found`, but that is what `make ip65-blob` produces when run *without* the libs. A genuine fresh clone fails earlier, at assembly: src/net/ip65/ip65_blob.s(22): Error: Cannot open include file '../../../ip65-build/ip65-c64.bin' which is the error users actually report. Both are now documented with the ordering that produces each. Reported by a second user hitting the same wall after #86 merged. #86 verified that the failure reproduces; it did not verify that its own recovery worked from a clean clone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
JC-000 added a commit
that referenced
this pull request
Aug 14, 2026
Both prerequisites that bit contributors this week fail with errors that do not name them, and both were documented only on paths the affected reader does not walk (#89 for the ip65 blob, #90 for the harness). This puts them together, before either entry point: git submodule update --init --recursive make ip65-libs && make ip65-blob # ip65 backend python3 -m pip install -e ../c64-test-harness with the exact error each one prevents, so searching the traceback finds the fix. Uses `python3 -m pip` because a venv mismatch reproduces #90 exactly after an install that appeared to succeed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 14, 2026
JC-000 added a commit
that referenced
this pull request
Aug 15, 2026
… correction Self-correction on top of the previous commit, caught in review before merge. ## What I got wrong That commit claimed plain `make` already rebuilt the ip65 blob in the right order and that `make ip65-blob` "was never a required step". I had measured it: delete the blob, `make clean`, `make`, watch it rebuild byte-identically. The measurement was real. The conclusion was wrong, and shipping it would have re-blocked the next fresh clone -- exactly what issue #89 was filed to prevent. The confound is worth knowing, because it will fool anyone else measuring here. **ca65 does not resolve `.incbin` only relative to the including source file**, whatever the comment in ip65_blob.s said. It also tries the path relative to the current directory, and `../../../` from a repo root escapes three levels ABOVE the checkout. A git worktree lives at `<repo>/.claude/worktrees/<name>/` -- exactly three levels down. So my worktree, with its own blob deleted, silently assembled the PARENT checkout's blob and reported success. Reproduced deliberately in a scratch tree (`x/y/z/src/net/ip65/ip65_blob.s`, no `x/y/z/ip65-build/`, blob planted at the top): ca65 exit 0. The original CLAUDE.md text was right about the observable behaviour and right about the error message. It was wrong only about the mechanism -- it blamed a phony target with "no rule connecting the two". ## What is actually broken, and the fix There IS a rule, and $(IP65_BIN) has always been a prerequisite of the PRG. What was missing is an edge from the *object* that consumes the blob: make cannot see through `.incbin`, so from a clean build/ it was free to assemble ip65_blob.o before the blob rule ran -- and did. build/net/ip65/ip65_blob.o: $(IP65_BIN) Fixed at the source rather than documented around, so the workaround step goes away instead of needing a carefully worded warning. ## Evidence Genuine `git clone` from GitHub into a scratch dir, submodule init, `make ip65-libs`, then plain `make`: before: src/net/ip65/ip65_blob.s(22): Error: Cannot open include file '../../../ip65-build/ip65-c64.bin': No such file or directory make: *** [build/net/ip65/ip65_blob.o] Error 1 after: exit 0; blob 6,951 B cf1a5ff7...; PRG 47,105 B d522e684... Output-neutral -- the ip65 PRG hashes d522e684... with and without the edge, reproduced in both the fresh clone and this worktree. Full evidence bar, since this touches the Makefile: make clean && make -> exit 0, 47,105 B, d522e684... make clean && make BACKEND=uci -> exit 0, 62,977 B, 66e37037... python3 tools/test_ecdsa_kat_oracle.py -> 6/6 (3 valid, 3 invalid CAVP) python3 tools/test_x509.py -> 11/11 ## Docs CLAUDE.md and README now describe the real mechanism, credit that the original text was right about the failure and wrong only about the why, and both warn against measuring blob behaviour in a nested worktree. ip65_blob.s's own comment asserted the false source-relative rule right above the `.incbin`; corrected, since this commit proves it wrong and changes the adjacent build rule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
JC-000 added a commit
that referenced
this pull request
Aug 15, 2026
… correction Self-correction on top of the previous commit, caught in review before merge. ## What I got wrong That commit claimed plain `make` already rebuilt the ip65 blob in the right order and that `make ip65-blob` "was never a required step". I had measured it: delete the blob, `make clean`, `make`, watch it rebuild byte-identically. The measurement was real. The conclusion was wrong, and shipping it would have re-blocked the next fresh clone -- exactly what issue #89 was filed to prevent. The confound is worth knowing, because it will fool anyone else measuring here. **ca65 does not resolve `.incbin` only relative to the including source file**, whatever the comment in ip65_blob.s said. It also tries the path relative to the current directory, and `../../../` from a repo root escapes three levels ABOVE the checkout. A git worktree lives at `<repo>/.claude/worktrees/<name>/` -- exactly three levels down. So my worktree, with its own blob deleted, silently assembled the PARENT checkout's blob and reported success. Reproduced deliberately in a scratch tree (`x/y/z/src/net/ip65/ip65_blob.s`, no `x/y/z/ip65-build/`, blob planted at the top): ca65 exit 0. The original CLAUDE.md text was right about the observable behaviour and right about the error message. It was wrong only about the mechanism -- it blamed a phony target with "no rule connecting the two". ## What is actually broken, and the fix There IS a rule, and $(IP65_BIN) has always been a prerequisite of the PRG. What was missing is an edge from the *object* that consumes the blob: make cannot see through `.incbin`, so from a clean build/ it was free to assemble ip65_blob.o before the blob rule ran -- and did. build/net/ip65/ip65_blob.o: $(IP65_BIN) Fixed at the source rather than documented around, so the workaround step goes away instead of needing a carefully worded warning. ## Evidence Genuine `git clone` from GitHub into a scratch dir, submodule init, `make ip65-libs`, then plain `make`: before: src/net/ip65/ip65_blob.s(22): Error: Cannot open include file '../../../ip65-build/ip65-c64.bin': No such file or directory make: *** [build/net/ip65/ip65_blob.o] Error 1 after: exit 0; blob 6,951 B cf1a5ff7...; PRG 47,105 B d522e684... Output-neutral -- the ip65 PRG hashes d522e684... with and without the edge, reproduced in both the fresh clone and this worktree. Full evidence bar, since this touches the Makefile: make clean && make -> exit 0, 47,105 B, d522e684... make clean && make BACKEND=uci -> exit 0, 62,977 B, 66e37037... python3 tools/test_ecdsa_kat_oracle.py -> 6/6 (3 valid, 3 invalid CAVP) python3 tools/test_x509.py -> 11/11 ## Docs CLAUDE.md and README now describe the real mechanism, credit that the original text was right about the failure and wrong only about the why, and both warn against measuring blob behaviour in a nested worktree. ip65_blob.s's own comment asserted the false source-relative rule right above the `.incbin`; corrected, since this commit proves it wrong and changes the adjacent build rule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
JC-000 added a commit
that referenced
this pull request
Aug 15, 2026
chore: finish the pytest-boundary rename, correct CLAUDE.md against measurement, and fix#89's fresh-clone build
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The fresh-clone recipe #86 shipped does not work. A second user hit the wall it was written to remove, which prompted actually running it.
Verified 2026-08-14 against a clean
git cloneof master:makeip65_blob.s(22): Cannot open include file '.../ip65-c64.bin'make ip65-libsthenmakemake ip65-blobthenmakecf1a5ff7…), 47,105 B PRG (417c7085…)Two defects
1. The recipe omits
make ip65-blob. Andmakecannot substitute for it:ip65-blobis a phony target, whilesrc/net/ip65/ip65_blob.spulls the artifact in through a ca65.incbinthat make's dependency graph never sees. There is no rule connecting them, so no amount ofmakewill produce the blob.2. The documented failure mode is the wrong one.#86 quotes
ld65: Error: Input file '../ip65/ip65/ip65_tcp.lib' not found. That is whatmake ip65-blobproduces when run without the libs — a real ordering, but not the one a fresh clone hits. A fresh clone fails earlier, at assembly, with the.incbinerror above. That is what users actually report, and it appeared nowhere in the docs, so searching for it found nothing.Both orderings and both errors are now documented, with the four-command recipe that resolves either.
Why this slipped
#86 verified that the failure reproduced — three steps, three distinct errors — and did not verify that its own recovery worked from a clean clone. The fix for a documentation trap was itself an unexecuted claim, which is the same defect class the surrounding work has been about. The correction is now backed by a full clone-build-verify cycle rather than by reading the Makefile.
🤖 Generated with Claude Code