Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/desktop-cef/src/worldscript_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <unordered_map>

#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_task.h"
#include "include/wrapper/cef_helpers.h"

Expand Down Expand Up @@ -61,6 +62,11 @@ void WorldScriptHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
printf("[worldscript_host] rust_core ping = %d\n", worldscript_rust_ping());
fflush(stdout);

// QNBS-v3: CefClient::GetAccessibilityHandler doesn't exist (PR #391's real finding) — that method is on CefRenderHandler instead, which is OSR-only ("when window rendering is disabled", include/cef_render_handler.h) and doesn't apply to this Views-based windowed host. SetAccessibilityState's own doc comment (include/cef_browser.h) confirms windowed browsers need only this one call: "all platform accessibility objects will be created and managed by Chromium's internal implementation" — no CefAccessibilityHandler required.
Comment thread
qnbs marked this conversation as resolved.
browser->GetHost()->SetAccessibilityState(STATE_ENABLED);
Comment thread
qnbs marked this conversation as resolved.
printf("[worldscript_host] accessibility_state_requested = true\n");
fflush(stdout);

CefPostDelayedTask(TID_UI, new PollShutdownTask(this), kShutdownPollIntervalMs);
}

Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/native-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ Wave 2's first deliverable — the CEF binding/C++ decision — is now backed by
| CEF renders reliably on Linux dev systems | DEBT — partial | cef-runtime, Wave 2 (in progress) | Two data points now (dev-machine spike + CI-run PR #388 on GitHub Actions `ubuntu-latest`), the second of which renders the **real production bundle** (not `about:blank`) with a verified exact title, not just a blank page. Still one GPU config per machine, no sandbox, mainly X11/Xvfb (Wayland now also smoke-proven, see the dedicated row below). Exit condition (unchanged from roadmap §2's Wave 2 exit criteria): broader Linux/GPU/display-server matrix coverage (Appendix A.3) before this can flip to PASS. |
| Wayland display-server smoke | **PASS** — single-runner smoke only | cef-runtime, Wave 2 | PR #393: `worldscript_host` (the exact binary already proven under X11) also renders the real production bundle under a headless Weston Wayland compositor (`--ozone-platform=wayland`), same FFI-boundary + exact-title checks as the X11 harness, CI-run and non-blocking (roadmap §44.2). Grounded in real evidence before attempting: Chromium's own upstream GN default compiles Wayland Ozone support into every standard Linux build, and CEF's `tools/gn_args.py` has no override disabling it. Does **not** satisfy roadmap §44.2/§44.5's real-hardware/compositor matrix (NVIDIA/AMD/Intel × KDE/GNOME) — one virtual CI runner, one compositor implementation (Weston headless), no real GPU. |
| CEF lifecycle assumptions documented | **PASS** | cef-runtime | `docs/cef/knowledge/subprocess-and-shutdown.md`'s core Wave 2 claim (SIGTERM → graceful `TryCloseBrowser`/`OnBeforeClose`/`CefQuitMessageLoop`/`CefShutdown`, repeated clean start/close cycles) now has a real linked chain: test (`scripts/cef/run-launch-cycle-proof.mjs`) → CI job (`🧪 CEF Learning Harness`) → doc, exactly what §61.1.4 requires. Save-coordinator/window-state persistence remain explicitly Wave 5+ scope (not a Wave 2 gap); Windows/macOS and a real packaged layout remain open, tracked in the doc's own "Outline" section. |
| Early Accessibility Gate | Not yet attempted (real blocker found) | cef-runtime, Wave 2 | PR #391 attempted `CefAccessibilityHandler` — does not compile against CEF 151.3.18 (`CefClient::GetAccessibilityHandler()` doesn't exist in this version). Reverted rather than left half-working, after a fallback attempt (enable-only, no observability) regressed the previously-reliable FFI/rendering proofs. Real CEF-151 API research needed before the next attempt — see `docs/cef/knowledge/cef-architecture-primer.md`. |
| Early Accessibility Gate | **PASS** — state enablement only, tree observability open | cef-runtime, Wave 2 | PR #391 found the real root cause: `GetAccessibilityHandler()` is declared on `CefRenderHandler` (OSR-only, "when window rendering is disabled"), not `CefClient` — never reachable from this windowed host regardless of what was inherited. PR #397: `CefBrowserHost::SetAccessibilityState(STATE_ENABLED)` alone is windowed-mode-correct per its own doc comment; CI-proven in every one of 3 repeated cycles with zero regression to the FFI/rendering/crash-reporting/Wayland proofs. Does **not** yet prove the platform accessibility tree is observable — that needs OS-level AT-SPI introspection on Linux, separate unattempted follow-up — see `docs/cef/knowledge/cef-architecture-primer.md`. |
| Sandbox posture | Not yet attempted | desktop-security, Wave 2/3 (roadmap §12) | Every run so far used `no_sandbox=true`; zero evidence either way on this row. |
| Crash reporting / renderer-crash resilience | **PASS** — crash-reporting half only | cef-runtime | PR #392: `crash_reporter.cfg` + `CefCrashReportingEnabled()` verified true, `chrome://crash` deliberately crashes the renderer, `CefRequestHandler::OnRenderProcessTerminated` fires (`TS_PROCESS_CRASHED`), the browser process/message loop survive, and a real Crashpad `.dmp` file — the harness's actual assertion, alongside Crashpad's own `.meta`/`settings.dat` housekeeping files (observed, not independently asserted) — is produced under an overridden `BREAKPAD_DUMP_LOCATION`; all CI-run, not a doc claim. Symbolization (decoding the dump into a stack trace via `dump_syms`/`minidump_stackwalk`) needs a full Chromium source checkout and was not attempted — see `docs/cef/knowledge/cef-architecture-primer.md`. |
| CEF SDK fetch/verify + version diagnostics automated | **PASS** | cef-runtime | `🧪 CEF Learning Harness` CI job (`.github/workflows/cef-learning-harness.yml`) fetches the pinned CEF SDK, verifies its checksum, and parses real version macros out of the extracted `include/cef_version.h` — a genuine CI-run check, not a doc claim. |
| Linux dependency inventory — clean-machine data point | DEBT — partial | cef-runtime | Same CI job runs the package-presence check against a stock `ubuntu-latest` runner before any `apt-get`, adding a real second data point beyond the spike's one already-configured dev machine. PR #395 added the specific check this row previously flagged as missing: `scripts/cef/check-linux-runtime-linkage.mjs` runs `ldd` against the real, already-built `worldscript_host` and `libcef.so` — both fully resolved on the runner, zero unresolved dependencies. Still narrow: one distro/runner image only, no packaged-installer dependency declaration. |
| CEF host build + repeated launch/close cycle proof, in CI | **PASS** | cef-runtime | PR #388: `apps/desktop-cef/`'s `worldscript_host` (real, repo-committed C++/Rust source, not spike code) builds against the fetched CEF SDK and runs 3 independently-verified clean start/close cycles under Xvfb in CI — the roadmap's literal "isolated learning harness" / "safe repeated startup/shutdown" deliverables (§3142), not just the fetch/diagnostics increment. |
| Rust FFI boundary proven inside the real host | **PASS** | cef-runtime, rust-core | `worldscript_rust_ping()` (rust-core, linked via Corrosion) is called from `OnAfterCreated` on every cycle and its exact sentinel value observed in CI output — stronger than the ADR-0020 spike's decoupled isolation test, since this proves the boundary works inside the actual multi-process CEF host, not a standalone C++ program. |

**Overall for this snapshot**: 7 PASS (crash reporting explicitly PASS for its reporting half only, not symbolization; Wayland explicitly PASS for a single-runner smoke only, not the real-hardware/compositor matrix), 2 explicit DEBT-in-progress rows (each with a concrete exit condition, not open-ended), 2 not-yet-attempted rows correctly left blank rather than assumed. No row is marked PASS without the evidence cited above.
**Overall for this snapshot**: 8 PASS (crash reporting explicitly PASS for its reporting half only, not symbolization; Wayland explicitly PASS for a single-runner smoke only, not the real-hardware/compositor matrix; Early Accessibility Gate explicitly PASS for state enablement only, not tree observability), 2 explicit `DEBT — partial` rows (each with a concrete exit condition, not open-ended), 1 row marked `Not yet attempted` (Sandbox posture) rather than assumed. No row is marked PASS without the evidence cited above.
12 changes: 6 additions & 6 deletions docs/cef/CEF-RUST-COMPETENCY-MATRIX.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# CEF/Rust Competency Matrix

**Companion to:** [`ROADMAP-CEF-DESKTOP-MIGRATION.md`](ROADMAP-CEF-DESKTOP-MIGRATION.md) §4.11, §61.1, Appendix A.1 · [ADR-0019](../adr/0019-cef-desktop-runtime-strategy.md)
**Established:** Wave 0, 2026-08-18. **Baseline was: nothing done yet.** Updated in place, 2026-08-18/19 (Wave 2, ADR-0020 spike + PR #386/#387/#388/#391/#392/#393), per this doc's own "Update discipline" below — items flip to `true` only with a linked evidence commit, in the same commit as the flip. This file exists so future waves have a live, gradeable target instead of re-deriving the checklist from the roadmap prose each time.
**Established:** Wave 0, 2026-08-18. **Baseline was: nothing done yet.** Updated in place, 2026-08-18/19 (Wave 2, ADR-0020 spike + PR #386/#387/#388/#391/#392/#393/#397), per this doc's own "Update discipline" below — items flip to `true` only with a linked evidence commit, in the same commit as the flip. This file exists so future waves have a live, gradeable target instead of re-deriving the checklist from the roadmap prose each time.

This is an engineering gate (roadmap §4.11.6), not a training checklist. `WS-CEF-IPC` (Wave 4) and any production storage capability exposing privileged native operations may not proceed until the relevant items below are `true` with linked evidence.

Expand All @@ -14,7 +14,7 @@ cef_competency:
repeated_shutdown_ci: true # scripts/cef/run-launch-cycle-proof.mjs, cef-learning-harness CI job (PR #388)
renderer_crash_ci: true # chrome://crash + OnRenderProcessTerminated + browser-process survival, cef-learning-harness CI job (PR #392)
sandbox_smoke: false
accessibility_smoke: false
accessibility_smoke: false # state ENABLEMENT is proven (PR #397, SetAccessibilityState, 3/3 CI cycles) — this field is specifically about the platform accessibility tree being observable, which needs OS-level AT-SPI introspection and was not attempted
crash_symbolization_smoke: false # crash REPORTING is proven (PR #392) — this field is specifically about decoding a dump (dump_syms/minidump_stackwalk), which needs a full Chromium source checkout and was not attempted
```

Expand All @@ -27,7 +27,7 @@ CI validation of this block ("fail CI when a required item for the active progra
| CEF architecture (process model, browser/frame/client ownership, message loop, shutdown ordering, subprocess packaging, sandbox expectations) | Partial | Process model, message loop, and shutdown ordering all have real working code + CI proof (`apps/desktop-cef/`, PR #388), now written up in `docs/cef/knowledge/cef-architecture-primer.md` (PR #390, no longer a skeleton). Subprocess *resource layout* (unpackaged CEF build output — `COPY_FILES`) is confirmed, but real shipped/installer packaging is separate, unproven, later scope. Sandbox expectations still have zero evidence. |
| CEF threading & lifetime rules (UI-thread callbacks, IO thread, ref-counted objects, callback lifetime, async cancellation, shutdown races) | Partial | `CEF_REQUIRE_UI_THREAD()` used throughout; `IMPLEMENT_REFCOUNTING`/`CefRefPtr` applied correctly; a real callback-lifetime lesson learned and fixed (`base::Unretained` vs. a plain `CefTask` — see `apps/desktop-cef/src/worldscript_handler.cpp`), now written up in `docs/cef/knowledge/threading-and-lifetimes.md` (PR #390, no longer a skeleton). IO thread, render-process-side code, and async-cancellation patterns remain untouched. |
| Rust binding layer (crate/version, unsafe/FFI boundary, wrapper ownership, API coverage gaps, upgrade procedure) | Partial | `apps/desktop-cef/rust-core/` (`worldscript_rust_core`, Corrosion-linked) — FFI boundary proven inside the real CEF host in CI (PR #388), not just an isolated test. No upgrade procedure written yet (`docs/cef/knowledge/binding-upgrade-playbook.md` still skeleton); API coverage is currently one trivial function, not representative of real surface area. |
| Cross-platform native host (Linux loader/resource layout, Windows process/installer/sandbox, macOS bundle/signing, window lifecycle, high-DPI, IME/a11y) | Partial (Linux only) | Linux loader/resource layout confirmed via a real filesystem listing in CI (`docs/cef/knowledge/linux-runtime-notes.md`); a real cwd-relative-path startup bug found and fixed. Zero Windows/macOS evidence. Window lifecycle proven for open/close only — high-DPI and IME/a11y untouched. |
| Cross-platform native host (Linux loader/resource layout, Windows process/installer/sandbox, macOS bundle/signing, window lifecycle, high-DPI, IME/a11y) | Partial (Linux only) | Linux loader/resource layout confirmed via a real filesystem listing in CI (`docs/cef/knowledge/linux-runtime-notes.md`); a real cwd-relative-path startup bug found and fixed. Zero Windows/macOS evidence. Window lifecycle proven for open/close only. Accessibility: state enablement proven (PR #397), tree observability (AT-SPI) and IME both still untouched. High-DPI untouched. |
| Operational CEF (crash reporting, symbol handling, version-update automation, sandbox verification, packaging deps, runtime diagnostics) | Partial | Packaging deps: `scripts/cef/check-linux-runtime-deps.mjs` (dpkg package presence) + `scripts/cef/check-linux-runtime-linkage.mjs` (PR #395 — real `ldd` against the CI-built runtime artifacts `worldscript_host` and `libcef.so`, both fully resolved on the CI runner), both CI-run. Runtime diagnostics: `scripts/cef/print-cef-version-diagnostics.mjs` + verbose CEF logging (`--enable-logging=stderr --v=1`) added mid-debugging this wave. Crash reporting: proven in CI (PR #392) — `crash_reporter.cfg` + `CefCrashReportingEnabled()` + a deliberately induced renderer crash (`chrome://crash`) produced a real Crashpad `.dmp` file (the harness's actual assertion) under an overridden `BREAKPAD_DUMP_LOCATION`, alongside Crashpad's own `.meta`/`settings.dat` housekeeping files (observed, not independently asserted); the browser process survived. Symbol handling (decoding a dump into a stack trace) needs `dump_syms`/`minidump_stackwalk` built from a full Chromium source checkout — out of reach of this project's minimal-CEF-SDK CI setup, not attempted. Version-update automation and sandbox verification remain not started. |

## Appendix A.1 checklist (live)
Expand All @@ -42,7 +42,7 @@ CI validation of this block ("fail CI when a required item for the active progra
[x] Unpackaged CEF resource layout proven — PR #388, real filesystem listing in CI (real shipped/installer packaging remains separate, unproven, later scope)
[x] Repeated startup/shutdown harness green — PR #388, 3/3 cycles, cef-learning-harness CI job
[x] Renderer crash observation green — PR #392, chrome://crash + OnRenderProcessTerminated (TS_PROCESS_CRASHED), browser process survived, cef-learning-harness CI job
[ ] Accessibility smoke green (attempted, real blocker — see cef-architecture-primer.md's "Accessibility API" section)
[ ] Accessibility smoke green (state enablement proven, PR #397, 3/3 CI cycles, zero regression; tree observability — AT-SPI introspection — still open, see cef-architecture-primer.md's "Accessibility API" section)
[ ] Crash-reporting/symbolization smoke green (crash-reporting half proven — PR #392, real Crashpad dump produced in CI; symbolization/decoding the dump not attempted, needs a full Chromium source checkout — see cef-architecture-primer.md)
[ ] Linux dependency inventory complete (inventoried + ldd-verified against the real CI-built runtime artifacts (worldscript_host, libcef.so), PR #395 — still one distro/runner image, no packaged-installer declaration; see native-readiness.md)
[x] X11/Wayland initial smoke complete — PR #393: X11 proven since PR #388 (Xvfb); Wayland now also proven (headless Weston compositor, --ozone-platform=wayland, same FFI+title checks, cef-learning-harness CI job). Real-hardware/compositor matrix (roadmap §44.2/§44.5 — NVIDIA/AMD/Intel × KDE/GNOME, real graphics hardware) remains unproven; this is one virtual-CI runner only.
Expand All @@ -62,7 +62,7 @@ CI validation of this block ("fail CI when a required item for the active progra
[x] renderer termination observed and handled — PR #392, chrome://crash deliberately crashes the renderer, OnRenderProcessTerminated fires, browser process/message loop survive, cef-learning-harness CI job
[ ] sandbox development plan validated
[ ] Linux runtime dependencies inventoried (inventoried + ldd-verified against the real CI-built runtime artifacts (worldscript_host, libcef.so), PR #395 — still one distro/runner image, no packaged-installer declaration; see native-readiness.md)
[ ] at least one accessibility smoke test performed (attempted, real blocker — see cef-architecture-primer.md's "Accessibility API" section)
[ ] at least one accessibility smoke test performed (state enablement proven, PR #397, 3/3 CI cycles, zero regression; tree observability — AT-SPI introspection — still open, see cef-architecture-primer.md's "Accessibility API" section)
[x] at least one crash-reporting/symbolization path proven — PR #392: crash-reporting path proven end-to-end (real Crashpad dump produced in CI); full symbolization (decoding the dump) is a separate, unattempted step needing a full Chromium source checkout
[ ] upgrade playbook exists
```
Expand All @@ -76,7 +76,7 @@ Superseding the original "Wave 0 does not claim" list, now that some of those it
- The CEF integration approach **has** been selected (Option B, ADR-0020) — this is no longer an open item.
- A learning harness **does** exist and runs in CI (`cef-learning-harness`, PR #388) — this is no longer an open item.
- Still true: no external-expertise engagement has been triggered — none of the escalation criteria (roadmap §4.11.5) have occurred.
- Still true, and still the most important caveat: this is Linux-only (X11 proven since PR #388, Wayland smoke also proven PR #393 — but one virtual CI runner, no real GPU/hardware matrix), `no_sandbox=true` throughout, no dump symbolization (crash *reporting* is proven), no working accessibility mechanism (a real CEF-151 API blocker was found and documented, not silently skipped), and no upgrade-playbook prose exists yet (`docs/cef/knowledge/binding-upgrade-playbook.md` remains a skeleton — architecture, threading, and binding-cookbook docs are no longer skeletons, PR #390). The competency gate above is explicitly **not** satisfied.
- Still true, and still the most important caveat: this is Linux-only (X11 proven since PR #388, Wayland smoke also proven PR #393 — but one virtual CI runner, no real GPU/hardware matrix), `no_sandbox=true` throughout, no dump symbolization (crash *reporting* is proven), no accessibility-tree observability (state *enablement* is proven, PR #397 — its own real root cause was found rather than staying blocked, but the tree itself is still unverified), and no upgrade-playbook prose exists yet (`docs/cef/knowledge/binding-upgrade-playbook.md` remains a skeleton — architecture, threading, and binding-cookbook docs are no longer skeletons, PR #390). The competency gate above is explicitly **not** satisfied.
- This matrix will continue to be updated in place as each item is genuinely satisfied, with a link to the proving test/CI job/doc (roadmap §61.1.4 evidence-link pattern) — not marked done on intention alone.

## Update discipline
Expand Down
Loading
Loading