From e0f5f055f1298b7e9fbe5fd777950e012d38bd56 Mon Sep 17 00:00:00 2001
From: umer
Date: Fri, 30 Oct 2026 14:09:25 +0400
Subject: [PATCH 1/2] Clickable options keep their script, are judged on a real
press, and keep their source (0.8.0)
Sign-off found the export script-free, so a design option could not be
clicked, and 0.7.0 already kept a live option's inline script: measured
with a clickable inbox option, the export keeps the script under
`script-src 'unsafe-inline'` and `default-src 'none'`, and a real mouse
press in Chrome changes the page. The gaps were judging and source.
- render-check gains clicks(): at 390 and 1280 it presses the first
control a person can press (button, role=button/tab/menuitem, submit)
with Input.dispatchMouseEvent, and keeps the page before and after the
press, the control's label, what a person reads after it, and whether
the page also changed on its own (idle).
- The judge is asked for `behaviour { score, reason, defects }` with
those frames, only for a live page that carries a control; a press that
changes nothing is a defect and the option does not pass (bar stays 9).
A page drawn from App.jsx has no script left, so it is never asked.
- A drawn option writes its engine source readable beside it in
`
+
+
+
+
Design review Thursday
Can we walk the board flows at 10:00?
+
diff --git a/journeys/click.mjs b/journeys/click.mjs
new file mode 100644
index 0000000..b2cf4dd
--- /dev/null
+++ b/journeys/click.mjs
@@ -0,0 +1,112 @@
+// Nonpaid real-CLI proof that a clickable option stays clickable: an inbox brief whose rows and filter are wired by an inline script ->
+// make exports the option with its script, loading nothing -> the host presses one of its controls with a real mouse event in a headless
+// browser and keeps the page before and after it -> the independent judge is asked about behaviour and returns a verdict -> a control that
+// changes nothing is judged and refused -> a drawn App.jsx option keeps its source readable beside it -> the view serves the clickable page
+// in its sandy frame and a real click on what "Open live" opens still works. Local stand-ins answer the model and the judge, so scores are
+// synthetic, never design quality.
+import '../test/fixtures/provider-hooks.mjs';
+import assert from 'node:assert/strict';
+import { execFile, spawn } from 'node:child_process';
+import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import { promisify } from 'node:util';
+import { renderCheck } from '../src/render-check.mjs';
+import { standIn } from '../test/fixtures/critic-model.mjs';
+import { installJudge } from '../test/fixtures/judge-cli.mjs';
+const root = new URL('..', import.meta.url).pathname, out = process.env.DONE_DONE_EVIDENCE_ROOT ?? process.argv[2];
+if (!out) throw Error('Give an evidence folder');
+mkdirSync(out, { recursive: true });
+const BRIEF = 'An inbox app: pick a message from the list to read it, and filter the list to unread';
+// What the stand-in model writes: an inbox whose rows open their message and whose filter narrows the list, both wired by an inline script.
+const inbox = (title, wired = true) => `