oh-my-opencode 5.0.0-beta.62 → 5.0.0-beta.63

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.
Files changed (213) hide show
  1. package/THIRD-PARTY-NOTICES.md +8 -6
  2. package/dist/cli/doctor/checks/browser-provider.d.ts +2 -0
  3. package/dist/cli/index.js +64 -35
  4. package/dist/cli-node/index.js +64 -35
  5. package/dist/config/schema/agent-names.d.ts +0 -1
  6. package/dist/config/schema/browser-automation.d.ts +0 -2
  7. package/dist/config/schema/oh-my-opencode-config.d.ts +0 -1
  8. package/dist/hooks/comment-checker/__fixtures__/download-probe.fixture.d.ts +1 -0
  9. package/dist/index.js +61 -535
  10. package/dist/oh-my-opencode.schema.json +0 -1
  11. package/dist/skills/ast-grep/SKILL.md +12 -0
  12. package/dist/skills/debugging/references/tools/playwright-cli.md +79 -161
  13. package/dist/skills/frontend/SKILL.md +1 -1
  14. package/dist/skills/frontend/references/design/aside.md +1 -1
  15. package/dist/skills/frontend/references/design/clone-from-url.md +1 -1
  16. package/dist/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
  17. package/dist/skills/review-work/SKILL.md +1 -1
  18. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
  19. package/dist/skills/ultimate-browsing/SKILL.md +17 -29
  20. package/dist/skills/ultimate-browsing/engine/AGENTS.md +2 -1
  21. package/dist/skills/ultimate-browsing/engine/templates/package.json +2 -2
  22. package/dist/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
  23. package/dist/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
  24. package/dist/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
  25. package/dist/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
  26. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
  27. package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -3
  28. package/dist/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
  29. package/dist/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
  30. package/dist/skills/ulw-execute/SKILL.md +1 -1
  31. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  32. package/dist/skills/ulw-research/SKILL.md +3 -3
  33. package/dist/skills/visual-qa/AGENTS.md +1 -1
  34. package/dist/skills/visual-qa/SKILL.md +1 -1
  35. package/dist/skills/visual-qa/references/browser-setup.md +75 -0
  36. package/dist/tui.js +12 -5
  37. package/package.json +16 -23
  38. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  39. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -0
  40. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  41. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  42. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  43. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  44. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  45. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  46. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  47. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  48. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  49. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  50. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  52. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  53. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  54. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  55. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
  58. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +5 -4
  59. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  60. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  62. package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +1 -1
  63. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  64. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  65. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +13 -0
  66. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +5 -4
  67. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +5 -4
  68. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +582 -322
  69. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +5 -0
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.js +16 -12
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.d.ts +4 -0
  72. package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.js +34 -0
  73. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.d.ts +19 -0
  74. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.js +107 -0
  75. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +2 -1
  76. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +48 -22
  77. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +9 -7
  78. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +105 -114
  79. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.d.ts +15 -0
  80. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.js +86 -0
  81. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +5 -1
  82. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +15 -3
  83. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +3 -4
  84. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.js +12 -5
  85. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-budget-io.d.ts +5 -0
  86. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-budget-io.js +67 -0
  87. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +8 -62
  88. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +11 -1
  89. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +120 -88
  90. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +3 -2
  91. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +18 -10
  92. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +4 -4
  93. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +5 -5
  94. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +8 -17
  95. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  96. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  97. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
  98. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +5 -4
  99. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +5 -0
  100. package/packages/omo-codex/plugin/components/ulw-loop/src/evidence.ts +16 -16
  101. package/packages/omo-codex/plugin/components/ulw-loop/src/ledger.ts +33 -0
  102. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-commit.ts +124 -0
  103. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +58 -51
  104. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +126 -140
  105. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-log.ts +84 -0
  106. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +26 -3
  107. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +3 -3
  108. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/factory.ts +30 -5
  109. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-budget-io.ts +59 -0
  110. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +8 -59
  111. package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +129 -111
  112. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +19 -10
  113. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +4 -4
  114. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +5 -4
  115. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +8 -16
  116. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/barrier.ts +13 -0
  117. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-child.ts +65 -0
  118. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-cli-qa.mjs +76 -0
  119. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-crash.ts +23 -0
  120. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-mutations.mjs +58 -0
  121. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-writer.ts +65 -0
  122. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/lease-clock.ts +23 -0
  123. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-commit-log.test.ts +252 -0
  124. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-commit-recovery.test.ts +190 -0
  125. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +50 -35
  126. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-log-newest.test.ts +72 -0
  127. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-completed-plan.test.ts +43 -0
  128. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-session-context.test.ts +21 -0
  129. package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +92 -0
  130. package/packages/omo-codex/plugin/components/ulw-loop/test/status-next-actions-surface.test.ts +133 -0
  131. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +12 -12
  132. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +4 -1
  133. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  134. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  135. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  136. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  137. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  138. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  139. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  140. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  141. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  142. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  143. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  144. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  145. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  146. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  147. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  148. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  149. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  150. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  151. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  152. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  153. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  154. package/packages/omo-codex/plugin/package-lock.json +12 -12
  155. package/packages/omo-codex/plugin/package.json +1 -1
  156. package/packages/omo-codex/plugin/scripts/sync-skills.d.mts +4 -0
  157. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +15 -7
  158. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +12 -0
  159. package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +79 -161
  160. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
  161. package/packages/omo-codex/plugin/skills/frontend/references/design/aside.md +1 -1
  162. package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +1 -1
  163. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
  164. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  165. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
  166. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +17 -29
  167. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +2 -1
  168. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +2 -2
  169. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
  170. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
  171. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
  172. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
  173. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
  174. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -3
  175. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
  176. package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
  177. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +5 -4
  178. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +1 -1
  179. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
  180. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +3 -3
  181. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +1 -1
  182. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +1 -1
  183. package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +75 -0
  184. package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -2
  185. package/packages/prompts-core/prompts/ultrawork/codex.md +5 -4
  186. package/packages/shared-skills/skills/ast-grep/SKILL.md +12 -0
  187. package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +79 -161
  188. package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
  189. package/packages/shared-skills/skills/frontend/references/design/aside.md +1 -1
  190. package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +1 -1
  191. package/packages/shared-skills/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
  192. package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
  193. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
  194. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +17 -29
  195. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +2 -1
  196. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +2 -2
  197. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
  198. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
  199. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
  200. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
  201. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
  202. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -3
  203. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
  204. package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
  205. package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
  206. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  207. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
  208. package/packages/shared-skills/skills/visual-qa/AGENTS.md +1 -1
  209. package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
  210. package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +75 -0
  211. package/dist/skills/visual-qa/references/agent-browser-setup.md +0 -45
  212. package/packages/omo-codex/plugin/skills/visual-qa/references/agent-browser-setup.md +0 -45
  213. package/packages/shared-skills/skills/visual-qa/references/agent-browser-setup.md +0 -45
@@ -177,7 +177,7 @@ Scaling floor — more angles always justify more workers:
177
177
  | Multi-faceted | 4 | 6 | 2 | 2 | 14 |
178
178
  | Full due diligence | 4 | 6 | 3 | 2 | 15 |
179
179
 
180
- The browsing column is BINDING, not advisory: when the brief says `Browsing: yes`, the roster names a browsing-worker angle before the first wave launches, and that worker is spawned in the same turn as the rest of the wave. A run that reaches wave 2 with zero browsing workers on a `Browsing: yes` brief has silently downgraded every source to what plain fetch happened to return.
180
+ The browsing column is BINDING, not advisory: when the brief says `Browsing: yes`, the roster names a browsing-worker angle, armed with the `ultimate-browsing` skill, before the first wave launches, and that worker is spawned in the same turn as the rest of the wave. A run that reaches wave 2 with zero browsing workers on a `Browsing: yes` brief has silently downgraded every source to what plain fetch happened to return.
181
181
 
182
182
  **Disambiguate before you expand.** When the topic names something that could resolve several ways — a product, a person, a codename, a version — the first wave settles WHICH entity before any worker researches its history, benchmarks, or controversies: canonical name, first-party URL or account, whether it exists in the claimed category, and a confidence line. An unresolved entity never becomes a premise in a later wave's spawn message; that is exactly how a run starts inventing facts about something that does not exist.
183
183
 
@@ -185,7 +185,7 @@ Role protocols — embed the relevant one in each spawn message; every worker ge
185
185
 
186
186
  - **Codebase (explore), 2-4 workers.** Grep with 3+ keyword variations; structural/AST search; LSP definitions and references; file-name globs; `git log --all -S '<keyword>'` and `--grep` for history including deleted code. Cross-validate hits across tools. Report absolute file paths, patterns with `file:line`, and how findings connect.
187
187
  - **Web (librarian), 3-6 workers.** At least 10 distinct websearch queries per worker, each with a different operator or angle (see Search craft); fetch the full page for every result that matters — snippets lie. Context7 with 3+ queries per known library. grep.app and `gh search code|repos|issues` for real-world usage. Official docs via sitemap discovery (`<base>/sitemap.xml`), then targeted pages.
188
- - **Browsing, 1-3 workers on a `Browsing: yes` brief (0 otherwise).** This worker RENDERS pages, it does not re-fetch them: it drives a real browser through whatever the harness provides — the Browser plugin, an agent-browser or playwright skill, or a code-cell browser — and loads the `ultimate-browsing` skill to escalate through its tiers (insane-search engine with its Phase-2.5 archive surrogates, platform-native readers, then Chrome stealth) only when that browser is blocked. Its standing deliverable is a full-page screenshot of every top source plus the rendered text plain fetch could not reach; a worker that returns only fetched text has not done its job. JS-rendered, login-gated, WAF-blocked, and screenshot-bearing sources all belong here rather than in the web lane. **Provenance is part of the claim**: when a source came back with `provenance` of `snapshot` (an archive copy), cite it with its `snapshot_timestamp` and never state it as the current live page; content from a `proxy` route is `untrusted` and needs a second independent route before any claim rests on it. When one blocked territory hides many leads, fan out more browsing subagents in parallel for breadth instead of serializing one worker through them.
188
+ - **Browsing, 1-3 workers on a `Browsing: yes` brief (0 otherwise), every one loaded with the `ultimate-browsing` skill.** The skill owns the routing — the harness's own browser first, then its extraction engine with archive surrogates, platform-native readers, and Chrome stealth as each source demands; the worker owns the deliverable. This worker RENDERS pages, it does not re-fetch them: its standing deliverable is a full-page screenshot of every top source plus the rendered text plain fetch could not reach; a worker that returns only fetched text has not done its job. JS-rendered, login-gated, WAF-blocked, and screenshot-bearing sources all belong here rather than in the web lane. **Provenance is part of the claim**: when a source came back with `provenance` of `snapshot` (an archive copy), cite it with its `snapshot_timestamp` and never state it as the current live page; content from a `proxy` route is `untrusted` and needs a second independent route before any claim rests on it. When one blocked territory hides many leads, fan out more browsing subagents in parallel for breadth instead of serializing one worker through them.
189
189
  - **Repo deep-dive (librarian), 0-2 workers.** Shallow-clone the most relevant repos to `${TMPDIR:-/tmp}`, pin the HEAD SHA, read core modules, follow call chains, return SHA-pinned permalinks.
190
190
 
191
191
  Example spawn (codebase axis; librarian, browsing, and repo-dive follow the same contract with their own protocol):
@@ -384,7 +384,7 @@ High-yield combinations: official docs (`site:<docs domain>`), GitHub implementa
384
384
  | Obeying a surrounding "stop exploring" rule mid-research | Authority section — those rules do not bind this mode |
385
385
  | Asking a worker to write journal or session files | Workers are read-only; you journal every return |
386
386
  | Two workers given the same angle | One unique angle per worker, always |
387
- | A `Browsing: yes` run whose roster carries no browsing worker | The browsing column is binding — name the angle in the brief and spawn it with the first wave, before any lead is chased |
387
+ | A `Browsing: yes` run whose roster carries no browsing worker, or a browsing worker spawned without `ultimate-browsing` | The browsing column is binding — name the angle in the brief and spawn it, armed with the skill, in the first wave before any lead is chased |
388
388
  | Contested claim settled by judgment | Phase 3 — run code, capture output, verdict |
389
389
  | Deliverable claims without citations | Every claim cites a source or a verification artifact |
390
390
  | Guessing the deliverable format instead of asking | The format gate is unconditional: propose PDF+DOCX plus the domain-fitting alternatives and the template, then wait before wave 1 |
@@ -11,7 +11,7 @@ The visual-QA skill's executable core: a zero-dependency Node CLI that produces
11
11
  ```
12
12
  visual-qa/
13
13
  ├── SKILL.md # reviewer workflow (dual oracle, evidence gates) — the prose contract
14
- ├── references/agent-browser-setup.md
14
+ ├── references/browser-setup.md
15
15
  └── scripts/
16
16
  ├── visual-qa.mjs # SHIPPED RUNTIME: bun-build bundle of cli.ts (+ embedded modules)
17
17
  ├── cli.ts # development source; dispatches image-diff / tui-check
@@ -73,7 +73,7 @@ Before any reviewer sees an image, verify each capture yourself: the file signat
73
73
  ### Web
74
74
 
75
75
  1. Capture a REFERENCE image: the user's mock/target, generated page snapshot, Figma export, source-site capture, or known-good baseline. Save as PNG. If the user provided overview text or annotations, save them next to the image and treat them as part of the reference packet.
76
- 2. Capture the ACTUAL rendered screenshot at the same viewport size, driving the browser your harness actually has. Where a code cell can reach a browser (`new Bun.WebView()` on a Bun >= 1.4 kernel, otherwise `playwright-core` against the local Chrome), capture in-process: it needs no CLI and returns the PNG path directly. In Codex, `browser:control-in-app-browser` is that in-process surface — use it first unless the page needs an authenticated user browser session. Otherwise use the project's configured browser tooling (the playwright, agent-browser, or dev-browser skill). Save as PNG. If nothing is available, install [agent-browser](https://github.com/vercel-labs/agent-browser) (`bun add -g agent-browser && agent-browser install`) and capture with it — see `$SKILL_DIR/references/agent-browser-setup.md` for the full setup, including how to shoot a fixed-viewport screenshot.
76
+ 2. Capture the ACTUAL rendered screenshot at the reference viewport. Use two browser tiers from js eval: (1) `new Bun.WebView()` on Bun >= 1.4 (macOS default; Linux/Windows need installed Chrome/Chromium/Edge); (2) otherwise, or for Chrome semantics, stealth, trace, or authenticated profiles, WRITE a `playwright-core` script and run it from the kernel against local Chrome (`chromium.launch({ channel: "chrome" })` / `launchPersistentContext` on a CLONED profile, never the live one). In Codex, prefer `browser:control-in-app-browser` for ordinary captures. Save PNG and return its path; close the browser context. See `$SKILL_DIR/references/browser-setup.md` for fixed-viewport examples and prerequisites.
77
77
  3. Run the diff and keep the JSON:
78
78
 
79
79
  ```
@@ -0,0 +1,75 @@
1
+ # Browser setup (Web capture)
2
+
3
+ Use the js-eval kernel for both tiers. In Codex, prefer
4
+ `browser:control-in-app-browser` for ordinary captures.
5
+
6
+ ## Tier 1: Bun.WebView
7
+
8
+ On a Bun >= 1.4 kernel, `new Bun.WebView()` is the macOS default (system
9
+ WebKit, no browser download). Linux/Windows require `backend: "chrome"`
10
+ and installed Chrome/Chromium/Edge. WebView is headless; WebKit has no CDP,
11
+ and `type()` emits no keyboard events. Use tier 2 when these differences matter.
12
+
13
+ ```js
14
+ // js-eval cell; url and pngPath belong to this QA run.
15
+ const view = new Bun.WebView({ width: 1280, height: 720 })
16
+ try {
17
+ await view.navigate(url)
18
+ await Bun.write(pngPath, await view.screenshot())
19
+ console.log(pngPath)
20
+ } finally {
21
+ view[Symbol.dispose]()
22
+ }
23
+ ```
24
+
25
+ ## Tier 2: playwright-core with local Chrome
26
+
27
+ For other kernels, real-Chrome semantics, stealth, traces, or authenticated
28
+ profiles, WRITE a script beside the project's installed `playwright-core`
29
+ dependency and execute it from js eval. The user installs `playwright-core`
30
+ once with `bun add playwright-core` if needed; Chrome must already exist.
31
+ No managed browser download is needed.
32
+
33
+ ```js
34
+ // capture.mjs
35
+ import { chromium } from "playwright-core"
36
+ const [url, pngPath] = process.argv.slice(2)
37
+ const browser = await chromium.launch({ channel: "chrome", headless: true })
38
+ try {
39
+ const page = await browser.newPage({ viewport: { width: 1280, height: 720 }, deviceScaleFactor: 1 })
40
+ await page.goto(url, { waitUntil: "load", timeout: 30000 })
41
+ await page.screenshot({ path: pngPath })
42
+ console.log(pngPath)
43
+ } finally {
44
+ await browser.close()
45
+ }
46
+ ```
47
+
48
+ Run from the js-eval kernel (also works on a Node kernel):
49
+
50
+ ```js
51
+ const { promisify } = await import("node:util")
52
+ const { execFile } = await import("node:child_process")
53
+ const result = await promisify(execFile)("node", [scriptPath, url, pngPath], { timeout: 45000 })
54
+ console.log(result.stdout)
55
+ ```
56
+
57
+ For auth, CLONE the user-data directory to a private task-owned directory
58
+ and use `chromium.launchPersistentContext(clonePath, { channel: "chrome" })`.
59
+ NEVER launch against or clear cookies/cache/site data from the live profile.
60
+ Close the context and remove only the clone after QA. For script-based stealth,
61
+ read the ultimate-browsing skill's `references/chrome-stealth.md`.
62
+
63
+ ## Capture a screenshot at a fixed viewport
64
+
65
+ Match CSS viewport AND PNG dimensions: WebKit follows native display scale
66
+ (a 1280x720 viewport can yield 2560x1440 pixels). Use matching reference
67
+ captures or Chrome's `deviceScaleFactor`, not resizing to force a pass.
68
+ Wait for the specific page state, not a sleep, then compare:
69
+
70
+ ```sh
71
+ node "$SKILL_DIR/scripts/visual-qa.mjs" image-diff reference.png actual.png
72
+ ```
73
+
74
+ Inspect `dimensionsMatch` and `diffRatio`, then inspect the image. Close every
75
+ WebView/browser context and the fixture server, even on a failed capture.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // omo-codex-install:6df5dbbbb7ca9b9dce86fae98a525a9caa7de96caed85a4b77d4e8b4ab4d1501:205e3b91b12b465ff20c412c1ae0f8bf179eb3523234e475875924abeb015bd4
2
+ // omo-codex-install:6df5dbbbb7ca9b9dce86fae98a525a9caa7de96caed85a4b77d4e8b4ab4d1501:9b64e23f577a752e30550d1f643f52fe0f27897bd70bc633db60eb57deab9827
3
3
  var __esm = (fn, res, err) => () => {
4
4
  if (fn)
5
5
  try {
@@ -7706,7 +7706,7 @@ var package_default;
7706
7706
  var init_package = __esm(() => {
7707
7707
  package_default = {
7708
7708
  name: "@oh-my-opencode/omo-codex",
7709
- version: "5.0.0-beta.62",
7709
+ version: "5.0.0-beta.63",
7710
7710
  type: "module",
7711
7711
  private: true,
7712
7712
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -13271,6 +13271,7 @@ var OmoTaskSettingsSchema = object({
13271
13271
  model_concurrency: record(string2(), number2().int().nonnegative()).optional(),
13272
13272
  max_depth: number2().int().nonnegative().default(1),
13273
13273
  residency_max_children: ResidencyMaxChildrenInputSchema.default(8),
13274
+ resident_idle_timeout_ms: number2().int().positive().max(Number.MAX_SAFE_INTEGER).default(900000),
13274
13275
  ttl_ms: number2().int().positive().default(86400000),
13275
13276
  state_dir: string2().optional(),
13276
13277
  reattach_on_reconcile: boolean2().optional(),
@@ -13315,6 +13316,7 @@ var OmoTaskSettingsLayerSchema = object({
13315
13316
  model_concurrency: record(string2(), number2().int().nonnegative()).optional(),
13316
13317
  max_depth: number2().int().nonnegative().optional(),
13317
13318
  residency_max_children: ResidencyMaxChildrenInputSchema.optional(),
13319
+ resident_idle_timeout_ms: number2().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
13318
13320
  ttl_ms: number2().int().positive().optional(),
13319
13321
  state_dir: string2().optional(),
13320
13322
  reattach_on_reconcile: boolean2().optional(),
@@ -62,16 +62,17 @@ exercises the surface; capture the artifact.
62
62
  for color / layout / CJK evidence, which degrades truecolor.
63
63
  3. Browser use — in Codex, use `browser:control-in-app-browser`
64
64
  first when available and no authenticated/persistent user browser
65
- profile is required. Otherwise use Chrome to drive the REAL page;
66
- if Chrome is not available, download and use agent-browser
67
- (https://github.com/vercel-labs/agent-browser). Capture action
65
+ profile is required. Otherwise, or for Chrome semantics, stealth,
66
+ or trace, WRITE a `playwright-core` script and run it from js eval
67
+ against local Chrome (`chromium.launch({ channel: "chrome" })` /
68
+ `launchPersistentContext` on a CLONED profile). Capture action
68
69
  log + screenshot path. Never downgrade to a non-browser surface
69
70
  for a browser-facing criterion. NEVER clear cookies, cache, or
70
71
  site data (`Network.clearBrowserCookies`, `Storage.clearCookies`,
71
72
  `chrome.browsingData.remove`, "clear browsing data") on the user's
72
73
  real/main browser profile — it wipes their logged-in state. If you
73
74
  need that profile's login state, clone it first (`rsync -a
74
- <profile>/ <tmp-clone>/`) and launch Chrome / agent-browser against
75
+ <profile>/ <tmp-clone>/`) and launch Chrome against
75
76
  the clone as the user-data-dir; run any clearing there only.
76
77
  4. Computer use — when the surface is a desktop/GUI app rather than a
77
78
  page, drive it via OS-level automation (a computer-use agent,
@@ -11,6 +11,18 @@ This skill ships a Python wrapper at `scripts/ast_grep_helper.py` and platform i
11
11
 
12
12
  ---
13
13
 
14
+ ## OmO native: the ast-grep MCP tools (fastest path, no CLI needed)
15
+
16
+ OmO native also registers a bundled ast-grep MCP server. Its three tools are **deferred**: they are absent from the resident tool list and activate automatically the first time you call them by name — no `tool_search` round trip needed.
17
+
18
+ - `mcp__ast_grep_search({ pattern, language, paths })` — AST-shape search, the MCP equivalent of `sg run -p`. Prefer this over shelling out to `sg` for one-off lookups: no install, no PATH issues.
19
+ - `mcp__ast_grep_rewrite({ pattern, rewrite, language, paths, apply })` — preview matches (`apply: false`, the default) or apply the rewrite (`apply: true`). Same two-pass discipline as `sg run -r`: preview first, then apply.
20
+ - `mcp__ast_grep_scan({ paths })` — run project YAML rules (`sgconfig.yml`, `rules/`), the MCP equivalent of `sg scan`.
21
+
22
+ Same pattern language as the CLI: `$VAR` matches one AST node, `$$$VAR` matches zero or more, and the pattern is code, not regex. `paths` accepts a file or directory list; `language` is required for patterns that are ambiguous across languages.
23
+
24
+ ---
25
+
14
26
  ## When to use this skill
15
27
 
16
28
  Use it whenever the user's question is about **code structure**, not bytes:
@@ -1,194 +1,112 @@
1
- # Playwright CLI — Browser QA That Actually Drives a Browser
1
+ # Browser QA — Scripts from js eval
2
2
 
3
- **https://playwright.dev/ · https://github.com/microsoft/playwright**
4
-
5
- For any browser-served web UI bug, this is the correct tool. Not curl. Not imagination. Not a headless HTTP library. A real browser with a real rendering engine, real JS execution, real cookies, real service workers, real viewport.
6
-
7
- **In Phase 8 Manual QA for browser products, using Playwright is not optional.** Curl cannot catch: CSS that breaks at specific viewport widths, hydration mismatches, client-side router bugs, cookie/session interactions, service-worker caching, JS-triggered navigations. All of those are common bug classes. Drive a browser.
8
-
9
- > Note: `microsoft/playwright-cli` is the legacy repo; the current tooling lives in `@playwright/test` (npm) and `playwright` (pip), which include the `playwright` CLI. Use those — the legacy `playwright-cli` package is deprecated.
10
-
11
- ---
3
+ A browser UI bug needs a rendered browser, not curl. Use two tiers from the
4
+ js-eval kernel: `new Bun.WebView()` on Bun >= 1.4 for ordinary captures (macOS
5
+ uses WebKit; Linux/Windows need installed Chrome/Chromium/Edge), otherwise a
6
+ written `playwright-core` script against local Chrome. Use the script tier for
7
+ Chrome semantics, stealth, traces, keyboard events, or authenticated profiles.
8
+ In Codex, prefer `browser:control-in-app-browser` for ordinary page control.
12
9
 
13
10
  ## When to reach for Playwright
14
11
 
15
- | Bug symptom | Use Playwright? |
16
- |---|---|
17
- | Form submit produces wrong result | ✅ — Playwright drives the form exactly as a user does |
18
- | Page blank in prod, fine locally | ✅ — hydration/env differences need a real browser |
19
- | CSS looks wrong at a specific width | ✅ — use `--viewport-size` |
20
- | Click doesn't fire / wrong handler | ✅ — Playwright fires real DOM events |
21
- | Flash of unstyled content / loading glitch | ✅ — use trace viewer to see frames |
22
- | API returns wrong data | ❌ — use curl, this isn't a browser bug |
23
- | Backend returns wrong status code | ❌ — use curl |
24
- | Client hits a URL that returns 500 | ✅ but also ❌ — Playwright shows the call + response + failure effect on UI |
25
-
26
- ---
12
+ Use the script tier for forms, hydration, responsive CSS, cookie/session flows,
13
+ service workers, or client-side navigation. For a backend-only status/body bug,
14
+ use HTTP. WebView is headless, WebKit has no CDP, and `type()` emits no keyboard
15
+ events; choose real Chrome when these distinctions affect the reproduction.
27
16
 
28
17
  ## Install (per-project)
29
18
 
30
- Playwright installs browser binaries separately from the npm package.
31
-
32
- ```bash
33
- # In the project
34
- npm init playwright@latest # interactive; picks TS/JS + browsers + config
35
- # Or if Playwright is already a dep:
36
- npx playwright install # downloads browsers
37
- npx playwright install chromium # just chromium
38
- npx playwright install --with-deps # also installs OS deps (Linux)
39
- ```
40
-
41
- Python:
42
- ```bash
43
- pip install playwright
44
- playwright install
45
- ```
19
+ Reuse installed `playwright-core`. If absent, the user can install the script
20
+ dependency once with `bun add playwright-core`. Chrome must already be installed;
21
+ report an absent executable rather than downloading a managed browser. Write the
22
+ script beside the dependency so normal module resolution works.
46
23
 
47
- ---
24
+ For stealth, use the ultimate-browsing reference `references/chrome-stealth.md`:
25
+ its optional plugins are user-installed once in the engine directory and executed
26
+ as a script, not injected into WebView.
48
27
 
49
28
  ## The four things you'll actually use
50
29
 
51
- ### 1. `codegen` — record a session, generate the script
52
-
53
- The fastest way to create a repro. Opens a real browser; your clicks / typing become a Playwright script you can paste into a test.
54
-
55
- ```bash
56
- npx playwright codegen https://your-app.local
57
- npx playwright codegen --viewport-size=375,667 https://your-app.local # iPhone SE size
58
- npx playwright codegen --device="iPhone 14" https://your-app.local
59
- ```
60
-
61
- Click / type / navigate in the browser; watch the script build in the side panel. Copy the generated script into your journal as the repro for Phase 8.
62
-
63
- ### 2. A one-shot Playwright script — reproduce + capture
64
-
65
- Usually the Phase 8 QA artifact. Save to `/tmp/debug-repro.spec.ts` (journal it):
66
-
67
- ```ts
68
- // /tmp/debug-repro.spec.ts
69
- import { test, expect } from '@playwright/test';
70
-
71
- test('refinement chat shows non-empty response when env var set', async ({ page }) => {
72
- await page.goto('http://localhost:3000/chat');
73
- await page.fill('textarea[name="message"]', 'Add a logging step');
74
- await page.click('button[type=submit]');
75
-
76
- // Wait for the response to appear (not just the spinner to disappear)
77
- const response = page.locator('[data-testid="assistant-reply"]');
78
- await expect(response).toBeVisible({ timeout: 30_000 });
79
- await expect(response).not.toBeEmpty();
80
-
81
- // Capture evidence
82
- await page.screenshot({ path: '/tmp/debug-after-fix.png', fullPage: true });
83
- console.log(await response.textContent());
84
- });
85
- ```
86
-
87
- Run it with tracing enabled for rich post-mortem:
88
-
89
- ```bash
90
- npx playwright test /tmp/debug-repro.spec.ts --trace on --headed
91
- ```
92
-
93
- ### 3. `PWDEBUG=1` — step through the script with Playwright Inspector
94
-
95
- ```bash
96
- PWDEBUG=1 npx playwright test /tmp/debug-repro.spec.ts
30
+ ### 1. Write a reproduction script
31
+
32
+ Record the exact URL, inputs, viewport, expected UI state, and output artifact.
33
+ For auth, CLONE the user-data directory and use `launchPersistentContext` on the
34
+ clone. NEVER launch against or clear data from the live profile.
35
+
36
+ ### 2. Reproduce + capture
37
+
38
+ ```js
39
+ // debug-repro.mjs
40
+ import { chromium } from 'playwright-core';
41
+ const [url, pngPath, tracePath] = process.argv.slice(2);
42
+ const browser = await chromium.launch({ channel: 'chrome', headless: true });
43
+ try {
44
+ const context = await browser.newContext({ viewport: { width: 1280, height: 720 } });
45
+ await context.tracing.start({ screenshots: true, snapshots: true });
46
+ try {
47
+ const page = await context.newPage();
48
+ page.on('pageerror', error => console.error(error));
49
+ await page.goto(url, { waitUntil: 'load', timeout: 30000 });
50
+ // Add the scenario's actions and locator/state assertions here.
51
+ await page.screenshot({ path: pngPath });
52
+ console.log(pngPath);
53
+ } finally {
54
+ await context.tracing.stop({ path: tracePath });
55
+ await context.close();
56
+ }
57
+ } finally {
58
+ await browser.close();
59
+ }
97
60
  ```
98
61
 
99
- Opens the Playwright Inspector alongside the browser. You can step through Playwright actions, see the DOM state at each step, and edit selectors on the fly.
100
-
101
- Use this when the script doesn't reproduce cleanly and you need to watch it run.
62
+ A screenshot alone is not a reproduction assertion. Use locators for the exact
63
+ observable state; fail the script when that state is absent.
102
64
 
103
- ### 4. `show-trace` — post-mortem on a failed run
65
+ ### 3. Run from the js-eval kernel
104
66
 
105
- ```bash
106
- npx playwright show-trace trace.zip
107
- # or from the test-results dir:
108
- npx playwright show-trace test-results/<test-name>/trace.zip
67
+ ```js
68
+ const { promisify } = await import('node:util')
69
+ const { execFile } = await import('node:child_process')
70
+ const result = await promisify(execFile)('node', [scriptPath, url, pngPath, tracePath], { timeout: 60000 })
71
+ console.log(result.stdout)
109
72
  ```
110
73
 
111
- Scrubs through a recorded session: timeline, DOM snapshot at each action, network, console, source. When a test failed on CI but passed locally, this is the single best artifact.
74
+ ### 4. Inspect the trace
112
75
 
113
- ---
76
+ Retain the trace ZIP for the project's existing trace viewer and inspect the PNG.
77
+ Trace snapshots, network events, and screenshots identify where the UI diverged.
78
+ Keep auth-bearing traces private; do not upload them to public viewers.
114
79
 
115
80
  ## Headless vs headed during debugging
116
81
 
117
- Always add `--headed` when debugging. Headless browsers sometimes behave subtly differently (font rendering, viewport, media permissions). For QA evidence, run headed and screenshot.
118
-
119
- ```bash
120
- npx playwright test --headed
121
- npx playwright test --headed --project=chromium # pin the browser
122
- ```
123
-
124
- ---
82
+ Use `headless: false` with an available display when reproducing headed-only
83
+ behavior. State which mode produced the evidence; do not claim a headless capture
84
+ proves desktop-browser permissions or window behavior.
125
85
 
126
86
  ## Catching the silent-failure patterns Playwright is good at
127
87
 
128
- ```ts
129
- // Toast that flashes and disappears
130
- page.on('console', msg => console.log('[browser console]', msg.type(), msg.text()));
131
-
132
- // Unhandled page errors (uncaught exceptions in the page JS)
133
- page.on('pageerror', err => console.error('[page error]', err));
134
-
135
- // Network failures — e.g., backend returned 500 but UI shows nothing
136
- page.on('response', async resp => {
137
- if (!resp.ok()) {
138
- console.warn(`[network ${resp.status()}] ${resp.url()} — ${await resp.text()}`);
139
- }
140
- });
141
-
142
- // Request that never came back
143
- page.on('requestfailed', req => {
144
- console.error('[request failed]', req.url(), req.failure()?.errorText);
145
- });
146
- ```
147
-
148
- Add these listeners to the top of the debug script. They surface a lot of the "UI showed nothing" class of bug.
149
-
150
- ---
88
+ Subscribe before triggering the action: `page.on('pageerror', ...)`,
89
+ `page.on('requestfailed', ...)`, or a bounded `page.waitForResponse(...)` promise.
90
+ Await that specific response/state rather than sleeping or waiting for generic
91
+ network idleness. Propagate failed assertions and process exit codes.
151
92
 
152
93
  ## Viewport and device emulation
153
94
 
154
- CSS bugs that only appear at specific sizes, or layout bugs on mobile:
155
-
156
- ```ts
157
- // At test level
158
- test.use({ viewport: { width: 375, height: 667 } });
159
-
160
- // Per-page
161
- await page.setViewportSize({ width: 375, height: 667 });
162
-
163
- // Predefined devices
164
- import { devices } from '@playwright/test';
165
- test.use({ ...devices['iPhone 14'] });
166
- ```
167
-
168
- ---
95
+ Use `page.setViewportSize({ width: 375, height: 667 })` for a narrow capture.
96
+ `devices` comes from `playwright-core`; apply the desired preset when creating
97
+ a context. Match the reference's pixel scale as well as its viewport.
169
98
 
170
99
  ## Gotchas
171
100
 
172
- - **Wait for state, not for time.** `await page.waitForTimeout(2000)` is flaky. Use `await expect(locator).toBeVisible()` or `page.waitForResponse(urlPattern)`.
173
- - **Stale selectors re-resolve.** Playwright's locators re-find the element on each action, unlike Puppeteer's handles. Don't over-think it.
174
- - **Service workers persist across test runs in headed mode.** If you see cached behavior from a previous run, add `await context.clearCookies()` + clear storage before the test.
175
- - **Installing on CI requires `--with-deps`** on Linux images that lack the browser's shared-library deps.
176
- - **Parallel tests share a browser process by default**; if one test polls a debugger port, others may interfere. Use `workers: 1` for debugging.
177
-
178
- ---
101
+ - Wait for state, not time: locator visibility or the exact response is the signal.
102
+ - Locators re-resolve after UI changes; stale element handles do not.
103
+ - Fresh task-owned contexts avoid cached state leaking between runs.
104
+ - Auth belongs in a private clone, never the live browser profile.
105
+ - Give every run its own output directory and bounded process lifetime.
179
106
 
180
107
  ## Phase 9 cleanup specifics
181
108
 
182
- ```bash
183
- # Remove trace files from debug runs
184
- rm -rf playwright-report/ test-results/ trace.zip
185
-
186
- # Remove debug spec files from /tmp
187
- rm -f /tmp/debug-*.spec.ts
188
-
189
- # Remove screenshot captures
190
- rm -f /tmp/debug-*.png
191
-
192
- # If you installed browsers just for this session (rare):
193
- # Don't remove them — they're useful for future sessions. They live in ~/Library/Caches/ms-playwright (macOS) or ~/.cache/ms-playwright (Linux).
194
- ```
109
+ Close WebView/browser contexts even on failure, stop the fixture server, and remove
110
+ only this run's temporary scripts and profile clone. Preserve requested PNG/trace
111
+ artifacts, then record the cleanup receipt. Do not kill unrelated browsers or
112
+ remove a user's installed Chrome.
@@ -146,7 +146,7 @@ Domains: `product` `style` `typography` `color` `landing` `chart` `ux` `react` `
146
146
  | Situation | Load |
147
147
  |---|---|
148
148
  | Brand/style not among the 70 in `references/design/`, or the user says "Open Design" | `open-design` skill — the local nexu-io/open-design library (137+ design skills, 150+ design systems) |
149
- | Driving a browser for the Design QA phase | `agent-browser` skill |
149
+ | Driving a browser for the Design QA phase | `visual-qa` skill: Bun.WebView / local-Chrome `playwright-core` scripts from js eval; Codex in-app browser |
150
150
  | Pure TypeScript/logic work with zero visual surface | `programming` skill alone — this skill adds nothing there |
151
151
 
152
152
  ## Activation
@@ -1,7 +1,7 @@
1
1
  # Design System Inspired by Aside
2
2
 
3
3
  > Category: Developer Tools & IDEs
4
- > AI browser agent. Bright product-app marketing, custom display type, soft squircle controls, agent-browser product framing.
4
+ > AI browser agent. Bright product-app marketing, custom display type, soft squircle controls, browser-product framing.
5
5
 
6
6
  ## Provenance
7
7
 
@@ -8,7 +8,7 @@ A `DESIGN.md` whose every token, interaction state, and motion value was read fr
8
8
 
9
9
  ## Phase 1 — Extract the runtime truth (never guess a value)
10
10
 
11
- Drive a real browser: Codex `browser:control-in-app-browser` first, otherwise the project's `agent-browser` / playwright / dev-browser tooling. Do NOT parse CSS files — minification, CORS, CSS-in-JS, and Tailwind utilities make source unreliable. `getComputedStyle` returns what the browser ACTUALLY rendered, so it is the only source of truth.
11
+ Drive a real browser from js eval: `new Bun.WebView()` on Bun >= 1.4 (macOS default; Linux/Windows need installed Chrome/Chromium/Edge), otherwise write and run a `playwright-core` script against local Chrome (`channel: "chrome"`). Use that script lane for Chrome semantics, stealth, trace, or auth, with persistent contexts on CLONED profiles only. Codex: `browser:control-in-app-browser`. Do NOT parse CSS files — minification, CORS, CSS-in-JS, and Tailwind utilities make source unreliable. `getComputedStyle` returns what the browser ACTUALLY rendered, so it is the only source of truth.
12
12
 
13
13
  Sweep the page and read, for every meaningful element and every repeated pattern:
14
14
 
@@ -11,8 +11,8 @@
11
11
  # ─── How to run ───
12
12
  # 1. Install uv (if not installed):
13
13
  # curl -LsSf https://astral.sh/uv/install.sh | sh
14
- # 2. Install Playwright browsers (one-time):
15
- # uv run --with playwright python -m playwright install chromium
14
+ # 2. Chrome must already be installed locally:
15
+ # The script uses channel="chrome"; it downloads no browser.
16
16
  # 3. Run:
17
17
  # uv run lighthouse-audit.py https://example.com
18
18
  # uv run lighthouse-audit.py https://example.com --desktop-only
@@ -127,7 +127,7 @@ You are the QA lane. Do not delegate hands-on QA to a sub-agent: the orchestrato
127
127
  2. **Pick the channel that faithfully exercises the surface** and capture the artifact:
128
128
  - HTTP: `curl -i` (or an API request context) - status line, headers, body.
129
129
  - CLI / TUI: a real pty - drive the command and keep the transcript; for color or layout evidence render through a browser-based terminal, never a `tmux capture-pane` dump.
130
- - Web: the real page in a real browser - the harness's in-process surface (a `Bun.WebView` / `playwright-core` code cell, or Codex's Browser plugin) or the agent-browser CLI - action log plus screenshot.
130
+ - Web: from js eval, use `new Bun.WebView()` on Bun >= 1.4 (macOS default; Linux/Windows need Chrome/Chromium/Edge). Otherwise, or for Chrome semantics, stealth, trace, or auth, write and run a `playwright-core` script against local Chrome (`channel: "chrome"`; persistent context on a CLONED profile). Codex: `browser:control-in-app-browser`. Capture action log plus screenshot.
131
131
  - Desktop / GUI: OS-level automation against the running app - action log plus screenshot.
132
132
  - Library / SDK: a script that imports and exercises the public API - transcript.
133
133
  - Data-shaped work (migrations, configs, generated files): the resulting artifact itself, diffed or dumped.