Your E2E tests break because of selectors, not bugs.
A vision model is the eyes. A real cursor is the hands.
CSS selectors break on refactors, not bugs. SimMan clicks what a user sees โ so tests survive markup churn and catch visual failures DOM tools are blind to.
No LLM inside the engine. A structured scenario drives Playwright deterministically; vision is used only where selectors would be. 99 tests, headless, no API key needed.
Declare your app's own ground truth per step โ a network call observed (kind: network) or an element actually enabled (kind: element_enabled). When declared, it overrides the vision judge. Hybrid verification, not vibes.
Run grounding fully offline on Apple Silicon with Qwen2.5-VL via MLX โ screenshots never leave your machine. Or use hosted Gemini with zero setup.
Scenarios are plain YAML in user language โ action / expected per step. A PM can review your test plan.
simman synthesize: describe a goal, the agent explores the page and proposes a plan โ and a human must approve it (approve / edit / reject) before any browser action runs. Agent proposes, human disposes.
# install npm i -g simman npx playwright install chromium export GEMINI_API_KEY=... # preflight, then run a scenario simman doctor simman run scenarios/example.yaml --base-url http://localhost:3100
# or: describe the goal, approve the plan, get a repeatable test simman synthesize http://localhost:3100 "compose a post and publish it" # โ agent explores the page and proposes a plan # โ gate: [a]pprove ยท [e]dit in $EDITOR ยท [r]eject (nothing runs unapproved) # โ saved scenarios/compose-post.yaml โ re-runs forever, no LLM needed
id: compose-and-post steps: - action: "Type a greeting into the message box" expected: "The message box contains the greeting" - action: "Click the Post button" expected: "A confirmation appears" truth: # your app's ground truth โ overrides the vision judge kind: network match: /api/posts method: POST