The pmOS gitlab truncates clones under load (early EOF / invalid
index-pack); the pip install runs in the root branch before clone_retry
exists, so give it its own 3-attempt loop.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Charger-insertion boots (androidboot.mode=charger, ABL-appended) divert to
a minimal charging.target instead of the full UI, ending the dead-battery
bootloop: ADSP charging/USB-PD runs, splash+panel killed ~6-10s in via an
initramfs hook, modem+cdsp stopped, radios/sensors suppressed, CPU capped.
Power key reboots to a normal boot, volume-up shows battery status,
volume-down enables USB ssh, unplug powers off. Measured >= breakeven on a
100mA-classified SDP port, strongly net-positive on real chargers.
Suspend duty-cycling (~13mA floor) exists behind an off-by-default flag:
resume from deep suspend intermittently kills the UFS link (hibern8 exit
failed ret=5) - do not enable until that kernel bug is fixed.
Byte-identical to the deployment verified on the dev phone 2026-08-24
(journal/power: r5 armed tests, crash autopsies, measurements).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gitlab.freedesktop.org's on-demand archive endpoint 503/504s for hours
at a stretch: runs #25, #27, #30 and #31 all died in 'abuild checksum'
fetching the pinned libqmi tarball, outlasting the 3x30s in-run retry.
git clone is served from a different code path and holds up (verified
against all three repos while the archive endpoint was flaky), so clone
libqmi/ModemManager/libcamera (retried) and git-archive the pinned refs
into the aports, the same way the kernel and imsd tarballs are already
produced. The pins stay single-sourced in the APKBUILDs.
libcamera gains a checksum step: its committed sums were for the
fd.o-served tarball, and git-archive output is not byte-identical.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Run #25 died at 'pmbootstrap checksum libqmi' on a bare HTTP 503 from
gitlab.freedesktop.org. That host serves three of this pipeline's inputs
(libqmi, modemmanager and now libcamera), and its 503s are transient - it
answered 200 again minutes later - so a hiccup there should cost a retry,
not a 2-hour run.
Same shape as clone_retry, applied to the checksum and build calls that
fetch sources. The kernel and imsd checksums need no retry: their tarballs
are generated locally by this script.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
34cfc09 added aports/temp/libcamera but never taught build.sh to copy it,
so run #24 built the image with pmOS's stock 99990.7.2-r1 and published no
libcamera package at all. Copy it like libqmi/modemmanager (upstream aport
deleted first - duplicate pkgnames are a pmbootstrap hard error) and build
it explicitly so the -r2 apk reaches the registry publish step.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Run 22 failed with 'catcrafts-fp6-repo: Could not find it in pmaports
or any APKINDEX': build.sh copies each overlay aport explicitly and
this one was never in the list, so pmbootstrap could not resolve the
new extra_packages entry.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The catcrafts-fp6-repo aport (signing key + repositories entry) existed
but nothing installed it: images shipped with the CI-built packages
baked in and no update channel, so 'apk upgrade' never delivered new
kernel/imsd builds despite CI publishing every apk to the registry.
Add it to extra_packages and document the registry in the README.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
erase dtbo + flash userdata + RAM-boot + dd boot_a from Linux + verify
modem NV and report honestly. Shipped in dist/ with every release; README
points at it. The one believed-safe-but-unisolated step (userdata flash)
is self-verified by the script's final check.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-system audit findings: without an explicit provider selection the
image installed real PulseAudio (Plasma Mobile hard-path), which claims
the card and ships a wireplumber fragment disabling hardware.audio -
zero sinks forever. Mirror the dev phone's world: pipewire backend meta
+ pipewire-pulse + echo-cancel in extra_packages, pulse meta banned via
apk conflict in fp6-device-tweaks. The two hand-made /etc audio
fragments (wireplumber no-ACP rule, AEC pair for VoLTE speakerphone)
move into soc-fairphone-fp6-audio.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-system audit on the flashed phone found the IMU dead: the journal's
documented reinstall-loss trio (inv-icm42600-spi modules-load - fallback-only
SPI node never coldplugs; the accel poll udev rule for auto-rotate; the
iio-sensor-proxy libssc-crash restart drop-in). All device-critical, none
personal - now packaged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two device-critical pieces previously applied only by the dev restore
script: masked sleep targets (idle-suspend resets the WCN combo firmware
and kills wifi ~40min - a device defect, not personalization) and imsd
enabled at boot, gated on /etc/imsd.env existing so unconfigured systems
don't boot a failing unit. A stranger now needs exactly: flash, wifi via
UI, write imsd.env, restart imsd.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pmbootstrap's install-time build plan is not topologically sorted; the
versioned makedep made that a hard error instead of a stale-dep build.
Explicit bottom-up build restores order; no-op when current.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pmbootstrap's build plan is not dependency-ordered: MM built first and
grabbed the cached 1.39.0 libqmi from the volume's package repo. The
versioned makedepend states the real requirement and forces our bumped
libqmi to build first. Kernel pkgver gains the source commit date so
registry-subscribed phones receive kernel updates.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The forgejo VM occasionally 500s under crawler load - a clone blip
should cost 10 seconds, not the run. dist/ keeps its inode so a shell
cd'd into it no longer breaks the next podman start.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
libqmi: the upstream-merged (!470, in no release yet) LOC Register Events
client-identification TLVs, taken verbatim from upstream main (532de37e).
modemmanager: the AFW engine unlock + Position Report derivation (!1463,
still draft upstream, review-hardened and verified on device). Both as
patches on Alpine's git-snapshot aports, pkgrel=100.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
imsd turns out to be fully public already (0.2.7 snapshot + emergency
stage 1 + the make build path) - no tag needed, same git-archive dance as
the kernel. callaudioshim was a load-bearing unpackaged home-dir script on
the phone (callaudiod replacement, working in-call mic mute); now an aport
autostarted at phase 1. kde-telephony's modem daemon autostart is hidden
via /etc/skel from the imsd package, mirroring the phone's user override.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Files copied byte-identical from the tested dev phone; installed to the
exact deployed paths (the spaced tplg/UCM filenames come from the machine
driver's card name). Wired into the image via extra_packages.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Partition nodes (loopNpM) only appear via the host devtmpfs; a privileged
container's own /dev never gains them. Drop the static mknod dance, warn
when /dev is not the host's.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Alpine's packaged pmbootstrap predates pmaports' master->main rename and
fails reading channels.cfg. Pinning also matches the version the rest of
this script was written against.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
'pmbootstrap config' demands an existing config file, so write
pmbootstrap_v3.cfg ourselves (INI, aports/device/ui/systemd). Explicit
set -eu because 'sh script' ignores shebang flags - run 3 shipped a
3.5KB 'image' because failures didn't propagate. dist/ is now the only
build-user-owned path, so the tag step's git works again.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Learned from the pmbootstrap 3.11 source: aports overlays must replace
upstream dirs in one tree (duplicate pkgnames are a hard error), pmbootstrap
refuses root (drop to a sudo-capable build user), and export symlinks are
boot.img + fairphone-fp6.img. Stage 1 builds without imsd until the v0.3.0
tag exists. Temporary push trigger for bring-up.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kernel aport forked from pmaports 7.1.2-r0, repointed at milos-linux
combined-stable with the tested FP6 config (+EFI_ZBOOT for packaging);
imsd + nftables aports from the pending pmaports submission. build.sh
carries TODO(validate) markers - not yet run end-to-end.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>