Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

ac-os: boot command, crash overlay, and OTA build name fix

- Fix pull_ota using local build name instead of OTA name on USB
- Add "boot <piece>" command to prompt.mjs (sets default boot piece
in config.json, bare "boot" shows current)
- Add JS crash overlay: red CRASH bar with error message rendered
in C when paint/act/sim throws an unhandled exception (auto-
dismisses after 5s, flashes on first appearance)
- Detect previous C-level crashes (/mnt/crash.json from signal
handler) and show on next boot
- Clear crash state on piece jump

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+88 -2
+3 -1
fedac/native/ac-os
··· 977 977 fi 978 978 log "SHA256 verified: ${ACTUAL_HASH:0:16}..." 979 979 980 - # Override VMLINUZ so flash_usb uses the downloaded kernel 980 + # Override VMLINUZ and build name so flash_usb uses the downloaded kernel 981 + # (not the locally-generated name from scripts/build-name.sh) 981 982 VMLINUZ="${PULLED_KERNEL}" 983 + export AC_BUILD_NAME="${BUILD_NAME}" 982 984 log "Ready to flash: ${BUILD_NAME}" 983 985 } 984 986
+21
fedac/native/pieces/prompt.mjs
··· 333 333 return; 334 334 } 335 335 336 + // Set default boot piece 337 + if (baseWord === "boot") { 338 + if (spaceIdx > 0) { 339 + const pieceName = cmd.slice(spaceIdx + 1).trim(); 340 + if (pieceName) { 341 + system?.saveConfig?.("piece", pieceName); 342 + message = "boot → " + pieceName; 343 + } else { 344 + message = "usage: boot <piece-name>"; 345 + } 346 + } else { 347 + // Show current boot piece 348 + const raw = system?.readFile?.("/mnt/config.json"); 349 + let cur = "notepat"; 350 + if (raw) try { cur = JSON.parse(raw).piece || cur; } catch (_) {} 351 + message = "boot piece: " + cur; 352 + } 353 + messageFrame = 0; 354 + return; 355 + } 356 + 336 357 // Dark/light mode override 337 358 if (lower === "dark") { 338 359 __theme._forceDark = true;
+46 -1
fedac/native/src/ac-native.c
··· 2074 2074 } 2075 2075 } 2076 2076 2077 + // Check for previous crash (written by signal handler) 2078 + { 2079 + FILE *cf = fopen("/mnt/crash.json", "r"); 2080 + if (cf) { 2081 + char cbuf[512] = {0}; 2082 + fread(cbuf, 1, sizeof(cbuf) - 1, cf); 2083 + fclose(cf); 2084 + char sig[32] = {0}; 2085 + parse_config_string(cbuf, "\"signal\"", sig, sizeof(sig)); 2086 + if (sig[0]) { 2087 + rt->crash_active = 1; 2088 + rt->crash_frame = 0; 2089 + snprintf(rt->crash_msg, sizeof(rt->crash_msg), 2090 + "previous crash: %s", sig); 2091 + ac_log("[ac-native] Previous crash detected: %s\n", sig); 2092 + } 2093 + // Remove crash file so we don't re-show it 2094 + remove("/mnt/crash.json"); 2095 + } 2096 + } 2097 + 2077 2098 // Override piece_path from config.json boot piece (pieces bundled at /pieces/) 2078 2099 // Resolve aliases: "claude" and "cc" → terminal (with param "claude") 2079 2100 if (strcmp(rt->piece, "claude") == 0 || strcmp(rt->piece, "cc") == 0) { ··· 2844 2865 } 2845 2866 JS_FreeValue(rt->ctx, global); 2846 2867 2847 - // Reset counters 2868 + // Reset counters and crash state 2848 2869 rt->paint_count = 0; 2849 2870 rt->sim_count = 0; 2871 + rt->crash_active = 0; 2872 + rt->crash_count = 0; 2873 + rt->crash_frame = 0; 2874 + rt->crash_msg[0] = 0; 2850 2875 2851 2876 // NOTE: "claude" and "cc" aliases removed — claude.mjs handles auth curtain 2852 2877 // before jumping to terminal:claude itself. ··· 2883 2908 js_call_paint(rt); 2884 2909 2885 2910 clock_gettime(CLOCK_MONOTONIC, &_pf_paint1); 2911 + 2912 + // Crash overlay — red bar with error message when JS throws 2913 + if (rt->crash_active) { 2914 + rt->crash_frame++; 2915 + int bar_h = 24; 2916 + int flash = (rt->crash_frame < 30) ? (rt->crash_frame % 6 < 3 ? 255 : 180) : 200; 2917 + graph_ink(&graph, (ACColor){flash, 0, 0, 240}); 2918 + graph_box(&graph, 0, 0, screen->width, bar_h, 1); 2919 + graph_ink(&graph, (ACColor){255, 255, 255, 255}); 2920 + font_draw_matrix(&graph, "CRASH", 4, 4, 2); 2921 + // Truncate message to fit screen 2922 + char crash_display[128]; 2923 + snprintf(crash_display, sizeof(crash_display), "%s", rt->crash_msg); 2924 + graph_ink(&graph, (ACColor){255, 200, 200, 255}); 2925 + font_draw_matrix(&graph, crash_display, 60, 8, 1); 2926 + // Auto-dismiss after 5 seconds (300 frames at 60fps) 2927 + if (rt->crash_frame > 300) { 2928 + rt->crash_active = 0; 2929 + } 2930 + } 2886 2931 2887 2932 // Software cursor on its own overlay buffer (unaffected by KidLisp effects) 2888 2933 if (cursor_fb && input && (input->pointer_x || input->pointer_y)) {
+11
fedac/native/src/js-bindings.c
··· 5316 5316 } 5317 5317 } 5318 5318 5319 + // Helper: record a JS crash for the overlay 5320 + static void js_record_crash(ACRuntime *rt, const char *fn_name, const char *msg) { 5321 + rt->crash_active = 1; 5322 + rt->crash_count++; 5323 + rt->crash_frame = 0; 5324 + snprintf(rt->crash_msg, sizeof(rt->crash_msg), "%s(): %s", fn_name, msg ? msg : "unknown"); 5325 + } 5326 + 5319 5327 void js_call_paint(ACRuntime *rt) { 5320 5328 if (!JS_IsFunction(rt->ctx, rt->paint_fn)) return; 5321 5329 current_rt = rt; ··· 5328 5336 JSValue stack = JS_GetPropertyStr(rt->ctx, exc, "stack"); 5329 5337 const char *stack_str = JS_ToCString(rt->ctx, stack); 5330 5338 fprintf(stderr, "[js] paint() error: %s\n%s\n", str, stack_str ? stack_str : ""); 5339 + js_record_crash(rt, "paint", str); 5331 5340 if (stack_str) JS_FreeCString(rt->ctx, stack_str); 5332 5341 JS_FreeValue(rt->ctx, stack); 5333 5342 JS_FreeCString(rt->ctx, str); ··· 5387 5396 const char *stack_str = JS_ToCString(rt->ctx, stack); 5388 5397 fprintf(stderr, "[js] act() error: %s\n%s\n", str, stack_str ? stack_str : ""); 5389 5398 ac_log("[js] act() error: %s\n%s\n", str, stack_str ? stack_str : ""); 5399 + js_record_crash(rt, "act", str); 5390 5400 if (stack_str) JS_FreeCString(rt->ctx, stack_str); 5391 5401 JS_FreeValue(rt->ctx, stack); 5392 5402 JS_FreeCString(rt->ctx, str); ··· 5425 5435 JSValue stack = JS_GetPropertyStr(rt->ctx, exc, "stack"); 5426 5436 const char *stack_str = JS_ToCString(rt->ctx, stack); 5427 5437 fprintf(stderr, "[js] sim() error: %s\n%s\n", str, stack_str ? stack_str : ""); 5438 + js_record_crash(rt, "sim", str); 5428 5439 if (stack_str) JS_FreeCString(rt->ctx, stack_str); 5429 5440 JS_FreeValue(rt->ctx, stack); 5430 5441 JS_FreeCString(rt->ctx, str);
+7
fedac/native/src/js-bindings.h
··· 100 100 // User config (read from /mnt/config.json on EFI partition) 101 101 char handle[64]; // e.g. "jeffrey" (without @) 102 102 char piece[64]; // default piece name, e.g. "notepat" 103 + 104 + // JS crash overlay — set when paint/act/sim throws an unhandled exception 105 + int crash_active; // 1 = crash bar visible 106 + int crash_count; // total JS exceptions since piece load 107 + char crash_msg[256]; // last error message 108 + char crash_piece[64]; // piece that crashed 109 + int crash_frame; // frame counter for animation 103 110 } ACRuntime; 104 111 105 112 // Initialize QuickJS and register all AC API bindings