bcf3856b6f9bcd89bbbc892dc562b43bb6ed5485
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
37e3373db9 |
docs: correct the workflow counts these comments name
Adding release.yml and desktop-assets.yml made 'the three workflows a tag fires' wrong in three files that each said it slightly differently. |
||
|
|
369810e06b |
ci: stop testing every commit twice on a runner there is one of
A branch push and its pull request are the same commit. With `branches: ['**']` alongside `pull_request:`, opening a PR booked four runs -- check and e2e for the branch, then both again for refs/pull/N/head -- and this host has capacity 1, shared with an index build that can hold it for three hours. PR #1's own checks queued two runs deep behind exactly that. `pull_request` covers feature branches. `main` stays because a post-merge run is the record of the trunk's health, and now that main refuses direct pushes it happens exactly once per merge. The trade is that a branch pushed with no PR open gets no CI. That matches the workflow this repo just committed to, and the signal returns on the same commit the moment a PR exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AfVYUVExXsx1nSWrXN8mAh |
||
|
|
1128881e8d |
docs(wails): move the prose onto v3 and record Phase 7
CLAUDE.md gains a Packaging section for the four Taskfile facts the recipes just needed — wails3 on PATH by bare name, no -ldflags on `wails3 build`, bin/ not build/bin/, and bundling as its own step — plus how build/'s platform metadata generates from build/config.yml and what that refresh overwrites. Its lifecycle, bindings, harness, events and CI sections were still describing v2. The events one matters most: the rule to emit through events.Emit survives, but its justification is now the weaker one, and saying so is the point of the migration. v2's runtime.EventsEmit log.Fatalf'd on any context not carrying the runtime; v3's emit takes no context at all, so what is left to pin is that one emit path is what lets emitStatus drop an unchanged payload for every caller at once. README told a contributor to `go install wails/v2/cmd/wails` and apt-get libgtk-3-dev/libwebkit2gtk-4.1-dev; the CLI is vendored and the stack is GTK4 + WebKitGTK 6.0. Two comments claiming Xvfb and one claiming frontend/wailsjs go with them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDCbcCZQepnpSQYJ6SxxZm |
||
|
|
deb3f3da7e |
feat(wails): move the e2e harness and headless launch onto v3
make e2e is green on chromium: 92 passed. The harness is rebuilt on
what v3 actually offers, and three of the four things it replaced turn
out to be better than what they replaced.
The headless launch is v3's own server mode. scripts/dev-headless.sh
ran a `-tags dev` binary whose app_dev.go parsed -devserver/-assetdir
out of os.Args; that file went with v2, so the harness had no server at
all. `-tags dev,server` is a first-class mode and needs no display, so
Xvfb is gone from the script and from CI.
The bridge hooks two places, neither of them EventsOn. Inbound is
window._wails.dispatchWailsEvent, wrapped by pre-creating the object
the runtime keeps and putting an accessor on the one property.
Outbound is fetch: v3 routes every runtime call through one POST, so
the bridge sees binding calls and event emits from any module, needs no
walk of an object graph, and cannot miss a call made before it looked.
__yjEvents.call posts to that endpoint by method name, so it depends on
nothing in the app's bundle and works on a page with no init script.
That is what lets seed-sandbox.sh drop playwright-cli entirely — it
drove AddLibrary through a browser only because window.go was v2's one
way in — and with it a global npm install and a second Chromium in CI.
measure.mjs and one spec lose their window.go walks and read the
bridge's log instead; e2e/support/method-ids.mjs derives id -> name
from frontend/bindings/ (phase 6b option 1, so it cannot go stale
silently). Plain .mjs because measure.mjs runs under bare node and one
derivation beats two that can disagree.
Four bugs surfaced, and the migration is how.
The cross-service wiring never ran headless. It hung off
Common.ApplicationStarted, which server mode never emits —
setupCommonEvents is an explicit no-op there — so the queue had no
TrackLoader and playing a track changed the queue and then silently did
nothing. It is a service registered last now (backend/startup.go):
services start in registration order, which is the ordering the wiring
needs, in every mode.
Six specs called SetQueue with 3 of its 4 arguments. v2 accepted that
and filled the gap; v3 answers "expects 4 arguments, got 3".
requested-badge's cleanup read window.go and returned early on
`if (!svc)` — the silent cleanup its own comment was written to
prevent, one migration later. It posts to the runtime endpoint now,
which any page can do.
SearchIndex.Search trusted a startup latch, so rows a spec staged
afterwards were unsearchable and three specs passed only when an
earlier one happened to flip it. shelves.go fixed exactly this and left
hasCatalogRows behind; the search path now uses it as the fallback,
with the latch still the fast path.
Two spec edits are deletions of assertions about v2. harness.spec
checked Object.keys(window.go) and that a bad call *hung*; it now
checks the real runtime is loaded and that the backend rejects with a
TypeError naming the argument. album-actions asserted a tracklist
legend that
|
||
|
|
4471db3aef |
feat(wails): move the Go side to v3
Phases 2 and 3 of plan 009, plus the parts of phase 1 that could not
land before them. Nothing in the tree imports wails/v2 any more; all
three lint and test configurations are green and `go build .` produces
a running binary.
The point of the migration is one file. backend/events/emit.go probed
ctx.Value("events") — a v2-*private* context key — to decide whether
emitting was safe, because runtime.EventsEmit called log.Fatalf on a
context without the runtime and took the process down with it. v3's
emit takes no context, so that is now application.Get() == nil. D1
held: events.Emit keeps its ctx as the WithSink test seam, and all 45
call sites and 7 test files are untouched.
The bootstrap splits into application.New + Window.NewWithOptions +
Run. Ten bound services implement ServiceStartup instead of being
handed a context by hand from OnStartup, which also stops ten
SetContext methods being exported as bindings. jobs.Registry and
explore.SearchIndex keep theirs — neither is bound, so converting them
would be churn for no binding removed.
Four things differed from the plan and are written up in it: GPU policy
moved to the per-window LinuxWindow options rather than surviving on
LinuxOptions; there is no OnStartup/OnDomReady option, so app-level
wiring hangs off ApplicationStarted; application.NewService is generic,
so FEBindings []any could not survive (the binding generator is a
static analyser and would have seen nothing); and the quit veto had to
be restructured, because v3's dialog answers on a callback rather than
returning the button, so ShouldQuit vetoes, asks, and quits again from
the callback.
Window state saving moves to a WindowClosing hook — the size has to be
read while the window still exists, and v3's OnShutdown has neither
context nor window. backend/logging is deleted rather than ported:
v3 takes a *slog.Logger directly, so the v2 logger.Logger adapter had
no caller left.
Phase 1's tail rides along, now that it can: the Makefile's wails
invocations, all 50 webkit2_41 sites, lefthook, both packaging recipes
and ci.yml's apt lists. v3 builds against GTK4 + WebKitGTK 6.0, which
Arch and ubuntu:24.04 both ship, so the tag is a deletion rather than
a translation.
Phase 4 is next and the branch is not usable until it lands: the app
builds, but frontend/wailsjs/ is v2's tree and nothing regenerates it,
so the frontend cannot reach the backend yet.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDCbcCZQepnpSQYJ6SxxZm
|
||
|
|
0b7ffd5679 |
build: check that css template literals were not ended by a comment
A backtick inside a comment in a css`` literal ends the literal. It has cost four sessions across three plans, it is written down in CLAUDE.md, the skill and NOTES.md, and it was read twice in the session it then cost a cycle in. Knowledge that has been ignored three times is not a knowledge problem. The expense is the report, not the mistake: the literal ends early, the rest of the CSS parses as JavaScript, and tsc says 'Class static side incorrectly extends base class static side' pointing at a line of prose -- or, in a shared module, every test in the suite fails to import and the output reads like a broken test runner. make dev-headless mean- while keeps serving the last good bundle. Detection is exact rather than heuristic: if a backtick in a comment closed the literal early, the text the parser took as the literal contains an unterminated /*. Nothing else produces that. Verified both ways -- clean on the tree, and red on a deliberately broken comment. |
||
|
|
0a25bca128 |
ci(e2e): give the container an audio device that keeps time
The e2e job's red history is one measurement being wrong. ALSA's `null` plugin does not pace: measured in this exact image through beep and oto with the same speaker.Init arguments player.InitSpeaker uses, 3000 ms of audio is consumed in 2.96 ms — a thousand times too fast. So every track finished instantly, the position reset to zero, and three specs failed on a clock that never moved. It read as a flake because InitSpeaker succeeds either way, in ~3 ms either way. A PulseAudio null sink is timer-scheduled: the same 3000 ms takes 3762 ms, and 12 s takes 13.5 s — the overhead is a constant buffer drain, not a rate error. Verified under the private session bus and Xvfb dev-headless.sh runs the app in, with no system D-Bus and no kernel module, which is what makes it reachable from a container. The sink is a dependency with a rate, so it is now checked like one: a step plays three seconds and fails if they take under two. Without it the failure surfaces three steps later as "the elapsed clock is 19 s adrift", which reads as an app bug and cost two sessions of exactly that suspicion. |
||
|
|
5111a6c8ab |
ci(e2e): run the WebKit project even when chromium fails
The WebKit step had no `if:`, so a chromium failure skipped it — and chromium has been failing on the container's audio clock for every push of the last two sessions. The job log says `conclusion: skipped`, so the one place WebKit2GTK gets any coverage has produced no signal at all while the plan recorded a possible WebKit regression as unverified. |
||
|
|
9f03b3ff94 |
ci: enforce the commit format CLAUDE.md said was enforced
CLAUDE.md has claimed since the file was written that commitlint gates the commit format in CI and that semantic-release runs off it. There was no commitlint config, no workflow running one, and nothing invoking .releaserc.yml — so the first thing every contributor and every agent reads about this repo was false in two places. scripts/commit-check.sh is the smaller honest answer: the grammar is one regex, and commitlint would mean a Node dependency tree at the root of a Go repo to run it. It is a commit-msg hook locally and a CI step over every commit in a push, and its type list is .releaserc.yml's so the check and the release rules cannot drift. The semantic-release half is recorded as configured-but-not-wired rather than implied to run. |
||
|
|
ccacd67a21 |
fix(ci): build the frontend before any Go typecheck
main.go embeds frontend/dist, so lint, test and bindings-check all fail on a fresh clone until pnpm build has run. Invisible locally because anyone who has started the app has a dist/ lying around, and the container prototype missed it because both job scripts shared one mounted directory, so job 1 consumed a dist/ that job 2's dev-headless had built on an earlier run. |
||
|
|
5ca6cad45a |
feat(harness): agent-drivable dev harness and CI that gates
A coding agent could develop this repo's Go packages and could not develop the application: every path to running YellowJacket ended in a blocking GTK window, so 265 bound methods, 46 events, 33 component directories and 13 stores had exactly one form of verification available — `tsc --noEmit`. The unlock is that `wails dev`'s dev server on :34115 serves the real frontend with the real generated bindings against the same Go backend a desktop window attaches to, so a plain Chromium under Xvfb gets a fully functional app. Four test tiers now exist, cheapest first: - `make ui-test` — 313 Vitest tests in a real browser in ~2 s, no app, no backend, no display. Works because `frontend/wailsjs/` is a pure passthrough to `window.go`/`window.runtime`, so faking just those two globals runs the real bindings and the real store code. - `make test` — services in-process, asserting on the payload the frontend would receive, via a new `events.Emit` wrapper. - `make dev-headless` + `playwright-cli` — the real app, driven interactively, with an event bridge on `window.__yjEvents` and a dev-only control surface at `/__test/`. - `make e2e` — 19 of those flows frozen as Playwright specs. `events.Emit(ctx, …)` replaces all 35 direct `runtime.EventsEmit` call sites: wails' `getEvents` `log.Fatalf`s on any context without its runtime, so those paths could not run under test and a background worker could take the app down. Four packages had each hand-rolled the same guard; nine more guarded on `ctx != nil`, which does not help. `TestNoDirectRuntimeEmits` fails the build on a new one. Fixtures are generated, not committed (`make testdata`), and seeds are built by *running the app* — never by hand-writing config and DB rows, which would be a second description of a valid YJ_HOME. `.gitea/workflows/ci.yml` is the first workflow here that tests anything; the other three only package, so `gitea_ci` reported only packaging jobs and misled anyone asking whether a push was healthy. Both jobs were prototyped to green in a bare ubuntu:24.04 container before the YAML was written, which immediately caught `make lint` linting three configurations that nothing builds: all three passes omitted `webkit2_41`, so wails resolved webkit2gtk-4.0 — which Arch still ships and Ubuntu 24.04 dropped. Operational instructions live in `.pi/skills/yellowjacket-dev/`, measured discoveries in `.planning/NOTES.md`, and architecture in `CLAUDE.md` — split by tense, not by topic, because a topical split gives every new fact two plausible homes. `make skill-check` fails a commit if the skill cites a make target that does not exist. |