325 Commits
Author SHA1 Message Date
NotAlexNoyleandClaude Fable 5.1 e3e3a68cb3 T-505 item 3: the owner's defaults by performance — the parts by part on, the express second frame off; item 4's start
The owner (2026-11-03, "choose based on performance"): the parts by part ON by default (desktop Wikipedia 11.4
against 10.8 fps by finger, the long page 19.4 against 19.2; JIHAD_GPU_PARTS_PER=0 or <state>/no-parts-per turns
it off), the express lane's second frame on the first in flight OFF (11.4 against 11.4, 18.1 against 19.4;
JIHAD_GPU_EXPRESS_SECOND_PARTS=1 turns it on), and item 4 next over the damaged-rows read. The daemon rebuilt
and pushed to the three variants (ba9bd159), default-check x3 passes; the desktop daemon tests pass.

PICKUP carries item 4's starting design: the tiles' CPU pixels reachable on the compositor side, the band
condition "tiled painted or colour layers only" rather than "scroll only", and the scale at Wikipedia's fit
zoom (0.69 with the tiles at resolution 1) as the owner's decision before the build.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 13:00:06 -05:00
NotAlexNoyleandClaude Fable 5.1 d331e4ed29 T-505 item 3: the parts' pictures by part (engine 0073), the express second frame back; item 4 next
The owner's "cheaper part pictures" (2026-11-03). Engine 0073: each rect of a frame's parts list carries a
signature of its own (its outermost fixed or sticky layer's subtree, every subtree layer's last paint as the
stamp of one up-only counter, the part's scale, quarter-pixel phase, place inside its rect and size);
compose_post3/start3 (overview_ok 4) take the signatures the daemon holds and the pass reads only the rects
not in the list; the poll's 54 ints carry each rect's signature and the rects read. The daemon keeps eight
part pictures by signature and, with JIHAD_GPU_PARTS_PER=1 (or <state>/parts-per), sends the list; without
it E2's rule. The express lane's second frame on the first in flight is back when both are without their
parts (JIHAD_GPU_EXPRESS_SECOND_PARTS=1 or <state>/express-second-parts): its dress puts back what lay
beneath the first's parts and beneath the first's base's parts from the slot records (serials, the rows
read, a slot's previous record kept aside), never on a first that is itself two deep. JIHAD_GPU_VERIFY=1
now verifies the express lane's frames (the reference composed before the job; verifyCompare shared with the
main lane) and JIHAD_GPU_TEST_DRESS_HOLD=<pre|mid>:<ms> holds a first frame's dress so the second's copy
catches it. Both switches off by default: the defaults are the owner's call.

By finger: desktop Wikipedia 10.8 -> 11.4 fps flowing (its contents panel, the part that changes, is 310 of
the 340 KB: the lever is bounded by the changing part's size), the long page 19.2 / 19.4 / 18.1. Verify after
the pan mark: 0 wrong rows in every run on both pages, 142 two-deep frames among them, 55-80 of those with
the first's dress held (docs/rounds/t505-2026-11-03/notes.txt).

The inspector's review (Codex out of credits): REVISE, seven findings, all fixed (impl-review-findings-t505-
cpuparts.md, review 3). The verify then exposed a latent main-lane fault from review 2's F4 (2026-11-02): a
second job whose in-flight base the parts rule refused built on the newest finished frame but told the engine
it was the previous composite, so the frame was recorded 316 rows off and the next own-slot frames copied
wrong rows; fixed (srcInFlight in gpuJobStart; 0 wrong in three runs after).

Also: build/desktop/build-goanna.sh takes a jobs argument like the ARM script (the host short of memory);
tools/device/t502/README.md documents the switches; the kit's R4 criterion, the build site's T-505 row and
PICKUP's top section carry the state; the three variants run this head (default-check x3 passes).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 12:47:59 -05:00
NotAlexNoyle ffd6aae246 Update canonical Gitea links 2026-11-03 10:47:00 -05:00
NotAlexNoyleandClaude Fable 5.1 62af6e82c7 The engine on UXP RB_20261027 (T-551..T-554): the queue rebased, 0060 dropped, every pin, the device checked
The owner's choice of 2026-11-02 after T-551's check found the tag: the update now, patch 0060 (the
roots, byte-identical upstream) dropped, special attention to the certificate and HTTPS changes.
- update-engine.sh RB_20261027 / --finish: the 72 patches on the tag (0060 fell away as already
  applied), jihad/uxp-RB_20261027 at 52ad9ab66e in third_party/uxp, the queue rewritten and
  renumbered from 0060, the pins (engine-version.env, the OE recipe, .gitmodules, the UA and the
  three start pages: UXP/6b18be9), JIHAD_APP_BUILD_ID 20261103000000; patch-queue.sh --check,
  check-engine-pins.sh and check-engine-api.py (baseline rewritten, unchanged) agree.
- docs/ENGINE-SOURCE.md: the base, the dropped 0060, the renumbering, and the range's 12 commits
  each with its disposition — the two NSS certificate commits (emSign removed after the eMudhra
  compromise; certdata to Sept 2026) were on the device since the roots of 2026-10-25 and are the
  base's now; no PSM, TLS protocol, HSTS or certificate-UI change in the range; the memory-safety
  fixes (the JS OOB array copy, the jar: flag, feTile, the layout frame table, the mutation
  observer's strong ref, SQLite 3.54.1) taken with the base.
- audit-roots.py against the fetched release certdata and the CCADB report: identical set and
  trust, none removed, RESULT OK (docs/rounds/certs-2026-11-03).
- Desktop: the full build clean; 14 of 18 tests pass, the four left are the desktop GTK path's
  known read-back limit. ARM: libxul, the daemon, the bundle, the three packages; full pushes to
  all three variants; default-check x3 faults 0; the daemon's start line 28 of 29 optional
  exports as before. The areas the commits touch, on the device (tools/device/engine-checks.sh,
  new): about:settings, about:personas and about:addons through jar: under the flag change,
  cookies through the new SQLite, an SVG filter page with feTile and its overflow case
  (render/goanna/test/jihad-svg-filter.html, new), a long press's selection; faults 0.
  The certificate kit's checks (tools/device/cert-checks.sh): the TLS 1.0 refusal, the clean loads,
  expired / wrong.host / self-signed / untrusted-root with the SSL confirm's right flags, OCSP
  revocation enforced on grc.com, ssl.com and DigiCert's demos, revoked.badssl.com's CRL-only case
  invisible as before: nothing changed with the base.
  Records: docs/rounds/engine-rb27-2026-11-03/notes.txt.
- tools/device/cert-checks.sh and t502/enyo-restore-job.sh (new): the certificate kit's device
  checks under a hand-started daemon, and the Enyo job put back after any spike round.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 10:25:46 -05:00
NotAlexNoyleandClaude Fable 5.1 c29f396c21 T-505: the long page's wrong verify frame found and fixed (engine 0073); the second review's fixes
The one frame of 58 with 13 wrong rows (PICKUP 2026-10-26, item 2) reproduced on the device with the
verify dumps: the base frame's record of what lay beneath its header held the header itself. Its job
was the load's tree change (a 4 px strip), composed by the engine as a partial composite of those
columns but read whole rows: the other columns were the window target's last composite, the verify
reference with the parts. Engine 0073 composes a content-only frame's changed rows whole. Found the
same day by the inspector's review (Codex out of credits until Nov 4th), whose other findings are
fixed too: every part's beneath recorded before any is drawn and put back in reverse (F3), the main
lane's second job only on a base of its own kind (F4). cpuPartsDress and the main poll log the
restore (the base record, d, the rows put back, a pixel of the record), rate-limited.

Records: docs/rounds/t505-2026-11-02/notes.txt, context/impl/impl-review-findings-t505-cpuparts.md
(review 2). Verified: the long page's scripted pan under JIHAD_GPU_VERIFY=1 on the Enyo variant, 85 frames, 78
shifted, 0 wrong rows (2 wrong in each round before the fix); frames looked at. Kit: R4's CPU-parts
criterion met on the long page too, R2 gains the read-width criterion.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-02 20:30:35 -05:00
NotAlexNoyleandClaude Opus 5.5 81f56bef6d T-505: the parts' picture in the frame's own job (E2, engine 0072); the review's fixes
Two inspector reviews of the parts on the CPU (Codex was out of credits) returned REVISE, and the
owner's question on the stale-picture trade was answered by a third design, now built:
- the engine reads the parts' picture in the frame's own job when the parts' signature (their
  layers' content, attributes, structure, sizes) is not the one the daemon holds; the daemon keeps
  the last three pictures by signature and dresses each frame with its own, rect by rect: exact,
  no separate picture job, no matching, no stale switch;
- a content layer above a part: the frame not shown, the engine's parts for 2 s (the document
  after three); parts over 1 MB: the engine's; the card's hold set reported apart (T-544's meaning);
- review fixes: the express lane's second frame no longer copies a frame being dressed (C1); the
  kind recorded with the slot (C7); the out-of-page rows white before dressing (C10); misses that
  are not misses not counted (C8); parts buffers lent by token, returned at the poll, reclaimed
  10 s after a forgotten job; CPU parts on unless JIHAD_GPU_CPU_PARTS=0 or <state>/no-cpu-parts.

Verify (main lane only, scripted Wikipedia pan): 0 wrong rows in 27 shifted frames; without the
parts the same run showed 2 frames with wrong rows. Scripted pan: Wikipedia 12.8 fps (9.4 without),
the long page 23.6 (18.8); by finger Wikipedia 12.3 (9.5), the long page 18.3 (15.7). Frames looked
at. The findings and their status: context/impl/impl-review-findings-t505-cpuparts.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtfxSpM1w2uiVKeLKoV3g3
2026-10-26 14:43:50 -04:00
NotAlexNoyleandClaude Opus 5.5 2bd3e6f1ae T-505: the sticky parts on the CPU (behind a switch); own-slot frames diffed without the scroll (engine 0070, 0071)
The owner's CPU/GPU split, "both, parts first". With JIHAD_GPU_CPU_PARTS=1 every GPU frame is
composed without the page's fixed and sticky parts (engine 0070, flag 128) and the daemon draws
them over it from a picture of the parts alone (flags 64|128, remade when the parts' generation
moves); what lay beneath the parts is kept per slot so frames still build on each other. Both
lanes make frames of the same kind (the main lane's are dressed at its poll, under the frame lock).

Faults found and fixed on the way (docs/rounds/t505-2026-10-26/notes.txt):
- the picture never matched a frame (the engine's keep split; engine 0070 reports whole layer
  rects); three misses in a row now turn the parts back to the engine's for the document;
- frames built on their slot's own frame had no scroll compensation in the diff (engine 0071):
  every layer transaction during a pan was a whole read;
- T-511's own-slot rule took a slot stale whole after a one-off whole change (each drag's
  settle): never a slot stale whole now (both lanes' default behaviour);
- the picture's geometry no longer has to match the frame's overscan row or height; it reads only
  the rows around the last picture's parts.

JIHAD_GPU_CPU_PARTS_STALE=1 (the owner's trade, off): frames keep the previous picture while a
changed part's is made (at most 600 ms).

Scripted pan, the card moving: desktop Wikipedia 9.4 fps without, 11.2 with the parts on the
CPU, 14.2 with the stale switch too; the long page 18.8 -> 24.7 (parts + stale). By finger the
rounds spread 11-13 fps on Wikipedia against ~10 without. Frames looked at: parts once, in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtfxSpM1w2uiVKeLKoV3g3
2026-10-26 13:44:33 -04:00
NotAlexNoyleandClaude Opus 5.5 554ed514dc T-505: the cause proven, the card measured; the card's frame wrapped without alpha
The owner's sequence: a Codex adversarial review (context/impl/impl-review-findings-t505-codex.md), then
"prove the cause first": JIHAD_GPU_NO_PUBLISH=1 (a diagnostic: frames made and read, never handed to the
card) shows the same daemon work making desktop Wikipedia 32 fps and the long page 53 while LunaSysMgr draws
nothing, 8.6 / 13.6 while the card moves: the card's redraw on the shared GPU and memory makes every daemon
stage ~3x slower. Then the card's paint measured (the adapter's [paint-stat] lines under its paint log): a
~10 ms software blit (Piranha's PSoftContext2D) of the whole view ~20 times a second, mostly repaints; a
PGSurface kept per frame changed nothing (not kept). The frame is now wrapped without alpha (every path
writes alpha 255): the blit 9 -> 5 ms, LunaSysMgr's card instance -15 % CPU while panning, the picture the
same; <state>/alphawrap reverts. The pan rate is unchanged; the owner's plan is the CPU/GPU split next.
tools/host/express-jobs.py also reads scripted pans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtfxSpM1w2uiVKeLKoV3g3
2026-10-26 11:52:33 -04:00
NotAlexNoyleandClaude Opus 5.5 a507ee867c T-504: a double tap out after a pan while zoomed in drawn at once from a half-resolution overview (engine 0069)
The owner's bounded overview. Right after a zoom in that raises the resolution, the express thread posts, all
at once and while the layer tree still holds the tiles at a resolution of 1, two or three windows (a frame's
rows each at half the zoom: the kept frame's scroll and a frame below and above, the scrolled content alone,
read with their alpha so rows no tile covered are left out) and the page's fixed and stuck parts alone at the
kept frame's scroll (with their alpha). At the zoom back, when the kept frame is off the card's view and the
picture covers it, the frame is the picture at twice its size with the parts drawn over it where they sit at
the new position. Desktop Wikipedia by finger: 40-56 ms where the paint's frame came at 294-614 ms; a pan past
the picture still waits. An inspector review's six findings fixed (the readback forced the alpha, the parts
carried the old background, the sticky probe, the scratch's lifetime and size, past-the-last-window placement,
one-to-one matching). Cost: the zoom in's sharp frame 682-779 ms against 519-545.

T-505 measured read only (the owner's "measure first"): tools/device/t502/finger-pan.sh and
tools/host/express-jobs.py; desktop Wikipedia 9.5 fps and the long page 16.6 under a finger, bound by the
readback path (docs/rounds/t505-2026-10-26/notes.txt).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtfxSpM1w2uiVKeLKoV3g3
2026-10-26 09:56:42 -04:00
NotAlexNoyleandClaude Opus 5.5 f50e49c128 T-544: the card holds sticky sidebars and fixed bars still between frames of a pan
The owner, watching finger pans: "the center column is scrolling/panning smoothly but the sidebars
are not". Between frames the card moved the whole frame it holds, desktop Wikipedia's sticky sidebars
with it, and each new frame put them back. Engine 0068 returns each frame's fixed and stuck rects
with its poll; the daemon writes them and the view row into the 192 bytes before the segment
trailer (JihadStuckBlock, tagged with the frame's number; JIHAD_GPU_NO_HOLD=1 off); the adapter draws
them where the frame drew them and covers their moved copy in the page's colour beside them.
Four mid-drag screenshots each way: sidebars at +0 px in all four with it (the column moved up to
150 px), displaced 11-12 px in two of four without; no ghost; frame rate unchanged.
R3's pan criterion is re-opened against the corrected test (the owner's choice): with the card
moving desktop Wikipedia pans at ~7 fps. The card-redraw throttle prototype showed no gain and is not
kept. UXP_PIN and SRCREV at 078a0942.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KP7JxhNqPrvYp27QDy8hP8
2026-10-26 07:02:14 -04:00
NotAlexNoyleandClaude Opus 5.5 fe3fa819ea The scripted pan moves the card, as a finger does; with it, desktop Wikipedia under a finger is measured at ~7 frames a second
The owner, watching a scripted pan: "the center column of the page doesnt move, just the sidebars".
The inject pan sent the card's scroll commands to the daemon and the card's view stood still; every
scripted pan figure so far left out the card's own redraw. It now tells the card to scroll each step and
the card reports its scroll, one source as under a finger (JIHAD_INJECT_PAN_NOCARD=1: the old test).
Measured with the card moving: desktop Wikipedia 86 frames in 11.9 s of real finger drags (jobs a median
95 ms: the card's redraw shares the GPU, the stuck sidebars re-read as ~700 whole rows a frame), the long
page 222 in 11.6 s. The express-thread copy prototype (T-505) showed no gain and is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KP7JxhNqPrvYp27QDy8hP8
2026-10-26 06:09:09 -04:00
NotAlexNoyleandClaude Opus 5.5 292d857b9d T-516: a gesture's first frame on two cores and its view read alone — double taps 20/20 within 250 ms; desktop Wikipedia's pan 24.0 fps with the sensors running
The owner chose both levers after measuring each alone: the first frame at a new zoom reads the card's
view (engine 0067, compose flag 16; JIHAD_GPU_NO_ZOOM_VIEW_FIRST=1 off) and the daemon brings the second
core online on the card's zoom or pan (cpu1/online written 1 only where it reads 0, at most every 500 ms;
JIHAD_NO_CPU_UP=1 off; never the governor). UXP_PIN and SRCREV at 46894167.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 05:30:11 -04:00
NotAlexNoyleandClaude Opus 5.5 31fce6143d T-527: the second review's fixes — the zoom-back frame kept by the lane that sees the zoom first, its publish clear of reads in flight; about:addons' search filter re-measured
Daemon: zoomBackKeep(newZoom) from either lane (only a resolution-1 frame not at the new zoom, once
per shown frame, reusing its buffer), no publish while a job's read may copy from a slot, the main
lane's old-zoom frames superseded, dropped at an input and once the tree is at 1 again; an adopted
frame at the held zoom releases the hold; the world offset cleared for a rooted document; the
adopted failure count; mLoadWasDone atomic. jihadPersonas.js: the search list's filter attributes
observed; a detail view's length kept only in the window made for it.
Device: double taps out 0-1 ms with the page's script busy (12 of 12 zooms within 250 ms), about:addons
sharp after a pinch, the search filter's length followed, pans and verify unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 03:01:26 -04:00
NotAlexNoyleandClaude Opus 5.5 45a63a9209 about:addons: the search results' rows say Uninstall too; their list pans by finger (chrome-look R2 ticked)
The search list joins the main list in the relabel (as its results arrive) and in JihadEngine.jsm's
surface table (check-engine-api.py: 0 FAIL). Enyo by finger: twelve local results for a search
pan to the last.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 02:10:22 -04:00
NotAlexNoyleandClaude Opus 5.5 180c8f0743 about:addons: an add-on's details longer than the card pan (T-527 review #13)
A view with no list reports what overflows it at the card's height and keeps that length while
the same view is shown (its box stretches with the window); the window's resize measures again.
Enyo by finger: Palefill's preferences (1233 rows at the 980 layout width) pan to their last row,
one layout change, no loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 01:16:54 -04:00
NotAlexNoyleandClaude Opus 5.5 286a926569 T-527 (R6): a double tap out shows a frame at once — the frame kept at the zoom in is published again on the way back
At a zoom in that raises the resolution the daemon keeps the frame the card shows; when the card
comes back to exactly that zoom and the kept frame covers its view, the express lane publishes it
into a free slot at once. The old tiles at under half their size make no frame, so the double tap
out had nothing until the paint at its resolution (573-771 ms). Device: published 0 ms after the
zoom, the painted frame at 771 ms, the kept frame dumped and looked at.
JIHAD_GPU_NO_ZOOM_BACK=1 turns it off; JIHAD_GPU_ZOOM_BACK_DUMP=<path> writes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 00:16:45 -04:00
NotAlexNoyleandClaude Opus 5.5 623dc1acf7 T-527: the review's fixes — XUL layout height per document, pan frames under a zoom of 0.5, the rootless offset per document, the fling lead bounded, the adoption's bookkeeping
From the inspector's read of the night's GPU-path changes (notes.txt lists all fifteen):
- a new document resets the layout viewport when its height differs too (about:addons' list
  length laid the next page out 4000 px tall)
- the express lane's 'under half the painted resolution' rule holds only while a paint at the
  zoom's own resolution would draw larger (under 0.5 every pan frame was refused)
- the rootless flag and world offset reset on navigation and follow the shown document
- the fling speed over 30 ms at least, the lead at most the overscan rows and not past the end
- an adopted main-lane frame: not after a lost composite, only with the load done, published with
  the main lane's bookkeeping and failure count, its next key the second job's slot
- the critical phase's end leaves a newer held zoom alone; zoom release and critical end take
  the frame lock; the dirty key includes the page height; the displayport is set again at a new
  window size
- the inject channel: cardscroll, and rect reports the engine's and the card's scroll

Device (daemon 7e78ab50, libxul 707d9e76): pans 33.1 / 23.6 fps, verify 0 wrong, zooms as
before, default-check 0 faults, about:addons -> a page -> about:addons right.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 00:03:03 -04:00
NotAlexNoyleandClaude Opus 5.5 a597e4a697 about:addons' long lists pan again (chrome-look R2): a XUL page's whole length reported and painted, and moved by the compositor's world offset on the GPU path
Found by finger with twelve sideloaded test extensions: the list did not move. The card was told the window's height
(a XUL root's min-height never reached the reported size), and on the GPU path a page with no root scroll frame cannot
be moved by the card's scroll (no engine scroll, no root metrics): every frame showed its top, the main lane's frames
labelled at the engine's scroll 0.

- jihadPersonas.js growToList puts the list's whole length on the root (jihad-content-height, from its items, so it
  does not follow the window); the daemon makes a XUL document's window that tall, and back when a view says 0
  (GoannaRenderPage::XulContentHeight/LayoutHeight, BrowserPageGoanna::emitGeometry).
- GoannaRenderPage::GpuRootless (a XUL document); gpuScrollTo, the express lane's view and the main lane's frame
  position use the compositor's world offset for such a page.
- A page that got shorter (a list to an add-on's details) has the card's scroll clamped (msgScrolledTo with its own
  position; the adapter only re-sizes its scroller).
By finger (Enyo): two drags reach Pad 12, a flick returns to the top, Pad 12's More opens its details from their top.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 22:41:12 -04:00
NotAlexNoyleandClaude Opus 5.5 0481ca9410 T-527: a flick no longer shows grey while the card coasts — the express lane composes each frame where the card will be when it is shown (its speed times 80 ms, JIHAD_GPU_EXPRESS_PREDICT_MS)
The card sends its position on every step of a kinetic coast; the express frames trailed a ~4000 px/s coast by one
or two frame times, and the card slid the older frame past its overscan (the lower 27-50 % of the card grey for
~0.4 s after a flick on the long page, the fixed header gone). The reader thread keeps the card's speed from its
positions; xStart composes at the position plus speed times 80 ms (no further than a card's height, not above the
page's top) and the header's renderedY places it. By finger: content to the bottom 0 and 250 ms after a flick; the
fixed header still slides for the first ~250 ms; slow drags unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 22:18:08 -04:00
NotAlexNoyleandClaude Opus 5.5 d5f50632e3 T-527 (R8) / T-511 DONE: the WebGL cube at 25-28 fps on the card — the card redraws only what changed, a tall band surface (engine 0063); the PDK adapter builds again
The 480 px spinning cube, the sensors running: 25.3-28.0 fps on the card (was 16.6-22.0), 360 px 28.9-29.9,
240 px 29.4-30.0 (the page's own ~30); verify with a ticker beside the canvas and the cube stopped 0 rows wrong.

- The frame trailer's dirty words (render/browserserver/Src/JihadFrameWindow.h): before each msgPainted the
  daemon writes the rect that differs from the frame published before it and both frames' numbers — the
  union of every composite's change since, at that frame's geometry; a forgotten job, popups, a software
  frame or an earlier-posted job not yet polled make it whole (BrowserPageGoanna pubDirtyAdd/pubDirtyTake,
  publishWindow; JIHAD_GPU_NO_DIRTY=1 off). The adapter, showing that base frame at the same geometry, zoom
  and scroll, invalidates only the rect (BrowserAdapter::msgPainted, BrowserOffscreen::dirtyRect). The YAP
  messages and the header are unchanged; docs/IPC-CONTRACT.md now describes the trailer.
- Engine patch 0063 (bda31412): a change too tall for the 256-row band surface takes a 512-row band surface
  (JIHAD_GPU_BAND_TALL) instead of the frame-sized target; frames are packed for the band surface first, so
  desktop Wikipedia's pan frames stay where they were (its pan unchanged). Pins moved; 63 patches reproduce.
- The PDK adapter had not built since T-540: YapProxy.h's member initializer (m_sendFailed) is C++11 and the
  PDK's gcc 4.3.3 refuses it; initialized in the constructor. The YAP contract check passes.
- The pan's 56 ms+ gaps traced: tools/host/gap-trace.py, and with JIHAD_GPU_TIMELINE=1 the express lane notes
  why it made no frame and every trailer is logged. Desktop Wikipedia's 10 s pan: 24 gaps, all the compositor
  job's (a whole read after a tree change, the copy from the base, a job behind the page's tile uploads).
- default-check.sh reads across the daemon log's 2 MB rotation; gpu-spike-collect.sh removes the frame dumps.
- Kit R8's 24 fps criterion ticked, R3's gap criterion annotated; T-511 DONE; notes, README knobs, ENGINE-SOURCE
  0063, PICKUP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 22:04:28 -04:00
NotAlexNoyleandClaude Opus 5.5 911034810b T-527 (R6): the zoom's sharp frame 3-4x sooner — the critical displayport, the express lane publishing the main lane's frame, engine patch 0062
Measured with the emulated finger on desktop Wikipedia, the sensors running: the first frame painted at a new
zoom's resolution 593 ms after a double tap in (was 2212), 669 after a double tap out (1890), 513 after a pinch
in (1660), 551 after a pinch out (746); the first frame at the new zoom stays 58-105 ms.

- The critical displayport (GoannaRenderPage::SetGpuDpCritical, BrowserPageGoanna::gpuCriticalEnd): a zoom that
  changes the resolution paints what the card shows first, no margins; the margins once a frame of that paint
  is out (2 s at most). JIHAD_GPU_NO_CRITICAL=1, JIHAD_GPU_CRIT_MARGIN=<CSS px>.
- The express lane publishes a main-lane frame composed while the main thread is away in the engine (40 ms,
  JIHAD_GPU_EXPRESS_TAKEOVER_MS): it polls the job, publishes its slot and takes it off the main lane's list
  (a double tap's repaint sat composed 845 ms behind a 1.1 s pump of the page's script). A main-lane post
  kicks the express thread; it looks every 3 ms while a main-lane frame is in flight.
- The zoom hold ends when the express frame is posted, not published; a zoom out past half the painted
  resolution makes no frame from the old tiles (471 ms of minified draws for a mostly blank frame).
- Engine patch 0062 (63c20e39): PaintFrame's DecideScrollableLayer replaced the root's displayport base with
  the composition size at the origin on every paint, so 0059's base (what the card shows, at the shift, times
  the resolution) never reached a paint; the GPU path now keeps it. Pins moved (62 patches reproduce the pin).
- JIHAD_GPU_ZOOM_DUMP_SEQ=1; tools/device/t502/finger-zoom.sh (+ finger-zoom-device.sh); zoom-seq.sh ROUND_DIR.
- Pans unchanged or better (long page 29.5-35.4 fps, desktop Wikipedia 22.3-28.5), verify 0 structurally
  wrong; ENGINE-SOURCE rows for 0059-0062; docs/rounds/t527-2026-10-25/notes.txt; kit R6 annotated (still open:
  the double tap out's first frame within 250 ms); PICKUP's delta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:14:05 -04:00
NotAlexNoyleandClaude Fable 5.1 ef9691eca8 Cavekit 3.1 alignment: tools/host/cavekit-sync.py regenerates .cavekit/tasks.json and reconciles task-status.json from every tier table of the build site (the loop saw 171 of 327 tasks; now all, 304 complete / 16 blocked / 7 in progress); cavekit-overview.md's Status column counted from each kit's criteria with the Finger Emulation row added; plan-overview.md and impl-overview.md point at the current sources; the plugin registration refreshed (the 3.1 marketplace's ck, which reports 3.0.0 from its own manifest); the rotate item done by the card's own orientation request (the Enyo test hook's rotate scenario); PICKUP's device state after the fling-lead push
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 19:48:38 -04:00
NotAlexNoyleandClaude Fable 5.1 c0aee8d02b T-541 DONE: a fast flick on an image-heavy page no longer lands on grey — the GPU displayport at rest is a height each way (JIHAD_GPU_DP_Y 0.25 → 0.75; the A/B on desktop Wikipedia cost nothing: 80 vs 74 express frames over the same five flicks, the main lane 5-8 fps either way) and a fling adds a lead of up to a height in its direction from the card's scroll speed (BrowserPageGoanna's velocity → SetGpuLead → asymmetric margins); about:personas' flicks by finger: the grey lower third and the white upper third are gone, a sliver at the very bottom on the first flick after load
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 19:30:59 -04:00
NotAlexNoyleandClaude Fable 5.1 88a3c2bc58 Proxies by finger in all three shells: My own proxy typed on the keyboard and used, a login-asking proxy (tools/host/auth-proxy.py) answered through each shell's dialog, the section's redraw, the Relay when chosen (https pass-through, the site's own issuer in the padlock) — and the owner's rule recorded: the Riverstone Relay is never a default, a fallback for webOS older than 3.0 only (the shipped defaults audited: direct connection, no automatic selection, the Relay's CA trust off); the settings page says so; a login dialog's reply deadline raised to 180 s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 19:01:24 -04:00
NotAlexNoyleandClaude Fable 5.1 1d85d84d47 T-539/T-540 DONE: the slow-script dialog by finger — the card's confirm names the engine's buttons in its text (OK = Continue, Cancel = Stop script; Cancel stops the script and the card stays usable); a dialog whose card closes meanwhile no longer holds the daemon's main thread for the 60 s reply wait — the wait watches the card's socket (a hang-up ends it, measured 6 s after the close) and a failed send to the card (YapProxy remembers EPIPE; the sink says clientAlive/clientFd)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 15:05:32 -04:00
NotAlexNoyleandClaude Fable 5.1 697226111b T-537/T-538 DONE: Enter in a textarea reaches the page first (a real keydown + keypress; duckduckgo.com's box now searches, a plain textarea still gets its line break); a field inside a frame by finger — the edit target follows a tapped frame into its document and a tap on the frame of the current target re-raises the keyboard; the followed layout width (T-499) survives the keyboard's height-only resize, so a fit-zoomed page neither re-flows nor re-zooms around the keyboard (it went 0.78 → 1.0 and moved the field 88 px); the everyday-browsing round in Enyo (DuckDuckGo by keyboard, a result, back, forward) recorded; jihad-frame-field.html added to the harness
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 14:34:13 -04:00
NotAlexNoyleandClaude Fable 5.1 1a18b7492a T-536 DONE: about:addons by finger — a closed popup's pixels stayed on the card (the GPU frame rebuilt on the slot that still carried the composited menu): the popup-close transition now voids every slot, the software path's and the GPU path's (gpuSlotsReset), verified gone after Check for Updates and after a dismiss; engine patch 0062 (a content invalidation on popup close) proved unnecessary and is dropped, the engine back at ec8f0ed7 (patches through 0061); the row after Undo relabelled Uninstall by a mutation observer; the tools menu styled readable; the three packages rebuilt and pushed — the device is the repository head
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 14:07:42 -04:00
NotAlexNoyleandClaude Fable 5.1 16afea29fe about:addons by finger (part): Uninstall → Undo and the update check act on one tap; three findings fixed in source, untested on the device at the cut-off — engine patch 0062 repaints the content when a composited popup closes (the tools menu's pixels stayed on the card after Check for Updates), the row after Undo relabelled Uninstall by a mutation observer, the tools menu styled readable (#utils-menu); PICKUP says exactly what is left
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 11:14:59 -04:00
NotAlexNoyleandClaude Fable 5.1 7825c9ba5d T-535 DONE: one tap, one click — the adapter sent a clickAt from the gesture single-tap on top of the pen path's hit-test click (added 2026-07-07 when the daemon answered no hit test), so every tap was two clicks: a checkbox toggled twice, about:addons' Disable disabled and re-enabled, Preferences opened one run in five; the gesture's clickAt removed, the three adapters rebuilt and verified by finger in each shell (cavekit-input-bridging R1, FINGER-TESTS about:addons)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 10:45:14 -04:00
NotAlexNoyleandClaude Fable 5.1 241988a8f0 T-529/T-530/T-531 DONE, T-532/T-533 (new) DONE: the certificate-trust round on the device — the ten new TLS roots' test sites load with the platform import off, the import now trusts 0 webOS roots (the five it added are built in), badssl's cases recorded, OCSP revocation enforced (CRL-only revocation invisible: no CRL fetch or CRLite in UXP, recorded); the TLS floor raised to 1.2 (the engine's default accepted TLS 1.0/1.1; the Settings row can lower it); the Trust dialog only for the engine's overridable errors (a revoked certificate got Trust Always and accepting reloaded into the same failure; now a failed load with the engine's alert); the daemon's start line counts the built-in roots on the removed report (0); update-engine.sh --pins checks UXP release's certdata; T-534 opened for NSS's TLS 1.3 label of a revoked refusal
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 10:04:52 -04:00
NotAlexNoyleandClaude Fable 5.1 124bca3801 T-528/T-529 (part)/T-531 (part): the certificate-trust kit and Tier 90; the root audit (tools/host/audit-roots.py: the engine's roots vs UXP release and the CCADB removed report by SHA-256) found 24 removed roots shipped and 19 missing; the roots rolled to UXP release 037cc5f6 as engine patch 0060 with the pins and a check; the platform import's removed list rebuilt from today's report (106); docs/CERTIFICATE-TRUST.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 08:59:02 -04:00
NotAlexNoyleandClaude Fable 5.1 414d284291 T-526 (part): the caret and the Backspace repeat, Copy from the address and Paste into a page field, a download of two types (the CE bench opens neither: no handler app); a generated one-line PDF as the download fixture
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 23:26:55 -04:00
NotAlexNoyleandClaude Fable 5.1 02b9edfe7a T-525 (part): the chrome buttons of the three shells with the emulated finger — all act but Mojo's back and forward, which emit no command (open); the daemon logs pageBackward/pageForward; Enyo's long-press on text and a field
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 19:37:38 -04:00
NotAlexNoyleandClaude Fable 5.1 937419d1b8 T-523/T-524/T-514: the finger round's part 1 with the emulated finger — the owner's grey found and fixed: the smart zoom's block and the viewport's maximum, the root's displayport base and clip at a resolution (engine 0059), the GPU-path hit test, the resolution before the displayport; the results in the kits (cavekit-finger-emulation R2-R4, cavekit-gpu-rendering R6, R8, R12)
The emulated finger (tools/device/finger: tap, dtap, hold, drag, drag2, flick, pinch, sleep, raw) drove the
scrolling and gesture items of docs/FINGER-TESTS.md in Enyo, Mochi and Mojo; every result is on its item and
the data in docs/rounds/finger-2026-10-24/zoom-grey.txt.

Found and fixed (the owner's "areas turn grey" of 2026-10-18):
- A double tap on desktop Wikipedia fitted a 104 px infobox cell (6.2x) and the engine's default maximum-scale
  of 10 passed the adapter's cap: the smart zoom's block is at least a third of the card wide, and a viewport tag
  without maximum-scale reports 4.0 (GoannaRenderPage).
- At rest the zoomed frame lost its right third from a zoom of 2.0 and everything from 2.98: once the pres shell
  has a resolution, Gecko takes the root's displayport base in layout device px and divides base + margins by the
  resolution, and nsGfxScrollFrame divided the root's display-list clip too; the scroll port handed over in CSS px
  shrank to 479 px at 2.33, short of the card's view 531 px over (the engine has no sideways range on a page laid
  out at the card's width). jihad_layout_set_displayport2 takes the card's shift and scales base and margins by
  the resolution; the clip is the port on the GPU path (engine c79d16f8, patch 0059, UXP_PIN moved). The daemon
  passes the shift and sets the displayport again when the shift leaves the re-anchor margin or the zoom changes,
  and sets the resolution BEFORE the displayport (a pinch from 2.33 to 2.8 clipped again; the zoom-out painted the
  whole page, 160 tiles).
- A tap or a second double tap on a zoomed page found nothing: the GPU path keeps the position in the engine's
  scroll and the compositor's shift, not the render pan docToViewport read. docOffset/gpuAlignForHitTest scroll
  the engine to the card's position before a discrete hit test; a zoomed-in page with no block under a double tap
  answers the page's width, which the adapter clamps to the fit.
- Above a resolution of ~4096 / the layout viewport's larger side the frame still clips (3.49) and empties (4.0),
  even with the resolution held (JIHAD_GPU_RES_MAX, kept for bisection): the page's maximum-scale is capped at
  4000 / the declared viewport's larger side on the GPU path (2.91 for desktop Wikipedia, 4.0 for a device-width
  page). The cause, the coast gap of a flick (the engine paints only at the coast's end: ~0.5 s of blank lower card
  and no fixed header) and the first frame at a new zoom (1.6-2.9 s) are T-527's.

Verified on the bench after the fixes, all three variants (dev copies: libxul 4d753b8f, daemon 7c29035a, the
originals kept as .orig): the double tap to the infobox at 2.33 full at rest, a sideways drag at the zoom painted,
pinches to 2.99 full, the zoom-out at once, a tap on a zoomed link opening it, Mojo's pinch on mobile Wikipedia
never grey, the WebGL cube through a pinch, a drag and three reopenings, the settings and personas pages flicked
to both ends. T-514 (the owner's finger round) closes with it; R12's "finds it smooth" stays the owner's word.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 18:50:58 -04:00
NotAlexNoyleandClaude Fable 5.1 318869f2a6 T-518/T-519/T-520/T-522: the kits' open criteria closed on the current build — the records, the GPU verify sweep and per-page table, the blocker's device criteria (cavekit-gpu-rendering R2-R4, R11; cavekit-content-blocking R3, R4, R6, R7; cavekit-modern-web R1, R6); the generic hiding sheet's 4 s cost found and fixed
Tier 88 (context/plans/build-site.md): the registry had no unblocked task left; what remained to an
agent were criteria no task covered any more.

T-518. Criteria met by earlier tasks ticked with their evidence: gpu R11's review (T-513 and Codex's
2026-10-24 pass), content-blocking R7 (the bundle's sha check against NOTICE and the lists' README, the
README paragraph with cardview.jpg, round 26's licence reading), modern-web R1 (T-484 and run 2c; the
README's Caveats link) and T-500's two. T-501's stays [~] for MSE (below). The template placeholders
never filled (T500_KIT, T501_KIT, T501_DEVICE_RESULT in docs/MODERN-WEB.md, DEVICE_STATE_EVENING and
TRACE_PICKUP in PICKUP) are filled; .cavekit/config is the owner's one line again; the README's
"Where it stands" regenerated.

T-519. On the build with the review fixes (engine 0058), the 10 s scripted pan on six pages under
JIHAD_GPU_VERIFY=1 (docs/rounds/t519-2026-10-24/): 0 rows structurally wrong on all; 0 rows differ at
all on the long page, jihad-fixed-both.html (new: an opaque header AND footer, nothing else), sticky-mix,
scroll-js and Hacker News; Wikipedia 3 of 70 frames with resampling-class rows. The one miss is the
verify mode's own: on jihad-anim-css.html the animated block's 160 rows differ (the reference samples the
animation at its own compose time), every other row equal — R2's first criterion [~] with the engine
fix named. The dumps looked at frame by frame; Hacker News at 0.955 shows its right side and bottom.
R4's four ticked on the compositor's lines: the fixed-both page reads two bands with both kept, the long
page one kept, Wikipedia's see-through panels as 2 columns in 3-5 chunks; sticky-mix takes the whole path
as in T-503's rounds (its sticky layer changes every step). R3's table: the GPU path against NOGPU=1 on
every page, in docs/RENDERING-OPTIONS.md — the GPU path ahead on every page (long static 30-33 against 11-12.5 fps, Wikipedia 18.5-26 against 2.7-2.9, Hacker News 37-48 against 6-10). The frame rates were measured again
without verify after a first sweep read 5-6 fps under it (a whole reference per job):
tools/device/t502/README.md says so; pan-run.sh takes ROUND_DIR.

T-520. The blocker's device criteria on the Enyo card through the inject channel, the listed hosts mapped to the
host PC in the device's /etc/hosts for the run (only the blocker can then stop a load): a listed host opens
top-level; EasyPrivacy's ||123count.com^$third-party loads first-party (the page on that host) and is refused
third-party; an @@||host^ exception (a list copy with one added, exceptions 6+1083 against 5+1079) loads the
host; the master switch and hiding flip live through setpref (the observer re-applies the sheet); the
settings line shows the versions and a counter that rose 10 -> 16 on a page with 6 refusals; "Update the lists
now" moved the lists three times and the line followed; shouldLoad on 200 refused images is within 10 % of
blocking off (6.5 against 6.0 s, the floor the engine's own per-image work); MSE reports H.264 and AAC
(T-501's criterion closed). R4's cost criterion was NOT met: hiding on cost the MDN page's copy 3.7-7.5 s
against 2.6-3.0 off, the real cached page 15 against 11, and a daemon's first load 8-12 s.

T-522. Four variants of the cached sheet on the device named the cost: the 268 @-moz-document regexp groups
(one per site-excepted generic selector, each carrying the 160 generic-hide hosts' 2.4 KB regexp again),
evaluated per document; the same 13,079 keyed selectors under url-prefix scopes or bare cost nothing. The
compiler (version 11) keeps those selectors apart (excSel) and the component adds them to the per-document
sheet for every host the selector is not excepted on, with the generic-hide sites (hosts and address
prefixes) honoured there too; the global sheet keeps its one regexp group. Measured: the MDN copy with hiding on 2868, 3104, 2876 ms against 2712, 2578, 2846 off
(+8.7 %, within R4's 15 %), a daemon's first load 3.7 s where it took 8-12; generic hiding still applies
under a host name, a site-excepted selector is hidden where not excepted, and a $generichide host
(jetzt.de mapped to the host PC) gets neither; the compile reports 268 excepted selectors per document and
154 generic-hide sites with 4 address prefixes.

New test pages: jihad-fixed-both.html (an opaque header and footer), jihad-tp-first/third.html,
jihad-exception.html, jihad-hiding.html, jihad-excsel.html, jihad-mse-probe.html, jihad-plain-ok.png.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 13:49:05 -04:00
NotAlexNoyleandClaude Opus 5.5 3f4e1a27e8 T-513/T-499: the review of Tier 87 fixed and verified, Codex's nine on top; the layout viewport per document (cavekit-gpu-rendering R2, R10; cavekit-modern-web R6)
T-513. Two inspectors reviewed Tier 87 (Codex was out of credits) and found twelve problems, all fixed
(context/impl/impl-review-findings-gpu-2.md). The engine's are engine 0058 (the band scratch per
compositor, every closed card's pbuffers and GL objects freed, the frame surface current for a stacked
band frame, WebGL textures externally owned, given-up reads counted and never copied into a slot, the
regions cap, the sticky probe's reach); the daemon's: the buffer the card shows is never composed into,
the express jobs forgotten on a GPU fallback, a job of another frame size given up, the adapter's window
check, the inject threads joined. Twenty card cycles add 76 KB (R10, was +16 MB a card).

R2's new criterion passes: a fast flick (40 verified frames, shifts to 1210 rows) and two cards panned
in turn (22 frames) with 0 rows wrong. JIHAD_GPU_VERIFY's reference is now composed right behind its
job on the same layer tree: composed at the job's poll it met a tree the flick had moved on from and
called right frames wrong. New round tools: tools/device/t502/two-cards.sh, the inject channel's
"target focus|last", the Enyo hook's A step.

Codex then reviewed all of it and found nine more, all fixed: the opt-in read paths' late writes (engine),
the previously shown buffer's in-flight mark restarted on each publish, the verify buffers a pool never
resized or reused while pending, the document key the inner window's id, the adapter's window bound by
division, finished inject threads reaped, and the spike scripts' daemon waits and restore order.

T-499. The card's own size resent keeps a followed layout viewport; the layout viewport is the
document's (a new document starts at the card's size: a device-width page after a followed one was laid
out at 1000 and shown at 0.77); the rule waits until the document is parsed and never follows
about:blank (mid-parse the engine lays a page out at 980 as if it had no meta viewport). Probe page with
rotation and navigation, BBC, YouTube mobile, Wikipedia, DuckDuckGo: docs/rounds/t499-2026-10-19/.

The three interfaces pass their default checks on this build (GPU path, express lane, no fault or
fallback); the bench runs it with the rebuilt adapters. Engine 0058 is in the patch queue and the pins
moved to it (build/engine/engine-version.env, the OE recipe, the gitlink, ENGINE-SOURCE's row). The kits'
criteria this met (gpu R2's flick and two-card criterion, R10's twenty cycles, modern-web's T-499 line)
and PICKUP's night delta with the traps (the bench's Wi-Fi outage, prefs saved over by an exiting daemon)
land with the Tier 88 commit that follows, whose kit edits share hunks with these.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 13:49:04 -04:00
NotAlexNoyleandClaude Opus 5.5 506c41144d T-487: the blocklist updater tested on the device; EasyPrivacy's truncation guard and the skipped early look fixed (cavekit-content-blocking R5)
On the Enyo card: a forced update (lastUpdate cleared) fetched EasyList 202610191826 and EasyPrivacy
202610191828 over HTTPS, logged the versions and the counts, and the next page's image from
beacon.cdnpure.com, a rule only in the new EasyPrivacy, was blocked (render/goanna/test/
jihad-blocking-update.html, docs/rounds/t487-update.png). With the network off (a dead proxy) the update
logged "no download" for both lists and changed nothing, with no dialog (t487-netoff.png). Across daemon
restarts no download within 4 days, nor within a day of a failed one.

Two bugs the runs found, fixed in components/jihadContentBlocker.js: EasyPrivacy was refused as
"truncated" on every update (its 57,139 lines held against both lists' rule count; each download is now
held against its own list's copy), and a due update skipped at the timer's one early look (a page had
started within 20 s) waited six hours (it now looks again 60-90 s later).

tools/device/set-prefs.sh waits for the daemon to exit before it edits prefs.js (an exiting daemon saved
its prefs over the edit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 13:49:04 -04:00
NotAlexNoyleandClaude Opus 5.5 e8b0e4250d T-512 (part): the GPU path's diagnostics off by default behind JIHAD_GPU_LOG (cavekit-gpu-rendering R11)
The [jihad-gpu] lines of the engine and the daemon print only with JIHAD_GPU_LOG=1, or in a device
round's JIHAD_GPU_TIMELINE, JIHAD_GPU_VERIFY or JIHAD_GPU_DUMP_EVERY; failures and fallbacks print
anyway. One gate each: the engine's gfx/2d/JihadGpuLog.h (engine 0057, exported as
mozilla/gfx/JihadGpuLog.h) and the daemon's render/goanna/JihadGpuLog.h. A daemon on the GPU path now
logs three startup lines from the engine; a page's close logs its express-lane frame count, which
default-check.sh counts (all three interfaces pass on the bench, no fault or fallback). Hand-started
daemons (gpu-spike-start.sh) keep the lines (NOLOG=1 drops them).

Engine 0057 also puts the page's layer transactions on JIHAD_GPU_TIMELINE with their tile uploads
(T-517, rounds 349-357). Every JIHAD_GPU_* switch is in tools/device/t502/README.md; the README and
docs/RENDERING-OPTIONS.md carry the evening's numbers. The device scripts' per-run files are ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:23:23 -04:00
NotAlexNoyleandClaude Opus 5.5 902187aebe T-517/T-511 review fixes: the express lane's own-slot base guarded, slots invalid while written, WebGL off after a give-up (cavekit-gpu-rendering R3, R8, R11)
An inspector review of the day's GPU-path work (context/impl/impl-review-findings-gpu.md), every
finding fixed:
- the express lane builds on its slot's own frame only with no main-lane job in flight (a composed,
  unpolled job's change was in no slot's record), never takes a slot a main-lane job holds, and a slot
  is invalid from a job's post (either lane) to its publish;
- an own-slot base after a scroll only when neither the latest composite nor the slot's frame had
  fixed or stuck layers (the engine judges those against the previous composite);
- a failed main-lane job drops every slot's record; a recentring move invalidates the slot first;
- engine 0054: a window-moved shift saves every kept rect before writing any, and WebGL makes no EGL
  contexts once the daemon has given the GPU path up (jihad_offscreen_gpu_given_up);
- the adapter reads the window trailer once.
T-504: a zoom's express frame gives up main-lane frames at the old zoom that were not composed yet.

The day's failed approaches are in context/impl/dead-ends.md. Rounds 339-340: the default checks of
all three interfaces pass; verify mode on a main-lane Wikipedia pan, 0 structurally wrong frames.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 11:13:45 -04:00
NotAlexNoyleandClaude Opus 5.5 4b8a595b5a T-517 (part): frame windows, a scrolled frame moves within its segment instead of its rows (cavekit-gpu-rendering R3)
A shared frame segment holds four screens of pixels and a GPU frame is about one. A frame may now
start further into it: the daemon writes where (its window, in rows) into a 64-byte trailer at the
segment's end before every publish (render/browserserver/Src/JihadFrameWindow.h), and the adapter's
BrowserOffscreen::rasterBuffer() reads the frame from there. The adapter marks the segments it makes;
the daemon moves windows only in those (an adapter from before keeps every frame at the start). The
YAP messages and the BrowserOffscreenInfo header are unchanged.

A slot's frame built on its own older frame after a scroll is now that frame with its window moved by
the scroll (engine 0053: the shift is then only the kept rects), where 3.7 MB of rows were moved on
the compositor thread every pan frame; near an end of the segment the frame goes back to the middle
with one copy. Both lanes keep every slot's stale rows (the express lane used to drop the other slots'
records on each publish; a frame composed and dropped adds its change too, and a forgotten composite
drops them all), so the express lane can build on its slot's own frame; it takes that or the copy from
the newest slot by measured frame time (the other tried every 16th frame). A windowed GPU frame is
never the software path's repaint base.

Rounds 325-332: verify mode on main-lane pans 0 structurally wrong frames after the pan began;
dumped express frames coherent; the long test page pans at 30.5-36.4 fps (median frame gap 26 ms, was
29); Wikipedia unchanged at 19-21 (its sticky panels' passes); the default checks of all three
interfaces pass with the window-aware adapters, frames right by eye. JIHAD_GPU_NO_WINDOWS=1 and
JIHAD_GPU_EXPRESS_NO_OWN=1 for A/B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 09:57:37 -04:00
NotAlexNoyleandClaude Opus 5.5 e0416cbc96 T-517 (part): no cache clean of the frame rows when the segments are mapped write-through (cavekit-gpu-rendering R3)
The daemon has attached the shared frame segments write-through (the Palm kernel's shmat flag) since
2026-10-17, so every store reaches memory; the cacheflush syscall over the frame's rows, added in the
same round, cleans only to the point of unification (it is meant for code) and cost up to 4 ms a
frame on the publishing thread (3.7 MB line by line after a shift). It now runs only when a segment
had to be mapped cached; JIHAD_GPU_CACHE_CLEAN=1 cleans anyway. Wikipedia pan, median frame gap
42-43 ms against 45 (rounds 323); what the card shows checked by eye on the cube and Wikipedia
(round 324).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 08:48:37 -04:00
NotAlexNoyleandClaude Opus 5.5 8518970ce0 T-511 (part): WebGL on the device's GPU on the GPU path, composited with no copy (cavekit-gpu-rendering R8)
Engine 0051: on the GPU path WebGL asks EGL for its context and is not blocklisted there; the
Adreno 220's GL_INVALID_ENUM for the stencil back write mask no longer fails the context's init;
every pbuffer context on the GPU path is in one share group, so a canvas's texture is composited
with no readback (the driver has no EGLImage from a GL texture); a context is released from its
thread before it is destroyed (the second WebGL page closed faulted in libGLESv2 before).
JIHAD_GPU_NO_SHARE=1 keeps contexts unshared, read back through a canvas-sized pbuffer. On the
software path WebGL stays off.

Engine 0052 and the daemon: a compose job gives the columns its bands are stale in, the poll
reports the columns the composite changed, each slot keeps its stale columns as it keeps its rows,
and a narrow change's bands are read as one column (the compositor job 44 ms against 47 for a
480 px canvas; JIHAD_GPU_NO_COLUMN_READ=1 reads whole rows). The slot's own frame is the base when
its stale rows beyond the last three frames' changes are few: the 480 px canvas copied the whole
frame from the newest slot every frame to read the same rows.

The test page render/goanna/test/jihad-webgl-cube.html (a spinning textured cube; size, checks,
context loss, the missing extensions, a stop and a counter beside the canvas for the verify mode).
Rounds 281-313 (docs/rounds/t502-2026-10-17/webgl-r281-313.txt): contexts on the GPU path, none
on the software path; the cube renders right; 8 card open/close cycles and a lose/restore without
a fault; the spot checks pass, the four missing extensions listed; the column read verified against
whole composites with a change outside the canvas's columns. Open: the 480 px cube draws 21.5-25 fps
but the card gets 18-20.5 (240 px 26.5-27): the compositor job's floor, carried by T-517.

Also: adapter-install.sh no longer turns on the adapter's paint log (its gate filled /var and hung
the daemon in a journal commit); crash reports list every executable mapping; gpu-bench section 17
(no EGLImage from a GL texture) and the GL extension list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 07:44:26 -04:00
NotAlexNoyleandClaude Opus 5.5 bf26d622b7 T-515 fix: the YAP proxy's locks are pthread mutexes, so the adapter builds again
The express lane's reader thread (5f7c9fc3) put std::mutex, std::lock_guard and std::atomic in
YapProxy.h. The adapter compiles the same YAP sources with the PDK's gcc 4.3.3 (the device WebKit
host's own compiler), which has neither <mutex> nor <atomic>: build-adapter-pdk.sh had failed since.
A small YapLock / YapLockGuard over pthread_mutex_t takes their place; the command tag counter is
taken under the queue's lock. The three adapters build; the daemon's behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 07:44:12 -04:00
NotAlexNoyleandClaude Opus 5.5 773c1c69c8 T-510: the GPU path, with the express lane, is the default in all three interfaces (cavekit-gpu-rendering R1)
The generated upstart jobs start each daemon with JIHAD_GPU_COMPOSITOR=1 JIHAD_GPU_EXPRESS=1. The
daemon settles the path before the engine starts (the engine tests the variable's presence in many
places): JIHAD_GPU_COMPOSITOR=0, or user_pref("jihad.gpu.enabled", false) in the profile's prefs.js
(read as text: the pref service is not up yet; the bundle's default is true), unsets both and the
software path renders. The log names the path and why ("rendering: ..."). A GPU that fails at run
time still falls back by itself (T-509).

On the bench (CE 3.1.0) the three jobs were installed in a remount window: Enyo, Mochi and Mojo each
load, pan, pinch and close desktop Wikipedia on their own default daemon through the card's
self-test hook (tools/device/t502/default-check.sh), no fault and no fallback; the pref put Mochi on
the software path and back, and JIHAD_GPU_COMPOSITOR=0 did the same for a hand-started daemon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 05:03:05 -04:00
NotAlexNoyleandClaude Opus 5.5 cf1342e0a4 T-516 (part): the zoom's first frame after a pause: the clock up at the card's command, the frame threads first (cavekit-gpu-rendering R6)
The double taps' slow first frames were not draws: the engine timeline (engine 0050) put their time
in the first readback after a pause (100-390 ms, 30-40 usual) and the CPU swizzle (20-122 ms, 7
usual): the clocks after two idle seconds and the engine's other threads. The YAP reader thread now
raises the clock hold on a card's scroll, zoom or smart-zoom request (the clock hold made thread-safe;
JIHAD_CLOCK_HOLD_MS), and the Compositor and JihadExpress threads run at nice -6 (JIHAD_GPU_FRAME_NICE).
Double taps over 250 ms: 4-8 of 12 before, 0-2 after (median 158 ms). Left: the GPU's own ramp after
a pause. A warm-up frame on the smart-zoom request was tried and dropped (its own slow frame queued
ahead of the zoom's). The timeline also logs the clock hold's transitions and each express frame's
clocks.

T-510 (the default) is repointed from T-504 to T-515: it waited so the owner's zoom complaint would
not ship, and the express lane closed it; T-504 stays open for the ramp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 04:46:54 -04:00
NotAlexNoyleandClaude Opus 5.5 5f7c9fc300 T-515 (part): frames made off the main thread, the express lane (cavekit-gpu-rendering R3, R6)
With JIHAD_GPU_EXPRESS=1 on the GPU path each card's YAP commands are read on a thread of the
proxy's own and the daemon's frame bookkeeping is under one frame lock, which the main thread lets go
of only in the engine's pump and in a frame's layer paint. An express thread composes the layer tree
as it stands at the card's newest scroll and zoom and publishes the frame: every frame while the card
moves (the main lane paints layers and moves the anchor), and the main thread's stalls otherwise.
Engine 0048 splits the frame's paint from its compose post and lets any thread post and poll jobs;
0049 stops a composite acknowledged after the card's widget is gone from dereferencing it (a crash
on a card's disconnect seen in a device round).

Device rounds 240-269: zooms while the page's script holds the main thread come within 250 ms
(Wikipedia after its load 10/10 within 160-225 ms, held off median 681 and three never framed; a
page holding the main thread 600 ms in every 700 within 45-91 ms, held off median 450); that page
pans at 26-32 fps (2.4-3.8). Desktop Wikipedia pans at 19-21 fps: the compositor thread's ~45 ms a
frame is the floor now (T-517); the double taps' slow frames are GPU draws (T-516). Off by default
with the GPU path; no change with it off (the test page 30-33 fps, software 2.9-3.2).

Also: wants under a lock of their own (the reader thread never waits for the frame lock: a proxy's
teardown joins it), commands tagged in arrival order (a main frame serves the card once it took up
the newest), main frames older than an express publish dropped, the zoom hold released by an
express frame, the inject channel's pan and zoom through the card's path, JIHAD_GPU_TIMELINE,
JIHAD_GPU_ZOOM_DUMP=log, zoom-seq.sh, jihad-script-hold.html; a 32-bit 1L << 40 in the band merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 03:53:01 -04:00
NotAlexNoyleandClaude Opus 5.5 51bda89012 T-509: the GPU path given up safely, and its cost measured (cavekit-gpu-rendering R1, R10)
The daemon gives the GPU path up for its life, and renders in software from the next paint, when
the compositor fails or refuses three frames in a row (no GL context: the engine falls back to its
software compositor) or a frame is not composed within 3 s (JIHAD_GPU_JOB_BOUND_MS): the jobs are
forgotten (engine 0047: the compositor then writes nothing into their slots), the engine scrolled to
the card's position, the compositor's scroll, view, overscan and resolution put back, and pages made
afterwards start in software. Tested with the engine's new switches: JIHAD_GPU_TEST_NO_EGL=1 and
JIHAD_GPU_TEST_STALL=30, the page rendered both times, LunaSysMgr kept its EGL.

Measured: desktop Wikipedia in Enyo 210 MB resident on the GPU path against 143 MB; three daemons at
once (tools/device/t502/three-daemons.sh) 447 MB against 341 MB with the device's free plus cached
memory at 324 MB against 476 MB and swap untouched; idle CPU equal on settled Wikipedia (41 and 42
ticks in 30 s, no frame either way) and on the test page, lower on Hacker News.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 01:21:46 -04:00
NotAlexNoyleandClaude Opus 5.5 54e182dcda T-508: video and Flash on the GPU path (cavekit-gpu-rendering R7)
On the device with the GPU path: VP8, Theora, VP9 and H.264 clips play to the end with every frame
decoded, the video its own image layer, at the clips' own rates (15 fps clips published at 16-20
fps; the 640x360 24 fps clip at 15.5-18, the software path 10-15); a 60 s clip matches the software
path frame for frame. Styled video (jihad-video-styled.html): rounded corners, an opacity fade and a
modal over the video draw as on the software path. Flash: the test movie animates (21-25 fps) and
takes keys (green to red).

H.264, AAC and MP3 had played on neither path: push-engine-update.sh never carried FFmpeg's
libavcodec/libavutil, so a device updated by it since a full install without them refused every
MP4. It carries them now (pushed to all three variants). The build site's T-499..T-501 and the
handoff's placeholders are filled from commit 4ded8d72 and today's checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 00:54:57 -04:00
NotAlexNoyleandClaude Opus 5.5 589a0c2f85 T-507: every other card event on the GPU path (cavekit-gpu-rendering R9)
On the device with the GPU path and a new test page (render/goanna/test/jihad-card-events.html): the
card rotated to landscape and back (1024x890 frames with the overscan) and the keyboard's resize
redraw right; the select's list opens and a pick reaches the page; the caret shows in the tapped
field; find-in-page highlights its match; a link, back, forward and reload show the right page each
time. Two fixes for overscan: a thumbnail is taken from the published frame's view row (it took
the overscan above it), and the popups are composited at the published job's position and zoom.
The test hook gains back, forward, reload and orientation steps; the inject channel a thumbnail
command. Link taps: the daemon sends no highlight rectangles on either path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 23:38:03 -04:00
NotAlexNoyleandClaude Opus 5.5 e6331d3f18 T-506: animation, new content and a self-scrolling page against the chart (cavekit-gpu-rendering R5)
An input-latency probe on the inject channel: a click, key, text insert or script marks the time
and the GPU publish logs the first frame with changed rows after it. Measured on the device:
jihad-anim-css.html 26-31 fps reading only its 160 changed rows; eight keys typed into
jihad-input-echo.html reach a published frame in 22-62 ms and five DOM edits in 26-70 ms (the
chart's 106 ms); jihad-scroll-js.html followed at 10.7-13.9 fps (the chart's 9).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 23:10:52 -04:00