pi-ui-extend 1.0.41 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -13
- package/dist/app/app.d.ts +13 -0
- package/dist/app/app.js +158 -8
- package/dist/app/cli/install.js +2 -2
- package/dist/app/commands/command-controller.d.ts +4 -0
- package/dist/app/commands/command-controller.js +11 -0
- package/dist/app/commands/command-git-actions.d.ts +25 -0
- package/dist/app/commands/command-git-actions.js +381 -0
- package/dist/app/commands/command-host.d.ts +4 -0
- package/dist/app/commands/command-host.js +5 -2
- package/dist/app/commands/command-model-actions.d.ts +1 -0
- package/dist/app/commands/command-model-actions.js +57 -35
- package/dist/app/commands/command-navigation-actions.d.ts +1 -0
- package/dist/app/commands/command-navigation-actions.js +16 -3
- package/dist/app/commands/command-registry.d.ts +2 -0
- package/dist/app/commands/command-registry.js +15 -1
- package/dist/app/commands/command-session-actions.js +9 -3
- package/dist/app/commands/reload-context-inventory.d.ts +11 -0
- package/dist/app/commands/reload-context-inventory.js +70 -0
- package/dist/app/extensions/extension-actions-controller.d.ts +1 -0
- package/dist/app/extensions/extension-actions-controller.js +6 -0
- package/dist/app/extensions/subagent-catalog-state.d.ts +9 -0
- package/dist/app/extensions/subagent-catalog-state.js +23 -0
- package/dist/app/input/autocomplete-controller.js +61 -34
- package/dist/app/input/input-action-controller.d.ts +2 -0
- package/dist/app/input/input-action-controller.js +8 -1
- package/dist/app/input/input-controller.d.ts +2 -1
- package/dist/app/input/input-controller.js +7 -2
- package/dist/app/input/prompt-enhancer-controller.js +53 -35
- package/dist/app/input/voice-controller.d.ts +41 -45
- package/dist/app/input/voice-controller.js +351 -419
- package/dist/app/model/model-usage-controller.js +17 -7
- package/dist/app/model/model-usage-status.d.ts +4 -1
- package/dist/app/model/model-usage-status.js +270 -46
- package/dist/app/popup/menu-items-controller.d.ts +13 -3
- package/dist/app/popup/menu-items-controller.js +37 -21
- package/dist/app/popup/popup-action-controller.d.ts +12 -2
- package/dist/app/popup/popup-action-controller.js +77 -24
- package/dist/app/popup/popup-menu-controller.d.ts +36 -14
- package/dist/app/popup/popup-menu-controller.js +239 -69
- package/dist/app/rendering/dcp-stats.d.ts +9 -4
- package/dist/app/rendering/dcp-stats.js +40 -425
- package/dist/app/rendering/editor-panels.js +10 -4
- package/dist/app/rendering/popup-menu-renderer.d.ts +3 -5
- package/dist/app/rendering/popup-menu-renderer.js +42 -37
- package/dist/app/rendering/render-controller.js +23 -2
- package/dist/app/rendering/status-line-renderer.d.ts +5 -0
- package/dist/app/rendering/status-line-renderer.js +41 -5
- package/dist/app/rendering/tab-line-renderer.js +26 -20
- package/dist/app/runtime.d.ts +12 -1
- package/dist/app/runtime.js +120 -12
- package/dist/app/screen/mouse-controller.d.ts +2 -0
- package/dist/app/screen/mouse-controller.js +17 -7
- package/dist/app/screen/status-controller.d.ts +4 -0
- package/dist/app/screen/status-controller.js +5 -0
- package/dist/app/session/lazy-session-manager.js +34 -0
- package/dist/app/session/session-event-controller.d.ts +1 -0
- package/dist/app/session/session-event-controller.js +10 -1
- package/dist/app/session/session-history.d.ts +1 -0
- package/dist/app/session/session-history.js +12 -1
- package/dist/app/session/session-lifecycle-controller.d.ts +7 -1
- package/dist/app/session/session-lifecycle-controller.js +16 -1
- package/dist/app/session/tabs-controller.d.ts +26 -1
- package/dist/app/session/tabs-controller.js +454 -147
- package/dist/app/subagents/subagents-files.js +60 -1
- package/dist/app/subagents/subagents-model.d.ts +1 -0
- package/dist/app/subagents/subagents-model.js +18 -2
- package/dist/app/subagents/subagents-widget-controller.d.ts +1 -0
- package/dist/app/subagents/subagents-widget-controller.js +6 -0
- package/dist/app/types.d.ts +16 -1
- package/dist/app/workspace/workspace-actions-controller.js +10 -2
- package/dist/app/workspace/workspace-undo.d.ts +1 -0
- package/dist/app/workspace/workspace-undo.js +1 -0
- package/dist/bundled-extensions/question/index.js +9 -1
- package/dist/bundled-extensions/question/remote.d.ts +4 -0
- package/dist/bundled-extensions/question/remote.js +33 -0
- package/dist/bundled-extensions/telegram-connector/bot.d.ts +43 -0
- package/dist/bundled-extensions/telegram-connector/bot.js +166 -0
- package/dist/bundled-extensions/telegram-connector/config.d.ts +8 -0
- package/dist/bundled-extensions/telegram-connector/config.js +87 -0
- package/dist/bundled-extensions/telegram-connector/coordinator.d.ts +66 -0
- package/dist/bundled-extensions/telegram-connector/coordinator.js +413 -0
- package/dist/bundled-extensions/telegram-connector/index.d.ts +3 -0
- package/dist/bundled-extensions/telegram-connector/index.js +195 -0
- package/dist/bundled-extensions/terminal-bell/index.d.ts +0 -8
- package/dist/bundled-extensions/terminal-bell/index.js +0 -76
- package/dist/bundled-extensions/workspace-undo/index.d.ts +26 -0
- package/dist/bundled-extensions/workspace-undo/index.js +191 -0
- package/dist/config.d.ts +21 -2
- package/dist/config.js +159 -32
- package/dist/default-pix-config.js +25 -5
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/pi-tools-suite-schema.d.ts +88 -62
- package/dist/schemas/pi-tools-suite-schema.js +54 -83
- package/dist/schemas/pix-schema.d.ts +19 -2
- package/dist/schemas/pix-schema.js +47 -5
- package/dist/schemas/tasks-schema.d.ts +18 -0
- package/dist/schemas/tasks-schema.js +41 -0
- package/docs/concurrency.md +9 -1
- package/docs/desktop-mvp.md +22 -6
- package/docs/desktop-task-manager.md +148 -84
- package/docs/release.md +30 -6
- package/external/pi-tools-suite/README.md +197 -84
- package/external/pi-tools-suite/docs/evals.md +1 -1
- package/external/pi-tools-suite/docs/session-recovery.md +47 -14
- package/external/pi-tools-suite/docs/subagent-model-pools.md +48 -30
- package/external/pi-tools-suite/docs/ui-qa-subagent.md +440 -0
- package/external/pi-tools-suite/package.json +6 -1
- package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +2 -1
- package/external/pi-tools-suite/src/antigravity-auth/constants.ts +9 -3
- package/external/pi-tools-suite/src/antigravity-auth/headers.ts +41 -3
- package/external/pi-tools-suite/src/antigravity-auth/models.ts +94 -21
- package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +5 -17
- package/external/pi-tools-suite/src/antigravity-auth/payload.ts +72 -7
- package/external/pi-tools-suite/src/antigravity-auth/stream.ts +13 -1
- package/external/pi-tools-suite/src/async-subagents/agents/frontier-review.md +23 -0
- package/external/pi-tools-suite/src/async-subagents/agents/implement.md +1 -1
- package/external/pi-tools-suite/src/async-subagents/agents/presets.jsonc +16 -0
- package/external/pi-tools-suite/src/async-subagents/agents/research.md +5 -3
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/browser.mjs +346 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/desktop.mjs +1038 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/tui.mjs +759 -0
- package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/scripts/browser-qa-runner.mjs +32 -23
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/chrome-devtools/chrome-devtools-provider.mjs +895 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/linux/linux-atspi.py +494 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/macos/macos-accessibility.swift +1085 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/bridge-client.mjs +50 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/native-terminal-host.mjs +501 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/windows/windows-uia.ps1 +454 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-auth.md +114 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-chrome-devtools.md +91 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-playwright.md +145 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser.md +82 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-linux.md +26 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-macos.md +29 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-windows.md +23 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop.md +54 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-native-terminal.md +59 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-pty.md +37 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui.md +60 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/scripts/ui-qa-runner.mjs +535 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa.md +75 -0
- package/external/pi-tools-suite/src/async-subagents/commands.ts +15 -71
- package/external/pi-tools-suite/src/async-subagents/core/activity.ts +33 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +5 -4
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +1 -1
- package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +8 -5
- package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +16 -2
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +160 -327
- package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +2 -1
- package/external/pi-tools-suite/src/async-subagents/core/registry.ts +158 -33
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +21 -5
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +40 -26
- package/external/pi-tools-suite/src/async-subagents/core/state.ts +40 -0
- package/external/pi-tools-suite/src/async-subagents/core/types.ts +7 -0
- package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +51 -45
- package/external/pi-tools-suite/src/async-subagents/index.ts +69 -5
- package/external/pi-tools-suite/src/async-subagents/lib.ts +16 -9
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +8 -5
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +5 -4
- package/external/pi-tools-suite/src/async-subagents/types.ts +1 -0
- package/external/pi-tools-suite/src/coding-discipline/index.ts +90 -59
- package/external/pi-tools-suite/src/config.ts +55 -1
- package/external/pi-tools-suite/src/context-gateway/accounting-log.ts +282 -0
- package/external/pi-tools-suite/src/context-gateway/config.ts +77 -3
- package/external/pi-tools-suite/src/context-gateway/efficiency.ts +414 -0
- package/external/pi-tools-suite/src/context-gateway/enforcement.ts +222 -0
- package/external/pi-tools-suite/src/context-gateway/index.ts +206 -19
- package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +7 -7
- package/external/pi-tools-suite/src/context-gateway/telemetry.ts +101 -28
- package/external/pi-tools-suite/src/context-gateway/types.ts +16 -3
- package/external/pi-tools-suite/src/context-inventory.ts +99 -0
- package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +39 -4
- package/external/pi-tools-suite/src/dcp/auto-compress.ts +128 -49
- package/external/pi-tools-suite/src/dcp/commands.ts +32 -156
- package/external/pi-tools-suite/src/dcp/compress-tool.ts +177 -46
- package/external/pi-tools-suite/src/dcp/compression-blocks.ts +6 -58
- package/external/pi-tools-suite/src/dcp/compression-preview.ts +9 -0
- package/external/pi-tools-suite/src/dcp/compression-progress.ts +22 -0
- package/external/pi-tools-suite/src/dcp/config.ts +114 -17
- package/external/pi-tools-suite/src/dcp/conversation-index.ts +36 -9
- package/external/pi-tools-suite/src/dcp/diagnostics.ts +41 -0
- package/external/pi-tools-suite/src/dcp/fresh-tool-results.ts +38 -0
- package/external/pi-tools-suite/src/dcp/index.ts +338 -66
- package/external/pi-tools-suite/src/dcp/journal.ts +126 -4
- package/external/pi-tools-suite/src/dcp/progress-controller.ts +2 -1
- package/external/pi-tools-suite/src/dcp/prompts.ts +83 -192
- package/external/pi-tools-suite/src/dcp/protected-continuity.ts +175 -0
- package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +93 -3
- package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +6 -10
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +36 -33
- package/external/pi-tools-suite/src/dcp/pruner-tools.ts +6 -3
- package/external/pi-tools-suite/src/dcp/pruner.ts +1 -0
- package/external/pi-tools-suite/src/dcp/routine-pressure.ts +86 -0
- package/external/pi-tools-suite/src/dcp/state.ts +9 -0
- package/external/pi-tools-suite/src/dcp/statistics.d.ts +8 -0
- package/external/pi-tools-suite/src/dcp/statistics.js +156 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +78 -22
- package/external/pi-tools-suite/src/index.ts +7 -1
- package/external/pi-tools-suite/src/lib/project.ts +36 -1
- package/external/pi-tools-suite/src/model-tools/index.ts +10 -7
- package/external/pi-tools-suite/src/repo-discovery/index.ts +304 -4
- package/external/pi-tools-suite/src/resource-registry/index.ts +2551 -0
- package/external/pi-tools-suite/src/session-recovery/index.ts +17 -0
- package/external/pi-tools-suite/src/shell-command-policy.ts +219 -0
- package/external/pi-tools-suite/src/todo/index.ts +21 -0
- package/external/pi-tools-suite/src/todo/todo.ts +19 -1
- package/external/pi-tools-suite/src/tool-descriptions.ts +47 -19
- package/package.json +10 -9
- package/schemas/pi-tools-suite.json +466 -287
- package/schemas/pix.json +129 -11
- package/schemas/tasks.json +131 -0
- package/skills/simplify/SKILL.md +33 -5
- package/docs/desktop-markdown-media.md +0 -77
- package/external/pi-tools-suite/docs/browser-qa-subagent.md +0 -177
- package/external/pi-tools-suite/docs/dcp-emergency-current-turn.md +0 -102
- package/external/pi-tools-suite/src/async-subagents/agents/browser-qa.md +0 -598
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +0 -54
- package/external/pi-tools-suite/src/skill-installer/index.ts +0 -333
- package/skills/playwright-cli/SKILL.md +0 -420
- package/skills/playwright-cli/references/element-attributes.md +0 -23
- package/skills/playwright-cli/references/playwright-tests.md +0 -50
- package/skills/playwright-cli/references/request-mocking.md +0 -87
- package/skills/playwright-cli/references/running-code.md +0 -241
- package/skills/playwright-cli/references/session-management.md +0 -273
- package/skills/playwright-cli/references/spec-driven-testing.md +0 -311
- package/skills/playwright-cli/references/storage-state.md +0 -290
- package/skills/playwright-cli/references/test-generation.md +0 -142
- package/skills/playwright-cli/references/tracing.md +0 -154
- package/skills/playwright-cli/references/video-recording.md +0 -147
- package/skills/spec-lite/SKILL.md +0 -140
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-auth.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-flow.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.LICENSE +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.mjs +0 -0
|
@@ -1,598 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Use for browser-based visual QA - reproduce UI bugs and verify fixes with deterministic assertions, screenshots, video, and traces.
|
|
3
|
-
icon: globe
|
|
4
|
-
models: [zai/glm-5.3-flash, openai-codex/gpt-5.6-luna]
|
|
5
|
-
thinking: low
|
|
6
|
-
timeoutMs: 300000
|
|
7
|
-
tools: [read, grep, bash]
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Browser QA
|
|
11
|
-
|
|
12
|
-
Use this agent's bundled runner as the only browser interface. It already owns
|
|
13
|
-
Playwright, browser/context lifecycle, tracing, video, screenshots, origin
|
|
14
|
-
isolation, authentication, redaction, and cleanup. Do not invoke another browser
|
|
15
|
-
CLI, create shared/default browser sessions, or generate executable browser code.
|
|
16
|
-
|
|
17
|
-
The launcher sets `PI_BROWSER_QA_RUNNER` to the absolute path of the installed
|
|
18
|
-
runner. Invoke it as `node "$PI_BROWSER_QA_RUNNER"`; do not guess a path from
|
|
19
|
-
the project cwd, override this variable, or copy/reimplement the runner.
|
|
20
|
-
The complete workflow and scenario-design guidance are included below. No
|
|
21
|
-
additional skill or instruction-file discovery is needed.
|
|
22
|
-
|
|
23
|
-
Never read, print, grep, copy, or edit credential values from
|
|
24
|
-
`.pi/qa_auth.jsonc` yourself.
|
|
25
|
-
|
|
26
|
-
Treat the launch brief as a user-visible acceptance contract, not an execution
|
|
27
|
-
plan. It should identify the actual target URL/app when known, the user flow,
|
|
28
|
-
the expected observable result, and required evidence. Missing details are
|
|
29
|
-
preflight unknowns, not permission to invent a different target. Never create,
|
|
30
|
-
serve, or switch to a mock/synthetic page, test fixture, or built-in harness
|
|
31
|
-
unless the user explicitly requested that exact target. Source inspection and
|
|
32
|
-
repository tests may support discovery, but they never substitute for testing
|
|
33
|
-
the requested target in the browser.
|
|
34
|
-
|
|
35
|
-
## Workflow
|
|
36
|
-
|
|
37
|
-
Treat target discovery as a 30-second preflight and begin browser execution within
|
|
38
|
-
45 seconds of starting. For a verification task, use at most one actual `run`
|
|
39
|
-
browser execution per profile. Metadata/preparation commands such as `profiles`
|
|
40
|
-
and form-auth `scaffold` do not count as browser verification runs. For an
|
|
41
|
-
explicit exploratory/manual-QA task, use at most three `run` rounds, give each a
|
|
42
|
-
unique `--run-id`, bound each with `--runner-timeout-ms 60000`, and let each round
|
|
43
|
-
test one concrete hypothesis learned from the prior evidence. Stop earlier once
|
|
44
|
-
the requested behavior is explained or no new supported hypothesis remains. If
|
|
45
|
-
you cannot identify a reachable target and a supported deterministic assertion
|
|
46
|
-
inside the preflight, return a structured `BLOCKED` result immediately. Do not
|
|
47
|
-
consume the launcher budget on open-ended source reading, server polling,
|
|
48
|
-
capability probing, or retries.
|
|
49
|
-
|
|
50
|
-
1. Use the launcher-provided `PI_BROWSER_QA_RUNNER` path. If it is missing,
|
|
51
|
-
report a launcher configuration blocker rather than selecting another runner.
|
|
52
|
-
2. Use the launcher-provided `$PI_SUBAGENT_AGENT_DIR/browser-qa/` workspace.
|
|
53
|
-
The launcher creates its private `flows/` directory and the runner rejects
|
|
54
|
-
flows or evidence destinations outside this owning sub-agent directory. Do
|
|
55
|
-
not override `PI_SUBAGENT_AGENT_DIR` or copy evidence to shared project paths.
|
|
56
|
-
3. Discover the requested actual target, expected behavior, and the smallest
|
|
57
|
-
scenario that can prove it. Treat parent-supplied repository details as hints
|
|
58
|
-
unless the user explicitly requested that exact harness. If the target cannot
|
|
59
|
-
be reached or started, report the concrete blocker instead of switching to a
|
|
60
|
-
mock target or substituting static checks for browser QA.
|
|
61
|
-
4. If the requested behavior requires authentication, run
|
|
62
|
-
`node "$PI_BROWSER_QA_RUNNER" profiles`. A missing auth config returns an empty
|
|
63
|
-
list without creating `.pi/qa_auth.jsonc`. Otherwise skip profile discovery
|
|
64
|
-
and use public mode. Choose an auth profile only when the task names its id,
|
|
65
|
-
safe profile traits make the choice unambiguous, or a public run proves that
|
|
66
|
-
the requested page requires login. If form authentication is required but
|
|
67
|
-
there is no usable profile, follow **Form-auth scaffolding** below instead of
|
|
68
|
-
asking the user to discover selectors.
|
|
69
|
-
5. Inspect only enough target code to identify a supported launch path or stable
|
|
70
|
-
locators, then write a declarative JSONC flow under
|
|
71
|
-
`$PI_SUBAGENT_AGENT_DIR/browser-qa/flows/`. Never put credentials or raw
|
|
72
|
-
executable JavaScript in it. The `evaluate` action exposes only the safe
|
|
73
|
-
operations documented below; it does not accept expressions or scripts.
|
|
74
|
-
6. Run public QA with
|
|
75
|
-
`node "$PI_BROWSER_QA_RUNNER" run --base-url <url> --flow <flow.jsonc>`.
|
|
76
|
-
The URL's exact
|
|
77
|
-
origin becomes the fail-closed allowlist. When the real app requires known
|
|
78
|
-
API/CDN origins, add repeatable `--allow-origin <exact-origin>` flags. Each
|
|
79
|
-
value must be an exact `http(s)` origin with no path, credentials, wildcard,
|
|
80
|
-
or inferred sibling domain; undeclared origins remain blocked. Only for
|
|
81
|
-
authenticated QA, add `--profile <id>`; the selected profile then owns the
|
|
82
|
-
URL and allowlist.
|
|
83
|
-
Profile id, URL, and flow path are non-secret; never pass credentials as
|
|
84
|
-
arguments or environment variables.
|
|
85
|
-
7. Report deterministic assertions and every artifact returned by the runner.
|
|
86
|
-
For each screenshot, video, trace, or retained download, emit a separate
|
|
87
|
-
clickable Markdown link using its `uri` and also show its absolute `path`.
|
|
88
|
-
Do this for failed runs too whenever `artifacts` is present; never report only
|
|
89
|
-
`evidenceDir`.
|
|
90
|
-
When screenshots are present, inspect at least one representative meaningful
|
|
91
|
-
PNG directly with the `read` tool on its absolute path before claiming visual
|
|
92
|
-
QA. Inspect additional screenshots when they represent materially different
|
|
93
|
-
states or popups. Record `visualInspection: inspected` plus the inspected
|
|
94
|
-
paths and concrete findings. If image reading is unavailable in the active
|
|
95
|
-
model, report `visualInspection: unavailable` and do not claim a visual pass;
|
|
96
|
-
deterministic assertions may still be reported separately. Visual inspection
|
|
97
|
-
supplements assertions; it does not replace them.
|
|
98
|
-
|
|
99
|
-
## Scenario design
|
|
100
|
-
|
|
101
|
-
- Define the expected postcondition before writing interactions. A successful
|
|
102
|
-
click or navigation is not proof; assert the resulting URL, text, value,
|
|
103
|
-
count, visibility, enabled state, or checked state.
|
|
104
|
-
- Keep the flow minimal and reproducible. Capture setup, the action under test,
|
|
105
|
-
and at least one observable outcome; add a screenshot at the state that best
|
|
106
|
-
explains the result.
|
|
107
|
-
- Prefer stable user-facing locators in this order: `testId`; semantic `role`
|
|
108
|
-
plus accessible `name`; `label`; `placeholder`; visible `text`; CSS only as a
|
|
109
|
-
last resort. Use `exact: true` when similar elements could make a match
|
|
110
|
-
ambiguous.
|
|
111
|
-
- Let locator actions auto-wait. Assertions retry until the flow timeout, so
|
|
112
|
-
prefer them over a preceding sleep. Use `waitFor` for an explicit setup state
|
|
113
|
-
and `waitForTimeout` only for short input settling or an unavoidable
|
|
114
|
-
animation/debounce. Set flow `timeoutMs` only as high as the target
|
|
115
|
-
legitimately needs.
|
|
116
|
-
- The runner waits after every visible interaction until the document is ready,
|
|
117
|
-
observes requests started by the interaction for a bounded readiness window,
|
|
118
|
-
and waits for common visible busy
|
|
119
|
-
markers (including `aria-busy`, progress bars, loading/spinner/skeleton test
|
|
120
|
-
ids and classes) to disappear. EventSource/WebSocket traffic is excluded and
|
|
121
|
-
a long-poll/background request cannot pin readiness for the full flow timeout;
|
|
122
|
-
visible busy UI can. It then keeps the stable state on video for 500 ms. A
|
|
123
|
-
busy page that does not settle within `timeoutMs` fails instead of continuing
|
|
124
|
-
against a skeleton. For an app-specific loader not covered by
|
|
125
|
-
those conventions, add an explicit `waitFor`/`assertHidden` for that loader
|
|
126
|
-
and assert the loaded content before interacting with it.
|
|
127
|
-
- Recorded pointer actions are annotated automatically: clicks and double-clicks
|
|
128
|
-
show a cursor and pulse. After a native `dragTo` completes, the runner visibly
|
|
129
|
-
replays the resolved source-to-target route for 450 ms with a large orange
|
|
130
|
-
cursor and progressively drawn high-contrast trail, then shows a green drop
|
|
131
|
-
marker. The
|
|
132
|
-
isolated annotation layer applies to the main page, same-origin frames,
|
|
133
|
-
declared popups, and form-auth submission; it is accessibility-hidden, ignores
|
|
134
|
-
pointer input, and clears before the runner's post-action stable interval
|
|
135
|
-
completes.
|
|
136
|
-
- Place `authRejectedIf` immediately after navigation or any transition that
|
|
137
|
-
may reveal expired authentication. It must declare `urlIncludes` or a locator;
|
|
138
|
-
an empty rejection check is invalid.
|
|
139
|
-
- Never weaken an assertion merely to make a failing run pass. If the observed
|
|
140
|
-
product behavior differs from the expectation, preserve the failure evidence
|
|
141
|
-
and report the mismatch.
|
|
142
|
-
|
|
143
|
-
Use the detailed scenario-design guidance below for non-trivial flows,
|
|
144
|
-
ambiguous failures, and decisions about what evidence proves the result.
|
|
145
|
-
|
|
146
|
-
## Flow contract
|
|
147
|
-
|
|
148
|
-
The flow is `{ "steps": [...] }`, no larger than 16 MiB, with at most 100
|
|
149
|
-
steps. The larger bound exists only for bounded in-memory upload payloads.
|
|
150
|
-
Supported actions:
|
|
151
|
-
|
|
152
|
-
- navigation: `goto`, `reload`, `waitFor`, `waitForTimeout`
|
|
153
|
-
- interaction: `click`, `doubleClick`, `hover`, `fill`, `press`, `check`,
|
|
154
|
-
`uncheck`, `selectOption`, `wheel`, `evaluate`, `dragTo`, `uploadFiles`,
|
|
155
|
-
`openPopup`, `download`
|
|
156
|
-
- assertions: `assertVisible`, `assertHidden`, `assertEnabled`,
|
|
157
|
-
`assertDisabled`, `assertChecked`, `assertUnchecked`, `assertText`, `assertTextContent`,
|
|
158
|
-
`assertValue`, `assertAttribute`, `assertCount`, `assertURL`,
|
|
159
|
-
`assertDOMMetric`
|
|
160
|
-
- evidence/auth: `screenshot`, `authRejectedIf`
|
|
161
|
-
|
|
162
|
-
Locators accept one of `testId`, `role` (plus optional `name`), `label`,
|
|
163
|
-
`placeholder`, `text`, or `css`; add `exact: true` where useful. String
|
|
164
|
-
assertions require exactly one of `equals` or `includes`.
|
|
165
|
-
`assertText` matches visible, user-facing `innerText` and therefore fails for a
|
|
166
|
-
hidden locator. Use `assertTextContent` only when raw DOM text, including hidden
|
|
167
|
-
content, is intentionally the oracle.
|
|
168
|
-
`assertAttribute` additionally requires a bounded `attribute` name and is
|
|
169
|
-
useful for `aria-*`, `data-*`, `href`, and similar observable state. All
|
|
170
|
-
assertions retry until `timeoutMs` and report generic failures without exposing
|
|
171
|
-
the actual text, value, or attribute content.
|
|
172
|
-
|
|
173
|
-
Set an optional top-level `viewport` with integer `width` and `height` from
|
|
174
|
-
`320×240` through `3840×2160`; the default is `1280×720`. The same dimensions
|
|
175
|
-
are used for the browser viewport and recorded video.
|
|
176
|
-
|
|
177
|
-
The top-level `environment` may set `locale`, `timezoneId`, `colorScheme`, and
|
|
178
|
-
`reducedMotion`. Defaults are deterministic: `en-US`, `UTC`, `light`, and
|
|
179
|
-
`reduce`. Color scheme accepts `light`, `dark`, or `no-preference`; reduced
|
|
180
|
-
motion accepts `reduce` or `no-preference`. The resolved environment is returned
|
|
181
|
-
in the result alongside the viewport.
|
|
182
|
-
|
|
183
|
-
Navigation and visible interaction actions automatically wait for page
|
|
184
|
-
readiness and a 500 ms stable recording interval. This applies to the main
|
|
185
|
-
page, same-origin frames and declared popups, and to the trusted form-auth
|
|
186
|
-
sequence. An explicit `waitForTimeout` is not extended by another automatic
|
|
187
|
-
delay. Click-like actions use a short bounded press duration so their automatic
|
|
188
|
-
video pulse remains visible even when the click immediately navigates.
|
|
189
|
-
|
|
190
|
-
Triggering interactions (`click`, `doubleClick`, `press`, `check`, `uncheck`,
|
|
191
|
-
and `selectOption`) may declare race-free expectations that are armed before
|
|
192
|
-
the interaction:
|
|
193
|
-
|
|
194
|
-
- `expectResponse`: exact origin-relative `path` (without query/fragment),
|
|
195
|
-
uppercase `method`, and integer `status` from 100 through 599;
|
|
196
|
-
- `expectDialog`: `type` (`alert`, `beforeunload`, `confirm`, or `prompt`), a
|
|
197
|
-
nested `message` matcher with exactly one of `equals`/`includes`, and boolean
|
|
198
|
-
`accept`.
|
|
199
|
-
|
|
200
|
-
The runner never records response bodies, headers, URLs, actual dialog text, or
|
|
201
|
-
prompt defaults in observations or failure reasons. A mismatching dialog is
|
|
202
|
-
dismissed so it cannot deadlock the browser.
|
|
203
|
-
|
|
204
|
-
`dragTo` requires a source `locator` and `dropTarget`, with optional bounded
|
|
205
|
-
`sourcePosition` and `dropPosition` `{ x, y }`. `uploadFiles` accepts only
|
|
206
|
-
in-memory entries `{ name, mimeType, base64 }`; up to 10 files, 5 MiB each and
|
|
207
|
-
10 MiB total. An empty array clears the input. Filesystem paths and directories
|
|
208
|
-
are not supported.
|
|
209
|
-
|
|
210
|
-
`download` atomically clicks its locator and requires a nested `filename`
|
|
211
|
-
matcher. `maxBytes` defaults to 5 MiB and is capped at 25 MiB. Downloads are
|
|
212
|
-
deleted after validation unless `retain: true` and a safe `name` are supplied;
|
|
213
|
-
retained bytes appear in `artifacts.downloads` under a runner-generated `.bin`
|
|
214
|
-
name. The runner cancels while its private copy grows past `maxBytes`, but this
|
|
215
|
-
is an evidence-retention bound rather than a network-bandwidth guarantee because
|
|
216
|
-
the browser may already hold temporary bytes. Retained bytes are scanned for
|
|
217
|
-
configured authentication before publication. The actual server filename is
|
|
218
|
-
never placed in diagnostics.
|
|
219
|
-
|
|
220
|
-
`openPopup` atomically clicks a locator, captures a same-origin popup, and stores
|
|
221
|
-
it under a safe `name` (maximum three). Target later actions with
|
|
222
|
-
`{ "target": { "type": "popup", "name": "..." } }`. Target same-origin
|
|
223
|
-
iframes with `{ "target": { "type": "frame", "locator": { ... } } }`; add
|
|
224
|
-
`page` with a popup name for a frame inside that popup. Frame origin is checked
|
|
225
|
-
from its live document before every scoped step. Cross-origin popups/frames are
|
|
226
|
-
rejected. Popup recordings are returned as separate video artifacts.
|
|
227
|
-
|
|
228
|
-
`wheel` accepts finite `deltaX`/`deltaY` values and requires at least one
|
|
229
|
-
non-zero delta. With a locator, the runner hovers that element before sending
|
|
230
|
-
the wheel input. Safe `evaluate` operations are:
|
|
231
|
-
|
|
232
|
-
- `scrollTo`: optional locator plus numeric `x`/`y` or the string `"max"`;
|
|
233
|
-
- `scrollBy`: optional locator plus numeric `deltaX`/`deltaY`;
|
|
234
|
-
- `metrics`: optional locator plus an optional safe `name`; values are returned
|
|
235
|
-
in the runner's `observations` array.
|
|
236
|
-
|
|
237
|
-
Element metrics are `scrollLeft`, `scrollTop`, `scrollWidth`, `scrollHeight`,
|
|
238
|
-
`clientWidth`, `clientHeight`, `x`, `y`, `width`, and `height`. Page metrics are
|
|
239
|
-
`scrollX`, `scrollY`, `scrollWidth`, `scrollHeight`, `clientWidth`,
|
|
240
|
-
`clientHeight`, `viewportWidth`, and `viewportHeight`. Use `assertDOMMetric`
|
|
241
|
-
with a `metric` and exactly one of `equals`, `greaterThan`,
|
|
242
|
-
`greaterThanOrEqual`, `lessThan`, or `lessThanOrEqual` for a deterministic
|
|
243
|
-
oracle. Raw JavaScript remains intentionally unsupported.
|
|
244
|
-
|
|
245
|
-
```jsonc
|
|
246
|
-
{
|
|
247
|
-
"viewport": { "width": 844, "height": 847 },
|
|
248
|
-
"environment": {
|
|
249
|
-
"locale": "en-GB",
|
|
250
|
-
"timezoneId": "Europe/London",
|
|
251
|
-
"colorScheme": "dark"
|
|
252
|
-
},
|
|
253
|
-
"steps": [
|
|
254
|
-
{ "action": "goto", "path": "/settings" },
|
|
255
|
-
{ "action": "authRejectedIf", "urlIncludes": "/login" },
|
|
256
|
-
{
|
|
257
|
-
"action": "assertVisible",
|
|
258
|
-
"locator": { "role": "heading", "name": "Settings", "exact": true }
|
|
259
|
-
},
|
|
260
|
-
{
|
|
261
|
-
"action": "wheel",
|
|
262
|
-
"locator": { "css": ".settings-panel" },
|
|
263
|
-
"deltaY": 500
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
"action": "assertDOMMetric",
|
|
267
|
-
"locator": { "css": ".settings-panel" },
|
|
268
|
-
"metric": "scrollTop",
|
|
269
|
-
"greaterThan": 0
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
"action": "click",
|
|
273
|
-
"locator": { "testId": "save-settings" },
|
|
274
|
-
"expectResponse": {
|
|
275
|
-
"path": "/api/settings",
|
|
276
|
-
"method": "PUT",
|
|
277
|
-
"status": 200
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
"action": "assertText",
|
|
282
|
-
"locator": { "testId": "toast" },
|
|
283
|
-
"includes": "Saved"
|
|
284
|
-
},
|
|
285
|
-
{ "action": "screenshot", "name": "settings-saved" }
|
|
286
|
-
]
|
|
287
|
-
}
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
For multiple profiles, invoke the runner separately. Every invocation gets an
|
|
291
|
-
isolated browser context and exclusive evidence directory; the runner closes
|
|
292
|
-
all owned browser resources on success and failure. Flows, screenshots, video,
|
|
293
|
-
sanitized traces, retained downloads, and runner result manifests remain under
|
|
294
|
-
`$PI_SUBAGENT_AGENT_DIR/browser-qa/` so normal sub-agent shutdown or cleanup
|
|
295
|
-
deletes them with the run directory. For form auth, recording starts on the login
|
|
296
|
-
page and includes field filling and submission; password inputs remain masked,
|
|
297
|
-
but the private video may show visible login identifiers. Tracing starts only
|
|
298
|
-
after login succeeds so credentials are not captured in the trace.
|
|
299
|
-
|
|
300
|
-
## Credentials and blocked runs
|
|
301
|
-
|
|
302
|
-
### Form-auth scaffolding
|
|
303
|
-
|
|
304
|
-
When a public HTTPS login page (or loopback HTTP page for local development) is
|
|
305
|
-
known and there is no usable profile, invoke the trusted runner once:
|
|
306
|
-
|
|
307
|
-
```sh
|
|
308
|
-
node "$PI_BROWSER_QA_RUNNER" auth scaffold \
|
|
309
|
-
--profile <safe-id> \
|
|
310
|
-
--login-url <public-login-url>
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
The runner discovers the login form and privately writes a target-specific
|
|
314
|
-
`.pi/qa_auth.jsonc` containing `__PI_QA_SECRET_n__` values. It may create the
|
|
315
|
-
file or replace only the runner's own empty generated template; it refuses to
|
|
316
|
-
overwrite invalid or non-empty auth configuration. Never inspect the result.
|
|
317
|
-
Relay `QA_AUTH_SCAFFOLD_CREATED`, the reported file, profile, placeholder count,
|
|
318
|
-
and action, then ask the user to replace only those placeholder values. Browser
|
|
319
|
-
QA must resume in a new run after the user confirms that edit.
|
|
320
|
-
|
|
321
|
-
By default, login succeeds when the discovered form becomes hidden. A form-less
|
|
322
|
-
page therefore requires an explicit deterministic signal using either
|
|
323
|
-
`--success-url <glob>` or `--success-selector <selector>` with optional
|
|
324
|
-
`--success-state attached|detached|visible|hidden`. Use `--base-url <url>` only
|
|
325
|
-
to override the profile's same-origin application root. These are public
|
|
326
|
-
metadata; never put credential values in command arguments or environment
|
|
327
|
-
variables.
|
|
328
|
-
|
|
329
|
-
Do not scaffold cookie, bearer, storage, storage-state, MFA, CAPTCHA, or
|
|
330
|
-
federated login. For those modes, use the generic empty-template flow below and
|
|
331
|
-
ask the user to configure the profile themselves.
|
|
332
|
-
|
|
333
|
-
Do not request credentials merely because `.pi/qa_auth.jsonc` is absent. If the
|
|
334
|
-
task explicitly requires authenticated behavior, or a public run reaches the
|
|
335
|
-
flow's `authRejectedIf` check, and `profiles` returned no usable profile, run
|
|
336
|
-
form-auth scaffolding when supported. Otherwise run
|
|
337
|
-
`node "$PI_BROWSER_QA_RUNNER" profiles --require-auth`. Only these paths
|
|
338
|
-
may create the private auth file.
|
|
339
|
-
|
|
340
|
-
If that command or an authenticated run returns `QA_AUTH_UPDATE_REQUIRED`, stop
|
|
341
|
-
and explicitly report that authenticated browser QA requires credentials or an
|
|
342
|
-
auth-config update. Ask the user to fill the reported file and rerun QA. If
|
|
343
|
-
`templateCreated` is true, say that a private empty template was created at that
|
|
344
|
-
path. Relay only the runner's profile, file, reason, action, and template-created
|
|
345
|
-
state; never read the generated file or attempt to recover by exposing or
|
|
346
|
-
replaying credentials. If the action is `fill_credentials`, also relay the
|
|
347
|
-
placeholder count and tell the user to replace only the generated placeholder
|
|
348
|
-
values.
|
|
349
|
-
|
|
350
|
-
For any other blocked run, report the runner status and redacted reason. Do not
|
|
351
|
-
claim that browser QA passed based on source inspection, unit tests, or a build.
|
|
352
|
-
|
|
353
|
-
After any runner invocation that actually performed browser testing, include
|
|
354
|
-
all non-empty `artifacts.screenshots`, `artifacts.videos`, and
|
|
355
|
-
`artifacts.traces`, and `artifacts.downloads` groups in the final response.
|
|
356
|
-
These links are mandatory so the user can open the evidence directly.
|
|
357
|
-
Also include `visualInspection` with `inspected` or `unavailable`; never infer a
|
|
358
|
-
visual pass from a successful runner status alone.
|
|
359
|
-
|
|
360
|
-
### Scaffold safety and edge cases
|
|
361
|
-
|
|
362
|
-
The trusted runner discovers the most likely form, fillable fields, submit
|
|
363
|
-
control, and form container on the unauthenticated page. It writes only
|
|
364
|
-
discovered selectors and generated placeholders to the private `0600` config.
|
|
365
|
-
The agent treats that config as opaque and user-owned. Scaffold status exposes
|
|
366
|
-
only the file path, profile id, counts, and action, never inspected DOM text,
|
|
367
|
-
input values, URLs, or selectors.
|
|
368
|
-
|
|
369
|
-
Scaffolding rejects pages without a discoverable fillable field or submit
|
|
370
|
-
control, form-less pages without an explicit success condition, remote HTTP
|
|
371
|
-
login pages, cross-origin base URLs, malformed success options, symlinked or
|
|
372
|
-
permissive auth paths, and invalid or non-empty existing configuration. Report
|
|
373
|
-
these blockers; do not bypass them. No generated profile is usable until the
|
|
374
|
-
user replaces its secret placeholders.
|
|
375
|
-
|
|
376
|
-
## Detailed scenario-design guidance
|
|
377
|
-
|
|
378
|
-
Use the bundled declarative runner throughout. This workflow does not require
|
|
379
|
-
a separate browser CLI or executable Playwright scripts.
|
|
380
|
-
|
|
381
|
-
### Build the proof before the steps
|
|
382
|
-
|
|
383
|
-
Write down three things first:
|
|
384
|
-
|
|
385
|
-
1. **Setup:** the page and state needed to expose the behavior.
|
|
386
|
-
2. **Action:** the smallest user interaction that exercises it.
|
|
387
|
-
3. **Oracle:** the observable state that proves success or reproduces failure.
|
|
388
|
-
|
|
389
|
-
Good oracles are product-visible and specific: an exact URL, a stable status
|
|
390
|
-
message, a field value, item count, enabled/disabled state, or checked state.
|
|
391
|
-
Avoid treating “the click did not throw” or “the screenshot looks plausible” as
|
|
392
|
-
proof.
|
|
393
|
-
|
|
394
|
-
When verifying a fix, prefer a focused regression flow over a broad tour of the
|
|
395
|
-
application. If multiple independent states matter, assert each one explicitly.
|
|
396
|
-
|
|
397
|
-
For explicit exploratory/manual QA, keep exploration bounded rather than turning
|
|
398
|
-
it into an open-ended crawl. Run at most three minimal rounds. Each round should
|
|
399
|
-
start from one concrete hypothesis, produce a deterministic observation plus a
|
|
400
|
-
meaningful screenshot, and use that evidence to decide whether another round is
|
|
401
|
-
justified. Verification tasks remain one browser run per profile.
|
|
402
|
-
|
|
403
|
-
### Choose resilient locators
|
|
404
|
-
|
|
405
|
-
Prefer locators that match how users and accessibility APIs identify controls:
|
|
406
|
-
|
|
407
|
-
1. `testId` when the product exposes a stable test contract.
|
|
408
|
-
2. `role` with accessible `name` for buttons, links, headings, dialogs, and
|
|
409
|
-
similar semantic elements.
|
|
410
|
-
3. `label` for form controls.
|
|
411
|
-
4. `placeholder` or visible `text` when they are stable product copy.
|
|
412
|
-
5. `css` only when no semantic contract exists.
|
|
413
|
-
|
|
414
|
-
Use `exact: true` when duplicate or substring matches are possible. Avoid CSS
|
|
415
|
-
that encodes DOM depth, generated classes, styling details, or element order.
|
|
416
|
-
If a locator is ambiguous, inspect nearby source or rendered copy and choose a
|
|
417
|
-
more specific product contract rather than adding arbitrary delays.
|
|
418
|
-
|
|
419
|
-
### Wait for state, not time
|
|
420
|
-
|
|
421
|
-
Runner interactions inherit Playwright auto-waiting. Usually an action followed
|
|
422
|
-
by an assertion is enough. Use `waitFor` only when the next operation depends on
|
|
423
|
-
a distinct attached/detached/visible/hidden transition.
|
|
424
|
-
|
|
425
|
-
After navigation and visible interactions, the runner also waits for DOM
|
|
426
|
-
readiness, tracks requests causally started by that action through a bounded
|
|
427
|
-
readiness window, waits for common visible
|
|
428
|
-
`aria-busy`/progress/loading/spinner/skeleton markers, and keeps a 500 ms stable
|
|
429
|
-
interval. EventSource/WebSocket traffic is ignored, and a long poll is not
|
|
430
|
-
allowed to pin the entire flow timeout. A visible busy indicator may still hold
|
|
431
|
-
readiness until `timeoutMs`. This is a safe baseline, not an application-specific
|
|
432
|
-
oracle: explicitly wait for a custom loader to become hidden and assert the
|
|
433
|
-
loaded content when the application uses different readiness semantics.
|
|
434
|
-
|
|
435
|
-
`waitForTimeout` is bounded to five seconds and should be exceptional—for a
|
|
436
|
-
known animation, debounce, or externally scheduled transition with no
|
|
437
|
-
observable intermediate state. Sleeping longer hides races instead of proving
|
|
438
|
-
behavior. If a normal operation legitimately needs more time, adjust the flow's
|
|
439
|
-
`timeoutMs` rather than inserting repeated sleeps.
|
|
440
|
-
|
|
441
|
-
All assertion actions retry until that timeout. This makes an action followed
|
|
442
|
-
directly by `assertText`, `assertVisible`, `assertURL`, or another assertion
|
|
443
|
-
safe for asynchronously rendered outcomes. `assertText` requires the locator to
|
|
444
|
-
be visible and matches rendered `innerText`; use `assertTextContent` only when
|
|
445
|
-
hidden/raw DOM text is deliberately part of the oracle. Use `assertAttribute` for
|
|
446
|
-
observable state such as `aria-expanded`, `aria-invalid`, or `data-state`
|
|
447
|
-
instead of reading DOM state through executable JavaScript.
|
|
448
|
-
|
|
449
|
-
### Responsive and scrolling scenarios
|
|
450
|
-
|
|
451
|
-
Set the flow's top-level `viewport` whenever the bug depends on a breakpoint or
|
|
452
|
-
available height. Assert `viewportWidth` or `viewportHeight` with
|
|
453
|
-
`assertDOMMetric` when the dimensions themselves are part of the proof; the
|
|
454
|
-
runner also includes the applied viewport in its result.
|
|
455
|
-
|
|
456
|
-
Use `wheel` to reproduce real pointer-wheel input. Add a locator when the wheel
|
|
457
|
-
must target a nested scrolling container—the runner hovers it before sending
|
|
458
|
-
the input. Because browser scrolling may be scheduled after the wheel event,
|
|
459
|
-
wait only for a short known settling interval when a direct metric assertion is
|
|
460
|
-
otherwise racy.
|
|
461
|
-
|
|
462
|
-
Use safe `evaluate` `scrollTo`/`scrollBy` operations for deterministic setup or
|
|
463
|
-
to distinguish input handling from layout behavior. Use the `metrics` operation
|
|
464
|
-
to retain a named page/element snapshot in result `observations`, and use
|
|
465
|
-
`assertDOMMetric` for pass/fail. Raw JavaScript expressions are intentionally
|
|
466
|
-
excluded: flows remain declarative and cannot inspect authentication storage or
|
|
467
|
-
execute arbitrary same-origin requests.
|
|
468
|
-
|
|
469
|
-
### Deterministic browser environment
|
|
470
|
-
|
|
471
|
-
Set top-level `environment` when locale, timezone, color scheme, or motion
|
|
472
|
-
preferences can change the behavior. The runner otherwise uses stable defaults
|
|
473
|
-
(`en-US`, `UTC`, `light`, `reduce`) instead of inheriting host settings. Prefer
|
|
474
|
-
asserting product-visible copy or state derived from those settings; do not use
|
|
475
|
-
screenshot pixels as the only oracle.
|
|
476
|
-
|
|
477
|
-
### Causal network and dialog expectations
|
|
478
|
-
|
|
479
|
-
Put `expectResponse` or `expectDialog` on the interaction that causes the event.
|
|
480
|
-
The runner arms both listeners before the interaction, avoiding the race in a
|
|
481
|
-
separate “click, then wait” sequence. Response expectations deliberately match
|
|
482
|
-
only an exact allowlisted-origin pathname, HTTP method, and status. This proves
|
|
483
|
-
that a matching request started and received a response within the action
|
|
484
|
-
window without retaining its URL query, headers, or body.
|
|
485
|
-
|
|
486
|
-
Dialog expectations match a fixed dialog type and exact/included message, then
|
|
487
|
-
accept or dismiss it declaratively. A mismatch is dismissed before the step
|
|
488
|
-
fails so the page cannot freeze. Actual event metadata is never included in
|
|
489
|
-
failure diagnostics. Do not place secrets in expected messages or response
|
|
490
|
-
paths even though the runner keeps diagnostics generic.
|
|
491
|
-
|
|
492
|
-
### Drag, upload, and download scenarios
|
|
493
|
-
|
|
494
|
-
Use `dragTo` for native DOM drag/drop and assert the resulting product state.
|
|
495
|
-
Optional source/drop positions are relative bounded coordinates. Canvas-only,
|
|
496
|
-
OS-native, or custom synthetic-event drag protocols remain unsupported; do not
|
|
497
|
-
work around that with executable JavaScript.
|
|
498
|
-
|
|
499
|
-
Uploads are memory-only base64 payloads declared in the flow. This intentionally
|
|
500
|
-
prevents a flow from selecting arbitrary project files, credential config, or
|
|
501
|
-
directories. Keep fixtures minimal and non-secret. An empty file list clears a
|
|
502
|
-
file input.
|
|
503
|
-
|
|
504
|
-
Use the atomic `download` action rather than clicking a download link directly.
|
|
505
|
-
Always match the suggested filename and choose a tight `maxBytes`. Retain a
|
|
506
|
-
download only when its contents are needed as evidence; otherwise the runner
|
|
507
|
-
deletes it after validation. Retained downloads use generated private names,
|
|
508
|
-
not server-provided paths, and are scanned for configured authentication before
|
|
509
|
-
publication. `maxBytes` bounds the runner's private evidence copy and triggers
|
|
510
|
-
cancellation while it grows, but it is not a network-bandwidth guarantee: the
|
|
511
|
-
browser can receive temporary bytes before cancellation.
|
|
512
|
-
|
|
513
|
-
### Same-origin frames and popups
|
|
514
|
-
|
|
515
|
-
Use a scoped `target` for iframe or named popup interactions. The runner checks
|
|
516
|
-
the live frame origin before every scoped step and checks a popup after it loads;
|
|
517
|
-
both must remain in `allowedOrigins`. This supports embedded application UI and
|
|
518
|
-
same-origin auxiliary windows without opening a route around the network guard.
|
|
519
|
-
Cross-origin login, payment, and third-party widgets remain intentionally out of
|
|
520
|
-
scope. Each popup adds a separate private video artifact, so open only the
|
|
521
|
-
windows needed for the proof.
|
|
522
|
-
|
|
523
|
-
### Authentication transitions
|
|
524
|
-
|
|
525
|
-
Add `authRejectedIf` directly after initial navigation and after transitions
|
|
526
|
-
that can redirect to login or display an expired-session marker. This converts
|
|
527
|
-
stale credentials into an explicit update request instead of misreporting a
|
|
528
|
-
product regression.
|
|
529
|
-
|
|
530
|
-
Do not encode credentials, tokens, storage values, or login form secrets in the
|
|
531
|
-
flow. The trusted runner applies the selected profile internally. For form auth,
|
|
532
|
-
video starts on the login page and includes field filling and submission; password
|
|
533
|
-
inputs remain masked, but visible identifiers can appear, so treat the video as
|
|
534
|
-
sensitive private evidence. Tracing starts only after login succeeds and is
|
|
535
|
-
sanitized before retention.
|
|
536
|
-
|
|
537
|
-
### Evidence strategy
|
|
538
|
-
|
|
539
|
-
The runner always attempts a final or failure screenshot, records video from the
|
|
540
|
-
first page, and creates a sanitized post-auth trace. Add named `screenshot`
|
|
541
|
-
steps only at states that materially help explain the result—for example before
|
|
542
|
-
and after a destructive interaction, or when a transient success message is
|
|
543
|
-
the oracle.
|
|
544
|
-
|
|
545
|
-
Use evidence by purpose:
|
|
546
|
-
|
|
547
|
-
- **Screenshot:** quick review of one meaningful visual state.
|
|
548
|
-
- **Video:** chronological confirmation of the complete user flow.
|
|
549
|
-
- **Trace:** action/DOM timing diagnosis for a failed or flaky interaction.
|
|
550
|
-
|
|
551
|
-
Videos automatically show a transient cursor and yellow pulse for clicks and
|
|
552
|
-
double-clicks. After a native `dragTo` gesture completes, its resolved
|
|
553
|
-
source-to-target route is replayed over 450 ms with a large orange cursor and
|
|
554
|
-
progressively drawn high-contrast trail, followed by a green drop marker. These
|
|
555
|
-
annotations are
|
|
556
|
-
runner-owned, pointer-transparent, and accessibility-hidden; they cover the main
|
|
557
|
-
page, same-origin frames, declared popups, and form-auth submission. Their
|
|
558
|
-
bounded animations finish within the normal post-action stable interval, so
|
|
559
|
-
they explain the chronology without becoming screenshot or assertion oracles.
|
|
560
|
-
|
|
561
|
-
Assertions determine pass/fail; evidence explains it. Preserve and link every
|
|
562
|
-
artifact group returned on both passed and failed runs.
|
|
563
|
-
|
|
564
|
-
For visual QA, do not stop at artifact generation. Open at least one meaningful
|
|
565
|
-
PNG with the model's image-capable `read` path and inspect layout, clipping,
|
|
566
|
-
overlap, state styling, and other visual defects relevant to the scenario. If
|
|
567
|
-
the active model cannot read images, explicitly report visual inspection as
|
|
568
|
-
unavailable rather than treating deterministic assertions as a visual pass.
|
|
569
|
-
|
|
570
|
-
### Diagnose failures without weakening the test
|
|
571
|
-
|
|
572
|
-
Classify the first failing step:
|
|
573
|
-
|
|
574
|
-
- wrong target/setup or service unavailable;
|
|
575
|
-
- authentication rejected or expired;
|
|
576
|
-
- locator no longer matches the product contract;
|
|
577
|
-
- expected state never appeared;
|
|
578
|
-
- actual product behavior contradicts the expectation.
|
|
579
|
-
|
|
580
|
-
Fix the flow only when its setup or locator is wrong. Do not replace a precise
|
|
581
|
-
assertion with a vague one, increase timeouts reflexively, or remove the failing
|
|
582
|
-
step to manufacture a pass. Keep the failure artifacts and state the expected
|
|
583
|
-
versus observed behavior.
|
|
584
|
-
|
|
585
|
-
### Cleanup and isolation
|
|
586
|
-
|
|
587
|
-
Each runner invocation owns one isolated context and evidence directory and
|
|
588
|
-
closes its browser resources in a `finally` path. Do not create parallel shared
|
|
589
|
-
or default sessions outside the runner. Test multiple auth profiles with
|
|
590
|
-
separate invocations so cookies, storage, traces, and evidence cannot mix.
|
|
591
|
-
|
|
592
|
-
Keep the declarative flow and every generated screenshot, video, trace, and
|
|
593
|
-
result manifest inside `$PI_SUBAGENT_AGENT_DIR/browser-qa/`. The launcher owns
|
|
594
|
-
that path and the runner validates it before opening a browser. Do not override
|
|
595
|
-
the environment path or copy evidence into shared `.pi/qa-runs`/`.pi/qa-flows`
|
|
596
|
-
directories: the agent-local workspace is intentionally removed by the normal
|
|
597
|
-
sub-agent shutdown and cleanup lifecycle. Authentication config remains a
|
|
598
|
-
separate persistent input under project `.pi/`.
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Value of asyncSubagents in pi-tools-suite.jsonc.
|
|
3
|
-
// Bundled role definitions and ordered models live in agents/*.md.
|
|
4
|
-
// Full config schema: https://unpkg.com/pi-ui-extend/schemas/pi-tools-suite.json
|
|
5
|
-
"defaultType": "research",
|
|
6
|
-
"maxConcurrent": 5,
|
|
7
|
-
"maxResultBytes": 100000,
|
|
8
|
-
"vision": {
|
|
9
|
-
"blindModelPatterns": [
|
|
10
|
-
"zai/glm-4.5*", "glm-4.5*", "*/glm-4.5*",
|
|
11
|
-
"zai/glm-5-turbo*", "glm-5-turbo*", "*/glm-5-turbo*",
|
|
12
|
-
"zai/glm-5.3", "glm-5.3", "*/glm-5.3"
|
|
13
|
-
]
|
|
14
|
-
},
|
|
15
|
-
// Only omitted roles use the LLM router. Model selection itself is deterministic.
|
|
16
|
-
"routing": {
|
|
17
|
-
"enabled": true,
|
|
18
|
-
"model": "zai/glm-5-turbo",
|
|
19
|
-
"fallbackModels": ["openai-codex/gpt-5.6-luna"],
|
|
20
|
-
"maxTaskChars": 1200,
|
|
21
|
-
"maxTokens": 512,
|
|
22
|
-
"maxRetries": 1,
|
|
23
|
-
"timeoutMs": 12000,
|
|
24
|
-
"debug": false
|
|
25
|
-
},
|
|
26
|
-
// A preset is an available model pool, NOT a role-to-model mapping.
|
|
27
|
-
// Choose the first usable entry in each agent's models that is in
|
|
28
|
-
// this pool. Pool order does not reorder agent preferences. The remaining
|
|
29
|
-
// matching candidates are the only quota fallbacks; never leave the pool.
|
|
30
|
-
// Oracle uses its strong candidate list, preferring another provider when
|
|
31
|
-
// possible, but also respects this pool. An empty intersection is an error.
|
|
32
|
-
// Explicit task.model, CLI --model, and FORCE_CURRENT_MODEL remain overrides.
|
|
33
|
-
// Legacy preset model/types/fallbackModels fields still load for compatibility.
|
|
34
|
-
"presets": {
|
|
35
|
-
"cheap": {
|
|
36
|
-
"description": "GLM pool: economical workers plus GLM-5.3 for oracle.",
|
|
37
|
-
"models": ["zai/glm-5-turbo", "zai/glm-5.3-flash", "zai/glm-5.3"]
|
|
38
|
-
},
|
|
39
|
-
"gpt": {
|
|
40
|
-
"description": "GPT pool: Luna/Terra workers; Sol is available to oracle.",
|
|
41
|
-
"models": ["openai-codex/gpt-5.6-luna", "openai-codex/gpt-5.6-terra", "openai-codex/gpt-5.6-sol"]
|
|
42
|
-
},
|
|
43
|
-
"deep": {
|
|
44
|
-
"description": "Legacy preset name for the mixed pool; workers retain economical candidate order, oracle uses strong models.",
|
|
45
|
-
"models": ["zai/glm-5-turbo", "zai/glm-5.3-flash", "openai-codex/gpt-5.6-luna", "openai-codex/gpt-5.6-terra", "openai-codex/gpt-5.6-sol", "zai/glm-5.3"]
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
// Override role behavior here or define project specialists in .pi/agents/.
|
|
49
|
-
// Old builtin names are not aliases; define them explicitly only when you
|
|
50
|
-
// intentionally want custom types with those exact names.
|
|
51
|
-
// Per-type "icon" names the agent glyph for UI widgets (agent, search, code,
|
|
52
|
-
// flask, globe, sparkles, brain, wrench, terminal, bug, book, eye, zap, rocket).
|
|
53
|
-
"types": {}
|
|
54
|
-
}
|