AI compilation
How VisualQ converts Gherkin steps into runnable Playwright code.
Whenever you save a feature (or hit Compile in the editor), VisualQ runs the compile pipeline:
Gherkin source
│
▼
parser ─► AST (features, scenarios, steps)
│
▼
matcher ─► for each step, find a matching step definition (project → org → system)
│
▼ unresolved steps
LLM ─► Claude Sonnet (via OpenRouter) generates the Playwright body
│
▼
AST whitelist + TS typecheck
│
▼
step_definitions/ (Firestore) + dedup hash + audit logWhat the LLM sees
For every unresolved step we send the LLM:
- The literal step text + Cucumber-expression parameters detected so far.
- The DOM hint from the project (selectors candidates, captured by the
recorder or the
ElementPicker). - The list of existing step definitions in your project, so the AI matches the project's style.
- A robust Playwright template (uses
getByRole,expect,waitForLoadState).
Validation
Generated code is validated before it is persisted:
- AST whitelist — only
page.*,expect,request,console, and the injectedctx/pillarhelpers are allowed.import,require,process,eval, and arbitraryfetchcalls are rejected. - TypeScript compile — the generated body must compile against the Playwright types.
If validation fails, the step is marked as unresolved and the editor shows
the violation messages. You can edit the step text or write the body manually
(see Step library).
Cost control
LLM cost can spiral if every keystroke triggers a compile. VisualQ mitigates this with three levers:
- Hash-based cache —
hash(stepText + projectId + baseUrl)is consulted first. Repeated steps reuse the previous generation. - Debounce — the editor only calls
/api/frt/compileafter 1.5 s of inactivity. - Rate limit — 30 compiles/minute/user, 200 compiles/hour/org. See Roles, rate limits, audit log.
Every generation is recorded in the audit log with userId, featureId,
tokensUsed, and model.
Editing generated code
Admins can flip the Show generated code toggle on a step, edit the
Playwright body inline, and save. The edited step is marked
editedByUser: true, so future AI re-compiles will not overwrite it.
Hand-edited steps can be reverted to AI-generated by clearing the
editedByUser flag from the step library browser.