Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
411 commits
Select commit Hold shift + click to select a range
d021534
docs(adr): 0004 — self-hosted Attic for NixOS binary distribution
mrosseel May 28, 2026
82f26b0
feat(nixos): wire cache.pifinder.eu — Attic standalone, cachix removed
mrosseel May 28, 2026
43c3d2a
chore: stamp build [skip ci]
github-actions[bot] May 28, 2026
9c32f22
ci(nixos): gate stamp-build on push events (lets brickbots PR runs su…
mrosseel May 28, 2026
ba8283e
Merge upstream/main into nixos
mrosseel Jun 17, 2026
8678421
fix(comets): make vectorized propagation work on skyfield >= 1.46
mrosseel Jun 17, 2026
c069005
fix(catalogs): restore upstream's catalog module (T9 search + disk ca…
mrosseel Jun 17, 2026
f8c82eb
test(software): update version literals for MIN_NIXOS_VERSION 3.0.0
mrosseel Jun 17, 2026
5084410
fix(logging): persist active log-config selection in PiFinder_data
mrosseel Jun 18, 2026
298275e
fix(solver): load tetra3 DB by name instead of an explicit path
mrosseel Jun 18, 2026
7eef66a
ci(nixos): publish releases to retained Attic cache, drop Cachix
mrosseel Jun 18, 2026
dea4e56
merge: bring nixos up to date with upstream/main
mrosseel Jun 18, 2026
3a08c27
chore(nixos): stop tracking .direnv build cache
mrosseel Jun 18, 2026
606664b
feat(nixos): manage Python deps with uv2nix instead of hand-written d…
mrosseel Jun 18, 2026
d18bf30
ci(nixos): cache lint/test/type-check via Attic, drop dead magic-nix-…
mrosseel Jun 18, 2026
3ae56cd
fix(nixos): reliable WiFi AP fallback, clearer offline UX, surface sy…
mrosseel Jun 18, 2026
8ca2139
ci(nixos): run build fallback on native ubuntu-24.04-arm instead of QEMU
mrosseel Jun 19, 2026
b2fc711
fix(nixos): provision uv2nix build backends for dbus-python, pygobjec…
mrosseel Jun 19, 2026
ab0ead7
fix(nixos): make the uv2nix env build on aarch64 (build backends, hea…
mrosseel Jun 19, 2026
0985ec0
fix(nixos): provide setuptools backend for timezonefinder (sdist on a…
mrosseel Jun 19, 2026
cf1eef7
ci(nixos): tokenless Attic pull for fork PRs + always() on stamp-build
mrosseel Jun 19, 2026
f22d398
chore: stamp build [skip ci]
github-actions[bot] Jun 19, 2026
9ed7d3a
fix(network): make D-Bus wifi add/delete/list robust
mrosseel Jun 19, 2026
30acc36
fix(nixos): repair non-root /nix/store ownership before NetworkManager
mrosseel Jun 19, 2026
3750286
chore: stamp build [skip ci]
github-actions[bot] Jun 19, 2026
ba2496a
fix(nixos): patch RPi.GPIO board detection for mainline-DT Pi 4
mrosseel Jun 19, 2026
fade0f5
chore: stamp build [skip ci]
github-actions[bot] Jun 19, 2026
f87bba1
fix(nixos): bind-remount the store in the ownership repair (don't tak…
mrosseel Jun 19, 2026
dbbd598
chore: stamp build [skip ci]
github-actions[bot] Jun 19, 2026
1668edc
fix(network): report the live wifi mode instead of the init-time cache
mrosseel Jun 19, 2026
b57aa23
fix(nixos): surface nix errors from pifinder-upgrade instead of swall…
mrosseel Jun 19, 2026
115c19a
chore: stamp build [skip ci]
github-actions[bot] Jun 19, 2026
b6d3582
fix(nixos): drop the invalid pifinder-release pubkey placeholder
mrosseel Jun 19, 2026
be112f7
feat(nixos): set root password declaratively via hashedPassword
mrosseel Jun 19, 2026
ea86c0c
fix(nixos): build the migration tarball with root-owned paths
mrosseel Jun 19, 2026
7158f42
fix(nixos): make picamera2 previews optional for headless camera
mrosseel Jun 19, 2026
7b51f38
chore: stamp build [skip ci]
github-actions[bot] Jun 19, 2026
0d2e4e4
docs(nixos): note pifinder user must stay initialPassword (not hashed)
mrosseel Jun 20, 2026
a383881
chore: stamp build [skip ci]
github-actions[bot] Jun 20, 2026
58daae3
fix(nixos): wait for clock sync before first-boot download; real OLED…
mrosseel Jun 20, 2026
67ab181
chore: stamp build [skip ci]
github-actions[bot] Jun 21, 2026
df21998
merge: bring nixos up to date with upstream/main
mrosseel Jun 23, 2026
3e18c91
chore: stamp build [skip ci]
github-actions[bot] Jun 23, 2026
9bfe25b
test(software): _fetch_github_releases propagates network errors
mrosseel Jun 23, 2026
1a759d1
chore: stamp build [skip ci]
github-actions[bot] Jun 23, 2026
4708a39
fix(nixos): pin explicit NTP servers so a dead DHCP NTP server can't …
mrosseel Jun 23, 2026
0d299f4
chore: stamp build [skip ci]
github-actions[bot] Jun 23, 2026
5a7640a
test(nixos): port web integration tests to Nix
mrosseel Jun 23, 2026
0bfd6ae
chore: stamp build [skip ci]
github-actions[bot] Jun 23, 2026
851c6f1
docs(nixos): add NixOS deploy/update context (channels, rollback, bui…
mrosseel Jun 24, 2026
f263b74
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
fc18bde
fix(ci): make Lint & Test workflow green again
mrosseel Jun 24, 2026
d048d34
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
599d08d
feat(nixos): size-based download progress + availability check + prom…
mrosseel Jun 24, 2026
d26db31
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
b7cb42e
fix(ci): add user nix profile to PATH so attic resolves on the migrat…
mrosseel Jun 24, 2026
2a4f376
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
bb824aa
fix(network): AP no longer self-starts and beats client WiFi at boot;…
mrosseel Jun 24, 2026
4899492
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
ba83bc2
feat(status): show the active uplink (Ethernet when wired) and live W…
mrosseel Jun 24, 2026
4aa5978
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
fb45b22
fix(nixos): upgrade/first-boot size query is advisory, never aborts
mrosseel Jun 24, 2026
0999ea7
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
32d5531
docs: convert contributors guide to the Nix workflow (deps, channels,…
mrosseel Jun 24, 2026
0b7d399
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
26b1bb6
fix(nixos): fast delta-only download-size query for the progress bar
mrosseel Jun 24, 2026
46e4c25
fix(nixos): make software updates fail closed
mrosseel Jun 24, 2026
3728d85
fix(ui): keep unstable trunk and testable PRs visible
mrosseel Jun 24, 2026
9d6a5d2
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
4a37f0a
fix(ui): read testable PRs from upstream
mrosseel Jun 24, 2026
07db713
chore: stamp build [skip ci]
github-actions[bot] Jun 24, 2026
210f2c0
feat(nixos): drive update channels from manifest
mrosseel Jun 24, 2026
d1657e6
ci(nixos): keep manifest branch single-file and concurrency-safe
mrosseel Jun 24, 2026
9b7c725
ci(nixos): simplify publish_manifest.sh — drop one-time source-tree c…
mrosseel Jun 25, 2026
5aa3b27
feat(nixos): rotate Attic cache keys after S3 chunk-store cutover
mrosseel Jun 25, 2026
9fcfeb5
docs(nixos): add handover notes for manifest-driven update channels
mrosseel Jun 24, 2026
a4f8db2
ci(nixos): stop building on mrosseel pushes — PRs/dispatch only
mrosseel Jun 25, 2026
0082044
fix(ci,software): manifest from brickbots; build-native verify-only o…
mrosseel Jun 25, 2026
dfcd5b6
ci: build+publish on brickbots pushes only (scoped push trigger)
mrosseel Jun 25, 2026
b1cf8bc
ci(nixos): align CI workflows with brickbots PR #493 (no diff)
mrosseel Jun 25, 2026
cd6b7d7
ci(nixos): rotate Attic dev cache key in nixos-pr-build.yml (sync wit…
mrosseel Jun 25, 2026
10eb481
revert(nixos): restore 8UU dev cache key — undo the accidental S3-cut…
mrosseel Jun 25, 2026
e289db6
refactor(nixos): rename migration.nix → device.nix
mrosseel Jun 25, 2026
7e0bbb0
feat(nixos): live within-path download progress + key-proof + avahi/h…
mrosseel Jun 25, 2026
73d0cc6
fix(catalog): rebuild stale object cache so the details screen stops …
mrosseel Jun 25, 2026
f10edd8
fix(nixos): boot the selected camera — repoint extlinux DEFAULT + reboot
mrosseel Jun 26, 2026
f886940
docs(adr): correct Attic chunking claim in ADR 0001
mrosseel Jun 26, 2026
ef6b735
perf(nixos): split tetra3 + fonts out of pifinder-src
mrosseel Jun 26, 2026
9f842e6
feat(nixos): rollback to previous generation via Software screen
mrosseel Jun 26, 2026
3315105
feat(nixos): first-boot resolves full system from update manifest (st…
mrosseel Jun 27, 2026
8709bb3
build(nixos): manage tetra3 solver as a uv dependency, drop submodule
mrosseel Jun 29, 2026
19d21f5
docs(claude): comments state present facts, not change history
mrosseel Jun 29, 2026
4ddab4b
ci: add NixOS release workflow (SD image + migration tarball, fork-so…
mrosseel Jul 2, 2026
82b54e6
ci: NixOS release workflow (SD image + migration tarball, sha256, nat…
mrosseel Jul 2, 2026
a241dd0
fix(nixos): provision setuptools build backend for cedar-solve
mrosseel Jul 2, 2026
2b59040
feat(nixos): drop 4.9GB catalog images from SD image (fetched on demand)
mrosseel Jul 2, 2026
4cffb61
ci: sync release workflow + update_manifest (manifest population, mig…
mrosseel Jul 3, 2026
6875a6d
fix(migration): generate NM wifi keyfiles in Python pre-reboot with c…
mrosseel Jul 3, 2026
74bd21e
feat(nixos): libnm net-policy daemon (wired > wifi client > AP), repl…
mrosseel Jul 3, 2026
a443e2f
feat(nixos): trial/commit boot watchdog — auto-rollback only unproven…
mrosseel Jul 3, 2026
82e44a0
fix(nixos): tetra3 import straggler + identify builds by store path, …
mrosseel Jul 3, 2026
d0fc699
docs(nixos): grill session — recovery ladder, trial/confirm, update-m…
mrosseel Jul 3, 2026
f42d66b
feat(nixos): self-arming boot watchdog + failure splash — new generat…
mrosseel Jul 3, 2026
bad6f79
feat(nixos): retire pifinder-build.json, minimal migration tarball (A…
mrosseel Jul 4, 2026
badf162
feat(nixos): watchdog reports on confirmed-generation failure + recov…
mrosseel Jul 4, 2026
dc158bd
revert(migration): drop the Python keyfile generator from nixos — mig…
mrosseel Jul 4, 2026
44cebba
chore(nixos): drop Raspbian-side migration code — it runs pre-migrati…
mrosseel Jul 4, 2026
c9fc578
merge: upstream/main into nixos (Rev-4 hardware, tz fixes, obslist CS…
mrosseel Jul 4, 2026
a3334e5
feat(nixos): rev-4 hardware enablement — buzzer PWM0/GPIO12, gpio-pow…
mrosseel Jul 4, 2026
108db93
build(nixos): platform-mark hardware-only deps so uv sync works on x8…
mrosseel Jul 4, 2026
8a71ef4
fix(nixos): drop full linux-firmware (723MB) — Pi 4 needs only the Br…
mrosseel Jul 5, 2026
740ca3c
ci: sync release.yml (tarball budget guard)
mrosseel Jul 5, 2026
bbbadb5
docs(nixos): ADR 0007 — extlinux and kernels on ext4, FAT is firmware…
mrosseel Jul 5, 2026
042af10
fix(nixos): first-boot resolves from the manifest unconditionally — d…
mrosseel Jul 5, 2026
754e5aa
fix(nixos): bake the first-boot fallback target into the migration im…
mrosseel Jul 5, 2026
a1cd400
fix(nixos): first-boot writes current-build.json — the device identit…
mrosseel Jul 5, 2026
a05ec81
fix(nixos): stable udev name for the GPS UART — kernel ttyAMA numberi…
mrosseel Jul 5, 2026
51b8abf
fix(software): hide the exact running build from the unstable list
mrosseel Jul 5, 2026
6bf94c3
fix(gps): correct UBX NAV-SVINFO field offsets (off by one)
mrosseel Jul 5, 2026
b15b66d
fix(gps): decode NAV-SAT per spec for protVer >= 15 receivers
mrosseel Jul 5, 2026
77aef3b
fix(gps): don't count acquisition candidates as satellites seen
mrosseel Jul 6, 2026
a1107a5
fix(gps): count acquiring satellites as seen, not only code-locked ones
mrosseel Jul 6, 2026
21d2c95
merge: bring nixos up to date with upstream/main
mrosseel Jul 10, 2026
50603c5
fix(nixos): gate manifest availability on real cache presence
mrosseel Jul 10, 2026
336b42c
fix(nixos): override imx462 xclk to 74.25 MHz so the camera streams
mrosseel Jul 11, 2026
240d2dd
style: reformat with ruff 0.4.8 (the version CI pins)
mrosseel Jul 11, 2026
44a3673
ci(nixos): drive lint/type/test checks with uv — this branch retired nox
mrosseel Jul 11, 2026
b6664c4
fix(sys): restart the full pifinder.service unit name so the NixOS su…
mrosseel Jul 11, 2026
6370802
feat(nixos): advertise Samba share over mDNS via avahi (_smb._tcp)
mrosseel Jul 11, 2026
028fbdb
feat(nixos): add on-device dev shell, wire into direnv, CI and docs
mrosseel Jul 12, 2026
7f471d0
fix(nixos): make Samba share guest-accessible like Raspbian (no passw…
mrosseel Jul 12, 2026
c8d7ae2
merge: bring nixos up to date with upstream/main
mrosseel Jul 13, 2026
a651263
feat(nixos): pygame SDL runpath fix + sys_utils dev fallback for loca…
mrosseel Jul 13, 2026
7e81c63
fix(nixos): drop unwired pygame keyboard drain that stole keypresses
mrosseel Jul 13, 2026
7ca7c94
refactor(nixos): gate on-device dev git/rsync behind pifinder.devMode
mrosseel Jul 13, 2026
50a0b2f
fix(imu): bit-banged I2C bus + resilient IMU monitor loop
mrosseel Jul 13, 2026
80a4513
fix(nixos): expose SkySafari and stabilize mDNS
mrosseel Jul 13, 2026
30a6dc1
fix(solver): re-open cedar shmem per solver generation
mrosseel Jul 13, 2026
b0f4136
Make `nix develop` work on MacOS (apple silicon)
jscheidtmann Jun 29, 2026
0ee8f68
fix(update): report the running build, not the pre-reboot label
mrosseel Jul 13, 2026
0d08d00
fix(web): network settings apply live — no restart, honest button
mrosseel Jul 13, 2026
63c8cb1
feat: screen off burn-in protection + debug camera test mode
mrosseel Jun 18, 2026
1cc86e5
style: format camera interface with CI ruff
mrosseel Jul 11, 2026
ed2f7e2
feat: dev mode toggle gating the unstable update channel
mrosseel Jul 13, 2026
84d865a
feat(focus): add raw multi-star focus views
mrosseel Jul 14, 2026
8b33c1d
merge: sync upstream/main into nixos
mrosseel Jul 14, 2026
2f23e8f
feat(sqm): self-calibrating SQM: raw-green photometry, per-frame blac…
mrosseel Jul 14, 2026
f8a76ab
fix(main): require 7x SQUARE dev-mode gesture within a 10s window
mrosseel Jul 14, 2026
edb35a5
fix(focus): center quadrants below title bar
mrosseel Jul 14, 2026
af27c3b
test(focus): cover all display geometries
mrosseel Jul 14, 2026
40877e0
feat(sqm): self-calibrating SQM: raw-green photometry, per-frame blac…
mrosseel Jul 14, 2026
fe331c1
fix(focus): keep preview compatible with Python 3.9
mrosseel Jul 14, 2026
88c1187
refactor(sqm): remove dead noise-floor wiring from the SQM path
mrosseel Jul 14, 2026
21ff721
fix(sqm): robust mzero — median over stars, 70% nonlinearity cut, B-V…
mrosseel Jul 14, 2026
3fd4b0e
fix(sqm): robust mzero — median over stars, 70% nonlinearity cut, B-V…
mrosseel Jul 14, 2026
a2943af
fix: accept -1 (screen off) power state and silence spurious log errors
mrosseel Jul 14, 2026
d4fe46f
feat(sqm): per-sensor sky-passband offset (V-band meter scale)
mrosseel Jul 14, 2026
6e867f5
fix(test-mode): re-apply fake GPS at startup when test mode was persi…
mrosseel Jul 14, 2026
9cefd1c
feat(sqm): per-sensor sky-passband offset (V-band meter scale)
mrosseel Jul 14, 2026
8d98731
fix: make camera test mode follow shared state so it survives restarts
mrosseel Jul 14, 2026
33c0efe
fix(focus): stabilize star centroids and quadrant tracking
mrosseel Jul 14, 2026
ef57317
fix(sqm): compute SQM on imx462/290 and hide default until measured
mrosseel Jul 14, 2026
df332b4
fix(sqm): set imx462/imx290 raw bias_offset to measured 238 ADU
mrosseel Jul 15, 2026
d2e12f0
fix(sqm): stop PedestalEstimator overriding the measured black level
mrosseel Jul 15, 2026
edd23a4
fix(sqm): CAL wizard must send typed ReloadSqmCalibration to the solver
mrosseel Jul 15, 2026
0ee63d6
fix(sqm): set imx462/imx290 raw bias_offset to measured 238 ADU
mrosseel Jul 15, 2026
5b94834
fix(sqm): stop PedestalEstimator overriding the measured black level
mrosseel Jul 15, 2026
6f8ffce
fix(sqm): compute SQM on imx462/290 and hide default until measured
mrosseel Jul 15, 2026
39470c0
feat(sqm): randomize sweep exposure order
mrosseel Jul 15, 2026
4c187c1
fix(sqm): CAL wizard must send typed ReloadSqmCalibration to the solver
mrosseel Jul 15, 2026
2f1f0e9
feat(sqm): randomize sweep exposure order
mrosseel Jul 15, 2026
cc839c9
fix(focus): show single star after quadrant view
mrosseel Jul 15, 2026
14a7a0e
feat(sqm): record effective photometry constants in sweep metadata
mrosseel Jul 15, 2026
8e50e55
feat(sqm): record effective photometry constants in sweep metadata
mrosseel Jul 15, 2026
7f7ab18
feat(focus): stretch full-frame Image view
mrosseel Jul 15, 2026
0507b39
fix(focus): refine readouts, Image contrast, and Single zoom
mrosseel Jul 15, 2026
42c1add
fix(comets): restore vectorized propagation in Nix env
mrosseel Jul 15, 2026
041c92d
docs(sqm): band offset is site-regime dependent, not a pure sensor co…
mrosseel Jul 15, 2026
fa02bec
docs(sqm): band offset is site-regime dependent, not a pure sensor co…
mrosseel Jul 15, 2026
811bfa7
fix(nixos): keep current Skyfield with batched comet support
mrosseel Jul 15, 2026
d72c840
fix(focus): center sparkline gap on readout
mrosseel Jul 15, 2026
107cb7b
fix(focus): space history from rendered number outline
mrosseel Jul 15, 2026
660096d
feat(sqm): session anchor from a reference-meter reading
mrosseel Jul 15, 2026
9a8e173
feat(sqm): session anchor from a reference-meter reading
mrosseel Jul 15, 2026
64eba8c
fix(focus): expire stale history while frames are missing
mrosseel Jul 15, 2026
e88a595
feat(sqm): measured imx296 constants from the 2025-10-31 mono sweep
mrosseel Jul 15, 2026
63030cd
feat(sqm): measured imx296 constants from the 2025-10-31 mono sweep
mrosseel Jul 15, 2026
3ad469a
merge: sqm-fix into nixos
mrosseel Jul 15, 2026
948906c
refactor(sqm): delete the processed-image (PNG) SQM path
mrosseel Jul 15, 2026
d89ff95
merge: sqm-fix into nixos (session anchor, imx296 constants, PNG-path…
mrosseel Jul 15, 2026
1f78ca4
feat(sqm): session anchor from a reference-meter reading
mrosseel Jul 15, 2026
8d4a88e
feat(sqm): measured imx296 constants from the 2025-10-31 mono sweep
mrosseel Jul 15, 2026
7e8a550
refactor(sqm): delete the processed-image (PNG) SQM path
mrosseel Jul 15, 2026
4a3af5e
refactor(sqm): rename Anchor feature to Correct; drop dead correction…
mrosseel Jul 15, 2026
672e727
fix(devshell): add bashInteractive so bash has progcomp/readline
mrosseel Jul 15, 2026
f5955e1
fix(sqm): guard None dark_current in calc; always record sweep SQM me…
mrosseel Jul 15, 2026
85d2524
fix(sqm): create the SQM calculator lazily, on the first solve
mrosseel Jul 16, 2026
730d044
merge: sqm-fix into nixos (lazy SQM calculator creation)
mrosseel Jul 16, 2026
6a9b52b
test(solver): pin cedar shmem reopen-on-restart contract
mrosseel Jul 16, 2026
9d933b5
fix(web): accept comma or period decimal separator in location entry
mrosseel Jul 16, 2026
396bc58
feat(sqm): recalibrate hq sqm_band_offset from 4 referenced sweeps
mrosseel Jul 16, 2026
c3bed19
fix(sqm): reject noise-collapsed wing boundaries; recalibrate band of…
mrosseel Jul 16, 2026
0d2edf0
feat(ui): software update screen polish
mrosseel Jul 16, 2026
552b198
merge: sqm-fix into nixos (wing-boundary floor, band offset recalibra…
mrosseel Jul 16, 2026
6aed601
fix(ui): lift update status line 2px clear of the screen edge
mrosseel Jul 16, 2026
e14251a
chore: retrigger build (built_at manifest stamp)
mrosseel Jul 16, 2026
90ad7c7
fix(software): disable migration unlock on NixOS systems
mrosseel Jul 16, 2026
0e10a6b
refactor(ui): replace 7x-square gestures with Dev Mode menu toggle
mrosseel Jul 16, 2026
a6e8f26
refactor(software): delete the NixOS migration UI flow
mrosseel Jul 16, 2026
812f9b4
chore: retrigger build (built_at manifest stamp)
mrosseel Jul 16, 2026
aac1347
fix(sqm): derotate centroids onto the raw; growth-curve aperture corr…
mrosseel Jul 17, 2026
2d8bbb8
merge: sqm-fix into nixos (SQM rotation fix, growth-curve aperture co…
mrosseel Jul 17, 2026
57b0a9d
feat(sqm): refit imx296 band offset for the growth-curve pipeline
mrosseel Jul 17, 2026
e3cd1cb
merge: sqm-fix into nixos (imx296 band offset refit)
mrosseel Jul 17, 2026
ac9d581
fix(sqm): exposure-invariant zero point; wing-safe annulus; sensor te…
mrosseel Jul 17, 2026
88dd132
merge: sqm-fix into nixos (exposure-invariant zero point, wing-safe a…
mrosseel Jul 17, 2026
a4d87bc
feat(sqm): radiometer-first architecture with star-maintained calibra…
mrosseel Jul 17, 2026
f16dbde
merge: upstream main into sqm-fix (SCREEN_ROTATE_AMOUNTS x solve_rota…
mrosseel Jul 17, 2026
7e85d48
merge: sqm-fix into nixos (radiometer-first SQM, black-level tracking…
mrosseel Jul 17, 2026
95a4e59
feat(sqm): per-image sweep metadata JSON with radiometry and sensor temp
mrosseel Jul 17, 2026
be8aa92
merge: sqm-fix into nixos (per-image sweep metadata JSON)
mrosseel Jul 17, 2026
f13c527
feat(sqm): dump full rolling-window tracker state into sweep metadata
mrosseel Jul 17, 2026
85e898a
merge: sqm-fix into nixos (tracker window dumps in sweeps)
mrosseel Jul 17, 2026
ce1f5eb
fix(nixos-upgrade): decide camera boot entry against the new build, n…
mrosseel Jul 17, 2026
c09248d
fix(sqm): black-level lease + calibration evidence for imx296 charact…
mrosseel Jul 18, 2026
8829538
merge: sqm-fix into nixos (black-level lease, calibration evidence, s…
mrosseel Jul 18, 2026
b12bf46
fix(sqm): CI green — mypy Optional narrowing in color_index, ruff-for…
mrosseel Jul 18, 2026
72d8fe1
feat(telemetry): record radiometer samples as radio events
mrosseel Jul 18, 2026
1c99851
feat(sqm)!: remove SQM Correct; SWEEP takes the down menu slot
mrosseel Jul 18, 2026
4730924
merge: sqm-fix into nixos (radio telemetry, SQM Correct removal, SWEE…
mrosseel Jul 18, 2026
e9a16a9
chore(sqm): drop editorializing marking-menu comment
mrosseel Jul 18, 2026
6cfdb75
merge: sqm-fix into nixos (comment cleanup)
mrosseel Jul 18, 2026
f711f27
chore(nixos): untrack nix build result symlinks
mrosseel Jul 18, 2026
7a550fd
fix(test): drop stale UIMigration refs from test_ui_modules
mrosseel Jul 18, 2026
0851ca5
fix(test): match test_radec_entry to current radec_entry API
mrosseel Jul 18, 2026
4f195af
feat(sqm): per-frame optical-black pedestal for IMX290/IMX462
mrosseel Jul 18, 2026
6c4db85
docs(sqm): document per-frame optical-black pedestal (IMX290/462)
mrosseel Jul 18, 2026
fa9b1a2
build(nixos): drop dev caches from the runtime source closure
mrosseel Jul 18, 2026
06bcd47
chore(sqm): disable black-level tracker to isolate optical-black pede…
mrosseel Jul 19, 2026
8b7d664
fix(sqm): scale photometry and wing geometry to the photometry image
mrosseel Jul 19, 2026
47f088a
fix(sqm): tracked black level supersedes static bias, wizard or profile
mrosseel Jul 19, 2026
2a9c94d
fix(sqm): wizard captures gate on actual exposure and skip clamp settle
mrosseel Jul 19, 2026
2354693
fix(nixos): content-address the kernel OB patch to stop repo-wide reb…
mrosseel Jul 19, 2026
e8ae101
feat(sqm): correct IMX462 dark-sky spectral excess
mrosseel Jul 19, 2026
53a124d
Merge pull request #30 from mrosseel/sqm-optical-black
mrosseel Jul 21, 2026
2bbdd5c
ci(nixos): ARM-primary testable build (ubuntu-24.04-arm first, pi5 la…
mrosseel Jul 21, 2026
f4a59a3
feat(telemetry): section checklist, size cap, recomputable radio event
mrosseel Jul 22, 2026
1ca2fe5
merge: upstream/main into nixos
mrosseel Jul 24, 2026
e7f7a43
merge: upstream/main into nixos (full-sensor sweeps, PR #544)
mrosseel Jul 29, 2026
4de3901
fix(ci): manifest job checks out the PR base, not the default branch
mrosseel Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use nix
watch_file flake.nix flake.lock shell.nix
watch_file nixos/pkgs/uv-python.nix
watch_file python/pyproject.toml python/uv.lock
Empty file modified .github/scripts/publish_manifest.sh
100644 → 100755
Empty file.
94 changes: 85 additions & 9 deletions .github/scripts/update_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@
import argparse
import json
import re
import urllib.error
import urllib.request
from datetime import datetime, timezone
from pathlib import Path


STORE_PATH_RE = re.compile(r"^/nix/store/[a-z0-9]+-[A-Za-z0-9._+=?,-]+$")

# The binary caches devices resolve upgrades from. A build is only advertised
# as available once one of these actually serves its narinfo — see set_available.
DEV_CACHE = "https://cache.pifinder.eu/pifinder"
RELEASE_CACHE = "https://cache.pifinder.eu/pifinder-release"
DEFAULT_CACHES = (DEV_CACHE, RELEASE_CACHE)
EMPTY_MANIFEST = {
"schema": 1,
"generated_at": None,
Expand Down Expand Up @@ -49,19 +57,63 @@ def valid_store_path(value: str | None) -> bool:
return isinstance(value, str) and STORE_PATH_RE.fullmatch(value) is not None


def set_available(entry: dict) -> dict:
if valid_store_path(entry.get("store_path")):
entry["available"] = True
entry.pop("reason", None)
else:
def _narinfo_url(store_path: str, cache: str) -> str:
digest = Path(store_path).name.split("-", 1)[0]
return f"{cache.rstrip('/')}/{digest}.narinfo"


def cache_serves(store_path: str, caches, timeout: int = 15) -> bool | None:
"""Whether the closure is actually downloadable from a cache right now.

Returns True if any cache serves the narinfo (200); False only if every
cache answered and none had it (a real 404 everywhere); None if a cache
could not be reached, so presence is unknown. Publishing treats anything
other than True as "do not advertise", so a failed push or a down cache can
never advertise a build the device cannot fetch.
"""
saw_404 = False
for cache in caches:
url = _narinfo_url(store_path, cache)
try:
with urllib.request.urlopen(url, timeout=timeout) as resp:
if resp.status == 200:
return True
except urllib.error.HTTPError as exc:
if exc.code == 404:
saw_404 = True
else:
return None
except (urllib.error.URLError, OSError, TimeoutError):
return None
return False if saw_404 else None


def set_available(entry: dict, caches=DEFAULT_CACHES, verify: bool = True) -> dict:
store_path = entry.get("store_path")
if not valid_store_path(store_path):
entry["store_path"] = None
entry["available"] = False
entry.setdefault("reason", "no build")
return entry

if verify:
present = cache_serves(store_path, caches)
if present is not True:
entry["available"] = False
entry["reason"] = "not in cache" if present is False else "cache unreachable"
return entry

entry["available"] = True
entry.pop("reason", None)
return entry


def replace_entry(entries: list[dict], predicate, entry: dict) -> list[dict]:
return [item for item in entries if not predicate(item)] + [entry]
# Newest first: consumers (release channels in the update UI, and the
# migration target lookup) take the head of the list as the current entry.
# The unstable channel is re-sorted after this, so prepending is neutral
# there.
return [entry] + [item for item in entries if not predicate(item)]


def sort_unstable(entries: list[dict]) -> list[dict]:
Expand All @@ -75,11 +127,17 @@ def key(item: dict) -> tuple[int, int, str]:
return sorted(entries, key=key)


def resolve_verify(args: argparse.Namespace) -> tuple[tuple[str, ...], bool]:
caches = tuple(args.verify_cache) if args.verify_cache else DEFAULT_CACHES
return caches, not args.skip_cache_check


def update_build(args: argparse.Namespace) -> None:
manifest = load_manifest(args.manifest)
channels = manifest["channels"]
store_path = args.store_path or None
short_sha = (args.head_sha or args.sha)[:7]
caches, verify = resolve_verify(args)

if args.pr_number:
number = int(args.pr_number)
Expand All @@ -96,7 +154,7 @@ def update_build(args: argparse.Namespace) -> None:
"store_path": store_path,
"built_at": now_iso(),
}
set_available(entry)
set_available(entry, caches, verify)
channels["unstable"] = replace_entry(
channels["unstable"],
lambda item: item.get("kind") == "pr"
Expand All @@ -116,7 +174,7 @@ def update_build(args: argparse.Namespace) -> None:
"store_path": store_path,
"built_at": now_iso(),
}
set_available(entry)
set_available(entry, caches, verify)
channels["unstable"] = replace_entry(
channels["unstable"],
lambda item: item.get("kind") == "trunk"
Expand All @@ -131,6 +189,7 @@ def update_build(args: argparse.Namespace) -> None:

def update_release(args: argparse.Namespace) -> None:
manifest = load_manifest(args.manifest)
caches, verify = resolve_verify(args)
channel = "beta" if args.release_type == "beta" else "stable"
entry = {
"kind": "release",
Expand All @@ -142,9 +201,11 @@ def update_release(args: argparse.Namespace) -> None:
"source_sha": args.sha,
"version": args.version,
"store_path": args.store_path or None,
"migration_url": args.migration_url or None,
"migration_sha256_url": args.migration_sha256_url or None,
"built_at": now_iso(),
}
set_available(entry)
set_available(entry, caches, verify)
manifest["channels"][channel] = replace_entry(
manifest["channels"][channel],
lambda item: item.get("kind") == "release" and item.get("label") == args.tag,
Expand All @@ -153,6 +214,17 @@ def update_release(args: argparse.Namespace) -> None:
save_manifest(args.manifest, manifest)


def add_cache_args(sub: argparse.ArgumentParser) -> None:
# A build is advertised as available only if one of these caches actually
# serves its narinfo. Repeatable; defaults to the dev + release caches.
sub.add_argument("--verify-cache", action="append", metavar="URL")
sub.add_argument(
"--skip-cache-check",
action="store_true",
help="advertise on store-path syntax alone (tests / offline only)",
)


def parser() -> argparse.ArgumentParser:
root = argparse.ArgumentParser()
sub = root.add_subparsers(dest="command", required=True)
Expand All @@ -170,6 +242,7 @@ def parser() -> argparse.ArgumentParser:
build.add_argument("--head-repo")
build.add_argument("--head-ref")
build.add_argument("--head-sha")
add_cache_args(build)
build.set_defaults(func=update_build)

release = sub.add_parser("release")
Expand All @@ -180,8 +253,11 @@ def parser() -> argparse.ArgumentParser:
release.add_argument("--version", required=True)
release.add_argument("--release-type", choices=("stable", "beta"), required=True)
release.add_argument("--store-path", required=True)
release.add_argument("--migration-url")
release.add_argument("--migration-sha256-url")
release.add_argument("--title")
release.add_argument("--notes")
add_cache_args(release)
release.set_defaults(func=update_release)

return root
Expand Down
Loading
Loading