100 Commits
Author SHA1 Message Date
phantomptr 6c97eb0977 Release v7.1.5 2026-10-18 14:43:29 -07:00
phantomptrandClaude Opus 5.5 cf7f5884b1 Merge #475 review fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 14:35:03 -07:00
phantomptrandClaude Opus 5.5 1d56e09c19 helper: #475 review fixes
- A durable-by-log job is not ended for the table until it has settled
  (no pack segments, or `settled`): between unswept_n reaching 0 and the
  settle, its last Status{unswept=0} and the segments' removal are still to
  come, and an eviction or the 10 s reap there left the sender's settle wait
  to time out and the segments behind. C test for that window.
- create() checks the retiring ids first and evicts only when the create it
  makes room for will go through (the id is not retiring, and the retiring
  list has room for the victim's id too), so no victim is destroyed for
  nothing. The retiring list holds 2 x AVA1_MAX_JOBS ids, which makes its
  "full is unreachable" comment true with evictions.
- The victim is destroyed on a thread of its own (ava1_job_put_nowait), off
  the JobOpen path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 14:16:06 -07:00
phantomptrandClaude Opus 5.5 b82cd65803 7.1.5 notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 14:08:15 -07:00
phantomptrandClaude Opus 5.5 e24cfed18b Merge #475: finished uploads leave the job table
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 14:08:06 -07:00
phantomptrandClaude Opus 5.5 6ce864c0f6 Merge rename to PS5Upload Minion
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 14:08:05 -07:00
phantomptrandClaude Opus 5.5 5d0ff05913 Payloads catalog: releases with empty notes, gone repos, readable cache age
websrv v0.35 has "body": null, which failed the whole release list.
A repo that returns 404 now says it can't be found and that the saved
version still works; the cache age reads "saved 57 days ago".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 14:07:39 -07:00
phantomptrandClaude Opus 5.5 38f992f78e helper: ended uploads leave the job table on a live session (#475)
The Files screen uploads a pick of files one AVA1 job per file, all on the
engine's one shared session. The console's job table holds 32 jobs, and an
upload that ended stayed listed (with its job thread and workers) until its
session ended: only parked jobs were ever reaped, and a session is parked only
when it ends. So the 33rd file of a pick got ERR_BUSY "too many jobs, or this
job is still closing" for 12 retries and failed, and every later file did the
same until the helper was replaced (a new session). Reproduced on the Phat
(FW 13.60): file 24 of the Switch-like set failed busy, and the table never
drained while the session lived.

- A finished upload or download (not a copy, op or console-to-console send)
  stamps concluded_ms once its JobDone is out (or the peer's came in).
- The reaper lets such a job go 10 s after that, attached or not, unless it
  still has files settling (unswept), as SPEC §11.7 intended.
- A JobOpen that finds the table full takes the slot of the concluded
  transfer that ended longest ago and nobody else holds, instead of BUSY.

Tests: C unit test of the eviction and reap rules (wire_upload), and a host
test of 40 single-file jobs in a row on one session (failed at file 32 before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 13:46:29 -07:00
phantomptrandClaude Opus 5.5 433139d18e Rename PS5Upload Files to PS5Upload Minion
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 13:25:23 -07:00
phantomptr e763303a63 Release v7.1.4 2026-10-18 12:23:30 -07:00
phantomptrandClaude Opus 5.5 91969a15f1 7.1.4 notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:56:22 -07:00
phantomptrandClaude Opus 5.5 12a61d6199 Merge console cheat downloads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:56:12 -07:00
phantomptrandClaude Opus 5.5 5c9c4aeffd Merge cheats memory-write fix (Wolverine crash)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:56:12 -07:00
phantomptrandClaude Opus 5.5 c149a6ffe1 cheats: drop SIGSTOP, lock fixes, private-memory rule
- No SIGSTOP/SIGCONT: stopping the game froze games for CheatRunner and
  SIGSTOP also reaches SceSysCore as SIGCHLD. The game keeps running;
  the write order (caves before hooks on, the reverse off) is what keeps
  it from running half a cheat.
- Physical writes (FW > 8.20), as CheatRunner does them: a range inside
  a loaded module must lie wholly inside the game's eboot or an /app0
  module (system libraries and module edges are refused); a range in no
  module (heap, direct memory: absolute/data cheats) is gated only by a
  canonical user address and a present, readable page, with no vm_map
  entry walk (that walk panicked kernels on PS4-BC and special entries).
- The other enabled cheats' ranges are collected under g_apply_lock, and
  an incomplete list (alloc, unreadable file or state, unresolvable mod,
  too many ranges) refuses the turn-off with nothing written.
- A short read of the state file is a failed read, so state_set never
  rewrites it with keys missing.
- Self-test: the keep range now really overlaps the hook, and the hook
  is checked restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:55:55 -07:00
phantomptrandClaude Opus 5.5 ef0d59b681 console cheats: download review fixes
- One deadline covers the reply and its body, and the body is read in
  chunks (getReader; arrayBuffer when there is no stream) and abandoned
  past 4 MiB: a stalled or oversized body can no longer hang the finder.
- The helper reports "replaced" when a file of that name was already
  stored; the page says so (cw_cheats_find_replaced, 21 locales).
- A stored file closes only the finder that asked for it, and only while
  its game is running.
- The finder stays open through a transient empty status: it closes when
  another game is reported or no game on two reads in a row.
- downloadCheat refuses a name the helper would refuse before fetching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:48:06 -07:00
phantomptrandClaude Opus 5.5 fd9dce6479 cheats: review fixes — rollback, private writes, FW split, shared caves
- Rollback restores the failing location too (a write torn across two
  pages, or a read-back mismatch), then the earlier ones; undo failures
  are reported in the error. The write loop, checks and rollback move to
  cheat_plan_apply() with a memory-ops backend.
- FW split as in CheatRunner: <= 8.20 mdbg only (copy-on-write, private);
  > 8.20 physical page only, no mdbg write fallback.
- A physical write must land inside the game's own module (eboot, handle
  0, or a module under /app0); Section / module_name / absolute addresses
  in a system library are refused.
- Turning a cheat off leaves alone a code cave that overlaps another
  enabled cheat of the same title.
- The game is held with SIGSTOP (not ptrace) while the writes land;
  SIGCONT on every path. kill(pid, 0) before every write.
- state_set runs under g_apply_lock; the sidecar is read whole (no 4 KiB
  cut) and an unreadable one is not rewritten.
- Self-test: fake memory backend failing on every Nth write, on the second
  page of a page-straddling write (turning on and off), on the undo
  itself, a mismatch, the game exiting mid-apply, and a shared cave.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:47:20 -07:00
phantomptrandClaude Opus 5.5 dd16c7c47f console cheats: find and download cheats on the console
The console page's Cheats section only listed cheat files already on the
console. It can now find the running game's cheats in the community repos
(read by the PS5 browser itself; a port of cheats.rs's repo list, filename
parsing and content URLs), mark the ones for the installed version, and
download one: the browser fetches it and POSTs it to the helper, which
stores it atomically where the cheat engine looks.

Helper: CSP connect-src allows raw.githubusercontent.com and
api.github.com; new /api/cheats/version (appinfo CONTENT_VERSION/APP_VER)
and streamed /api/cheats/store (strict name check, <= 4 MiB, same-folder
temp + rename via wf_receive_file). cheats.c unchanged: the engine rescans
its folders on every list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:40:49 -07:00
phantomptrandClaude Opus 5.5 02469c725b cheats: write game memory through its physical pages, all-or-nothing
Every Marvel's Wolverine cheat crashed the console; CheatRunner's worked.
Our engine PT_ATTACHed the game, set the protection byte of the vm_map
entry holding the address to RWX with kernel_mprotect, wrote with PT_IO,
and "restored" it to R-X. Measured on the Pro (FW 13.60): the game's
.text is one 95 MiB entry (0x400000-0x6324000), execute-only (0x04), so
each toggle made the whole executable RWX under a copy-on-write PT_IO
write and left it R-X. kernel_mprotect edits the entry byte directly (no
pmap update, no split); CheatRunner traced two kernel panics to that
call and moved to the page-table walk this commit uses.

- Read/write through kernel_proc_getpaddr + the direct map (mdbg as a
  fallback), inside kernel_rw_lock; read back after every write. No
  ptrace stop, no protection change.
- Apply a cheat as a whole: every location is read and checked against
  its cheat and original bytes before anything is written; on a write
  failure the earlier writes are undone. The old engine wrote whichever
  locations matched, so a jump could land without its code cave.
- Write code caves before the jumps into them when turning on, and the
  reverse when turning off (cheats_plan.c, host-tested on the real
  Wolverine pack).
- Refuse a cheat the parser had to truncate, and a base of 0.
- Toggle state is keyed by the flat index across all of a title's files;
  a toggle in the second file used to mark the first file's mods, which
  the watcher then re-applied at the next launch.

Verified on the Pro with Wolverine running: God Mode, Max Resources/XP
(20 locations), Infinite Item Charges and an MC4 Infinite Health on and
off, 60 s each, game and console stayed up; a clashing MC4 cheat was
refused with nothing written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 11:27:08 -07:00
phantomptrandClaude Opus 5.5 d11e2c1631 Save backups: put the game's name in the zip name
PPSA01234-Game Name-User.zip, when the game's name is known.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 10:53:46 -07:00
phantomptrandClaude Opus 5.5 a90ea16b4b path_policy: match path_protected_forms' header so GCC builds the C tests
GCC's -Werror=array-parameter rejected the definition's char[PATH_MAX]
parameters against the header's char * (clang accepts it), breaking
the Linux engine-workspace, C interop and coverage CI jobs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 09:59:14 -07:00
phantomptr 7ab0b4f485 Release v7.1.3 2026-10-18 09:08:27 -07:00
phantomptrandClaude Opus 5.5 2fee3c2c25 7.1.3 notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 08:51:54 -07:00
phantomptrandClaude Opus 5.5 a2d0aa8886 Merge Payloads hub, HearBridge and Processes & ports
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 08:51:53 -07:00
phantomptrandClaude Opus 5.5 9297147661 console files: transfer review fixes
- A text save is refused (409 busy) while an upload and a download both run,
  so at least two of the four web workers stay free.
- Throughput floor: uploads, downloads and .tar streams are dropped below
  1 KiB/s averaged over 60 s, on top of the 20 s idle timeout.
- Early refusals on streamed routes read off up to 64 KiB / 2 s first, so
  the page gets the real error code.
- Leftover .ps5u-*.part files older than 24 h in the target folder are swept
  at upload begin and text save (that folder only, lstat, links untouched).
- A Range header too long to keep is ignored (200, whole file), not a 400.
- The editor saves with the file's dominant line ending and says when lone
  CRs will be normalised (new string in all 21 locales).
- Upload dialog free-space separator; Upload/Download hidden also when the
  page is opened by the console's own LAN address (from /api/settings).
- The .tar walk starts from the canonical root and resolves the trust
  store's forms once per archive instead of a realpath per entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 08:51:30 -07:00
phantomptrandClaude Opus 5.5 da8220d7e7 console files: upload and download from another device
When PS5Upload Files is opened from a phone or PC on the LAN (not from the
console itself), Files offers Upload here and Download.

Upload: POST /api/upload/begin checks path policy, the folder, an existing
name (409 exists / not_a_file) and free space (507) before any byte is sent
and reserves the one upload slot (409 busy; forgotten after 30 s); the bytes
follow as POST /api/upload/data?id= (streamed, idle timeout 20 s), written
to a temp file beside the target and renamed only when complete, so a cancel
or a dropped client leaves nothing. /api/upload/cancel frees a reservation.
The page sends files (or a folder, where the browser can pick one) one at a
time with progress, Skip this file / Stop, and Skip / Keep both / Replace
for names already there.

Download: /api/download/begin hands out a /dl/<ticket>/<name> link (128-bit,
for that item only, 60 s after last use) that the browser saves with a plain
navigation: a file with Content-Length and Range, a folder as a .tar streamed
as it is read (pax for long names and > 8 GiB sizes, links and other mounts
left out). One download at a time; trust store and its ancestors refused.

Measured on the Phat (13.60, LAN), 1 GiB: upload 66-75 MiB/s, download
111 MiB/s, folder .tar 101 MiB/s. Strings in all 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 08:28:40 -07:00
phantomptrandClaude Opus 5.5 064392d6a8 console files: permissions, new file and text editing
Info gets a Permissions editor (owner/group/other x read/write/run, octal,
"apply to everything inside" for folders; exFAT/FAT drives say permissions
are not kept). /api/fs/chmod takes an optional mode (<= 0777) for the item
alone (FS_CHMOD) or recursively (CHMOD_R job); without it, Fix permissions
is unchanged.

New file (toolbar + sheet) makes an empty file and opens it in the new text
editor; Edit / Edit as text opens any file up to 1 MiB that is valid UTF-8
without NUL. Saves go through POST /api/fs/save-text: the web server can now
hand a request to a streamed route after the token check (body read by the
route with an idle timeout, not the 5 s header deadline); the save is
refused over 1 MiB or with a NUL, checks the mtime/size (and mtime_ns, now in
/api/fs/stat) the editor read before writing and again before the rename,
and writes a same-folder temp file that keeps the old mode and is renamed
onto the file after a same-device check (webui_files.c, host selftest;
cross_device.h audit updated). CRLF files stay CRLF; a changed file asks
Save anyway / Discard; ↑/↓ stay inside the text box until its first/last
line. Phone width: tools wrap, rows tighten, dialogs fit (no sideways
scroll). Strings in all 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 08:28:00 -07:00
phantomptrandClaude Opus 5.5 c0c08d9c21 Payloads: hub review fixes
- HearBridge discovery has an 8 s overall deadline, tries the remembered
  port first and stops after the first connect timeout; reads can't
  outlast the deadline.
- The HearBridge routes refuse a console address with whitespace,
  control characters or URL syntax before any request; routes are
  tested at the axum level (unknown action and bad host are 400s).
- HearBridge is read every 15 s while its card is collapsed, 5 s with
  Manage open; the User-Agent comment now says what it does and doesn't
  avoid. A failed scan no longer waits for results.
- Marker checks wait for the catalogue and stand aside during transfers.
- HearBridge's card has its own loading line; summaries re-read after
  an Update.
- Removed the seven translations the old tabs used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 07:59:00 -07:00
phantomptrandClaude Opus 5.5 c5a239238c Payloads: HearBridge status and controls
HearBridge (Bluetooth headset audio) gets an integration card on On your
PS5. The engine talks to it for the app (its page sends no CORS
headers): new /api/ps5/hearbridge/{status,saved,devices,action} routes
find it on 8090..8095, read its status with the token stripped, and
pass only volume, mute, night mode, latency, reconnect, scan, select
and stop, each checked against the ranges HearBridge takes. The token
is read fresh per change and never leaves the engine.

The card shows the stream state, headset, battery, link quality,
delay, codec, volume and game profile; Manage has the volume and
latency sliders, mute, night mode, reconnect, scan and connect, saved
headsets, recent events and a link to HearBridge's own page for
pairing, EQ and backups. Stop uses HearBridge's clean stop. An absent
or older HearBridge shows "HearBridge didn't answer" with the page
link. A card opened by a link now scrolls into view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 07:38:10 -07:00
phantomptrandClaude Opus 5.5 d6c47afd9e Payloads: On your PS5 hub; Processes & ports
Payloads now has three tabs: Catalog, Send and On your PS5 (the default
once a console is connected, and the only tab in the web UI). On your
PS5 shows a card for every payload running or installed on the console,
found from the process list and each payload's marker file, plus
running payloads the catalogue doesn't know. A card opens the payload's
web page, offers an update when the catalogue has a newer release than
the running version, stops it (the existing kill confirm), and for
ShadowMount+, nanoDNS and Payload Manager expands to the panel that used
to be its own tab.

Ports moved next to Processes: the screen is now Processes & ports with
two tabs. Old links (?tab=manager|shadowmount|nanodns|ports,
/payloads/<integration>, /nanodns, /shadowmount) land on the card or on
the Ports tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 07:23:58 -07:00
phantomptrandClaude Opus 5.5 bb53c4f928 Payloads: add HearBridge (Bluetooth audio) to the catalogue
Also name ports 8090 (HearBridge) and 9180 (PS5Upload Files) in Ports
and mark both as web pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 06:53:01 -07:00
phantomptrandClaude Opus 5.5 530c63f28f ava1 soak: let the open-descriptor count settle before failing
The weekly ASan soak failed once at round 582 with 14 -> 16 descriptors
after 581 flat rounds: a connection teardown still finishing after the
fixed 300 ms settle. Poll for up to 10 s like the job and pack checks;
a real leak never settles back and still fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 06:18:17 -07:00
phantomptr ac1fa9f8ef Release v7.1.2 2026-10-18 05:54:06 -07:00
phantomptrandClaude Opus 5.5 11d12102c0 Save data: per-user names, user filter and per-user USB backups
On a shared console every user's saves were listed together under raw
user ids, and USB backups of the same game shared one folder, so
Restore all from USB could restore one user's backup into another's
save. Label saves with the owner's name (profile info), start on the
signed-in user with a Whose saves picker, name local backup zips after
the game and user, and keep USB backups in a per-user folder (legacy
backups used only when one user owns the title).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-18 05:54:03 -07:00
phantomptr d7169cc7e1 Release v7.1.1 2026-10-17 22:53:28 -07:00
phantomptrandClaude Opus 5.5 a54b04fbc4 Big Sur: old-WebKit fallbacks so the app scrolls again
macOS Big Sur's WKWebView (Safari 14) lacks dvh units and the
padding/margin-inline/block and inset shorthands. The minifier dropped
the hand-written height:100% fallback, so the app shell had no height
and nothing scrolled. Write an older equivalent before each such
declaration in the built CSS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 22:53:26 -07:00
phantomptr 23e33a21ca Release v7.1.0 2026-10-17 16:26:43 -07:00
phantomptrandClaude Opus 5.5 4432ea1459 7.1.0 notes: don't promise the offline copy on every browser
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 16:20:10 -07:00
phantomptrandClaude Opus 5.5 13a61f5c1e 7.1.0 notes and FAQ for PS5Upload Files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 16:19:35 -07:00
phantomptrandClaude Opus 5.5 712ff87d6a console page: final hardware-pass fixes
Web threads get the 512 KiB mgmt stack (they run mgmt handlers); a recent
folder that is gone (404) is dropped via a new prefs "forget" op; a non-exFAT
image inside a .ffpfsc reads as unsupported, not damaged, and is logged to
stderr; text find shows its count after a pause in typing; free-name probes
use /api/fs/stat missing_ok (200 {"missing":true}) so no 404 noise. hw_info
comment updated for the page's 10 s HW_TEMPS poll on a web worker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 16:19:35 -07:00
phantomptrandClaude Opus 5.5 a507c9b035 Merge console page robustness and polish (F8)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 15:46:42 -07:00
phantomptrandClaude Opus 5.5 831018b04d console page: F8 review fixes
- cheats: "attached to the game" (busy) only for EBUSY; other attach
  failures stay a plain "pt_attach failed (errno=N)".
- Continue on your phone shows only in the console's own browser
  (127.0.0.1/localhost); a gap above the dialog buttons.
- The token read gives up after 4 s (offline screen); a small splash
  instead of a blank page while it is asked.
- No silent reload: an appcache update, or a helper version newer than
  the page's build, shows a one-press "updated: Reload" banner (Later
  hides it). cw_update_* in 21 locales.
- own_addrs reports a getifaddrs failure and the list is kept (no
  flapping); EMFILE/ENFILE/ENOBUFS/ENOMEM never count toward a broken
  listener.
- backHistory header: Escape/○ at Home closes the browser on the PS5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 15:34:03 -07:00
phantomptrandClaude Opus 5.5 f77c33e579 console page: rebind, marquee, continue on phone, deferred fixes
- Helper listener heals itself on the accept thread (no new thread): every
  5 s it rebinds after a resume (10 s clock gap) or, with LAN access on,
  when the console's addresses change (Host allowlist refreshed); a
  listener whose poll/accept keeps failing for 5 s is rebound too.
- Long file names slide while their row is focused (text-indent marquee,
  prefers-reduced-motion respected; one focusin/focusout pair).
- Continue on your phone: /api/settings carries the console's LAN address;
  rename, new folder, go to path and bulk rename show a QR code and
  http://<addr>:9180/ while LAN access is on. Tiny dependency-free QR
  encoder (byte mode, v1-10, L/M), checked against segno symbols.
- Deferred: FS stat ids from stat() (a symlink to the destination is
  itself); clipboard header; language switch keeps the shown language
  until the new one loads, strings fetch times out after 10 s; own
  Cache-Control detected in any case; cheats toggle right after the game
  exits says closed at once (helper drops its 2 s cache, dead pid reads as
  no game), a racing PC/page toggle says "another app is changing";
  failed batch items stay selected; Fix permissions title counts items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 15:18:01 -07:00
phantomptrandClaude Opus 5.5 4ff889720d console page: offline page, error boundary, close on ○ at Home
- Offline copy: a service worker (/sw.js, network first for / and
  /strings/*, never /api/* or POSTs) plus the appcache fallback
  (<html manifest="/cache.appcache">) the PS5 browser honours for Payload
  Manager. Both are emitted by the console build with the page's hash and
  embedded in the helper (webui_offline.c), served with their own types and
  Cache-Control: no-cache; the page is now no-cache (storable) instead of
  no-store.
- Boot gate: the page reads /api/token first; no answer (or not the
  helper's) shows "PS5Upload Files isn't running" with Try again / Close,
  re-checked every 5 s, reloading once the helper answers.
- Error boundary: Reload, or Reset settings & reload (this page's
  ps5upload.* keys, the tour mark kept), instead of a blank page.
- ○ on the first screen (PS5 browser only) calls window.close(); a refused
  close leaves the next ○ to the browser. A popstate that pops nothing is
  ignored, and within 1.5 s of load before any key/click a pop only puts
  the guard back (WebKit's load-time popstate, tour-at-load).
- cw_* strings for F8 in all 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 14:58:11 -07:00
phantomptrandClaude Opus 5.5 7d510c0f06 Merge #473 app.db pagination fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 14:53:37 -07:00
phantomptrandClaude Opus 5.5 17716f912b Merge console files viewer, search and disk usage (F5+F6)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 14:38:44 -07:00
phantomptrandClaude Opus 5.5 bf7157a5ff console files: search and viewer hardening
Index name match is linear (iterative, one backtrack point; selftest bounds
the pathological pattern); star runs collapsed. INDEX_SEARCH filters an
optional "under" before its limit; This folder says when matches elsewhere
filled the reply. Text viewer draws a window around a find target with
memoized blocks and one scan per query. Hex reads only 64 KiB; end-of-list
buttons keep focus (hex First/Last added); D-pad left/right on the picture
changes image (nav hands arrows to [data-nav-arrows]); SFO key scan bounded;
folder size and disk usage share one walk; Search waits for the drives;
Disk usage starts at the folder shown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 14:37:10 -07:00
phantomptrandClaude Opus 5.5 ec2c8f3a6b console files: search and disk usage
Helper: /api/index/start|status|search|cancel over INDEX_START / STATUS /
SEARCH / CANCEL (handlers unchanged; the engine never calls them). Their
bodies are scanned quote to quote, so every root and pattern is checked
for no '"', '\' or control character and < 256 bytes (codec, selftested).
Roots: 1-8, absolute, never the trust store (403). The page's last start
(roots, started_at, cancelled) is remembered so status says whether the
index there is the page's and what it covers. Search answers at most 500
results, filters by `under` (asking the helper's 5,000 for a folder) and
never returns a trust-store path; truncated when the helper's limit or
the page's is reached. JSON buffers on the heap.

Page: Search (toolbar) — name or * / ? pattern (a word matches anywhere),
all drives or this folder; the first search builds the index for that
scope with a running count and Cancel, then searches; a covering index
is reused; results (name, folder, size) open in Files at the item. An
older helper (404) is told. Disk usage (toolbar) — the drive's
subfolders as bars, biggest first, measured one after another with
folderSize's walker under one budget (500k entries, 3 min, 2,000
subfolders), cancellable, one at a time page-wide (refuses while a
folder-size walk runs); "›" looks inside (○ comes back up), ✕ opens in
Files. Strings cw_files_search_* / cw_files_usage_* in 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 14:11:33 -07:00
phantomptrandClaude Opus 5.5 3a1e8019b6 console files: viewer — text find, JSON, hex, image browsing, game banner
Text: the first 1 MiB as numbered rows (long lines cut every 2,000
characters, numbered once), drawn 1,500 rows at a time; find with
Previous / Next on-screen buttons (case-insensitive, wraps, counts up to
10,000), a wrap toggle, and "View as hex". .json files are pretty
printed (shown as written when they do not parse); sce_sys/param.json
gets a summary card: title, title id, content id, version, required
system software.

Hex: the first 64 KiB of any file (sheet "View as hex"), offset | hex |
ASCII, 1 KiB pages with Previous / Next page.

Images: previous / next through the folder's images in list order
(on-screen arrows, disabled at the ends; ←/→ on the picture when the
browser delivers them); the 16 MiB cap message stays.

Game banner: a folder with sce_sys shows title, id, version, firmware and
sce_sys/icon0.png, from param.json (PS5) or param.sfo (PS4: PSF parser,
strings and integers, every offset bounds-checked), each read ≤ 64 KiB.

New code under files/viewer/; Files.tsx and ActionsSheet only wire it.
Strings cw_files_vw_* / cw_files_game_* in 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 14:06:39 -07:00
phantomptrandClaude Opus 5.5 d46a966990 Merge console files PC integration (F7)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:53:30 -07:00
phantomptrandClaude Opus 5.5 0ffeba67f8 console files: handoff and upload-badge hardening
- The Uploading badge reads upload roots through ava1_data_upload_roots,
  under the open lock (where roots are written) and the table lock, and
  leaves out parked, finished, stopping and recovery-placeholder jobs.
- files_handoff_take_json checks its buffer before taking, so a too-small
  buffer can no longer empty the slot and lose the handoff.
- PC app: the Show on PC poll skips its ticks while a transfer runs on
  that console (like the other background management pollers); away from
  File System a handoff becomes a toast with "Open" instead of navigating.
- Console "Show on PC" now says "Sent to your PC." (no promise it opens),
  in all 21 languages; new PC strings for the Open offer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:52:35 -07:00
phantomptrandClaude Opus 5.5 1f16fb97fc console files: decompress progress, case-only rename, unpack name hardening
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:48:00 -07:00
phantomptrandClaude Opus 5.5 4b51f802d3 console files: shared favourites and Show on TV / Show on PC
The console page takes the PC's "Show on console" handoff every 3 s while
visible (any section) and opens Files there: a folder as it is, a file in
its folder with the file focused, a path that is gone opens nothing and
says so. "Show on PC" in the actions sheet (once the helper is known to
have handoffs) leaves the item for the PC app. Folders a PC upload is
writing into (/api/jobs "uploading") show an "Uploading" badge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:36:15 -07:00
phantomptrandClaude Opus 5.5 c12787d7e0 console files: bulk rename, folder size, verify, decompress
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:22:35 -07:00
phantomptrandClaude Opus 5.5 8c86887b97 console files: Pinned on console, Show on console and Show on PC in the PC app
File System's path bar dropdown gets a "Pinned on console" group (the
console page's pinned folders, a click opens one; pin / unpin the folder
shown). The row and folder context menus get "Show on console": the
console page opens that place. The app takes the console's "Show on PC"
handoff every 3 s on File System (10 s elsewhere, never while hidden) and
opens it in File System with a toast. All of it is hidden against an
older helper (the engine says supported:false).

Strings for both sides in all 21 languages, in one block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:20:58 -07:00
phantomptrandClaude Opus 5.5 8d188eda1d console files: files.* methods and engine routes for shared prefs and handoffs
Helper: files.prefs_get/prefs_set (148/149) reach files_prefs.c, the same
file the console page's /api/files/prefs uses; files.handoff_put/take
(150/151) keep one Show on TV / Show on PC slot per direction in helper
memory, gone after two minutes, emptied by a take (files_handoff.c, host
self-test). The page gets /api/files/handoff/take {for:"console"} and
/api/files/handoff/put {to:"pc"}; /api/jobs adds "uploading", the roots
of up to 8 running uploads, for the Files badge.

Engine: GET /api/ps5/files/prefs, POST .../prefs/set, .../handoff/put,
.../handoff/take. An older helper answers unknown method, reported as
{"supported":false} so the PC app hides the features.

console files: shared favourites and Show on TV / Show on PC

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 13:09:27 -07:00
phantomptrandClaude Opus 5.5 dccc77f38b console files: paste decides "the item itself" by dev+ino, Stop/close skip a waiting conflict
/api/fs/stat returns dev and ino (lstat of the accepted path) so a
case-insensitive exFAT spelling of the same folder or item is never offered
Replace (which deleted the item first) and a cut there is a no-op. Jobs Stop
left running stay in the cut clipboard; Stop during a Replace delete says so;
Stop and closing Files answer a pending conflict with Skip; one combined
replace-all body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 12:49:19 -07:00
phantomptrandClaude Opus 5.5 910321cb4a console files: copy, cut and paste with conflict choices
Copy / Cut in the actions sheet put items in a page clipboard (kept across
folders and sections); a bar in the status line shows "3 items to paste
(cut)" with Paste here and Clear. Paste stats each destination first; a
conflict asks Skip / Keep both ("name (2).ext", first free number) /
Replace (danger confirm), with Apply to all. Replace of a file uses the
copy job's overwrite flag (new optional "overwrite" on /api/fs/copy, off by
default); a folder (or a kind change, or a same-drive cut, which is a
rename) deletes the existing one first and waits, since overwrite merges
folders. Cut = rename on the same drive, copy job with move across drives;
one batch at a time with progress and Stop; a successful cut empties the
clipboard, a copy keeps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 12:41:26 -07:00
phantomptrandClaude Sonnet 5.5 099b941871 console files: deterministic 20k test, accent-folded sort, select-bar filter clear
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 12:22:00 -07:00
phantomptrandClaude Sonnet 5.5 4fcb9e913a console files: one-row toolbar, more rows on screen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 12:18:29 -07:00
phantomptrandClaude Sonnet 5.5 f7daeec308 console files: sort, hidden files, filter, icons, select all
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 11:48:31 -07:00
phantomptrandClaude Opus 5.5 a1d1692ef0 console files: hold unmount while a game runs, hold eject during transfers, pinned in Go to path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 11:31:45 -07:00
phantomptrandClaude Opus 5.5 5fa4afeb55 console files: path bar, favourites, recent, eject and unmount
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 11:22:19 -07:00
phantomptrandClaude Opus 5.5 264b8096f8 Review fixes for #473: reconcile folders only on a partial app.db read
- Registered-only titles are added only when app.db could not be read in
  full; the helper's registered list is every /user/app folder, so with a
  complete read a folder app.db does not list is a leftover, not a game.
  NPXS ids are excluded, and a candidate needs a mount.lnk source or a
  param.json/param.sfo in its sce_sys.
- app.db pages carry the table's row count (SQL reader only); the engine
  marks the list truncated when it changes between pages.
- A SQL walk that ends on anything but SQLITE_DONE reports truncated.
- FAQ: the phone guide is phrased as a question; references updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 11:13:58 -07:00
phantomptrandClaude Opus 5.5 61178d7526 FAQ: use PS5Upload from your phone or another computer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 11:07:03 -07:00
phantomptrandClaude Opus 5.5 b7b1ccaf58 Page through the app database so no installed game is hidden (#473)
APP_DB_QUERY answered at most 256 rows, and fewer when its 64 KiB reply
filled, with nothing saying the list was cut. A title installed by a
homebrew installer (no /user/appmeta folder) that sorted past that point
disappeared from the installed list.

Payload: app.db.query takes an optional {"offset","limit"} window and
answers offset/next/more/truncated; a full buffer now ends the page with
more=true instead of closing the list. An empty request is page one, so
older engines keep working.

Engine: appdb_query follows the pages (at most 32) and marks the list
truncated when it could not finish (or an older helper returned a full
256). The installed list reads app.db once per request, adds registered
titles whose app folder exists, reports incomplete, and a truncated list
never proves a title absent for install verification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 11:07:03 -07:00
phantomptrandClaude Sonnet 5.5 3b4338d284 console page: name it PS5Upload Files
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 10:53:29 -07:00
phantomptrandClaude Opus 5.5 d435ac27db console page: load only the active language's strings
The page embedded all 21 languages' cw_* strings (174 KiB of the 220 KiB gzip
budget). Now it embeds English only; every other language is a separate
build artifact (dist-console/strings/<lang>.json) gzip'd into the helper and
served at GET /strings/<lang>.json (Host/Origin checked, no token, immutable
year-long cache; the page asks with ?v=<hash of the strings>). The page shows
English until the chosen language arrives, falls back to English per key, and
stays in English (logged once) when a load fails.

Page: 607.1 KiB raw / 174.4 KiB gzip -> 357.5 KiB raw / 112.5 KiB gzip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 10:49:30 -07:00
phantomptrandClaude Opus 5.5 4d7575ec3b console page: the input log's last batch gets past the helper's rate gate
Fix round 2. The helper refused a request under 500 ms after the last one (429),
which caught the final batch sent as Controls closes, right after a regular one,
so ○ was still lost. The gate is now a pure, host-tested function: one request
marked {"final":true} is admitted inside the window, once per window, each body
still at most 4 KiB. The page marks its final batch (keepalive, cut to fit with
the flag) and sends it only after a regular send still on the wire, so the two
never arrive out of order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 10:29:15 -07:00
phantomptrandClaude Sonnet 5.5 f220b63e58 console page: Fix permissions in Files
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 10:25:10 -07:00
phantomptrandClaude Opus 5.5 66a321abb9 console page: Controls says Received for unused keys, keeps the last log batch
Fix round 1 for the controls guide. Controls shows "Works" only for input the page
acts on today (nav.ts's always-live keys, verified bindings, the pointer) and
"Received" for keys that arrive but are not used yet. Stopping the input log, or
the page being hidden while it runs, sends the queued events at once with fetch
keepalive, so ○ closing Controls is not lost. Legend labels wrap to two lines and
fit in all 21 languages; the drive list's Try again shows Loading; the focused
drawing keeps its ring without the washed-out fill; unused cw_settings_display
removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 10:20:54 -07:00
phantomptrandClaude Opus 5.5 f9ffbe4df9 console page: controls guide, first-run tips, help
A Controls screen (Settings, the rail's Help, or OPTIONS once measured) draws the
DualSense with each button's job on the page and lights every button the page
receives ("Works"); PS and Mute are marked as used by the PS5, the rest "not
received yet". While it is open the input log is on, and keys do nothing else
(no click, no focus move, no browser reload) except ○, which closes it.

Three first-run tip cards (sections; ✕ selects, ○ goes back, everything has an
on-screen button; the PS5 pointer and full screen) show once, skip with ○ or
Skip, and come back from Settings › Show tips again. A help overlay lists the
buttons that work on the current screen and those not confirmed yet. The hint
bar shows ✕ and ○ plus only verified buttons with a job on the screen in front.

Settings order: Theme · Language · Full screen · Controls · Show tips again ·
Allow other devices · home screen tile · About. Empty and failed states say what
happens next (drive list and settings get Try again). CHANGELOG 7.1.0 describes
the final page. Gzip budget 220 KiB (ruling R19).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 10:09:24 -07:00
phantomptrandClaude Opus 5.5 e4d069a3f0 console page: Cheats for the running game
The console page gets a Cheats section (rail: Home, Files, Cheats, Settings; Home's
Cheats shortcut now shows). It lists the running game's cheats as switches: X or the
square button switches the focused one, rows are inert while a switch runs, and the
helper's state is read again after every switch. No game, no cheats, the game closing
while the page is open, and helper errors each say what to do next, with Refresh.

The helper adapts the cheat methods exactly as the PC engine calls them:
/api/cheats/status (CHEATS_STATUS), /api/cheats/list {title_id} (CHEATS_GET, every
entry re-escaped, a cut reply keeps its whole entries) and /api/cheats/toggle
{title_id,index,on} (CHEATS_TOGGLE, its free-text refusals mapped to tokens).
Downloads and deletes stay in the PC app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 09:39:58 -07:00
phantomptrandClaude Sonnet 5.5 297a76efd2 console page: every running task keeps its Cancel, honest empty state, cover fallback
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 09:14:44 -07:00
phantomptrandClaude Sonnet 5.5 8db3aeab3c console page: stored theme applied before first paint, stricter token guard, visible danger focus
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 09:11:16 -07:00
phantomptrandClaude Sonnet 5.5 d286b72deb console page: Home without power actions or repeats
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 09:08:27 -07:00
phantomptrandClaude Sonnet 5.5 9274e78afe console page: themes matching the PC app
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 08:59:38 -07:00
phantomptrandClaude Opus 5.5 33f1851cdc console page R1 fixes: text fields never take hover focus, unmeasured buttons stay inert, honest full screen
- Hover never focuses a text field; a field holds focus against hover only for
  1.5 s after a key typed into it, so the ring cannot stay on an input while
  the pointer (and the native ✕ click) sits on OK.
- Ruling R18: only verified bindings act; the always-live set is the arrows,
  Enter, Escape and Backspace (and the old gamepad buttons). F5, Home,
  PageUp/PageDown, ContextMenu, F1, F11 keep their browser defaults. PageUp/
  PageDown are left to text fields once verified.
- Full screen: a refusal (error event or rejected promise) hides it for the
  session; a webkit request counts only when the page really went full
  screen; automatic only in the PS5 browser; Escape spends no try; the
  Settings switch follows fullscreenchange.
- cw_hint_filter removed from all 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 08:52:14 -07:00
phantomptrandClaude Opus 5.5 c1c74dece8 console page: the pointer is the focus, the whole DualSense in one table, an input log, full screen, TV scale
The PS5 browser drives an on-screen pointer and ✕ clicks at it, so the page
now treats hover as focus: the ring and what ✕ activates are the same
element. After a key move the pointer is parked (drift under 6 px is
ignored) and a click there activates the focused control instead.

nav.ts's button table covers every DualSense button with its action, the
keys/keyCodes it may arrive as and verified:false until measured: L2/R2 page,
L3 top, R3 rail, OPTIONS help, Create refresh, touchpad full screen, PS/Mute
system. The hint bar shows ✕/○ always, the rest once verified.

POST /api/input-log appends compact, privacy-neutral event lines to a 64 KiB
ring at /data/ps5upload/webui-input.log (same-directory rewrite, bounded
body, 429 under 500 ms); the page sends only while setInputLogEnabled(true).

Full screen on the first activation (standard, then webkit-prefixed), with a
Settings switch hidden where unsupported. Type scales with the viewport
(26 px at 1540x700). Raw page budget 640 KiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 08:25:31 -07:00
phantomptrandClaude Sonnet 5.5 20f8809415 Hide the console page tile from the PC library; settings fixes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 07:52:03 -07:00
phantomptrandClaude Opus 5.5 8550d3380d CHANGELOG 7.1.0: say what the console page was verified to do
Made for the controller (D-pad and ✕) and works with the PS5's Back
button; no "controller alone" claim. Batches run one item at a time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 07:35:15 -07:00
phantomptrandClaude Opus 5.5 c51c38d919 console page: one job at a time, browser Back steps back in the page, polish
- Copy/move/delete batches send the next item only after the previous
  item's job left "running" (files/batch.ts: page-wide batch, survives
  section switches, "Copying 3 of 40", Stop ends it before its next item).
- The PS5 browser's ○ is history back: one history guard sits on top
  while the page has somewhere to go back to (modal, folder, a section
  other than Home); popstate runs the page's back action. Escape,
  Backspace and a gamepad ○ call history.back() through the same path.
- Home's confirm dialog keeps 409/503 errors inside it; the status poll
  pauses while the page is hidden; images over 16 MiB say "too large to
  preview"; storage cards are role=button with Enter/Space; the tile
  switch waits for the helper's real result (tile_busy/tile_failed).
- New cw_ strings in all 21 locales; three unused ones removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 07:35:15 -07:00
phantomptrandClaude Opus 5.5 284d22c6e5 helper web UI: free seen jobs, hide the tile from the PC library, games-only Close
- /api/jobs releases the page's finished jobs after replying
  (ava1_jobs_release_seen), so batches cannot fill the shared table.
- list_registered_titles_json leaves out WEBUI_TILE_TITLE_ID; a PC's
  APP_UNREGISTER of the tile is Settings -> tile off (saved tile:false,
  tile thread removes it) so the next start does not re-register it.
- Now running: the focused app is never the tile; the fallback names
  only a game title id (PPSA/CUSA/... prefixes), never the browser, the
  tile or homebrew. Codec selftest covers it.
- /api/settings carries tile_busy/tile_failed (webui_tile_state); the
  tile request is made before the reply.
- put_str/r_status clamp `at` after every escape/printf; send_error and
  r_fs_delete clamp too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 07:35:02 -07:00
phantomptrandClaude Opus 5.5 9d2625850e ava1: release the console page's finished jobs once it has seen them
ava1_jobs_release_seen(me): every finished operation or copy owned by
the console page keeps only the grace (AVA1_OP_GRACE_MS) after the page
first read it finished, instead of a copy holding one of the 32 shared
job slots for the full 10-minute park age. Operations reuse
ava1_op_status_delivered; copies are restamped and the reaper keeps a
delivered copy only for the grace. A paired PC's jobs are never touched.

ava1-ctest: the 32-job cap with list_all (full table refuses a 33rd for
the page and a PC; releasing the page's own makes room, PC jobs stay)
and the grace (page jobs gone after ~10 s, PC op and copy still listed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 07:35:02 -07:00
phantomptrandClaude Opus 5.5 ffa85203ec payload: square, full-bleed PS5Upload tile icon
The PS5 shows home-screen tile art edge to edge. The macOS squircle icon (transparent rounded
corners and margin) sat as a small rounded square inside a grey frame; this is the same logo
flattened onto a white square, centred, filling ~70% of the tile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:59:50 -07:00
phantomptrandClaude Sonnet 5.5 76928943b9 console page: Home lists finished jobs only from this console
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:54:23 -07:00
phantomptrandClaude Sonnet 5.5 81a6e0d5ff console page: show the name as PS5Upload
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:46:47 -07:00
phantomptrandClaude Opus 5.5 97345a6514 console page: rail/content navigation regions, storage cards open Files
The rail and the content are nav regions ([data-nav-region]). Up/Down stay
in the focused region and stop at its ends. Left/Right move within the
region while something lies straight that way, else enter the neighbouring
region at its entry: [data-nav-entry] (the rail's active section), else the
control last focused there if it is still shown, else its first control.
Modals keep their own scoping. ✕ on a Home storage card opens Files at
that drive's path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:42:46 -07:00
phantomptrandClaude Sonnet 5.5 81654f8793 console page: Settings
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:33:08 -07:00
phantomptrandClaude Opus 5.5 902d6cef65 console page: Files review fixes
Closing the viewer aborts its reads (no more 1 MiB requests holding a
helper web worker); copying or moving a folder into itself or a subfolder
is refused on the page with its own message; a 409 says "already exists"
only for an exists code; opening Files at a path (Browse USB) resets the
selection and focuses the first row like any folder change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:22:45 -07:00
phantomptrandClaude Opus 5.5 79a14d5731 console page: Files
Drives -> folders (folders first, natural name order, sizes, free space),
paged 256 at a time through /api/fs/list's next offset; "Show more" loads
the next page when the D-pad reaches it. The actions sheet (triangle or the
on-screen "..."): View, Copy to..., Move to..., Rename, New folder, Info,
Delete (confirm names the item and the count). Select (square or the
toggle) applies Copy/Move/Delete to several items, sent one request at a
time; Copy/Move/Delete are off while a batch is being started. Moves rename
on the same drive and fall back to a move copy job on 409 cross_mount; copy
and move send each item's full destination path, as JOB_COPY and the
engine use it. Viewer for png/jpg (blob URL, revoked on close) and
txt/log/json/ini/xml (first 1 MiB as text nodes, D-pad steps through it).
Circle goes up one folder or closes the open modal.

ConfirmDialog (and every new modal) restores focus to the row now at the
opener's place when the opener is gone; Files also refocuses that place
when a refresh removes the focused row. App's circle handler is now a
nav fallback so a section's own circle runs first. Home's Browse USB
appears, since Files opens at ctx.params.path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 06:16:58 -07:00
phantomptrandClaude Opus 5.5 f91e0f9b67 console page: Home
Running game with Close, one storage card per drive, every job with its
owner (this console / a PC) and Cancel, quick actions Browse USB (hidden
until Files opens at a path), Rest mode and Restart. Every destructive
action goes through the shared ConfirmDialog (nav modal, focus on the safe
choice, ○ closes). useJobs polls /api/jobs every 1 s while a job runs,
every 5 s otherwise, stops on unmount and on 401. Sections get a context
(status, refreshStatus, openSection with params). Strings in 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 05:49:08 -07:00
phantomptrandClaude Opus 5.5 8f7233827f console page: modal-scoped navigation, anti-framing headers, D-pad echo guard
- nav.ts: while a [data-nav-modal] is open only handlers scoped inside it
  run (onNavAction's new scope getter), so the reload banner (and later
  dialogs) keep ○/L1/R1 from moving focus to the page behind; confirm
  with focus outside the modal brings focus in instead of clicking.
- R12: an Arrow keydown within 100 ms after the gamepad fired the same
  direction is dropped as the browser's echo.
- GET / adds frame-ancestors 'none' and X-Frame-Options: DENY.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 05:29:45 -07:00
phantomptrandClaude Opus 5.5 99dda9acb8 console page: build, shell, controller navigation
The page the helper serves on the PS5 itself: client/src/console/ built by
vite.console.config.ts into one self-contained dist-console/index.html
(script and styles inlined, safari13, 253 KiB raw / 84.5 KiB gzip; the
build fails over 450 KiB raw or 150 KiB gzip). payload/Makefile gzips it
into build/webui_page.c and the helper serves it at GET /, with
GET /api/token for the per-start token.

- Shell: top bar (logo, console chip from /api/status), rail of the
  implemented sections (Home, Files, Settings placeholders), hint bar
  showing only verified bindings, reload banner on a 401.
- nav.ts: spatial focus (aligned neighbours first), the R11 default input
  table (keyboard + Gamepad "standard", all unverified), D-pad repeat.
- api.ts: token fetched once, X-PS5U-Token on every POST, 401 → expired.
- strings.ts: cw_* keys from all 21 locales via build-console-strings.mjs
  (vm-eval like the i18n gate), English fallback.
- CI: client npm ci before every make payload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 05:23:26 -07:00
phantomptrandClaude Opus 5.5 87880bf0db payload: webui tile re-mounts only after a reboot and removes its staged /user/app copy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 05:01:25 -07:00
phantomptrandClaude Opus 5.5 7a12127b67 payload: webui settings and ps5upload home-screen tile
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 04:55:15 -07:00
phantomptrandClaude Opus 5.5 1bbeb52fa3 payload: webui read replies sandboxed, web calls counted in the exit's in-flight RPCs, list next offset
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 04:32:30 -07:00
phantomptrandClaude Opus 5.5 da9cf4e49e payload: webui API routes for home, files and settings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 04:22:17 -07:00
phantomptrandClaude Opus 5.5 2803f01d19 payload: bounded webui server inside the helper
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 03:59:04 -07:00
phantomptrandClaude Sonnet 5.5 180309354f payload: webui token and host/origin checks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 03:25:24 -07:00
phantomptrandClaude Sonnet 5.5 8004ed1a38 payload: webui HTTP parser: segmentation-independent line cap, reject duplicate identity headers
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 03:23:25 -07:00