E1 · Green battery
5 minRun the full battery.
Done when: node scripts/bateria.mjs; echo "saída: $?" → BATERIA: 24/24 ok and saída: 0.
Lesson 4 · 18 min
When the code or the spec changes, a site with WebMCP fails silently: detection does not find the API, falls back to the form, and nobody notices. Only a battery catches it. In this lesson you freeze the contract and the cases for the tools, run them in all four modes, and watch the battery catch the old API name.
Start the lesson
Goal: freeze the contract and cases for your tools, run them in four modes, and watch the battery catch the old API name regression.
Click each step.
The battery in course 2 tests the page; this one tests the page and the server against a contract that does not change without a decision.
Inherited from LOOP-R Engenharia (frozen tests) and applied to the tools.
The expected result does not change just to make the test pass. Did the spec or the rule change? Re-freeze and explain it in the commit.
The hash makes the change visible: nobody edits casos.json without the battery refusing.
The cases call the tools directly (executeTool, tools/call), as an agent would.
No model in the loop: the same code gives the same verdict.
The round with no API proves that the person books through the form.
It is the first line of the battery, before any agent.
New spec, new Chrome or new SDK: run the battery before anything else.
The watcher from lesson 6 tells you when it is time.
watcher flags it → battery → read what changed → fix or re-freeze with a reason
Four modes, 24 checks, no model and no cost.
cd ~/projetos/formacao-webmcp-expert-v72/kit node scripts/bateria.mjs; echo "saída: $?"
== Chromium 156.0.8078.4 (Playwright) · bateria congelada (spec 2026-10-16, MCP 2026-07-28) ok [sem] fallback: página sem WebMCP e sem erro de JavaScript · sem ok [sem] fallback: a pessoa reserva pelo formulário ok [polyfill] contrato: 4 ferramentas com as anotações congeladas · 4 registradas ok [polyfill] c1 buscar_oficinas · of-301 ok [polyfill] c2 buscar_oficinas · erro ok [polyfill] c3 reservar_vaga (pessoa recusa) · 0 reserva(s) ok [polyfill] c4 reservar_vaga (pessoa confirma) · 1 reserva(s) ok [polyfill] c5 reservar_vaga (pessoa confirma) · erro, 1 reserva(s) ok [polyfill] c6 listar_comentarios · 2 comentário(s) ok [polyfill] nenhum erro de JavaScript ok [nativo] contrato: 4 ferramentas com as anotações congeladas · 4 registradas ok [nativo] c1 buscar_oficinas · of-301 ok [nativo] c2 buscar_oficinas · erro ok [nativo] c3 reservar_vaga (pessoa recusa) · 0 reserva(s) ok [nativo] c4 reservar_vaga (pessoa confirma) · 1 reserva(s) ok [nativo] c5 reservar_vaga (pessoa confirma) · erro, 1 reserva(s) ok [nativo] c6 listar_comentarios · 2 comentário(s) ok [nativo] nenhum erro de JavaScript ok [mcp] contrato: 2 ferramentas com as anotações congeladas · buscar_oficinas,reservar_vaga ok [mcp] c1 buscar_oficinas · of-301 ok [mcp] c2 buscar_oficinas · erro ok [mcp] c3 reservar_vaga (pessoa recusa) · 0 reserva(s) ok [mcp] c4 reservar_vaga (pessoa confirma) · 1 reserva(s) ok [mcp] c5 reservar_vaga (pessoa confirma) · erro, 1 reserva(s) BATERIA: 24/24 ok saída: 0
c5 asks the person and they confirm, but the rule refuses (of-102 has no spots left): an error and no new booking. In MCP, the question to the user comes before the rule's refusal.
BATERIA RECUSADA: casos.json ou contrato.json mudou depois de congelado. Se o esperado mudou de verdade (spec nova, regra nova), rode --recongelar e explique no commit. saída: 2
Someone changed "reservas": 0 to 1 in case c3 to "make the test pass". The battery does not even run: the hash does not match bateria/CONGELADA and the exit code is 2.
navigator.modelContext is the old name (before PR #177, accepted on 05/19/2026). A copy of the page that uses it: the site keeps working, and only the battery notices.
cd ~/projetos/formacao-webmcp-expert-v72/kit
E=$(bash scripts/copia.sh a4)
# a regressão: alguém cola um exemplo antigo que usa o nome de antes de 19/05/2026
sed -i 's/const mc = document.modelContext; /const mc = navigator.modelContext; /' $E/pagina/ferramentas.mjs
cd $E && node scripts/bateria.mjs sem nativo | grep -E "FALHA|ok \[sem\]|BATERIA"; echo "saída: ${PIPESTATUS[0]}"ok [sem] fallback: página sem WebMCP e sem erro de JavaScript · sem ok [sem] fallback: a pessoa reserva pelo formulário FALHA [nativo] contrato: 4 ferramentas com as anotações congeladas · 0 registradas FALHA [nativo] c1 buscar_oficinas · ferramenta ausente FALHA [nativo] c2 buscar_oficinas · ferramenta ausente FALHA [nativo] c3 reservar_vaga · ferramenta ausente FALHA [nativo] c4 reservar_vaga · ferramenta ausente FALHA [nativo] c5 reservar_vaga · ferramenta ausente FALHA [nativo] c6 listar_comentarios · ferramenta ausente BATERIA: 3/10 ok saída: 1
The sem mode passes: the person books normally. In nativo, the detection does not find navigator.modelContext in Chromium 156, the page falls back, and the four tools disappear. No JavaScript error: without the battery, nobody would see it.
On a throwaway copy of the kit.
cd ~/projetos/formacao-webmcp-expert-v72/kit E=$(bash scripts/copia.sh a4c) # o erro comum: mudar o esperado para o teste passar sed -i 's/"reservas": 0/"reservas": 1/' $E/bateria/casos.json cd $E && node scripts/bateria.mjs mcp; echo "saída: $?"
The battery goes green, the regression gets caught, and a case of your own. Each exercise ends in a done when.
Run the full battery.
Done when: node scripts/bateria.mjs; echo "saída: $?" → BATERIA: 24/24 ok and saída: 0.
Run the rehearsal for the page that uses navigator.modelContext.
Done when: The block prints FALHA [nativo] contrato: 4 ferramentas com as anotações congeladas · 0 registradas, BATERIA: 3/10 ok and saída: 1.
Run the rehearsal with the changed casos.json.
Done when: The block prints BATERIA RECUSADA: casos.json ou contrato.json mudou depois de congelado. and saída: 2.
In a copy of the kit (bash scripts/copia.sh e4), add a case c7 to bateria/casos.json (e.g. buscar_oficinas with tema mcp, expecting of-302), re-freeze it with --recongelar, and run the battery on the copy.
Done when: In the copy, node scripts/bateria.mjs; echo "saída: $?" → BATERIA: 27/27 ok and saída: 0 (c7 in polyfill, nativo and mcp).
The explanation appears after the answer.
Question 1 of 4
The page uses navigator.modelContext. What does the visitor see in Chromium 156?
Question 2 of 4
What is the bateria/CONGELADA file for?
Question 3 of 4
Why does the battery run the sem mode before the others?
Question 4 of 4
The spec changed and a tool's expected annotation is now different. The right move is:
Choose an option. The explanation appears after your attempt.