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

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 (249) 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 +70 -41
  4. package/dist/cli-node/index.js +70 -41
  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 +89 -588
  10. package/dist/oh-my-opencode.schema.json +4 -5
  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 +18 -11
  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 +4 -2
  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-codex-validation.d.ts +7 -5
  68. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +7 -2
  69. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +7 -4
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +931 -442
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +6 -0
  72. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +20 -12
  73. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +8 -0
  74. package/packages/omo-codex/plugin/components/ulw-loop/dist/driver-objective-ack.d.ts +4 -0
  75. package/packages/omo-codex/plugin/components/ulw-loop/dist/driver-objective-ack.js +18 -0
  76. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence-artifacts.d.ts +1 -0
  77. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence-artifacts.js +37 -0
  78. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.d.ts +1 -0
  79. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.js +24 -12
  80. package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.d.ts +4 -0
  81. package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.js +34 -0
  82. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +1 -0
  83. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +6 -0
  84. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.d.ts +19 -0
  85. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.js +107 -0
  86. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +6 -2
  87. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +54 -25
  88. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-goal-factory.d.ts +10 -3
  89. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-goal-factory.js +38 -31
  90. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +9 -7
  91. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +105 -114
  92. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.d.ts +15 -0
  93. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.js +86 -0
  94. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +5 -1
  95. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +15 -3
  96. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +11 -8
  97. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.js +28 -12
  98. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.d.ts +335 -0
  99. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.js +109 -10
  100. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.d.ts +3 -0
  101. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-budget-io.d.ts +5 -0
  102. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-budget-io.js +67 -0
  103. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +8 -62
  104. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +11 -1
  105. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +120 -88
  106. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +3 -2
  107. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +18 -10
  108. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +4 -4
  109. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +3 -2
  110. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +4 -4
  111. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +9 -1
  112. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.d.ts +3 -2
  113. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +11 -11
  114. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +8 -17
  115. package/packages/omo-codex/plugin/components/ulw-loop/dist/success-criteria-input.d.ts +9 -0
  116. package/packages/omo-codex/plugin/components/ulw-loop/dist/success-criteria-input.js +41 -0
  117. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  118. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  119. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
  120. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +15 -3
  121. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +7 -4
  122. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +26 -14
  123. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +8 -0
  124. package/packages/omo-codex/plugin/components/ulw-loop/src/driver-objective-ack.ts +20 -0
  125. package/packages/omo-codex/plugin/components/ulw-loop/src/evidence-artifacts.ts +45 -0
  126. package/packages/omo-codex/plugin/components/ulw-loop/src/evidence.ts +23 -16
  127. package/packages/omo-codex/plugin/components/ulw-loop/src/ledger.ts +33 -0
  128. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +7 -0
  129. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-commit.ts +124 -0
  130. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +67 -54
  131. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-goal-factory.ts +63 -31
  132. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +126 -140
  133. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-log.ts +84 -0
  134. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +26 -3
  135. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +11 -7
  136. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/factory.ts +47 -12
  137. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/manifest.ts +124 -10
  138. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/types.ts +3 -0
  139. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-budget-io.ts +59 -0
  140. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +8 -59
  141. package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +129 -111
  142. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +19 -10
  143. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +4 -4
  144. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +5 -4
  145. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-types.ts +13 -1
  146. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +12 -10
  147. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +8 -16
  148. package/packages/omo-codex/plugin/components/ulw-loop/src/success-criteria-input.ts +56 -0
  149. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +37 -1
  150. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/barrier.ts +13 -0
  151. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-child.ts +65 -0
  152. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-cli-qa.mjs +76 -0
  153. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-crash.ts +23 -0
  154. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-mutations.mjs +58 -0
  155. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-writer.ts +65 -0
  156. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/lease-clock.ts +23 -0
  157. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-commit-log.test.ts +252 -0
  158. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-commit-recovery.test.ts +190 -0
  159. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +50 -35
  160. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-log-newest.test.ts +72 -0
  161. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-completed-plan.test.ts +43 -0
  162. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-driver-states.test.ts +33 -4
  163. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-dx.test.ts +219 -0
  164. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-session-context.test.ts +21 -0
  165. package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +92 -0
  166. package/packages/omo-codex/plugin/components/ulw-loop/test/status-next-actions-surface.test.ts +133 -0
  167. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +12 -12
  168. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +4 -1
  169. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  170. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  171. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  172. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  173. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  174. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  175. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  176. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  177. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  178. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  184. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  185. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  186. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  187. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  188. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  189. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  190. package/packages/omo-codex/plugin/package-lock.json +12 -12
  191. package/packages/omo-codex/plugin/package.json +1 -1
  192. package/packages/omo-codex/plugin/scripts/sync-skills.d.mts +4 -0
  193. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +15 -7
  194. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +12 -0
  195. package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +79 -161
  196. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
  197. package/packages/omo-codex/plugin/skills/frontend/references/design/aside.md +1 -1
  198. package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +1 -1
  199. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
  200. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  201. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
  202. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +17 -29
  203. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +2 -1
  204. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +2 -2
  205. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
  206. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
  207. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
  208. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
  209. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
  210. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -3
  211. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
  212. package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
  213. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +5 -4
  214. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +1 -1
  215. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
  216. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +3 -3
  217. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +1 -1
  218. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +1 -1
  219. package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +75 -0
  220. package/packages/omo-codex/scripts/install-dist/install-local.mjs +6 -4
  221. package/packages/prompts-core/prompts/ultrawork/codex.md +5 -4
  222. package/packages/shared-skills/skills/ast-grep/SKILL.md +12 -0
  223. package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +79 -161
  224. package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
  225. package/packages/shared-skills/skills/frontend/references/design/aside.md +1 -1
  226. package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +1 -1
  227. package/packages/shared-skills/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
  228. package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
  229. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
  230. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +17 -29
  231. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +2 -1
  232. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +2 -2
  233. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
  234. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
  235. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
  236. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
  237. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
  238. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -3
  239. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
  240. package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
  241. package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
  242. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  243. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
  244. package/packages/shared-skills/skills/visual-qa/AGENTS.md +1 -1
  245. package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
  246. package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +75 -0
  247. package/dist/skills/visual-qa/references/agent-browser-setup.md +0 -45
  248. package/packages/omo-codex/plugin/skills/visual-qa/references/agent-browser-setup.md +0 -45
  249. package/packages/shared-skills/skills/visual-qa/references/agent-browser-setup.md +0 -45
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: ultimate-browsing
3
- description: "Reaches web pages a plain fetch cannot: renders JS, drives clicks and forms, captures screenshots, holds a login, and gets past WAF blocks through platform-native readers and stealth Chrome. Use for any page work beyond retrieving static text."
3
+ description: "Renders, drives, and screenshots web pages: JS-rendered sources, clicks and forms, persistent logins, WAF-blocked hosts (platform-native readers, stealth Chrome), and the browsing lane of a research run, with screenshots as provenance. Not for plain search or unblocked static fetch."
4
4
  ---
5
5
 
6
6
  # Ultimate Browsing
7
7
 
8
8
  Web access for everything a plain fetch cannot finish: a page that renders in JS, a click or a form, a screenshot, a login that must persist across pages, or a host that blocks generic fetchers (WAF / 403 / Cloudflare). Start at the cheapest tier that can do the job and climb only when it cannot:
9
9
 
10
- **Tier 1 — insane-search** (headless extraction + WAF bypass) -> **Tier 1.5 — agent-reach** (platform-native APIs, esp. Chinese platforms) -> **Tier 2 — a real browser**: 2a a code-driven kernel browser, 2b Chrome stealth (CloakBrowser + agent-browser) when the page fights back.
10
+ **Tier 1 — insane-search** (headless extraction + WAF bypass) -> **Tier 1.5 — agent-reach** (platform-native APIs, esp. Chinese platforms) -> **Tier 2 — a real browser**: 2a Bun.WebView, 2b a local-Chrome `playwright-core` script from js eval for Chrome semantics, stealth, trace, or auth.
11
11
 
12
12
  ## PHASE 0 — ROUTE FIRST (MANDATORY)
13
13
 
@@ -86,33 +86,26 @@ Routing table, per-platform auth (set `TWITTER_*` env vars, `gh auth login`, a t
86
86
 
87
87
  ### Tier 2a — kernel browser (default)
88
88
 
89
- Drive the page from the code cell you are already in, with no CLI process and no open CDP port. On a Bun >= 1.4 runtime that is `new Bun.WebView()` (`navigate`, `click`, `type`, `evaluate`, `screenshot`, raw `cdp`); elsewhere it is `playwright-core`/`puppeteer-core` against the local Chrome. Snapshots and screenshots come back in-process, so this is the cheapest way to answer "what does the page actually render".
89
+ Use `new Bun.WebView()` from the js-eval kernel on Bun >= 1.4: macOS defaults to system WebKit; Linux/Windows need installed Chrome/Chromium/Edge. WebView is headless, WebKit has no CDP, and `type()` emits no keyboard events. For other kernels or when those differences matter, use 2b.
90
90
 
91
91
  ```js
92
- await using view = new Bun.WebView({ width: 1280, height: 800 })
93
- await view.navigate(url)
94
- const title = await view.evaluate("document.title")
95
- await view.screenshot({ path: "/tmp/page.png" })
92
+ const view = new Bun.WebView({ width: 1280, height: 800 })
93
+ try {
94
+ await view.navigate(url)
95
+ const title = await view.evaluate("document.title")
96
+ await Bun.write(pngPath, await view.screenshot())
97
+ } finally {
98
+ view[Symbol.dispose]()
99
+ }
96
100
  ```
97
101
 
98
- Climb to 2b when the site detects automation (Turnstile, FingerprintJS, "unusual traffic"), when the flow needs a persistent logged-in profile or injected cookies, or when the kernel browser cannot reach the page at all.
102
+ Use 2b for real-Chrome semantics, stealth, trace, authenticated profiles, or a page the kernel browser cannot reach.
99
103
 
100
104
  ### Tier 2b — Chrome stealth (blocked or logged-in pages)
101
105
 
102
- CloakBrowser is a stealth Chromium with source-level fingerprint patches that passes Cloudflare Turnstile, FingerprintJS, BrowserScan, and 30+ detectors; agent-browser is the CDP automation CLI that drives it. Both are runtime-installed tools (not vendored here). Full setup, version pins, launch flow, cookie login, and cross-platform notes are in [references/chrome-stealth.md](references/chrome-stealth.md).
106
+ WRITE a `playwright-core` script and run it from js eval against installed local Chrome: `chromium.launch({ channel: "chrome" })`, or `launchPersistentContext` on a task-owned profile. For authenticated state, CLONE the user's profile first (`rsync -a <profile>/ <tmp-clone>/`); NEVER launch against or clear cookies/cache/site data from the live profile. Codex: prefer `browser:control-in-app-browser` for ordinary page control.
103
107
 
104
- NEVER clear cookies, cache, or site data (`Network.clearBrowserCookies`, `Storage.clearCookies`, `chrome.browsingData.remove`, "clear browsing data") on the user's real/main browser profile — it wipes their logged-in state everywhere. If the task needs that profile's login state, clone the profile directory first (`rsync -a <profile>/ <tmp-clone>/`) and launch CloakBrowser / agent-browser with the clone as the user-data-dir; run any clearing on the clone only.
105
-
106
- ```bash
107
- # 1. Launch CloakBrowser with CDP on :9242 (see chrome-stealth.md for install + venv).
108
- # 2. CloakBrowser launches tabless — open the first tab via CDP before any agent-browser command:
109
- curl -s -X PUT "http://127.0.0.1:9242/json/new?https://example.com"
110
- # 3. Drive it with agent-browser over CDP:
111
- agent-browser --cdp 9242 snapshot -i # interactive elements (@eN refs)
112
- agent-browser --cdp 9242 click @e3
113
- agent-browser --cdp 9242 screenshot out.png
114
- agent-browser --cdp 9242 close
115
- ```
108
+ Keep the engine's Playwright templates for script-based extraction. Stealth is optional: the user installs `playwright-extra` + `puppeteer-extra-plugin-stealth` once in the engine directory and the script wraps the `playwright-core` browser type. Setup, persistent-context arguments, screenshots, and cleanup are in [references/chrome-stealth.md](references/chrome-stealth.md). A stealth flag is not proof of access: inspect the rendered result and report challenges that remain.
116
109
 
117
110
  ### Cookie login (cross-platform)
118
111
 
@@ -134,14 +127,11 @@ Cookie export files are written with owner-only `0600` permissions. Do not place
134
127
  |------|-------------|
135
128
  | [references/insane-search/README.md](references/insane-search/README.md) | Tier-1 engine harness (R1-R7, Phase 0 API index, no-site-name rule) + its `*.md` deep-dives |
136
129
  | [references/agent-reach/README.md](references/agent-reach/README.md) | Tier-1.5 routing table, platform auth, per-category `*.md` |
137
- | [references/chrome-stealth.md](references/chrome-stealth.md) | Tier-2 CloakBrowser + agent-browser install, CDP flow, version pins, cookie login |
130
+ | [references/chrome-stealth.md](references/chrome-stealth.md) | Tier-2 playwright-core scripts, optional stealth setup, cloned profiles, cookie login |
138
131
 
139
132
  ## Environment variables
140
133
 
141
134
  ```bash
142
- CLOAK_CDP_PORT=9242 # CloakBrowser CDP port (default 9242)
143
- AGENT_BROWSER_USER_AGENT="..." # override UA to hide HeadlessChrome
144
- AGENT_BROWSER_HEADED=1 # show the browser window
145
135
  # agent-reach auth: set the channel-specific env vars from each tool's docs only if you have access
146
136
  # insane-search needs no env vars — it auto-installs deps on first run
147
137
  ```
@@ -149,9 +139,7 @@ AGENT_BROWSER_HEADED=1 # show the browser window
149
139
  ## Anti-patterns
150
140
 
151
141
  - Do NOT launch Chrome stealth for plain text extraction — use Tier 1.
152
- - Do NOT pass an `--init-script` for the webdriver flag — CloakBrowser already patches it at source; the only required override is `--user-agent`.
153
- - Do NOT run agent-browser before creating the first tab via `curl -X PUT .../json/new` — CloakBrowser launches tabless.
154
- - Do NOT use vanilla Chrome when stealth is needed — always CloakBrowser.
155
- - Do NOT forget to `close` the session when done.
142
+ - Use stealth plugins only in an explicitly installed script environment, not injected into WebView.
143
+ - Close every WebView/browser context when done and remove only task-owned profile clones.
156
144
  - Do NOT inject cookies without reloading the page.
157
145
  - Do NOT hardcode site domains/selectors into `engine/**` or `waf_profiles.yaml` — runtime hints only (see the no-site-name rule in the insane-search reference).
@@ -65,7 +65,8 @@ is a regression, not an upgrade:
65
65
  - **De-personalization** — no personal absolute paths, no personal auth token literals,
66
66
  no personal browser choice; enforced by `depersonalization-gate.test.ts`.
67
67
  - **Skill-level layering** — the engine is Tier 1 under a router that also owns Tier 1.5
68
- (agent-reach) and Tier 2 (CloakBrowser + agent-browser). Upstream has no such tiering.
68
+ (agent-reach) and Tier 2 (Bun.WebView / local-Chrome playwright-core scripts from js eval).
69
+ Upstream has no such tiering.
69
70
 
70
71
  ### WANT — upstream improvements worth porting forward
71
72
 
@@ -2,9 +2,9 @@
2
2
  "name": "insane-search-templates",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
- "description": "Local deps for Playwright real-Chrome templates. npm install && npx playwright install chrome",
5
+ "description": "Script-only dependencies for local Chrome templates driven from js eval; Chrome must already be installed.",
6
6
  "dependencies": {
7
- "playwright": "^1.62.1",
7
+ "playwright-core": "^1.62.1",
8
8
  "playwright-extra": "^4.3.6",
9
9
  "puppeteer-extra-plugin-stealth": "^2.11.2"
10
10
  }
@@ -76,11 +76,12 @@ async function main() {
76
76
  const playwrightExtra = requireOptionalModule('playwright-extra');
77
77
  const stealthPlugin = playwrightExtra ? requireOptionalModule('puppeteer-extra-plugin-stealth') : null;
78
78
  if (playwrightExtra && stealthPlugin) {
79
- ({ chromium, devices } = playwrightExtra);
79
+ ({ devices } = require('playwright-core'));
80
+ chromium = playwrightExtra.addExtra(require('playwright-core').chromium);
80
81
  const stealth = stealthPlugin();
81
82
  chromium.use(stealth);
82
83
  } else {
83
- ({ chromium, devices } = require('playwright'));
84
+ ({ chromium, devices } = require('playwright-core'));
84
85
  }
85
86
 
86
87
  const dev = devices[deviceName];
@@ -94,6 +95,8 @@ async function main() {
94
95
  try {
95
96
  ctx = await chromium.launchPersistentContext(profileDir, {
96
97
  channel: 'chrome',
98
+ args: ['--disable-blink-features=AutomationControlled'],
99
+ ignoreDefaultArgs: ['--enable-automation'],
97
100
  headless,
98
101
  ...dev,
99
102
  });
@@ -10,9 +10,9 @@
10
10
  * NO-SITE-NAME RULE: this file must never branch on specific hostnames.
11
11
  * All site specifics come from the JSON input (url, waitSelector).
12
12
  *
13
- * Dependencies (install once on target machine):
14
- * npm i -g playwright playwright-extra puppeteer-extra-plugin-stealth
15
- * npx playwright install chrome # system Chrome binary
13
+ * User setup: ../../references/chrome-stealth.md (engine-local dependencies).
14
+ * Chrome must already be installed; optional stealth plugins run only in this script.
15
+ * Execute this script from js eval; profileDir must be task-owned or a CLONED profile.
16
16
  */
17
17
 
18
18
  const fs = require('fs');
@@ -82,18 +82,20 @@ async function main() {
82
82
  const playwrightExtra = requireOptionalModule('playwright-extra');
83
83
  const stealthPlugin = playwrightExtra ? requireOptionalModule('puppeteer-extra-plugin-stealth') : null;
84
84
  if (playwrightExtra && stealthPlugin) {
85
- ({ chromium } = playwrightExtra);
85
+ chromium = playwrightExtra.addExtra(require('playwright-core').chromium);
86
86
  const stealth = stealthPlugin();
87
87
  chromium.use(stealth);
88
88
  } else {
89
- // Fallback to plain playwright (no stealth). Still uses channel:chrome.
90
- ({ chromium } = require('playwright'));
89
+ // Core controls installed Chrome without downloading a managed browser.
90
+ ({ chromium } = require('playwright-core'));
91
91
  }
92
92
 
93
93
  let ctx;
94
94
  try {
95
95
  ctx = await chromium.launchPersistentContext(profileDir, {
96
96
  channel: 'chrome', // real Chrome, not bundled Chromium
97
+ args: ['--disable-blink-features=AutomationControlled'],
98
+ ignoreDefaultArgs: ['--enable-automation'],
97
99
  headless,
98
100
  viewport,
99
101
  });
@@ -0,0 +1,86 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import subprocess
6
+ import tempfile
7
+ import unittest
8
+ from pathlib import Path
9
+
10
+ from test_playwright_templates import (
11
+ TEMPLATE_NAMES,
12
+ TEMPLATES_DIR,
13
+ _install_fake_playwright,
14
+ _write_file,
15
+ )
16
+
17
+
18
+ class PlaywrightTemplateStealth(unittest.TestCase):
19
+ def test_extracts_html_and_closes_wrapped_chrome_when_stealth_is_installed(self) -> None:
20
+ for template_name in TEMPLATE_NAMES:
21
+ with self.subTest(template_name=template_name), tempfile.TemporaryDirectory() as tmp:
22
+ # Given: core has no plugin API; only addExtra supplies a registered wrapper.
23
+ root = Path(tmp)
24
+ modules = root / "node_modules"
25
+ profile = root / "profile"
26
+ receipt = root / "launch.json"
27
+ _install_fake_playwright(modules)
28
+ _write_file(modules / "puppeteer-extra-plugin-stealth/index.js", """
29
+ module.exports = () => ({ name: 'stealth' });
30
+ """)
31
+ _write_file(modules / "playwright-extra/index.js", """
32
+ const assert = require('node:assert/strict');
33
+ const fs = require('node:fs');
34
+ exports.addExtra = (core) => {
35
+ assert.equal(core, require('playwright-core').chromium);
36
+ assert.equal(Object.hasOwn(core, 'use'), false);
37
+ const events = ['wrap'];
38
+ let registered = false;
39
+ return {
40
+ use(plugin) {
41
+ assert.equal(plugin.name, 'stealth');
42
+ registered = true;
43
+ events.push(plugin.name);
44
+ },
45
+ async launchPersistentContext(profileDir, options) {
46
+ assert.equal(registered, true);
47
+ events.push({ profileDir, channel: options.channel, viewport: options.viewport });
48
+ const context = await core.launchPersistentContext(profileDir, options);
49
+ return {
50
+ ...context,
51
+ async close() {
52
+ await context.close();
53
+ events.push('close');
54
+ fs.writeFileSync(process.env.STEALTH_RECEIPT, JSON.stringify(events));
55
+ },
56
+ };
57
+ },
58
+ };
59
+ };
60
+ """)
61
+ script = root / template_name
62
+ script.write_bytes((TEMPLATES_DIR / template_name).read_bytes())
63
+ env = {key: value for key, value in os.environ.items() if key != "NODE_PATH"}
64
+ env["STEALTH_RECEIPT"] = str(receipt)
65
+
66
+ # When: the actual bundled entry point consumes its normal stdin protocol.
67
+ result = subprocess.run(
68
+ ["node", str(script)],
69
+ input=json.dumps({"url": "https://example.com/", "profileDir": str(profile), "headless": True}),
70
+ text=True, capture_output=True, timeout=5, env=env, check=False,
71
+ )
72
+
73
+ # Then: HTML arrives through the registered wrapper and the context is closed.
74
+ self.assertEqual(result.returncode, 0, result.stderr)
75
+ self.assertEqual(result.stdout, "<html><article>ok</article></html>")
76
+ self.assertEqual(result.stderr, "")
77
+ viewport = {"width": 390, "height": 844} if "mobile" in template_name else {"width": 1366, "height": 900}
78
+ self.assertEqual(json.loads(receipt.read_text(encoding="utf-8")), [
79
+ "wrap", "stealth",
80
+ {"profileDir": str(profile), "channel": "chrome", "viewport": viewport},
81
+ "close",
82
+ ])
83
+
84
+
85
+ if __name__ == "__main__":
86
+ unittest.main()
@@ -21,7 +21,7 @@ def _write_file(path: Path, content: str) -> None:
21
21
 
22
22
  def _install_fake_playwright(node_modules: Path) -> None:
23
23
  _write_file(
24
- node_modules / "playwright" / "index.js",
24
+ node_modules / "playwright-core" / "index.js",
25
25
  """
26
26
  const page = {
27
27
  async goto() {},
@@ -47,7 +47,6 @@ def _install_fake_playwright(node_modules: Path) -> None:
47
47
  };
48
48
 
49
49
  exports.chromium = {
50
- use() {},
51
50
  async launchPersistentContext() { return context; },
52
51
  };
53
52
  exports.devices = {
@@ -78,9 +77,7 @@ def _install_working_playwright_extra(node_modules: Path) -> None:
78
77
  _write_file(
79
78
  node_modules / "playwright-extra" / "index.js",
80
79
  """
81
- const playwright = require('playwright');
82
- exports.chromium = playwright.chromium;
83
- exports.devices = playwright.devices;
80
+ exports.addExtra = (browserType) => browserType;
84
81
  """,
85
82
  )
86
83
 
@@ -149,7 +146,7 @@ def _run_template(
149
146
 
150
147
  @unittest.skipUnless(shutil.which("node"), "node is required for Playwright template tests")
151
148
  class PlaywrightTemplateErrorHandling(unittest.TestCase):
152
- def test_missing_playwright_extra_warns_and_falls_back_to_plain_playwright(self) -> None:
149
+ def test_missing_playwright_extra_warns_and_falls_back_to_playwright_core(self) -> None:
153
150
  for template_name in TEMPLATE_NAMES:
154
151
  with self.subTest(template_name=template_name):
155
152
  result = _run_template(
@@ -166,7 +163,7 @@ class PlaywrightTemplateErrorHandling(unittest.TestCase):
166
163
  self.assertIn("best-effort optional module playwright-extra failed:", result.stderr)
167
164
  self.assertIn("Cannot find module 'playwright-extra'", result.stderr)
168
165
 
169
- def test_missing_stealth_plugin_warns_and_falls_back_to_plain_playwright(self) -> None:
166
+ def test_missing_stealth_plugin_warns_and_falls_back_to_playwright_core(self) -> None:
170
167
  for template_name in TEMPLATE_NAMES:
171
168
  with self.subTest(template_name=template_name):
172
169
  result = _run_template(
@@ -1,127 +1,113 @@
1
- # Tier 2 — Chrome stealth (CloakBrowser + agent-browser)
1
+ # Tier 2 — Chrome stealth through playwright-core scripts
2
2
 
3
- Real interaction (clicks, forms, screenshots, video, persistent login) for pages that defeat Tier 1/1.5. Two runtime tools, both installed on demand — neither is vendored in this skill:
4
-
5
- - **CloakBrowser** (`pip`) — stealth Chromium with source-level C++ fingerprint patches. The Python wrapper source is MIT; the downloaded Chromium binary is covered by CloakBrowser's separate binary license and is not redistributed by this package. Passes Cloudflare Turnstile, FingerprintJS, BrowserScan, and 30+ detectors. Pin **0.5.7**.
6
- - **agent-browser** (`npm`, Apache-2.0) — native CDP automation CLI that drives CloakBrowser. AX-tree snapshots, `@eN` refs, click/fill/type/scroll, screenshots, video, cookie/state/session management. Pin **0.34.0**.
7
-
8
- ```
9
- CloakBrowser (stealth Chromium) <- CDP port 9242 -> agent-browser CLI
10
- - 57 C++ fingerprint patches - AX-tree snapshots, @eN refs
11
- - Canvas/WebGL consistency - click / fill / type / scroll
12
- - navigator.webdriver = false at C++ source - screenshot, video record
13
- - Humanize mode (mouse curves, timing) - cookie / state / session mgmt
14
- ```
3
+ For real-Chrome semantics, stealth, traces, or authenticated sessions, WRITE a
4
+ script and run it from the js-eval kernel. Use installed local Chrome, not a
5
+ managed browser download. Ordinary macOS captures on a Bun >= 1.4 kernel use
6
+ `new Bun.WebView()`; Linux/Windows WebView needs installed Chrome/Chromium/Edge.
7
+ Codex's ordinary browser surface is `browser:control-in-app-browser`.
15
8
 
16
9
  ## Install (one-time)
17
10
 
18
- CloakBrowser runs in a dedicated Python venv. Cross-platform: macOS, Linux, and Windows all supported by both tools (use the venv path convention for your OS).
19
-
20
- The venv lives at a fixed path so every session reuses one stealth-Chromium download instead of creating a new venv per working directory, and every command below calls its interpreter by absolute path — no `activate` step to forget.
21
-
22
- ```bash
23
- # CloakBrowser (MIT wrapper source; separate binary license, pin 0.5.7):
24
- VENV="$HOME/.agents/cloak-venv" # Windows: %USERPROFILE%\.agents\cloak-venv
25
- uv venv "$VENV" --python 3.13
26
- uv pip install --python "$VENV/bin/python" "cloakbrowser==0.5.7"
27
- "$VENV/bin/python" -c "import cloakbrowser; cloakbrowser.ensure_binary()" # downloads stealth Chromium on first import
11
+ Only the user installs these script dependencies, once in the skill's engine
12
+ directory. Stealth plugins run inside scripts, never inside WebView:
28
13
 
29
- # agent-browser (Apache-2.0, pin 0.34.0):
30
- bun add -g agent-browser@0.34.0 && agent-browser install
31
- agent-browser --version # 0.34.0
14
+ ```sh
15
+ cd "$SKILL_DIR/engine"
16
+ test -f package.json || cp templates/package.json package.json
17
+ bun add playwright-core@1.62.1 playwright-extra@4.3.6 puppeteer-extra-plugin-stealth@2.11.2
32
18
  ```
33
19
 
34
- Verify CloakBrowser:
35
-
36
- ```bash
37
- "$VENV/bin/python" -c "import cloakbrowser; print(cloakbrowser.__version__, cloakbrowser.CHROMIUM_VERSION, cloakbrowser.binary_info()['installed'])"
38
- # -> 0.5.7 <chromium-version> True
39
- ```
20
+ Chrome must already be installed. The bundled `templates/playwright_real_chrome.js`
21
+ and `templates/playwright_mobile_chrome.js` resolve these dependencies from their
22
+ parent engine directory. Without optional plugins, templates report the fallback
23
+ and use plain `playwright-core`; do not call that fallback stealth.
40
24
 
41
25
  ## Launch + drive
42
26
 
43
- NEVER clear cookies, cache, or site data (`Network.clearBrowserCookies`, `Storage.clearCookies`, `chrome.browsingData.remove`, "clear browsing data") on the user's real/main browser profile — it wipes their logged-in state everywhere. If you need that profile's login state, clone it first (`rsync -a <profile>/ <tmp-clone>/`) and launch with the clone as the user-data-dir; run any clearing on the clone only.
44
-
45
- ```bash
46
- # 1. Launch CloakBrowser with CDP on :9242 (background). cloakbrowser lives only in the venv,
47
- # so call its interpreter by absolute path — this works in any shell, activated or not:
48
- "$HOME/.agents/cloak-venv/bin/python" -c "import asyncio,cloakbrowser; asyncio.run(cloakbrowser.launch_async(headless=False, stealth_args=True, args=['--remote-debugging-port=9242']))" &
49
-
50
- # 2. CloakBrowser launches tabless -> agent-browser would say "No page found".
51
- # Open the first tab via CDP before any agent-browser command:
52
- curl -s -X PUT "http://127.0.0.1:9242/json/new?https://example.com"
53
-
54
- # 3. Connect agent-browser. CloakBrowser already patches navigator.webdriver=false at the
55
- # C++ source, so NO --init-script is required — only --user-agent to hide HeadlessChrome:
56
- agent-browser --cdp 9242 \
57
- --user-agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.7680.177 Safari/537.36" \
58
- open https://example.com
59
-
60
- # 4. Interact:
61
- agent-browser --cdp 9242 snapshot -i # interactive elements (@eN refs)
62
- agent-browser --cdp 9242 click @e3
63
- agent-browser --cdp 9242 screenshot out.png
64
-
65
- # 5. Close when done:
66
- agent-browser --cdp 9242 close
27
+ Close the source browser before cloning its user-data directory for a consistent
28
+ copy. Preserve its `Local State` alongside the selected profile. Use a private,
29
+ task-owned clone, never the live user-data-dir. NEVER clear the live profile's
30
+ cookies, cache, or site data. For unauthenticated QA, use a fresh task-owned profile.
31
+
32
+ Write `capture.cjs` in the engine directory. `clonePath`, URL, and output path are
33
+ arguments owned by this QA run; keep cookie values out of argv and logs:
34
+
35
+ ```js
36
+ const { chromium: core } = require('playwright-core');
37
+ const { addExtra } = require('playwright-extra');
38
+ const stealth = require('puppeteer-extra-plugin-stealth');
39
+ const [clonePath, url, pngPath] = process.argv.slice(2);
40
+ const chromium = addExtra(core);
41
+ chromium.use(stealth());
42
+
43
+ async function capture() {
44
+ const context = await chromium.launchPersistentContext(clonePath, {
45
+ channel: 'chrome',
46
+ headless: true,
47
+ args: ['--disable-blink-features=AutomationControlled'],
48
+ ignoreDefaultArgs: ['--enable-automation'],
49
+ viewport: { width: 1280, height: 720 },
50
+ });
51
+ try {
52
+ const page = await context.newPage();
53
+ await page.goto(url, { waitUntil: 'load', timeout: 30000 });
54
+ await page.screenshot({ path: pngPath });
55
+ console.log(JSON.stringify({ pngPath, webdriver: await page.evaluate(() => navigator.webdriver) }));
56
+ } finally {
57
+ await context.close();
58
+ }
59
+ }
60
+ capture().catch((error) => { console.error(error); process.exitCode = 1; });
67
61
  ```
68
62
 
69
- agent-browser ships its own always-version-matched usage guide — load it instead of guessing flags:
63
+ Run the script from js eval with a bounded process lifetime:
70
64
 
71
- ```bash
72
- agent-browser skills get core # core workflows, patterns, troubleshooting
73
- agent-browser skills get core --full # + full command reference and templates
74
- agent-browser skills get electron # Electron apps (VS Code, Slack, Discord, Figma, ...)
75
- agent-browser skills list # everything available on the installed version
65
+ ```js
66
+ const { promisify } = await import('node:util')
67
+ const { execFile } = await import('node:child_process')
68
+ const result = await promisify(execFile)('node', [scriptPath, clonePath, url, pngPath], { timeout: 45000 })
69
+ console.log(result.stdout)
76
70
  ```
77
71
 
78
- ## Verify stealth
79
-
80
- ```bash
81
- agent-browser --cdp 9242 eval 'navigator.webdriver' # must print false
82
- ```
72
+ For extraction, run a bundled template the same way, supplying its JSON input on
73
+ stdin (`url`, `profileDir: clonePath`, `waitSelector`, `headless`). The template
74
+ returns HTML on stdout. For traces, use `context.tracing.start()` before navigation
75
+ and `context.tracing.stop({ path: tracePath })` before closing. Use `headless: false`
76
+ only with an available display when headed behavior is the criterion.
83
77
 
84
- Verified 2026-07 with CloakBrowser 0.5.7 + agent-browser 0.34.0: `navigator.webdriver` reads the boolean false with no init-script, bot.sannysoft.com all-green, browserscan.net "Normal" (15/15), nowsecure.nl Turnstile bypassed.
78
+ ## Verify stealth
85
79
 
86
- > **agent-browser 0.33.x behavior note:** the daemon now defaults to a 1-hour idle timeout (saves restore state, closes the browser, exits after 1 h of no commands). Set `AGENT_BROWSER_IDLE_TIMEOUT_MS=0` to restore the old always-persist behavior. External WebSocket stream consumers see latest-wins frame delivery; `record` (CDP) and the dashboard are unaffected.
80
+ Inspect the page, screenshot, and requested content. `navigator.webdriver === false`
81
+ checks one browser property, NOT a promise to pass a detector or challenge.
82
+ Persistent challenge pages or missing content are failures, even if the script
83
+ exits zero. Do not keep retrying or silently swap browser tooling.
87
84
 
88
85
  ## Cookie login (cross-platform)
89
86
 
90
- `scripts/extract_cookies.py` reads cookies from a local browser profile and optionally injects them into the running CDP session. Profile-path resolution and value decryption are per-OS:
87
+ `scripts/extract_cookies.py` exports local-browser cookies with owner-only `0600`
88
+ permissions. Keep exports private and never commit them. For a persistent context,
89
+ load the exported cookies with `context.addCookies(...)`, then navigate/reload.
90
+ Browser- or device-bound login tokens may not transfer to a clone.
91
91
 
92
- | OS | Profile location | Cookie value decryption |
93
- |----|------------------|--------------------------|
94
- | macOS | `~/Library/Application Support/<app>/` | Keychain (AES-128-CBC, PBKDF2 salt `saltysalt`) |
95
- | Linux | `~/.config/<app>/` (Chromium), `~/.mozilla/firefox/` (Firefox) | libsecret/SecretService, then PBKDF2 + AES-128-CBC |
96
- | Windows | `%LOCALAPPDATA%\<app>\User Data\` | DPAPI (`CryptUnprotectData`) + AES-256-GCM (`os_crypt` key) |
97
-
98
- ```bash
99
- # Extract to a file:
100
- mkdir -p ~/.local/state/omo-cookies
101
- python3 ../scripts/extract_cookies.py --browser chrome --domain youtube.com --output ~/.local/state/omo-cookies/youtube.cookies.json
102
- # Extract and inject into the running CDP session:
103
- python3 ../scripts/extract_cookies.py --browser chrome --domain youtube.com --inject --cdp 9242
104
- ```
105
-
106
- Cookie export files are written with owner-only `0600` permissions. Do not place live auth cookies in shared temp directories or commit them to a repo. Cookie injection sends values to CDP over stdin rather than argv, so live cookie values do not appear in process listings. Cookies apply on next navigation — reload after injecting. Google services use fingerprint-bound tokens (SIDTS) that may not transfer across browser profiles. Firefox-family profiles store cookies unencrypted; Chromium-family profiles trigger a one-time OS-keyring prompt on macOS/Linux.
92
+ The helper's `--inject --cdp <port>` targets a task-owned local Chrome CDP endpoint,
93
+ which a script can also use via `chromium.connectOverCDP(...)`. Expose CDP on
94
+ loopback only, never against the live profile. Values travel on stdin, not argv.
107
95
 
108
96
  ## Anti-patterns
109
97
 
110
- - Do NOT launch CloakBrowser for plain text extraction — use Tier 1.
111
- - Do NOT pass an `--init-script` for the webdriver flag — CloakBrowser already patches it at source; the only required override is `--user-agent`.
112
- - Do NOT run agent-browser before creating the first tab via `curl -X PUT .../json/new` — CloakBrowser launches tabless.
113
- - Do NOT use vanilla Chrome when stealth is needed — always CloakBrowser.
114
- - Do NOT forget to `close` the session when done.
115
- - Do NOT inject cookies without reloading the page.
98
+ - Plain text extraction does not need a stealth browser: use the extraction lane.
99
+ - Never launch against, clear, or delete the user's live profile.
100
+ - Never claim stealth from successful startup alone; validate rendered content.
101
+ - Never run plugins without explicit user-installed script dependencies.
116
102
 
117
103
  ## Troubleshooting
118
104
 
119
- ```bash
120
- # Port 9242 already in use (macOS/Linux):
121
- lsof -ti:9242 | xargs kill -9
122
- # agent-browser can't connect:
123
- curl -s http://127.0.0.1:9242/json/version | head -5 # empty -> CloakBrowser not running
124
- # Update either tool:
125
- uv pip install --python "$HOME/.agents/cloak-venv/bin/python" --upgrade "cloakbrowser==0.5.7" && "$HOME/.agents/cloak-venv/bin/python" -c "import cloakbrowser; cloakbrowser.ensure_binary()"
126
- bun add -g agent-browser@0.34.0
127
- ```
105
+ A missing Chrome executable is a prerequisite failure: report it, do not download
106
+ a replacement. Missing plugins require the one-time setup above; module errors
107
+ inside installed plugins are real failures, not optional-dependency misses.
108
+ A locked profile usually means the source was not cloned or another run owns the
109
+ clone. Use a new task-owned clone instead of killing unrelated browsers.
110
+
111
+ Always close contexts in `finally`, stop the fixture server, and remove only this
112
+ run's clone and temporary scripts. Preserve requested PNG/trace evidence and record
113
+ the cleanup receipt, including failures.
@@ -223,11 +223,17 @@ result = fetch(
223
223
  python3 -c "import curl_cffi, bs4, yaml" 2>/dev/null || pip install curl_cffi beautifulsoup4 pyyaml -q
224
224
  ```
225
225
 
226
- Playwright 로컬 경로 사용 시 Node가 필요:
226
+ 브라우저를 직접 제어할 때는 js eval에서 Bun >= 1.4의 `new Bun.WebView()`를
227
+ 사용한다(macOS 기본; Linux/Windows는 설치된 Chrome/Chromium/Edge 필요).
228
+ 그 외 또는 Chrome 동작·stealth·trace·인증이 필요하면 `playwright-core` 스크립트를
229
+ 작성해 js eval에서 로컬 Chrome(`channel: "chrome"`)으로 실행한다.
230
+ 사용자가 엔진 디렉터리에서 한 번 설치할 스크립트 의존성:
227
231
  ```bash
228
- npm i -g playwright playwright-extra puppeteer-extra-plugin-stealth
229
- npx playwright install chrome
232
+ cd "$SKILL_DIR/engine"
233
+ test -f package.json || cp templates/package.json package.json
234
+ bun add playwright-core@1.62.1 playwright-extra@4.3.6 puppeteer-extra-plugin-stealth@2.11.2
230
235
  ```
236
+ Chrome은 이미 설치되어 있어야 한다. 인증 프로필은 먼저 복제하고 복제본만 사용한다.
231
237
 
232
238
  ## 빠른 참조 — Phase 0 명령어
233
239