Skip to content
Hozu
Menu
All trials

Trial 0003 — Fresh agents build and change the same app in Tenon and in Nuxt

Question (step 2 of trial 0002): does an AI that has never seen Tenon build and maintain an app more cheaply or more correctly than with a mainstream framework? The decision on Phase 6 depends on the answer.

Setup

Results

Tenon build Nuxt build Tenon change Nuxt change
Hidden acceptance 12 / 12 12 / 12 6 / 6, regression 12 / 12 6 / 6, regression 12 / 12
Assistant turns 47 20 45 15
Shell commands 27 11 24 6
Tool output read (chars) 105,733 11,484 45,122 17,359
Output tokens 21,961 8,769 14,943 5,513
Fresh input tokens 198,017 39,747 80,238 36,456
Cached input tokens read 3.87 M 0.97 M 2.80 M 0.72 M
Wall time 3.9 min 2.0 min 2.7 min 1.2 min
App source after the change 24.0 KB (contracts 4.6 KB) 11.0 KB

Tenon cost about 2.5–4× more on every token metric and took about 2× the time. Correctness was the same: both arms passed everything, and so did the regression suite after the change. The Nuxt agent also made its forms work without JavaScript, which Tenon cannot do yet (ADR 0011, Tier 1 item 5).

Where Tenon's cost came from

  1. Learning:
    • Before writing any code, the build agent read three examples, three ADRs and then the framework source (ui.ts, op.ts, fn.ts), because the docs did not answer its questions.
    • The change agent (also fresh) read framework source again: the invalidation builder, the adapter's tag handling and the client runtime.
    • Nuxt needs none of this; the model already knows it.
  2. Busy states duplicate the UI (TN005):
    • Every control that sends an event must be handled in every state where it is visible.
    • Handling an event in a busy state would re-run the invoke, and there is no way to say "ignore this event here".
    • So the agent rendered every control twice: once live in idle, once disabled in adding / toggling. This is the largest single source of extra code.
  3. DOM strings to enums: a <select> value arrives as string, so choosing a priority took three guarded transitions, following the showcase's pattern.
  4. Coarse invalidation: invalidates can read only the mutation input. "Clear done" cannot name the deleted ids, so every detail query got the list-wide tag.
  5. Contracts: 4.6 KB of the 24 KB. They are required (TN016), and they did not find a defect in this trial because the agents made none that the acceptance suite detected.
  6. Undocumented details:
    • filtering a query result by machine state (fn as an each source)
    • the /_tenon/effect request shape that the agent needed for curl

Framework defect found and fixed

The detail page (no machine) shipped client.js and the whole feature machine. planRoute collected the mutations that all of the page's features could invalidate, even from features whose machine is not bound on that page. Only machine-bound page views count now. The page ships 0 JS again, as principle 8 requires. Regression test: packages/compiler/test/plan.test.ts.

What trial 0002's step 1 changed here

Nothing observable. Neither agent wrote a literal value outside its schema. This confirms the user's point that character typos are not how AI fails. The fresh agents' real friction was learning cost and expressiveness, not invalid values.

Verdict

Not confirmed.

Limits: one run per arm, one small app, the same model for both arms. Verification may pay off on larger apps and over longer maintenance. This trial does not show that, and it shows the price clearly.

Recommendation

Do not start Phase 6 (ADR 0011). What decides the question is Tenon's cost for an AI, not the number of features it has. Two directions, for the user to choose: