by Milica Antic
Gallery
1 / 5
What it does
Wemora migrates a React web app (an SPA with React Router) to an Expo / React Native mobile app, screen by screen, and proves that each mobile screen behaves like the original. A tester agent writes executable UI tests against the original web app. Each test must pass on the original and fail on an empty screen. A builder agent writes the mobile screen. A deterministic Gatekeeper promotes the screen into the app only after the screen passes type checks and runs every one of its tests. Each screen ends as proven, partial, unproven or failed, with the reason in an HTML report. npm run verify re-runs all saved tests on a finished run with no model and no API key, and npm run sabotage breaks one screen to show that verify catches it.
How the agents run concurrently
All participants join one Mozaik runtime and coordinate only through typed events on the bus. Events carry IDs only. The data lives on one shared board, a RuntimeState subclass that holds the plan, the status and round of every unit, the tests, the gate results, the coverage and a cost ledger. Analyzers (1–4) read parts of the web app in parallel. When the last analysis.done arrives, an architect merges their reports into a plan. The plan is split into waves: shared units first (data, layout, theme), then screens. Builders (up to 4) and testers (up to 2) then work at the same time. Testers take screens from every wave at once and test the original web app in a real browser. Builders write mobile code for every unit whose dependencies are promoted. Each builder can write only to its own staging folder, which a Mozaik interception handler enforces. The Gatekeeper (a non-model participant) holds each draft.submitted until that screen's tests.ready arrives. It then runs the gates and either promotes the screen (unit.promoted) or sends gate.failed. A failed draft goes back to the same builder with the exact failing step. Rounds 3–4 move to a stronger model. The Conductor (also non-model) owns the task queue and the team size. It sets the number of builders and testers from the ready work, at most one change per minute. It adds a tester when screens queue up without tests. It lowers the builder limit when the API returns 429. It stops cleanly when the budget runs out. Every decision is logged with its reason (agents.rescaled, rate.limited). In our real Recepti run, 4 builders and 2 testers ran in parallel. When the gateway started returning 429, the Conductor scaled builders down from 4 to 1 and back up. run.jsonl and the report's timeline show the overlapping agent work.