Skip to content

Latest commit

 

History

History
908 lines (640 loc) · 243 KB

VALIDATION.md

File metadata and controls

908 lines (640 loc) · 243 KB

Validation record

Desktop and mobile review implementation — October 20, 2026

Implemented Cere_Desktop_Mobile_Review_and_Implementation_Instructions.md (W01–W16) in commits 6637073..7f14fe4; the full record, with every finding, scenario, check, artifact hash and remaining owner step, is docs/REVIEW-VALIDATION.md. On the final tree, inside tools/test-virtual-desktop.sh: npm test passed 783 tests with 23 skips and no failures on Node 26.11.1, 24.22.0 and 26.8.2; ctest passed 4 of 5 (the GPU avatar test fails identically on unmodified HEAD); the offscreen cere-ui-check passed 100 with 9 skips and one failure (reviewTransitions, which fails identically on HEAD under the same load). Android: 76 unit tests, lint without errors on all three variants, four APKs, instrumentation on API 37 and 36 (30 tests each, no failures) and the paired phone-to-broker check passing 5 of 5 checkpoints on both. A staged install and the Arch package matched their source with build identity 7f14fe4, and the installed broker started, reported that build and shut down confirmed. Two full-suite runs stalled under heavy foreground load and one of them reported a failure of the new W10 script test; neither reproduced alone, and both are recorded there as unresolved. Nothing was pushed, published or installed.

Publication check — October 15, 2026: npm test passed 577 tests, with 1 optional skip and no failures; npm run typecheck and git diff --check passed. Editor recovery files and machine-specific validation JSON/service/geometry snapshots remain local and are excluded from Git, as are runtime logs. References to those local records below document the verification performed. The seam comparisons and twenty route storyboards are included in the repository; authoring sheets and other raw validation captures remain local.

Shared avatar scale and seam repair — October 16, 2026

Corrected the shared standing-animation artwork preparation path for Cere, Daemona, Jade, Nova, Soap, Brandy, Archy, Ghost, Violet, Leafy, Cachy, Usagi, Cynthia, Genga, Kippy, Pomni, Rem, Sarah, Sylva and Witty. This is the complete catalog read from assets/avatars.json.

The apparent upper-body zoom was baked into the surface atlases. Height-only source registration left different head/body proportions between authored drawings. tools/prepare-avatar-poses.mjs then crossfaded their lower bodies into the neutral legs, and repeated that splice after optical-flow interpolation. A differently sized or displaced torso consequently met fixed neutral legs across a soft horizontal band. All twenty avatars shared this path. Cere used a fixed blend band; the other nineteen used a height-relative band. The original software UI and native checks passed with these defective atlases, demonstrating why sole/bounds checks alone were insufficient.

The runtime audit covered AvatarPuppet, the shared skeleton, motion/controller integration, Pet.qml, GesturePlayer.qml, SurfaceMotion.js, MotionStage.qml, PortraitState.js, portraits and all motion definitions. Each current avatar renders one connected surface. Its fit scale is independent of animation, and its skeleton transforms are rigid. No separate torso scale, animation-dependent blur/layer, changing part z-order, stale scale or divergent per-avatar skeleton path caused this defect. Route reset and interruption behavior already worked; new checks now explicitly cover it.

Changes and safeguards:

  • Removed both neutral-leg splices. Complete drawings now register to the neutral head size and sole anchors before interpolation. The torso, hips and legs share one affine coordinate map, with no pixel mixture at their joints. Authored head tilt is retained. Open eyes and held blinks use the same registration.
  • Standing interpolation anchors the soles geometrically, including final 8-bit alpha rounding. It never pastes another pose's legs into the drawing. Pickup keeps its original suspended frames, flailing, free feet and release path.
  • All avatars now use connected-figure extraction. This removes faint sheet-divider lines admitted by the older rectangular crops, observed in Cere's blush and Nova's presenting sheet.
  • Sarah's celebration registration now uses explicit eye landmarks in the local source registry; the color detector had confused gold ornamentation with irises. Other source registration settings are unchanged.
  • Added tools/avatar-registration.h, the optional OpenCV authoring targets in CMake, and tests/avatar-registration.cpp. Regression checks cover scale recovery, sole anchoring, continuous joints, straight limbs, tilted heads, alpha quantization and invalid input. Native checks require an exact neutral render after every route, including after secondary motion and blinking. The surface-clock test covers 76 clips × 20 avatars and 2,160 interrupted route transitions, including reduced-motion resets.

All 6,120 prepared route frames were audited for clipping and standing sole alignment; all twenty pose sheets were visually reviewed across wave, thinking, presenting, celebration, blush, pickup and held blinking. The six routes include all aliases. Hover/click intensity, carry loops/reversal, smooth return and idle restoration are also exercised through the actual QML interaction path. The twelve portrait cells per avatar, neutral artwork, catalog, palettes, motion definitions and rig geometry are preserved. Carry frame pixels are compared against the original atlas snapshots.

Before/after evidence committed for review: native software blush captures, eight avatars, animated blush comparison / MP4, and all twenty route/blink storyboards. The animation compares Archy, Leafy, Cachy, Pomni, Rem and Witty through entry, full blush and return, at half playback speed. It uses preserved original and corrected packed frames; the static comparison uses actual native software captures. Original atlases, registration metadata, the initial dirty-worktree patch and baseline captures remain locally under build/avatar-seam-audit/before/ and native-before/.

Builds, executable test suites, rendered evidence and staged startup used the private desktop wrapper described below, with CERE_CAGE_BINARY="$PWD/build/witty-validation/virtual-deps/cage-build/cage". Source/diff inspection and some read-only pixel/coordinate diagnostics ran directly. Final rendering runs and package checks are scripted in build/avatar-seam-audit/run-accepted-validation.sh; exact command output, isolation records and exit codes are retained under build/avatar-seam-audit/accepted/.

Check Result and evidence
npm run build Passed; accepted/build.log.
node --test --test-concurrency=2 tests/*.test.ts and npm run typecheck 745 tests: 744 passed, one optional IndexTTS skip, zero failures; node-suite.log. Unaffected broker/UI logic checks were reused after the final offline artwork refinement.
node --test tests/avatar-surface-motion.test.ts Final packed assets: 38 passed, zero skips/failures; accepted/assets.log.
ctest --test-dir build --output-on-failure 4/5 passed: registration, motion, software avatars and QML. Offscreen OpenGL reproduces only the pre-existing wider-card readback/silhouette failure on all twenty avatars; accepted/ctest.log. Actual Wayland OpenGL passes below.
./build/cere-avatar-check "$PWD" on private Wayland/OpenGL All twenty passed, graphics API 3, exit 0; accepted/gpu-wayland.log. Includes exact neutral restoration after every route.
Software cere-ui-check connectedSurfacePoses avatarPointerReactions 5 passed, zero failures/skips, 708,507 ms. All twenty avatars at 100% and 200%: standing routes, interruption, blinking, reduced motion, hover/click strength, pickup, reversal and release; accepted/ui-software.log.
Wayland cere-ui-check connectedSurfacePoses avatarPointerReactions 5 passed, zero failures/skips, 810,121 ms. All twenty avatars at 100% and 200%, using actual private-seat pointer events; accepted/ui-wayland.log. The 40 pickup sequences contain 1,219 captures with no identical neighboring frames (accepted/pointer-capture-manifest.json); captures are under artwork/avatars/validation/seams/wayland/. The seat is empty after cleanup.
Software cere-ui-check fluidAvatarAnimation 3 passed; 49 updates/900 ms, 50 distinct positions, maximum step 0.14178°; accepted/ui-cadence.log. Run separately from competing render checks.
Software cere-ui-check assistantIdentitySettings avatarThemeSwitching pinnedConversationBubbles 23 passed, zero failures/skips; final/ui-settings.log. Identity, palette and bubble behavior are unchanged by the subsequent head-tilt correction.
python3 tools/install-user.py --prefix build/avatar-seam-audit/stage then node build/avatar-seam-audit/stage-smoke.mjs Passed: packaged UI/broker startup, all twenty selections, independent name, persisted Witty after private broker restart, clean process exits; accepted/stage-install.log, accepted/stage-smoke.log, stage-smoke.json.
Atlas/preservation/registration audit and git diff --check Passed: 6,120 unclipped route frames, exact sole anchors throughout all 5,100 standing frames, positive coordinate-map orientation for all 1,600 authored standing poses. All portraits, rigs, catalog, palettes and motions match their original hashes/data; all carry pixels are identical. accepted/assets.log, accepted/evidence.log, accepted/preservation-and-geometry.json; atlas SHA-256 values in accepted/generation-manifest.json.

Software UI commands use env QT_QPA_PLATFORM=offscreen:configfile="$PWD/tests/fixtures/offscreen-scales.json" QT_QUICK_BACKEND=software after tools/test-virtual-desktop.sh. Native software rendering is included in CTest. Final artifact commands are in build/avatar-seam-audit/run-artifacts.sh and final-evidence.mjs.

Rejected prototypes and failed diagnostics remain in the audit directory. Visual inspection rejected separate torso/ankle fits that bent Leafy's and Cachy's legs. A later coordinate-map audit rejected rotation unwinding that folded hair near the neck in Genga, Kippy and Sarah. The final implementation uses one affine body map and preserves head tilt, with regressions for both cases. An early concurrent cadence run missed its step threshold; the isolated final run above passed. These intermediate failures are not counted as accepted results.

Delivery remains project-only. Existing uncommitted work was preserved; the diffs in fourteen untouched tracked files match the initial snapshot exactly (accepted/worktree-preservation.txt). No installed client, broker, user service, real profile or desktop pointer was replaced, restarted or used for these checks. Physical mouse hardware and the installed session are intentionally outside this validation; the private Wayland seat exercises the production overlay. Human review should use the comparisons and full route sheets to judge authored pose aesthetics and optical-flow softness during fast limb/hair/cape movement, particularly pickup inbetweens.

Witty / twenty-avatar catalog — October 16, 2026

Added Witty under Settings → Companion → Avatar & colors, bringing the catalog to 20. The exact reference/witty.png was confirmed present and visually unambiguous before work; SHA-256: f6bdb77a59aae8a831a4184b8fcc2058cf1896b934e8fb0eb99cf9205ca9f671. The reference defines the charcoal complexion, spiked black armor, high ponytail, torn cape, spade ornaments, mint eye and violet accents. The mint X is a fixed facial mark; only the visible eye blinks. Repository instructions and the artwork → packed atlas → native puppet → QML motion/portrait → theme/settings → staged startup path were inspected before editing. The interrupted run's files were inventoried and retained.

Witty uses the existing pipeline: 306 prepared frames, six routes (wave, thinking, presenting, celebration, hands-to-cheeks blush and pickup), gentle hover and stronger click, blinking and smooth interrupted/reversed transitions, flailing arms and freely dangling legs with a smooth release, and twelve conversation-mood portraits. Her obsidian/mint/violet palette reaches menus, conversation cards, bubbles, message links, motion previews and live icons. The broker enum, native startup allowlist, catalog, settings search and acceptance checks include Witty. Avatar selection retains the independent name, personality and voice, including draft preservation, conflict-safe saving and persistence.

Built-in imagegen produced the source artwork and corrections from the reference. Files and prompts are under artwork/avatars/witty/, including carry-sheet.png, carry-sheet-prompt.txt, the five other gesture sheets and prompts, portrait-sheet.png, portrait-prompt.txt, extraction/eyelid sources, front.png, blink.png and registration.json. Selected sources are wave/thinking/present v4, celebrate/shy v5 and carry v3; rejected candidates and their prompts are retained. Runtime files are assets/witty-surface.png, assets/witty-surface-rig.json and assets/witty-portraits.png. The existing exclusion of local artwork/ from Git is preserved.

The resting image retains the reference's visible RGB exactly. The source registry removes the extraction's lavender fringe and normalizes authored standing sizes. A visual audit of all 96 gesture source cells found that a color-only iris search could mistake mint hair or the X for the eye. Witty now supplies explicit normalized eye landmarks for each cell, with closed-eye annotations for the stronger blush. Other avatars retain their existing registration path. A regression check verifies that held blinks change only the registered visible eye and leave authored closed-eye blush untouched. Six sheets each contain sixteen separate figures; the portrait sheet has twelve. The packed atlas is 6400 × 10120, below Qt's 256 MiB decoded-image limit, with no opaque edge clipping, identical standing foot baselines, moving carried legs and eight blink cells including neutral.

Visual review: packed poses, twelve portraits, visible-eye blinks and unchanged X, source landmarks, themes, and Wayland interactions at 100% / 200%. Thirty-frame pickup sequences and MP4s are retained in both pointer directories, plus software, native OpenGL and Wayland gesture captures under artwork/avatars/validation/witty/.

Test isolation

Every test run after the user's isolation instruction used tools/test-virtual-desktop.sh, including unit tests, builds/checks, artwork audits, software rendering, GPU rendering, pointer checks, settings checks and staged startup. The pre-interruption baseline rendering result is historical evidence, not a substitute for the isolated final checks.

The wrapper creates private user, mount, process, IPC, network and session-bus namespaces with Bubblewrap, a disposable home/runtime, a project-backed private /tmp, a headless Cage parent and a nested Hyprland compositor with a 1920 × 1080 virtual output. Only /dev/dri/renderD128 is exposed for GPU rendering; there are no DRM display-controller nodes, /dev/input, /dev/uinput, host Wayland/X11 sockets, host session bus, user profile or network access. Offscreen OpenGL uses the nested compositor's private Xwayland display and cookie. The configuration is tests/fixtures/virtual-hyprland.lua. Each invocation snapshots its runner so editing the harness cannot corrupt a running command's cleanup.

The compositor-level pointer acceptance path uses tests/acceptancepointer.h and the vendored MIT wlr-virtual-pointer protocol. Motion, buttons, hover, drag grabs and release are delivered by the private Wayland seat to the production layer-shell overlay. This is the isolated equivalent of the hardware-pointer check, not a claim that physical mouse hardware was tested. No kernel input device is created or host pointer moved. isolation.txt, monitors.json, config-errors.txt, devices-before.json, devices-after.json and command.exit are retained per run in build/witty-validation/; final pointer runs leave an empty seat.

This machine needed a project-local Cage 0.3.1 build. Its source and archive are in build/witty-validation/virtual-deps/; the single compatibility change is wlr_xdg_shell_create(server.wl_display, 5) → 6 in cage.c, satisfying the installed Aquamarine client. It was built with the local Meson environment (-Dman-pages=disabled) and Ninja, without installing system packages. To repeat the recorded checks in this workspace:

export CERE_CAGE_BINARY="$PWD/build/witty-validation/virtual-deps/cage-build/cage"
tools/test-virtual-desktop.sh bash -c 'node --test --test-concurrency=2 tests/*.test.ts'
tools/test-virtual-desktop.sh npm run typecheck
tools/test-virtual-desktop.sh npm run build
tools/test-virtual-desktop.sh ctest --test-dir build --output-on-failure
tools/test-virtual-desktop.sh ./build/cere-avatar-check "$PWD"
tools/test-virtual-desktop.sh ./build/cere-ui-check avatarPointerReactions:desktop-100
tools/test-virtual-desktop.sh ./build/cere-ui-check avatarPointerReactions:desktop-200
tools/test-virtual-desktop.sh ./build/cere-ui-check connectedSurfacePoses

Software UI commands additionally pass env QT_QPA_PLATFORM=offscreen:configfile="$PWD/tests/fixtures/offscreen-scales.json" QT_QUICK_BACKEND=software after the wrapper. The full-catalog command lists and evidence destinations are in build/witty-validation/run-acceptance.sh. run-registered.sh records the final artwork rechecks; CERE_TEST_AVATAR=witty limits avatar loops while pointer tests retain their Cere baseline. Invalid selections fail rather than silently checking zero avatars.

Results and delivery

Logs and audit scripts below are in build/witty-validation/:

  • npm run build: passed (build.log). The final UI harness rebuild passed (build-ui-resize-wait.log); existing unchecked-QFile-return warnings remain.
  • Full repository suite with node --test --test-concurrency=2 tests/*.test.ts: 744 tests, 743 passed, one optional IndexTTS skip, no failures in 220,571 ms (node-test-complete.log, full-suite-complete/command.exit = 0). This includes the explicit-eye regression. The focused art/identity/palette run also passed 65/65 (registered-art-tests.log). npm run typecheck and git diff --check passed (typecheck-complete.log, diff-check-complete.log).
  • Full CTest after final artwork: 3/4 passed (ctest-registered.log). Motion, software avatars and QML pass. Offscreen OpenGL reproduces only the documented wider-card readback/silhouette failure across the catalog; it is the pre-existing failure, not a new Witty regression. The private Xwayland display lets this check reach the same assertions instead of failing to create an OpenGL context.
  • Desktop Wayland/OpenGL: all twenty avatars passed, including the final landmark recheck (opengl-wayland-registered.log, registered-renderers/command.exit = 0). GPU rendering uses Mesa on Intel UHD Graphics, with a real scene graph on the virtual Wayland desktop.
  • assistantIdentitySettings avatarThemeSwitching pinnedConversationBubbles: 23 passed, no failures/skips (ui-settings-themes.log). Covers all twenty selections, independent name/personality/voice, local drafts, stale-save conflicts, compact save/discard, native and QML menus, message links, live icons and retained bubble contents. A fresh focused Witty theme run also passed 3/3 (ui-theme-witty-final.log).
  • Full software connectedSurfacePoses fluidAvatarAnimation: 4 passed, no failures/skips (ui-surface-software.log). All twenty avatars, five standing routes and both sizes pass playback, interruption, reduced-motion and input-region checks. Cadence: 51 updates / 900 ms, 52 distinct head positions, maximum sampled step 0.27632°. Full software pointer checks at both sizes passed 4/4 (ui-pointer-software.log).
  • Final software artwork/harness recheck, CERE_TEST_AVATAR=witty with connectedSurfacePoses avatarPointerReactions: 5 passed, no failures/skips (ui-software-resize-final.log). This includes Witty's five standing routes at both sizes and Cere/Witty pointer interactions at both sizes, after fixing the queued-resize wait.
  • Full Wayland overlay connectedSurfacePoses: 3 passed, no failures/skips (ui-surface-wayland.log). Full catalog pointer checks at 100% and 200% each passed 3/3 (ui-pointer-wayland-100-final.log, ui-pointer-wayland-200.log). Final Witty/Cere pointer rechecks passed 3/3 at each size (ui-registered-pointer-100.log, ui-registered-pointer-200.log); Witty's final gesture checks at both sizes passed 3/3 (ui-registered-surface-wayland.log). Hover reaches the gentle hands-to-cheeks pose, clicking intensifies it, pickup continuously reverses its flail cycle, and release retraces smoothly to hover/neutral without opening a click panel.
  • Source/packed audits passed (source-inspection-final.log, registered-eye-audit.log, packed-audit.json). Full-catalog asset tests check frame counts, bounds, planted feet, moving carried legs, blink geometry/silhouettes, portrait grids and complete palettes with 4.5:1 text / 3:1 boundary contrast. The added Witty test checks the actual registered blink location and the closed-eye endpoint.
  • python3 tools/install-user.py --prefix build/witty-validation/stage passed (registered-stage-install-session.log). stage-smoke.mjs passed (stage-persistence-final.log, stage-smoke.json): packaged UI startup 18,142 ms, all twenty selections accepted, independent name retained, Witty persisted through a private broker restart, UI and both private broker processes exited with status 0. State/runtime live inside the sandbox's private /tmp; no installed profile or service is involved.

Earlier attempts are retained rather than presented as passes. Default-parallel npm test runs hit the existing state-fan-out timing assertion and voice-import cancellation timing respectively (npm-test-initial.log, npm-test-parallel.log); the complete bounded-concurrency run passed without changing that application code or those tests. A serial attempt was interrupted and is not counted. An early mutable-runner version failed during cleanup after successful Qt results; the runner now executes a frozen copy. Early offscreen OpenGL lacked private Xwayland, and an initial staging attempt correctly rejected a foreign-owned ancestor in the namespace; both harness configurations were corrected. Faster focused software runs exposed an immediate MouseArea lookup racing a queued resize between slots/data rows; the harness now waits for matching window/MouseArea geometry. Full-catalog Qt results above are retained, and affected final artwork/harness checks are repeated separately.

Preservation audit: 498 prior artifact hashes, all nineteen prior catalog entries, palettes and source-registration records remain unchanged (preserved-catalog.json). artifact-manifest.json records 71 Witty/reference/runtime/catalog/source files. Existing unrelated work, including the documentation deletion and earlier expansion assets, is preserved.

Delivery is project-only. Passive process/service inspection confirms the installed UI PID 3508, overlay PID 4888, and broker PID 5517 remain unchanged; the broker is still active since 07:25:24 EDT (installed-processes-before.txt, installed-processes-after.txt, broker-before.txt, broker-after.txt). No Cage, test compositor, cere-ui-check or cere-avatar-check processes remain; the only Hyprland process is the original working desktop (desktop-processes-after.txt). The installed client and broker have not been replaced or restarted. For later activation, finish active conversations, exit the installed client, stop cere-broker.service, run python3 tools/install-user.py from this project, start the broker service, then launch ~/.local/bin/cere --show and choose Settings → Companion → Avatar & colors → Witty. These activation steps have not been performed.

Nineteen-avatar catalog — October 16, 2026

Added Cynthia, Genga, Kippy, Pomni, Rem, Sarah and Sylva under Settings → Companion → Avatar & colors. Before editing, reference/ was listed and the exact, unambiguous files cynthia.png, genga.png, kippy.png, pomni.png, rem.png, sarah.png, sylva.png and cachy.png were confirmed and visually inspected. Reference hashes are recorded in build/avatar-expansion-19-validation/reference-manifest.json.

Cachy is unchanged. Its current reference SHA-256 is 0c097473e219ce5046d79f4cef284579a5a75188be9605bb53d3f88c395606d5, matching the previous expansion manifest. All sixteen recorded Cachy source/runtime files also match, and its implemented appearance matches that reference. There is one Cachy catalog entry. All 112 files recorded for the previous seven-avatar expansion, the original twelve catalog entries and their palettes remain unchanged (preserved-catalog.json).

Each new avatar has 306 prepared animation frames, six routes (wave, thinking, presenting, celebration, timid hands-to-cheeks blush and pickup), gentle-hover and stronger-click holds, neutral and endpoint blinking, interrupted/reversed transitions, a flailing carry loop with freely moving legs and smooth release, twelve conversation portraits, and a complete reference-derived palette. The broker identity type, native startup allowlist, settings search, portrait checks and rendering checks now accept all nineteen choices. Name, personality and voice remain independent, with the existing persistent settings, draft and conflict protections. Exact search words now outrank partial words so Rem finds the avatar setting before “Remember…”.

Built-in imagegen produced the artwork from each matching reference's leftmost front view. Local authoring files are in artwork/avatars/{cynthia,genga,kippy,pomni,rem,sarah,sylva}/: extraction/eyelid images and prompts, front.png, blink.png, six gesture sheets and prompts, carry-sheet.png, carry-sheet-prompt.txt, portrait-sheet.png, portrait-prompt.txt, layout/gesture correction prompts, and registration.json. Rejected versions remain with their correction records. Runtime files are assets/{id}-surface.png, assets/{id}-surface-rig.json and assets/{id}-portraits.png. The existing exclusion of local artwork/ from Git is preserved.

Preparation registers only Rem's visible eye, preserving the fringe over the other. Her wave route normalizes an authored size change between rows. The existing silhouette splitter is shared by gesture preparation and the six portrait sheets with uneven gutters; the 4×4 result was verified byte-identical across 84 existing/new sheets (1,344 source frames). Portrait packing uses a common scale and clear margins. Original visible resting RGB is retained exactly. All 42 final gesture sheets contain sixteen separate figures. Standing feet use the original reference through keys and interpolated frames, including the bottom-edge sole samples in Sarah's shy source; packed output has no clipped opaque edges.

Visual evidence: all new poses, 84 portraits, and software / desktop OpenGL resting poses. Source/runtime hashes for 500 files are in build/avatar-expansion-19-validation/artifact-manifest.json.

Checks actually run; logs and local audit scripts are under build/avatar-expansion-19-validation/:

  • npm run build: passed (build.log). The final acceptance harness also rebuilt with cmake --build build --target cere-ui-check --parallel 4 (build-ui-final.log); existing unchecked-QFile-return warnings remain. npm run typecheck and git diff --check: passed.
  • npm test: 740 tests, 739 passed, one optional IndexTTS skip, no failures (npm-test.log). Includes all nineteen avatars, six routes, exact source pixels, 306 frames per atlas, fixed planted baselines, moving carried legs, unclipped frame edges, matching blink-cell geometry/silhouettes, complete portrait grids, new portrait gutters, identity persistence and palette contrast. The focused catalog/contrast run also passed 26 checks (catalog-palettes.log).
  • node build/avatar-expansion-19-validation/audit-source-sheets.mjs and node build/avatar-expansion-19-validation/audit-packed.mjs: passed (source-audit.log, packed-audit.log). All 84 new portraits have clear top/side edges and at least 45.8% opaque artwork per cell (portrait-grid.json).
  • ctest --test-dir build --output-on-failure: motion, avatar-software and QML passed. The offscreen OpenGL avatar check reproduced only the documented wider-card readback failure for all nineteen avatars (ctest.log); the same failure was observed for the original twelve before editing (baseline-rendering.log).
  • QT_QPA_PLATFORM=wayland QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl ./build/cere-avatar-check "$PWD": passed all nineteen avatars (opengl-wayland.log). Captures are under artwork/avatars/validation/expansion-19/native/.
  • QT_QPA_PLATFORM=offscreen:configfile="$PWD/tests/fixtures/offscreen-scales.json" QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check assistantIdentitySettings avatarThemeSwitching pinnedConversationBubbles: 22 passed, no failures/skips (ui-settings-themes.log). Covers all nineteen selections, independent name/personality/voice, draft preservation and stale-save conflicts, compact save/discard, QML/native menus, message links, live icons and retained bubble contents. Theme comparison and individual settings/chat/motion/icon captures are retained.
  • python3 tools/install-user.py --prefix build/avatar-expansion-19-validation/stage and node build/avatar-expansion-19-validation/stage-smoke.mjs: passed (stage-install.log, stage-smoke.log, stage-smoke.json). The packaged UI and private broker accepted all nineteen selections, preserved the independent name, persisted Sylva, and exited cleanly. Startup took 43,387 ms with a 60-second harness allowance. This used isolated state/runtime directories inside the validation folder.
  • With QTEST_FUNCTION_TIMEOUT=900000 and the software Qt environment above, ./build/cere-ui-check connectedSurfacePoses fluidAvatarAnimation: 4 passed, no failures/skips (ui-surface-software.log). All nineteen avatars × five standing routes × two sizes passed playback, interruption, reduced-motion and clickable-region checks. The cadence sample recorded 41 updates in 900 ms, 42 distinct head positions and a maximum sampled step of 0.26743 degrees. Software captures are retained. The initial sweep exceeded QtTest's default five-minute function limit after expansion; it was rerun with a fifteen-minute allowance (ui-surface-software-initial.log).
  • With QTEST_FUNCTION_TIMEOUT=900000, QT_QPA_PLATFORM=wayland, QT_QUICK_BACKEND=rhi, QSG_RHI_BACKEND=opengl and QT_QUICK_CONTROLS_STYLE=Basic, ./build/cere-ui-check connectedSurfacePoses: 3 passed, no failures/skips in 517,489 ms (ui-surface-wayland.log). All nineteen avatars passed gesture playback, interruption, reduced motion and input-region coverage at 100% and 200% on the production layer-shell host. All 209 captures are retained under Wayland gestures. The seven new characters were visually reviewed in 100% and 200% contact sheets: extended hands fit, standing feet remain planted, and no detached limbs or clipped opaque edges were observed.
  • With the software Qt environment and fifteen-minute function allowance, ./build/cere-ui-check avatarPointerReactions: 4 passed, no failures/skips in 412,871 ms (ui-pointer-software.log). All nineteen avatars passed hover, click, pickup, carry reversal and smooth release at both sizes; Cere also checks click thresholds, reduced motion and urgent-state priority. Captures are under software/pointer-{100,200}/.
  • With the live Wayland/OpenGL environment above, QTEST_FUNCTION_TIMEOUT=900000, CERE_CAPTURE_POINTER=1, and CERE_POINTER_EVIDENCE_ROOT="$PWD/artwork/avatars/validation/expansion-19/wayland", ./build/cere-ui-check avatarPointerReactions:desktop-100: 3 passed, no failures/skips in 281,724 ms (ui-pointer-wayland-100.log). All nineteen avatars passed hover, stronger click, pickup, carry reversal, and smooth release. 100% interactions, carry frames, individual captures and seven pickup videos are retained. All 30 captured frames differ for each new avatar (capture-manifest.json).
  • With the same live environment and capture settings, ./build/cere-ui-check avatarPointerReactions:desktop-200: 3 passed, no failures/skips in 321,898 ms (ui-pointer-wayland-200.log). All nineteen avatars passed the same interactions at 200%. 200% interactions, carry frames, individual captures and seven pickup videos are retained. The new avatars were visually reviewed at both sizes: hover intensifies on click, arms and legs move during pickup, and silhouettes remain inside the surface. All thirty captured frames differ for every new avatar at each size. Videos are assembled at 15 fps and do not establish a 60 Hz performance guarantee.
  • Final artifact integrity: all 500 source/runtime records, all eight requested references, and all 112 previous-expansion records still match their SHA-256 manifests (final-artifact-integrity.json).

The live harness now owns one test overlay at a time, suspending only its own automatically spawned child while the in-process host is active. The live pointer check uses a temporary /dev/uinput mouse for button and motion events, positions it with Hyprland’s cursor dispatcher, and waits for Qt to receive the requested coordinates. It restores the cursor and destroys the device afterward; software runs retain Qt events. Release under the real pointer checks the carry route reversing into hover, followed by return to neutral after pointer exit; the software case also checks the explicit landing motion after release outside the avatar. Earlier mixed native/synthetic attempts are retained in ui-pointer-wayland-initial.log, ui-pointer-wayland-single-host.log, ui-pointer-wayland-position-sync.log and ui-pointer-wayland-native-initial.log. Focused input diagnostics are retained as pointer-probe-*.log; the priority fixture now explicitly selects its session in each overlay so a second size cannot retain the previous fixture. These changes are confined to the acceptance harness.

Delivery is project-only. The installed client and running broker have not been replaced or restarted. Final verification retained UI PID 3508, overlay PID 4888, and broker PID 5517, with the broker still running since 07:25:24 EDT (installed-processes-before.txt, installed-processes-after.txt). No test processes or temporary pointer devices remain (runtime-cleanup.json). For later activation: finish active conversations, exit the installed client, stop cere-broker.service, run python3 tools/install-user.py from this project, start the broker service, then launch ~/.local/bin/cere --show. These activation actions have not been performed. Existing unrelated working-tree changes are preserved.

Seven additional reference avatars — October 16, 2026

Added Brandy, Archy, Ghost, Violet, Leafy, Cachy and Usagi, bringing Settings → Companion → Avatar & colors to twelve choices. Before editing, reference/ was listed and the exact, unambiguous files brandy.png, archy.png, ghost.png, violet.png, leafy.png, cachy.png and usagi.png were confirmed and visually inspected.

Each new avatar uses the existing connected-surface pipeline: 306 prepared frames across wave, thinking, presenting, celebration, timid hands-to-cheeks blush and pickup; separate gentle-hover and stronger-click holds; held-pose and neutral blinks; reversible transitions; a ping-pong flail and smooth release; twelve conversation portraits; and a complete matching palette for QML, native menus, message links, bubbles and live icons. Name, voice and personality remain independent. Broker validation, native startup validation, catalog/search and acceptance checks now include all twelve choices.

New artwork was generated with built-in imagegen using the matching reference as the visual source. Local authoring files are under artwork/avatars/{brandy,archy,ghost,violet,leafy,cachy,usagi}/: front.png, blink.png, extraction/eyelid sources and prompts, six gesture sheets and their prompts, carry-sheet.png, carry-sheet-prompt.txt, portrait-sheet.png, portrait-prompt.txt, and registration.json. artwork/avatars/sources.json holds registration inputs. The existing Git exclusion of artwork/ is preserved. Shipped runtime files are assets/{id}-surface.png, assets/{id}-surface-rig.json and assets/{id}-portraits.png.

Preparation now accepts selected reference IDs, derives default IDs from the catalog, supports the new iris colors and eye search regions, and separates figures by their opaque silhouettes when sheet gutters vary. It bounds extended hands, normalizes the two authored routes whose drawings changed size between rows, and preserves planted feet through optical-flow intermediates. Rejected incomplete grids were replaced before packing. Runtime atlas checks always run, including when optional local authoring sources are absent; only exact-source comparisons may skip.

Visual evidence: registered poses, all 84 new portraits, native captures and settings/theme captures. Every packed frame passed opaque-edge bounds and standing/carried-foot checks. Original visible resting pixels are retained; moving poses are generated artwork.

Checks actually run, with logs under build/avatar-expansion-validation/:

  • npm run build, followed by cmake --build build --parallel 4 and the capture-test rebuild cmake --build build --target cere-ui-check --parallel 4: passed (build.log, build-final.log, build-ui-capture.log). Existing unrelated unchecked-QFile-return compiler warnings remain.

  • npm run typecheck and git diff --check: passed (typecheck.log).

  • node --test tests/avatar-surface-motion.test.ts tests/avatar-animation.test.ts tests/assistant-identity.test.ts tests/avatar-settings.test.ts tests/settings-catalog.test.ts tests/qml-tokens.test.ts: 69 passed, no skips (focused.log). Includes all twelve avatars, exact visible source pixels, all six routes and new palette contrast checks.

  • npm test: 718 tests: 717 passed, 1 optional IndexTTS skip, no failures (npm-test.log).

  • ctest --test-dir build --output-on-failure: motion, avatar-software and QML passed; the offscreen OpenGL avatar check reproduced the pre-existing wider-card readback failure for the original five and the new seven (ctest.log). The same failure was recorded before editing (baseline-rendering.log, baseline-opengl-basic.log). After the final artwork bake, ctest --test-dir build -R '^(motion|avatar-software|qml)$' --output-on-failure: 3/3 passed (ctest-final.log).

  • QT_QPA_PLATFORM=wayland QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl ./build/cere-avatar-check "$PWD": passed all twelve avatars, graphics API 3 (opengl-wayland.log). The original five also passed this command at baseline (baseline-opengl-wayland.log).

  • QT_QPA_PLATFORM=offscreen:configfile="$PWD/tests/fixtures/offscreen-scales.json" QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check assistantIdentitySettings avatarThemeSwitching pinnedConversationBubbles: 15 passed, no failures/skips (ui-settings-themes.log). All twelve previews and saved choices, compact save/discard, independent name/voice/personality, stale-draft conflict handling, every new palette, message links, native menus, live icons and retained bubble contents were checked.

  • python3 tools/install-user.py --prefix build/avatar-expansion-validation/stage and node build/avatar-expansion-validation/stage-smoke.mjs: passed with the final runtime assets (stage-install.log, stage-smoke.log, stage-smoke.json). The packaged broker/UI started in private state/runtime directories, accepted all twelve selections, kept the custom name, persisted Usagi after shutdown and exited cleanly. Both final runtime logs are empty. A first repeat hit the harness’s 15-second startup deadline while other builds/checks were running; the final run allowed 45 seconds and observed startup in 18,977 ms. No installed process was used.

  • QT_QPA_PLATFORM=wayland QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl QT_QUICK_CONTROLS_STYLE=Basic CERE_CAPTURE_POINTER=1 ./build/cere-ui-check avatarPointerReactions: 3 passed, including setup/cleanup (ui-pointer-wayland.log). All twelve avatars passed hover, stronger click, pickup, carry reversal and smooth release; Cere also checks click thresholds, reduced motion and urgent-state priority. Qt pointer events were sent through the actual production layer-shell overlay. Existing Qt empty-path/focus warnings remain.

Desktop rest / hover / click / pickup and carry sequence samples were visually inspected. Each new avatar has 30 distinct consecutive captures with no frozen neighbors, recorded in the capture manifest. Recordings sample about 15 fps; they do not measure the renderer’s full clock rate. Pickup videos: Brandy, Archy, Ghost, Violet, Leafy, Cachy, Usagi.

  • QT_QPA_PLATFORM=offscreen:configfile="$PWD/tests/fixtures/offscreen-scales.json" QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check avatarPointerReactions: 3 passed, no failures/skips (ui-pointer-software.log). Hover, click, carry reversal and release passed for all twelve avatars in software rendering.
  • With the same software environment, ./build/cere-ui-check connectedSurfacePoses fluidAvatarAnimation: 4 passed, no failures/skips (ui-surface-software.log). All twelve avatars × five standing routes × two sizes passed playback, interruption, endpoint blinking, reduced-motion and clickable-region checks. Cadence measured 53 updates in 900 ms, 54 distinct head positions and a maximum sampled step of 0.17974 degrees. Software gesture captures are retained alongside the desktop captures.

The source/runtime SHA-256 manifest is build/avatar-expansion-validation/artifact-manifest.json. The existing installed UI/overlay remained running; cere-broker.service remained active with PID 5517 before and after validation (installed-processes.txt, installed-processes-after.txt). The only remaining check limitation is the pre-existing offscreen OpenGL readback failure described above; actual Wayland OpenGL and software rendering passed.

Delivery is project-only. The installed client and running broker were neither replaced nor restarted. For later activation, finish active conversations, exit the installed client, stop cere-broker.service, run python3 tools/install-user.py from this project, start the broker service and launch ~/.local/bin/cere --show. These activation actions were not performed. The project’s existing unrelated documentation deletion and additional reference images were preserved.

Undated statements, extraction default and candidate re-adjudication — October 16, 2026

The owner's two decisions after EV-01, as local commits on ui-overhaul: c5059bd accepts a grounded statement that names no time, df526ae makes glm-5.3-flash:cloud the code default, 34e5da7 adds cere memory readjudicate for pending extraction candidates, and beeedcc records the evaluation. The extraction prompt is unchanged. Nothing was pushed, installed or restarted; four conversations were working when checked.

Checks actually run after the last code change (logs under ~/.cache/cere-readjudication/):

  • npm run typecheck and git diff --check passed.
  • CERE_TTS_DISABLED=1 npm test: 698 tests, 696 passed, 2 skipped, none failed. The skips are the opt-in IndexTTS check and the source-pixel avatar check. After two test-only additions, node --test tests/review-memory.test.ts tests/memory-curation.test.ts passed 29 of 29.
  • c5059bd and df526ae were each checked as committed, with the typecheck and the memory, extraction and knowledge tests (50 of 50 each, the settings-catalog test included for df526ae), so each commit stands alone.
  • Negative controls, each a scratch edit: mapping an undated statement to an approximate time again fails both undated-statement tests; keeping a stored candidate's approximate precision fails the re-adjudication test; and a lineage role that erasure follows fails its expiry check.
  • QT_QPA_PLATFORM=offscreen:configfile=$PWD/tests/fixtures/offscreen-scales.json QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check settingsSectionNavigation extractionModelSelection: 4 passed. The native build, ctest and the full UI run were not repeated: no C++ changed, and the UI loads QML from the source tree.
  • EV-01 for glm-5.3-flash:cloud at its recorded digest, with owner approval: 32 of 32 accepted proposals correct (gate passed), predicate precision 88.9% (gate failed), nothing accepted from the 10 statements that hold nothing; see the evaluation.
  • Re-adjudication on private VACUUM INTO copies of the live store (deleted afterwards): the dry run considered the 35 pending candidates, accepted none and rejected all 35 as ungrounded. A full run on a second copy made the same decisions and passed PRAGMA integrity_check, and a second pass found nothing pending.

Live state: before any other step, the store was backed up through the running broker with cere memory backup --output ~/.local/state/cere/memory-backups/before-undated-rule-2026-10-16.sqlite (revision 98841; the copy passed PRAGMA integrity_check), and the current erasure registry was copied beside it. The live candidates have not been re-adjudicated: the installed broker predates readjudicate, and installing follows the safe order in §9.4 of the next-stage plan while no conversation is working. After that, run cere memory readjudicate --dry-run, then cere memory readjudicate --output with a new backup path. Nine of the 35 candidates reach their seven-day expiry on October 17 (from 13:04 EDT) and leave without a recorded decision if this waits.

PyPersona next stage — October 16, 2026

Implemented from prompts/Cere-PyPersona-Next-Stage-Plan.md on ui-overhaul as local commits, from a0b956e to fa1e763; nothing was pushed, installed or restarted. The owner authorized the commits (D1), kept artwork/ deleted (D2) and authorized the extraction evaluation (D5). For the remaining decisions the plan's recommendations were taken: withheld recall does not skip capture (D3); collection Markdown follows the vault privacy rule (D4); the newest two pre-migration backups are kept, for at most 14 days, and clearing memory deletes them (D6). NF-02 and README feature documentation were not added (D7, D8), A05 task binding stays deferred (D9), and nothing was reinstalled (D10).

Delivered: S1 (four commits keeping the owner's screenshot work, the plans and the artwork/ removal apart from slices 0–5), RC-01, S3, S4, S5, RC-02 to RC-07, RC-12, RC-13 and EV-01. Not built, as the plan decides: A03, M11, A05 task binding, M10's recognition interface, slice 6, the A02 HTTP transports, RC-08 to RC-11, NF-02 and EV-02, and the optional parts of RC-04 (CLI file-edit events) and RC-05 (a model-facing nudge).

Checks actually run after the last code change (logs under ~/.cache/cere-pypersona/nextstage/):

  • npm run typecheck and git diff --check passed.
  • CERE_TTS_DISABLED=1 npm test: 696 tests, 694 passed, 2 skipped, none failed. The skips are the opt-in IndexTTS check and the source-pixel avatar check, which now skips because the source art is outside the repository. With another project compiling (load average up to 17), four existing timing-sensitive tests each failed once and then passed alone and on a full rerun: F-005 and F-004 in tests/review-service.test.ts (a recall racing a memory invalidation, OUTCOME_UNKNOWN), a tests/remote.test.ts WebSocket event after close, and one stall in tests/audio-devices.test.ts.
  • cmake --build build --parallel 8 had nothing to rebuild. ctest --test-dir build --output-on-failure: motion, avatar-software and qml passed; the GPU avatar check failed "wider cards must preserve silhouette and ground", as at baseline.
  • QT_QPA_PLATFORM=offscreen:configfile=$PWD/tests/fixtures/offscreen-scales.json QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check: 81 passed, 2 failed, 9 skipped in 872 s. reviewTransitions failed as at baseline. collectionsExportAndPackages did not find the conversation's More button; it passed alone and in its full-run order after memoryCurationPinsAndTimeline and behaviorStylePostureAndChecks. The 9 skips need a live compositor or Spotify. Earlier, after each change: localModelsTranscriptionAndNotes, collectionsExportAndPackages, graphInspectorPolicyForgetAndCorrection (extended with the pre-migration backup line), memoryCurationPinsAndTimeline, responsivenessMeasurements, behaviorStylePostureAndChecks (posture count 6 to 7 for Without memory), behaviorPresetsAndPreview, requiredChecksAndOutputSections, projectTaskLifecycle and toolServerSettings passed.
  • node benchmarks/memory/nl-baseline.ts and node benchmarks/memory/document-baseline.ts reproduced the recorded figures exactly.
  • The request-equivalence check is now tests/context-plan.test.ts (S3). It and the migration pin fail on a one-character change, checked in a scratch copy.
  • EV-01 ran the 50-statement corpus against glm-5.3-flash:cloud, nemotron-3-super:cloud and gpt-oss:20b-cloud; see the evaluation. The preserved extraction-results.json is unchanged.

Older entries cite artwork/… paths for logs and captures; that directory was moved out of the repository on October 15. During this session, at 07:37 EDT, docs/Cere_Graph_Memory_Implementation.md was moved out of the working tree by other work (a copy is in ~/Pictures); that deletion is not part of these commits.

PyPersona enhancement plan, slices 0–5 — October 15–16, 2026

Implemented from prompts/Cere-PyPersona-Enhancement-Plan.md on ui-overhaul at 0837f91, and committed on October 16 as 6e6aa8a. The in-flight screenshot and documentation edits and the removal of artwork/ are preserved, in their own commits (a0b956e, 83b02d5). Slices 0–4 are complete. Slice 5 adds M22 and M14; A03, M11 and slice 6 are deferred. The per-proposal record and every log are local, under ~/.cache/cere-pypersona/ (PROGRESS.md, baseline/ and final/).

Baseline before any change (clean git archive HEAD tree): npm test 578 tests, 576 passed, 1 skipped, 1 failed (tests/avatar-surface-motion.test.ts, which cannot read artwork/avatars/cere/registration.json since artwork/ moved). ctest passed 4/4. The offscreen cere-ui-check had 65 passed, 1 failed (reviewTransitions) and 9 skipped.

Checks actually run after the last change:

  • npm run typecheck and git diff --check passed.
  • CERE_TTS_DISABLED=1 npm test: 671 tests, 669 passed, 1 skipped, 1 failed. The failure is the same artwork test as at baseline.
  • cmake --build build --parallel 8 passed for every target.
  • ctest --test-dir build --output-on-failure: motion, avatar-software and qml passed. The GPU avatar check failed its "wider cards must preserve silhouette and ground" geometry for all five avatars. The untouched baseline tree fails identically on the same run date after passing at the start of the session, so the cause is the state of the GPU render path rather than these changes.
  • QT_QPA_PLATFORM=offscreen:configfile=$PWD/tests/fixtures/offscreen-scales.json QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check: 82 passed, 1 failed, 9 skipped. The failure is reviewTransitions, as at baseline; the 9 skips need a live compositor or Spotify. Seventeen slots are new: behaviorPresetsAndPreview, sendKeysRecipesAndContext, projectTaskLifecycle, memoryCurationPinsAndTimeline, behaviorStylePostureAndChecks, collectionsExportAndPackages, localModelsTranscriptionAndNotes, requiredChecksAndOutputSections, searchSourcesForOneMessage, compatibleEndpointConversation, toolServerSettings, customToolEditor, audioDeviceChoosers, voiceCommandReview, responsivenessMeasurements, backgroundWorkIndicator and scheduleReviewedRecipe. Each new screen was captured and inspected.
  • Request equivalence (A01): for a fixed Ollama turn with personality, memory, telemetry, web search and a tool round, the request payloads are byte-identical to those of the untouched HEAD tree captured on the same date, so turns that choose none of the new features send exactly what they sent before.
  • Retrieval baselines: node benchmarks/memory/nl-baseline.ts and node benchmarks/memory/document-baseline.ts. Their figures, and the floors their tests pin, are in docs/memory/evaluation.md.

Existing tests changed deliberately: the provider counts in apiProviderSetup and ollamaConversation include the compatible endpoint, with 8 providers and 7 handoff targets. The shared API adapter tests now also run against the compatible endpoint. The Review posture's expected ceiling now includes extension tools. markdownMessages injected its fixture row before the reload that follows selecting a conversation had finished, so the reload could replace the row mid-test. One full run crashed at tests/ui.cpp:1078 because of this; the slot now waits for both resets, as avatarThemeSwitching already did. On this host ananicy-cpp renices every node process to 16, so the background-priority test compares against the test process's own priority.

Not established: native file dialogs cannot be driven offscreen (Save as…, Import a package…, Add folder…). Their broker side is covered by tests and the dialogs' callers by RPC-level UI checks. The microphone was not recorded, since a test would capture the host's microphone; dictation is covered with a recorder stand-in in the broker tests. This session installed nothing and restarted nothing. The tree was installed afterwards, at 21:28 EDT on October 15: the broker and interface restarted then, and the live memory store applied migration 5 (retention_pins) at 21:28:53, without a backup.

Documentation screenshots — October 15, 2026

screenshots/ holds 41 PNG images (5.7 MiB) of the real interface: desktop scenes, the compact panel, the workspace, dialogs, every Settings category, the five avatars, their themes and the six gestures. screenshots/README.md is the gallery. The README, docs/tts.md, docs/workspace-telemetry.md, docs/mobile/SETUP.md and docs/memory/operations.md embed the relevant ones.

tools/screenshots/run.sh regenerates them. It seeds a demo profile (seed.ts), starts scripted Codex, Claude Code, AntiGravity and Ollama fixtures plus hyprctl, wpctl and busctl shims (fixture.mjs), and runs the new cere-screenshots target (capture.cpp) offscreen against one 1920×1080 virtual output (screens.json). Everything runs in private user, mount, process and network namespaces with /home/demo on a tmpfs, so no real profile, compositor, media player, notification service, provider account or network is reached. Desktop scenes draw Cere's own pet, panel and bubble windows at their real positions over a generated wallpaper.

Checks actually run:

  • cmake --build build --target cere cere-screenshots passed.
  • npm run typecheck passed, including tools/screenshots/seed.ts.
  • CERE_SCREENSHOTS_DIR=$PWD/screenshots tools/screenshots/run.sh: 23/23 passed (21 capture slots plus setup and cleanup) in 182 s. Each image was inspected; earlier runs found and fixed reused fixture item IDs, which had overwritten a reply after Cere restarted the Codex process.
  • tools/screenshots/run.sh settingsPages into a scratch directory: 3/3 passed, writing its 12 images alone.

Seen in the captures and left unchanged: small grey marks, for example before the approval bubble's title, likely because qml/CScrollBar.qml shows its 8 px thumb whenever size < 1, including 0 before content is measured; and qml/Shell.qml reports one busy session as "1 conversations working", a state the screenshots avoid. The demo's Health and recovery dialog lists the API providers as network problems because the demo has no network or API keys.

Hover blush, pickup animation and Companion settings — October 15, 2026

All five reference avatars now use a gentle held blush on hover and a stronger click reaction. Clicking still toggles chat. Both strengths share one sequence: click deepens the current drawing, then eases back to the hover pose without crossing neutral. Ordinary work can continue behind that direct reaction; approvals, errors, disconnects and dragging retain priority. Quiet, hidden, reduced-motion and zero-intensity policies remain authoritative.

Pickup uses new built-in imagegen artwork for Cere, Daemona, Jade, Nova and Soap: alternating arm flails, bent knees and freely dangling feet. The shared animation clock cycles the suspended drawings, eases rotation around the actual grab point, fades the ground shadow and retraces the route on release. Six illustrated routes provide 306 prepared frames per avatar. The native bound is 384 frames; the largest decoded atlas is 259,072,000 bytes, below Qt's 256 MiB allocation limit. The atlas cache still retains one decoded source.

tools/prepare-avatar-poses.mjs separates touching sheet halos from opaque body cores, preserves whole horns/boots across uneven source rows, fits each carry route uniformly around its eye anchor and removes small disconnected optical-flow debris. Initial checks caught clipped feet and a stray interpolated boot fragment; the final frame checks pass. PNG replacement is atomic. --carry-only reuses the five existing gesture routes when refining pickup art. Selected source sheets and prompts are artwork/avatars/{id}/carry-sheet.png and carry-sheet-prompt.txt; rejected refinement prompts are outside the project under /tmp/cere-interactions-before/rejected-refinements/.

Avatar cards and their save/discard controls are now in Settings → Companion → Avatar & colors. Personality saves only name/style, and Companion saves only the avatar. Both retain identity conflict checks and unsaved-draft preservation. Search and palette links route avatar controls to Companion.

Checks actually run (logs under artwork/avatars/validation/interactions/):

  • cmake --build build --target cere cere-motion-check cere-avatar-check cere-ui-check --parallel 3 passed (build.log; later test-only rebuild in build-ui-final.log).
  • node --test tests/avatar-surface-motion.test.ts tests/avatar-animation.test.ts tests/assistant-identity.test.ts tests/avatar-settings.test.ts tests/settings-catalog.test.ts: 42 passed, node.log. Includes smooth strength changes, interrupted/reversed carry loops, damped grab-pivot dynamics, original neutral pixels, all prepared frame bounds, free carried feet and held-pose blink cells.
  • ctest --test-dir build -R '^(motion|qml)$' --output-on-failure: 2/2 passed, logic-rendering.log. ctest --test-dir build -R '^(avatar|avatar-software)$' --output-on-failure: 2/2 passed, avatar-rendering.log. Native GPU/software render checks include all six routes for all five avatars and the bounded frame loader.
  • python3 tools/install-user.py --prefix /tmp/cere-interaction-stage and node /tmp/cere-interaction-stage-smoke.mjs passed: packaged broker/UI startup, all five selections, empty private runtime logs (stage-install.log, stage-smoke.json).
  • node --test tests/emoticon-state.test.ts: 7/7 passed, emoticon.log. Explicit pointer reactions now own the badge ahead of ordinary task status. The tooltip only appears over the badge itself, so hovering the body does not cover the blush. After that fix, ctest --test-dir build -R '^qml$' --output-on-failure passed (qml-final.log).
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check avatarPointerReactions: 3/3 passed, including setup/cleanup (avatar-pointer-software.log). All five avatars passed hover, click, pickup and release; Cere also checks the drag threshold, click-to-hover continuity, a full carry reversal, reduced motion and urgent-state priority.
  • QT_QPA_PLATFORM=wayland QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl QT_QUICK_CONTROLS_STYLE=Basic CERE_CAPTURE_POINTER=1 ./build/cere-ui-check avatarPointerReactions: 3/3 passed on the actual always-on-top layer-shell overlay (avatar-pointer-wayland-overlay-opengl.log). The earlier ordinary-window test could be occluded and lose compositor frame callbacks; the final test uses the production overlay surface. Qt reports existing text-input focus warnings in the harness. All 39 consecutive carry captures differ, and visual review found no clipped limbs, disconnected fragments or frozen frames. Captures sample approximately 15 fps, not the renderer's full frame rate.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check assistantIdentitySettings and the same command with avatarThemeSwitching: 3/3 and 6/6 passed, including setup/cleanup (assistant-identity-software.log, avatar-theme-software.log).

Final registered poses: rows Cere/Daemona/Jade/Nova/Soap; columns rest, gentle hover, stronger click, then five phases of pickup.

All five avatars in the Wayland overlay · Captured pickup animation.

Delivery: the validated native host, nine QML/JS files and twelve motion/atlas files are installed under ~/.local. The UI was refreshed; the broker remained PID 189774. All 22 installed hashes match the staged package, and avatar/name/personality, motion policy, scale, position and visibility are unchanged. The installed binary has the same ELF build ID as build/cere; CMake changes its runtime library path to $ORIGIN. Installed desktop capture, file hashes, preserved settings, and runtime log. The runtime reports existing Qt empty-path, portal-registration and text-input-focus warnings, with no QML or avatar-load errors. An initial copy raced the old executable's shutdown and returned ETXTBSY before replacing any file; the successful install uses atomic file replacement.

The passing Wayland acceptance above sends Qt pointer events to the actual layer-shell surface. An additional standalone compositor virtual-pointer probe reached hover but could not deliver its synthetic click; it did not establish a physical-input pass. Its script/diagnostics remain in /tmp/cere-interaction-desktop.mjs and /tmp/cere-interactions-before/compositor-probe/. It did not change the user broker or settings.

Five reference avatars and connected gestures — October 15, 2026

Replaced the retired cutout/sprite pipeline with reference-derived connected surfaces for Cere, Daemona, Jade, Nova and Soap. Each has wave, thinking, presenting, celebration and timid hands-to-cheeks blush routes, 255 prepared gesture frames, endpoint blinks and twelve portrait expressions. The original reference RGB is retained in the resting figure; generated gesture drawings use uniform scaling and planted feet. The original Cere head proportions are preserved. New art was created with built-in imagegen; sources, extraction/eyelid edits and prompts are retained under artwork/avatars/{id}/.

Runtime changes include reversible gesture transitions, one shared animation clock, bounded lazy atlas/frame caching, silhouette hit regions covering every route, and Soap selection/palette support. Quiet/reduced motion and zero intensity retain the original still. The 74 intent clips remain; they share five illustrated routes and continuous micro-acting rather than pretending to be 74 separately drawn animations. motions.json now retains only semantic pose metadata; deleted sprite files are no longer dependencies. Settings search uses token prefixes so searching tan finds Soap’s avatar control instead of matching inside assistant.

Checks actually run:

  • cmake --build build --target cere cere-avatar-check cere-ui-check --parallel 4 passed; artwork/avatars/validation/build.log. After migrating the obsolete sprite integrity test, cmake --build build --target cere-motion-check --parallel 4 passed; motion-build.log.
  • node --test tests/avatar-surface-motion.test.ts tests/avatar-animation.test.ts tests/assistant-identity.test.ts tests/avatar-settings.test.ts tests/settings-catalog.test.ts: 38/38 passed, node.log. This includes original visible pixels, fixed feet and unclipped bounds for every prepared frame of all five avatars, route interruption and accessibility policy. The first pass exposed a foot-baseline metadata mismatch and search ranking issue; both were corrected before the passing run.
  • ctest --test-dir build -R '^(motion|avatar|avatar-software|qml)$' --output-on-failure: 4/4 passed, rendering.log. Native GPU/software captures cover all five avatars and gesture endpoints, blink cells and repeated frame changes. The motion test now verifies semantic pose references and timelines; native surface tests own raster integrity.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software ./build/cere-ui-check connectedSurfacePoses: 3 passed, 0 failed including setup/cleanup, ui.log. All five avatars × five routes × two scales passed silhouette/input-region, endpoint, interruption, blinking and reduced-motion checks. An initial preview failure was an asynchronous settings race in the test; it now waits for the persisted motion policy before requesting shy.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check fluidAvatarAnimation assistantIdentitySettings: 4 passed, 0 failed including setup/cleanup, ui-cadence-settings.log. Animation cadence, avatar switching, name/settings persistence and draft behavior passed. Offscreen window-mask warnings are recorded.
  • npm run typecheck passed, typecheck.log. The renamed tools/interpolate-avatar-poses.cpp compiled with OpenCV 5 and explicit video/imgcodecs/imgproc/core libraries; interpolator-build.log.
  • python3 tools/install-user.py --prefix /tmp/cere-avatar-set-stage passed, stage-install.log. node /tmp/cere-avatar-stage-smoke.mjs started the packaged broker and UI in private state/runtime directories and switched through all five avatars, including Soap; stage-smoke.json. Both private runtime logs were empty. Editor swap files are excluded from installation.

Actual Wayland desktop acceptance used a private broker and overlay with the production binary, ordinary settings.update and ui.animate RPC, and grim crops tracked by the overlay PID on every frame. All five neutral and shy poses were inspected at 192×208. No clipping, detached joints, doubled hands or visible smearing was observed at that desktop size. Cere’s recorded interrupted ponder-to-shy route reverses through neutral before entering the new pose. Capture sampling is approximately 15 fps; it is evidence of desktop rendering, not a measurement of the renderer’s 60 Hz clock. Private processes exited cleanly; the user broker retained PID 90342.

Delivery: the new native UI, QML, canonical assets and broker avatar enum are installed under ~/.local. Only the UI was restarted (ui.quit {stopTasks:false}); the running conversation, avatar selection, name, size and position were preserved. Soap’s broker support loads on the next broker restart. The current broker still has the four-avatar enum in memory and was deliberately kept running because restarting it would interrupt this task. Once active work is finished, systemctl --user restart cere-broker.service activates the installed five-avatar enum. All five selections were already verified against the staged new broker. Existing user-profile startup produced Qt file/portal/focus warnings; no avatar loading or rendering failure was observed.

Cleanup removed 609 retired avatar files (144.7 MiB) from the project and 28 obsolete installed runtime files. A reversible copy and SHA-256 manifest are outside the project at /tmp/cere-avatar-retired-20261015/; the preceding installation is backed up at /tmp/cere-avatar-install-20261015/previous/. Original reference/ images, current authoring sources and the user’s workspace assets/.animations.json.kate-swp were preserved. Historical sections below describe older revisions and may link to retired files. Generated poses are new artwork; the pixel-preservation guarantee applies to the resting reference figure, not every generated moving frame.

Waist and hip continuity — October 14, 2026

Corrected the four rig registrations after the common proportion change left a second pinch below the torso. Each outfit now places its hip artwork behind the flared torso hem and retains enough of the existing atlas crop to overlap the thighs. Crop extensions preserve source-pixel scale; Daemona stops before the next row's boot artwork. No raster artwork changed in this follow-up. The shared torso is now a child of the pelvis, so hip drop carries the upper body too. Hip clothing uses the torso transform, keeping its overlap fixed during breathing and tilt while the legs remain independently jointed.

tests/avatarpuppet.cpp now checks the painted silhouette across the hem, torso/head movement with the pelvis, fixed clothing overlap, and painted hip/thigh overlap across tilt, breath and leg limits. It also captures magnified rest/tilt/breath waist strips. The old registrations fail these new checks for all four avatars: the secondary inward pinch measured 7.25–9 reference pixels. The corrected registrations pass the 1.5-pixel allowance.

Checks and artifacts in /tmp/cere-waist-study:

  • cmake --build build --target cere-avatar-check --parallel 4 passed (build-regression.log).
  • CERE_PUPPET_TEST_SOFTWARE=1 QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software ./build/cere-avatar-check "$PWD" passed for all four avatars (regression.log). The same command against /tmp/cere-waist-study/before-root failed as expected (before-regression.log).
  • QT_QPA_PLATFORM=xcb QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl QSG_RENDER_LOOP=threaded ./build/cere-avatar-check "$PWD" passed for all four avatars (gpu-native.log). Software and native GPU waist captures were visually inspected. The earlier offscreen OpenGL capture limitation remains; this run used native XCB for GPU validation.
  • CERE_TTS_DISABLED=1 node --test tests/avatar-animation.test.ts tests/assistant-identity.test.ts: 27/27 passed (node-tests.log). ctest --test-dir build -R '^(motion|qml)$' --output-on-failure: 2/2 passed (ctest.log).
  • python3 tools/install-user.py --prefix /tmp/cere-waist-study/stage and node /tmp/cere-waist-study/stage-smoke.mjs /tmp/cere-waist-study/stage passed. The packaged app switched all four avatars in an isolated profile; its runtime log was empty. All four staged rig files match source hashes (stage-manifest.json). The live installation was not updated.

preview.html contains before/after rest captures and the new waist strips. after/ preserves all pose, motion and waist captures from both backends. git diff --check passed for the affected files.

Shared avatar proportions and consistent playback — October 14, 2026

The four avatars now resolve through native/avatardefinition.h. One base proportions profile makes body/limb geometry 16% shorter and 10% wider around the common ground anchor. Faces, expression overlays and back hair keep their authored geometry. Daemona, Jade and Nova supply named joint-registration offsets instead of duplicate skeletons. This resolved definition is shared by the desktop, selection cards and input masks.

GesturePlayer samples the selected avatar’s pose/channel catalog and reselects only after that catalog updates. A separate native avatarChanged notification prevents unrelated state snapshots from restarting gestures. Reduced-motion definition changes repaint without advancing the animation clock. Motion previews use the configured name and tolerate an empty program; existing native windows receive the selected avatar’s icon explicitly.

Validation and artifacts:

  • cmake --build build --parallel 4 passed, /tmp/cere-avatar-system/build-final.log. The final test-only rebuild, cmake --build build --target cere-avatar-check --parallel 4, passed, build-avatar-final.log in the same directory.
  • CERE_TTS_DISABLED=1 node --test tests/avatar-animation.test.ts tests/assistant-identity.test.ts: 27/27 passed, /tmp/cere-avatar-system/node-tests.log.
  • ctest --test-dir build -R '^(motion|avatar-software|qml)$' --output-on-failure: 3/3 passed, /tmp/cere-avatar-system/ctest-supported-final.log. Native assertions cover one-time resolution, unchanged head artwork, invalid joint overrides, foot alignment, compact geometry, all 32 poses, unclipped silhouettes and aspect fitting. The same production window switches across all four avatars, matching application behavior. The fitting check uses actual device pixel ratio and allows a one-pixel rasterization difference; a tiling compositor may refuse requested window dimensions.
  • QT_QPA_PLATFORM=xcb QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl QSG_RENDER_LOOP=threaded ./build/cere-avatar-check "$PWD": passed for all four avatars, /tmp/cere-avatar-system/gpu-native-final.log. Native-window GPU pose/gesture sheets were visually inspected, along with the software sheets and selection/settings captures. The standalone gallery is /tmp/cere-avatar-system/preview.svg; source captures are /tmp/cere-motion-evidence/ and /tmp/cere-ui-evidence/.
  • With QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic, ./build/cere-ui-check assistantIdentitySettings avatarThemeSwitching -o /tmp/cere-avatar-system/ui-identity-final.log,txt passed 6/6 cases, and ./build/cere-ui-check fluidAvatarAnimation livelyPreviewAndSharedMood -o /tmp/cere-avatar-system/ui-motion-final.log,txt passed 4/4 cases, including setup/cleanup. These exercise save/discard/conflict behavior, all avatar themes, native icons, custom pose/channel sampling, same-ID definition replacement, reduced-motion repainting and unchanged gesture time after a state refresh. The identity test waits for the previous save to unlock the name field before editing again.
  • python3 tools/install-user.py --prefix /tmp/cere-avatar-system/stage passed. node /tmp/cere-avatar-system/stage-smoke.mjs /tmp/cere-avatar-system/stage passed isolated packaged startup and switching through all four avatars; /tmp/cere-avatar-system/stage-smoke.log. Changed assets match source byte-for-byte and the installed ELF build ID matches the build (installation rewrites its RPATH); /tmp/cere-avatar-system/stage-manifest.json. The captured packaged runtime log is empty.

Limitation: the default offscreen OpenGL test intermittently produces missing/streaked readback regions on this machine (Qt 6.12.0, NVIDIA 615.78.08). Both basic and threaded loops exhibited failures; explicit resource cleanup and a shared test window did not resolve them. The new clipping checks correctly reject those captures. This is not claimed fixed, and the full default CTest run is not reported as passing. Native XCB/threaded OpenGL and offscreen software checks above passed. No Wayland layer-shell placement/input-region acceptance was run.

Delivery: workspace changes and the staged package are ready. The installed user application and broker were not replaced or restarted.

Avatar proportions and joint alignment — October 14, 2026

Refined all four production puppet atlases with built-in imagegen and registered their cutouts individually in assets/{cere,daemona,jade,nova}-rig.json. The silhouettes have narrower waists, rounded thighs, longer legs, tapered boots and smaller head/body proportions. Thighs now inherit hip motion; knee and elbow pivots sit inside painted overlap on both adjoining parts. Facial overlays cover the face rather than replacing the entire hair silhouette. Atlas crop boundaries exclude neighboring limb fragments. The existing animation channels, 32 poses, reference size, avatar selection, palettes and portrait sheets are retained. artwork/avatar-proportions-prompts.txt records the four output paths and all generation/refinement prompts; generated alpha was preserved.

Checks run:

  • cmake --build build --parallel 4: passed; /tmp/cere-avatar-redesign/build.log.
  • CERE_TTS_DISABLED=1 node --test tests/avatar-animation.test.ts tests/assistant-identity.test.ts: 27/27 passed; /tmp/cere-avatar-redesign/animation-identity-final.log. After the final boot crop refinement, CERE_TTS_DISABLED=1 node --test tests/assistant-identity.test.ts: 4/4 passed; /tmp/cere-avatar-redesign/artwork-final.log. Nova's first generated sheet failed the zero-alpha corner assertion; imagegen alpha cleanup corrected the artwork without relaxing the test.
  • ctest --test-dir build --output-on-failure: 4/4 passed; /tmp/cere-avatar-redesign/ctest-final.log. After the final crop refinement, ctest --test-dir build -R '^avatar(-software)?$' --output-on-failure: 2/2 passed; /tmp/cere-avatar-redesign/ctest-avatar-final.log. The renderer checks painted joint attachment, hip/leg movement and all 32 poses for all four avatars on OpenGL and software backends, plus sampled gesture timelines. Running the new checks against the saved original rigs failed on detached hip motion and uncovered joint pivots as expected; /tmp/cere-avatar-redesign/regression-before.log.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software ./build/cere-ui-check assistantIdentitySettings avatarThemeSwitching livelyPreviewAndSharedMood: 7 passed, 0 failed, including setup/cleanup; /tmp/cere-avatar-redesign/ui-final.log. Covers saving and switching every avatar, desktop pet readiness, motion preview animation and shared mood behavior.
  • DESTDIR="$(cat /tmp/cere-avatar-redesign/stage-path)" cmake --install build --prefix /usr: passed; /tmp/cere-avatar-redesign/install.log. All eight packaged rigs/atlases matched the workspace byte for byte. QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software CERE_PUPPET_TEST_SOFTWARE=1 ./build/cere-avatar-check "$(cat /tmp/cere-avatar-redesign/stage-path)/usr/share/cere": passed for all four packaged avatars; /tmp/cere-avatar-redesign/package-render.log. Staged package: /tmp/cere-avatar-stage-0Go6df.

Visually inspected the before/after comparison /tmp/cere-avatar-redesign/comparison.png, the enlarged lineup and pose sheets in /tmp/cere-avatar-redesign/final/, both rendering backends' pose/gesture sheets in /tmp/cere-motion-evidence/, and desktop/settings previews in /tmp/cere-ui-evidence/. The final crop corrections remove stray skin/fabric at the boots; face-only overlays remove neighboring arm fragments above curious expressions.

Delivery: workspace assets and staged package are ready. The installed client and broker were not replaced or restarted. UI validation used isolated fixtures and offscreen windows; live Hyprland placement/input regions were not exercised.

Jade and Nova avatars — October 14, 2026

Settings → Personality now offers Cere, Daemona, Jade and Nova. Saving Jade applies black and vivid scarlet; Nova applies black, violet and purple. Both include animated desktop cutouts, twelve expression portraits, matching menus, message links/code backgrounds, bubbles, motion previews, badges and live tray/window icons. The compact selector uses smaller preview cards. Names, personality and speaking voice remain independent; saving, discarding, conflict handling and startup retain their existing behavior.

Artwork was generated with built-in imagegen from reference/jade.png and reference/nova.png, with the existing Cere art as the layout/style reference. assets/jade-puppet.png and assets/nova-puppet.png are 1536×1024 transparent atlases; their *-rig.json files register the cutouts on the shared skeleton. The *-portrait-expressions.png sheets are 1448×1086 with four columns and three rows. Jade retains scarlet hair, a black crown, feathered wings, tattoos and plaid; Nova retains her half-up bun, violet-tipped hair, purple jewelry and black jacket. artwork/jade-nova-prompts.txt records all prompts, including Nova's torso and transparency refinements. Generated alpha was preserved; no pixel editing scripts were used.

Validation performed:

  • npm test: 537 passed, 0 failed, 1 opt-in synthesis skip (538 total), /tmp/cere-jade-nova-tests.log. npm run typecheck passed. After the final scarlet/compact-card refinement, node --test tests/qml-tokens.test.ts tests/settings-catalog.test.ts tests/assistant-identity.test.ts: 15/15 passed, /tmp/cere-jade-nova-focused-final.log. These cover persisted selection for every avatar, unchanged identity/voice settings, catalog completeness, usable transparent cutouts, all portrait cells, Settings search, and contrast across every palette.
  • cmake --build build --parallel 4 passed, /tmp/cere-jade-nova-build-final.log. ctest --test-dir build --output-on-failure: 4/4 passed, /tmp/cere-jade-nova-native-final.log, including OpenGL/software rendering and QML portraits/badges. The old two-avatar count assertion was updated to four. After the final palette refinement, ctest --test-dir build -R '^qml$' --output-on-failure passed again, /tmp/cere-jade-nova-qml-final.log.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software ./build/cere-ui-check assistantIdentitySettings avatarThemeSwitching markdownMessages pinnedConversationBubbles settingsSectionNavigation responsiveLayoutsAndDesktopActions: 10 passed, 0 failed, including setup/cleanup, /tmp/cere-jade-nova-ui-final.log. Theme switching is exercised separately for Daemona, Jade and Nova: native palettes/icons, existing Markdown contents and colors, saved selection in a fresh host, full/compact windows, draft discard and restoring Cere. The compact selector saves both new avatars through their actual buttons; pinned replies keep their place while every theme changes.
  • /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/*.qml exited 0, /tmp/cere-jade-nova-qmllint.log. The final selector also passed a focused lint, /tmp/cere-jade-nova-personality-qmllint.log. Warnings concern existing runtime-registered native types/dynamic properties; the UI runs reported no QML errors. git diff --check passed.
  • DESTDIR="$(cat /tmp/cere-jade-nova-stage-path)" cmake --install build --prefix /usr passed, /tmp/cere-jade-nova-install.log. QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software CERE_PUPPET_TEST_SOFTWARE=1 ./build/cere-avatar-check "$(cat /tmp/cere-jade-nova-stage-path)/usr/share/cere" rendered all four packaged avatars, /tmp/cere-jade-nova-package-render.log.
  • LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" node /tmp/cere-jade-nova-stage-check.mjs jade and the same command ending in nova both passed, /tmp/cere-jade-nova-package-startup-{jade,nova}.log. Each launched the staged application/broker with an isolated persisted avatar and custom name, verified the packaged catalogs/artwork byte-for-byte, and switched through all four avatars without QML errors. Temporary processes and profiles were cleaned up.

Visually inspected: /tmp/cere-ui-evidence/{jade,nova}-theme-{settings,compact,chat,pet,bubble}.png and /tmp/cere-motion-evidence/clips-{jade,nova}-software.png. The gesture sheets show limb joins, wings/hair, blinks and open-hand poses. The final UI captures show the scarlet/violet themes and compact cards.

Delivery: the workspace build and staged package are ready. The installed client and broker were not replaced or restarted. These checks use offscreen rendering and provider fixtures; live Hyprland placement/input regions were not exercised. Expected offscreen/accessibility-bus warnings remain.

Avatar palettes — October 14, 2026

Saving Daemona in Settings → Personality now applies a black/crimson palette throughout the desktop client. Cere restores the original blue palette. The theme follows the existing saved avatar, with no additional preference; choosing or discarding an unsaved avatar draft leaves the active theme alone. Name, personality and voice remain independent.

assets/palettes.json supplies both QML and native Qt colors. It is compiled into each host and also ships for standalone QML previews. Shared tokens cover surfaces, controls, focus rings, menus, notifications and conversation cards; portraits, mood badges (including mirrors), motion previews and pet shadows now use avatar colors too. Native menus and dialogs receive the matching application palette. Daemona's live tray/window icon renders her existing neutral portrait. Markdown code blocks and anchors are recolored in existing replies without changing their contents or link targets. Unknown avatar choices fall back to Cere through the existing avatar resolver. Installed launcher branding remains Cere.

Validation performed:

  • npm test: 535 passed, 0 failed, 1 opt-in synthesis skip, /tmp/cere-theme-tests.log. Palette checks cover catalog completeness, shared color tokens, 4.5:1 text contrast and 3:1 control boundaries for both avatars. npm run typecheck passed, /tmp/cere-theme-typecheck.log.
  • cmake --build build --parallel 4 passed, /tmp/cere-theme-build.log (existing unused-result warnings in the UI harness). ctest --test-dir build --output-on-failure: 4/4 passed, /tmp/cere-theme-ctest.log, including both rendering backends and new portrait/badge palette checks.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software ./build/cere-ui-check assistantIdentitySettings avatarThemeSwitching markdownMessages pinnedConversationBubbles: 6/6 passed including setup/cleanup, /tmp/cere-theme-ui-verified.log. Checks cover save/discard, native palette and icon propagation, existing Markdown links/code backgrounds, compact/workspace switching, a freshly connected host, live bubble updates and restoring Cere. Settings navigation and responsive layouts also passed in /tmp/cere-theme-ui-final.log; the initial switching test's history-load and native-event timing races were corrected before the final run.
  • /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/*.qml exited 0, /tmp/cere-theme-qmllint.log, with existing native-type/dynamic-property and singleton import warnings. git diff --check passed.
  • DESTDIR="$(cat /tmp/cere-theme-stage-path)" cmake --install build --prefix /usr passed, /tmp/cere-theme-install.log. LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" node /tmp/cere-theme-stage-check.mjs launched the staged host/broker with an isolated persisted Daemona profile and switched avatars both ways without QML errors, /tmp/cere-theme-package-startup.log. The offscreen environment reports an unavailable accessibility bus and unsupported compositor features; no live compositor test was run.

Visually inspected captures: /tmp/cere-ui-evidence/daemona-theme-settings.png, daemona-theme-compact.png, daemona-theme-chat.png, daemona-theme-motion.png, daemona-theme-pet.png, daemona-theme-bubble.png, daemona-theme-icon.png, and cere-theme-restored.png. The visual pass caught cached cyan Markdown anchors; the final formatter and regression check cover that case.

Delivery: the workspace build and staged package are ready. The installed live client and broker were not replaced or restarted.

Saved defaults for new conversations — October 14, 2026

The new-conversation dialog has a Save as my defaults switch. When it is on as a conversation opens, Cere keeps that conversation's provider, model, effort, desktop tools and temporary choice in settings.conversationDefaults, and the next general conversation opens with them, with a note saying so. The switch starts off each time; opening a conversation without it saves nothing.

  • General conversations. A general conversation is one started from the new-conversation dialog: New session in the sidebar, Sessions or an empty chat, or Ctrl+N outside Projects. Project sessions come from projects.createSession with the project's own saved defaults (projects table). Delegated sessions are created by sessions_start with the model and effort their parent conversation asks for. CLI imports, branches, handoffs, terminal links, recipes and phone-started conversations each pass their own choices to Core.create.
  • Where the defaults live. conversationDefaults is a settings key, null until saved, validated by Core.updateSettings with the rules project defaults follow; null clears it. Only qml/NewSession.qml reads it, and only for a general conversation: not for project settings (which keep their own Save defaults) and not for CLI imports. Core.create never fills it in, so no other way of starting a conversation can pick it up. settings.ollama.model, the Ollama default in Connections that project sessions and the phone also use, is not written. A saved model or effort the provider no longer lists shows as "· saved" and is checked when the conversation opens.
  • Not saved. The title and folder belong to each conversation. Trust is a confirmation for one folder's CLI configuration, so it is never saved: a saved trust would confirm every folder opened later.
  • Scrolling. The switch sits at the bottom of the dialog, and the dialog kept its scroll position between openings, so the next opening could hide the note. The new-conversation dialog now opens at its top through a scrollToTop() helper on CDialog; other dialogs are unchanged.

Checks on this machine. While this was built, another session edited broker/core.ts, broker/types.ts, tests/ui.cpp, README.md and other files for its own feature, so the checks ran in a separate worktree holding this tree as it was at 09:37 plus only these changes:

  • Baseline, same tree before these changes: full offscreen UI suite 58 passed, 0 failed, 9 skipped in 469 s (/tmp/cere-d-baseline.txt); Node tests 523, 522 passed, 1 skipped.
  • tests/conversation-defaults.test.ts (new): both tests failed before the change. They cover the unset default, strict validation (rejected patches change nothing), restart, clearing, settings.ollama.model left alone, and that project sessions, a sessions_start delegation and an explicit session.create never pick the defaults up. Node tests: 525, 524 passed, 1 skipped (opt-in installed IndexTTS), 0 failed. npm run typecheck and git diff --check passed.
  • A fresh ./tools/build.sh of the worktree passed in 75 s. qmllint: NewSession.qml adds only unqualified-access findings for App and footer ids, as its existing lines have; CDialog.qml adds none.
  • New UI slot newConversationDefaults: a stock conversation saved as defaults (Codex, fixture-model, high); the next dialog opens at its top with the note, the defaults filled in, and title, folder and trust empty; a conversation opened as filled in inherits them and saves nothing without the switch; saving again replaces them (Ollama, fixture-plain:latest, temporary). The project's settings dialog, its stored defaults and a session started from it keep the project's own defaults, and the Ollama default is unchanged. Opening at the top was checked against the old behaviour: without scrollToTop() the reopened dialog sat 54 px down.
  • Full offscreen UI suite in the worktree: the first run had 58 passed, 1 failed, 9 skipped (responsiveLayoutsAndDesktopActions, the race below), the second 59 passed, 0 failed, 9 skipped, and the run after the fix 59 passed, 0 failed, 9 skipped in 489 s (/tmp/cere-d-full3.txt): the baseline's 58 plus newConversationDefaults. The six soft review notes that read FAIL are the baseline's; "fresh state has no sessions" now counts 39 sessions instead of 35, the four this slot opens.
  • On the main tree with the other session's work in place: npm run typecheck passed and node --test on the new, core, projects and Ollama tests passed 66/66. The full UI suite was not run there while that work was in progress.

Found on the way: an effort chosen while one of the dialog's deferred passes was pending could be undone. chooseModel() scheduled the effort pass with the effort captured at that moment, so a catalog update arriving just before a choice put the old effort back and recorded it as wanted. That is how the first full run failed responsiveLayoutsAndDesktopActions (effort empty after Refresh); a trace of the dialog's passes (/tmp/cere-d-trace-3.txt) shows the stale call undoing the test's choice in the same millisecond. The pass now reads the wanted effort when it runs. The new slot replays the order, a pass and then a choice: with the old behaviour the choice reverts to the captured effort. Before the fix the responsive slot failed in 1 of 2 full runs and 2 of 13 repeated runs of the dialog's slots; after it, 12 of 12 such runs and the full run passed. The trace and the replay are the evidence; the run counts only agree with them.

Not verified: the live Hyprland desktop. Cere Mobile has its own new-conversation screen and does not read these defaults.

Avatar selection and assistant names — October 14, 2026

Settings → Personality now edits an independent assistant name, avatar and personality draft. Cere remains the default name and avatar. Daemona has a cutout animation atlas and twelve expression portraits based on reference/daemona.png; both variants share the existing motion channels, poses, gestures and reduced-motion behavior. Save updates the desktop pet, portraits, motion preview, empty-chat illustration, reply labels and accessibility names. Names reach managed providers on the next turn, including resumed Codex/Claude conversations, and local/ElevenLabs voice test introductions. Selecting an avatar does not change the name, personality or speaking voice. Blank names restore Cere; invalid names/avatars are rejected atomically, and old profiles receive the defaults.

Identity saves compare the three original draft values, so an unrelated setting update whose snapshot is still in flight cannot cause a false revision conflict. A concurrent identity edit blocks saving and preserves the draft for copying/discarding. The comparison cannot be used to bypass revision checks on other settings. Existing user edits elsewhere in this checkout were retained.

Implementation: broker/personality.ts, types.ts, store.ts, core.ts, provider hooks in providers.ts, ollama.ts, antigravity.ts, and the voice introduction in tts.ts; avatar catalog/selection and input-region updates in native/controller.{h,cpp}; qml/PersonalitySettings.qml, SettingsCatalog.js, GesturePlayer.qml, CerePortrait.qml, Chat.qml, and companion/name labels on the other desktop surfaces. README.md describes usage. The built-in imagegen tool produced assets/daemona-puppet.png and assets/daemona-portrait-expressions.png; exact prompts are in artwork/daemona-prompts.txt. assets/avatars.json lists the two choices and assets/daemona-rig.json maps the new art onto the shared rig.

Validation performed:

  • npm test: 533 passed, 0 failed, 1 opt-in IndexTTS synthesis skip (534 total), /tmp/cere-avatar-full-tests-final.log. New cases cover migration, persistence, Unicode/control-character validation, literal names, independent settings, stale drafts, avatar asset integrity, and name changes through Codex, Claude, Ollama and all three direct API providers. The Ollama tool-loop case checks that a running turn retains its original name.
  • npm run typecheck: passed, /tmp/cere-avatar-typecheck.log. cmake --build build --parallel 4: passed, /tmp/cere-avatar-build.log (existing unused-result warnings in the UI harness).
  • ctest --test-dir build --output-on-failure: 4/4 passed, /tmp/cere-avatar-ctest.log. Both avatars were rendered on OpenGL and software backends, including the gesture contact sheets. The final portrait source binding was rechecked with ctest --test-dir build -R '^qml$' --output-on-failure: 1/1 passed, /tmp/cere-avatar-qml-tests.log.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software ./build/cere-ui-check personalitySettings assistantIdentitySettings: 4/4 passed including setup/cleanup, /tmp/cere-avatar-ui.log. The final selector, settings navigation and pending-save recovery passed with ./build/cere-ui-check assistantIdentitySettings settingsSectionNavigation reconnectRecoversTranscriptAndFailsPendingRequests under the same environment (5/5, /tmp/cere-avatar-ui-final.log). After updating the empty-chat illustration, ./build/cere-ui-check assistantIdentitySettings reviewEmptyStates also passed (4/4, /tmp/cere-avatar-surfaces.log). Wide and compact captures are /tmp/cere-ui-evidence/avatar-settings-wide.png and avatar-settings-compact.png; the pet is daemona-pet.png. Gesture sheets: /tmp/cere-motion-evidence/clips-daemona-opengl.png and clips-daemona-software.png.
  • /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/PersonalitySettings.qml qml/CerePortrait.qml qml/GesturePlayer.qml qml/MessageCard.qml qml/ApprovalBubble.qml qml/Pet.qml qml/Shell.qml qml/Settings.qml qml/VoiceSettings.qml qml/CompanionSettings.qml qml/MotionSettings.qml qml/SessionList.qml qml/Chat.qml: exited 0, /tmp/cere-avatar-qmllint.log. Warnings include the native AvatarPuppet type registered at runtime and existing dynamic-property/layout warnings; actual UI runs reported no QML errors. git diff --check: passed.
  • Staged installation: DESTDIR="$(cat /tmp/cere-avatar-stage-path)" cmake --install build --prefix /usr, /tmp/cere-avatar-install.log. New assets matched their source hashes; QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software CERE_PUPPET_TEST_SOFTWARE=1 ./build/cere-avatar-check "$(cat /tmp/cere-avatar-stage-path)/usr/share/cere" rendered both installed avatars, /tmp/cere-avatar-package-render.log. LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" node /tmp/cere-avatar-stage-check.mjs launched the installed-path UI and broker with an isolated profile, loaded a persisted Daemona avatar/custom name, and accepted a live name update with no application diagnostics, /tmp/cere-avatar-package-startup.log. The local dependency path is required in this development environment; the initial bare staged launch could not find LayerShellQt. Temporary test processes/profiles were cleaned up.

Delivery: workspace binaries and the staged package are ready. The installed live client and broker were not replaced or restarted. These checks used an offscreen display and provider fixtures; a live compositor pass (including physical input-region behavior) and live model calls were not performed.

Conversations stuck on Thinking — October 13, 2026

Every new conversation stayed at Thinking… and never reached its provider. The stuck Claude session sat at starting with no provider process: Core.sendTurn was waiting for memory recall. One graph-memory worker thread had run near 100 % CPU since about 09:50, reading memory.sqlite at nearly 5 GB/s with no writes, and had used 79 minutes of CPU by 11:15. A Forget or Clear in Project memory at 09:50 had started an erasure preview. Its walk re-entered the erased history the October 10 expiry loop left: 96,805 erased claims, artifacts and payloads and 290,415 lineage rows. The walk's lookups had no index, so each step scanned whole tables. The worker serves one request at a time and a turn waited for recall without a deadline, so every turn queued behind the walk.

  • Erasure walk. Migration 3 indexes the columns the walk looks records up by, and the columns that reference a payload, so deleting one never scans a table. The walk skips tombstoned records, whose descendants were erased with them. It collects a selected record's supporting sources in one query, and closures use set membership. An erasure reuses the preview computed just before it while nothing has committed, and skips targets an earlier job already scrubbed.
  • Budgets and cancellation. Forget previews and the source lookup before an erasure stop after 30 s, and retention expiry after 60 s, never inside a transaction. An accepted erasure has no budget, so its replay at startup can always finish. Cancelling a request sets a second slot in its shared cancellation buffer, which a running walk checks at each step.
  • Watchdog. The worker announces each request it starts. A request that runs past its limit ends the worker. The limit is one minute beyond its budget, ten minutes for an erasure or expiry that may be committing, and none for backup, restore, rebuild or compaction. The open transaction rolls back, waiting requests fail, and a new worker replays any recorded erasure that never committed. Closing gives a busy worker five seconds. A housekeeping tick now catches its own errors, which would otherwise have been unhandled rejections in the broker, and health reports them as maintenance_error.
  • Turns. A reply waits at most eight seconds for memory, then continues without recalled context and marks memory degraded; Stop still ends the wait at once. Meanwhile the session's activity is recalling, shown as Recalling memory… in the conversation, the Activity Panel and the session list. The portrait, the emoticon and the pet's pose treat it as thinking, and Cere Mobile's source has the label too. Housekeeping yields while a turn recalls.
  • Compaction. cere memory compact --output PATH writes a backup and manifest to a new path, then in the same worker call removes tombstoned claims, artifacts and payloads with their support and lineage rows, finished projection jobs, and change records of tombstoned targets that every projection has passed. Tombstones, erasure jobs, commits and the erasure registry stay.

Checks on this machine:

  • Replay on a VACUUM INTO copy of the live store, before the fix: previewing a forget of the entity User (36,857 erased claims) had not finished after 100 s. A turn's own memory calls (scope, observe_text, retrieve, health, pending_artifacts, embedding_search, claim_job, extraction_next, maintenance) each took under 40 ms. After the fix, the same preview took 494 ms (453 targets) and a Clear preview of the ~/.cere scope 336 ms.
  • npm run typecheck passed. npm test: 523 tests, 522 passed, 1 skipped (opt-in installed IndexTTS), 0 failed, also after the final change that removed the budget from accepted erasures. New tests: tests/memory-worker.test.ts (watchdog restart, cancellation of a running call, budgets and limits, bounded close), tests/activity-labels.test.ts (every session activity labelled in each desktop view and in Cere Mobile), five in tests/memory.test.ts (walk over erased history, budget and cancellation stops, preview reuse, compaction, index use), one each in tests/shared-memory.test.ts and tests/core.test.ts (recall deadline and Stop), and a portrait case.
  • ./tools/build.sh passed. ctest --test-dir build --output-on-failure: 4/4 passed.
  • QT_QPA_PLATFORM=offscreen:configfile=$PWD/tests/fixtures/offscreen-scales.json QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check: the first run had 57 passed, 1 failed and 9 skipped in 470 s. reviewTransitions lost the reading position from cycle 7, the cycle that opens the session list's menu. It passed when run alone (./build/cere-ui-check reviewTransitions, 3 passed in 42 s), and a second full run had 58 passed, 0 failed, 9 skipped in 467 s, so that test is intermittent. Memory is disabled during it. Skipped tests need the live compositor or Spotify.
  • Installed with python3 tools/install-user.py after quitting the interface through ui.quit, then systemctl --user restart cere-broker.service. The old broker reached its 10 s shutdown deadline with the walk still running; migration 3 applied at 11:16:02. The final client change was copied into the installed broker, and that restart took 45 ms; the open interface reconnected.
  • cere memory compact --output ~/.local/state/cere/memory-backups/before-compaction-2026-10-13.sqlite took 16 s. memory.sqlite went from 475 MB to 96 MB. It removed 96,805 claims, support rows, artifacts and payloads each, 290,415 lineage rows, 196,968 finished projection jobs and 484,025 change records; tombstones (290,415) and erasure jobs (96,805) were unchanged. On a copy, PRAGMA integrity_check returned ok and the foreign key check found no violations in 0.14 s.
  • Live, Claude Code on haiku with effort low in a scratch project with memory on: two turns each showed recalling for about 0.5 s, then thinking, and finished in 3.9 s and 4.6 s. Forgetting the first turn's passage took 56 ms and clearing the scratch scope 356 ms; the scratch conversation was then deleted. cere memory query afterwards took about 105 ms, with token_budget_trimmed as its only coverage note.

Not verified: the watchdog restart and running-call cancellation live (a stand-in worker covers them). The Cere Mobile label change was not built into an APK. The forget started at 09:50 never got past its preview, so nothing was erased then. Compaction drops the link from an erased claim to its source: before compaction, a forget of User also selected the sources of its erased claims (453 records), afterwards only the entity (1 record). The first recalls after the restart reported semantic_degraded and deadline_partial while Ollama was briefly slow, which cleared on its own. The 228 retryable extraction runs (EXTRACTION_RETRYABLE) predate this change.

Settings by category — October 12, 2026

Settings shows one category at a time instead of one long page. qml/SettingsCatalog.js is the single list of three groups (Cere herself, Assistant, System), eleven categories and 61 individual settings, each naming the objectName of its control. The rail, the chips, Settings search, the command palette and deep links all read it.

  • Page. qml/Settings.qml has a header, Find a setting, the category navigation from qml/SettingsNav.qml (a rail of page tabs beside pages at least 700 px wide, otherwise a sideways-scrolling strip of chips), and one PageScroll whose column holds every category page with only the current one visible. All pages stay instantiated, so their requests on load and their objectNames keep working. The inline sections moved into CompanionSettings, MotionSettings, AssistanceSettings, ScriptsSettings, ConnectionsSettings and ApplicationSettings, each owning its dialogs. PersonalitySettings, VoiceSettings, RemoteSettings, KnowledgeSettings and TelemetrySettings are reused unchanged apart from two new objectNames, speechBrief and disableRemote. Backup and Health moved from the header to Application › Maintenance (the Health button now carries its dialog's name, Health and recovery), Show/Hide Cere moved from Motion to Companion › Presence, and the "Jump to section" picker is gone. Every other existing objectName is kept; only settingsSectionPicker went with the picker.
  • Search and deep links. Search ranks a setting's own label above its keywords and both above a category, with an exact category name first. Enter or a result calls revealControl(): it opens the category, scrolls to the control, focuses it and outlines it for about a second; a control in a part of the page that is switched off reveals that part. Before scrolling, the visible page is laid out at once with ensurePolished(), repeated until the control holds still, because a page that was hidden a moment ago still has stale wrapped-text heights. Escape clears a search before it leaves Settings. The command palette lists every category and setting from the catalog as settings:<category> and settings:<category>/<target> (ids the broker's navigation history accepts) and opens them through open(category, target). Desktop's Manage scripts opens Saved scripts. Voice is left out of the rail, search and palette while speech is unavailable.
  • Tests. tests/ui.cpp gains openSetting() and openCategory(), and the slots that reached into the long page open their category first. settingsSectionNavigation is rewritten: rail tabs and selection, a one-result search with Enter landing on the focused, outlined control, the no-result text, Escape, every catalog target revealed in view (or present when switched off), chips at 720 px with the current chip scrolled into view, and both deep links. responsiveLayoutsAndDesktopActions opens Application before its bottom-of-page check, and its edge check treats the chip strip as one scrolling control. tests/settings-catalog.test.ts checks that every target names a control in qml/, that ids, targets and labels are unique, that Settings has one page per category, that the palette has no hard-coded list, and search ranking.

Checks on this machine:

  • node --test tests/settings-catalog.test.ts: 4/4; changing one target to a missing name fails it. npm test: 511 tests, 510 passed, 1 skipped (opt-in installed IndexTTS), 0 failed. npm run typecheck and git diff --check passed. tests/qml-tokens.test.ts covers the new QML files.
  • ./tools/build.sh passed. qmllint on the new QML files reports only unqualified access to the App context property; Settings.qml and SettingsNav.qml use pragma ComponentBehavior: Bound for their delegates. An early chip strip whose height depended on its width made Qt report "Detected recursive rearrange" (none in the baseline run); the strip now always reserves its scroll bar's room, and no later run shows the warning.
  • Offscreen UI, targeted: navigationAndScreenshots settingsSectionNavigation workspaceTelemetryControls apiProviderSetup providerSpeechSwitches elevenLabsSettings indexTtsSettings voiceSettings personalitySettings memoryCitationDisplay ollamaConversation extractionModelSelection searchAndMemory responsiveLayoutsAndDesktopActions persistentPermissionSwitches (/tmp/cere-f2-ui-a.txt) and avatarPresenceShowcase livelyPreviewAndSharedMood expressiveActing graphInspectorPolicyForgetAndCorrection foldersAttachmentsAndPalette reviewApprovalsAndKeyboard reviewAccessibilityInventory reviewWorkflows (/tmp/cere-f2-ui-b.txt) all passed after fixes found by the first run (the navigation check's object lookup, and the stale layout above).
  • Full offscreen UI suite: 58 passed, 0 failed, 9 skipped in 546 s (/tmp/cere-f2-full.txt), the same totals as after the citation change: the baseline's 57 plus memoryCitationDisplay. A fallback for a remembered category that is unavailable when the page is created was added afterwards; the first targeted group above passed again with it (/tmp/cere-f2-ui-final.txt).
  • The accessibility inventory now counts only the visible category: 47 named settings controls in the full run (161 for the whole page before), none unnamed. The soft review notes that read FAIL are the same six as in the baseline run.

Not verified: the live Hyprland desktop (mouse-wheel scrolling of the chip strip, pointer hover on the rail). Cere Mobile keeps its own settings screen; parity is deferred. Old command-palette favourites and recents that named a Settings section by its label no longer match an entry and are ignored.

Memory citation display toggle — October 12, 2026

Replies that use recalled memory cite it as [evidence:ID]. Settings → Memory → Show memory citations in replies (showMemoryCitations, off by default) now keeps those markers out of everything a reply is shown in or copied from. Stored replies keep them: broker/memory.ts still reads the cited ids from the saved answer for record_response.

  • Rules. broker/citations.ts and native/citations.h apply the same rules and are both checked against tests/fixtures/memory-citations.json (35 cases). A marker takes the space before it when punctuation or the end of the line follows, and the space after it at the start of a line; parentheses or backticks that only wrap it go too. Comma or semicolon lists and adjacent brackets count as one marker. A line left with only a list marker or a label such as Evidence: or **Sources:** is removed without doubling a blank line. A partial marker at the end of a streaming reply is dropped. Fenced code is not exempt. Short ids such as [evidence:abc] and text without a complete marker are returned unchanged. Every pattern is bounded by literals, so long or malformed input stays linear.
  • Desktop. Controller exposes showMemoryCitations with its own change signal and displayText(text, showCitations). MessageCard (conversations, completion cards and pinned-reply cards) shows, copies, quotes, speaks and branches the stripped text; Copy of a transport-shortened message strips the full text after its chunks are assembled. The completion inbox and Activity agent results use the same text. Tool output is unchanged.
  • Broker. speechText strips markers before reading, so no voice provider reads them, whatever the setting. A brief reading measures its 600 characters after stripping. Command-palette transcript snippets follow the setting.

Checks on this machine:

  • Baseline before this change, same working tree: ./tools/build.sh, then the full offscreen UI suite: 57 passed, 0 failed, 9 skipped in 533 s (/tmp/cere-baseline-full.txt). The 9 skips are the live-desktop slots.
  • node --test tests/citations.test.ts: 4/4, including all fixture cases and a linear-time check on hostile input. tests/core.test.ts adds default, strict validation, restart and brief-reading checks; the brief-reading assertion fails with the core change removed. tests/navigation-search.test.ts adds the snippet check. tests/tts.test.ts now copies broker/citations.ts into its minimal install, since broker/tts.ts imports it.
  • npm test: 507 tests, 506 passed, 1 skipped (opt-in installed IndexTTS), 0 failed. npm run typecheck and git diff --check passed.
  • ./tools/build.sh passed. Offscreen UI markdownMessages memoryCitationDisplay completionBubbles searchAndMemory: 6/6 with setup and cleanup (/tmp/cere-f1-ui.txt). The new memoryCitationDisplay runs the C++ rules over the fixture, then checks a real Codex fixture reply: no marker in the rendered document, Copy, the chunked full-text copy or Quote; markers appear and disappear live when the setting changes, with one change signal per change and none for unrelated updates.
  • Full offscreen UI suite: 58 passed, 0 failed, 9 skipped in 530 s (/tmp/cere-f1-full.txt); the extra pass is the new slot. The accessibility inventory counts 161 named settings controls (160 before).
  • qmllint on the four changed QML files adds only unqualified warnings for the App context property, as every existing App use does.

Not verified: a live, memory-enabled conversation on the desktop. Cere Mobile still shows markers; its settings and Markdown renderer are unchanged.

Codex 0.162.1 and Claude Code 2.1.296 compatibility — October 12, 2026

Audit of the Codex and Claude Code integrations against the installed CLIs, which are the current stable releases on GitHub and npm (both published October 9). The provider list had failed for both CLIs: at login the interface waited 3 s for cere-broker.service, which waits for the memory service, then started its own broker, whose PATH lacked ~/.local/bin.

  • Provider discovery. The broker adds ~/.local/bin to its PATH at start, and each CLI is resolved on PATH, then in ~/.local/bin and its installer's own directory. Detection reads the version banner: Codex below 0.158.0 or Claude Code below 2.1.259 is reported as needing an update, and Claude's help text is read only when the banner has no version. Errors say whether a CLI was missing, not executable, too slow or failed.
  • Broker launch. The interface queues the service start with --no-block and starts its own broker only when systemctl refuses the start or does not answer within 3 s. A broker that finds the runtime lock taken names the owner's pid.
  • Claude Code. Turns pass --system-prompt-snapshot off, so a resumed conversation uses the current personality and memory guidance. A result that arrives while background work runs is held until that work and Claude's follow-up reply finish. A process replaced by the next turn can no longer change that turn's state, and Stop during the hand-over cancels the turn before a new process starts.
  • Codex. File-change approvals show the diff from the announced fileChange item, cut at 100,000 characters; a cut or missing diff cannot be approved from a phone. Network approvals name the destination, approvals for input to a running command say so, and choices follow availableDecisions. Cere answers currentTime/read, shows compaction items as compacting activity, tracks multi-agent v2 subAgentActivity items as agents, keeps listAgents from adding old agents, records Codex warnings as tool activity without changing the spoken reply, keeps async questions with the reply and opts out of seven high-volume notifications.
  • Claude history import. Titles use Claude's generated title, else the first typed prompt, skipping command records, caveats and Cere's memory block.

Checks on this machine:

  • npm run typecheck passed. npm test: 497 tests, 496 passed, 1 skipped (opt-in installed IndexTTS), 0 failed. After the last edit, node --test tests/providers.test.ts: 23/23, including 6 new tests. ./tools/build.sh passed.
  • An isolated working-tree broker started with PATH=/usr/bin:/bin found Codex 0.162.1 with 7 models and Claude Code 2.1.296 with 13 models, both remote-restricted.
  • Claude Code on haiku, run directly: after --resume, a changed --append-system-prompt-file was ignored until --system-prompt-snapshot off was passed. Through Cere, the resumed turn followed the changed personality. A background sleep 12 command kept the turn working with the task running; Claude's follow-up reply landed in the same turn, and the next message completed without error.
  • Codex on gpt-5.6-luna: the file-change approval showed add …/hello.txt with its content and was marked approvable from a phone; the file was written.
  • MCP: Claude Code 2.1.296 first sends server/discover, receives Cere's -32601 reply and initializes with 2025-11-25. A server answering 2024-11-05 and one echoing the requested version both connected in about 460 ms, so Cere's MCP server is unchanged.
  • python3 tools/install-user.py, then the login race reproduced by stopping cere-memory.service and starting app-cere@autostart.service: the broker ran under cere-broker.service with ~/.local/bin on PATH and its memory credentials, and both CLIs reported ready catalogs.

Not verified: a live Codex multi-agent v2 turn (the session's permission classifier blocked it; a fixture covers the mapping). currentTime/read and managed-network approvals were not triggered live. build/cere-ui-check was not rerun; the interface change only affects installed launches. Two observations from the switch-over: the old interface crashed with SIGSEGV while quitting, right after the install had replaced its executable and bundled libraries, so quit the interface before installing. After the memory service was stopped, its first restart failed because Qdrant was not ready within the start script's wait; the next start succeeded.

Completeness review fixes — October 9, 2026

Fixes for the repository review of f9d4a0f (branch ui-overhaul), findings F1–F12. Product decisions: restore keeps this computer's setup; the persistent bypass switches stay and are documented; nemotron-3-super stays the extraction default; saved conversations can be deleted.

  • F1/F2 restore. Under systemd the broker exits with status 75, which cere-broker.service restarts (RestartForceExitStatus=75, SuccessExitStatus=75); unmanaged runs keep the detached relaunch, and a runtime lock stops a second broker. The staged profile carries current settings (paused, grants cleared), API keys, the mobile identity, paired devices with their command and audit records, and voice profiles. The preview states what is kept and what is replaced.
  • F3 API output. Catalog input/output limits are read per provider; Claude API requests use the model's output limit (4,096 when none is listed). Output-limit stops on all three APIs keep the partial reply, mark it, and keep it in model history; refusals fail clearly.
  • F4 sends. Before a turn is recorded, Ollama checks a local model's chat, tool and image support and image limits, and AntiGravity refuses images. Image attachments are refused at attach time for AntiGravity and for Ollama models without image support; a turn the provider never accepts goes back to the draft with its attachments.
  • F5, F8, F12 docs. README permissions, shortcuts, providers, phone model changes, cere toggle, login startup, restore, API limits, deletion and validation commands; memory docs for the extraction default and migration 2; mobile reconnect advice; URL forms above; PKGBUILD depends on pipewire-alsa instead of pulseaudio-alsa. Mobile rename trims and defaults titles like the desktop.
  • F6/F7. QML component tests run in CTest (qml, with QML_XHR_ALLOW_FILE_READ=1). New .github/workflows/desktop-check.yml builds and tests in an Arch container; mobile-check.yml also runs :app:testDebugUnitTest.
  • F9 offline. The interface relaunches a broker that stays down (after 6 s, at most every 15 s; systemctl --user start when installed). Expand works offline. Drafts typed offline are kept and saved on reconnect; Stop is disabled and the turn reads "Connection lost — reconnecting…".
  • F10 delete. Delete… in the session context menu, confirmed, removes the conversation and what it owns; busy, approval-pending and power-session conversations are refused.
  • F11 harness. Live-desktop slots skip offscreen. Order-dependence causes fixed: memory left enabled (fixture prompts changed), a folder filter left on a deleted folder (now reset in SessionList.qml), archived sessions missing from broker state, a completion bubble pausing roaming, a session-creation race in projectAndDraft, pinned rows hiding the context-menu target, and a settings/animation race. Product fixes found on the way: the toast overlay swallowed clicks on controls beneath it (now input-transparent, fading under the pointer); a stale saved position was re-applied on unrelated state updates; and with per-output QPA scaling the pet window shrank while crossing outputs (its configured size is now re-asserted).
  • UI review backlog. F-11, F-15, F-19, F-20, F-22, F-23 and F-25–F-28 are implemented. New assertions cover F-11 (compact conversation ≥ 420 px at 440×860; measured 468 px), F-19/F-25 (noticesFloatOverPagesAndAreNotRepeated), F9 (offlineDraftSurvivesBrokerRelaunch) and F10 (sessionContextActions).

Checks on this machine, with isolated state and runtime directories:

  • ./tools/build.sh passed. npm test: 478 tests, 477 passed, 1 skipped (opt-in installed IndexTTS), 0 failed. npm run typecheck, npx tsc -p tsconfig.mobile.json, node tools/mobile-contract.ts --check and git diff --check passed.
  • ctest --test-dir build --output-on-failure: 4/4 (motion, avatar, avatar-software, qml). The previous README qmltestrunner command fails 3 portrait tests without QML_XHR_ALLOW_FILE_READ=1; with it, 14/14. Without a display the OpenGL avatar test aborts, so CI runs CTest under xvfb-run.
  • QT_QPA_PLATFORM=offscreen:configfile=$PWD/tests/fixtures/offscreen-scales.json QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check (local library paths): 55 passed, 0 failed, 9 skipped in 458 s. Skipped as live-only: spotifyPlaybackRoundTrip, captureEditorRoundTrip, mouseFollowing, mouseFollowingAcrossOutputs, overlayAndFloatingModes, fullscreenOverlay, compactPanelFloatsWithoutAlwaysOnTop, approvalBubbleNeverTakesFocus, reviewLiveOutputs. No test broker or temporary directory remained.
  • After-captures from that run are in docs/ui-review/after/ under the baseline names (123 of 131). The 8 review-live-* captures need temporary live outputs and were not regenerated. Soft review notes that read FAIL: bubble has no default-focused control and bubble leaves the keyboard alone (offscreen reports the bubble active, as in Stage 3), fresh state has no sessions (the full run creates sessions first), session menu open before expand, and timer started from compact (offscreen has no hyprctl, so the Desktop error card can shift the layout under the click; it passed in the previous full run).
  • Android :app:testDebugUnitTest through gradlew-quiet.sh: PASS (up to date; 5 tests, 0 failures; no Android sources changed).
  • Restore under systemd: a transient user unit with the packaged restart settings ran the broker on isolated directories; after backup → preview → activate it restarted once (Result=success) and answered with recoveryPending false 3.8 s later. Personality and Ollama host were kept, tools were paused, and the previous profile was retained.

Not verified: the desktop CI workflow has not run (no container runtime here). The live-desktop slots were not rerun on Hyprland in this pass. The nemotron-3-super extraction evaluation needs separate approval for its cloud calls. Phone behaviour after a desktop deletion was not exercised on a device. The Desktop page can show one failure both as its error card and as a toast, outside F-25's scope.

UI/UX overhaul from docs/ui-review/REVIEW.md — October 1, 2026

Branch ui-overhaul, one commit per stage on top of snapshot 1f30596 (the previously uncommitted tree). Every UI run used the harness's isolated CERE_STATE_DIR/CERE_RUNTIME_DIR and the local Ollama/Codex fixtures. Offscreen runs used LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QPA_PLATFORM=offscreen:configfile=$PWD/tests/fixtures/offscreen-scales.json QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic build/cere-ui-check SLOT… -o LOG,txt; live runs dropped the platform override and used the running Hyprland session. Baseline comparisons use the snapshot built in a separate worktree with only the harness crash guard below applied.

Stage 1 — S1 fixes

  • F-01 transition state. session.draft accepts an optional desktop view record: cursor, selection, Search web, Activity Panel expansion, the message at the top of the conversation (ID plus position within it as a share of its height) and composer focus. View-only saves change neither the draft revision nor the session's place in recent order; a send clears the view with the draft. Chat.qml restores the record after the editor completes, anchors by message rather than pixel offset with a short settle pass, accepts a view that arrives just after a surface opens, and keeps the selection when focus moves (persistentSelection). Dragging the conversation scrollbar now stops new output from pulling the view down, as wheel and drag scrolling already did. The mobile DTO is built field by field and does not carry view.
  • F-14 draft race. A save made while another is in flight now hands over to Controller::deferDraft, which sends it with the confirmed revision once its predecessor succeeds, even if Expand has destroyed the editor. The controller also flushes drafts before destroying either panel.
  • F-02 requester identity. New qml/SessionIdentity.qml shows provider and session ID, the full wrapped title, and the middle-elided project path (with tooltip) on separate lines; approval and completion cards share it, and qml/Labels.js holds provider display names.
  • F-03 compact height. Title and provider share one block; the chat page scrolls when shorter than its minimum, so no control is clipped; below a 560 px chat page the tools fold into a More menu beside Send; the composer minimum drops to 96 px on short pages; the conversation keeps 160 px (300 px with a pending question).
  • F-04/F-13/F-17/F-21. Without always-on-top the compact panel is floated, sized and moved through Hyprland like the pet and bubble, with its output set before its size; opening the compact panel focuses the composer; the bubble filters approvals with its own process's panel visibility instead of the broker's delayed echo; compactPanelFitsEveryOutput now expects the 860 px request.
  • Files: broker/core.ts, broker/types.ts, native/controller.cpp, native/controller.h, qml/Chat.qml, qml/Shell.qml, qml/ApprovalCard.qml, qml/ApprovalBubble.qml, qml/CompletionCard.qml, qml/CIcon.qml, qml/SessionIdentity.qml, qml/Labels.js, tests/workspace.test.ts, tests/ui.cpp, README.md.
  • Harness: window is a QPointer and init() restores the workspace when a failed slot left none, which removes the cascade segfault recorded in REVIEW.md §7; reviewEmptyStates restores the Ollama host before its model (the combined restore was refused, leaving later review slots without Ollama); reviewTransitions now asserts every field across 10 cycles and mid-stream, reading back with a generated flick; reviewSurfacesAtScale asserts reachability; new compactPanelFloatsWithoutAlwaysOnTop (live only); new F-14 ordering case in draftsStayCoherentAcrossComposers, confirmed to fail with the hand-off disabled; a tool() helper reaches folded tools through More.
  • Results: ./tools/build.sh passed (/tmp/cere-overhaul-build-s1.log). npm test 446 passed, 0 failed, 1 skipped of 447 (/tmp/cere-overhaul-npm-test-s1.log; baseline 440/441 + 1 skipped, the difference is the new draft-view test and tests added concurrently in tests/remote.test.ts). npm run typecheck and git diff --check passed.
  • Targeted offscreen UI runs passed: reviewLongContent reviewTransitions twice (/tmp/cere-s1-j1.txt, /tmp/cere-s1-j2.txt), reviewEmptyStates reviewLongContent reviewTransitions (/tmp/cere-s1-q.txt), reviewSurfacesAtScale on all five fixture outputs (/tmp/cere-s1-m.txt), activityAndPermissionBubble compactSessionNavigation approvalsIdentifyTheirRequester twice, draftsStayCoherentAcrossComposers, compactComposerClipboard compactPanelFitsEveryOutput compactSessionNavigation responsiveLayoutsAndDesktopActions. Live on Hyprland: compactPanelFloatsWithoutAlwaysOnTop compactPanelFitsEveryOutput passed (/tmp/cere-s1-live-c.txt).
  • Full offscreen suite: 41 passed, 16 failed, 2 skipped (/tmp/cere-s1-final.txt) against 35 passed, 22 failed, 1 skipped for the guarded baseline (/tmp/cere-base-full2.txt). Eight of the remaining failures need the live compositor (pet windows, hyprctl, fullscreen); the others also fail in the baseline full run, except reviewTransitions (it had no assertions before) and searchAndMemory. In that run the Ollama fixture left sessions working: reviewLongContent could not complete its first turn, so the transition check had no conversation to read. searchAndMemory passed 3/3 on both builds with the identical slot sequence (/tmp/cere-s1-sm*.txt, /tmp/cere-base-sm*.txt) and now reports session status on failure.
  • Compact conversation height (offscreen, reviewSurfacesAtScale): 343 → 369 px at 440×860, 216 → 302 px at 440×668 (1.5× and 2× 1080p), 24 px with clipped controls → 160 px plus page scrolling at 440×460 (1366×768 @1.5).
  • Another writer edited broker/remote/*, the Android sources, docs/mobile/*, protocol/mobile/v1/CONTRACT.json, qml/RemoteSettings.qml and tests/remote.test.ts during these runs; one full run loaded RemoteSettings.qml mid-edit (Expected token '}'). Those files are not part of these commits.

Stage 2 — shared rules and tokens

  • The token, component and type-scale work was swept, uncommitted, into the other writer's commit c7d35d3 ("Publish Cere Mobile 0.1.3 development snapshot and approval fixes"), which was then pushed to origin/main. That history is public, so it was not rewritten; the remainder of Stage 2 is the follow-up commit after it. In c7d35d3 the Stage 2 parts are: qml/Theme.qml (surface, boundary, text and focus colours, the type scale caption 11 · secondary 12 · body 13 · message 14 · section 15 · title 20 · page 22 · display 28, spacing 4/8/12/16/24, radii 6/9/12/14/16, Theme.duration()), new CTextArea, CMenu, CMenuItem, CMenuSeparator, restyled CButton, CField, CComboBox, CSpinBox, CCheckBox, CSlider, CScrollBar (12 px track, named, thumb 4.8:1), CDialog, CSection, CActionRow, every colour literal outside Theme.qml and the avatar artwork replaced by tokens, 349 font sizes in 38 files moved to the type scale (no text below 11 px), free-text editors moved to CTextArea so each has a 3:1 boundary and the 2 px cyan focus ring, all menus themed, and tests/qml-tokens.test.ts. qml/RemoteSettings.qml was left alone while it was being edited concurrently; it has no colour literals and nothing below 11 px.
  • Follow-up commit: the compact page slide uses Theme.duration(180), so reduced motion, quiet mode and zero intensity make page changes instant and lower intensity shortens them; README motion paragraph updated; one menu item re-indented.
  • Contrast from the shipped tokens (WCAG 2.2): text 11.9–17.1:1 and muted 5.8–8.3:1 on every surface including selected; control boundary border #61788f 3.32 (raised) to 4.21 (sidebar); borderStrong/scrollThumb #6b839c 3.87–4.79; primaryBorder 3.84–4.76; dangerBorder 3.55–4.52; warningBorder 3.61–4.52; approvalBorder 3.93–5.04; focus ring cyan 8.3–12.2. Message-card outlines stay decorative (containers, not controls).
  • CERE_TTS_DISABLED=1 node --test tests/qml-tokens.test.ts 3/3 passed; with a planted "#123456" and a 9 px ternary size in a probe file it failed both checks as intended (probe removed). npm test 463 passed, 0 failed, 1 skipped of 464 on c7d35d3 (/tmp/cere-overhaul-npm-test-s2.log); npm run typecheck and ./tools/build.sh passed; every changed QML file passed qmllint.
  • Offscreen UI: navigationAndScreenshots settingsSectionNavigation workspaceTelemetryControls personalitySettings searchAndMemory graphInspectorPolicyForgetAndCorrection 8/8 (/tmp/cere-s2-a.txt); compactSessionNavigation responsiveLayoutsAndDesktopActions compactComposerClipboard foldersAttachmentsAndPalette draftsStayCoherentAcrossComposers queuedOllamaMessages 8/8 (/tmp/cere-s2-c.txt); markdownMessages questionsAndAgentActivity activityAndPermissionBubble approvalsIdentifyTheirRequester completionBubbles sessionContextActions 7/8 (/tmp/cere-s2-b3.txt). The failure is the Archive step of sessionContextActions (ui.cpp:1887); the baseline worktree fails the same step in the identical batch (4/8, /tmp/cere-base-b.txt) and the slot passes alone on both builds, so it is order-dependent and predates the themed menus.
  • F-08 diagnosis for Stage 3: the API key fields already set Accessible.name, yet QAccessible reports an empty name. A standalone probe (/tmp/cere-a11yprobe) shows Qt 6.11 drops the name of any TextField in password or password-on-edit mode, even with Accessible.passwordEdit: false, while Accessible.description survives.
  • Process note: Cere started duplicate claude -p processes for this conversation when a message arrived during a running turn (the message reached the live process and also spawned a new one). Two duplicates were stood down; one overlapping UI run crashed (/tmp/cere-s2-b.txt was overwritten by the duplicate's run and is not evidence). Recorded as an out-of-scope Cere issue.

Stage 3 — S2 fixes, first part (October 4, 2026)

  • F-05 Tab. CTextArea, the composer and the phone pairing response editor in qml/RemoteSettings.qml move focus on Tab and Shift+Tab and never insert a tab. reviewApprovalsAndKeyboard now asserts that Tab leaves the composer at once, inserts nothing and comes back round the chain, and that Shift+Tab leaves it. settingsSectionNavigation asserts the same for the pairing editor and failed with that editor's handlers removed (Tab stayed in the pairing response editor, ui.cpp:138).
  • F-07 workspace minimum. 720×520 instead of 720×580. reviewSurfacesAtScale resizes the workspace to that minimum on all five fixture outputs and asserts that no control leaves it sideways and that the composer is inside it or the page scrolls.
  • F-08 and F-18 accessible names. The API key fields also set Accessible.description, which Qt keeps for password fields (see the Stage 2 diagnosis). The inventory reads the description for password fields, and reviewAccessibilityInventory now asserts that no control is unnamed: 0 unnamed of 14, 50, 150 and 16 workspace controls (Chat, Desktop, Settings, Sessions) and of 10 and 45 compact ones (Chat, Desktop).
  • F-09 bubble focus. Without always-on-top the bubble keeps WindowDoesNotAcceptFocus except while the pointer is over it (Controller::setBubbleFocusable, driven by the bubble's HoverHandler), and before the bubble shows on Hyprland the controller installs a named runtime rule, no_initial_focus for the title Cere Approval, because Hyprland focuses every new window. Requests are still answered with the pointer or from either panel. New live-only approvalBubbleNeverTakesFocus passed 4/4 on Hyprland 0.56.2 with a Lua configuration; the legacy windowrulev2 branch was not exercised. Offscreen, the bubble leaves the keyboard alone note in reviewApprovalsAndKeyboard still reads FAIL because that platform reports the bubble active even with the flag set; it is a note, not an assertion, and only the live slot is evidence.
  • F-10 long lines. Message bodies use TextEdit.Wrap, so a long URL or path breaks where it must. formatMessage(document, proseWidth) gives every block outside code and tables a right margin equal to the document's overflow, so prose stays at the visible width while a wide table or code block still scrolls, and fitTable sets each table column between its longest word and its natural width. Cards reformat when their width changes. reviewLongContent asserts the widest prose line of the fixture reply: 698.8 of 700 px (workspace 1040), 639.8 of 648 px (workspace 720) and 358.2 of 366 px (compact 440), 31 prose blocks each, with the document still 1308 px wide for its table.
  • F-12 send key. Enter sends and Shift+Enter starts a new line, as before. The hint now says so at every width (Enter sends · Shift+Enter new line from 480 px, the empty composer's placeholder below that) and README matches.
  • Not done: F-11 and F-19 (compact chrome and the overlay toast). The compact conversation is still 369 px at 440×860 against the 420 px target. F-13 and F-14 shipped with Stage 1.
  • Files: native/controller.cpp, native/controller.h, qml/ApiConnection.qml, qml/ApprovalBubble.qml, qml/CTextArea.qml, qml/Chat.qml, qml/MessageCard.qml, qml/RemoteSettings.qml, tests/ui.cpp, README.md.
  • Results: ./tools/build.sh passed. npm test 463 passed, 0 failed, 1 skipped of 464. npm run typecheck, npx tsc -p tsconfig.mobile.json, node tools/mobile-contract.ts --check and git diff --check passed; qmllint exited 0 on the six changed QML files; ctest --test-dir build passed 3/3.
  • Offscreen UI: reviewLongContent reviewApprovalsAndKeyboard reviewSurfacesAtScale, reviewAccessibilityInventory and settingsSectionNavigation passed.
  • Full offscreen suite: 44 passed, 15 failed, 3 skipped, against 44 passed, 15 failed, 2 skipped for the Stage 2 commit 8bbb20b built in a separate worktree; the extra skip is the new live-only slot. The same 15 slots fail on both builds, with the same messages except captureEditorRoundTrip, which stopped one step later in the baseline full run and fails alone at the same step on both builds (2/2 each). Seven pass alone on this tree, so they are order-dependent: emoticonBadges, pinnedConversationBubbles, completionBubbles, compactProjectsAndEnterToSend, compactComposerClipboard, sessionContextActions and reviewTransitions. reviewBrokerDisconnectMidTurn fails alone at its last capture after all of its notes passed. The other six (mouseFollowing, mouseFollowingAcrossOutputs, overlayAndFloatingModes, petGesturesAndReducedMotion, fullscreenOverlay, roamingPlacementIsContinuousAcrossOutputs) were not rerun alone.

AntiGravity model/effort compatibility — September 30, 2026

  • Diagnosed the running client's failed AntiGravity session: discovery was ready with 14 models, but gemini-3.1-pro-high was combined with medium effort. The installed CLI reproduced --model gemini-3.1-pro-high conflicts with --effort=medium, with zero model turns. The original failure is recorded in ~/.gemini/antigravity-cli/log/cli-20260930_221107.log:122.
  • broker/antigravity.ts now limits effort choices for effort-suffixed model IDs, rejects conflicting saved settings before dispatch, omits redundant matching effort flags, and preserves bounded provider error details with credential redaction. Added regressions in tests/antigravity.test.ts, its subprocess fixture, and tests/session-models.test.ts; README documents the model selection rule.
  • CERE_TTS_DISABLED=1 node --test tests/antigravity.test.ts tests/session-models.test.ts tests/models.test.ts passed 16/16 (/tmp/cere-antigravity-fix-tests.log). After correcting a TypeScript narrowing issue in one new assertion, CERE_TTS_DISABLED=1 node --test tests/antigravity.test.ts passed 6/6 (/tmp/cere-antigravity-fix-adapter-tests.log) and npm run typecheck passed (/tmp/cere-antigravity-fix-typecheck.log). git diff --check passed. No QML/native changes or native rebuild were needed.
  • A live turn through the patched AntigravityAdapter, using the running broker's environment and a temporary workspace, completed with CERE_ANTIGRAVITY_OK on gemini-3.1-pro-high with default effort. A separate import of the installed module discovered all 14 live models and offered only high for that model.
  • Corrected the existing failed session through session.configure with its current revision, clearing the conflicting effort override. Verified identical transcript, native conversation ID, draft and attachments; no message was resent. Evidence: /tmp/cere-antigravity-session-repair.json. Atomically installed only the adapter into ~/.local/share/cere/broker/antigravity.ts, with backup /tmp/cere-antigravity-before-sx8ylxrx/antigravity.ts and install record /tmp/cere-antigravity-fix-install.json. The corrected session can be retried now; the prevention/error-reporting code loads on the next broker restart. The active broker was left running to preserve this conversation.

Header portrait speech toggle — September 30, 2026

  • The top-left Cere head toggles the persisted speechEnabled master setting in both compact and expanded layouts. The existing broker path stops current and queued speech when disabled. The portrait retains its greeting animation, adds an amber crossed-speaker mute badge and action tooltip, and supports keyboard Space/Enter and accessible activation. The control is disabled while disconnected. Volume, voice, Quiet mode and per-provider selections are preserved; explicit Test voice retains its existing preview behavior.
  • Changed qml/CerePortrait.qml, qml/Shell.qml, qml/CIcon.qml, docs/tts.md and this record. No executable/backend dependency or native code changed; QML is loaded from files, so no native rebuild was needed.
  • node --test tests/tts.test.ts tests/portrait-state.test.ts passed 28/28 (/tmp/cere-head-mute-tests.log). With the existing offscreen/software Qt environment, build/cere-ui-check voiceSettings providerSpeechSwitches -o /tmp/cere-head-mute-ui.txt,txt passed 4/4 including setup/cleanup, constructing the modified header and exercising the existing settings controls. No additional permanent test was added for this small UI binding.
  • /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/CerePortrait.qml qml/CIcon.qml passed (/tmp/cere-head-mute-components.log). Shell lint retains eight pre-existing layout/property warnings, confirmed against a temporary copy with only the new header bindings removed (/tmp/cere-head-mute-qml.log, /tmp/cere-head-mute-qml-baseline.log); no new warning was introduced. git diff --check passed.
  • Installed the three QML files and updated documentation atomically into the existing user installation. The current UI was not restarted; reopen Cere to load the new header behavior. The broker already supports the master setting, so this change requires no new backend method.

Per-provider speech switches and ElevenLabs — September 30, 2026

  • Added Voice → Speak replies from for all seven conversation providers. Partial boolean settings updates validate atomically, merge with defaults and persist in SQLite. All providers start enabled for existing installations. Ordinary final replies and pinned conversational updates respect the switches; avatar bubbles remain visible. Disabling a provider cancels only its active/queued speech, preserving other providers' queued replies. Re-enabling does not replay old messages; explicit voice previews remain available.
  • Completed the preceding ElevenLabs request: selectable API speech engine, private saved/environment API key, paginated account voices, TTS model discovery and manual IDs, explicit cloud-text setting, streamed 24 kHz PCM with SoX tuning, HTTP retry integration, sanitized failures and cancellation. The API key stays outside settings, snapshots and reviewed backups. Redirects are refused. Interrupted audio is not replayed. Local references are never uploaded; using CERE as an ElevenLabs clone requires creating/selecting that voice in the ElevenLabs account. No new dependency was added. Deployment did not change the user's selected speech provider; a final live status read showed ElevenLabs selected, with the CERE IndexTTS profile still retained.
  • Added broker/elevenlabs.ts, qml/ElevenLabsSettings.qml and tests/elevenlabs.test.ts. Updated broker/credentials.ts, broker/types.ts, broker/store.ts, broker/core.ts, broker/tts.ts, qml/VoiceSettings.qml, tests/tts.test.ts, tests/pinned-replies.test.ts, tests/ui.cpp, README.md, docs/tts.md and this record. Unrelated existing workspace changes were preserved.
  • npm test: 427 passed, zero failed, one skipped of 428 (/tmp/cere-voice-final-all-tests.log). The skip is the existing installed-model opt-in check. node --test tests/tts.test.ts tests/pinned-replies.test.ts tests/elevenlabs.test.ts: 38/38 passed (/tmp/cere-voice-final-focused.log). Tests cover settings migration/persistence/validation, enabled versus muted pinned and unpinned replies, bubble retention, selective queue cancellation, preview exemption, streamed PCM boundaries, early playback, HTTP retries, no partial-stream replay, request abort, catalog pagination, key redaction/private permissions, provider switching and the real SoX pipeline into a test audio sink.
  • npm run typecheck, npm run build, /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/VoiceSettings.qml qml/ElevenLabsSettings.qml and git diff --check: passed (/tmp/cere-voice-final-types.log, /tmp/cere-voice-final-build.log, /tmp/cere-voice-final-qml.log). No repository-wide lint command exists; injected QML context references are informational. An initial UI run preceded completion of the rebuilt binary and could not find the new test slot; the final post-build run below passed.
  • With QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins", build/cere-ui-check providerSpeechSwitches elevenLabsSettings voiceSettings indexTtsSettings -o /tmp/cere-voice-final-ui.txt,txt: 6/6 passed including setup/cleanup. Screenshots inspected: /tmp/cere-ui-evidence/speech-provider-switches.png and /tmp/cere-ui-evidence/elevenlabs-settings.png.
  • PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" ctest --test-dir build --output-on-failure: 3/3 passed (/tmp/cere-voice-final-ctest.log). python3 tools/install-user.py --prefix build/voice-stage and node /tmp/cere-voice-stage-smoke.mjs passed, validating staged QML/modules, credential storage/redaction and provider settings (/tmp/cere-voice-final-stage.log, /tmp/cere-voice-stage-smoke.log). python3 tools/install-user.py installed the tested update into the user prefix (/tmp/cere-voice-final-install.log). The running broker/client was not restarted; restart Cere to load these new controls and backend methods.
  • ElevenLabs HTTP calls used fixtures; no account audio was generated or billed, so account access, voice quality and live latency remain unmeasured. API integration follows the official streaming/voice/model references linked in docs/tts.md. Test credentials were confined to temporary test state; no user's key or voice recording was sent to the service.

IndexTTS speech latency improvement — September 30, 2026

  • IndexTTS-2.5 now keeps Wav2Vec2-BERT reference encoding on CPU for CUDA devices below 10 GiB VRAM, including during construction; synthesis stays on GPU. The adapter calls upstream's unchanged embedding extraction/normalization and transfers the resulting embeddings to the synthesis device. Upstream's reference cache remains in use. Scoped constructor hooks restore on failure, CPU work defaults to at most four Torch threads unless OMP_NUM_THREADS is set, and capabilities/UI disclose the reference device. No upstream source or checkpoint files were modified. IndexTTS-2 placement is unchanged.
  • Changed files: broker/indextts-worker.py, broker/indextts-config.ts, qml/IndexTTSSettings.qml, tests/indextts-worker-test.py, docs/tts.md and this record. Installed the worker and QML updates atomically into the existing user installation. Configured the existing CERE profile for CUDA BF16, 40-character chunks and 30-minute idle unload. Preserved the full 15-second reference and original MP3, natural pitch and same-as-speaker emotion. Ollama was not stopped; the client/broker was not restarted.
  • python3 -B tests/indextts-worker-test.py passed, including new dependency-free CPU/GPU tensor routing and constructor-exception cleanup checks (/tmp/cere-index-speed-unit.log). node --test tests/indextts.test.ts tests/tts.test.ts passed 35/35 (/tmp/cere-index-speed-tests.log).
  • CERE_INDEXTTS_INTEGRATION=1 CERE_INDEXTTS_DEVICE=cuda:0 CERE_INDEXTTS_REFERENCE=/home/otectus/.local/share/cere/voices/indextts/2d295546-2c43-4f87-a898-bed3bf28142a/speaker-a36bd3f4-dee7-48ad-8d07-0ff5dc00454e.wav node --test tests/indextts-integration.test.ts passed all five languages with the real CERE reference, offline network denial, ordered audio and sample-rate/duration checks (/tmp/cere-index-speed-languages.log).
  • npm run typecheck, npm run build, /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/IndexTTSSettings.qml and git diff --check passed (/tmp/cere-index-speed-types.log, /tmp/cere-index-speed-build.log, /tmp/cere-index-speed-qml.log). With QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins", build/cere-ui-check indexTtsSettings -o /tmp/cere-index-speed-ui.txt,txt passed 3/3 including setup/cleanup. The full broker suite was not repeated for this scoped worker optimization.
  • node /tmp/cere-index-speed-test.mjs measured the actual full CERE reference on the RTX 4050 alongside Ollama: load 21.70 s, first audio after load with uncached reference 12.84 s, then first audio with cached reference 4.02 s. The warm 66-character sample generated 9.17 s of audio in 12.11 s. Total GPU memory at the end of synthesis was 5,130 MiB, returning to 681 MiB after worker exit (/tmp/cere-index-speed-test.log). These are single stochastic samples, not latency guarantees. The earlier CPU preview took approximately 90 seconds including cold load; it is not a controlled same-temperature comparison. Cold loading remains significant, and larger competing GPU allocations or optional Qwen emotion loading can still exhaust VRAM.
  • Live installed-app verification, node /tmp/cere-index-speed-live.mjs: both previews completed successfully through real playback. Cold first playback was 36.17 s; warm first playback was 4.56 s (/tmp/cere-index-speed-live.log). The selected CERE profile is active, GPU BF16 with CPU reference preparation, and the worker is left ready for the next reply. The user installation's worker matches the final source; the final thread-setting refinement preserves explicitly configured OpenMP behavior without changing the tested four-thread default.

IndexTTS selectable speech provider — September 30, 2026

Implemented IndexTTS-2.5 and optional IndexTTS-2 behind one isolated, uv-managed Python worker. The provider includes pinned installation/repair/verification, runtime capability gating, private voice profiles, all five emotion sources, 2.5-only duration control, ordered segment audio, generation cancellation, idle/provider-switch unload and the Voice settings panel. Existing Piper/Kokoro speech remains available. No host Python or npm dependency was added. The upstream source is pinned to d9e41aac89fd00b3d71497fddb287b7f24613712; exact checkpoint/auxiliary revisions, checksums and Torch/CUDA versions are in packaging/indextts-manifest.json. See docs/tts.md for installation, runtime layout/removal, license, usage and troubleshooting.

Files for this change: added broker/indextts-config.ts, broker/indextts-engine.ts, broker/indextts-worker.py, broker/indextts_audio.py, broker/indextts.ts, packaging/indextts-manifest.json, tools/setup-indextts.py, tools/benchmark-indextts.ts, qml/IndexTTSSettings.qml, tests/fixtures/indextts-worker.mjs, tests/indextts.test.ts, tests/indextts-worker-test.py and tests/indextts-integration.test.ts; updated the speech/settings integrations in broker/core.ts, broker/tts.ts, broker/types.ts, broker/store.ts, qml/VoiceSettings.qml, tests/ui.cpp, CMakeLists.txt, README.md, docs/tts.md, packaging/tts-NOTICES.md and this record. Other existing/concurrent workspace changes were preserved.

Validation commands and results:

  • npm test: 416 passed, zero failed, one skipped out of 417 (/tmp/cere-indextts-all-tests-recheck.log). The skipped check requires installed models and explicit opt-in; both versions were run separately below. The preceding full run hit the previously observed 30-second recovery-backup timing assertion (/tmp/cere-indextts-all-tests-final.log); CERE_TTS_DISABLED=1 node --test tests/recovery-races.test.ts then passed 4/4 in isolation (/tmp/cere-indextts-recovery-recheck.log) and the full rerun passed. Concurrent memory fixes resolved the earlier semantic-memory failures; those fixes are recorded separately below.
  • node --test tests/indextts.test.ts tests/tts.test.ts tests/pinned-replies.test.ts tests/core.test.ts: 68 passed (/tmp/cere-indextts-acceptance.log). The 14 IndexTTS cases include CJK/Arabic punctuation and atomic annotations, ordering/stale generations, hard cancellation/early iterator exit/idle exit, per-version emotion/range/capability gating, synthetic reference audio, resumable/checksummed downloads, SQLite persistence, private profile lifecycle, sanitized errors and switching providers during inference. Python tests run from this suite without model/GPU dependencies.
  • npm run typecheck and npm run build: passed (/tmp/cere-indextts-typecheck.log, /tmp/cere-indextts-build-final.log). The benchmark generator typing issue recorded in the earlier telemetry entry is fixed.
  • /usr/lib/qt6/bin/qmllint -I qml --unqualified info qml/IndexTTSSettings.qml qml/VoiceSettings.qml: passed (/tmp/cere-indextts-qmllint-final.log); unqualified runtime-injected App context references are informational. There is no repository-wide lint script. Python source AST checks and git diff --check also passed.
  • PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" ctest --test-dir build --output-on-failure: 3/3 passed (/tmp/cere-indextts-ctest.log).
  • With QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins", build/cere-ui-check indexTtsSettings voiceSettings -o /tmp/cere-indextts-ui.txt,txt: 4/4 passed, including setup/cleanup. The final IndexTTS-only screenshot rerun passed 3/3 (/tmp/cere-indextts-ui-final.txt). Screenshots inspected: /tmp/cere-ui-evidence/indextts-settings.png and /tmp/cere-ui-evidence/indextts-voice-profile.png.
  • python3 tools/install-user.py --prefix build/indextts-stage: passed (/tmp/cere-indextts-stage.log). A Node smoke check imports the staged engine/config, verifies the packaged worker/audio helper/installer/manifest/QML, probes the installed runtime and unloads it (/tmp/cere-indextts-stage-smoke.log).
  • Installed and checksum-verified both checkpoints and all required auxiliaries; 2.5 also has the optional Qwen emotion component. python3 tools/setup-indextts.py --version 2.5 --verify passed (/tmp/cere-indextts-verify-final.jsonl). The worker disables download fallbacks, sets offline library modes and denies Python socket DNS/connect operations. Real synthesis and an explicit denied-network probe passed. This is an application offline guard, not an OS network namespace sandbox.
  • CERE_INDEXTTS_INTEGRATION=1 CERE_INDEXTTS_DEVICE=cuda:0 CERE_INDEXTTS_REFERENCE=/home/otectus/.local/share/cere/kokoro/previews/kokoro-af_heart.wav OMP_NUM_THREADS=4 MKL_NUM_THREADS=4 node --test tests/indextts-integration.test.ts: passed all five 2.5 languages, checking ordered 22,050 Hz audio and duration (/tmp/cere-indextts-gpu-integration.log). With CERE_INDEXTTS_VERSION=2 CERE_INDEXTTS_DEVICE=cpu, the same command passed both 2 languages (/tmp/cere-indextts2-integration.log).
  • Real saved-profile import, playback conversion through SoX (pitch/volume and 48 kHz resampling) into the test audio sink, lazy Qwen text-emotion synthesis on CPU, and profile deletion passed (/tmp/cere-indextts-pipeline.log). No physical speaker was used. The temporary profile was deleted; the user's default provider/voice was not changed.

Measurements: RTX 4050 Laptop 6,141 MiB, driver 615.71.09, 31 GiB RAM, Torch 2.8.0+cu128, Python 3.11.13, OMP_NUM_THREADS=4 MKL_NUM_THREADS=4. Command: CERE_INDEXTTS_REFERENCE=/home/otectus/.local/share/cere/kokoro/previews/kokoro-af_heart.wav CERE_INDEXTTS_EVIDENCE=/tmp/cere-indextts-final-measurements OMP_NUM_THREADS=4 MKL_NUM_THREADS=4 node tools/benchmark-indextts.ts. Evidence: /tmp/cere-indextts-final-measurements/measurements.json and /tmp/cere-indextts-final-benchmark.log. These are single stochastic runs on a shared desktop. GPU chunks target 40 characters under low-VRAM gating; CPU uses the configured 160-character target.

Model/device/precision Load Loaded / peak total VRAM First audio after load, 200 characters RTF Stop to process exit
2.5 CUDA BF16 23.36 s 5,255 / 5,777 MiB 3.06 s 0.78 0.184 s
2.5 CUDA FP32 OOM after 19.00 s peak 5,830 MiB unavailable unavailable worker exited
2.5 CPU FP32 20.59 s CPU inference 42.83 s 7.63 0.245 s
2 CUDA FP16 OOM after 23.39 s peak 5,822 MiB unavailable unavailable worker exited

BF16 unload returned GPU memory to its 3 MiB baseline. During later runs another Ollama process allocated about 674 MiB; IndexTTS exited and was absent from the GPU process list, while the shared GPU total remained 685 MiB. The 2 FP16 attempt returned to its 685 MiB baseline (/tmp/cere-indextts2-fp16.log). CPU hardware detection briefly creates a small CUDA context that also disappears on process exit. End-to-end cold profile preview reached the test sink in 22.91 s; cold lazy-Qwen CPU text-emotion synthesis completed in 47.16 s. OOM never triggers a silent retry or device fallback.

Remaining limits/open questions: the 6 GB GPU has little headroom, and competing models can also prevent BF16 loading. FP32 CUDA and optional 2 FP16 synthesis timings are unavailable after measured OOM; whether 2 FP16 fits an otherwise empty GPU remains unverified. CPU works but is slow. CUDA kernels/DeepSpeed were not exercised (no CUDA compiler installed); MPS/XPU are not exposed, and non-Linux platforms are best effort. Stop latency covers the software worker boundary, not physical speaker buffers. Reference minimum 3 seconds is Cere's quality policy, not an asserted upstream guarantee. No unresolved implementation decision blocks use. The workspace build and staged package are updated; the running installed client was not restarted or replaced.

Semantic memory recall failures — September 30, 2026

  • Fixed the shared cause of the three previously recorded failures: optional Qdrant collection setup/query could consume the 500 ms retrieval deadline before canonical embedding_search ran. The already-aborted signal then discarded otherwise usable local semantic recall. Retrieval now obtains canonical embedding hits first and retains them when the optional projection times out or returns no hits. Successful projected hits retain their existing ranking precedence; final canonical hydration and policy/erasure validation still apply.
  • Isolated the Ollama fixtures in tests/knowledge.test.ts and tests/review-service.test.ts from the host's Qdrant configuration. Added deterministic initialization/query timeout regressions using a query with no lexical overlap, plus an empty-projection/erasure-during-lookup regression. Both timeout regressions failed before the production fix (/tmp/cere-memory-regression-before.log). The original three failures were reproduced before editing (/tmp/cere-memory-baseline.log); a diagnostic trace confirmed embeddings completed in milliseconds while projection lookup consumed the deadline (/tmp/cere-memory-trace.log).
  • CERE_TTS_DISABLED=1 node --test tests/knowledge.test.ts tests/review-service.test.ts passed 27/27 before adding the final empty-projection/erasure regression (/tmp/cere-memory-focused.log). The final npm test run, including that regression, passed 416/417, with zero failures and one skip for the opt-in installed IndexTTS language check (/tmp/cere-memory-full-tests.log). This resolves the three memory-test blockers recorded in the earlier entries below.
  • npm run typecheck and git diff --check passed (/tmp/cere-memory-typecheck.log). No native/UI code changed; the broker tests execute the TypeScript source directly. No installation or service restart was performed.

Workspace telemetry — September 30, 2026

  • Added an opt-in Linux telemetry worker, bounded in-memory session/workspace state, native inotify and flock helpers, same-user Unix IPC, Fish/Bash/Zsh hooks, a native prompt reporter, explicit stderr wrapper, settings controls and request-only Ollama/direct-API context. No new npm/system dependency was added. Setup, the one-line file inventory, manual walkthrough, bounds and limitations are in docs/workspace-telemetry.md.
  • npm run build passed (/tmp/cere-telemetry-build.log). CERE_TTS_DISABLED=1 node --test tests/telemetry.test.ts tests/telemetry-persistence.test.ts tests/telemetry-shells.test.ts passed 13/13 (/tmp/cere-telemetry-focused.log). The focused suite covers canonical containment and deletion/symlink escapes, sequence/expiry isolation, redaction and report budget, actual Unix sockets and inotify, atomic HEAD/file saves, pause/clear races, persistence/backups/diagnostics, forced-worker native cleanup, and interactive shell status/coexistence/nesting/interrupt/install tests.
  • The full npm test run passed 409/413, with 3 failures and 1 skip (/tmp/cere-telemetry-full-tests.log). The failures are the previously documented semantic-memory assertions: “semantic graph memory survives restart…” and “embedding outages preserve canonical memory…” in tests/knowledge.test.ts, and F-004 in tests/review-service.test.ts. The skipped check is the opt-in installed IndexTTS language test. This is not a green full-suite claim.
  • npm run typecheck is currently blocked by concurrent IndexTTS benchmark work: tools/benchmark-indextts.ts:30 and :51, TS2554 (generator .return() called without its required argument). That file was not modified for telemetry. Earlier typechecks passed before that concurrent file appeared. Current evidence: /tmp/cere-telemetry-types.log.
  • npx tsc -p tsconfig.mobile.json, node tools/mobile-contract.ts --check, git diff --check, and /usr/lib/qt6/bin/qmllint -I qml qml/TelemetrySettings.qml passed. QML lint used LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins"; its output is empty (/tmp/cere-telemetry-qmllint.log). There is no repository-wide TypeScript/C++ lint script.
  • With QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins", ./build/cere-ui-check settingsSectionNavigation workspaceTelemetryControls -o /tmp/cere-telemetry-ui.txt,txt passed 4/4 including setup/cleanup. The subsequently extended workspaceTelemetryControls run passed 3/3, including 4,096 rename-over saves with 75 heartbeat samples and a maximum UI gap of 23 ms (/tmp/cere-telemetry-ui-load.txt). Screenshot: /tmp/cere-ui-evidence/workspace-telemetry.png. These are offscreen acceptance checks, not a physical-desktop walkthrough.
  • PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" ctest --test-dir build --output-on-failure passed 3/3 native checks (/tmp/cere-telemetry-ctest.log).
  • python3 tests/telemetry-shells.py measured added p95 prompt latency of 0.54 ms Fish / 0.86 ms Bash / 0.31 ms Zsh, with 40 prompts per condition. node tools/benchmark-telemetry.ts measured 0.22% of one core idle, 130.9 MiB idle RSS, and 178.7 MiB peak RSS under 148,000 events plus six 4,096-file Git checkouts and 6,000 excluded-file writes. It reported degradation and 65,053 drops rather than unbounded queues; pending work drained to zero. Host event-loop p99/max were 12.17/21.00 ms. Evidence: /tmp/cere-telemetry-shells.json, /tmp/cere-telemetry-load.json. These isolated process figures are not total-client memory measurements or hard real-time guarantees.
  • python3 tools/install-user.py --prefix build/telemetry-stage and node /tmp/cere-telemetry-stage-smoke.mjs passed. The staged native bindings, worker, reporter, all three rc installers, Pause/Clear and owned socket cleanup were exercised (/tmp/cere-telemetry-install.log, /tmp/cere-telemetry-stage.log). The running installation and user rc files were not changed, and no client/service restart was performed.
  • Remaining acceptance limits: full-suite/typecheck blockers above; CLI telemetry injection remains explicitly withheld because no verified non-persistent CLI input channel exists. Remote conversations also omit telemetry. The injected block is excluded from automatic persistence; ordinary model replies may mention/paraphrase telemetry facts. External provider retention is outside Cere's control. Root .gitignore positive patterns are supported; nested and negated patterns are not. No focus integration or managed terminal was added.

HTTP retries and conversation model switching — September 30, 2026

  • Added a reusable HTTP-status retry wrapper to native OpenAI, Claude API, Google AI API and Ollama requests. Defaults are three retries, 1/2/4-second exponential delays plus up to 25% jitter, bounded Retry-After, cancellation, and status/count/delay logs. Streams, completed tool actions, unknown transport outcomes and non-transient statuses are not replayed. Cloud retry progress is an activity entry.
  • The desktop Model control now supports all seven managed providers. Changes apply to the next turn, preserve the session, transcript, draft and native CLI conversation ID, validate model-specific CLI effort and Ollama image/tool compatibility, and reject active or stale changes. API model changes keep portable messages and recorded tool evidence while removing model-specific reasoning/signatures from the working history. Custom API IDs work without a successful catalog fetch. Mobile configuration remains Ollama-only.
  • npm run build and npm run typecheck passed. Logs: /tmp/cere-retry-build.log, /tmp/cere-retry-typecheck-final.log.
  • CERE_TTS_DISABLED=1 node --test tests/http-retry.test.ts tests/session-models.test.ts tests/api-providers.test.ts tests/models.test.ts tests/ollama.test.ts tests/providers.test.ts tests/antigravity.test.ts tests/core.test.ts tests/remote.test.ts tests/erasure-boundaries.test.ts initially passed 136/138 cases. The two old Ollama expectations assumed HTTP 503 failed immediately; after updating them for retry recovery/exhaustion, CERE_TTS_DISABLED=1 node --test tests/ollama.test.ts passed all 23 cases. Other passing checks were reused. Logs: /tmp/cere-retry-focused.log, /tmp/cere-retry-ollama.log.
  • An additional adapter-close failure regression and the affected memory integrations passed with CERE_TTS_DISABLED=1 node --test tests/session-models.test.ts tests/memory-providers.test.ts tests/shared-memory.test.ts tests/memory-optimization.test.ts (23/23). Log: /tmp/cere-retry-history-tests.log. Together these runs cover 155 distinct passing broker cases. Retry coverage includes all requested status codes, SDK-style errors, jitter, Retry-After dates/limits, exhaustion, cancellation, unchanged request bodies, non-replayed streams/tools, and redacted logs. Model coverage includes real API adapter continuation, native adapter recreation/resume, draft/transcript persistence, configuration conflicts, permissions and failed shutdown.
  • With LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic, build/cere-ui-check apiProviderSetup conversationModelSwitching ollamaConversation -o /tmp/cere-retry-ui.txt,txt passed 5/5 including setup/cleanup. After refining catalog selection preservation, build/cere-ui-check conversationModelSwitching responsiveLayoutsAndDesktopActions -o /tmp/cere-retry-ui-responsive.txt,txt passed 4/4, with only the existing offscreen propagateSizeHints warnings. Screenshot inspected: /tmp/cere-ui-evidence/conversation-model-switch.png.
  • Provider HTTP calls used fixtures; no live billable API calls were made. The full suite was not rerun for this change; the three previously recorded semantic-memory failures below remain unresolved. The workspace build was updated; the running installation was not restarted.

Dedicated providers — September 30, 2026

  • Added AntiGravity CLI and native OpenAI Responses, Claude Messages, and Google GenerateContent API adapters, connection/key controls, model discovery, and session/handoff/branch selection. Keys remain outside the transcript database, snapshots and reviewed backups. The new providers execute on the desktop; remote creation/sending remains disabled explicitly.
  • npm run typecheck and npm run build passed. Native UI changes were rebuilt with PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" cmake --build build --parallel 4. Logs: /tmp/cere-provider-typecheck-final.log, /tmp/cere-provider-build.log, /tmp/cere-provider-ui-build-final.log.
  • CERE_TTS_DISABLED=1 node --test tests/antigravity.test.ts tests/api-providers.test.ts tests/ollama.test.ts tests/providers.test.ts tests/core.test.ts tests/memory-providers.test.ts tests/erasure-boundaries.test.ts tests/workflows.test.ts tests/remote.test.ts passed 118 tests. The subsequent additional broker dispatch/resume case passed with all 13 tests in CERE_TTS_DISABLED=1 node --test tests/api-providers.test.ts. Logs: /tmp/cere-provider-focused-final.log, /tmp/cere-api-final-tests.log.
  • API fixtures verify native request shapes, streaming UTF-8/SSE boundaries, images, tool results, retained reasoning/signatures, local history/resume, cancellation, incomplete streams, HTTP error redaction, cloud-memory gating and credential isolation. AntiGravity subprocess fixtures verify catalog parsing, resume IDs, distinct conversational messages, explicit bypass flags, stop and error handling.
  • With LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic, build/cere-ui-check apiProviderSetup settingsSectionNavigation ollamaConversation -o /tmp/cere-provider-ui-final.txt,txt passed the new setup and navigation checks. After updating both old provider-count assertions, build/cere-ui-check ollamaConversation -o /tmp/cere-provider-ui-regression.txt,txt passed all three selected/setup/cleanup cases, including the existing conversation and handoff flow. responsiveLayoutsAndDesktopActions also passed at the supported compact/workspace sizes in /tmp/cere-provider-ui.txt; its only warnings were the offscreen plugin's unsupported propagateSizeHints. Screenshot: /tmp/cere-ui-evidence/provider-menu-360x560.png.
  • A live AntiGravity turn through AntigravityAdapter returned CERE_PROVIDER_OK and completed successfully; the installed agy models catalog returned 14 models. Log: /tmp/cere-antigravity-live.log. No OpenAI, Anthropic or Google API keys were configured, so those providers were exercised with protocol fixtures rather than live billable generation.
  • npm test passed 345/349 tests. A serial rerun with CERE_TTS_DISABLED=1 node --test --test-concurrency=1 tests/knowledge.test.ts tests/review-service.test.ts tests/recovery-races.test.ts passed 26/29, including the recovery timing test. Three semantic-memory assertions still receive keyword instead of semantic: two in knowledge.test.ts and F-004 in review-service.test.ts. Logs: /tmp/cere-provider-full-tests.log, /tmp/cere-provider-isolated-tests.log. These failures remain unresolved; the complete suite is not green.

Validated on Arch/CachyOS, Hyprland 0.56.2, Qt 6.11.2, Node 26.8.2, Codex CLI 0.158.0, and Claude Code 2.1.284 on September 28, 2026.

Automated checks

  • npm run build: native application and Qt UI validation executable compile successfully.
  • npm run typecheck: TypeScript checks pass.
  • npm test: broker regressions cover fragmented JSON, input bounds, project trust, concurrent submissions, streaming reconciliation, stale approvals, permission revocation, grant scope, argument injection, and recovery without replay.
  • Animation update: 12 broker tests, 10 motion checks, and 7 native UI checks passed. The broker cases were also run explicitly with node --test --test-isolation=none tests/core.test.ts.
  • build/cere-ui-check: exercises navigation, captures each main screen, verifies a draft survives session switching, switches normal/overlay presentation, and checks fullscreen overlay placement. Screenshots: /tmp/cere-ui-evidence/; text report: /tmp/cere-ui-evidence.txt.
  • build/cere-motion-check: verifies pose bounds, transparent frame gutters, partial alpha coverage, gesture interruption, approval priority, stale timer rejection, quiet/reduced/hidden behavior, and shuffle-bag idle variety. Report: /tmp/cere-motion-evidence.txt.
  • The native visual checks also exercise jumping, pickup/landing, broker-relayed previews, hiding, and 50%, 100%, and 300% scale. Quiet mode produces identical captured frames after cancelling an active gesture. Final enlarged artwork was inspected against light and dark backgrounds after deterministic matte cleanup. The original GIFs referenced by that check are not included in this repository.
  • tools/live-check.ts: both actual CLIs call Cere’s harmless saved printf script through MCP, expose provider and Cere approval requests, return CERE_APPROVED, retain that value in a second turn, and retain it after their provider process is disconnected and resumed. Evidence: /tmp/cere-provider-evidence.jsonl.
  • Permission-denial runs confirmed that the test script did not execute when approval was rejected.
  • makepkg --nodeps --noconfirm: built the local Arch package using extracted CMake/Ninja/LayerShellQt dependencies; normal installation must resolve declared system dependencies.

Practical coverage limits

The local desktop has three monitors, all currently at scale 1. Dragging and output placement were exercised on this desktop. Mixed-DPI physical displays, physical monitor unplugging, suspend/resume, and screen lock were not exercised. Layer-shell places Cere over application windows; it does not override security surfaces or guarantee ordering against unrelated overlay applications.

Linked terminal sessions expose lifecycle and navigation only. Existing CLI transcripts can be selected for explicit handoff after their terminal writer stops. Claude history discovery reads a bounded subset of recent JSONL transcripts and can skip unknown formats. Native provider transcript history is preserved for resumption, while Cere’s visible transcript starts with the messages it has observed.

MCP forms support primitive values. URL sign-in requests show their HTTP(S) destination and need explicit confirmation; other URL schemes are declined. Unsupported complex forms fail closed and request terminal continuation. A broad Cere grant does not override the provider’s own permission requirements.

A final 60-second sample with the updated pet visible and no active CLI task measured 1.98% of one CPU core across Cere's three processes. Proportional set size was 216.8 MiB; summed resident set size was 356.2 MiB (including shared library mappings counted in multiple processes). Resource evidence: /tmp/cere-animation-resources.json. The earlier sparse GIF loop measured 0.15% CPU, 199.4 MiB PSS, and 331.2 MiB summed RSS. Smooth transforms and more detailed cached artwork increase resource use; summed RSS remains above the original 200 MiB budget. Static holds avoid continuous rendering, and hidden/quiet/reduced-motion hosts stop their animation timers.

Performance budgets are not guarantees across hardware. No cross-platform support claim is made beyond this Hyprland setup.

UI refinement and per-user installation — September 29, 2026

  • Rebuilt the native application with npm run build; npm run typecheck and all 12 broker tests passed, including the new live audio-status integration compiling successfully.
  • build/cere-ui-check -o /tmp/cere-ui-refinement.txt,txt passed all 8 cases with no QML warnings. The added case exercises every tab at 360×560, 440×720, 720×580 and 1040×780, checks control bounds with long app/window names, reaches the bottom settings actions, opens session/script dialogs and provider menus, filters Desktop actions, and starts/cancels an actual isolated timer.
  • After the final dialog margin adjustment, build/cere-ui-check responsiveLayoutsAndDesktopActions -o /tmp/cere-ui-dialog-refinement.txt,txt passed all 3 selected/setup/cleanup cases. Screenshots are under /tmp/cere-ui-evidence/, including desktop-1040x780-top.png, desktop-360x560-bottom.png, provider-menu-360x560.png, and script-dialog-360x560.png.
  • build/cere-motion-check -o /tmp/cere-motion-refinement.txt,txt passed all 10 checks. Native checks confirmed avatar dimensions at 50%, 100% and 300% without the old nameplate, and floating/overlay presentation above fullscreen windows.
  • python3 tools/install-user.py --prefix build/user-install staged the application, then python3 tools/install-user.py installed beneath ~/.local. The desktop entry passed desktop-file-validate, and the user unit passed systemd-analyze --user verify. The binary loads its bundled LayerShellQt library through $ORIGIN; its QML, assets and broker resolve from the installed data directory. Existing startup preference was retained and redirected to the installed launcher.
  • The previous development broker had no active sessions before migration. Installed cere-broker.service started successfully and its audio.status RPC returned the actual 100%, unmuted output state.
  • Final live checking exposed legacy Hyprland dispatch calls. Window focus/move/workspace actions and floating-pet placement now select the available Lua dispatcher API, retaining the legacy fallback. Syntax was checked against the official dispatcher documentation. node /tmp/cere-desktop-action-check.mts successfully focused Cere and exercised move/switch on its existing workspace; results are in /tmp/cere-desktop-action-check.json. The final rebuild, TypeScript check, 12 broker tests and full 8-case GUI suite passed after this correction. An intermediate popup check lost focus while another live desktop check was running; the final GUI suite ran without concurrent desktop input.

Satty capture and Spotify controls — September 29, 2026

  • Capture previously waited in Slurp and never opened Satty. It now captures the focused display, opens a separate Satty editor with the crop tool, and returns only the user-saved output. Save/copy output and the temporary original use different files; cancellation returns no image, and the original is removed on success, cancellation, and failure. Duplicate captures are rejected while editing.
  • Media previously chose the first MPRIS bus name, which was Chromium on this desktop. It now defaults to Spotify, shows its playback state, checks advertised capabilities, and sends each UI command to the displayed player's bus name. A disappeared target produces an error instead of redirecting the command. Other playing MPRIS applications remain the fallback when Spotify is absent.
  • npm run build and npm run typecheck passed. npm test passed all 17 tests, including five new process-level regressions covering competing players, explicit/disappeared targets, unavailable controls, Satty output, cancellation, editor errors, missing dependencies, and duplicate requests. One sandboxed Node worker exited without individual test output; the complete suite passed outside the sandbox.
  • build/cere-ui-check captureEditorRoundTrip -o /tmp/cere-satty-ui-check.txt,txt passed all 3 selected/setup/cleanup cases. The actual button opened real Satty; Enter saved a valid PNG and restored Cere's preview, while Escape restored Cere with cancellation feedback. Both paths removed the temporary original.
  • Navigation and responsive layout checks passed at all four existing window sizes in /tmp/cere-media-ui-check.txt. build/cere-ui-check spotifyPlaybackRoundTrip -o /tmp/cere-spotify-ui-check.txt,txt passed all 3 cases after correcting QVariant decoding in the test harness. Cere's actual Play/Pause button changed Spotify's D-Bus playback state in both directions and restored the initial state. Live next/previous were not exercised to avoid changing the listening queue; their player routing is covered by the process-level tests.
  • Evidence screenshots: /tmp/cere-ui-evidence/satty-saved-preview.png and /tmp/cere-ui-evidence/spotify-controls.png. API references: Satty and MPRIS Player.

Mouse-following roaming — September 29, 2026

  • Roaming now follows the pointer at up to 75 logical pixels/second with gradual acceleration and deceleration. It stops outside the character's bounding radius, ignores small pointer movements while settled, and follows onto the pointer's display. Roaming-area presets were replaced in the UI; persisted legacy bounds remain compatible but no longer constrain following.
  • Pointer/fullscreen sampling runs at 5 Hz only while following is allowed; the 16 ms movement timer runs only while moving. Hover/menu interaction, dragging, either open panel, active tasks/approvals, fullscreen applications, quiet/reduced motion, hiding, and disconnection pause movement. Final positions are saved when movement settles or pauses.
  • npm run build passed. build/cere-motion-check -o /tmp/cere-follow-motion.txt,txt passed 13 cases, including speed limits, stopping distance, reversal, pointer interaction, delayed-frame bounds, scaled pets, and negative monitor coordinates.
  • The focused desktop checks in /tmp/cere-follow-ui.txt passed following in floating mode, hover/quiet/disabled/panel pauses, position persistence, overlay switching, and existing gesture/reduced-motion behavior. The initial output-transition check failed; its setup was refined to choose monitors sharing an edge and verify the cursor warp. build/cere-ui-check mouseFollowingAcrossOutputs -o /tmp/cere-follow-outputs.txt,txt then passed all 3 selected/setup/cleanup cases, moving the overlay from HDMI-A-1 to eDP-1 and persisting the new output. Desktop checks restore the cursor and use isolated Cere state.

Ollama integration — September 29, 2026

  • npm run build and npm run typecheck passed. npm test passed all 34 broker tests. Ollama cases exercise catalog filtering, cloud labels, saved defaults, pinned endpoints, fragmented Unicode streams, multi-turn history through disconnect/restart, images, tool results, permission revocation, delegation ownership, cancellation, Stop races, and crash recovery without replay.
  • Native Qt UI checks used an isolated HTTP Ollama fixture. build/cere-ui-check navigationAndScreenshots projectAndDraft ollamaConversation responsiveLayoutsAndDesktopActions passed all 6 selected/setup/cleanup cases. After the handoff trust correction, build/cere-ui-check ollamaConversation activityAndPermissionBubble -o /tmp/cere-ollama-ui-final.txt,txt passed all 4 cases, with no QML warnings. Both commands used the local dependency library/plugin paths and QT_QUICK_CONTROLS_STYLE=Basic as documented in README.
  • Inspected rendered screenshots in /tmp/cere-ui-evidence/ollama-settings.png, ollama-new-session.png, ollama-conversation.png, and ollama-model-options.png. The UI exercised saving a default, creating a conversation with that default, streaming a response, selecting another model, disabling tools for a model without tool support, and creating a handoff draft only after project trust is confirmed.
  • Live gpt-oss:20b-cloud passed conversation recall after provider disconnect and the approved saved printf command. Evidence: /tmp/cere-ollama-live-AqXe9L/report.json and its private test database. That run declined a delegation when the model shortened the exact test prompt; the test harness was clarified to supply explicit JSON arguments.
  • node tools/check-ollama.ts gpt-oss:20b-cloud codex --delegate-only then passed actual Codex delegation, result retrieval, and final reporting. Evidence: /tmp/cere-ollama-live-Uqff1K/report.json.
  • node tools/check-ollama.ts gpt-oss:20b-cloud claude --delegate-only passed the same workflow with actual Claude Code. Evidence: /tmp/cere-ollama-live-ydLrQT/report.json.
  • Live checks used separate temporary brokers, projects, settings, and histories. No user project content was sent. This machine's available chat models are cloud-backed; inference on a locally downloaded chat model was not exercised. The same native API is covered by the local fixtures, including images; live vision inference and authenticated reverse proxies were not exercised.

Web search and embedding memory — September 29, 2026

  • npm run build and npm run typecheck passed. npm test passed all 46 broker tests. Added regressions cover the three HTML search parsers, fallback and pinned providers, local SearXNG JSON, private-network rejection, page limits and redirects, cancellation, settings migration, embedding prefixes and response validation, Unicode segmentation, restart persistence, project/server isolation, embedding outages, model/digest/dimension changes, edits during indexing, clear/disable races, bounded tool context, native model tools, source persistence, and explicit search for plain chat models.
  • With the README’s local Qt library/plugin environment, build/cere-ui-check ollamaConversation searchAndMemory responsiveLayoutsAndDesktopActions -o /tmp/cere-knowledge-ui-release.txt,txt passed all 5 selected/setup/cleanup cases, with no QML warnings. build/cere-ui-check compactSessionNavigation -o /tmp/cere-knowledge-compact.txt,txt passed all 3 cases. The combined run had a compositor focus timeout; the focused repeat passed. The checks use separate brokers, state directories, and local Ollama/SearXNG HTTP fixtures.
  • Screenshots inspected: /tmp/cere-ui-evidence/web-search-settings.png, memory-settings.png, project-memory.png, and web-search-conversation.png. The UI checks exercise selecting SearXNG, enabling memory, checking the default model, adding a fact, searching with a model without tool support, retaining source buttons, and resetting the search choice. Responsive controls were checked at 360×560, 440×720, 720×580, and 1040×780. Dialog clicks now scroll controls into view, and the search toggle fits in the existing chat action row.
  • Real nomic-embed-text returned 768-dimensional embeddings. Semantic recall of synthetic preferences and project facts, recall after broker restart in another conversation, live automatic search, source reading, and gpt-oss:20b-cloud use of injected memory passed. Final embedding/context evidence is /tmp/cere-knowledge-live-7yB0cj/report.json. That run then encountered an Ollama Cloud internal server error during the model web-tool check; node tools/check-knowledge.ts gpt-oss:20b-cloud --web-only passed on retry, in /tmp/cere-knowledge-live-v3I4AF/report.json.
  • The initial live memory-save call invented a replacement ID. The tool schema and error now explicitly explain creating with text only and obtaining real IDs before replacement. node tools/check-knowledge.ts gpt-oss:20b-cloud --memory-only passed, saving the requested synthetic fact through the actual model tool. Evidence: /tmp/cere-knowledge-live-vP9sdW/report.json. The prior successful model search run is also retained in /tmp/cere-knowledge-live-2TKIUz/report.json.
  • DuckDuckGo returned usable live results. Brave returned HTTP 429 and Mojeek returned a CAPTCHA on this connection. Those paths report provider failures; fallback parsing is covered by fixtures. A real private SearXNG deployment was not available; its protocol was tested through local HTTP fixtures. No CAPTCHA bypass or API subscription is used.
  • python3 tools/install-user.py --prefix build/knowledge-install staged the app. A second temporary installation outside the repository loaded its broker and HTML parser independently of workspace dependencies and successfully checked the real embedding model. Evidence: /tmp/cere-knowledge-install-e0_9fgwt/smoke.json and install.log. Production npm dependencies are bundled by CMake, and the Arch build installs its locked dependencies before staging.
  • Live checks used synthetic text in private temporary databases; user conversations and settings were not used. Chat inference was exercised through the available Cloud model; local chat-model inference was not available. Memory/search are opt-in. Embedding outages fall back to keyword matches, and model tool use remains model-dependent. Existing histories are preserved; only completed turns after enabling memory enter the new index.

Session Markdown and independent permission bypasses (2026-09-29)

  • npm test: 56 passed. New checks cover defaults and persistence, strict boolean validation, independent CLI/computer categories, pending-request acceptance, questions remaining unanswered, Pause/revocation, project trust, saved scripts, delegation, Claude MCP entry permissions, native provider launch arguments, Codex sandbox restoration and terminal-wrapper settings.
  • npm run typecheck and npm run build: passed.
  • With the README's Qt dependency environment, build/cere-ui-check markdownMessages permissionBypassSettings activityAndPermissionBubble -o /tmp/cere-markdown-permissions-final-ui.txt,txt: all 5 selected/setup/cleanup cases passed without QML warnings. Checks include headings, emphasis, strikethrough, inline/fenced code, nested lists, task lists, tables, local images, links and rejected executable URL schemes, Unicode, original Markdown copying, selection, streaming replacement, compact widths and horizontal table scrolling. Screenshots: /tmp/cere-ui-evidence/markdown-formatted.png, markdown-compact.png, markdown-wide-table.png, and permission-bypass-settings.png.
  • ollamaConversation and responsiveLayoutsAndDesktopActions also passed in the combined run recorded in /tmp/cere-markdown-permissions-ui.txt. That run exposed an incorrect test reference to Flickable's content item and a compositor timing issue in the existing multiple-approval click. The focused final run above passed after correcting the reference and waiting for window geometry to settle.
  • A no-inference probe against installed Codex 0.158.0 confirmed effective on-request/readOnly and never/dangerFullAccess policies in temporary threads. Claude and per-turn Codex wiring use deterministic subprocess fixtures; no billed model turns were run.
  • python3 tools/install-user.py --prefix build/markdown-permissions-install: staged successfully (log /tmp/cere-markdown-stage.log). The staged native launcher ran with QT_QPA_PLATFORM=offscreen; its independently imported broker passed a defaults/project-trust/printf smoke check using a temporary database.

Editable personality (2026-09-29)

  • npm run typecheck and npm run build: passed. npm test: 61 passed; log /tmp/cere-personality-tests.log. After moving Claude's personality to a private prompt file, node --test tests/providers.test.ts: all 5 passed; log /tmp/cere-personality-provider-tests.log.
  • With the README's Qt dependency environment, build/cere-ui-check personalitySettings responsiveLayoutsAndDesktopActions -o /tmp/cere-personality-ui.txt,txt: 4 selected/setup/cleanup cases passed without QML warnings. Covered default text, save/discard/reset, empty values, length/error handling, draft preservation during navigation and external settings updates, and responsive layouts. Visually inspected /tmp/cere-ui-evidence/personality-settings.png.
  • Broker/provider fixtures verify settings migration and persistence, atomic validation, all three prompt paths, Codex thread continuity and existing developer instructions, unchanged permission policies, per-turn updates, Ollama tool-loop consistency, and private Claude prompt-file cleanup. Installed Codex protocol generation confirmed the start/resume instruction fields; installed Claude recognized --append-system-prompt-file. No live model inference or installed-app update was performed.

Ollama context capacity (2026-09-29)

  • Removed Cere's 8,192-token cap when the model advertises a larger window. Context discovery handles architecture-specific metadata (including the empty Cloud architecture), modern /tags details, older /show responses, and configured/default fallbacks. The same capacity controls prompt budgeting and every chat/tool-loop request. Model descriptions display the selected window; overflow errors include the estimated turn size and available conversation budget.
  • npm test: 65 passed. npm run typecheck and npm run build: passed. Regressions cover small through million-token capacities, smaller/larger num_ctx defaults, multimodal encoder metadata, invalid metadata, missing metadata, full long messages and tool results, model switching, metadata changes, restart, genuine overflow and preservation of full history. After excluding unrelated model capabilities before metadata lookup, node --test tests/ollama.test.ts tests/knowledge.test.ts: 33 passed; typecheck passed again.
  • LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check ollamaConversation responsiveLayoutsAndDesktopActions -o /tmp/cere-context-ui.txt,txt: 4 selected/setup/cleanup cases passed, with no QML warnings. Inspected /tmp/cere-ui-evidence/ollama-model-options.png, including the displayed context fallback.
  • node /tmp/cere-context-live-check.mjs: all six available chat models passed against Ollama 0.34.4. Each received the same synthetic 92,817-character message and correctly returned a marker from its beginning. GPT-OSS 20B and 120B requested 131,072-token windows and evaluated 20,301 prompt tokens; Gemma 4 31B requested 262,144 and evaluated 22,952; Nemotron 3 Nano, Super and Ultra requested 262,144 and evaluated 21,547 each. Evidence: /tmp/cere-context-live-FXZ4Dm/report.json and its isolated test database. User conversations, settings and project contents were not used.
  • Available chat models were all Cloud-backed; local inference at maximum context was not exercised. Larger local windows require additional RAM/VRAM. Token budgeting remains an estimate and reserves space for instructions, tools and a reply. The installed running application was not updated or restarted.

Expressive character acting (2026-09-29)

  • Added eight identity-matched masked expressions in assets/cere-expressions.png; the original artwork remains intact. The built-in image-generation prompt and transparency correction are recorded in artwork/expressions-prompt.txt. Atlas crops preserve aspect ratio and foot anchoring, and the input mask includes both textures. Inspected actual rendered skeptical, tender, listening, thinking, speaking, permission and celebration screenshots under /tmp/cere-ui-evidence/acting-*.png.
  • Native policy now distinguishes focused listening, thinking, streamed replies, tool work, permissions and persistent problems. Priority interruptions settle into the latest state; terminal outcomes distinguish completion, cancellation and failure, and a cancellable 450 ms completion delay prevents adjacent faults/new work from briefly celebrating. Attention is shared with the other host and retained in broker snapshots. Local opening-phrase tone cues are conservative, optional, bounded, deduplicated and rate limited; they never infer success from prose or replay history.
  • Motion intensity defaults to 0.7. Idle gestures have longer shuffled pauses; supported resting poses blink irregularly, and subpixel breathing updates at 20 Hz instead of display refresh rate. Quiet/hidden hosts stop acting; reduced motion and zero intensity retain readable static state poses without animation timers. New expressions do not require any further artwork; matching closed-eye cels would extend blinks to those new poses in a future artwork pass.
  • npm run typecheck and npm run build: passed. Build log: /tmp/cere-expressive-build.log. npm test: 69 passed, /tmp/cere-expressive-broker-tests.log. Provider fixtures cover reasoning versus tool activity, private-thinking text exclusion, terminal races, setting persistence/validation and attention snapshots; no billed inference was used.
  • ./build/cere-motion-check -o /tmp/cere-expressive-motion.txt,txt: 15 passed. Covers both textures/alpha/timeline bounds, priority, stale completion tokens, static state behavior, restrained idle timing, tone-cue exclusions and the existing follower's speed/stopping limits.
  • Using LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic, the build/cere-ui-check expressiveActing petGesturesAndReducedMotion cases passed in /tmp/cere-expressive-animation-final.txt. They exercise real fixture streaming/tool/outcome events, composer focus, attention across hosts, live tone, static frame equality, animation shutdown, masked sprite hit coverage, new settings, errors, cancellation, permission priority and adjacent completion/error suppression. No QML warnings were emitted. activityAndPermissionBubble and responsiveLayoutsAndDesktopActions also passed in /tmp/cere-expressive-ui-final.txt.
  • Combined desktop runs exposed timing/target assumptions in the existing mouse-follow test. It now uses measured elapsed time for the speed bound and supplies a fresh pointer target for the resume check; the follower algorithm was unchanged. The isolated final command build/cere-ui-check mouseFollowing -o /tmp/cere-expressive-follow-final.txt,txt passed all 3 selected/setup/cleanup cases. The combined logs retain their earlier follow failures; individual passed checks above are not a claim that those entire combined runs passed.
  • A short, isolated overlay-plus-broker resource sample measured 2.57% of one CPU core over 12.06 seconds with idle breathing/blinks, and 0% over six-second reduced-motion and hidden samples. PSS was about 152–154 MiB for those two processes; this excludes the separate workspace host and is not a whole-installation memory budget or long-duration benchmark. Evidence: /tmp/cere-expressive-performance.json, /tmp/cere-acting-perf-YQPpEW/report.json and its empty runtime.log. A concurrent desktop sample was discarded; these measurements were taken separately from the UI checks.
  • python3 tools/install-user.py --prefix build/expressive-install passed and staged the binary, QML, broker dependencies and supplemental atlas. Log: /tmp/cere-expressive-stage.log. This is a staged installation only: the user's ~/.local application and running broker were not updated or restarted.
  • Existing protocol limitation: provider events are session-scoped, so an extremely late event from an older turn arriving after a new turn begins has no universal generation identifier. Same-turn terminal guards and adjacent-fault reaction cancellation are covered; this change does not replace provider protocols.

Android companion and physical pairing — September 29, 2026

  • npm test passed 165/165; the focused remote integration suite passed 15/15. npx tsc -p tsconfig.mobile.json and node tools/mobile-contract.ts --check passed. Whole-repository typecheck has separate concurrent review-test errors documented in docs/mobile/TESTING.md.
  • npm run build completed with exit 0; output is /tmp/cere-mobile-native-build.log. Both mobile GitHub workflows passed actionlint.
  • The final Android protocol/data tests passed 5/5 and 8/8; debug/release lint and debug/test/R8 release APK assembly passed. Exact command/output: mobile/android/app/build/reports/phone-fix-android-gate.log. apksigner verify passed for the installed debug APK.
  • Physical Pixel 10 Pro/API 37 pairing used Android authentication, matching six-word SAS and the live PC broker. Pairing/full synchronization and a separate cold-process key-retention/reconnection test each passed (OK (1 test)). Logs: /tmp/cere-phone-install/usb-pairing-repaired.log and /tmp/cere-phone-install/usb-connection-verified.log. The temporary test APK was removed; normal phone UI and desktop both reported Online/connected afterward.
  • Hardware testing exposed and fixed pre-restore deletion of committed pairing keys. Cache restore is now serialized/atomic, key cleanup waits for restored state, missing keys block before network access, and network availability coalesces connection attempts. The owner authenticated a UFW rule restricted to the phone's IP and the PC's selected address/interface on TCP 8443.
  • Installed debug SHA-256: 8ee806353ec6be9337c4417a09d5d7061cf9c01c79a6e480fcf4e4a2502c56d5. No live provider inference or desktop effect was performed; no release was published. Current roadmap dispositions and remaining release/hardware gates are in docs/mobile/TESTING.md.

Continuous articulated avatar (2026-09-29)

  • Replaced timed full-body cel stepping and 20 Hz breathing with a display-paced FrameAnimation, velocity-preserving analytic springs, interruption-safe expression mixtures, two-axis local gaze, and a native 20×28 textured rig. Both atlases share a normalized standing height and foot anchor; the face stays locally rigid. Twelve new gestures and ten shuffled idle options expand the catalog. Waving and roaming articulate held cels. Placement now follows the display clock with fractional-pixel compensation, and output-seam mirrors consume the primary avatar's exact sample through a shared QML engine. Quiet/reduced/hidden states suspend acting and pending settlement.

  • npm run build and npm run typecheck: passed (/tmp/cere-avatar-build.txt, /tmp/cere-avatar-typecheck.txt). node --test tests/avatar-animation.test.ts: 6 passed (/tmp/cere-avatar-engine-tests.txt), covering 30–240 Hz spring equivalence, interruption continuity, normalized expression weights, all catalog bounds, still-mode shutdown, delayed/invalid deltas and articulated wave/roaming structure.

  • ./build/cere-motion-check -o /tmp/cere-avatar-motion.txt,txt: 18 passed. QT_QPA_PLATFORM=offscreen ./build/cere-avatar-check "$PWD" and the same command with CERE_AVATAR_TEST_SOFTWARE=1: passed; logs /tmp/cere-avatar-render.txt and /tmp/cere-avatar-software.txt. Rig checks cover rigid facial distances, grounded feet, finite bounded inputs, mesh winding including the raised hand, visible rendering and alignment of both atlas families. The software backend uses continuous whole-cel transforms rather than local limb deformation. The implementation owner's focused compile, registration/render checks and software ASan lifecycle check also passed; artifacts /tmp/cere-avatar-register-4JBEiQ and /tmp/cere-avatar-final-MfrsvC.

  • With the README's Qt dependency environment, build/cere-ui-check fluidAvatarAnimation -o /tmp/cere-avatar-fluid-offscreen.txt,txt passed all 3 setup/test/cleanup cases under QT_QPA_PLATFORM=offscreen. The live Wayland run of fluidAvatarAnimation petGesturesAndReducedMotion expressiveActing mouseFollowing passed the first three functional cases, including real fixture state changes, pending permissions/errors, interruptions, unchanged reduced-motion pixels and sprite hit coverage; the subsequent follower case failed after the acting fixture; a fresh process passed both follower cases below. The combined test does not reset all session state between cases. Evidence /tmp/cere-avatar-desktop.txt. The cadence sample recorded 57 distinct rendered updates in 900 ms and a maximum sampled head-angle change of 0.02592 degrees; this short sample is not a long-duration frame-time guarantee. Actual rendered idle, nod, stretch, head shake, hair toss, giggle, bow and music screenshots are saved under /tmp/cere-ui-evidence/fluid-avatar-*.png; idle, stretch and hair-toss captures were visually inspected.

  • A fresh live Wayland run of build/cere-ui-check mouseFollowing mouseFollowingAcrossOutputs responsiveLayoutsAndDesktopActions -o /tmp/cere-avatar-follow.txt,txt passed both follower cases, including speed limits, hover/quiet/panel pauses and an actual HDMI-A-1 → eDP-1 crossing. The broad responsive-layout case failed on the pre-existing mobile Settings control row/fields at narrow widths and on timer cancellation; its software/offscreen retry also failed (/tmp/cere-avatar-layout.txt). These mixed runs are not reported as whole-suite passes.

  • npm test: 194/195 passed (/tmp/cere-avatar-all-tests.txt). The remote-process case encountered EADDRINUSE; node --test tests/remote-process.test.ts then passed alone (/tmp/cere-avatar-remote-retry.txt). No model inference was used.

  • An isolated overlay-plus-broker sample measured 4.75% of one CPU core over eight seconds of articulated idle, 0% over five seconds of reduced motion, and 0.20% over five seconds hidden. PSS was approximately 246 MiB while visible and 234 MiB hidden. This includes the current broker, excludes the separate workspace host, and is a short sample rather than a whole-installation budget. Evidence: /tmp/cere-avatar-performance-WciwUK/report.json; its runtime log is empty.

  • python3 tools/install-user.py --prefix build/avatar-install staged the implementation successfully (/tmp/cere-avatar-stage.txt). An isolated broker and overlay launched from the staged files, stayed connected/alive, and shut down cleanly with an empty runtime log (/tmp/cere-avatar-stage-smoke.txt, /tmp/cere-avatar-performance-zPmxfd/runtime.log). Staged motion QML, JS and catalog match the validated source. The existing user installation and broker were not replaced or restarted.

  • Installed-runtime follow-up: the current ~/.local installation already contains the full avatar overhaul. Source, staged and installed avatar QML/JS, catalog and both atlases match byte-for-byte; the two running UI processes match the installed executable, whose ELF Build ID matches the workspace build (CMake changes only the runtime-library search path during installation). The installed pet is visible with intensity 0.7 and quiet/reduced motion off. Five cropped live captures over 0.72 seconds were distinct, including movement in the blue-hair region; the final frame was visually inspected. Evidence: /tmp/cere-avatar-live-mluvhvzi/deployment.json and report.json. One active conversation remained running. This follow-up required no install, interface/broker restart or settings change.

Staged acting and presence (2026-09-29, follow-up)

  • Expanded to 32 poses, 67 clips and 14 shuffled idle gestures. assets/cere-inbetweens.png adds eight transparent intermediate drawings, generated with the built-in image tool using assets/cere-polished.png as the reference; the exact prompt is preserved in artwork/inbetweens-prompt.txt. Original atlases are unchanged. Family-based entry routes and authored internal stages prepare, release, transfer, arrive and settle. Native completion includes entryMs; urgent states use short entry paths.
  • The display-clock engine now owns asymmetric varied breathing, seeded attention beats, smooth asymmetric blinks with occasional double blinks, velocity-coupled hair roots/tips, independent shoulder springs, hip transfers and foot settling. The 28×36 native rig preserves the face and sole anchors. GPU pose weights accumulate in an isolated transparent layer rather than losing opacity through source-over blending. Qt 6.8+ and the build-time ShaderTools component are required. The software fallback retains whole-image animation, without full local articulation or additive pose mixing.
  • ./tools/build.sh passed (/tmp/cere-presence-build.log). npm run typecheck passed (/tmp/cere-presence-typecheck.txt). node --test tests/avatar-animation.test.ts: 10 passed (/tmp/cere-presence-engine.txt), covering all 67 clips, exact 30–240 Hz spring behavior, bounded follow-through, complete transition paths, urgent interruption, idle variety, pointer precedence, normalized blink weights and still-mode shutdown. build/cere-motion-check: 19 passed (/tmp/cere-presence-motion.txt), including entry-duration completion and accessibility/policy priorities.
  • With LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic, build/cere-ui-check avatarPresenceShowcase fluidAvatarAnimation petGesturesAndReducedMotion -o /tmp/cere-presence-ui.txt,txt passed all five setup/functional/cleanup cases on the real Wayland desktop. The idle cadence sample recorded 57 updates and 57 distinct head positions in 900 ms, with a maximum sampled head-angle step of 0.12935 degrees. Tests verify staged poses, idle attention, articulated waving, interruption continuity, opaque rendering, frozen reduced-motion pixels and a Settings preview that does not change task state. This is a short cadence sample, not a sustained frame-time guarantee.
  • Running that command with CERE_AVATAR_RECORD=/tmp/cere-presence-evidence recorded the actual native avatar at the default 0.7 intensity. Frames, the 28.5-second avatar-showcase.mp4, and the Settings capture (/tmp/cere-ui-evidence/presence-settings-preview.png) provide visual evidence. Idle, transition, wave, thinking and Settings frames were inspected. The video is a 24 fps diagnostic export; the live animation uses the display clock.
  • An isolated overlay-plus-broker sample measured 6.71% of one CPU core over 8 seconds of animated idle, 1.19% over 5 seconds of reduced motion and 0% over 5 seconds hidden, at approximately 243 MiB PSS. No model inference was used. Evidence: /tmp/cere-avatar-performance-WtGIWa/report.json; runtime log is empty. This includes broker work, excludes the workspace host, and is not a whole-application performance budget.
  • ctest --test-dir build --output-on-failure passed all three registered tests: motion, forced OpenGL avatar and software avatar (/tmp/cere-presence-ctest.txt). GPU checks retain a live layer while changing .5/.5 → 1/0 → 0/1 → deformed 1/0 → .5/.5, compare every RGBA channel with fresh synchronized item captures, and check opacity/brightness. All eight new atlas crops meet baseline/height tolerances and a 3-reference-pixel raster lower-center tolerance. An earlier window-grab assertion mixed asynchronous layer generations; the regression now waits for grabToImage().ready. Owner artifacts: /tmp/cere-avatar-itemgrab-xPD8ja.
  • The final real-Wayland build/cere-ui-check expressiveActing -o /tmp/cere-presence-expressive-final.txt,txt passed all three setup/test/cleanup cases. Earlier runs exposed a brief thinking-state observation window: the new entry stages made the send acknowledgement too long. That cue is now 640 ms including entry, while casual acting retains fuller transitions. The test waits for the actual settled state instead of a fixed celebration delay, and checks send RPC errors. Native gesture completion now uses a precise timer. Runtime logs for the successful avatar and conversational runs are empty.
  • python3 tools/install-user.py --prefix build/presence-install staged successfully (/tmp/cere-presence-stage.txt). An isolated staged broker/overlay smoke run passed (/tmp/cere-presence-stage-smoke.txt, empty /tmp/cere-avatar-performance-DenBqy/runtime.log). The validated binary and avatar QML/catalog/new atlas were then installed atomically under ~/.local; previous files are backed up in build/presence-backup-1790738327728. Both restarted interfaces match the installed binary byte-for-byte. Broker PID 71434 stayed running, all 21 sessions were preserved, the active session remained working, and avatar preferences were unchanged. Manifest: /tmp/cere-presence-deployment.json; installed runtime log /tmp/cere-presence-installed.log is empty. Six cropped live captures over 1.07 seconds were distinct and showed changing blue-hair pixels; the final capture was visually inspected. Evidence: /tmp/cere-presence-live/report.json. No model inference or task cancellation was used for validation or handoff.

Rigid cutout animation rework (2026-09-30)

  • Replaced the spatially weighted mesh with AvatarPuppet, a validated parent-joint skeleton rendering rigid cutouts through ordinary Qt image nodes. Arm and elbow transforms have no path to the head or hair. Head, torso, shoulders, elbows, thighs and knees have explicit pivots; only the back-hair joint receives bounded secondary rotation. GPU and software use the same implementation. Removed the old mesh/material/shaders and ShaderTools build dependency. The input envelope now derives from the actual cutouts and stance transforms.
  • assets/cere-rig.json owns anatomy, draw order, limits, spring tuning and 32 stance presets; assets/motions.json retains 67 clips and 14 idle gestures. qml/Motion.js interpolates joint targets while preserving spring velocity through interruptions. Acting intensity scales additional movement without changing the anatomical meaning of a stance. Local eye overlays preserve the head silhouette, and an interrupted blink finishes instead of snapping open. The README includes the authoring contract and a small elbow-key example.
  • assets/cere-puppet.png is a new 1536×1024 cutout sheet generated with the built-in image tool using assets/cere-polished.png as its identity reference. The exact prompt is in artwork/puppet-prompt.txt; all original atlases are preserved. Atlas regions are cropped and positioned by the manifest at runtime.
  • ./tools/build.sh passed (/tmp/cere-cutout-build-final.log); npm run typecheck passed (/tmp/cere-cutout-typecheck-final.txt). node --test tests/avatar-animation.test.ts passed 11 tests (/tmp/cere-cutout-engine-final.txt), covering every clip, declared channels, spring solutions at 30–240 Hz, still poses, interruption continuity, intensity, transition stages, attention and blinks.
  • PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" ctest --test-dir build --output-on-failure passed all three suites (/tmp/cere-cutout-ctest-final.txt): motion, forced OpenGL avatar, and software avatar. Production-asset checks load every real crop and all 32 presets, render wave/thinking, and prove head/hair independence under arm-only changes even with extreme head/torso transforms. Generic checks cover malformed hierarchies, rigidity, draw order, alpha overlap and scene-graph/source lifecycles.
  • The real-Wayland avatarPresenceShowcase and fluidAvatarAnimation checks passed (/tmp/cere-cutout-ui.txt), including staged entry poses, Settings preview, opaque rendering, wave elbow articulation, interrupted dragging and frozen reduced-motion pixels. A 900 ms cadence sample recorded 108 display-clock updates and 106 distinct head positions, with maximum sampled head step 0.06981 degrees. This is a short sample, not a sustained frame-time guarantee. Actual idle, blink, wave and thinking frames were visually inspected; a 28.5-second 24 fps diagnostic export is /tmp/cere-cutout-final-evidence/avatar-showcase.mp4.
  • python3 tools/install-user.py --prefix build/cutout-install staged successfully (/tmp/cere-cutout-stage-final.txt). An isolated staged broker/overlay launch passed with an empty runtime log. Short samples measured 11.07% of one CPU core during 8 seconds of animated idle, 0% during 5 seconds of reduced motion and 0% during 5 seconds hidden, at roughly 217–221 MiB PSS. This includes the isolated broker and overlay, excludes the workspace host, and is not a whole-application budget. Evidence: /tmp/cere-cutout-stage-v3M8Ok/report.json; no model inference was used.
  • Validation exposed two obsolete test assumptions: the removed stretchY property, and an immediate Settings click through a freed workspace pointer after an asynchronous expand(). The first assertion was removed; the latter now uses the existing restoreWorkspace() wait/reacquisition helper. A symbolized core isolated that failure to UiCheck::item, after all avatar state captures had completed, with no avatar renderer frames in the crashing stack.
  • The final build/cere-ui-check fluidAvatarAnimation petGesturesAndReducedMotion expressiveActing -o /tmp/cere-cutout-ui-verified.txt,txt run passed the first two functional cases and exposed the compositor focus problem in the third. After fixing that setup, build/cere-ui-check expressiveActing -o /tmp/cere-cutout-expressive-verified.txt,txt passed all 3 setup/test/cleanup cases; the unchanged successful cases were retained as valid evidence. Both use LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic. The final expressive check explicitly focuses the test-owned workspace by its exact Hyprland address/PID before checking actual composer active focus and listening. This fixes Wayland leaving the installed host active; the listening assertion remains intact. Final runtime logs are empty. The final cadence sample measured 103 updates in 900 ms, with maximum sampled head step 0.04950 degrees.
  • Installed the validated binary, avatar QML/JS, rig, atlas, motion catalog and authoring README atomically under ~/.local; prior files are backed up in build/cutout-backup-1790741827183. Only interface hosts restarted (new PIDs 21085 and 21101); broker PID 3139 stayed running. All 23 sessions were preserved, both active conversations remained working, and avatar settings/position were unchanged (intensity 0.8, scale 1, topmost on, quiet/reduced/hidden/roaming off). Installed executable hashes match both running hosts. Evidence: /tmp/cere-cutout-deployment.json; /tmp/cere-cutout-installed.log is empty. Six cropped live captures were distinct and the final installed frame was visually inspected (/tmp/cere-cutout-live/report.json).

Expressive header portraits (2026-09-30)

  • Both window headers use qml/CerePortrait.qml with the transparent twelve-frame assets/cere-portrait-expressions.png atlas. The built-in imagegen prompt is recorded in artwork/portrait-expressions-prompt.txt. Local assistant-reply classification is in qml/PortraitMood.js; activity precedence is in qml/PortraitState.js. The workspace integration accommodates the concurrent sidebar redesign; the installed header received only the portrait substitution.
  • node --test tests/portrait-mood.test.ts tests/portrait-state.test.ts passed 15 tests (/tmp/cere-portrait-unit.txt). Coverage includes negation, contrast, Unicode emoji, assistant/session filtering, streaming changes, stale/oversized replies, unfinished code fences and activity precedence. The classifier remains a deterministic English-oriented best guess; ambiguous and unsupported text stays neutral.
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software /usr/lib/qt6/bin/qmltestrunner -input tests/qml -import qml passed all 8 setup/test/cleanup cases (/tmp/cere-portrait-qml.txt). Checks cover twelve loaded tiles, rendered frame pixels, session changes, fresh streaming words with old message timestamps, hover/click, speech indication and animation stopping for hidden/quiet/reduced/zero-intensity states. /usr/lib/qt6/bin/qmllint -I qml qml/CerePortrait.qml and npx tsc --noEmit passed.
  • With QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic, ./build/cere-ui-check navigationAndScreenshots -o /tmp/cere-portrait-navigation.txt,txt and ./build/cere-ui-check compactSessionNavigation -o /tmp/cere-portrait-compact.txt,txt each passed all 3 setup/test/cleanup cases. Compact navigation covered 360×560, 440×720 and 1040×780. Only expected offscreen size-hint warnings occurred. Actual main and compact screenshots in /tmp/cere-ui-evidence were inspected. No native source changed, so these checks used the existing UI binary.
  • An isolated installed-layout staging run passed with an empty runtime log (/tmp/cere-portrait-stage-evidence.txt). Installed the three portrait QML/JS files, atlas and targeted header substitution under ~/.local/share/cere; original files are backed up in build/portrait-backup-1790749772339. Interface hosts restarted as PIDs 72089 and 72101; broker PID 3139 stayed running. All 25 sessions and all settings were preserved, and the three active conversations remained working (/tmp/cere-portrait-after.json). Deployment hashes: /tmp/cere-portrait-deployment.json; installed runtime log /tmp/cere-portrait-installed.log is empty. Six cropped live portrait captures were distinct, and the live header was visually inspected (/tmp/cere-portrait-live/header.png, /tmp/cere-portrait-live/report.json).

Original-silhouette refinement (2026-09-30)

  • Refined the cutout atlas with the built-in image tool against the original assets/cere-polished.png reference. The production atlas is assets/cere-puppet-v2.png; exact edit and repair prompts are in artwork/puppet-silhouette-prompt.txt. Original artwork and the first puppet atlas remain intact. The rig restores broad cargo thighs, substantial combat boots, loose dropped sleeves and larger gloves, balances the head/hair against wider shoulders and hips, and overlaps trouser fabric at the hip seam. Thinking, folded, glasses-adjustment and hair-tuck stances were refitted to the new anatomy. No motion-engine or production-renderer code changed in this refinement.
  • Inspected eight actual AvatarPuppet captures (rest, wave, folded, thinking, offer, jump, glasses adjustment and hair tuck), including an independent visual check on gray. Final captures: /tmp/cere-silhouette-preview/fit7; review sheet: /tmp/cere-silhouette-preview/fit7-review-gray.png. No clipping, transparent joint cracks or detached limbs were found. The folded stance remains a compact chibi wrist-crossing pose.
  • node --test tests/avatar-animation.test.ts: 11 passed (/tmp/cere-silhouette-engine-final.txt). PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" ctest --test-dir build --output-on-failure: all 3 passed, including forced OpenGL and software rendering with the final atlas/rig (/tmp/cere-silhouette-ctest-final.txt). The production-asset check now loads the manifest's declared atlas instead of requiring the previous filename. Its target was rebuilt with cmake --build build --target cere-avatar-check -j2 using the same PATH/library environment (/tmp/cere-silhouette-build.txt).
  • LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check fluidAvatarAnimation -o /tmp/cere-silhouette-fluid-final.txt,txt: all 3 setup/test/cleanup cases passed with an empty runtime log. The 900 ms cadence sample recorded 103 updates, 100 distinct head positions and a maximum sampled head step of 0.08091 degrees. This is a short continuity sample, not a sustained frame-time guarantee.
  • An earlier broader avatarPresenceShowcase fluidAvatarAnimation run rendered the avatar sequences and passed the fluid-animation case, but its Settings-preview section failed while concurrent workspace edits assigned an unsupported compact property in Shell.qml (/tmp/cere-silhouette-ui.txt). Those unrelated UI files were left to their owner; this is not a claim that the broader source UI run passed. The final assets were separately staged against the installed interface and exercised through an isolated broker/overlay launch, animated idle, reduced motion and hidden state (node /tmp/cere-silhouette-stage-smoke.mjs, /tmp/cere-silhouette-stage-final.txt). That runtime log is empty: /tmp/cere-silhouette-stage-5dBuAI/runtime.log.
  • Installed only assets/cere-rig.json and assets/cere-puppet-v2.png under ~/.local/share/cere, with backup build/silhouette-backup-1790749980451. Both interface hosts restarted (PIDs 73494 and 73509); broker PID 3139 remained running, all 25 sessions were preserved, both active conversations stayed working, and avatar preferences/position were unchanged. Manifest: /tmp/cere-silhouette-deployment.json; installed runtime log: /tmp/cere-silhouette-installed.log (empty). Six distinct live captures over 920 ms and the visually inspected final frame are in /tmp/cere-silhouette-live. No model inference or task cancellation was used.

Natural stance and movement pass (2026-09-30)

  • Relaxed the supporting arm, shoulders and torso throughout the 32 stance presets. Everyday offering/explaining poses now use one active palm with elbows closer to the body; waves retain hand height and a deeply bent elbow. Reworked speaking/waiting holds into gesture-and-release cycles, restored a two-arm raised stretch, and added alternating arm/shoulder movement and a fuller leg stride while running. Several gaze/sway clips now balance through the torso instead of rotating the entire character like a rigid pendulum. Artwork and rigid head/hair isolation remain unchanged.

  • qml/Motion.js uses quintic target curves with separate elbow/shoulder timing from the rig's articulation settings. Elbows fold before lifts and release after lowering shoulders. Interrupted entries snapshot actual joint values while retaining spring velocity. First loop playback begins at the first stance; subsequent cycles blend from the last stance. Partial key joints overrides inherit the named stance and preserve anatomical intent independently of intensity; the glasses-adjustment lift/lower keeps its closed hand instead of repeatedly swapping palm sprites.

  • node --test tests/avatar-animation.test.ts: 18 passed (/tmp/cere-natural-engine-final.txt). Coverage includes all clips/limits, mirrored joint timing, curve endpoints, interruption snapshots, cyclic entry, run arm swing, partial stance overrides and glasses hand continuity at intensities 0.2/0.5/1. PATH="$PWD/.local-deps/usr/bin:$PATH" LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" ctest --test-dir build --output-on-failure: 3 passed (/tmp/cere-natural-ctest.txt), including OpenGL/software rendering of the final rig. No native code changed, so the existing native check binaries were reused against the updated data.

  • LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check fluidAvatarAnimation petGesturesAndReducedMotion -o /tmp/cere-natural-ui-final.txt,txt: all 4 setup/functional/cleanup cases passed, with an empty runtime log. Checks include real desktop animation, drag interruption, reduced-motion pixel stability and gesture rendering. The short 900 ms cadence sample recorded 104 updates, 101 distinct head positions and maximum sampled head step 0.15143 degrees; this is not a sustained frame-time guarantee.

  • Inspected native-renderer captures of the stance set and actual 120 Hz motion samples, exported at 24 fps: 1,059 frames covering idle, wave, waiting, speaking, glasses adjustment, hair tuck, stretch, both running directions, thinking and an interrupted wave. Final frames are /tmp/cere-natural-motion/frame-*.png, segment ranges /tmp/cere-natural-segments.json, and the 44.125-second joint-animation diagnostic is build/natural-evidence/avatar-motion.mp4. The diagnostic renders the actual joint sampler through AvatarPuppet; it does not depict desktop window travel. Visual review caught and corrected a too-low wave, clasped running hands, a stretch that read as a presentation, and repeated hand swaps during glasses adjustment.

  • Final independent visual review cleared the corrected wave, two-arm stretch and directional runs (/tmp/cere-natural-motion/contact-corrected-final.png). An isolated launch against the installed interface passed animated idle, reduced-motion and hidden checks: node /tmp/cere-natural-stage-smoke.mjs, /tmp/cere-natural-stage-final.txt; runtime log /tmp/cere-natural-stage-xeF64n/runtime.log is empty.

  • Installed only the validated rig, motion catalog and qml/Motion.js under ~/.local/share/cere. Backup: build/natural-backup-1790751671182. Interface hosts restarted as PIDs 88781/88796 while broker PID 3139 stayed running; all 26 sessions, both active conversations and avatar settings/position were preserved. Manifest: /tmp/cere-natural-deployment.json; installed runtime log /tmp/cere-natural-installed.log is empty. Installed file hashes match source. After the overlay settled at its current position, six live captures were distinct over 931 ms and the final installed avatar was visually inspected (/tmp/cere-natural-live/report.json).

Tray and application head emblem (2026-09-30)

  • Added assets/cere-emblem.png, a transparent 1254×1254 head emblem generated with the built-in imagegen tool from the existing face identity reference. Prompt: artwork/emblem-prompt.txt. The native tray and QApplication window icon use this dedicated asset; the legacy full-body cleanup output cannot overwrite it. CMake now generates and installs nine hicolor sizes with tools/prepare-icons.mjs.
  • node --check tools/prepare-icons.mjs passed. Two independent actual-master generation runs were byte-identical (/tmp/cere-icons-check.0mf9U7). All generated and staged PNGs were checked for exact 16/22/24/32/48/64/128/256/512 dimensions and alpha. A Qt QIcon preview rendered 16–128 pixel sizes on dark/light backgrounds and was visually inspected (/tmp/cere-emblem-sizes.png).
  • ./tools/build.sh passed (/tmp/cere-emblem-build.log). python3 tools/install-user.py --prefix build/emblem-install passed (/tmp/cere-emblem-stage.log); desktop-file-validate build/emblem-install/share/applications/cere.desktop passed. The isolated staged executable stayed running with an empty runtime log (/tmp/cere-emblem-stage-evidence.txt).
  • QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software LD_LIBRARY_PATH="$PWD/.local-deps/usr/lib" QT_PLUGIN_PATH="$PWD/.local-deps/usr/lib/qt6/plugins" QT_QUICK_CONTROLS_STYLE=Basic ./build/cere-ui-check navigationAndScreenshots -o /tmp/cere-emblem-ui.txt,txt passed all 3 setup/test/cleanup cases. git diff --check passed for affected source files.
  • Installed only the staged executable, emblem master and nine icon sizes. Updated icon/desktop caches and restarted the two interface hosts, preserving closed-window state. Backup: build/emblem-backup-1790752468564; manifest: /tmp/cere-emblem-deployment.json. Both running executable hashes match the staged binary. Broker PID 3139 remained running; all 26 sessions and all settings were preserved, and the active conversation remained working (/tmp/cere-emblem-after.json). Installed runtime log /tmp/cere-emblem-installed.log is empty.
  • Live StatusNotifierItem :1.757/StatusNotifierItem publishes the new emblem at 22×22 and 64×64 (/tmp/cere-emblem-tray.json); its 64-pixel pixmap was visually inspected (/tmp/cere-emblem-tray-64.png). GTK icon-theme lookup resolves cere to the newly installed hicolor file at every generated size.

GitHub main publication preparation (2026-09-30)

  • npm run typecheck, npx tsc -p tsconfig.mobile.json, and node tools/mobile-contract.ts --check passed. npm test passed all 253 tests. A separate checkout of the staged Git index passed npm ci (zero reported vulnerabilities), typecheck, contract validation, and the same 253 tests after compiling native/peercred.cpp with g++ -std=c++17 -shared -fPIC -I/usr/include/node into build/cere-peercred.node.
  • npm run build passed. With the local dependency PATH/library environment, ctest --test-dir build --output-on-failure passed all three native tests. QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software /usr/lib/qt6/bin/qmltestrunner -input tests/qml -import qml passed 13 setup/test/cleanup cases.
  • Individual offscreen/software runs of build/cere-ui-check SLOT passed all 13 selected functional slots: navigationAndScreenshots, settingsSectionNavigation, voiceSettings, questionsAndAgentActivity, compactSessionNavigation, responsiveLayoutsAndDesktopActions, fluidAvatarAnimation, graphInspectorPolicyForgetAndCorrection, approvalsIdentifyTheirRequester, emoticonBadges, completionBubbles, draftsStayCoherentAcrossComposers, and reconnectRecoversTranscriptAndFailsPendingRequests. Each ran in a fresh process with the local Qt library/plugin paths and Basic controls style. These checks do not replace physical desktop or phone testing.
  • python3 tools/install-user.py --prefix build/main-install and CERE_TTS_DISABLED=1 python3 tools/check-memory-install.py --root build/main-install/share/cere passed. The isolated installed broker verified peer credentials, CLI operation, immediate recall, revision-guarded forgetting, immediate suppression, and pending purge during projection outage.
  • From mobile/android, with ANDROID_HOME="$PWD/.android-sdk", GRADLE_USER_HOME=/tmp/cere-android-gradle, and JAVA_HOME=/usr/lib/jvm/java-17-openjdk, ./gradlew --no-daemon :core:protocol:test :core:data:testDebugUnitTest :app:lintDebug :app:lintRelease :app:assembleDebug :app:assembleDebugAndroidTest :app:assembleRelease completed successfully (204 tasks: 43 executed, 161 up-to-date). Existing valid unit-test outputs were reused; Android instrumentation and physical-device checks were not rerun. The release APK remains unsigned.
  • Publication-preparation logs are in /tmp/cere-main-validation/, including node-tests.log, clean-node-tests.log, build.log, ctest.log, qml.log, per-slot ui-*.txt, install-smoke.log, and android.log. Local build/cache directories remain excluded from Git; generated Kotlin session state is now ignored too.
  • With the same Android environment, ./gradlew --no-daemon --no-configuration-cache -I ../../tools/mobile-sbom.gradle :app:mobileSbom passed and regenerated mobile/android/app/build/reports/mobile-sbom.cdx.json; log: /tmp/cere-main-validation/android-sbom.log. No signing or release tag is part of this main-branch publication.

Companion workflows, folders, and trust — September 30, 2026

This implementation adds folder/session organization, unified navigation, durable attachment drafts, context inspection, temporary conversations, project capsules, reviewed versioned recipes and result checks, contextual memory review, local voice drafts, offline utilities/routines, desktop profiles, permission leases, diagnostics, and staged backup/restore. Existing provider adapters, paged/recycled chat, graph-memory inspection, and desktop-broker mobile architecture remain in use.

  • CERE_TTS_DISABLED=1 node --test --test-concurrency=4 tests/*.test.ts: 314/314 passed, /tmp/cere-roadmap-backend-final.log. Coverage includes folder CAS/deletion without privilege changes, immutable attachment ownership and cleanup after confirmed forced stops, draft recovery, volatile temporary history, actual reviewed check exits, recipe invalidation/public-search rejection before dispatch, backup/forget races, restore reservations, memory maintenance/timer barriers, and subset-only mobile scope reduction.
  • npm run typecheck: passed, /tmp/cere-roadmap-typecheck-final.log. npm run build: passed, /tmp/cere-roadmap-build4.log. git diff --check and node tools/mobile-contract.ts --check: passed.
  • Offscreen Qt command: build/cere-ui-check permissionPowerSession foldersAttachmentsAndPalette projectCapsulesAndRecipeReview draftsStayCoherentAcrossComposers responsiveLayoutsAndDesktopActions compactSessionNavigation completionBubbles graphInspectorPolicyForgetAndCorrection questionsAndAgentActivity approvalsIdentifyTheirRequester reconnectRecoversTranscriptAndFailsPendingRequests -o /tmp/cere-roadmap-ui-acceptance.txt,txt: 13/13 passed including setup/cleanup. It used QT_QPA_PLATFORM=offscreen QT_QUICK_BACKEND=software QT_QUICK_CONTROLS_STYLE=Basic and the extracted-library paths documented above. A recipe editor binding warning in that run was corrected; the affected folder/palette and capsule/recipe cases then passed 4/4, with no QML warnings, in /tmp/cere-roadmap-ui-polish.txt. Screenshots remain under /tmp/cere-ui-evidence/.
  • build/cere-motion-check -o /tmp/cere-roadmap-motion.txt,txt: 19/19 passed. Android unit tests passed 29/29, with debug/release lint and builds, the instrumentation APK, and R8 release assembly successful; commands and hardware limits are in docs/mobile/TESTING.md. No Android device or emulator was available to execute instrumentation.
  • node benchmarks/memory/evaluate-reviewed.ts: 21 deterministic cases, 30/30 expected proposal outcomes, including correction, identity ambiguity, stale facts, project isolation, and erasure after restore; /tmp/cere-memory-reviewed-final.json. These fixture-driven canonical checks do not measure extraction-model quality or establish production accepted-assertion accuracy.
  • tools/benchmark-state.ts compared isolated 5,000-session snapshots: original p50/p95 7.713/10.763 ms, versus stable cached state 0.371/0.622 ms, with the payload reduced from roughly 1.45 MB to 65 KB. Evidence: /tmp/cere-state-baseline.json, /tmp/cere-state-cached.json. node tools/benchmark-companion.ts exercised 5,002 sessions, 10,000 messages, two concurrent mock turns and 100 canonical writes: mutation-plus-snapshot p95 0.953 ms, stream-event p95 0.182 ms, cancellation request 1.437 ms; /tmp/cere-companion-benchmark.json. These are broker workloads, not renderer/model/server latency guarantees.
  • python3 tools/install-user.py --prefix /tmp/cere-roadmap-stage: staged successfully. The isolated staged app exercised real socket RPC, offline calculations/notes/folders, a reviewed restore, broker replacement, reconnect, paused restored tools, and exclusion of unselected content. Evidence: /tmp/cere-stage-smoke-final.json; /tmp/cere-stage-runtime.log was empty. The final six-second offscreen sample, alongside backend validation, measured 16.45% of one CPU core with visible animation and 0% while hidden with all three processes still running; hidden PSS was about 274.5 MiB. Short software-rendering samples are not physical desktop budgets.
  • A worker-level restore check reproduced a 30-second consecutive SQLite-backup callback stall on Node 26.8.2. Canonical snapshots now use parameter-bound VACUUM INTO in the existing serialized memory worker. The focused same-worker backup/forget/restore regression checks a quoted output filename, integrity, retained content, the current forgetting registry, and a five-second upper bound. Core restore staging then measured 91.9 ms in /tmp/cere-recovery-timing-fixed.log; all 28/28 focused recovery/canonical checks passed in /tmp/cere-recovery-snapshot-tests.log.

No production profile was restored and no installed user broker was restarted. Local microphone/model execution, real-device mobile accessibility/capture/reconnection, and physical mixed-DPI docking/profile behavior remain hardware validation gates. Native Codex fork fields were checked against the installed CLI’s generated protocol schema and exercised with a protocol fixture; no live model inference was used for this rollout. Ordinary-provider retention still applies to temporary Cere conversations, which currently support text only.