Monorepo for Aesthetic.Computer
aesthetic.computer
1# FedAC Native Score
2
3`fedac/native` ships a USB-bootable kernel image with embedded initramfs and pieces.
4
5## Definition Of Shipped
6
7All of the following must be true:
8
91. `build/vmlinuz` is rebuilt from current `HEAD`.
102. Release is uploaded to CDN (`upload-release.sh`).
113. CDN metadata and hash verify.
124. Running devices can detect the new version and enter update flow.
135. At least one target medium (USB/internal EFI) is flashed and readback-verified.
14
15## Release Procedure
16
17### Quick commands (fish shell)
18
19```bash
20ac-os build # Build binary + initramfs + kernel
21ac-os flash # Build + flash USB
22ac-os upload # Upload current build as OTA release
23ac-os flash+upload # Build + flash + upload
24```
25
26`ac-os` is the preferred path for real devices. It layers user-local credentials
27and repo context into the initramfs on top of the base image:
28
29- Claude OAuth state, when present locally
30- GitHub PAT, when `gh auth token` succeeds
31- Tangled SSH identity, when `ssh -G knot.aesthetic.computer` resolves a local key
32
33### Manual steps
34
35```bash
36cd fedac/native
37
38# 1) Build image
39bash scripts/build-and-flash.sh --skip-binary
40sha256sum build/vmlinuz
41
42# 2) Publish CDN release (updates latest.version/latest.sha256/releases.json)
43bash scripts/upload-release.sh build/vmlinuz
44
45# 3) Verify CDN state
46curl -fsSL https://releases.aesthetic.computer/os/native-notepat-latest.version
47curl -fsSL https://releases.aesthetic.computer/os/native-notepat-latest.sha256
48curl -fsSL https://releases.aesthetic.computer/os/releases.json | jq '.latest'
49```
50
51## Credentials & Secrets
52
53- **DO Spaces (OTA upload)**: `aesthetic-computer-vault/fedac/native/upload.env.gpg`
54 - GPG-encrypted with Jeffrey's key (`77E1473C0FF13AB2`)
55 - Decrypt: `gpg --decrypt aesthetic-computer-vault/fedac/native/upload.env.gpg > /tmp/upload.env`
56 - Contains: `DO_SPACES_KEY`, `DO_SPACES_SECRET`
57- **GPG private key**: `.tmp-key-jeffrey-private.asc` (in repo root, gitignored)
58- **Handle colors API**: `https://aesthetic.computer/.netlify/functions/handle-colors` (public, no auth)
59
60## Device Repo Access
61
62- The on-device working tree lives at `/mnt/ac-repo`.
63- On WiFi connect, AC Native clones or pulls from the public GitHub HTTPS mirror:
64 - `https://github.com/whistlegraph/aesthetic-computer.git`
65- If a Tangled SSH key was baked at build time, the repo is also configured so:
66 - `origin` fetches from GitHub
67 - `origin` push mirrors to `git@knot.aesthetic.computer:aesthetic.computer/core`
68 - `origin` also pushes to the GitHub mirror
69 - `tangled` points directly at the knot remote
70- If no Tangled key is baked, the repo stays GitHub-only for pushes.
71
72## Update Signal Expectations
73
74- Native notepat checks `native-notepat-latest.version` on WiFi connect and periodic background checks.
75- When remote version differs from local `system.version`, UI shows update availability and emits audible notification.
76- Download+flash uses:
77 - `system.fetchBinary(...)` -> `/tmp/vmlinuz.new`
78 - `system.flashUpdate(...)` -> boot EFI partition
79 - `system.reboot()` after successful flash
80
81## USB Flash Methods
82
83### Method 1: build-and-flash.sh (full pipeline)
84
85Builds binary, packs initramfs, compiles kernel, partitions + flashes USB.
86
87```bash
88cd fedac/native
89bash scripts/build-and-flash.sh --flash /dev/sdX
90# Options: --skip-kernel (reuse existing vmlinuz), --skip-binary (reuse ac-native)
91```
92
93Requires privileged access to block devices. In devcontainer, `sfdisk`/`mkfs` may lack permissions.
94
95### Method 2: Docker privileged container (from devcontainer)
96
97When the devcontainer can't directly access block devices, use the Docker host:
98
99```bash
100# 1. Build binary and initramfs inside devcontainer
101cd fedac/native
102make CC=gcc # builds build/ac-native
103bash scripts/build-and-flash.sh --skip-kernel --skip-binary # rebuilds initramfs only
104
105# 2. Rebuild kernel to embed new initramfs (uses cached objects, fast)
106cd build/linux-6.14.2
107make -j$(nproc) bzImage
108cp arch/x86/boot/bzImage ../vmlinuz
109
110# 3. Flash via privileged Docker container (host path: /home/me/aesthetic-computer)
111sudo docker run --rm --privileged \
112 -v /home/me/aesthetic-computer/fedac/native/build:/build:ro \
113 -v /dev:/dev \
114 fedora:41 bash -c '
115 dnf install -y -q dosfstools util-linux
116 DISK=/dev/sdX
117 umount ${DISK}1 2>/dev/null || true
118 sfdisk --force $DISK <<EOF
119label: gpt
120type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, size=512M
121EOF
122 sleep 1
123 mkfs.vfat -F 32 -n ACBOOT ${DISK}1
124 mkdir -p /mnt/efi && mount ${DISK}1 /mnt/efi
125 mkdir -p /mnt/efi/EFI/BOOT
126 cp /build/vmlinuz /mnt/efi/EFI/BOOT/BOOTX64.EFI
127 sync && sleep 1 && sync
128 sha256sum /mnt/efi/EFI/BOOT/BOOTX64.EFI /build/vmlinuz
129 umount /mnt/efi
130'
131```
132
133**Key detail**: devcontainer workspace is at `/workspaces/aesthetic-computer` but the host path is `/home/me/aesthetic-computer`. Docker bind mounts must use the host path.
134
135### Method 3: Reflash existing USB (no repartition)
136
137If USB already has an EFI partition, skip partitioning:
138
139```bash
140sudo docker run --rm --privileged \
141 -v /home/me/aesthetic-computer/fedac/native/build:/build:ro \
142 -v /dev:/dev \
143 fedora:41 bash -c '
144 dnf install -y -q dosfstools
145 mount /dev/sdX1 /mnt
146 cp /build/vmlinuz /mnt/EFI/BOOT/BOOTX64.EFI
147 sync && sleep 1 && sync
148 sha256sum /mnt/EFI/BOOT/BOOTX64.EFI /build/vmlinuz
149 umount /mnt
150'
151```
152
153### Verification
154
155Always verify SHA256 match between source vmlinuz and flashed BOOTX64.EFI:
156
157```bash
158sha256sum build/vmlinuz # local
159# Must match the sha256sum printed inside the docker container
160```
161
162### Device node creation
163
164If `lsblk` shows the USB but `/dev/sdX` doesn't exist in the devcontainer:
165
166```bash
167sudo mknod /dev/sda b 8 0
168sudo mknod /dev/sda1 b 8 1
169```
170
171## OTA Update Hardening (2026-03-11)
172
173Critical fixes applied to the OTA flash path:
174
1751. **posix_fadvise instead of drop_caches**: `drop_caches=3` was destroying tmpfs-backed source file pages. Now uses `POSIX_FADV_DONTNEED` on only the destination file.
1762. **Fresh mount for flash**: Always mounts EFI partition at `/tmp/efi` instead of reusing `/mnt` (which may lack `EFI/BOOT/`).
1773. **EFI directory validation**: Aborts flash if `EFI/BOOT/` not found on mounted partition.
1784. **Source file pre-flight**: Validates source exists and is >1MB before copying.
1795. **Double sync with delay**: `syncfs` + `sync` + 500ms sleep + `sync` before verify and before reboot, giving vfat write-back time to flush.
1806. **Error logging**: syncfs failures, mount failures, and device detection logged with errno.
181
182## Next Features
183
184- **Multitouch input**: Track touch slots in `input.c` (MT protocol B),
185 expose multiple simultaneous touch points to JS pieces via `act({ event })`.
186 Enables chord playing in notepat and multi-finger gestures on 2-in-1 devices.
187- **Firmware blobs**: Add Realtek (RTW88/RTW89), MediaTek (MT7921/MT7925),
188 and Intel SOF audio firmware to initramfs for runtime driver loading.
189- **@sat hardware validation**: Get `lspci -nn` dump from ARDOR NEO G15
190 to confirm WiFi chip and audio codec, then add matching firmware.
191
192## Architecture
193
194See [internals.md](internals.md) for the full boot sequence and system architecture narrative.
195
196## Operational Checks
197
198- USB logs must be checked on every release candidate:
199 - `ac-native.log` for `[fetch]`, `[fetchBinary]`, `[flash]`, `[verify]`, `[mic]`, `[sample]`
200 - `ac-audio.log` for ALSA/capture diagnostics
201- Any `curl exit=77` or cert-path errors are a release blocker.
202- Any repeated mic open/close race errors are a release blocker.
203- Flash verify must report `OK: N bytes match` — any `MISMATCH` is a release blocker.
204
205## Commits from the Device
206
207When a commit is made directly from a running AC native device (via Claude Code on-device):
208
209- **Prefix**: `[ac-native]` at the start of the commit subject line
210- **Body**: Include `Committed from AC native device.` as the last line
211
212Example:
213```
214[ac-native] enable CONFIG_TYPEC, UCSI, UCSI_ACPI for USB-C power role swap
215
216Adds USB Type-C connector class support.
217
218Committed from AC native device.
219```
220
221This distinguishes on-device commits from dev-machine commits in git log.