A printer flashed back to stock came up with the FlashForge screen and no
Klipper behind it, and stayed that way however many times the stock package
was flashed. The .cfg files were the obvious suspect and are not the fault:
stock's run.sh does `cp $WORK_DIR/klipper/config/* /usr/data/config/ -rf`, and
the printer's busybox unlinks a dangling symlink rather than writing through
it, so printer.base.cfg and the seven beside it come back on every stock
flash. The ff-*.cfg links left behind resolve to nothing and are included by
nothing. Even the SAVE_CONFIG block our Klipper wrote into printer.cfg is
harmless -- configfile.py marks every autosave section valid through
access_tracking, so `[ff_tool 0]` there is not a config error on a stock
klippy. All three were put to the printer's own binaries in the replica.
What survives is /usr/prog/klipper/klipperDaemon. Every release links it at
the mod, whose `start` does nothing on purpose -- klippy is an s6-rc longrun
and a second unsupervised one would fight it for /dev/ttyS4 -- and the stock
package has no klipperDaemon to copy over it: not in the software component,
not in its md5sum.list, no line in run.sh. Stock's start.sh ends in
`klipperDaemon start`, so the UI starts and klippy never does.
installer/recovery.sh is the repair, packed by bin/pack-recovery.sh into a
.tgz that carries no mod at all: FlashForge's own klipperDaemon, taken off a
factory /usr/prog and gated on its md5, and their Klipper configs out of the
stock package the build reads. It sweeps FlashForge's config directory by
shape rather than by a list of names -- a symlink into $MODDIR there can only
be ours -- refuses to run while the mod is still the firmware, and never
touches printer.cfg, which no package has a copy of to put back. Output goes
to work/recovery/: bin/pack.sh wipes work/out, and the replica lane installs
the newest .tgz there as the mod under test.
qa/replica/test_recovery.py holds the whole story against a real machine: the
link the mod leaves, the busybox cp, the refusal, `klipperDaemon start`
leaving no pid file, then the same command forking a real klippy once the file
is back.
Publishing lives in Klipper4FlashForge/stock-recovery, which checks this repo
out and releases there, so a repair for owners of old releases is not buried
among firmware releases they must not flash to get it.
Two things found on the way, both in the harness rather than the mod:
seed-prog.sh appended USER-CONFIG-MUST-SURVIVE as a plain comment after the
SAVE_CONFIG header, and Klipper drops the entire autosave block on the first
line there that does not start with '#*#'. Every replica ran with klippy
seeing none of the machine's saved PID, shaper, mesh or probe values, and
failing on an unrelated-looking missing option. It is written inside the block
now, an older image's copy is repaired in place, and test_install.py asserts
the invariant.
installed_image() keyed its cache on the package md5 alone, so a rebuilt
PRINTER_IMAGE silently handed back a bake from the old base -- which made the
fix above read as ineffective twice before the cache was the suspect. The tag
mixes in the base image id now, and build-printer-image.sh takes IMAGE_TAG so
a rebuilt image can be published without moving a tag ci.yml pins.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hdzEqXuFcY4xXALGPbBFV
* Show the first-boot screen instead of describing it
bin/preview-boot-screen.py already renders every ffscreen.py phase to PNG
on the host, byte-identical to what the printer draws (make boot-screen-sim
proves it against the real replica). Four of those frames -- waiting,
importing, saving, complete -- now sit in installing.md's first-boot
walkthrough instead of leaving the reader to picture a progress bar from
prose alone.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RMV6mRtJ4dCxAj2QAifT8v
* Two big frames beat four small ones
24% width left the boot-screen text unreadable. Down to importing and
complete at 48% -- the same sizing the README already uses for the
HelixScreen pair -- and dropped the two frames no longer referenced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RMV6mRtJ4dCxAj2QAifT8v
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
The pages written on top of the old README inherited its premise: that after
flashing you face a gauntlet -- go/no-go checks, a safety net, a mandatory
calibration -- before the machine can be trusted with a model. That is not
what happens. The factory numbers import themselves on the first boot, a bed
mesh loads at the start of every print, and the mod is built to run the files
the stock firmware ran. A printer that printed before the flash prints after
it. "Your first print" now says so in its first line, and everything under it
is optional, ordered by what you would actually reach for: check the offsets
are applied, and calibrate only if that disagrees with the machine.
Three audiences now, because owner and contributor was not the real split.
"For experienced users" sits between them: How a print runs, and How
calibration works. Someone who knows Klipper and wants to change what happens
around their file has a place to go that is neither a walkthrough nor the
build system.
What was cut is most of what changed. Pages that were cryptic to the reader
they were aimed at -- Printing, Upgrading -- are out of the nav and kept on
disk to be rewritten rather than deleted. Within the pages that stayed:
Expected output, Probe sampling, What is being measured, the symptom table,
the dark-screen diagnosis, TOOL_Z_ADJUST, PLATE_CHECK, the ff-*.cfg
inventory, [ff_legacy] and SAVE_CONFIG in a paragraph about factory
calibration. Filenames and internals earn their place on an owner page only
when the reader has to type them or look at them; the rest moved to the
experienced pages or to Internals, where the audience wants them.
Calibration became a section rather than a page, because tool offsets are not
the only calibration: bed mesh has its own page now, and its own gotcha
written down -- BED_MESH_CALIBRATE writes `default`, a print loads
`MESH_DATA`, so a mesh probed by hand is a mesh no print will use. Input
shaping is described but has no procedure page yet.
Several claims came out because they were not true. "Is this for you" listed
calibration and input shaping as things the mod gives you; both are the
touchscreen's own sequences, recovered and reimplemented, and the notes say
so plainly. What the mod actually gives you is that anything speaking
Moonraker can drive the machine -- on stock, FlashForge's Klipper does not
toolchange at all, it raises a flag and waits for an application that is not
watching a Mainsail print, and the print hangs at the first T2. The page now
opens by telling most owners not to flash it.
Contributors are still deferred. Their pages are regrouped, not rewritten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3XZh4SqPdXAowVndz6tMr
Fourteen sections, install through troubleshooting, in the one file that
existed when there was nowhere else to put them. The site gave the manual a
home; this moves it there and orders it by what the reader is doing rather
than by which subsystem owns the answer. Someone whose printer will not boot
should not have to know that the symptom table lives in a file called
hardware-testing.md.
Three topics were documented two and three times over, and each copy was free
to drift: install in README and toolchange.md, calibration in README,
calibration.md and toolchange.md, slicer setup in README and toolchange.md,
"before you start" in all three. Each is now in one place.
The owner path is Is this for you -> Installing -> After the flash -> Your
first print -> Nozzle-offset calibration -> Printing -> Upgrading -> When
something goes wrong, with error codes, versions and how-it-works behind a
Reference group. The README keeps what a front door keeps: what this is, the
status checkboxes, what you give up, which file to download, and where to go
next.
toolchange.md was four documents in one 38 KB file. The owner half -- slicer
setup, filament, runout, the offset check before a first print -- is in
Printing and Your first print; the design notes, input shaper, roadmap,
HelixScreen and reverse-engineering notes stay, and the page moves to
Internals. hardware-testing.md was split down the middle by audience the same
way: the go/no-go checks and the symptom table were the owner's, and only
keeping the two verification files honest as the macros change is ours.
Two things this fixes rather than moves. The error-code table was
notes/70-error-codes.md, an internals note the README sent owners to; it is
docs/error-codes.md now, a page. And toolchange.md still opened "Not yet run
on hardware" while the README's checkboxes described a Creator 5 Pro that has
been printing for weeks -- the two pages have disagreed since the first
hardware run.
Contributors are deferred, as agreed: those pages are regrouped, not
rewritten. The nav says so.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3XZh4SqPdXAowVndz6tMr