From f0cc8744af25cf302ec948428293aa2d3c58a556 Mon Sep 17 00:00:00 2001 From: MendixMau Date: Fri, 30 Oct 2026 23:58:34 +0100 Subject: [PATCH 1/2] =?UTF-8?q?learn(demo):=20live-demo-autopilot=20skill?= =?UTF-8?q?=20=E2=80=94=20run=20the=20demo=20live=20with=20a=20take-over?= =?UTF-8?q?=20control=20panel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged from two field builds (desktop+phone offline demo 4/4 scenes; three-app hub demo 28/28 with an app killed mid-run and an 11 min pause). Skill text only, on-demand routing row, cross-link from record-demo-video. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + README.md | 1 + ROUTING.md | 1 + agents/test-agent.md | 1 + bin/gate-check.sh | 2 +- bin/lib/skill-routing.tsv | 1 + skills/live-demo-autopilot.md | 110 ++++++++++++++++++++++++++++++++++ skills/record-demo-video.md | 1 + 8 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 skills/live-demo-autopilot.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b057dda..0bd3d0fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased +- learn(demo): **`skills/live-demo-autopilot.md` — run the demo live, not as a video**: Playwright drives the real app through scripted scenes, captions carry a WHY line, a control panel lets the presenter pause and take over, redo or skip; plus the traps that each broke a run (trial licence stops the runtime ~2.5 h after start, 6-session cap and when `/xas/` logout really frees a slot, focus-stealing panel pausing the run, SIGTERM closing the browser before sign-out). Field: a desktop+phone offline manufacturing demo (4/4 scenes) and a three-app process-hub demo (28/28 with an app killed mid-run and an 11 min pause), 2026-10 — Maurits Visser - fix(doctor, sync-project, speed-setup): **doctor says when the speed fixes never reached a project**: `bin/exec.sh`, `bin/_common.sh` or `bin/lint-gate.sh` without the 2026-10-29 speed code (marker per file) gives a Machine health warning "speed fixes not active", and the Recommended fix leads with the exact `sync-project.sh --upgrade-bin ...` command (exec.sh always with its `_common.sh`; each copy backed up) before any other advice, because every other number measures the old scripts; `sync-project.sh` names the speed fixes on a hand-edited exec.sh / _common.sh that has the exit-code fix but not the speed work; `skills/speed-setup.md` has Claude show each local edit in one line and ask before replacing. Field: an English colleague's ExpenseTracker analysis after the toolkit update still showed a full mxbuild on every change (45.5 min, 57% of all exec time) with 15 drifted scripts in bin/; reproduced here with the real pre-#587 exec.sh / _common.sh / lint-gate.sh — doctor names all three, sync names exec.sh and refreshes the two unedited ones — Maurits (mauritscgvisser) - fix(doctor, speed-setup): **doctor no longer says "None needed" next to a verdict of "5x slower"**: when process starts are fast but one bench step is 5x+ the reference and 2 s+ slower, the Recommended fix names that step (slow git status: `git config core.untrackedCache true` / `core.fsmonitor true`, no admin rights); a project inside a OneDrive / Dropbox / Google Drive / iCloud folder gets a Machine health warning and "move the project to a local folder" as the fix; low-memory advice now offers "restart the computer" before `--cleanup`; the bench's git step runs one untimed warm-up so a stale index after a copy or clone no longer reads as slow (field, ab-581/gk: 18.3 s cold, 31 ms warm); `skills/speed-setup.md` tells Claude never to say deno, mxbuild or helper process to a user. Field run: ab-581/gk on Linux, bench 14.7 s vs 10.9 s, "None needed" correctly; a project under a OneDrive path, move advice shown — Maurits (mauritscgvisser) - fix(gate-check, gate-cache): **the closeout verdict cache also keys on file CONTENT, so an overwrite that keeps an old mtime (`cp -p`, `rsync -t`, `tar x`, `unzip`, `touch -d`) can no longer replay a stale verdict**: a signed triage.md copied over a FAIL one still printed the cached Stage 0 FAIL (PR #589 review); the cache now stores one `find | sort | xargs cksum | cksum` signature of the project files (skipping .git, node_modules, .mxtk, mprcontents, deployment, *.mpr, files over 1 MB) and any difference, or a signature that cannot be computed, re-evaluates; new `tests/wave2/test-gate-cache.sh` (hit, edit/delete/waiver miss, cp -p miss, TTL 0, 'not evaluated' line); `MXTK_GATE_CACHE_TRACE=1` prints `gate-cache: hit|miss` on --closeout. Field run: ab-581/base copy (197 MB, 633 hashed files) - signature 28 ms, cache hit 1464 -> 1498 ms vs 2567-2786 ms full evaluation - PR #589 reviewer, OlafFede (#583) — OlafFede (#583) diff --git a/README.md b/README.md index 20a9cd06..e9ecc4fe 100644 --- a/README.md +++ b/README.md @@ -753,6 +753,7 @@ Every mxcli project has a `.ai-context/skills/` directory (bundled by `mxcli ini | Turning an already-rigorous run into a narrated proof a stakeholder can trust without running anything | `skills/e2e-evidence-report.md` | | Recording a narrated screen-capture demo of a running app for a human to watch — opening on the app instead of a blank frame, and keeping captions synced to the pixels | `skills/record-demo-video.md` | | A demo film someone will watch looks captured, not produced — 25 fps smear, scroll jumps, no visible pointer, a dense page nobody can read: 2x CDP screencast at 60 fps, drawn cursor and click ripple, eased scroll, and a zoom rendered afterwards from the click log (never a CSS transform in the page) | `skills/demo-recording-polish.md` | +| Running a customer demo LIVE instead of a video — Playwright drives the real app through scripted scenes with captions and a control panel (pause and take over, redo, skip); off-screen or tile sign-in, session expiry, the 2.5 h trial-licence stop and the 6-session cap | `skills/live-demo-autopilot.md` | | Sending a demo guide, screenshots or a quickstart doc OUTSIDE the repo — to a customer, prospect or reviewer: relative image paths and "the name shown above" both break the moment the file travels alone, and the usernames a login panel displays are not the ones it accepts | `skills/share-demo-package.md` | | Running lint as a gate rather than a report — per-rule ratchet against a committed baseline, plus the crash and collapse guards that stop a blind rule passing | `project-bin/lint-gate.sh` | | Reading a lint result, or writing/repairing any .star rule — lint's failure mode is a confident clean pass, so 0 findings is a claim needing evidence | `skills/lint-that-actually-runs.md` | diff --git a/ROUTING.md b/ROUTING.md index 4c0518aa..b3735a8d 100644 --- a/ROUTING.md +++ b/ROUTING.md @@ -236,6 +236,7 @@ picks the row up. That is the whole procedure — there is no second list to rem | Turning an already-rigorous run into a narrated proof a stakeholder can trust without running anything | `skills/e2e-evidence-report.md` | test,review | 6 | ondemand | | Recording a narrated screen-capture demo of a running app for a human to watch — opening on the app instead of a blank frame, and keeping captions synced to the pixels | `skills/record-demo-video.md` | test | 6 | ondemand | | A demo film someone will watch looks captured, not produced — 25 fps smear, scroll jumps, no visible pointer, a dense page nobody can read: 2x CDP screencast at 60 fps, drawn cursor and click ripple, eased scroll, and a zoom rendered afterwards from the click log (never a CSS transform in the page) | `skills/demo-recording-polish.md` | test | 6 | ondemand | +| Running a customer demo LIVE instead of a video — Playwright drives the real app through scripted scenes with captions and a control panel (pause and take over, redo, skip); off-screen or tile sign-in, session expiry, the 2.5 h trial-licence stop and the 6-session cap | `skills/live-demo-autopilot.md` | test | 6 | ondemand | | Sending a demo guide, screenshots or a quickstart doc OUTSIDE the repo — to a customer, prospect or reviewer: relative image paths and "the name shown above" both break the moment the file travels alone, and the usernames a login panel displays are not the ones it accepts | `skills/share-demo-package.md` | test,review | 6,7 | ondemand | | Running lint as a gate rather than a report — per-rule ratchet against a committed baseline, plus the crash and collapse guards that stop a blind rule passing | `project-bin/lint-gate.sh` | mdl,gate | 5,6 | ondemand | | Reading a lint result, or writing/repairing any .star rule — lint's failure mode is a confident clean pass, so 0 findings is a claim needing evidence | `skills/lint-that-actually-runs.md` | gate,review | 5,6 | ondemand | diff --git a/agents/test-agent.md b/agents/test-agent.md index 88d69ae9..b1313c84 100644 --- a/agents/test-agent.md +++ b/agents/test-agent.md @@ -67,6 +67,7 @@ This table is your whole list. The baseline table in the project's CLAUDE.local. | `skills/e2e-evidence-report.md` | Turning an already-rigorous run into a narrated proof a stakeholder can trust without running anything | | `skills/record-demo-video.md` | Recording a narrated screen-capture demo of a running app for a human to watch | | `skills/demo-recording-polish.md` | A demo film someone will watch looks captured, not produced | +| `skills/live-demo-autopilot.md` | Running a customer demo LIVE instead of a video | | `skills/share-demo-package.md` | Sending a demo guide, screenshots or a quickstart doc OUTSIDE the repo | | `skills/improvement-register.md` | Any review pass that runs more than once | | `skills/journey-examples.md` | Writing an actual .journey.json | diff --git a/bin/gate-check.sh b/bin/gate-check.sh index 859cac5a..7dc11dc5 100755 --- a/bin/gate-check.sh +++ b/bin/gate-check.sh @@ -1907,7 +1907,7 @@ stage_protocol_paths() { 3) echo "skills/interview-protocol.md skills/change-intake.md skills/change-intake-detail.md skills/grill-mode.md skills/checkpoints/checkpoint-template.md skills/checkpoints/checkpoint-design.md skills/dispatching.md skills/small-project-tier.md skills/mendix-best-practices-index.md skills/decompose-app.md skills/mendix-service-seam.md skills/layering-review.md skills/architecture-blueprint.md skills/modularize-domain.md skills/design-artifacts.md skills/process-map.md skills/interaction-model.md skills/brd-to-build-plan.md skills/learned-multilingual-app.md skills/workflow-structure-rules.md skills/rest-between-mendix-apps.md skills/learned-mdl-cannot-express.md" ;; 4) echo "skills/interview-protocol.md skills/change-intake.md skills/change-intake-detail.md skills/grill-mode.md skills/checkpoints/checkpoint-template.md skills/checkpoints/checkpoint-build.md skills/agent-roles.md skills/dispatching.md skills/small-project-tier.md skills/module-brief.md skills/module-folder-convention.md skills/brd-to-build-plan.md skills/coverage-ledger.md skills/workflow-structure-rules.md skills/rest-integration-first-time-right.md skills/rest-between-mendix-apps.md skills/learned-constants-and-secrets.md" ;; 5|build-ready) echo "skills/interview-protocol.md skills/change-intake.md skills/change-intake-detail.md skills/grill-mode.md skills/agent-roles.md skills/dispatching.md skills/module-brief.md skills/learned-mdl-preflight.md skills/module-folder-convention.md skills/learned-microflow-patterns.md skills/microflow-preflight.md skills/mendix-best-practices-index.md skills/ui-preflight-pages.md skills/design-spacing.md skills/learned-stylegallery.md skills/ui-loop.md skills/module-review.md skills/testing-shape.md skills/decompose-app.md skills/mendix-service-seam.md skills/microflow-loop-antipatterns.md skills/rehost-app.md skills/iterative-build-loop.md skills/mdl-cookbook-microflows.md skills/build/mdl/oneshot-mdl-method.md skills/learned-page-patterns.md skills/learned-multilingual-app.md skills/oneshot-page-structure-patterns.md skills/mendix-agents.md skills/mendix-agent-ui.md skills/mendix-agent-setup.md skills/fixture-seeding.md skills/journey-proof.md skills/unhappy-path-testing.md skills/monkey-test.md skills/load-test.md skills/unit-test.md skills/e2e-locators-that-lie.md skills/report-schema.md skills/harness-architecture.md skills/process-coherence-pass.md skills/lint-that-actually-runs.md skills/improvement-register.md skills/journey-examples.md skills/wiring-sweep.md skills/learned-workflow-patterns.md skills/workflow-structure-rules.md skills/rest-integration-first-time-right.md skills/rest-between-mendix-apps.md skills/bug-submission-checklist.md skills/empty-widget-triage.md skills/learned-sidebar-collapse-icons.md skills/learned-popup-navigation.md skills/learned-datagrid-customcontent-binding.md skills/learned-popup-feedback-pattern.md skills/learned-mdl-cannot-express.md skills/learned-css-that-never-applied.md skills/learned-detection-gaps.md skills/learned-dg2-patterns.md skills/learned-file-upload-widget.md skills/security-is-not-a-later-script.md skills/learned-local-db-confusion.md skills/full-harness-audit.md skills/test-result-audit.md skills/finding-disposition.md skills/preview-over-hub-tunnel.md skills/walking-skeleton.md skills/platform-link.md skills/teamserver-alignment.md skills/learned-constants-and-secrets.md" ;; - 6) echo "skills/interview-protocol.md skills/change-intake.md skills/change-intake-detail.md skills/grill-mode.md skills/checkpoints/checkpoint-template.md skills/checkpoints/checkpoint-cutover.md skills/dispatching.md skills/mendix-best-practices-index.md skills/module-review.md skills/testing-shape.md skills/existing-app-assurance.md skills/decompose-app.md skills/app-analysis.md skills/module-dependency-review.md skills/microflow-loop-antipatterns.md skills/rehost-app.md skills/qa-loop-goal-pattern.md skills/learned-multilingual-app.md skills/mendix-agent-setup.md skills/e2e-harness-base.md skills/learned-db-assertions.md skills/fixture-seeding.md skills/journey-proof.md skills/unhappy-path-testing.md skills/monkey-test.md skills/load-test.md skills/unit-test.md skills/e2e-locators-that-lie.md skills/learned-skill-ux-audit.md skills/learned-skill-scope-delta.md skills/report-schema.md skills/harness-architecture.md skills/process-coherence-pass.md skills/e2e-evidence-report.md skills/record-demo-video.md skills/demo-recording-polish.md skills/share-demo-package.md skills/lint-that-actually-runs.md skills/improvement-register.md skills/journey-examples.md skills/wiring-sweep.md skills/workflow-structure-rules.md skills/rest-between-mendix-apps.md skills/bug-submission-checklist.md skills/empty-widget-triage.md skills/anonymize-client-app-for-demo.md skills/learned-css-that-never-applied.md skills/learned-detection-gaps.md skills/learned-local-db-confusion.md skills/full-harness-audit.md skills/test-result-audit.md skills/finding-disposition.md skills/handoff-to-studio-pro.md skills/preview-over-hub-tunnel.md skills/platform-link.md skills/teamserver-alignment.md skills/learned-constants-and-secrets.md" ;; + 6) echo "skills/interview-protocol.md skills/change-intake.md skills/change-intake-detail.md skills/grill-mode.md skills/checkpoints/checkpoint-template.md skills/checkpoints/checkpoint-cutover.md skills/dispatching.md skills/mendix-best-practices-index.md skills/module-review.md skills/testing-shape.md skills/existing-app-assurance.md skills/decompose-app.md skills/app-analysis.md skills/module-dependency-review.md skills/microflow-loop-antipatterns.md skills/rehost-app.md skills/qa-loop-goal-pattern.md skills/learned-multilingual-app.md skills/mendix-agent-setup.md skills/e2e-harness-base.md skills/learned-db-assertions.md skills/fixture-seeding.md skills/journey-proof.md skills/unhappy-path-testing.md skills/monkey-test.md skills/load-test.md skills/unit-test.md skills/e2e-locators-that-lie.md skills/learned-skill-ux-audit.md skills/learned-skill-scope-delta.md skills/report-schema.md skills/harness-architecture.md skills/process-coherence-pass.md skills/e2e-evidence-report.md skills/record-demo-video.md skills/demo-recording-polish.md skills/live-demo-autopilot.md skills/share-demo-package.md skills/lint-that-actually-runs.md skills/improvement-register.md skills/journey-examples.md skills/wiring-sweep.md skills/workflow-structure-rules.md skills/rest-between-mendix-apps.md skills/bug-submission-checklist.md skills/empty-widget-triage.md skills/anonymize-client-app-for-demo.md skills/learned-css-that-never-applied.md skills/learned-detection-gaps.md skills/learned-local-db-confusion.md skills/full-harness-audit.md skills/test-result-audit.md skills/finding-disposition.md skills/handoff-to-studio-pro.md skills/preview-over-hub-tunnel.md skills/platform-link.md skills/teamserver-alignment.md skills/learned-constants-and-secrets.md" ;; 7) echo "skills/interview-protocol.md skills/change-intake.md skills/change-intake-detail.md skills/grill-mode.md skills/checkpoints/checkpoint-template.md skills/checkpoints/checkpoint-cutover.md skills/close-the-loop.md skills/share-demo-package.md skills/handoff-to-studio-pro.md skills/platform-link.md skills/teamserver-alignment.md skills/deploy-to-sandbox.md" ;; *) echo "" ;; # diff --git a/bin/lib/skill-routing.tsv b/bin/lib/skill-routing.tsv index be0b6a14..596bf2cd 100644 --- a/bin/lib/skill-routing.tsv +++ b/bin/lib/skill-routing.tsv @@ -194,6 +194,7 @@ build-plan-status project-bin/build-plan-status.sh After marking a module done, e2e-evidence-report skills/e2e-evidence-report.md Turning an already-rigorous run into a narrated proof a stakeholder can trust without running anything test,review 6 ondemand verify record-demo-video skills/record-demo-video.md Recording a narrated screen-capture demo of a running app for a human to watch — opening on the app instead of a blank frame, and keeping captions synced to the pixels test 6 ondemand verify demo-recording-polish skills/demo-recording-polish.md A demo film someone will watch looks captured, not produced — 25 fps smear, scroll jumps, no visible pointer, a dense page nobody can read: 2x CDP screencast at 60 fps, drawn cursor and click ripple, eased scroll, and a zoom rendered afterwards from the click log (never a CSS transform in the page) test 6 ondemand verify +live-demo-autopilot skills/live-demo-autopilot.md Running a customer demo LIVE instead of a video — Playwright drives the real app through scripted scenes with captions and a control panel (pause and take over, redo, skip); off-screen or tile sign-in, session expiry, the 2.5 h trial-licence stop and the 6-session cap test 6 ondemand verify share-demo-package skills/share-demo-package.md Sending a demo guide, screenshots or a quickstart doc OUTSIDE the repo — to a customer, prospect or reviewer: relative image paths and "the name shown above" both break the moment the file travels alone, and the usernames a login panel displays are not the ones it accepts test,review 6,7 ondemand verify mpr-corruption-and-sp-load-errors skills/mpr-corruption-and-sp-load-errors.md Studio Pro will not load the project, or the .mpr looks gutted — recover before relaunching SP, never git checkout mdl,gate - ondemand diagnose lint-gate project-bin/lint-gate.sh Running lint as a gate rather than a report — per-rule ratchet against a committed baseline, plus the crash and collapse guards that stop a blind rule passing mdl,gate 5,6 ondemand verify diff --git a/skills/live-demo-autopilot.md b/skills/live-demo-autopilot.md new file mode 100644 index 00000000..05aa29aa --- /dev/null +++ b/skills/live-demo-autopilot.md @@ -0,0 +1,110 @@ +# Live Demo Autopilot — a scripted demo that runs live, with a control panel to take over + +**Applies to:** any mxcli project +**Purpose:** running a customer demo LIVE (no video) where Playwright drives the real app through +scripted scenes, captions say what and why, and the presenter can pause and take over, resume, +redo, skip, restart or stop at any moment. +**Source:** two field builds, 2026-10. Project A: a manufacturing app, desktop window and phone +window side by side, offline web app scenes, 4 scenes / 4 users, all scenes passing. Project B: a +process hub plus two domain apps (three Mendix apps, five personas), 6 scenes / 28 steps; final +test run 28/28 with one app killed mid-run and an 11 minute pause. This skill keeps the best of +both: A's layout, traceability and password-free sign-in, B's reliability layer. + +Not this skill: a film someone watches later → `record-demo-video.md` and `demo-recording-polish.md`. +A demo video is not a test; this autopilot IS one — it reports `X/N` steps every run. + +## 1. The three pieces + +| Piece | Presenter sees | Built as | +|---|---|---| +| **Launcher** | one local page: a light per app, licence minutes left, Start apps / Fresh restart / Start demo / Stop, links to deck and click list | ~140 lines of Node `http`; polls `/api/status` every 3 s; spawns your start scripts; no password passes through it | +| **App window(s)** | the real app, a drawn pointer that glides to each target and ripples on click, a caption plate (step + WHY line), a scene card at each scene start | Playwright, visible Chrome (`channel: 'chrome'`) | +| **Control panel** | scene list with pass/fail dots, the current step, the line to say, the process step and model element on screen | second window with `panel.html`; buttons talk back through `page.exposeBinding('demoCtl', ...)` | + +A control file (`ctl.sh pause|resume|redo|skip|restart|stop` appends to `/tmp/-live.ctl`, +polled every 300 ms) lets a clicker, a Stream Deck or a test watcher drive it too. + +## 2. The script is data + +```js +const SCRIPT = [{ title, why, who, device /* or app */, win, steps: [ + { id, short, cap, why, say, proc, element } ] }]; +const ACTIONS = { 'l-list': async page => { /* clicks */ } }; // one function per step id +const BEFORE = { 3: async () => { /* arm a fault, start a case through the API */ } }; +``` +- `cap` caption, `why` second caption line (why it matters to the business), `say` presenter line (panel only). +- `proc` the requirement / process step id (e.g. `P4-01`) and `element` the model element on screen + (`Module.PageName · NF_Submit`): the panel shows both, so every step traces to a requirement. +- Every step lingers ≥ 3 s. Each scene starts with an **anchor** that puts the right user on the + right page, so Redo and Skip always start from a known state. + +## 3. Choose the window layout + +| Story | Layout | +|---|---| +| Desktop + phone (offline web app) | two windows side by side, placed with CDP `Browser.setWindowBounds`; arrow pointer on desktop, touch dot on the phone (`matchMedia('(pointer: coarse)')`); offline scenes with `context.setOffline(true)` | +| Many users across several apps | ONE visible window; switch user by swapping session cookies, then click the sidebar link (no reload flash). Count full page loads and report them | + +## 4. Sign-in without a password on screen + +1. **Best: demo sign-in tiles** in the app (one tap per persona). No password in the script at all. +2. Else: sign in **off screen** in a headless browser and hand the session cookies to the visible + window. Passwords from env or a gitignored `.env`, never logged. Never parse them out of model + or seed scripts. +3. Set the persona's UI language during sign-in: a language stored per user survives reseeds, + and one user left in another language breaks every text selector. + +## 5. Reliability rules (each one broke a run before it existed) + +1. **Every click goes through `gate()`**: that is where pause, skip, redo and stop take effect. + After a pause, re-check the session and return to the page — the presenter clicked around. +2. **Same URL is not proof you are there.** Mendix opens forms and detail pages without changing + the URL; on a list URL require a visible list row before skipping the navigation click. +3. **Off-screen sessions expire** (10 min idle is common; an SSO app then shows its identity-provider + page). Track last use per persona; idle > 8 min → fresh sign-in before switching. Detect the + login and SSO pages and recover. +4. **Before each scene, every app must answer.** A dead app is named in the panel and the demo + waits (5 min) instead of failing on `fetch failed`. +5. **A step that needs state from a skipped step** (a case number) finds it on screen instead. +6. **Tag everything the demo types** (`ZZTEST-LIVE`, `CR-LIVE-`) so reset-and-seed removes it. +7. **Word guard**: a MutationObserver rewrites words that must never be on screen ("mock" → + "stand-in") and the run log counts the hits. +8. **Honest summary**: `steps passed X/N failed F gaps G`. A step the UI cannot do is a GAP, never + a pass. `--proof` saves a screenshot per scene end; read them back. + +## 6. Mendix trial-licence traps + +| Symptom | Cause | Fix | +|---|---|---| +| App "crashes" after a while: `ERR_EMPTY_RESPONSE`, a defunct java process | the trial licence stops the runtime ~2.5 h after start: `LicenseService: Maximum run time exceeded` in the runtime log | launcher shows minutes left (last "Runtime successfully started" line); **Fresh restart < 1 h before presenting**; the demo warns at start when < 35 min | +| `Maximum number of sessions exceeded` | 6 concurrent sessions; tests leak them | sign out with POST `/xas/` `{"action":"logout"}` + CSRF token, only after `mx.session.getConfig().csrftoken` exists, network idle + 1.5 s (earlier returns 200 but the session row stays); count `System.Session` with OQL before starting | + +## 7. Control-path traps + +| Symptom | Cause | Fix | +|---|---|---| +| Run sits paused right at the start | the new panel window steals focus; a Space typed elsewhere lands in it | tag key commands `key:`; ignore them for 3 s after the panel opens and in unattended runs (`--no-keys`) | +| Stop leaves sessions behind | Playwright closes the browsers on SIGTERM before your handler signs out | `chromium.launch({ handleSIGTERM: false, handleSIGINT: false, handleSIGHUP: false })`; freeze `gate()` while signing out | +| `mx.session.getConfig()` throws | session not loaded yet | call it inside try/catch in `waitForFunction` | + +## 8. Prove the autopilot before the customer does + +```bash +node live-demo.mjs --proof --exit-when-done --no-keys > run.out # unattended run +``` +Inject the failures that will happen on the day with a watcher that reacts to **log lines**, not +timers (a timer drifts): kill an app after scene N and restart it once the log says `APP DOWN`; +`ctl.sh pause` for 11 min after scene M, then resume. Pass = `X/N` with the denominator, and +the session count back to 0 after the run. Write the result to a report file. + +## 9. Optional: change it live + +The strongest close: approve a small change request in the room, then show it built. Before +screenshot → CR script → `mxcli check` → `bin/exec.sh` → restart → after screenshot. Pick a +one-page change (a column, a caption) and keep a spare; anything needing a new attribute on a +row object goes to the next change round, not the stage. + +## Portability + +Proven on macOS only (window placement, `open`, `pgrep`). Resolve Playwright with +`createRequire` from your global install instead of a hard-coded path. Windows: not field-run yet. diff --git a/skills/record-demo-video.md b/skills/record-demo-video.md index 0422f3ee..9d9d7247 100644 --- a/skills/record-demo-video.md +++ b/skills/record-demo-video.md @@ -5,6 +5,7 @@ narrated product demo, not a test artifact — with a repeatable technique for opening on the app instead of a blank frame, and for keeping narration synced to what's on screen. +**Live instead of recorded:** `live-demo-autopilot.md` (scripted demo run live, with a take-over panel). **Source:** field-tested on a live mxcli project's Playwright demo-recording script (mobile tour, two roles), 2026-09; the Node, counter, row-lookup and skip notes come from a requirements-driven back-office build's three-film set, From dfa48ea8034f91b558c91786dbf51330b5986721 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 15:37:13 +0000 Subject: [PATCH 2/2] Address #602 review: verified logout, 2-4 h licence stop, tiles off by default - Logout: a 200 proves nothing. Prove each logout by the System.Session count, and point at testing-shape.md, which measured /xas/ logout returning 200 with the session alive on Mendix 11.14. Keep the field run's timing recipe and fall back to mx.logout() if the count does not drop. - Trial licence stop: 2-4 h, with the 2.5 h run named as one field observation; load-test.md section 9 covers both limits. - Demo sign-in tiles: build them only into a demo or dev build, behind a constant that is off by default, and check it before any deploy. - Live change request: run it on a copy or branch of the demo model. render-routing --check in sync (baseline unchanged, 64,252); check-no-private-citations clean. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018LeNWZV2sVH62vkgfYh5u5 --- CHANGELOG.md | 2 +- skills/live-demo-autopilot.md | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e58d3f7..38e72b6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased -- learn(demo): **`skills/live-demo-autopilot.md` — run the demo live, not as a video**: Playwright drives the real app through scripted scenes, captions carry a WHY line, a control panel lets the presenter pause and take over, redo or skip; plus the traps that each broke a run (trial licence stops the runtime ~2.5 h after start, 6-session cap and when `/xas/` logout really frees a slot, focus-stealing panel pausing the run, SIGTERM closing the browser before sign-out). Field: a desktop+phone offline manufacturing demo (4/4 scenes) and a three-app process-hub demo (28/28 with an app killed mid-run and an 11 min pause), 2026-10 — Maurits Visser +- learn(demo): **`skills/live-demo-autopilot.md` — run the demo live, not as a video**: Playwright drives the real app through scripted scenes, captions carry a WHY line, a control panel lets the presenter pause and take over, redo or skip; plus the traps that each broke a run (trial licence stops the runtime 2–4 h after start, 6-session cap and proving a logout freed its slot by the `System.Session` count, demo sign-in tiles kept out of any deployed build, focus-stealing panel pausing the run, SIGTERM closing the browser before sign-out). Field: a desktop+phone offline manufacturing demo (4/4 scenes) and a three-app process-hub demo (28/28 with an app killed mid-run and an 11 min pause), 2026-10 — Maurits Visser - docs(bug-ledger): **32 ledger entries now say what mxcli v0.22–v0.29 changed about them, before anyone re-runs an old workaround**: 22 are fixed upstream per the mxcli changelog or source (among them BUG-121 terminators, BUG-141 workflow PersistentId, BUG-151 `rest call body $Var`, BUG-100 shared Docker stack, BUG-94 role visibility, BUG-128 module-role idempotence) and 10 changed shape or are partly fixed (BUG-154; BUG-04 no automatic module role since v0.27, BUG-WF04/WF05 named call arguments since v0.25, BUG-130/131 vs the v0.27 `exec` rollback). Each gets an "Upstream status" line naming the version, the issue and what to retest; none is closed or archived, because none was retested — the ledger archives only after a retest. Also corrects `BUG-DRAFT-audit-member-access-ce0066`: commit `2455ee9f` first shipped in v0.23.0, not v0.22. Source: mxcli v0.29 compatibility audit 2026-10-30 - fix(doctor, exec, page-scope, rehost, wf-add-path-terminators, module-close): **mxcli v0.29 compatibility, and doctor advises the latest mxcli**: on v0.29.0 (which `--install` fetches by default) four instruments read new output wrong. (1) `fix property-sets` prints `MIXED` rows and exits 1: doctor reported "could not classify" (rc 4, shown as info by sync) — now result `mixed`, a WARN naming the rows and saying the repair cannot clear them; (2) the repair also exits 1 while a MIXED name remains, so `--fix-property-sets` rolled back a repair that had landed — the apply step now passes when only MIXED is left (FAILED still fails); (3) `fix hashes` now verifies MPR v1 with new text, which exec.sh read as an error, so every `--patch` on a Mendix < 10.18 project went unverified — both v1 forms are read; (4) since v0.28 `SHOW MODULES` / `list modules` write `Protected AddOn|Solution` in Source, so a first-party module set to Protected dropped out of page-scope (FAULT, 0 modules) and out of the rehost module list — the export level no longer counts as an origin. `wf-add-path-terminators.py` refuses below Mendix 10.21 (the terminator type does not exist there; written in, the project will not load), module-close notes that v0.29 `docker check` checks the stored project (a CE0463 it now reports is real), and the stale "stay on v0.24" pin advice is replaced. **New:** the normal doctor run compares the project mxcli with the latest release (redirect of the asset URL, 5 s, nothing downloaded): WARN with release link and upgrade path when behind, a note when `MXCLI_VERSION` pins it, one quiet note offline, never a FAIL; `MXTK_NO_LATEST_CHECK=1` skips it. Golden input captured from the real v0.28.0/v0.29.0 binaries on the mxpatch fixture model and mutated copies (CAPTURE files); against master the new cases fail (exec-hash-verify 4, property-sets 7, mxpatch 1, page-scope-protected 3, rehost-list-modules 1, doctor-mxcli-latest 8). Field run: page-scope and doctor against real v0.29.0/v0.28.0 binaries in a cloud session — mxcli v0.29 audit (2026-10-30) - fix(skills): **skill text no longer tells agents that mxcli v0.25–v0.29 cannot do things it now does**: STOP 21 said `ALTER NAVIGATION` does not exist and restatement is the only write — it now points at `alter navigation`/`alter menu` (v0.28, mendixlabs/mxcli#1522) and in-loop `alter microflow`/`replace body of` (v0.29, ako/mxcli#1693), keeping its describe-first rule; STOP 1b now writes the bare `Editable: ` (v0.25) and limits the quoted-form trap to mxcli < v0.28 (#1567); `learned-mdl-cannot-express.md` marks file upload (`filemanager`, v0.27), tab `Badge:` (v0.29), app title (v0.29), role visibility `Visible: roles(…)` (v0.27) and `sidebartoggle` (v0.28) buildable from their version; four `learned-detection-gaps.md` rows (terminators, `if` without `else` in a handler, `Class` on a snippet call, property sets below 10.24.24) and `platform-link.md` now name the mxcli version that fixed them; three passages no longer assume mxcli auto-creates `.User` (gone since v0.27, #1474). `mdl-scan` STOP-1 now also catches the bare `Visible:/Editable: ` form inside a customContent column (it matched only `[`), since STOP 1b now recommends that form. Nothing deleted: old-version guidance stays, version-gated, because nothing was re-probed. Baseline 64,193 → 64,252 words. Source: mxcli v0.29 compatibility audit 2026-10-30 diff --git a/skills/live-demo-autopilot.md b/skills/live-demo-autopilot.md index 05aa29aa..e800ca7c 100644 --- a/skills/live-demo-autopilot.md +++ b/skills/live-demo-autopilot.md @@ -48,6 +48,9 @@ const BEFORE = { 3: async () => { /* arm a fault, start a case through the API ## 4. Sign-in without a password on screen 1. **Best: demo sign-in tiles** in the app (one tap per persona). No password in the script at all. + Tiles are an authentication bypass: build them only into a demo or dev build, behind a constant + that is **off by default**, never in a deployed or shared environment, and check that constant + is off before any deploy. 2. Else: sign in **off screen** in a headless browser and hand the session cookies to the visible window. Passwords from env or a gitignored `.env`, never logged. Never parse them out of model or seed scripts. @@ -76,8 +79,8 @@ const BEFORE = { 3: async () => { /* arm a fault, start a case through the API | Symptom | Cause | Fix | |---|---|---| -| App "crashes" after a while: `ERR_EMPTY_RESPONSE`, a defunct java process | the trial licence stops the runtime ~2.5 h after start: `LicenseService: Maximum run time exceeded` in the runtime log | launcher shows minutes left (last "Runtime successfully started" line); **Fresh restart < 1 h before presenting**; the demo warns at start when < 35 min | -| `Maximum number of sessions exceeded` | 6 concurrent sessions; tests leak them | sign out with POST `/xas/` `{"action":"logout"}` + CSRF token, only after `mx.session.getConfig().csrftoken` exists, network idle + 1.5 s (earlier returns 200 but the session row stays); count `System.Session` with OQL before starting | +| App "crashes" after a while: `ERR_EMPTY_RESPONSE`, a defunct java process | the trial licence stops the runtime 2–4 h after start (one field run, 2026-10-30: 2.5 h): `LicenseService: Maximum run time exceeded` in the runtime log. Both trial limits: `load-test.md` §9 | launcher shows minutes left (last "Runtime successfully started" line); **Fresh restart < 1 h before presenting**; the demo warns at start when < 35 min | +| `Maximum number of sessions exceeded` | 6 concurrent sessions; tests leak them | sign out, then **prove it**: the `System.Session` count (OQL) must drop after each logout and be 0 after the run. A 200 proves nothing: `testing-shape.md` (UI, logout helper) measured POST `/xas/` `{"action":"logout"}` returning 200 with the session alive (Mendix 11.14). In the 2026-10-30 field run the same call freed the slot only when sent with the CSRF token, after `mx.session.getConfig().csrftoken` existed, network idle + 1.5 s. If the count does not drop, use `mx.logout()`. Count sessions before starting too | ## 7. Control-path traps @@ -99,7 +102,8 @@ the session count back to 0 after the run. Write the result to a report file. ## 9. Optional: change it live -The strongest close: approve a small change request in the room, then show it built. Before +The strongest close: approve a small change request in the room, then show it built, on a +**copy or branch** of the demo model, never the one the scenes run on. Before screenshot → CR script → `mxcli check` → `bin/exec.sh` → restart → after screenshot. Pick a one-page change (a column, a caption) and keep a spare; anything needing a new attribute on a row object goes to the next change round, not the stage.