# One app, several builders — blank-app trial v1

Snapshot date: 2026-10-21. Protocol ready; vendor runs pending. No winner,
vendor score, measured cost, app export or app-version claim is available.

## Run ledger

- Lovable: blocked before creation. Registry says claude.ai connector only;
  no callable Lovable tool in this session. MCP Beast returned no_match twice
  on 2026-10-21 (search IDs 2089b66b-1aee-44f9-a468-d071de21f3cc and
  d11980e8-a0c3-4f6e-8090-e67ee316832d). Access gap, not a product defect.
- Bolt: blocked before creation. Coordinating session reports CLI/router
  discovery found no execution route after re-check. No runtime result.
- Cursor: not run. Hold the shared trial pending builder access; do not
  substitute an unrelated existing-repository task.
- All workflows: versions, plans, model selections, exports, elapsed minutes,
  costs, browser results and reviewer notes remain uncollected.

## Initial prompt — identical in every tool

Build a single-user task board from a blank project. Synthetic data only.
No login, payments, cloud database, analytics, external APIs or production
deployment. Add a task, mark it complete and retain title and status after
browser reload using localStorage. Display empty and invalid-input states.
Corrupt saved data must show a recoverable error; preserve it until the user
explicitly resets. Render titles as text, never HTML. Use a labelled title
input, an Add task button, a completion button per row and readable status.
Keyboard operation must work. Report storage write failures visibly.

Put the actual logic used by the UI in dependency-free task-store.mjs at the
export root, with these pure exports:

- addTask(tasks, title, id): new array, trimmed title, completed:false;
  blank title and duplicate id throw.
- completeTask(tasks, id): new array marking that task complete; repeating is
  harmless; unknown id throws. Never mutate input arrays or records.
- serializeTasks(tasks): JSON string retaining ids, titles and completion.
- restoreTasks(value): restore those records; null returns []; corrupt JSON
  and non-array input throw.

Include package and lock files, install/build/start commands and a README
covering storage/recovery. No credentials. Do not add filters yet. Record
all prompts, repairs and manual edits. Export before any repair.

## Follow-up prompt — after initial export and acceptance

Add All, Open and Completed filters. Preserve previously saved data. Filtering
must not delete or rewrite records. Export filterTasks(tasks, filter), accepting
all/open/completed, rejecting other values and never mutating input. Retain
all initial behavior. Export again before repairs.

## Runnable domain acceptance

Download app-builder-comparison.mjs beside this brief. Record the Node.js
version used. Review generated code before running: importing an export
executes local code. This verifier uses only Node built-ins.

    node app-builder-comparison.mjs /absolute/export/task-store.mjs initial
    node app-builder-comparison.mjs /absolute/followup-export/task-store.mjs followup

Nonzero exit means failure. Save the command and raw stdout/stderr. Missing
exports fail rather than being excluded. This deliberately constrained module
contract does not prove a platform cannot implement another design.

## Browser acceptance — required, currently unrun

1. Start the export using its README in a clean browser profile. Add Review
   export and Test recovery. Complete Review export. Reload: retain both tasks
   and their statuses. Add another task using only the keyboard.
2. Submit a blank title: visible error, no added record. Enter a title with
   an HTML tag: display literal text without executing markup.
3. Start the follow-up export with existing storage. Switch Open, Completed
   and All; verify matching rows and reload without losing any records.
4. Replace only the synthetic app's saved value with corrupt JSON in browser
   developer tools. Reload: capture the recovery message; preserve that value
   until explicit reset. Simulate localStorage write failure and capture a
   visible save error; do not accept successful-looking unsaved changes.
5. Record browser version, viewport, screenshots, console errors and failures.
   Inspect the UI's imports to confirm it uses the module tested by the oracle.
   Domain success cannot replace browser acceptance or a security review.

## Export and independent handoff

Use a dated directory for each tool and phase. Include unmodified source
archive, SHA-256, prompts, exact displayed plan/model/version (unknown when
not shown), timestamps, commands, raw oracle output and browser evidence.
Preserve first failures and subsequent repairs separately. A second reviewer
must start the export using the README without the original builder session.
Record install/build failures, missing setup, manual edits, review minutes
and whether existing data survives the follow-up.

Only synthetic inputs; inspect archives for secrets and identifying data
before publication. Record observed usage separately from subscription price.
Unavailable billing is unknown, never zero. Record platform waits separately
from human intervention. Agree a trial budget before execution; unfinished
work stays unfinished when that limit is reached.

## Interpretation

Each check is pass, fail, blocked or not run, with an artifact. Missing runs
never become scores or averages. Domain, browser and handoff results stay
separate. This local app says nothing about authentication, multi-user access,
backend reliability, production deployment or security. Those require another
explicit scope. Publish a dated snapshot when real exports exist, without
promising a perpetual leaderboard.
