crossdirect's /native bridge breaks under local podman (cc: cannot execute
cc1: posix_spawnp ENOENT in meson setup) while qemu-only builds work fine;
the env flag routes the affected packages (libqmi/MM/libcamera + a new
explicit imsd pre-build, since install has no per-package flag) through
--no-cross. Identical package output, slower build; kernel stays
cross-native. CI behavior unchanged when the env is unset.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
Divide the softISP statistics window into 16x12 zones and, when a white
point locus is tuned, vote only with zones whose implied gains lie within
zoneGateMargin of the locus - a large coloured light source can no longer
drag the white balance. Validated on-phone 2026-08-24: keyboard-scene A/B
shows a ~1700 K estimate shift caused solely by the gate (desk renders
neutral instead of blue); torch-toggle stability equal or better than r8
(settle 1.35-1.79 s, ON-edge repeatability +-0.011, CCM churn 21 vs 30
switches); AF regression clean. Evidence:
journal/camera/captures/2026-08-24-awb-zonegate-validation.md
Assisted-by: Claude:claude-fable-5
The package declared BSD-3-Clause while shipping aw88261_acf.bin, a
verbatim proprietary Awinic blob extracted from the stock vendor
partition - an affirmative false claim about the file. Mark the license
compound (BSD-3-Clause AND proprietary) and document per-file provenance;
the durable fix (FairBlobs adoption or install-time on-device extraction)
is tracked in the audio journal.
Assisted-by: Claude:claude-fable-5
pkgver 7.1.2 -> 7.2.0; config regenerated from the pmOS 7.2.0-r0 config
plus the FP6 bring-up fragment (same enables as before), olddefconfig'd
against the rebased combined-stable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
milos-linux combined-stable now carries the camera-main merge
(af49850e65bd): camss C-PHY support, the IMX896 main sensor, the DW9784
AF controller and the board DTS for all three (the VL53L3 ToF node is
DTS-only for now, its driver is future work). Kernel config gains
CONFIG_VIDEO_IMX896=m + CONFIG_VIDEO_DW9784=m - the camss core, CAMCC
and CCI are on since the ultra-wide commit, and the libcamera side
(IMX896 tuning, contrast AF, AWB stabilization) already ships since
aport r8.
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>
The softISP AWB is pure gray world, so panning swings ColourGains with
the frame average (white wall renders green when the frame is
warm-dominated, dark desk renders red when cool-dominated) and the CCM,
interpolated over a CT estimated from those gains, amplifies and
quantizes the swings.
Patch 0015 (ours, original work) adds optional per-sensor Awb tuning to
the simple IPA: a piecewise-linear locus of calibrated illuminant white
points in gain space that the gray-world estimate is clamped to
(clampMargin), a per-stats-frame EMA on the applied gains (damping)
with a fast-converge path for persistent illuminant changes, and CT
interpolated from the applied gains' position along the locus - on the
same scale as the tuning file's ccms table - instead of the generic
estimateCCT(). Tuning files without whitePoints keep the previous
behaviour exactly, so every other sensor is unaffected.
imx896.yaml gains the locus from the stock tuning blob's 10-point
per-illuminant AWB calibration (white points and their exactly
reciprocal gain triplets, cross-validated): the 7 on-locus points as
nodes, the 3 fluorescent points admitted via clampMargin 0.35. The
5000 K label is the blob's own proven anchor; 2856 K (A) is locked by
the fluorescent trio projecting onto the 2856-5000 chord at ~3960 K
(TL84); the rest are geometry-derived approximations.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Raw-RDI dark frames (phone face-down, minimum analogue gain) put the
pedestal at exactly 64 in 10-bit (mean 63.98, median 64, p1/p99 63/65)
= 4096 on the 16-bit scale. The softISP's dynamic estimate ran at 48;
the 16-code residual was amplified by the CCM into colour casts in
dark image regions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds imx896.yaml (CCMs for 2800/4000/5750 K) so the main camera gets
real colour instead of the uncalibrated fallback. The matrices are
numeric calibration data read out of the stock Android tuning blob -
measured spectral response of this sensor, not authored expression -
and are shipped by the project owner's decision, consistent with the
vendor-derived data this image already carries. Durable replacement is
to measure our own from a colour chart.
Note the file lists Adjust/Agc/Af as well as BlackLevel/Awb/Ccm: a
sensor-specific tuning file REPLACES the fallback's algorithm list, so
omitting them silently disables auto-exposure and autofocus.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hardware finding from the first r4 run on the phone: the focus-loss
detector compared the settled scene against the maximum sharpness
recorded during the sweep, which was measured under a different AGC
state. On the FP6 that maximum read 4848088 and the same position two
stats frames later read 1995445, so the detector fired immediately and
the lens swept forever. Patch 0014 takes the reference after the lens
settles and requires four consecutive out-of-band frames.
Verified on the phone: r4 re-swept without end, r5 completes one sweep
and stays put.
The DW9784 VCM works and libcamera discovers it through the sensor's
ancillary link, but nothing in the software ISP ever moves it. Backport
the out-of-tree autofocus work onto v0.7.2:
- 0007-0009 are Vasiliy Doylov's focus control, contrast autofocus and
focus-loss detection from the softisp-playground branch;
- 0010 is Pavel Machek's Librem5-tested robustness work (centre-window,
brightness-normalised sharpness, two-phase sweep, settle skip),
squashed and adapted;
- 0011-0013 are ours: the lens write no longer sits inside the
no-frame-start-emitter branch, the lensless-camera paths are guarded,
and AfMode is advertised with a continuous default so that stock
applications get autofocus without sending AfTrigger.
Provenance and the adaptations made to each patch are recorded in the
patch commit messages.
Teaches the software ISP's AGC the IMX896 gain law
(gain = 16384/(16384-code), inverted from the vendor driver and
round-tripped against all 3009 vendor gain-table entries, max error
0.049%) and adds the sensor properties (1.0um unit cell, test-pattern
map). Same shape as the OV13B10 pair; both verified to apply and
compile on v0.7.2 after 0001-0004.
The extracted-CCM tuning yaml is deliberately NOT packaged yet - the
color matrices come from the vendor Chromatix blob and the licensing
call is open (see the camera journal).
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>
Kernel config: CONFIG_VIDEO_OV13B10=m + CONFIG_VIDEO_DW9714=m — the camss
core, CAMCC and CCI were already enabled; the sensor and VCM drivers were
the only missing pieces. The camera carries themselves land via
milos-linux combined-stable (merge of the 'camera' topic branch,
nondescriptpointer's 5 patches, authorship preserved).
libcamera: new temp/ aport overriding pmOS 99990.7.2-r1 with -r2, adding
nondescriptpointer's OV13B10 sensor helper (gain = code/128, enables the
software-ISP AGC/AWB) and sensor properties patches on top of the pmOS
0.7.2 APKBUILD. Patch sha512s re-recorded from the actual files (his
APKBUILD diff carried stale hashes); all four patches verified to apply
against the v0.7.2 tarball.
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>
The stale-rpmh-votes GMU wedge (GMU fw init timeout under bursty GPU
use) is fixed in kernel builds from combined-stable >= 2026-08-14 by
carrying upstream 'drm/msm/a6xx: Fix stale rpmh votes after suspend'
(d9108bfdb746, drm-msm msm-next). This push also triggers the image
rebuild that picks the fix up.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The lock-check piped 'fastboot oem device-info' into grep -q, which exits
on first match; fastboot dies of SIGPIPE mid-transaction and leaves the
bootloader's fastboot state machine wedged, hanging the NEXT command
(the mysterious erase-dtbo stall). Capture-then-test everywhere.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every fastboot step gets a deadline and one retry (this bootloader hangs
per-command occasionally, and desktop ModemManager probes freshly
enumerated fastboot devices, blocking the USB claim). Refuse to run on a
locked bootloader before touching anything. SSH_ASKPASS_REQUIRE=force
self-answers the login password on OpenSSH >= 8.4.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OpenSSH deliberately reads passwords from the terminal only; since 8.4
an askpass helper overrides that even with a tty. The fresh image's
public default now answers both ssh and sudo - the installer runs with
zero typed credentials on any modern distro (older OpenSSH falls back
to one prompt).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When the wait times out the phone has usually booted fine; it is the
PC's side of the gadget link that nobody configured (or a network
manager grabbed it with the wrong profile - bitten by that ourselves).
Spell out the ip-link/ip-addr recovery and that rerunning is safe.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ssh ControlMaster keeps one authenticated connection (login typed at
most once, or never with sshpass installed); sudo answers itself via a
SUDO_ASKPASS helper carrying the image's public default password (sudo
-S would have eaten the boot image's first bytes from stdin). Helper
lives on tmpfs and evaporates with the install reboot.
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>
Proven 2026-08-09: RAM-booting writes nothing (modemst byte-identical
after), so a fresh install that dd's boot_a and userdata from the booted
Linux never triggers the ABL's boot-flash NV wipe. Classic flash flow
documented as the wiping alternative. Details in journal/modem.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Isolated by experiment (2026-08-09, journal/modem): flash boot alone
zeroes modem NV; erase dtbo and idle fastboot visits are safe; on-device
boot-deploy (incl. apk kernel upgrades) never trips it. Likely ABL
anti-tamper on boot-image overwrite under an unlocked bootloader.
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>
3 of 38 glib tests SIGABRT under qemu-user emulation; they pass on
native builders and do not touch the patched GNSS paths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>