commits
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build now runs ldd on iris_dri.so inside the initramfs, finds any
missing deps, copies them from the build system, and re-runs the
transitive dep resolver. Logs missing/fixed deps to build output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Init (PID 1) now spawns ac-native as a child process via &/wait.
If ac-native crashes from DRI/Mesa (signal > 128), init automatically
restarts it with AC_NO_SDL=1, falling back to DRM dumb buffers.
Flow: init → spawn ac-native (SDL enabled) → if signal crash →
respawn with AC_NO_SDL=1 (DRM only) → stable boot.
SDL/Mesa/DRI libs restored in initramfs. On hardware with working
GPU drivers, SDL3 GPU acceleration works. On broken DRI, auto-fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace cycling CSS animation with the luminance-based shadow algorithm
from disk.mjs getShadowColorForText(). Each syntax token gets a
contrasting shadow computed from its color:
- Dark colors get lightened shadows (85% mix with white)
- Bright colors get dark purple-blue shadows
- Channel-specific tinting for pure R/G/B colors
- Near-black gets bright white shadow
Shadows are baked into per-token CSS classes via _getStageShadowForColor()
and scoped to body.stage-mode so normal editing is unaffected.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace static white text-stroke with an animated text-shadow that
cycles through black, white, cyan, magenta, yellow, green over 6s.
Ensures code text stays readable even when color words sit on
their own background color.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sigsetjmp can't reliably recover from SIGSEGV during dlopen — process
state is corrupted. The Mesa iris_dri.so driver crashes on ThinkPad 11e
and no in-process recovery works. Removed all SDL/Mesa/DRI libs.
DRM dumb buffers work reliably. SDL3 GPU acceleration needs a
multi-process architecture (init spawns ac-native as child) so
DRI crashes are recoverable via process restart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Play/stop buttons are siblings of Monaco inside viz-container and
can't be z-indexed below the context menu. Hide them with
visibility:hidden when .context-menu-open is active.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- :has(.context-view) can't see inside Monaco's shadow DOM, so use
JS: onContextMenu adds .context-menu-open class to editor panel,
mousedown removes it. CSS boosts z-index to 100000 when class present.
- Bump center-square to z-index 1001 so it stays above editor panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The play/stop buttons and editor-header have z-index within the
editor panel. Boost .viz-container:has(.context-view) to 100000
so Monaco's context menu renders above all sibling controls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use .editor-panel:has(.context-view) to conditionally set z-index
100000 only when Monaco's context menu is present. This keeps the
center-square and other elements visible normally, but ensures the
context menu renders above everything when open.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove overflowWidgetsDomNode hack (shadow DOM blocked external styling).
Instead give .editor-panel z-index:100 so the context menu renders inside
Monaco with full theme styling and appears above sibling gutters/panels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The overflow widgets container is outside .monaco-editor so it
doesn't inherit the editor theme background. Add explicit bg,
border, and shadow for light/dark modes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use overflowWidgetsDomNode option to append Monaco's overflow
widgets (including context menu) to a container on <body>, fully
outside the editor panel hierarchy. This escapes all ancestor
stacking contexts so the menu renders on top of everything.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace fork-based probe with signal handler + sigsetjmp/siglongjmp.
If Mesa DRI crashes during dlopen or SDL_Init, the SIGSEGV/SIGBUS
handler catches it, restores signal handlers, cleans up, and falls
back to DRM dumb buffers. No fork, no child process, no PID 1 issues.
Works as init (PID 1) and under systemd alike.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The SDL3/Mesa DRI probe segfaults on ThinkPad 11e even in a child
process. When running as PID 1 (bare metal), the fork+crash corrupts
shared GPU/DRM state. Skip SDL entirely for PID 1 and use DRM dumb
buffers (which work reliably). SDL still available when running
under a proper init system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All oven builds today used kernel 6.19.9 and none booted (black screen).
The last working build used 6.14.2 (local ac-os flash). Reverting the
Docker builder to match the working kernel version.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gutters had position:relative + z-index:1-2 which created stacking
contexts that painted above the editor panel content (including
Monaco's context menu). Removing z-index lets the context menu
render on top.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add overflowingContentWidgets selector and position:relative to
Monaco overlay z-index rule so context menu escapes stacking contexts
- Remove padding/border-width shrink on user menu in narrow/mobile
layouts so the username button stays full size
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace ::before pseudo-element outlines with box-shadow inset,
which renders as part of the background layer and never covers
descendant content like Monaco's context menu. Remove the
z-index: 0 stacking context that was trapping the menu.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove max-width cap and font-size reduction on header-user-handle
in narrow container queries and mobile layout so the username stays
readable at 12px without truncation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create stacking context on .editor-panel (z-index: 0) and move
::before live-state outlines to z-index: -1 so they render above
the panel background but below all content including Monaco's
right-click context menu.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Put SDL/Mesa/DRI libs back in initramfs (we want GPU accel).
Init now dumps missing libs and ac-native stderr directly to
tty0 with a 5s pause so user can read the error on screen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SDL3/GBM/Mesa DRI libs were copied into initramfs unconditionally.
Their transitive deps or constructors crash on hardware without
working DRI. Since ac-native uses dlopen (no link-time SDL dep),
the binary runs fine without these libs and falls back to DRM.
Also updated cross-platform-samples.md with finalized architecture:
- Samples share # sigil with paintings (same PNG format)
- Separate samples MongoDB collection
- Shared code namespace (cross-collection uniqueness for #)
- Encoding version (v:1) on every record
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
F8 ON: engage hold mode (snapshot + auto-latch new notes)
F8 OFF: stop all held notes and clear, even if empty
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Any note played while hold is engaged automatically gets added
to the held set, so it sustains on release too.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
F8 captures all currently-held keys and keeps them sounding after
key release. Press F8 again to release all held notes. Visual
HOLD indicator shows next to octave in the wave row.
- High beep on engage, low beep on release
- Held keys immune to key-up until F8 toggled off
- stopAllSounds clears hold state (escape exit, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed all #ifdef USE_SDL guards, -DUSE_SDL, -lSDL3, SDL3/SDL.h
include. SDL3 code always compiles with void* types and dlsym
function pointers. No compile-time or link-time SDL dependency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All SDL3 functions loaded via dlsym at runtime instead of link-time
dependency. Binary starts and works on any hardware:
- SDL3 libs present + working GPU: GPU-accelerated rendering
- SDL3 libs missing or DRI broken: graceful fallback to DRM/fbdev
- Probe runs in child process to catch Mesa/GBM segfaults
No more -lSDL3 in LDFLAGS. Oven builds re-enabled with USE_SDL=1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary crash from linker loading libSDL3→libgbm→iris_dri.so before
main(). Needs dlsym-based loading to avoid link-time dep. SDL off
in oven builds for now. Probe improvements kept for future use.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- docker-build.sh: transitive dep loop now includes lib64/dri/*.so
(DRI drivers have many deps that were never resolved)
- init: set LD_LIBRARY_PATH, LIBGL_DRIVERS_PATH, GBM_DRIVERS_PATH,
MESA_LOADER_DRIVER_OVERRIDE=iris for Intel UHD 615
- AC_BUILD_SDL now defaults to 0; this fix prepares for re-enabling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SDL3/GBM/Mesa DRI libs caused immediate segfault on ThinkPad 11e
(libgbm.so cannot open DRI driver). Build now defaults to DRM-only
(AC_BUILD_SDL=0). SDL can be re-enabled per-build with AC_BUILD_SDL=1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JS_NewObjectClass(painting_class_id) for nopaint buffer/painting
meant GC would call fb_destroy() on runtime-owned framebuffers.
Now the finalizer skips buffers that match current_rt->nopaint_*.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
command -v returns exit 1 when tool not found, which set -e catches.
Also [ -n "" ] && cp pattern exits 1 with set -e. Fixed both with
|| true guards and if/then instead of && chains.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
partprobe was never in initramfs — all partition table re-reads
after sfdisk were silently failing, causing mkfs.vfat to fail on
NVMe because /dev/nvme0n1p1 didn't exist yet.
Now: partprobe bundled, plus blockdev/busybox/sfdisk --verify as
fallbacks, with 5s polling loop for device node appearance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Install: wait up to 5s for partition device node after repartitioning
with repeated partprobe probes. The 500ms wait was insufficient for
NVMe devices — mkfs.vfat failed because /dev/nvme0n1p1 didn't exist
yet after sfdisk recreated the partition table.
WiFi: save captive portal HTML to /mnt/portal_page.html for debugging
Getty ClearPass portals.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Dockerfile.builder: install ccache
- docker-build.sh: CC="ccache gcc" for binary + kernel builds,
skip make clean when ccache available, log hit rate at end
- native-builder.mjs: mount persistent ac-os-ccache Docker volume
- First build: same ~25min (cold cache). Subsequent: ~2-5min
(only recompiles changed files, rest served from cache)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrated from V1 (Node.js/SQLite on silo) to V2 (Go/Postgres on lith).
All 8 channels and 17 playlists migrated. Landing page updated with V2
API endpoints, DP-1 protocol section, Feral File attribution, and
iframe lifecycle tied to AC boot-log ready signal. KidLisp KIDLISP_COLORS
synced with full cssColors map + c0-c150 index shortnames + patterns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- num.parseColor(params): parse color names/RGB from string params
- num.randIntArr(max, len): random int array for rainbow mode
- num.timestamp(): timestamp string
- pen object: pointer_x/y from input state
- net.rewrite/net.log stubs
- pppline(points): polyline drawing on ink chain
- nopaint.mjs module stub: all exports stubbed for import resolution
- color-highlighting.mjs stub for HUD label imports
Web line.mjs should now load and run unchanged on AC Native.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runtime-level persistent painting canvas that survives piece swaps:
- system.painting: persistent ACFramebuffer, accessible from any piece
- system.nopaint: state machine (is/cancelStroke), brush position, buffer
- Auto-creates painting+buffer when piece exports system="nopaint"
- Touch→paint→bake lifecycle handled in C (js_call_act/js_call_paint)
- Painting composited as background before piece paint()
- Buffer baked onto painting on stroke lift, then cleared
- Non-nopaint pieces (prompt) can access system.painting to show it
New rendering primitives:
- page(painting) switches render target, returns chainable proxy
- paste(painting, dx, dy) alpha-composites buffers
- painting.pixels Uint8Array for direct pixel access
- line(x0,y0,x1,y1,thickness) thick lines via filled circles
- graph_line_thick() in graph.c
Includes painting.mjs test piece for standalone testing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Painting system:
- page(painting) switches render target, returns chainable proxy
- paste(painting, dx, dy) alpha-composites onto current target
- painting(w,h,cb) now exposes .pixels Uint8Array for direct access
- graph_line_thick() for variable-width brush strokes
- line(x0,y0,x1,y1,thickness) JS API with 5th thickness param
- New painting.mjs piece: persistent canvas, freehand line brush,
color cycling (c key), clear (n key), scroll thickness
DJ fixes:
- Speed control moved to audio callback with linear interpolation
(was broken in decoder resampler) — scratching actually works
- Negative speed support (-4x to +4x) for reverse scratching
- TTS fixed: was calling tts.speak() but API is sound.speak()
WiFi: ClearPass captive portal cmd=authenticate strategy
ac-os: strip @ prefix from handle, USE_SDL defaults off
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- audio: speed control now in audio callback with linear interpolation
instead of broken resampler approach — scratching actually works
- audio-decode: allow negative speed (-4 to +4), init ring_frac,
decoder always decodes at 1x (speed applied at playback)
- wifi: add ClearPass cmd=authenticate strategy for Getty portals,
add POST with accept params, add -k flag for HTTPS portals
- dj.mjs: TTS was calling tts.speak() but API exposes sound.speak()
— replaced all tts refs with sound.speak via say() helper
- ac-os: strip @ prefix from handle to prevent @@jeffrey double prefix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scale two-pass Gaussian blur strength by 1/3 to match the old single-pass
behavior — blur(5) was producing ~3x stronger output after the rewrite,
breaking pieces like $4bb that rely on specific blur levels.
Re-enable console.warn for network errors in fetchCachedCode so embed
failures are visible in devtools instead of silently swallowed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Makefile's ifdef USE_SDL triggers on any value including 0.
Now only passes USE_SDL=1 when USE_SDL env var is explicitly "1".
Fixes build failure in devcontainers without SDL3 headers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `node keeps.mjs wallets` to show balances across all chains
(XTZ, ETH, SOL, BTC, ADA) from vault wallets.json using public RPCs.
Raise kidlisp.com Monaco editor max lines from 16 to 64 so longer
pieces can be pasted in.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace velocity-accumulation wheel behavior with direct positional
scrolling. Wheel events now drive position smoothly across pages;
when idle (120ms debounce), eases to nearest page via easeOutCubic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All colors now use __theme (T.bg, T.fg, T.bar, T.border, T.accent,
T.ok, T.warn) — auto light/dark based on time of day
- USB plug: "USB DJ on" TTS, auto-scan + play first track
- USB unplug: "USB DJ off" TTS, stop playback, clear track list
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GettyLink returned HTTP 200 with a login page but the old code just
re-fetched the connectivity check URL. New flow:
1. Detect portal (connectivity check != 204)
2. Follow redirects, save portal page HTML
3. Extract form action URL from the page
4. POST to the form action (accepts terms on most portals)
5. Re-check connectivity after 1s propagation delay
Logs from USB showed: portal detected → auto-accept did nothing →
WebSocket connections got 302 Captive Portal endlessly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bottom panel reorganized: progress bar, time/speed, then button row
with proper spacing. Buttons: Prev, Play/Pause, Next, 1x, Scan —
all tappable in addition to existing keyboard shortcuts.
USB indicator moved to top-right under track counter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Init (PID 1) now spawns ac-native as a child process via &/wait.
If ac-native crashes from DRI/Mesa (signal > 128), init automatically
restarts it with AC_NO_SDL=1, falling back to DRM dumb buffers.
Flow: init → spawn ac-native (SDL enabled) → if signal crash →
respawn with AC_NO_SDL=1 (DRM only) → stable boot.
SDL/Mesa/DRI libs restored in initramfs. On hardware with working
GPU drivers, SDL3 GPU acceleration works. On broken DRI, auto-fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace cycling CSS animation with the luminance-based shadow algorithm
from disk.mjs getShadowColorForText(). Each syntax token gets a
contrasting shadow computed from its color:
- Dark colors get lightened shadows (85% mix with white)
- Bright colors get dark purple-blue shadows
- Channel-specific tinting for pure R/G/B colors
- Near-black gets bright white shadow
Shadows are baked into per-token CSS classes via _getStageShadowForColor()
and scoped to body.stage-mode so normal editing is unaffected.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sigsetjmp can't reliably recover from SIGSEGV during dlopen — process
state is corrupted. The Mesa iris_dri.so driver crashes on ThinkPad 11e
and no in-process recovery works. Removed all SDL/Mesa/DRI libs.
DRM dumb buffers work reliably. SDL3 GPU acceleration needs a
multi-process architecture (init spawns ac-native as child) so
DRI crashes are recoverable via process restart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- :has(.context-view) can't see inside Monaco's shadow DOM, so use
JS: onContextMenu adds .context-menu-open class to editor panel,
mousedown removes it. CSS boosts z-index to 100000 when class present.
- Bump center-square to z-index 1001 so it stays above editor panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use .editor-panel:has(.context-view) to conditionally set z-index
100000 only when Monaco's context menu is present. This keeps the
center-square and other elements visible normally, but ensures the
context menu renders above everything when open.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use overflowWidgetsDomNode option to append Monaco's overflow
widgets (including context menu) to a container on <body>, fully
outside the editor panel hierarchy. This escapes all ancestor
stacking contexts so the menu renders on top of everything.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace fork-based probe with signal handler + sigsetjmp/siglongjmp.
If Mesa DRI crashes during dlopen or SDL_Init, the SIGSEGV/SIGBUS
handler catches it, restores signal handlers, cleans up, and falls
back to DRM dumb buffers. No fork, no child process, no PID 1 issues.
Works as init (PID 1) and under systemd alike.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The SDL3/Mesa DRI probe segfaults on ThinkPad 11e even in a child
process. When running as PID 1 (bare metal), the fork+crash corrupts
shared GPU/DRM state. Skip SDL entirely for PID 1 and use DRM dumb
buffers (which work reliably). SDL still available when running
under a proper init system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add overflowingContentWidgets selector and position:relative to
Monaco overlay z-index rule so context menu escapes stacking contexts
- Remove padding/border-width shrink on user menu in narrow/mobile
layouts so the username button stays full size
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace ::before pseudo-element outlines with box-shadow inset,
which renders as part of the background layer and never covers
descendant content like Monaco's context menu. Remove the
z-index: 0 stacking context that was trapping the menu.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SDL3/GBM/Mesa DRI libs were copied into initramfs unconditionally.
Their transitive deps or constructors crash on hardware without
working DRI. Since ac-native uses dlopen (no link-time SDL dep),
the binary runs fine without these libs and falls back to DRM.
Also updated cross-platform-samples.md with finalized architecture:
- Samples share # sigil with paintings (same PNG format)
- Separate samples MongoDB collection
- Shared code namespace (cross-collection uniqueness for #)
- Encoding version (v:1) on every record
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
F8 captures all currently-held keys and keeps them sounding after
key release. Press F8 again to release all held notes. Visual
HOLD indicator shows next to octave in the wave row.
- High beep on engage, low beep on release
- Held keys immune to key-up until F8 toggled off
- stopAllSounds clears hold state (escape exit, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All SDL3 functions loaded via dlsym at runtime instead of link-time
dependency. Binary starts and works on any hardware:
- SDL3 libs present + working GPU: GPU-accelerated rendering
- SDL3 libs missing or DRI broken: graceful fallback to DRM/fbdev
- Probe runs in child process to catch Mesa/GBM segfaults
No more -lSDL3 in LDFLAGS. Oven builds re-enabled with USE_SDL=1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- docker-build.sh: transitive dep loop now includes lib64/dri/*.so
(DRI drivers have many deps that were never resolved)
- init: set LD_LIBRARY_PATH, LIBGL_DRIVERS_PATH, GBM_DRIVERS_PATH,
MESA_LOADER_DRIVER_OVERRIDE=iris for Intel UHD 615
- AC_BUILD_SDL now defaults to 0; this fix prepares for re-enabling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
partprobe was never in initramfs — all partition table re-reads
after sfdisk were silently failing, causing mkfs.vfat to fail on
NVMe because /dev/nvme0n1p1 didn't exist yet.
Now: partprobe bundled, plus blockdev/busybox/sfdisk --verify as
fallbacks, with 5s polling loop for device node appearance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Install: wait up to 5s for partition device node after repartitioning
with repeated partprobe probes. The 500ms wait was insufficient for
NVMe devices — mkfs.vfat failed because /dev/nvme0n1p1 didn't exist
yet after sfdisk recreated the partition table.
WiFi: save captive portal HTML to /mnt/portal_page.html for debugging
Getty ClearPass portals.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Dockerfile.builder: install ccache
- docker-build.sh: CC="ccache gcc" for binary + kernel builds,
skip make clean when ccache available, log hit rate at end
- native-builder.mjs: mount persistent ac-os-ccache Docker volume
- First build: same ~25min (cold cache). Subsequent: ~2-5min
(only recompiles changed files, rest served from cache)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrated from V1 (Node.js/SQLite on silo) to V2 (Go/Postgres on lith).
All 8 channels and 17 playlists migrated. Landing page updated with V2
API endpoints, DP-1 protocol section, Feral File attribution, and
iframe lifecycle tied to AC boot-log ready signal. KidLisp KIDLISP_COLORS
synced with full cssColors map + c0-c150 index shortnames + patterns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- num.parseColor(params): parse color names/RGB from string params
- num.randIntArr(max, len): random int array for rainbow mode
- num.timestamp(): timestamp string
- pen object: pointer_x/y from input state
- net.rewrite/net.log stubs
- pppline(points): polyline drawing on ink chain
- nopaint.mjs module stub: all exports stubbed for import resolution
- color-highlighting.mjs stub for HUD label imports
Web line.mjs should now load and run unchanged on AC Native.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runtime-level persistent painting canvas that survives piece swaps:
- system.painting: persistent ACFramebuffer, accessible from any piece
- system.nopaint: state machine (is/cancelStroke), brush position, buffer
- Auto-creates painting+buffer when piece exports system="nopaint"
- Touch→paint→bake lifecycle handled in C (js_call_act/js_call_paint)
- Painting composited as background before piece paint()
- Buffer baked onto painting on stroke lift, then cleared
- Non-nopaint pieces (prompt) can access system.painting to show it
New rendering primitives:
- page(painting) switches render target, returns chainable proxy
- paste(painting, dx, dy) alpha-composites buffers
- painting.pixels Uint8Array for direct pixel access
- line(x0,y0,x1,y1,thickness) thick lines via filled circles
- graph_line_thick() in graph.c
Includes painting.mjs test piece for standalone testing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Painting system:
- page(painting) switches render target, returns chainable proxy
- paste(painting, dx, dy) alpha-composites onto current target
- painting(w,h,cb) now exposes .pixels Uint8Array for direct access
- graph_line_thick() for variable-width brush strokes
- line(x0,y0,x1,y1,thickness) JS API with 5th thickness param
- New painting.mjs piece: persistent canvas, freehand line brush,
color cycling (c key), clear (n key), scroll thickness
DJ fixes:
- Speed control moved to audio callback with linear interpolation
(was broken in decoder resampler) — scratching actually works
- Negative speed support (-4x to +4x) for reverse scratching
- TTS fixed: was calling tts.speak() but API is sound.speak()
WiFi: ClearPass captive portal cmd=authenticate strategy
ac-os: strip @ prefix from handle, USE_SDL defaults off
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- audio: speed control now in audio callback with linear interpolation
instead of broken resampler approach — scratching actually works
- audio-decode: allow negative speed (-4 to +4), init ring_frac,
decoder always decodes at 1x (speed applied at playback)
- wifi: add ClearPass cmd=authenticate strategy for Getty portals,
add POST with accept params, add -k flag for HTTPS portals
- dj.mjs: TTS was calling tts.speak() but API exposes sound.speak()
— replaced all tts refs with sound.speak via say() helper
- ac-os: strip @ prefix from handle to prevent @@jeffrey double prefix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scale two-pass Gaussian blur strength by 1/3 to match the old single-pass
behavior — blur(5) was producing ~3x stronger output after the rewrite,
breaking pieces like $4bb that rely on specific blur levels.
Re-enable console.warn for network errors in fetchCachedCode so embed
failures are visible in devtools instead of silently swallowed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All colors now use __theme (T.bg, T.fg, T.bar, T.border, T.accent,
T.ok, T.warn) — auto light/dark based on time of day
- USB plug: "USB DJ on" TTS, auto-scan + play first track
- USB unplug: "USB DJ off" TTS, stop playback, clear track list
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GettyLink returned HTTP 200 with a login page but the old code just
re-fetched the connectivity check URL. New flow:
1. Detect portal (connectivity check != 204)
2. Follow redirects, save portal page HTML
3. Extract form action URL from the page
4. POST to the form action (accepts terms on most portals)
5. Re-check connectivity after 1s propagation delay
Logs from USB showed: portal detected → auto-accept did nothing →
WebSocket connections got 302 Captive Portal endlessly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bottom panel reorganized: progress bar, time/speed, then button row
with proper spacing. Buttons: Prev, Play/Pause, Next, 1x, Scan —
all tappable in addition to existing keyboard shortcuts.
USB indicator moved to top-right under track counter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>