0.16.0
Found by watching real models build apps from the wizard, end to end, on a
scratch store — and fixing what made them wander. Measured before release:
DeepSeek V4 Pro built the whole API brief (eight stories, four verifier calls
with twelve step checks) in sixteen minutes for fifteen cents, and five of six
dashboard stories with zero console errors and no sideways scroll at 1280px or
390px; it scores the five app skills at 96, 70, 75, 80 and 100 percent. GLM 5.3
Flash reaches the same places more slowly and, reading images, receives the
verifier's screenshots.
Added
- Checks that follow a requirement.
VerifyAppchecks takesteps— goto,
click, fill, select, press, wait — and anexpectof a selector,{ text },
{ url }or{ absent }, so "add a customer" is fill, submit, see the row.
Checks in one call share a page and its cookies, so a sign-in check first
leaves the rest signed in.screenshot: truesaves a PNG after load and
after each check under.aico/screenshots/and names the paths;
viewportis documented for the phone width. A failed check says what was
done and what was missing ("filled #name, clicked #add, but nothing matched
.row"). Before this a check could click one selector, and the agent, asked
to verify a form flow, installed a browser MCP and wrote its own driver. - A design skill.
app-designsays what a screen people pay for looks
like — one shell, hierarchy and rhythm, tokens not hex, real empty, loading
and error states, forms and tables, 390px and keyboard — with the six shapes
as Tailwind sketches in its references, an eval task, and a place in the
plan and platform skills. - The SaaS template has a product shell. Signed in: side navigation from
onenav.tslist, a page header with the counts and the primary action,
StatCard,StatusPillandEmptyStatecomponents, a menu undermd.
Signed out: a front door without placeholder copy. Success and warning
tokens, an icon, and a sentence inAICO.mdnaming the components and the
design skill. - Apps are runnable the moment they exist. Create writes
.env.localfrom
a template's.env.examplewith everychange-mevalue replaced by a
generated secret. The first sign-up used to throw "SESSION_SECRET is
missing" and the agent spent twenty steps on a form that was fine. - A bound conversation starts with the app. The empty state names the
app, its backlog progress, and offers "Build the next story", "Review what
is built" and "Plan the next iteration". - GUIDE.md has "Building an app" and the learning paragraph.
- Eyes for the verifier. When the session's model reads images, the
screenshots aVerifyAppcall saved are stored as attachments and shown to
the model on the next step, with a note to look at them as a person would.
Text-only models keep the paths for the person. GLM 5.3 Flash and the
DeepSeek V4 Flash vision build are marked as reading images. - Checks are not spent twice on unchanged code.
RunChecksremembers the
last green run per project; with no file written through the tools and no
shell command since, it answers with that result instead of a minute of
build.force: trueruns them anyway. - Two live probes.
scripts/apps-build-live.mjsdrives the whole loop with
a real model — create from a template, plan, build story by story, rate a
reply and keep the proposal it produces, steer a turn, deploy, then open
every screen in a browser at two widths — and never cuts a busy turn short.
scripts/skill-eval-live.mjsscores the five app skills against their tasks.
npm run test:apps:build,npm run test:skills:live.
Fixed
- The app-state line was computed once per turn. It said "installing"
through twenty steps of a running app, and the agent reported the state as
inconsistent and spent steps reconciling it. The caller's volatile sections
are now re-read before every step. - MCP tools added mid-turn were not callable.
McpAddServerloaded the
server and said "24 tools", but the tool list the model saw was built at the
top of the turn, so it guessed at names. The set is synced before each step. - A browser-cancelled request is not a failure.
net::ERR_ABORTEDon a
form POST answered by a redirect was reported as "request failed". - The side rail floated over the app panel. Plan, checks and task cards
were fixed to the window's edge; they now anchor to the chat column. - A build check knocked the running dev server over.
next devand
next buildwrote to the same.next; the two Next.js templates now give
development its own directory (.next-dev), which the engine's file lists
skip, and the health check answers 200 through a build. The dev server's
generated route types stay out ofnpm run typecheck, so deleting a page
no longer fails the check until the server has noticed. - OpenRouter's output ceiling was 8,192 tokens. A reasoning model routed
through the gateway reached it mid-thought, with nothing written and the
step reported as cut off. The default is 32,768, as for Z.AI first-party;
providers.openrouter.maxOutputTokensoverrides it. - A router's model id went to the wrong gateway. With a direct vendor
active,z-ai/glm-5.3-flashwas sent to a compatible endpoint that had
listed its two models and named neither, and every skill evaluation and a
whole build failed with "please check the model you provided". A gateway
that lists the model wins; then OpenRouter; then one that has said nothing. - A rating given after a turn ended was never extracted. The person reads
the reply, then clicks 👎, so the rating lands afterturn/end; extraction
at the end of the next turn only looked at that turn. It now also reads the
previous turn's ratings. Proposals from a session bound to an app are filed
with the app, not the workspace every app session shares. - The API template answered a browser with not_found. Its front door now
says what it is and where the OpenAPI document and health route are, and it
answers the favicon request a browser makes on every visit, which used to be
the one console error on an otherwise clean run. - A finished install read as "Stopped". The work ledger closed a
completednpm installas a stopped server; it now says "Installed", and an
app that starts again after an ended record opens a new one. - Money is not maths. "$240.00 (subtotal $200.00)" in a reply rendered as
a formula. A dollar that opens a plain number is escaped before the maths
pass;$x^2$, display maths, code spans and fences are untouched. - Paths read relative to the project or the app. Tool rows and the turn
summary showed sixty characters of temp directory before the file name; the
project root is stripped, and inside a bound app everything up to the app's
directory is. - The layout probe's app host takes a port of its own, so an aico already
serving on the machine no longer makes the workspace screen fail. - Ranking tests, workspace-root idempotence test, and the templates probe
(42 checks) were run before this entry.