214997144f58bd52d8481ad68b907ba8c8984601
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
214997144f |
feat(deps): upgrade Tauri to 2.11.5, and own the Android context it stopped setting
🏗️ Build and Test JellyTau / Run Tests (pull_request) Successful in 22m51s
🏗️ Build and Test JellyTau / Supply Chain (pull_request) Failing after 25s
Traceability Validation / Check Requirement Traces (pull_request) Successful in 14s
🏗️ Build and Test JellyTau / Android Compile Check (pull_request) Successful in 4m19s
The plugin versions could not be matched upward without this: both
tauri-plugin-log 2.9.0 and tauri-plugin-updater 2.10.1 require tauri
^2.10, and the tree was on 2.9.5. So the framework moves with them --
tauri 2.9.5 -> 2.11.5, tauri-build 2.5.3 -> 2.6.3, wry 0.53.5 -> 0.55.1
-- and every plugin's Rust crate and npm package is now pinned to the
same version on both sides.
That upgrade broke Android outright, and the breakage is the interesting
part.
Seven call sites in this crate reach JNI through
ndk_context::android_context(), which reads a process-global pair of
pointers. Nothing here ever set that global. `tao` did -- the windowing
layer under wry, three levels below anything this project names in
Cargo.toml. tao 0.34.5 called initialize_android_context() while starting
the activity and our code read what it left behind. tao 0.35.3 keeps the
same two pointers in a private struct and no longer publishes them.
The result, on every launch, was:
PANIC at ndk-context/src/lib.rs:72: android context was not initialized
8: ndk_context::android_context
9: jellytau_lib::run::{{closure}}
Not a crash in our code, and not a change to our code: an undocumented
side effect of a transitive dependency disappeared. Relying on someone
else to populate a global is a dependency that does not appear in
Cargo.toml and gives no warning when it goes.
src-tauri/src/android_context.rs now owns that invariant instead of
assuming it. JNI_OnLoad captures the JavaVM as the shared library loads
-- the earliest moment available, and nothing in tao, wry or tauri
defines one to collide with. The Context is resolved lazily via
ActivityThread.currentApplication() and pinned as a global reference for
the process lifetime, since ndk_context stores a bare pointer and does
not own it. It publishes the Application rather than the Activity:
SecureStorage.initialize() immediately reduces its argument to
applicationContext anyway, and an Application cannot outlive itself the
way a retained Activity would.
Restoring the global keeps all seven callers untouched. Threading a VM
and Context handle through five credential call sites would have been a
larger change with more risk, on the credential path.
Failure now degrades instead of aborting: it is logged and credentials
fall back to the encrypted-file path, which the app already supports.
Verified on a device, R8-minified, not merely compiled:
[INIT] Android JavaVM and Application published to ndk_context
Android SecureStorage initialized successfully
Android Keystore available via SecureStorage
[INIT] Using system keyring for credential storage
[CodecDetection] Detected 7 video codecs: av1,h263,h264,hevc,...
-- the real keystore path, not the fallback, and the app stays up. None
of this is reachable by CI: nothing there runs the app.
Also fixed here, both found the same way:
- `tauri android build --apk true` is now `--apk`. The CLI took a value
until 2.10; from 2.11 the stray `true` is a positional and the build
fails before starting. Three call sites in build-android.sh and one
in build-release.yml -- the latter builds the signed APK, by far the
most-downloaded artifact.
- scripts/build-android.sh ran `npm install` on its clean-build path in
a bun project, ignoring bun.lock and re-resolving the tree. That is
exactly how the plugin crate/package versions drift apart again.
scripts/check-tooling.sh now fails on any npm/yarn/pnpm invocation or
foreign lockfile, and runs in CI.
DR-222, DR-223.
|
||
|
|
9a19d30e6c |
fix(build): make the release actually buildable, and check it before tagging
🏗️ Build and Test JellyTau / Run Tests (pull_request) Successful in 18m41s
🏗️ Build and Test JellyTau / Supply Chain (pull_request) Successful in 31s
Traceability Validation / Check Requirement Traces (pull_request) Successful in 9s
🏗️ Build and Test JellyTau / Android Compile Check (pull_request) Successful in 4m5s
Preparing v0.10.0 meant building the release locally first. It did not build. Two separate defects were sitting on master, both invisible to every gate this project has, for the same reason: nothing in build-and-test.yml runs `tauri build`. Only a tag does. So the first time anyone would have discovered either was a failed release. **Tauri plugin versions had drifted apart.** Tauri refuses to build when a plugin's Rust crate and npm package are on different minor versions: tauri-plugin-log (v2.8.0) : @tauri-apps/plugin-log (v2.9.0) tauri-plugin-updater (v2.9.0) : @tauri-apps/plugin-updater (v2.10.1) Introduced by the updater and diagnostics work in this same branch -- `cargo add` took what the pinned toolchain allowed while `bun add` took latest, and the caret ranges let them separate. cargo check, clippy, cargo test and svelte-check all passed. Matching upward pulled wry 0.53.5 -> 0.54.2 along with wasm-bindgen, web-sys and webkit2gtk: the webview layer, which on Linux is the video playback path. That is not a change to make while cutting a release, so the npm packages are pinned down to the crates instead -- exactly, not by caret, since the caret is what allowed the drift. The upgrade is worth doing deliberately, with a playback check, and ci-operations.md says so. CI now runs `tauri info`, which performs the same comparison without building. Verified by reintroducing the mismatch and watching it fail. **The AppImage target had never been built.** It was added earlier in this branch because the release notes had advertised an AppImage for months while tauri.conf.json never produced one. It does not work out of the box: linuxdeploy carries its own `strip`, too old to parse the .relr.dyn section modern toolchains emit, and it fails on every bundled library -- strip: libzstd.so.1: unknown type [0x13] section `.relr.dyn' failed to bundle project `failed to run linuxdeploy` Ubuntu 23.10+ links with -z pack-relative-relocs by default, so the CI builder image fails exactly as a modern Arch host does. NO_STRIP=true is linuxdeploy's documented escape hatch. The resulting 153 MB AppImage was verified to be well-formed and to actually start. Without this the release would have failed at the Linux build step -- the artifact check added earlier refuses to publish when no AppImage is produced, which is the behaviour we want, but it would have refused a tagged build rather than a local one. Also: the traceability extractor now reads the tooling shell scripts that carry TRACES comments. DR-207, DR-213 and DR-220 all had them and were counted as uncovered because only .ts/.svelte/.rs were scanned. Listed individually rather than globbing scripts/*.sh -- most implement nothing, and adding one should be a decision. DR-221. |
||
|
|
5d02628689 |
fix(release): publish real notes, and stop shipping old releases' installers
🏗️ Build and Test JellyTau / Run Tests (pull_request) Successful in 15m1s
🏗️ Build and Test JellyTau / Supply Chain (pull_request) Successful in 42s
Traceability Validation / Check Requirement Traces (pull_request) Successful in 10s
🏗️ Build and Test JellyTau / Android Compile Check (pull_request) Successful in 4m6s
Two defects found while preparing v0.9.2, both of which had been shipping for months without anything to notice them by. **Every release note was the same 1,050 bytes.** All 35 releases from v0.0.1 to v0.9.1 published identical generic install instructions whose "What's New" section read "See CHANGELOG.md" -- a link that does not resolve from a release page. A reader learned nothing about what changed in any release the project has ever made. The body now comes from the `## <version>` section of CHANGELOG.md, and a missing section fails the release: notes that say nothing are worse than a build that waits for a maintainer to write two sentences. The 35 published bodies have been backfilled from the changelog via the tea CLI. This also corrects something introduced two commits ago. That change generated the body from `bun run release:notes`, which CLAUDE.md is explicit about -- its output is "a reviewed draft, not a final changelog". Publishing it unreviewed proved the point immediately: the v0.9.1..HEAD range contains a repo-wide prettier sweep, so every file in src/ counted as changed, their TRACES resolved to nearly the whole matrix, and the draft claimed the release had added the entire application. The script now skips cosmetic commits (chore(format), chore(deps), style) and reports how many rather than silently returning a smaller set, but it stays a local drafting tool. **Every release from v0.1.0 to v0.8.2 shipped every Windows installer ever built.** src-tauri/target/*/release/bundle/ is not versioned, cargo never cleans it, and the runner reuses the target directory -- so the copy step's bundle/**/*-setup.exe glob collected the lot. v0.8.2 carried sixteen installers, thirteen of them stale; v0.5.0 offered users a download list going back to 0.1.0. Eight months, and nothing to notice it by: the upload loop reported success, the files were real, and the page looked busy rather than wrong. It stopped only because an unrelated cargo cache change wiped the runner's target dir, so it was dormant, not fixed. Both desktop builds now remove the bundle directory before building, so a stale file cannot exist to be copied. Filtering the copy by version would have hidden it instead. The Linux job gets the same treatment: it was never hit only because Linux packaging is newer, and the glob is identical. scripts/check-release-artifacts.sh is the backstop for whatever reintroduces one by a route nobody predicted. It runs before the SBOM, the checksums and the upload -- all of which describe the file set, so a stale artifact has to be caught before it is hashed and published as part of the release. Verified against a reconstruction of the real v0.8.2 accumulation. DR-219, DR-220, UT-210. |
||
|
|
1d56517f07 |
docs(specs): add backend-owned stream selection
Traceability Validation / Check Requirement Traces (pull_request) Successful in 11s
Rust becomes the single owner of which stream to play — direct play or
transcode, at what ceiling, over what transport — and hands every player
backend a self-describing StreamSelection instead of a bare URL. mpv,
ExoPlayer and the HTML5/hls.js path all consume one decision rather than
three places re-deriving it.
The motivating leak is concrete. VideoPlayer.svelte determines transport with
`currentStreamUrl.includes(".m3u8")`, in two places, for a URL Rust
constructed and therefore already knows the shape of. That is the boundary
rule in miniature: not item-type taxonomy, but the same error of
reconstructing a domain fact in the presentation layer because the wire shape
did not carry it. A tagged Transport enum deletes it.
The design line, which ExoPlayer forces: Rust decides *what stream*, the
player decides *how to deliver it*. ExoPlayer has genuine adaptive track
selection; this spec must not reimplement or fight it. Rust only adapts where
the player cannot (mpv) and the server actually offers a ladder.
Six phases, and phase 1 stands alone as pure ownership movement with no
behaviour change. Phase 4 (direct-play negotiation) is what removes the
transcode and unblocks the Linux native-video work. Phase 5 (adaptation) is
gated on counting EXT-X-STREAM-INF entries in a real playlist — the
acceptance criteria require that count be recorded before it is either
started or dropped.
Takes DR-121 from read-through-media-cache.md, which specced Rust-owned
quality reporting but never built it; that spec keeps its capture half.
|
||
|
|
f11f5eddd5 |
docs(specs): record the Linux native-video compositing spike
🏗️ Build and Test JellyTau / Run Tests (pull_request) Successful in 15m3s
🏗️ Build and Test JellyTau / Supply Chain (pull_request) Successful in 38s
Traceability Validation / Check Requirement Traces (pull_request) Successful in 20s
🏗️ Build and Test JellyTau / Android Compile Check (pull_request) Successful in 4m11s
Adds the spike write-up and re-opens finding 2 of playback-backend-unification.md, which concluded that video cannot unify on a native engine because the webview owns the surface. That finding's general form has since been falsified on Android, where native video composites behind a transparent WebView and ships on by default. The evidence behind it was also entirely about foreign-window embedding -- mpv's render API, drawing into a GL context we own inside Tauri's own GTK tree, was never tested. The spike tests that one claim and comes back green on Linux for both X11 and Wayland, bar the Tauri default_vbox() half of G1. Findings 3-6 are deliberately left standing. Finding 3 in particular -- mpv has no adaptive bitrate -- is an independent disqualifier that a green compositing result does not clear, and the spike says so rather than reading as a green light. The next-free-id line moves to UR-079 / IR-033 / DR-219: this branch allocated UR-077 and UR-078 for the updater and diagnostics work, and DR-215 through DR-218 with them, after that line was last written. Authored in a parallel session working in the same checkout; committed here so it travels with the rest of the branch. |
||
|
|
32043a2152 |
docs: fold shipped specs into the architecture docs and delete them
A spec was a promise; sixteen of them had become descriptions of code that already shipped, sitting beside four that describe work still outstanding, with nothing in the file telling the two apart. Half the statuses were also wrong — audio-equalizer read "Accepted" with the EQ live on both platforms, the native video spec said the flag stays off after the default was flipped on. The shipped designs move into docs/architecture, which is the maintained description of the build, and the spec files go. Git history keeps the originals; what a future change still needs is carried across: - 01-rust-backend: favourites rewritten (the old section named a file that no longer exists and called shipped buttons "planned"), domain vocabulary owned by Rust (SearchScope, exclusions, the bitrate ladder), background workers - 02-svelte-frontend: app shell and chrome, library mosaic, series/episode navigation, downloaded browse, safe-area insets, native-video store, logging - 03-data-flow: locally-indexed search - 05-platform-backends: audio settings on ExoPlayer, the equalizer's band vocabulary, native video compositing, the background-audio handoff - 06-downloads-and-offline: one storage model, offline catalog visibility - 09-security: path confinement and input binding docs/specs/README.md now says what the directory is for and where each shipped design went. Deferred work the specs recorded is kept beside the code it concerns rather than lost: season-bounded autoplay, the two dead search commands, why indexing is a full crawl. requirements.md had fourteen stale statuses — Android audio parity still read "Linux only", DR-150 still said the native-video default was off, DR-190 was Proposed after DR-196 implemented it, and five tooling requirements were Proposed after landing. Three unbuilt specs suggested requirement ids that have since been allocated to other work; each now carries a warning. |