49 Commits
Author SHA1 Message Date
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
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 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 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 dc7bae02be Engine 0066 (T-527 review): the paint skip repaints after a resolution change and asks the child widget; a failed band surface retried after 30 s
UXP_PIN and SRCREV at 2f7898f0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 03:01:03 -04:00
NotAlexNoyleandClaude Opus 5.5 eb9987b742 Engine 0064, 0065 (T-527): a layer paint with nothing pending skipped, a moved displayport base repainted; a failed band surface not retried every frame
UXP_PIN and the recipe's SRCREV at the engine branch's f4fefca0; patch-queue --check reproduces it
with the 65 patches. Device: pans unchanged (the long page 33.1 fps, desktop Wikipedia 23.6), verify
0 rows wrong, default-check on the GPU path with 0 faults.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 00:02:53 -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 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 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 7a4873febb T-517 (part): a band frame's regions in one composite, tiles outside the clip skipped early (cavekit-gpu-rendering R3)
Engine 0055: the bands and the sticky columns' chunks of a pan frame are regions of one composite (the
transaction, the diff and BeginFrame/EndFrame once; per region its world, Prepare and RenderLayer),
where each was a composite of its own at ~5 ms of CPU. Engine 0056: a tile whose transformed bounds
miss the clip is skipped before its texture is locked and bound. Chunked desktop Wikipedia frames
compose in 10.6 ms where they took 22.5, and its 10 s scripted pan runs at 23.4-23.9 fps (20.0-21.7
before). Verify mode, the default checks of all three interfaces and the measurements are in
docs/rounds/t502-2026-10-17/floor-r314-320.txt (rounds 342-348), with what was tried and dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-19 12:46:20 -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 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 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 592c05ec1f T-505 (part): overscan on the GPU path, the per-page table and the gaps traced (cavekit-gpu-rendering R3)
The GPU frame now carries 0.15 of the card's height above and below the view once a page has been
panned (JIHAD_GPU_OVERSCAN; engine patch 0046 widens the root scroll frame's clip by it), so the card
has content to pan into between frames and while the main thread is busy, as the software path's
frames have: the grey past a view-sized frame's edges was one of the owner's grey areas. The view
sits the same rows down every frame (a view row that moved with the frame broke the compositor's
row shift: every frame read whole), rows outside the page are filled white, and frames are capped at
the compositor's first pbuffer (1400 rows: a 1412-row frame read its top rows from the bottom ones,
flipped). Verify: 0 structurally wrong rows on the test page, sticky-mix, desktop Wikipedia and
Hacker News. It costs ~10% of the pan rate (a quarter of the height cost 15-18%).

Measured (scripted 10 s pans, rounds 191 and 200-201): the GPU path ahead of the software path on
every page (the test page 30-35 fps against 2.7-3.2, sticky-mix 17-19 against 2.4-3.1, desktop
Wikipedia 19-26 against 2.7-2.9, Hacker News 31-37 against 6.4-10.4; with overscan the test page
25-32 and Wikipedia 16.5-24). The gaps of 56 ms and more are the page's own restyle on its first
scroll (955 ms), the paints of the displayport moves (58-121 ms) and short page events; Wikipedia at
24 fps needs frames made off the main thread, now T-515.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 23:04:14 -04:00
NotAlexNoyleandClaude Opus 5.5 5bc47d335a T-504 (part): the zoom's resolution above 1.1 and no edge antialiasing for a scale (cavekit-gpu-rendering R6)
Zoomed in past 1.1 the pres shell's resolution follows the zoom (without scale-to: layout adds a
post-scale, the geometry is unchanged), so the tiles land one to one on the card: desktop Wikipedia
at 2.2 is as sharp as the software path's paint instead of a 1x paint magnified. Below 1.1 the 1x
paint stays: a fit zoom's resolution resamples every image and glyph on the CPU and the Wikipedia
pan lost 3-5 fps to the dearer anchor paints. Engine patch 0045: no DEAA for an axis-aligned scale
on the GPU path (its shader variants compiled in the first frame of a zoom, ~150 ms each).

Desktop Wikipedia settled: the first frame at a new zoom in 52-217 ms (pinches), 61-124 ms for a
double tap in and 182-257 ms back out; a pan at 1.23 at 18.5-28 fps; the pan at the fit zoom
19-25 fps. Still open (with T-505): the first frame while the page's script holds the main thread.
The kit's R6 gains the sharpness criterion; T-504 recorded as partial.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 21:32:55 -04:00
NotAlexNoyleandClaude Opus 5.5 b214ab0e8b T-504 (part): no grey strip when zoomed in, and tile uploads that do not wait (cavekit-gpu-rendering R6)
Zoomed in, the card's view can sit where the engine cannot scroll (desktop Wikipedia at 1.23: x 245
CSS px of a scroll port that does not scroll sideways). The pan's settle moved the engine there,
found it at x 0 and turned the compositor's scroll off, so frames were published at x 0 under a card
at x 302: a grey strip down the right of the card (one of the owner's grey areas). The compositor
now keeps the scroll the engine could not reach.

Tile uploads: on the Adreno 220 the first write into a texture after its first draw costs ~18 ms a
256x256 tile (sections 11-15 of tools/device/gpu-bench.c pin it down: proportional to the size,
any format, once per texture, kept across a re-specification, triggered by a framebuffer clear
without a wait). Engine patch 0044 converts each new tile texture while it is 1x1 (1.1 ms) and
keeps textures in a pool. Desktop Wikipedia pinched in and out after its load: re-uploads slower
than 8 ms from 55-59 a run (24-37 ms average) to one; the first frame at the new zoom in 61 ms
(in) and 99 ms (out); the card covered at rest after both (screenshots looked at).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 19:53:15 -04:00
NotAlexNoyleandClaude Opus 5.5 a8003f7c87 T-387: the desktop engine on RB_20261006 and desktop tests for Personas, video controls and media (cavekit-engine-update R6)
The desktop engine had not been built since the Palm NPAPI work: patch 0043 guards the gain-focus
event and the spotlight export the way npapi.h defines Palm's NPEvent (the headless toolkit), and
the objdir was clobbered for the release. The daemon sources build for desktop again: the stall
sampler reads the PC per architecture, jemalloc's purge is a weak reference, the clock-hold flag is
defined in EngineHost.cpp.

New desktop tests (build/desktop/build-{personas,media}-test.sh): Personas 7/7 (wear an installed
Persona from about:personas, the theme manager's prefs, the about:addons Personas pane); media 18/18
(VP8, Theora and VP9 start, the controls' binding attaches, a tap pauses and another resumes, each
plays to its end with frames decoded; the Vorbis case needs a sound server and is skipped in the
container). Both negative controls fail as they must. prefsui_test's reset message brought up to
date: 38/38. Device (Enyo) after the ARM rebuild: a page loads and paints, the purge and the clock
hold work.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 18:53:20 -04:00
NotAlexNoyleandClaude Opus 5.5 e74e212daf T-503 (Cavekit Tier 87, rounds 138-150): fixed and sticky content at minimum cost and frames that verify
The GPU path is now a kit (context/kits/cavekit-gpu-rendering.md, R1-R12) and Tier 87 of the build
site (T-502...T-514). T-503:
- opaque fixed and stuck layers keep their pixels from the base frame, per covered rect; only the
  rows the shift uncovers beside them are read; the others are read as their columns, cut into
  chunks packed side by side on the band surface; a fixed header and footer read two bands
- the draw culling now culls (a quad clipped to nothing became a 2x2 rect at the origin)
- a sticky layer the engine already laid out stuck counts as stuck (its sticky ranges probed)
- the root composition covers what the card shows, and the page gets a displayport of what the
  card shows from the start and at every zoom (Hacker News' bottom strip was clipped blank)
- JIHAD_GPU_VERIFY changes nothing the next frame reads, skips frames from another zoom, and
  reports structurally wrong rows apart from sub-pixel resampling: 0 on the test page,
  jihad-sticky-mix.html, desktop Wikipedia and Hacker News
Pans: test page 27-34 fps, sticky-mix 15-17.5 (software 0.9-3.1), desktop Wikipedia 16.4-18.5
(was 13-14; software 9-12.4), Hacker News 34-37.5; animation 24-32 (engine patch 0042 amended)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 17:44:41 -04:00
NotAlexNoyleandClaude Opus 5.5 bc4a8eaff2 T-502 rounds 129-134: a desktop page drawn right on the GPU path (the root's composition is its scroll port: the window-sized one clipped the right third and the bottom), the displayport base and margins from what the card shows, the fixed-row re-read widened by the shift (a sticky header doubled), the second job built on the job in flight, frame dumps counted from the pan; en.wikipedia.org pans at 13-14 fps (software 9-12.4) with every row right, the test pan 24-31 (engine patch 0042 amended)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 13:57:41 -04:00
NotAlexNoyleandClaude Opus 5.5 e55056f967 T-502 rounds 126-128: the first real page (en.m.wikipedia.org) — the displayport cut to 0.5 heights and none sideways unless zoomed in (the 1.25-height one cost ~95 tile uploads and made the GPU path slower than software), the anchor at 0.25 heights, only stuck sticky layers counted as fixed rows, fixed rows recomputed after band frames; the real page pans at 15-17 fps against software's 9-12.4, the test pan 27-31, the animation page 27-33 (engine patch 0042 amended)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 12:47:02 -04:00
NotAlexNoyleandClaude Opus 5.5 147a506b53 T-502 rounds 120-125: anchor moves during a pan become band frames (the painted region, not its bounds, reaches the compositor on the GPU path; changed regions clipped to the frame before their bounds), the anchor distance a knob at 0.3 heights; the pan at 26-33 fps with clean frames (engine patch 0042 amended)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 12:16:52 -04:00
NotAlexNoyleandClaude Opus 5.5 fb3028bed7 T-502 rounds 118-119: the diff first, without a render, and a tree change composed on the band surface when its rows fit; the displayport from a page's own first scroll; the measured scroll shift no longer cleared before the bridge reads it; animation page 26-31 fps, self-scrolling page 13.5-17.4, pan 25.5-31, frames verified by dumps and by eye (engine patch 0042 amended)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 11:47:39 -04:00
NotAlexNoyleandClaude Opus 5.5 1d2ea9f8a5 T-502 rounds 115-117: the diff treats the root-content layer's scroll as a shift (a page's own scroll reads the entering band; the engine reports the frame's position), the diff scaled to frame pixels (a fit-zoomed animated page read the wrong rows), the two-deep queue reads the composed job's changed rows and runs only when nothing scrolls; pan 27-32 fps, animation 23.5-25, self-scrolling page 11-14, frames verified by dumps and by eye (engine patch 0042 amended)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 11:31:42 -04:00
NotAlexNoyleandClaude Opus 5.5 46854c6ae7 T-502 round 113-114: each frame built from the newest finished slot (copied with the scroll since it, only the entering band read, the fixed rows only on a scroll), the slot's own frame kept when it is cheaper (an animated page), a flush before the copy; the pan at 26-32 fps, the animation page 24-25.5; the self-scrolling page at 9-13.5 recorded as below round 86 (engine patch 0042 amended); pan-run.sh measures a page without a pan
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 11:03:25 -04:00
NotAlexNoyleandClaude Opus 5.5 1a332a663d T-502 rounds 99-112: the white rows were the Adreno 220 binning by the EGL surface's size (frame-sized pbuffer and targets); band frames on their own 768x256 surface kept current, the row shift behind the GPU, a done-pipe waking the daemon's loop, the displayport from a page's first pan, the compositor-side scroll engaged by card pans only and settled after them, two post-hand-off reads fixed, the other-slot stale union restored; the pan at 25-31 fps, the animation page 21-25, frames verified by dumps and by eye (engine patch 0042 amended)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 10:44:43 -04:00
NotAlexNoyleandClaude Fable 5.1 86c9f81466 T-502 rounds 92-100: the displayport set from layout, root scroll metadata and the scrollport as a scroll clip without APZ, no intermediate surface for a scaled container, the band-sized compositor target, glFinish before the readback (engine patch 0042 amended); the daemon's compositor-scroll band position, 1.25-height displayport with the anchor at 0.6, verify mode, frame dumps and white-row tracker; the documentation sweep (bench is CE 3.1.0, Go untested, pan claims corrected, Global Jihad on the list); OPEN: one composite in five white below row 484 (docs/PICKUP.md)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 06:11:52 -04:00
NotAlexNoyleandClaude Fable 5.1 e0fc5d146b T-502 round 91: two-band reads on scroll-only frames (engine patch 0042 amended: the bands, the row shift on the compositor thread, the fixed rows and the scroll-only flag from the request-count signal), the daemon's slot kept and shifted in place, the band position at the card's scroll on the compositor-scroll path, mid-pan frame dumps for the scripted pan; a pan at 21-22 fps reading ~100 rows a frame, NOT yet verified by eye (the dumps had not fired: novacom splits the env words); bench section 9 (a band-sized target composes in 2 ms, texture-FBO reads cost 20 ms a call, renderbuffer reads 1 ms)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 04:13:02 -04:00
NotAlexNoyleandClaude Fable 5.1 ce302977e6 T-502 round 90: the card's scroll applied in the compositor (engine patch 0042), the daemon's scroll anchor inside the painted displayport, a scripted pan through the inject channel, a long static test page; a pan at 17-20 fps with no content uploads
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 02:57:39 -04:00
NotAlexNoyleandClaude Fable 5.1 317a4fc76a T-502: the engine's temporary commit folded into patches 0040 (the compositor) and 0041 (the Adreno 220's GL), the diagnostics-only files restored; patch queue regenerated, pins moved to e0c04228, the engine docs' rows updated
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-18 02:42:01 -04:00
NotAlexNoyleandClaude Fable 5.1 73d1576ffa T-502 round 10: the card's zoom is a world transform on the compositor's layer tree (the engine's resolution and scroll-port calls black the frame on this path); the two engine commits re-split (0040 compositor, 0041 gl)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 12:56:49 -04:00
NotAlexNoyleandClaude Fable 5.1 618e5aa763 T-502 round 7: whole-texture uploads on the Adreno 220 (patch 0041), alpha forced in the compositor's read, the nonblank count sampled on the GPU path
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 11:32:10 -04:00
NotAlexNoyleandClaude Fable 5.1 c2a9c25830 T-502 round 6: the frame is composed and read on the compositor thread into the shared buffer (no snapshot road), a renderbuffer window target, pull mode (the compositor counts composite requests, the daemon pulls), the clock floor leak
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 11:23:17 -04:00
NotAlexNoyleandClaude Fable 5.1 714a9f1312 T-502 round 5: the readback swizzle in NEON
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 10:57:51 -04:00
NotAlexNoyleandClaude Fable 5.1 886d061537 T-502 round 4: the compositor draws into a plain pbuffer (no screen buffer) and the frame is read straight into the target
gpu-bench on the device: glReadPixels from a texture-backed FBO 370-640 ms,
from a renderbuffer FBO 28 ms, from the pbuffer 12-43 ms; the offscreen
GLScreenBuffer is a texture FBO, hence round 3's 240-490 ms readbacks.
The spike's context is now a pbuffer with no screen buffer, and
CopyToTarget reads RGBA into the target's bits and swizzles in place
(no temporary surface, no cairo flip; the flip was also what turned the
frame upside down on an offscreen context). The spike script turns T-499
off so the widget stays at the card's size.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 10:53:34 -04:00
NotAlexNoyleandClaude Fable 5.1 d42a7b0797 T-502 round 3: the child widget keeps the shared layer manager alive, the offscreen surface follows the frame size, per-stage timings; a four-layer CSS animation test page
Round 2 on the device: the OpenGL compositor came up on the Adreno 220
(EGL pbuffer, backend 2) and composed frames, but the snapshot road cost
224-390 ms per frame and a child widget's destroy tore the shared
ClientLayerManager down (SIGSEGV in BeginTransactionWithTarget). Patch
0040 amended; its log is docs/rounds/t502-2026-10-17/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 10:42:41 -04:00
NotAlexNoyleandClaude Fable 5.1 181d0d6cb9 T-502: the spike's env wins over the bundle's OMTC force-disabled pref (patch 0040 amended)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 10:32:08 -04:00
NotAlexNoyleandClaude Fable 5.1 8b528bfb3c T-502: the GPU compositor spike, engine patch 0040 and the daemon's compose path (not yet built)
With JIHAD_GPU_COMPOSITOR in the daemon's environment (JIHAD_DISABLE_OMTC
unset, MOZ_LAYERS_PREFER_OFFSCREEN=1) the offscreen widget creates an
in-process OpenGL compositor on an EGL pbuffer and the daemon's
ReadPixels takes its frame through the new jihad_offscreen_compose
export (layers painted, composited, read back over the upstream snapshot
road). Nothing changes without the env. Engine pin moved to fdf7c45d;
patch 0040 in the queue; ENGINE and ENGINE-SOURCE updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J67ZH8aYy8uzhgZDZ6Nvx9
2026-10-17 10:27:00 -04:00
NotAlexNoyleandClaude Opus 5.5 23ffd9af83 Engine: UXP RB_20261006; updates in two commands; a release build in Thumb-2
The owner, 2026-10-12: "Proceed with the UXP update, with a focus on making future updates
easier, and optimizing the code where possible, while supporting modern web standards. target
the latest release".

The engine (third_party/uxp) moves from master b2594a4 (2026-06-30) to the release RB_20261006
(5f290d1, about 170 upstream changes: NSS 3.90.14 and security fixes, constructable style sheets,
URL.parse(), revert-layer, aspect-ratio for grid items, :has(), typing speed, leak fixes), branch
jihad/uxp-RB_20261006 at 706d4782ba. Our 39 commits came across with git's three-way merge and no
conflict, now one commit per patch (the squash of 0001-0031 split); the six files both sides
changed were read: only --disable-npapi-gtk2 had to go (upstream now offers GTK2 NPAPI to GTK
toolkits only). check-engine-api.py: 0 FAIL, baseline re-written, no signature changed.

Future updates:
- build/engine/update-engine.sh [TAG] puts the queue (build/desktop/patches, now git mails) on a
  release with git am -3 in a worktree, lists the files both sides changed and runs the API check;
  --finish writes the queue again, checks the branch out and rewrites every pin (engine-version.env
  with the new UXP_TAG, the OE recipe, the user agent, the three start pages); --abort, --pins.
- make-device-bundle.sh reads the ICU data file's name from engine-version.env.
- render/goanna/EngineCalls.h: the 15 positional engine calls behind named wrappers.
- docs/ENGINE.md §6 is the procedure in those terms, with the full variant push an engine update
  needs (push-engine-update.sh does not carry the engine's own JS, CSS and chrome).

Optimised: mozconfig.goanna-arm is a release build (--enable-release --enable-gold: dead-code
removal and identical-code folding, both off in developer mode) in Thumb-2 (--with-thumb=yes).
Stripped libxul 46.2 -> 30.2 MB (-35%), its code -43%; an idle daemon 33.8 MB resident against
36 MB before.

Modern web: a Settings switch for CSS :has(), off by default as upstream releases ship it (slow
on some pages). render/goanna/test/modern-web.html reports the features.

Fixed on the way: postinst/prerm took the initramfs rootfs line for a read-write /, so a read-only
root was never remounted and the install failed; they read the real root mount now. The daemon
includes nsIDocument.h before nsIPresShell.h, which the new StyleSheet.h needs. JIHAD_APP_BUILD_ID
bumped. The UA and start pages say Goanna/6.9 UXP/5f290d1.

Device, all three (a full push-variant.sh each): 11 of 11 optional exports; Enyo: the feature page
before (no adoptedStyleSheets, replaceSync, URL.parse, revert-layer, :has) and after (all, :has
with its switch on), TLS 1.3 on howsmyssl.com, a Persona worn and taken off, Palefill enabled,
about:config, Flash at 23-25 fps; Mochi: the feature page; Mojo: Wikipedia. Nothing pushed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcrVQFRMC2ANGDfVaRG9Ed
2026-10-12 20:35:46 -04:00
NotAlexNoyleandClaude Opus 5.5 30a4970bd1 Engine update groundwork: the branch is the source of truth, pins in one file, exports in one header, a checker for candidate engines, docs/ENGINE.md
Owner: "lay the groundwork for a uxp/goanna update by making our interaction with it more
modular and maintainable by humans." Kit cavekit-engine-update.md, Tier 74. The engine itself is
not updated.

- build/engine/patch-queue.sh: --check applies the patch queue to UXP_BASE in a scratch git index
  and compares the result with UXP_PIN's tree (seconds, no checkout); --add writes the next patch
  from an engine commit. The queue had drifted from the engine branch: part of the squashed series
  (the Flash child's JIHAD_PLUGIN_SELF_DRIVE switch) and the eight later commits were missing.
  Now 0031 (that remainder) and 0032-0039 (format-patch of the commits); --check passes, 39
  patches reproduce the pin exactly. The never-applied snapshot, the WIP patch and the hand-diff
  script with its baseline are removed.
- build/engine/engine-version.env + check-engine-pins.sh: the upstream base, our pin, Goanna
  version, the short hash the UA shows and the ICU file, checked against the gitlink, the OE
  recipe SRCREV, the user agent, the three start pages and the bundler.
- render/goanna/EngineCompat.h: every jihad_* export the daemon takes from our engine branch,
  required or optional with its fallback, declared only there; the daemon logs at start-up which
  optional ones the running libxul lacks. Device: "engine: 11 of 11 optional jihad_* exports
  present", pages load.
- build/engine/check-engine-api.py (+ engine-api-baseline.json): what a candidate UXP tree no
  longer offers — our exports, IDL methods called positionally, interfaces we implement or
  redeclare (nsIXULAppInfo & co., the hand-copied nsIClipboardHelper IID), the engine JS and
  about:addons markup our components use, prefs, mozconfig options, the ICU file. Today: 0 FAIL.
- docs/ENGINE.md: the guide (where, the rule, the delta, touchpoints by risk, tools, update
  procedure, tests per touchpoint, device checklist, next steps). docs/ENGINE-SOURCE.md, the MPL
  record, lists all 39 changes (it listed four under old names); docs/UXP.md and the desktop
  README point at ENGINE.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcrVQFRMC2ANGDfVaRG9Ed
2026-10-08 19:41:11 -04:00
NotAlexNoyleandClaude Opus 4.8 57eb48724c Session 2026-08-15: audio backend, chrome-typing fix, cert store, device verification
Engine audio (gre-widgets R1/R7): switch cubeb ALSA -> PULSE backend, which is
what webOS's audio policy requires. mozconfig --enable-pulseaudio, pulse-0.9.22
sysroot headers matching the device ABI, and patch 0030 targeting JIHAD_PULSE_SINK.
Device-verified AUDIBLE (user-confirmed "I hear the tone"): decode -> cubeb pulse
-> DAC -> codec -> speaker/headphone. The prior ALSA backend was silent because it
presented as an anonymous ALSA-plugin stream that module-palm-policy muted; the
pulse-native stream identifies as the app and is left at full volume.

Chrome-page typing (preferences-ui R6): GoannaRenderPage::InsertText recovers a
null mFocusedEditable from document.activeElement, which dodges the focus-manager
window-scoping that made chrome documents (about:preferences) unable to receive
typed text. Device-verified: text now inserts into about:preferences fields.

Cert store (browser-services R5): new JihadCertStore dlopens libPmCertificateMgr
and integrates accept/trust with the webOS platform cert store; three defects fixed
(empty certFile, nsresult-in-Palm-ordinal-space, Trust-Always vs Trust-Once).
Device-verified end to end incl. the platform store write.

IPC contract (ipc-contract R1): vendored + patched the YAP generator so a
regeneration reproduces the shipped wire with zero hand edits.

Touch events (input-bridging R3): doTouchEvent enabled behind JIHAD_TOUCH_EVENTS,
28-byte NpPalmTouchEvent header re-staged, double-activation suppressor.

Non-blocking toast (gre-widgets R5): daemon PostNotification + Luna subscription +
card toasts; device-verified.

Mojo settings entry (preferences-ui R4): app-menu Settings item + settingsUrl(),
per product-owner direction reversing the earlier no-mojo-settings instruction.
All three variants now have a settings entry.

Plus: opal machine kernel string corrected (shortloin), prebuilt-input manifests,
build-goanna-arm.sh pipefail fix, desktop test harnesses (prefsui, xpi-mismatch),
and extensive device verification recorded in context/impl/impl-device-2026-08-15.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 18:17:25 -04:00
NotAlexNoyleandClaude Opus 4.8 6cc623adde Licensing & Branding (R3 + R4 complete): engine branding strip + source docs
R3 (no protected trademarks shipped): build-goanna.sh now strips Pale Moon /
Basilisk / Moonchild branding from the engine defaults before building --
- all.js: blocklist (basilisk-browser.org) + captivedetect (palemoon.org) URLs
  neutralized; two comment URLs neutralized;
- nsAboutRedirector.cpp: about:credits target -> the Jihad credits URL;
- nsAppRunner.cpp: the dead MOZ_APP_NAME=="basilisk"/"palemoon" literals (always
  false for the xulrunner app) -> "n/a" -- behavior identical, literals gone.
Incremental rebuild + scan: libxul.so, jihad-browserserver, and goanna.js each
contain 0 branding strings; the adapter round-trip still PASSES. The UA product
was already "Goanna" (nsHttpHandler), not a protected mark.

R4 (MPL source availability): docs/ENGINE-SOURCE.md records the UXP origin +
pinned revision (b2594a4), every engine modification (patches 0001-0004 + the
branding strip), and that modified MPL files stay MPL with source available here;
LICENSE now points to it.

Licensing & Branding (R1-R5) is complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 14:29:46 -04:00