Skip to content

docs: fix the fresh-clone recipe — it was missing make ip65-blob - #89

Merged
JC-000 merged 1 commit into
masterfrom
docs/fix-fresh-clone-recipe
Aug 14, 2026
Merged

docs: fix the fresh-clone recipe — it was missing make ip65-blob#89
JC-000 merged 1 commit into
masterfrom
docs/fix-fresh-clone-recipe

Conversation

@JC-000

Copy link
Copy Markdown
Owner

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 clone of master:

stepresult
plain makeFAILSip65_blob.s(22): Cannot open include file '.../ip65-c64.bin'
make ip65-libs then makeFAILS, identically
make ip65-blob then makesucceeds — 6,951 B blob (cf1a5ff7…), 47,105 B PRG (417c7085…)

Two defects

1. The recipe omits make ip65-blob. And make cannot substitute for it: ip65-blob is a phony target, while src/net/ip65/ip65_blob.s pulls the artifact in through a ca65 .incbin that make's dependency graph never sees. There is no rule connecting them, so no amount of make will 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 what make ip65-blob produces 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 .incbin error 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

#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
JC-000 merged commit 0a75540 into masterAug 14, 2026
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>
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
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@JC-000