Find the break. Check the repair.
Your button changed.
Your test didn’t.
See what failed, inspect the page, and check the repair.
Try it with or without an agent.
- 01 Looks good
- 02 Something breaks
- 03 9l finds the gap
- 04 A better test
A green test. Ready to ship?
Your shop looks good and its checkout test passes. Let’s break something the customer can see.
Studio Supply
Your bag · 2 itemsField notebook
Studio mug
Order confirmed: 2 items
Profile: waiting to continue
Try the working button. A manual click does not verify the test.
Your checkout test
✓ Test passes- Cart shows two itemsChecked by the test
- Order confirms two itemsChecked by the test
- Recommendations appearNo check for this yet
The test checks the cart and the order. What about the rest of the page?
Profile test
✕ Test stoppedThe test cannot find the button it was told to click.
This one uses the button’s name. That name changed, so the old address finds nothing.
Failure reproduced · 1 test executed
9 failures tried. 3 went unnoticed.Each square is one network failure injected by 9l.
Next: compare tests/stale-locator.spec.ts.healed with your original test. Review the button-name change and unchanged check before applying the repair in your project.
Select Elements to highlight the missing or observed target. Select Changes to inspect the repair.
Locator → page element
What the failure tells us
The old name is missing. The expected button role still exists under its new name.
That points to a stale locator. The unchanged profile assertion will check whether the candidate still performs the intended action.
Simplified element view. Native healing uses observed roles and names from the failure snapshot.
The locator-only candidate · not verified yet
− name: "Continue now"+ name: "Continue to review"UNCHANGED CHECK · the profile must say “Ready for Ada”
await expect(page.getByRole('status', {name: 'Profile'}))
.toHaveText('Ready for Ada');Candidate only. A matching button is not enough; the assertion must pass.
First inspect the failure, then choose “See the proposed repair”. There is no repair to review yet.
Interactive illustration based on a recorded local 9l run. These clicks change the illustration; they don’t execute tests or call an agent. Agent explanations are illustrative.
What else can 9l help with?Same shop. More everyday testing problems.
“A renamed button broke my test.”
9l can propose a supported locator repair, keep the checks intact and run the candidate separately before you accept it.
In this demo: “Continue now” → “Continue to review”. The candidate passed; the original test stayed unchanged.
Experimental healing ·9l heal · offline candidate, no model calls“Did that bug fix actually work?”
Run the same test on the code before and after a fix. Check that it fails on the bug and passes on the repair.
In this demo: a two-item order incorrectly said “1 item”. The same check failed before the fix and passed after it.
Experimental fix confirmation ·9l confirm“Did we break anything obvious?”
Scan a page for issues such as broken links, missing form labels and console errors. Compare it with an earlier scan to find new problems.
In this demo: a broken support link and a missing promo-code label were detected. Page inspection also listed usable controls.
Page observations, not test results ·9l scan + 9l inspect“What was this test meant to cover?”
Compare a test with a separate list of requirements. Save its source and declared author so you can trace what was assessed and executed.
In this demo: assessment flagged the missing recommendation check. Fault testing then demonstrated the gap.
Advisory assessment + source provenance ·9l assess + 9l provenance“Can an agent fill in the steps?”
Bounded goals can operate observed controls. Your explicit checks still decide whether the result is correct.
In this demo: a scripted goal filled a name and continued. A broken profile still failed the test. A separate purchase goal was blocked before ordering.
Experimental SDK goals · this demo uses a fixed offline script, not a live AI model. Goal completion is unverified.“Can I keep my tools?”
Keep ordinary Playwright tests, or add named steps with the optional SDK. An agent can call 9l tools through MCP and inspect execution receipts.
In this demo: both test styles ran. Through MCP, a support-link test was generated, reviewed and executed: failure on a broken link, pass after repair.
Playwright + SDK + MCP · receipts record which tests actually ranFor developers: the check, recorded results and how to run it
Locator repair: what actually ran
The recorded 9l heal tests/stale-locator.spec.ts --provider none run reproduced one failing test. Offline Tier 1 changed only the button-name literal from “Continue now” to “Continue to review”. The isolated candidate executed one test and passed the unchanged “Ready for Ada” assertion. The candidate was saved separately; the original was not applied or edited. There were zero provider calls.
“Agent + 9l” illustrates an agent reviewing the same evidence and requesting verification. It is not a recorded model response or a live Tier 2 run. If offline healing cannot find a supported repair, it returns unverified; an explicitly configured provider can propose a bounded candidate, which must still pass verification. An ambiguous target or a broken business outcome must not be hidden by weakening the assertion.
Missing check: fault testing
The second story illustrates experimental 9l prove. It runs the test with controlled network failures, then reports which failures caused assertions to fail. A failure that goes unnoticed is a reason to inspect your checks; it isn’t automatically an application bug.
The added check
The stronger test explicitly requires the pencil set recommendation. This is a human-readable demo requirement; 9l doesn’t add this assertion automatically.
await expect(
page.getByRole('complementary', {name: 'Recommended'})
).toContainText('Pencil set');
What actually ran
Recorded on 13 October 2026 with local Chromium on macOS/ARM64. Three faults—connection aborted, HTTP 500, and empty JSON—were tried against each of the cart, order and recommendation requests.
| Test | Healthy page | Caught | Missed |
|---|---|---|---|
| Original | Pass | 6 of 9 | 3 of 9 |
| With recommendation check | Pass | 9 of 9 | 0 of 9 |
Both runs completed. The runner checked all 20 execution receipts: two healthy baselines and 18 fault runs. All three missed failures affected recommendations. These synthetic results establish detection of these nine faults, not complete application coverage or a production benchmark.
This page is a curated snapshot of the checked run release-lab-rhRQbm, using a local build based on d0c743f67d62 plus the demo files. It does not contain the raw receipts. Regenerate the full report below to inspect evidence from your own run. This offline snapshot does not measure live model quality. Tab 04 adds a separate real Codex recording. Verified replay and native mobile are not demonstrated here.
Run the real example
With Node 24 and Go 1.25.13 or newer, run these commands in a checkout of the 9lives repository. No account or model key is needed. The initial install needs internet access.
npm ci npm exec playwright install chromium npm run demo:lab
On Linux, install the browser with npm exec playwright install --with-deps chromium. The walkthrough takes a few minutes and prints the path to an HTML report with commands, results and receipts for all eight experiments.
To share this illustration, send this single HTML file or host it as a static page. It works offline, has no external assets and sends no requests until you follow an external link.
The agent coordinates the work.
“Repair this test. Keep the check for Ready for Ada.”
Explore the page
Observe controls, try actions, collect browser feedback.
Optional exploration · its own browser sessionCheck the test and repair
Run the spec, restrict the edit, verify a separate copy, return evidence.
Uses your project’s tests and Playwright configuration9l backs the agent’s test verdict. It does not intercept Playwright MCP calls or automatically share that browser session. MCP is the connection through which the agent requests a tool.
- Input
- Rule / action
- Output
Tool call / observable evidence Illustrative
The algorithm, one decision at a time
This is a simplified control flow showing tool actions and decision rules. Each step is inspectable; the agent’s private reasoning is not part of the evidence.
agent: keep the user’s expected outcome and original assertion
agent: optionally explore with Playwright MCP
agent → 9l: run_test(spec) to reproduce the failure
agent → 9l: heal_test(spec, apply: false)
inside 9l healing:
run the original spec again in the project
if already passing with tests executed → return passed
if zero tests → return unverified
if an assertion failed → return needs_human
if unsupported failure → return unverified
try one supported offline locator proposal
if needed and available → bounded provider proposals
for each admitted proposal:
allow only the failed action’s supported locator literal to change
preserve assertions, imports, other actions and control flow
execute an isolated copy with fresh evidence
if an assertion fails → return needs_human
if evidence is incomplete → never accept as verified
if passed and executed count matches original → verified
if no verified candidate → return unverified
on verified result:
apply: false → save a .healed file for review
apply: true → recheck original source hash before writing
report savedPath / applied only if the write succeeded
The outer agent chooses which tools to call. The optional healing provider is a separate role: it proposes a candidate when offline healing cannot finish. 9l still checks every admitted candidate. This walkthrough’s successful repair needs no provider call.
A receipt records execution and completeness; it does not prove that a test covers every requirement. Assessment is advisory. SDK goal completion is unverified until explicit checks establish the expected result. Verified replay and native mobile are not demonstrated here.
Contracts: 9l MCP tools · Healing rules · Playwright MCP
This tab is a teaching simulation grounded in the tool contracts. It runs no browser tools, model calls or test assertions. The renamed-button outcome follows the recorded offline repair in tab 01; the other branches illustrate rejection rules.
Recorded execution · 13 October 2026. Real Codex decisions, a real Chromium browser, and the local demo shop. Switch between the working app and the same app with an intentional profile defect.
- Tests executed
- Real model decisions
- Run duration
- 9l receipt
- Validated
Codex returned completed in both runs. The explicit Playwright assertion decided whether the expected profile appeared.
Highlights select the key recorded events; the full trace retains every captured record. Grouped by source. Console and MCP timestamps are UTC; execution records use their original sequence numbers. Codex rows are receipt fields. MCP is a separate recorded session. Browser messages come from demo instrumentation; only allowlisted fields are shown.
What Codex asked the browser to do
9l requested bounded, typed decisions from the authenticated Codex CLI (0.159.3; configured model: gpt-6.1-sol). Its SDK worker executed the browser actions. This recording uses Playwright through the SDK; it does not use Playwright MCP.
Also executed through 9l MCP
Inspected the shop → reproduced the stale locator → verified a separate repaired copy.
- name: "Continue now" + name: "Continue to review"
1 test failed before repair. 1 test passed after. The original assertion was preserved. The original file was unchanged; the verified copy was saved with a .healed suffix.
Actual JSON-RPC tool calls orchestrated by this coding agent. This supported repair used 9l’s offline proposal: 0 healing model calls.
Inspect this run’s evidence and limits
Both runs used identical test source and matched its recorded provenance. The defect was enabled with LAB_PROFILE_BUG=1. Each run allowed one attempt, at most three actions and five decisions. One form submission was captured in each run.
The receipt’s structured output hash was checked against the saved file. Its events match the run, job and attempt IDs. Console capture is a separate demo artifact; it is not 9l’s structured execution stream. The SDK reports assertionCoverage: "unknown" and verifiedAssertions: 0: this example does not claim an assertion census or full coverage. The test’s explicit check and negative control establish this profile behavior.
The goal and the check
const result = await n9l.goal(
'Enter the customer name using the name parameter, click Continue to review once, then complete. The test will independently check the resulting profile.',
{ params: { name: 'Ada' }, maxActions: 3, maxDecisions: 5 }
);
expect(result.verified).toBe(false);
await expect(page.getByRole('status', { name: 'Profile' }))
.toHaveText('Ready for Ada');
The first attempt was incomplete
The shell initially selected Codex 0.144.5, which rejected the configured model. 9l returned incomplete / provider_error. Selecting Conductor’s working 0.159.3 binary for this process resolved it. No global settings changed. That unsuccessful attempt is retained in the local evidence and summarized in the download.
This standalone page embeds selected fields and recorded console events. Full receipts, structured streams, the test, screenshots and rerun scripts are retained in the workspace under .context/live-codex/. These are two executions of a synthetic shop, not a production benchmark. Clicking the page does not run a model or a test.
A recorded live run, displayed offline. Goal completion alone stays unverified. The passing and deliberately failing test results are shown separately from the teaching simulations in the other tabs.
Recorded experiment · 13 October 2026 UTC. A deliberately seeded app bug, a real Codex edit, and seven Chromium test executions. Explore the saved results below.
Same test. Before and after.A valid name. The app rejects it.
The test expects Ready for Ada. Its assertion fails on the broken app.
Application change · app/profile.cjs
− ready: normalized.length > 3+ ready: normalized.length > 0
Accept a non-empty name after trimming spaces. The original regression test stays unchanged.
Codex authored this edit in the editing session. 9l executes the verification; it did not generate the patch.
9l verdict:
Identical test bytes. Separate app checkouts. One test executed on each revision.
Actual MCP call: confirm_finding. The app starts from each checkout, so this comparison really exercises the changed code.
| Injected fault | Result |
|---|
Caught = the test failed on an assertion when 9l broke the response. This checks sensitivity to these faults; it does not establish full coverage or correct error handling. HTTP 401 is synthetic, not a real login flow.
Execution rows retain their original sequence numbers. Patch rows show source-control evidence. Only allowlisted fields are displayed; run IDs and timestamps are in the downloadable extract.
Inspect the unchanged test, patch, and receipts
The same regression test ran on both revisions
The actual application diff
Recorded commands
9l run tests/profile.spec.ts --sdk MCP → confirm_finding(spec, unfixed, fixed) 9l prove tests/profile.spec.ts --faults http-500,http-401,malformed-json
Execution used bounded timeouts and no retries. The seven receipts cover the initial failure, both revision checks, the proof baseline, and three fault runs. Their structured-output hashes and run identities were checked before embedding.
Source and rerun scripts are retained in .context/prove-fix/. The requirement is this demo’s explicit fixture contract, not a production product requirement. SDK assertion coverage remains unknown; this page shows recorded assertion events and the before/after result.
Experimental confirm and prove, qualified here on one synthetic local app in Chromium. Clicking this walkthrough displays recorded results; it does not call Codex or execute tests.