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
13 changes: 12 additions & 1 deletion apps/desktop/e2e/canvas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,19 @@ test("Canvas refuses external requests, privileged navigation and popups; closin
expect(await app.evaluate(({ BrowserWindow }) => BrowserWindow.getAllWindows().length)).toBe(1);
expect(requests).toBe(0);
await tid(page, "workspace-full").click();
// Escape can only leave full view once it is entered; sent earlier, the click wins the race.
// Renderer visibility changes before canvas:show reaches the native view.
await expect(tid(page, "main")).toBeHidden();
await expect.poll(async () => {
const rect = await tid(page, "canvas-preview").boundingBox();
return app.evaluate(({ BrowserWindow }, rect) => {
if (!rect) return false;
const window = BrowserWindow.getAllWindows()[0]!;
const view = window.contentView.children.find(v => 'webContents' in v && (v as import('electron').WebContentsView).webContents.getURL().startsWith('modex-canvas:'));
if (!view?.getVisible()) return false;
const bounds = view.getBounds(), zoom = window.webContents.getZoomFactor();
return (['x', 'y', 'width', 'height'] as const).every(key => Math.abs(bounds[key] - Math.round(rect[key] * zoom)) <= 1);
}, rect);
}, { message: "native Canvas view must reach the expanded preview before Escape" }).toBe(true);
await app.evaluate(({ webContents }) => {
const contents = webContents.getAllWebContents().find(w => w.getURL().startsWith("modex-canvas:"))!;
contents.focus(); contents.sendInputEvent({ type: "keyDown", keyCode: "Escape" });
Expand Down
15 changes: 15 additions & 0 deletions docs/reviews/2026-10-30-canvas-native-readiness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Canvas Escape native-readiness evidence

PR #443 first failed its head CI at `6b1bec2a77e6c8286c48b29e68cfa030b221877c` when the main pane stayed hidden after guest Escape in `e2e/canvas.spec.ts`. Five unchanged local repetitions passed and one controlled head retry passed 478 desktop cases with four skips and seven site cases. Protected queue run [40992737267](https://github.com/TypeSafeAI/modex/actions/runs/40992737267), job `123858729561`, then repeated the same failure at line 224: 477 desktop passes, four skips, one failure; site tests did not run. Both first failures and traces remain preserved. No second blind retry was requested.

A controlled diagnostic held the main-process `canvas:show` calls carrying `fullView: true`. The renderer's main pane became hidden while those calls remained pending. Guest `before-input-event` observed Escape while native full-view state had not been applied, and the main pane stayed hidden. After releasing the calls, another Escape arrived with full view applied and restored the main pane. This establishes that the old renderer-hidden assertion alone does not prove native readiness. The hosted traces lack the main-process event ordering needed to attribute those specific failures conclusively.

A second controlled check observed native guest visibility and geometry. The condition was false while the full-view calls were held, became true after they were applied, and Escape then restored the main pane (one pass, 5.5 seconds). The candidate waits until the visible native guest matches the renderer preview bounds, accounting for zoom and one-pixel rounding, before sending the same single Escape. Five unchanged candidate repetitions passed in 49.5 seconds. External-request refusal, privileged navigation refusal, popup refusal, main-pane restoration and guest-destruction assertions remain intact. No sleep, input retry, timeout increase or production change is introduced.

Diagnostics used the same application/test source tree as `2eda13864049071b6564894faa5ef49f708ebb14`, in the retained release worktree at `3b7153918c9f25898946950bed77baf9e936818d`. The first scratch setup attempt used an incorrect relative path and failed before test execution; the corrected diagnostic paths ran successfully. Logs, scratch source and traces are preserved outside worktrees in `~/Documents/Codex/artifacts/modex-land-and-prune/`, including `canvas-readiness-diagnostic.json`, `canvas-native-readiness-diagnostic/`, `canvas-native-readiness-candidate/` and the digest-verified queue artifact `pr443-queue-first-failure.zip` (SHA-256 `c757ad982439b9b2736ff8577aaad37df5af1a8f5365ab824212e3711f7ac32c`).

Local validation at `8638fd30a8b2d5e4eafc7fc543126f57bd9f3861` completed with exit 0: build passed; unit checks passed with 2,244 passes and 26 skips; full E2E passed 475 desktop cases with seven skips (21.0 minutes) and seven site cases (8.3 seconds). The transcript median was 175.7 ms against the approved 500 ms limit. The worktree remained clean throughout the run. The seven desktop skips retain the existing live-provider and real Open Knowledge gates.

The first hosted native-platform run `40998715521` failed Windows job `123877826277`: 15 native CLI tests passed and the natural-exit PTY case timed out waiting for `grandchild.heartbeat` ("PTY tree starts"). No PTY output or child receipt snapshot explains the startup failure. Terminal production, fixture, test, workflow and lockfile paths are unchanged from release source `2eda138`. One diagnostic retry with debug logging passed all 16 native CLI tests with no skips in 19.7 seconds (job `123881380189`); the full Windows job, including installer packaging, subsequently passed. The retry artifact `12953331073` matched GitHub's SHA-256 digest `8f8059eefc6942cda187bb849791e9f7cf9d4f1c9259c97fc873a3adbf8d951c`. This unchanged retry does not establish the original failure's cause. The original TAP artifact and job log remain preserved as `pr446-native-cli-win32-first.zip` and `pr446-windows-first-failure.log` in the external evidence directory.

CodeQL Actions job `123877816315` in run `40998711503` completed extraction and SARIF generation, then failed during the analysis step after upload began. Its log and check annotations provide no concrete failure reason; no root cause is claimed. The job-level retry API returned HTTP 403, "Jobs in this workflow run cannot be re-run". The original log is preserved as `pr446-codeql-first-failure.log`. Hosted macOS job `123878076309` in run `40998793846` passed 478 desktop cases with four skips (32.3 minutes), followed by seven site cases (17.6 seconds), at head `8638fd30a8b2d5e4eafc7fc543126f57bd9f3861`. The transcript median was 382.7 ms on Apple M1 Virtual, three cores, Node 24.21.0. iPhone, Linux and the Windows retry passed; the CodeQL Actions failure above remains unresolved for that head. Protected delivery remains pending. This harness change does not establish human keyboard or VoiceOver acceptance; issues #280 and #281 retain their separate acceptance gates.
2 changes: 2 additions & 0 deletions docs/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ The published application source is `2eda138` (v0.4.0). Later source deliveries

## In flight

- **Canvas Escape harness readiness.** Repeated hosted failures showed the main pane still hidden after guest Escape. A controlled delayed-IPC diagnostic proved that renderer full-view state can precede native readiness. The test-only candidate waits for the native guest to become visible at the expanded preview bounds before sending one Escape, retaining all security and lifecycle assertions. Five candidate repetitions and full local validation passed; the implementation also passed hosted macOS validation. The Windows first failure, passing retry and original CodeQL upload failure remain recorded. Protected delivery remains pending. [Evidence](reviews/2026-10-30-canvas-native-readiness.md).

- **Markdown keyboard E2E sequencing repair.** A native scroll completion race reproduced in a blank Electron window. The proposed test waits for the rightward scroll to finish before reversing, preserving the original movement and accessibility assertions. Fresh build and unit validation passed (2,196 passed, 23 skipped), the focused E2E passed 15/15 across three themes, and independent review found no blockers. Protected delivery landed through #435 and is included in v0.4.0. [Evidence](reviews/2026-10-28-markdown-scroll-sequencing.md).

- **Code Review packaged-app harness repair.** The shared harness and standalone IPC test now honor `MODEX_PACKAGED_APP`, including crash recovery. Two executable-identity regressions failed before the repair and passed afterward against a local ad-hoc bundle; development checks also passed. This is scoped harness evidence, not signed-release or human acceptance. [Evidence and remaining coverage limits](reviews/2026-10-28-code-review-packaged-harness.md).
Expand Down
Loading