Commit Graph
27 Commits
Author SHA1 Message Date
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 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 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 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 f1fea5f7c8 payload: webui HTTP request parser and response head
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 03:20:51 -07:00
phantomptrandClaude Opus 5.5 0c1aeae1ef Payloads → Ports: the ports in use on the PS5 (Discord ask)
New helper method net.ports (147, frame 265/266): binds each TCP and UDP
port and closes it at once (never connects, so no loader sees a silent
client), then binds 127.0.0.1 and the LAN address to tell network,
console-only and outgoing sockets apart. The socket sysctls
(net.inet.*.pcblist, kern.file) answer ENOENT on FW 13.60. A full pass
takes ~890 ms on the Phat. The engine names well-known ports and the
Payloads screen lists them, with Open only for web UIs and unknown ports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EU1Z2mdhAxBrH1yb48pxik
2026-10-15 10:05:11 -07:00
phantomptrandClaude Opus 5.5 252cfc4d69 check-no-ftx2: skip vendored payload/third_party (zlib's CRC table)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EU1Z2mdhAxBrH1yb48pxik
2026-10-14 20:48:43 -07:00
phantomptrandClaude Opus 5.5 ece147d720 Games: hide a title's icon from the PS5 home screen, and show it again (#407)
For shortcuts and loaders that, once set up, only clutter the home
screen. ⋯ → "Hide from home screen" on a Games card; a "Hidden" badge
marks it, "N hidden from the home screen" at the top filters to them,
and ⋯ → "Show on home screen" puts it back.

How: every user's icon table in app.db (tbl_iconinfo_<user>) has a
`visible` flag; the system hides some of its own apps with it. The
helper (app.icon_set, app.hidden_list) flips only that flag: nothing is
deleted, the title stays installed and playable. Guards: title ids only,
system apps (NPXS) refused, tables found by shape (titleId + visible),
app.db backed up once to /data/ps5upload/app.db.before-hide before the
first change, BEGIN IMMEDIATE (fails before any change if the system
holds the lock), and rolled back unless at least one and at most one
row per table changed. The hidden list is read live from app.db, so it
cannot drift from the console, and leaves out the system's own hidden
apps. The home screen redraws when an app is next opened and closed;
the console shows a notification saying so.

Verified on the Phat (FW 13.60): WebKit Autoloader hidden, listed, shown
again; a system app and an unknown id refused; the backup written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-11 00:36:44 -07:00
phantomptrandClaude Opus 5.5 d0c02ced52 check-no-ftx2: skip the website's copy of the release notes
site/releases.json repeats past release notes, which name FTX2, so the
check failed engine CI on every commit since the site was added. It is
history, like CHANGELOG.md, which is already exempt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-10 23:03:10 -07:00
phantomptrandClaude Opus 5.5 6862b8c522 make promo-post: introduction posts for new users
scripts/promo-posts.js writes .release_posts/about/: what PS5Upload is, its
features, how to start and where to download, shaped for X (a thread that
fits 280 per post, checked), Discord and Reddit, plus app screenshots to
attach. The version and link come from VERSION; release-posts.js stays the
per-release notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-10 20:53:04 -07:00
phantomptrandClaude Opus 5.5 90489a84a2 Android: install and download from a link, install from a saved server, and the online title lookup work in the Android build
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-10 16:07:54 -07:00
phantomptrandClaude Opus 5.5 6489b716c2 Android: the launcher shows the PS5Upload logo on every build
The logo was only applied when the Android project was first created, so an
existing one kept Tauri's placeholder, and the round icon was a small tile
inside a circle. scripts/release/android-icons.py draws the set from the icon
source (adaptive logo in the safe zone over white; full-bleed white tile and
disc for older launchers), and the post-init patch copies it on every build,
local and CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-10 16:02:02 -07:00
phantomptrandClaude Opus 5.5 8d05f60a7e PS5 Payload SDK v0.44, and scripts/update-ps5-sdk.sh to bump it
Pin v0.44 (sha256 4d06eab7...). Its crt/ and prospero-nid are identical
to v0.43, so the vendored sdk-crt (+ ps5upload.patch) and the portable
prospero-nid stay as they are; the helper, installer and elfldr build to
the same code (only the build-id differs). v0.44 adds LLVM 23 to the
candidate list, so the Makefile comment and Homebrew fallbacks move too.

scripts/update-ps5-sdk.sh (make update-sdk): finds the latest release
(or --tag), checks the zip, rewrites the pin, re-vendors prospero-nid
and crt only when upstream changed them (stops if our crt patch no
longer applies), moves the "SDK vX.Y" doc mentions and installs with
install-ps5-sdk.sh, keeping the old SDK as a backup. --check only
reports. The installer names its backups after the release they hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-10 11:14:44 -07:00
phantomptrandClaude Opus 5.5 7a5608c6a9 Remove dead engine/payload code and the FTX2 migration shims
Engine: drop the unused /api/fakelibs/manifest, /api/collection/summary and
/api/ps5/content-db/backup routes, the payload FTP client (core ftp.rs, FTP_START/STATUS)
and NOTIF_SEND, and pub items only their own tests called. The DPI reason strings now come
from the payload_lifecycle constants everywhere.

Shims: the legacy helper replace flow (engine legacy_helper/legacy_guard, the helper/state
and helper/replace routes, the status-error fold), the client's helper_old banner/state and
the payload's legacy takeover and retired-folder removal are gone. An old helper that does
not speak AVA1 now reads as no helper, and the normal send-the-helper flow replaces it. The
6.0 console folder cleanup now starts from a successful status probe.

Payload: remove the FTP server and its self-tests, notif.send, ftp.start/ftp.status
(ids 119, 120, 123 retired in the schema), the unused ShellUI sensor/install RPCs,
runtime_reconcile_mounts, register_services_init, hw_temps_get_text and
mgmt_call_fs_mkdir. MGMT_METHODS.md describes the current method table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
2026-10-10 06:24:09 -07:00
PhantomPtrandClaude Opus 5.5 9e5c258ad8 6.0.0: CI fixes, upgrade clean-up, docs and version (#377)
* docs: 6.0.0 changelog, README, FAQ and contributor docs

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* Release prep: version 6.0.0

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(ci): keep the leaked test pools reachable for LSan; skip the tiny-file floor under coverage

- ava1-ctest diag/mgmt_fs: the &'static Pool each test leaks for
  AvaTransport::with_pool is now held in a static list, so LeakSanitizer sees
  it (and the sessions on its threads) as reachable instead of reporting
  ~140 KB of indirect leaks the frame-name suppression could never match.
  Verified under clang ASan+LSan in Linux Docker: diag 13/13, mgmt_fs 40/40.
- download.rs tiny-file throughput floor is skipped when cargo-llvm-cov runs
  (CARGO_LLVM_COV set): instrumentation slows every call several times over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): data_rust servers use the clients' fast timing

Five folder-host tests gave the client fast timing (dead after 500 ms) but
left the server on the default (ping every 2 s). On a slow runner a half-second
gap made the client drop healthy lanes and the job stalled until the 36 s
progress limit (both CI runs on #374/#377). The ordered-download tests already
set both ends; these now do too. The app uses one timing on both ends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): the C lane socket-buffer test accepts Linux's wmem_max cap

Same cap as the Rust lane test: Linux CI gives the send side 416 KiB, so the
1 MiB floor failed under ASan in CI. 128 KiB is still far above a default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(ci): gcc unused-result in the FTP selftest, serial ctest in make test, sender state on failure

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(ava1): flush a partial bundle after any reader message, not only a record

The last small-file record could arrive while a large file's chunk or root
was still queued behind it: the flush saw a non-empty channel, the next
message was not a record, and the records sat unsent until the receiver
cut the job as stalled (CI-only flake; 7/36 under local parallel load, 0/48 after).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(validate): run the C interop tests serially in make ci too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(ava1): a resumed file goes in one-group pieces so a flapping link still makes progress

With kills every 2 s, the 4 MiB tail piece was cut before it was durable on every
attempt and the upload retried the same 28 MiB mark until it timed out (1 in 3
locally, CI coverage). Resumed files now send 1 MiB pieces: 5/5 in ~6 s.

Also: make docker-engine uses the repo root as context (as CI); governor
classification asserts are skipped under the sanitizers, where the C is the bottleneck.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): single-instance gate tests hold the C-server lock; relay test cap leaves margin

Coverage runs the C tests in parallel; the two gate tests stop the one global C server.
The relay order test's 4 MiB/s cap finished in 5.9 s on CI against its >6 s precondition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): periodic-kill bound widened under coverage; tiny-file floor relaxed on CI runners

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): lane-kill test kills until a resend; periodic-kill liveness race skipped under coverage

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): a hung relay fails its test at the bound instead of hanging the CI job

The dest-ends relay test ran the relay under spawn_blocking: on a hang the timeout
panicked but the runtime then waited forever for the blocking thread (27 min on CI).
It now runs on a plain thread. The engine test steps get a 25-minute bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): dest-ends relay test in its own binary on small files; relay logs its silent retries

The test hung a CI job twice inside the shared relay binary (behind the 384 MiB relays'
lock) and never reproduced locally or in Linux Docker. It now runs alone, on 4x32 MiB
(still twice the relay buffer), ~3 s. The relay's open-dropped and retry paths now say
so on stderr instead of looping silently. Governor classification asserts also skip
under coverage, where the instrumented sender is the bottleneck.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): the partly-durable relay test caps its first attempt so it can be interrupted

On a fast runner the uncapped relay finished all 160 MiB before the first durable
report was observed. The first attempt now reads A through a 32 MiB/s proxy (~5 s);
the resume runs uncapped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* feat: one-time 6.0 upgrade clean-up that keeps every setting

Host (engine, once per data dir): pre-5.x files no 5.41/6.0 code reads (api_token,
ps5upload.ini, ps5upload_profiles.ini/.json, app-config.json) move to ~/.ps5upload/legacy-5x/.
App (desktop, once): the 1.x/2.x config.json/profiles.json move to legacy-5x/; the cached
ezremote-dpi.elf nothing loads is deleted. Client: the retired upload-streams key is dropped.
Console (once per console, on its first 6.0 helper answer): the FTX2 /data/ps5upload/tx and
/spool folders are deleted; a failure retries later. The health check no longer lists those
folders (its fix would have recreated them). Nothing current is moved or reset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): the download periodic-kill race is skipped under coverage, like its upload twin

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): the tiny-zip floor only catches a stall on CI runners

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(test): 'other calls still answer during launches' is a state check, not a wall-clock bound

Both mgmt_t6 tests asserted a sub-300 ms answer while a slow Sony call ran; on a loaded
runner that separates nothing. They now assert the answer arrived while the slow call
was still in flight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

* fix(ci): reword the 6.0 migration comments for check-no-ftx2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XR8fQMhp7Rdgq2e4U9oDff

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 07:04:11 -07:00
PhantomPtr 5954c8adde 6.0.0: AVA1 replaces FTX2 — one encrypted connection for everything (#374)
See CHANGELOG.md (6.0.0). Full history of the work: tag ftx2-last and branch history archived in ps5upload-docs.
2026-10-05 00:25:05 -07:00
phantomptrandClaude Opus 5.5 52caaa0d22 fix(android): no dead-code warning, an APK that installs, honest deploy result
- stream_metadata is only called from desktop-only code, so the Android
  build warned it was never used; it now carries the same cfg.
- Debug Android builds keep line tables only (CARGO_PROFILE_DEV_DEBUG in
  ANDROID_ENV, so the desktop dev build is untouched). The app library
  was 558 MB with full debug info, stored uncompressed, making a 1.1 GB
  APK that failed to install on an emulator with
  INSTALL_FAILED_INSUFFICIENT_STORAGE. Now 231 MB / 566 MB APK; verified
  installing and starting on emulator-5554.
- On INSUFFICIENT_STORAGE on an emulator, remove the old install and
  retry; on a real device, say to free space.
- android-deploy printed "✓ deployed" unconditionally, even right after a
  failed install. The install step now reports the real outcome.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:16:19 -07:00
PhantomPtrandClaude Opus 5.5 105e4aae96 chore(android): run-android reuses and foregrounds the emulator; software rendering by default (#339)
* chore(android): run-android foregrounds and reuses the emulator; faster emulator

- ensure reuses a running or still-booting emulator instead of booting a
  second; run-android brings its window to the front and reopens a headless
  one with a window; run-android-background leaves it headless.
- A stopped emulator is waited on until it has really exited (forced after
  60s), so a restart no longer mistakes it for one that is booting.
- Windowed emulators render on the host GPU instead of software, with 4 GB
  RAM and up to 6 cores.
- Android dev serves Vite on 1430/1431 (PS5UPLOAD_VITE_PORT), so it can run
  alongside desktop dev on 1420.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(android): software rendering by default; host GPU is opt-in

-gpu host froze the Android 16 image within minutes on an M1 Max (the
emulator warns its guest GL layer is unstable above API 35), with or
without Guest ANGLE. PS5UPLOAD_EMU_GPU=host opts back in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:31:42 -07:00
PhantomPtrandClaude Opus 5.5 e6e8601363 Files crash: reload on a missing screen chunk; make keeps node_modules; dev FAQ/changelog (#340)
* fix(app): a screen whose code is gone reloads the page instead of crashing

Screens load on demand; when a screen's file can't be fetched the
import rejects ('Importing a module script failed') and the route showed
the crash screen. That happens to a web UI tab left open across an
update (it asks for file names the new build doesn't have) and to a dev
server whose dependency cache was rebuilt under it. Reproduced by
swapping the served build under an open tab: main showed the crash
screen for Files; now the page reloads once and opens Files from the
new build. A second failure within 30 s shows the error, so an outage
can't reload forever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(make): don't reinstall client dependencies that already match the lockfile

setup-client ran npm ci on every make (run-client, run-android, emu-test,
dist-*). npm ci deletes node_modules first — Vite's dependency cache
with it — so a dev server already running lost its cache and its
screens failed ('Importing a module script failed' on Files). It now
reinstalls only when package-lock.json or Node changed since the last
install (a stamp in node_modules). Checked: a make during a running dev
server leaves it working; a stale stamp still reinstalls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(dev): the FAQ and What's New screens load on the dev server

They imported the repo-root FAQ.md and CHANGELOG.md with ?raw, and the
dev server served those (outside the client folder) as raw markdown
instead of modules. A small Vite plugin exposes them as virtual modules,
which go through the normal pipeline in dev and in builds (each is its
own on-demand chunk, locally and in the Docker web UI build). New e2e
test: both screens show their document.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): 5.37.2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:47:36 -07:00
PhantomPtrandClaude Opus 5.5 6f5abad2b5 elfldr that recovers by itself; 75-minute publish builds; 5.37.1 notes (#338)
* feat(elfldr): vendor elfldr with a read deadline, embedded in the engine

elfldr serves one connection at a time and its reads had no deadline,
so a client that went silent without closing (a dropped link, a machine
or console asleep mid-send) left it running but deaf on :9021 — users
had to load elfldr again. Measured on the Phat (FW 5.10): the stock
build answered nothing while a silent connection stayed open; with a
15 s SO_RCVTIMEO it dropped that connection and answered the next
request at once, and a payload sent with 10 s pauses still loaded.

third_party/elfldr is upstream 02cfe91 plus ps5upload.patch (GPLv3,
credited), with the tested ELF checked in so every engine build embeds
it; `make elfldr` rebuilds it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(elfldr): the engine swaps a console's stock elfldr for the patched one

GET /api/ps5/elfldr/health tells healthy / stuck / absent from a request
elfldr answers without running anything. POST /api/ps5/elfldr/ensure
replaces the standard elfldr.elf with the embedded patched build when it
answers and isn't the one this engine installed (a reboot or autoloader
brings the stock one back), leaves any other loader on :9021 alone, and
returns once the new one answers. On the Phat: upgraded (pid 685,
answering at once), then 'current'; the helper was untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(publish): give each client build 75 minutes

The Intel macOS build ran past the 45-minute limit for v5.37.0 (about
33 minutes for v5.35.0 and v5.36.0), which cancelled it and skipped
create-release, so v5.37.0 was never published.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(engine): history tests get their own temp dirs

TmpDir named directories by pid and nanoseconds, but macOS time ticks in
microseconds: two tests starting together shared a directory and one
deleted it under the other (a_legacy_host_port_file_is_still_read read
nothing). A counter makes each name unique. The elfldr embed test reads
the embedded bytes directly instead of clearing an env var mid-run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(elfldr): the app keeps the patched elfldr in place and never sends into a stuck one

Before sending the helper, the app checks the console's loader: a stuck
one (took the connection, never answered) is waited out for 20 s — the
patched build clears in 15 — and one that stays stuck is reported
plainly ('load elfldr again') instead of a socket error. Once the helper
is up, the engine swaps the stock elfldr for the patched build: at once
after a fresh helper send (a reboot or wake brings the stock one back),
else at most every 10 minutes per console. Desktop, browser and Android
share the engine routes; strings in all 20 languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): 5.37.1 — elfldr recovers by itself; 5.37.0 folded in

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(elfldr): swap it in when the helper is already up at launch

Only ensurePayloadCurrent asked for the patched elfldr, and a helper
that is already up when the app opens never goes through it — on the
Phat the stock elfldr stayed. The status poll's 'arrives at up' edge
(first sighting included) now asks too, after the same settle as the
log capture and never during a transfer.

Hardware (Phat FW 5.10, web build and Android app): stock elfldr
replaced ~10 s after opening; a silent :9021 connection held while the
helper was shut down — the helper came back through the patched
elfldr; with the stock elfldr wedged, the Android app sent nothing for
150 s (health: stuck), then redeployed and swapped elfldr once released.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(convert): the compress stage pays for reading and writing on one thread

kraken_image::compress runs the encoder on a pool, but one thread reads
the source and writes each compressed block, so the stage takes the
longer of encoding and read+write — not the slower of reading and
encoding, as the estimate assumed. With the Windows Battlefield 6 run's
speeds the model now gives 75 min for a 71-min build.

The estimate also reports the speeds it measured (rates), because the
small read/write samples can be fooled by caches: on a source read an
hour earlier the read sample hit the file cache at 8.6 GB/s and the
estimate came out at 25 min for a 54-min build. Calibrating from past
builds is the follow-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): build-time estimate, stated as measured

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(docker): 25 minutes for the PR image checks

Both PR gates build the whole image (engine, and the client for the web
UI one) in about 7-10 minutes; the engine gate took 9m55s and the web UI
gate was cancelled at its 10-minute limit on PR #338.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:55:05 -07:00
phantomptrandClaude Opus 5.5 0b6901fa53 fix(payload): a resumed single-file upload writes where the acknowledged bytes end
A fresh single-file upload pre-sizes its .ps5up2-tmp to the full transfer
(posix_fallocate); a resume reopened it with O_APPEND, so the resumed
shards were written past the pre-sized end. A 1 GiB upload that dropped
and resumed grew to 1 GiB + the unsent remainder and COMMIT refused it
with size_mismatch (seen on the Android emulator).

Resume now opens without appending and seeks to entry->bytes_received
(the journal's acknowledged byte count). direct_open.h is header-only so
the new host self-test drives the same code on a real file.

Hardware (Phat 5.10): 1 GiB upload, engine killed at ~300 MB, resumed
with the same tx id — before: size_mismatch at 1,879,048,192 bytes;
after: committed at 1,073,741,824, SHA-256 identical to the source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 00:11:20 -07:00
PhantomPtrandClaude Opus 5.5 c7bb83d04d chore(scripts): rewrite release posts, drop outdated scripts; README highlights (#334)
release-posts.js
- Reads whole changelog groups (bold heading + wrapped bullets), not just
  the first line of each bullet.
- X: link counted as 23 chars, replies packed to fit 280, markdown stripped.
- Discord: full bullets when they fit 2000 chars, short ones otherwise;
  Reddit: real markdown sections instead of a code block.
- Says "pre-release" when GitHub does (gh), --prerelease/--stable to
  override; --only and --out to pick a platform and write files.
- make release-post calls it directly; the .sh wrapper is gone.

Removed (outdated)
- ps5-install-trace.py, ps5-install-watch.py, fpkg-mount-test.py: drove
  /api/pkg/install/start and the dpi-* routes, which no longer exist.
- gather-fakelibs.py: superseded by the app's Backport scan.
- pull_ps5_debug.py: pulled a debug dir the helper no longer writes to.

hw-test-loop.sh ran cargo from the repo root (no workspace there); it now
points at engine/Cargo.toml.

README: a Highlights section up top (unified install, Convert to FPKG,
sleep and wake), Android/web in the platforms badge, tested firmware 5.10 &
9.60.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 06:10:10 -07:00
phantomptrandClaude Opus 5.5 c14782944d PS5Upload v5.35.0
Upload, install, convert and manage PS5 game packages over the network.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 04:31:13 -07:00