lazycodex-ai 5.0.0-beta.86 → 5.0.0-beta.87

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 (175) hide show
  1. package/dist/cli/index.js +27 -21
  2. package/dist/cli-node/index.js +27 -21
  3. package/package.json +1 -1
  4. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  5. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -0
  6. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  7. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  8. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  9. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  10. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  11. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  12. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  13. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  14. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  15. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  16. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  17. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +1 -1
  18. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  19. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  21. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  23. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/ultrawork/README.md +1 -1
  25. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
  26. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +63 -89
  27. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  28. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  30. package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +2 -2
  31. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  32. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +63 -89
  34. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  35. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  36. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +2 -3
  37. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
  38. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  39. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  40. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  41. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  42. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  55. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  59. package/packages/omo-codex/plugin/package-lock.json +12 -12
  60. package/packages/omo-codex/plugin/package.json +1 -1
  61. package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +8 -2
  62. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -2
  63. package/packages/omo-codex/plugin/skills/browser/ATTRIBUTION.md +26 -14
  64. package/packages/omo-codex/plugin/skills/browser/SKILL.md +65 -52
  65. package/packages/omo-codex/plugin/skills/browser/references/commands.md +81 -66
  66. package/packages/omo-codex/plugin/skills/browser/references/install.md +31 -34
  67. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/README.md +41 -21
  68. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/frames-and-humans.md +33 -20
  69. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/ladder.md +24 -22
  70. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/network.md +35 -15
  71. package/packages/omo-codex/plugin/skills/browser/references/recipes/1password.md +13 -11
  72. package/packages/omo-codex/plugin/skills/browser/references/remote.md +5 -4
  73. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/index.js +1534 -0
  74. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +9 -0
  75. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/page-bundle.js +1395 -0
  76. package/packages/omo-codex/plugin/skills/browser/scripts/browser-doctor.mjs +37 -32
  77. package/packages/omo-codex/plugin/skills/browser/scripts/browser-install.mjs +31 -44
  78. package/packages/omo-codex/plugin/skills/browser/scripts/omowright.mjs +25 -0
  79. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -2
  80. package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +3 -3
  81. package/packages/omo-codex/plugin/skills/debugging/references/methodology/08-qa.md +1 -1
  82. package/packages/omo-codex/plugin/skills/debugging/references/tools/browser-qa.md +104 -0
  83. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
  84. package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +1 -1
  85. package/packages/omo-codex/plugin/skills/programming/SKILL.md +12 -18
  86. package/packages/omo-codex/plugin/skills/programming/references/rust/README.md +43 -15
  87. package/packages/omo-codex/plugin/skills/programming/references/rust/api-design.md +81 -0
  88. package/packages/omo-codex/plugin/skills/programming/references/rust/async-tokio.md +60 -28
  89. package/packages/omo-codex/plugin/skills/programming/references/rust/axum-stack.md +1 -13
  90. package/packages/omo-codex/plugin/skills/programming/references/rust/cargo-strict.md +44 -8
  91. package/packages/omo-codex/plugin/skills/programming/references/rust/clap-stack.md +8 -3
  92. package/packages/omo-codex/plugin/skills/programming/references/rust/concurrency.md +66 -52
  93. package/packages/omo-codex/plugin/skills/programming/references/rust/libraries.md +35 -25
  94. package/packages/omo-codex/plugin/skills/programming/references/rust/macros.md +63 -0
  95. package/packages/omo-codex/plugin/skills/programming/references/rust/one-liners.md +5 -3
  96. package/packages/omo-codex/plugin/skills/programming/references/rust/proptest-insta.md +8 -0
  97. package/packages/omo-codex/plugin/skills/programming/references/rust/type-state.md +50 -12
  98. package/packages/omo-codex/plugin/skills/programming/references/rust/unsafe-discipline.md +34 -6
  99. package/packages/omo-codex/plugin/skills/programming/references/rust/zero-cost-safety.md +62 -52
  100. package/packages/omo-codex/plugin/skills/programming/references/rust-ub/miri-sanitizers-loom.md +1 -1
  101. package/packages/omo-codex/plugin/skills/programming/references/rust-ub/ub-taxonomy.md +6 -3
  102. package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.sh +86 -75
  103. package/packages/omo-codex/plugin/skills/programming/scripts/rust/new-project.py +31 -28
  104. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  105. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +27 -20
  106. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +1 -1
  107. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +32 -100
  108. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +5 -11
  109. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +20 -37
  110. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +63 -89
  111. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +4 -4
  112. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +2 -3
  113. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
  114. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +1 -1
  115. package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +46 -46
  116. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -2
  117. package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -2
  118. package/packages/prompts-core/prompts/ultrawork/codex.md +63 -89
  119. package/packages/shared-skills/skills/browser/ATTRIBUTION.md +26 -14
  120. package/packages/shared-skills/skills/browser/SKILL.md +65 -52
  121. package/packages/shared-skills/skills/browser/references/commands.md +81 -66
  122. package/packages/shared-skills/skills/browser/references/install.md +31 -34
  123. package/packages/shared-skills/skills/browser/references/owned-engine/README.md +41 -21
  124. package/packages/shared-skills/skills/browser/references/owned-engine/frames-and-humans.md +33 -20
  125. package/packages/shared-skills/skills/browser/references/owned-engine/ladder.md +24 -22
  126. package/packages/shared-skills/skills/browser/references/owned-engine/network.md +35 -15
  127. package/packages/shared-skills/skills/browser/references/recipes/1password.md +13 -11
  128. package/packages/shared-skills/skills/browser/references/remote.md +5 -4
  129. package/packages/shared-skills/skills/browser/runtime/omowright/index.js +1534 -0
  130. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +9 -0
  131. package/packages/shared-skills/skills/browser/runtime/omowright/page-bundle.js +1395 -0
  132. package/packages/shared-skills/skills/browser/scripts/browser-doctor.mjs +37 -32
  133. package/packages/shared-skills/skills/browser/scripts/browser-install.mjs +31 -44
  134. package/packages/shared-skills/skills/browser/scripts/omowright.mjs +25 -0
  135. package/packages/shared-skills/skills/debugging/SKILL.md +2 -2
  136. package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +3 -3
  137. package/packages/shared-skills/skills/debugging/references/methodology/08-qa.md +1 -1
  138. package/packages/shared-skills/skills/debugging/references/tools/browser-qa.md +104 -0
  139. package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
  140. package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +1 -1
  141. package/packages/shared-skills/skills/programming/SKILL.md +12 -18
  142. package/packages/shared-skills/skills/programming/references/rust/README.md +43 -15
  143. package/packages/shared-skills/skills/programming/references/rust/api-design.md +81 -0
  144. package/packages/shared-skills/skills/programming/references/rust/async-tokio.md +60 -28
  145. package/packages/shared-skills/skills/programming/references/rust/axum-stack.md +1 -13
  146. package/packages/shared-skills/skills/programming/references/rust/cargo-strict.md +44 -8
  147. package/packages/shared-skills/skills/programming/references/rust/clap-stack.md +8 -3
  148. package/packages/shared-skills/skills/programming/references/rust/concurrency.md +66 -52
  149. package/packages/shared-skills/skills/programming/references/rust/libraries.md +35 -25
  150. package/packages/shared-skills/skills/programming/references/rust/macros.md +63 -0
  151. package/packages/shared-skills/skills/programming/references/rust/one-liners.md +5 -3
  152. package/packages/shared-skills/skills/programming/references/rust/proptest-insta.md +8 -0
  153. package/packages/shared-skills/skills/programming/references/rust/type-state.md +50 -12
  154. package/packages/shared-skills/skills/programming/references/rust/unsafe-discipline.md +34 -6
  155. package/packages/shared-skills/skills/programming/references/rust/zero-cost-safety.md +62 -52
  156. package/packages/shared-skills/skills/programming/references/rust-ub/miri-sanitizers-loom.md +1 -1
  157. package/packages/shared-skills/skills/programming/references/rust-ub/ub-taxonomy.md +6 -3
  158. package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.sh +86 -75
  159. package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.test.ts +83 -0
  160. package/packages/shared-skills/skills/programming/scripts/rust/new-project.py +31 -28
  161. package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
  162. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +27 -20
  163. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +1 -1
  164. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +32 -100
  165. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +5 -11
  166. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +20 -37
  167. package/packages/shared-skills/skills/ulw-execute/SKILL.md +4 -4
  168. package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
  169. package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +46 -46
  170. package/packages/omo-codex/plugin/skills/browser/scripts/browser-env.mjs +0 -41
  171. package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +0 -112
  172. package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.py +0 -296
  173. package/packages/shared-skills/skills/browser/scripts/browser-env.mjs +0 -41
  174. package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +0 -112
  175. package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.py +0 -296
@@ -1,71 +1,68 @@
1
1
  # Installing the attached engine
2
2
 
3
- Three pieces. The agent can install exactly one of them.
3
+ Three pieces. The onboarding script prepares all three; a human finishes exactly one.
4
4
 
5
5
  | Piece | Channel | Automatable |
6
6
  |---|---|---|
7
7
  | `bsk` CLI + daemon | upstream installer, GitHub Releases | **yes** |
8
- | Browser extension | Chrome Web Store / Edge Add-ons | **no — a human clicks Install** |
9
- | Daemon process | auto-starts on any `bsk` call | nothing to do |
8
+ | Browser extension | registered from the Web Store listing through Chrome's external-extension mechanism | **yes, up to one click** — the browser asks the user to enable it |
9
+ | Daemon process | auto-starts on the first call | nothing to do |
10
10
 
11
11
  ## Supported
12
12
 
13
13
  | | |
14
14
  |---|---|
15
15
  | Operating systems | macOS (Apple Silicon and Intel), Linux (x64, ARM64), Windows x64 |
16
- | Browsers | Chrome, Microsoft Edge. Other Chromium browsers work where they accept store builds. |
16
+ | Browsers | Chrome, Microsoft Edge, Brave, Chromium — any profile the doctor lists under `browsersDetected` |
17
17
 
18
- ## 1. The CLI
18
+ ## One command
19
19
 
20
20
  ```bash
21
- node "<skill-root>/scripts/browser-install.mjs"
21
+ node "<skill-root>/scripts/browser-install.mjs" [--json] [--wait-ms=180000]
22
22
  ```
23
23
 
24
- That wraps upstream's official installer:
24
+ In order it: runs upstream's official `install.sh` / `install.ps1` into `~/.local/bin` (any PATH
25
+ line the installer appends to a shell rc file is reverted — the library calls the binary by
26
+ absolute path); starts the daemon with `bsk status`; and, for every Chromium-family profile it
27
+ finds, registers the Web Store listing as an external extension:
25
28
 
26
- ```bash
27
- # macOS / Linux
28
- curl -fsSL https://raw.githubusercontent.com/Tencent/BrowserSkill/main/install.sh | sh
29
- export PATH="${BSK_INSTALL_DIR:-$HOME/.local/bin}:$PATH"
30
-
31
- # Windows (PowerShell)
32
- irm https://raw.githubusercontent.com/Tencent/BrowserSkill/main/install.ps1 | iex
33
- ```
34
-
35
- The Unix installer cannot change its parent shell's `PATH`. A shell opened before the install may
36
- still miss it, so either re-export in each call or use the absolute path (`$HOME/.local/bin/bsk`,
37
- `bsk.exe` on Windows). Verify with `bsk --version`.
29
+ | Platform | Where the entry goes | The user's one step |
30
+ |---|---|---|
31
+ | macOS | `<user data dir>/External Extensions/<id>.json` | quit the browser completely, open it again, click **Enable** in the dialog |
32
+ | Windows | `HKCU\Software\<vendor>\<browser>\Extensions\<id>` (`reg add`, no admin) | click **Enable** on the toolbar badge; no restart |
33
+ | Linux (Chromium) | `<user data dir>/External Extensions/<id>.json` | relaunch; installs without a prompt |
34
+ | Linux (Chrome / Edge / Brave) | `/opt/google/chrome/extensions/<id>.json` and siblings — root only | otherwise open the store link it prints and click **Add** |
38
35
 
39
- ## 2. The extension
36
+ The script prints that step as `humanStep`. **Relay it verbatim and wait**; with `--wait-ms` it
37
+ keeps polling the daemon until the extension connects. An empty `browsersConnected` afterwards is
38
+ not a failure to work around — the browser is closed or the user has not clicked yet; say which
39
+ and ask.
40
40
 
41
- Give the user the listing for their browser and wait:
41
+ If the user removed the extension from the browser before, Chrome blocklists its id for external
42
+ installs. The script detects that (`reason: "blocklisted"`) and prints the store link instead:
42
43
 
43
44
  - Chrome: https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi
44
45
  - Edge: https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg
45
46
 
46
- Then confirm it landed:
47
-
48
- ```bash
49
- bsk status --json # a non-empty "browsers" array means connected
50
- ```
51
-
52
- An empty `browsers` list is not a failure to work around. Either the browser is closed or the
53
- extension is not enabled; say which and ask.
47
+ Enterprise force-install policies are deliberately not used: they brand the browser "managed by
48
+ your organization" and the user cannot remove the extension.
54
49
 
55
- ## 3. Do not install upstream's skill
50
+ ## Do not install upstream's skill
56
51
 
57
52
  Upstream ships its own agent skill through `bsk install-skill`. **Do not run it here.** This
58
53
  package already provides the skill, and upstream's copy installs under a different name into the
59
54
  user skill directory, which takes precedence over a shipped skill — two descriptions of the same
60
- CLI, one of them shadowing the one that knows about this package's recipes and helper scripts.
55
+ engine, one of them shadowing the one that knows about omowright and this package's scripts.
61
56
 
62
57
  ## Diagnosing
63
58
 
64
59
  ```bash
65
- node "<skill-root>/scripts/browser-doctor.mjs" # this package's view
60
+ node "<skill-root>/scripts/browser-doctor.mjs" --json # this package's view: cli, daemon, profiles, registrations, connections
66
61
  bsk doctor # upstream's own checks
67
62
  bsk logs # daemon log
68
63
  ```
69
64
 
70
- The daemon exits about ten minutes after the last browser disconnects and is not a system service,
71
- so a reboot also stops it. Both heal on the next `bsk` call — no repair needed.
65
+ The daemon exits about ten minutes after the last browser disconnects and is not a system
66
+ service, so a reboot also stops it. Both heal on the next call — `connectBrowserSkill()` starts it
67
+ unless `BSK_AUTO_START=0` (sandboxes that reap background processes keep the daemon on the host
68
+ and share `BSK_HOME`; see upstream's sandboxed-agents guide).
@@ -1,11 +1,33 @@
1
1
  # The owned engine
2
2
 
3
- A browser **your code launches and owns**, driven over CDP, with its own profile. The opposite of
4
- the attached engine: no user logins, full control.
5
-
6
- **This package ships no such engine.** These documents describe the contract and the technique, so
7
- that a locally installed CDP library — or a script you write against one — is driven correctly.
8
- If no owned engine is installed, say so and stay on the attached engine.
3
+ A browser **your code launches and owns**, driven over CDP by omowright with its own profile. The
4
+ opposite of the attached engine: no user logins, full control.
5
+
6
+ ```js
7
+ const { omowright } = await loadOmowright()
8
+ const profile = mkdtempSync(join(tmpdir(), "omowright-"))
9
+ const browser = await omowright.connectPipe({
10
+ browserPath: "<CloakBrowser or chrome-headless-shell binary>",
11
+ browserArgs: ["--headless", "--no-first-run", `--user-data-dir=${profile}`],
12
+ storageRoot: profile,
13
+ dialogPolicy: { accept: true },
14
+ })
15
+ try {
16
+ const page = await browser.newTab("https://example.com/")
17
+ const tree = omowright.compactSnapshot(await page.snapshot()) // ALWAYS compact before a model reads it
18
+ await page.locator("e3").click() // refs come straight from the snapshot
19
+ await Bun.write("shot.png", await page.screenshot())
20
+ } finally {
21
+ await browser.close()
22
+ rmSync(profile, { recursive: true, force: true }) // paired: a leftover profile is a logged-in browser nobody watches
23
+ }
24
+ ```
25
+
26
+ `connectPipe` launches over `--remote-debugging-pipe`: no listening port, stdio drained, the
27
+ process reaped on `close()`. `connect("http://127.0.0.1:<port>")` attaches to a browser something
28
+ else launched. `connectCloakProfile({ profileDir })` launches CloakBrowser with a pinned
29
+ fingerprint seed — the stealth path for WAF and bot-scored targets, where the attached engine's
30
+ console capture would be a signal.
9
31
 
10
32
  ## When it is the right engine
11
33
 
@@ -16,27 +38,25 @@ If no owned engine is installed, say so and stay on the attached engine.
16
38
  | Solving a challenge widget programmatically | needs coordinate control and OCR |
17
39
  | Reading the network instead of the DOM | needs request interception on your own target |
18
40
  | A QA flight trace (steps, HAR, screenshots) | recording someone's real session is not acceptable |
41
+ | Headless or unattended runs | the user's browser is on their desk |
19
42
 
20
43
  For anything that needs the user's login, the attached engine wins. For extracting text from a
21
44
  blocked URL, neither: use the `ultimate-browsing` skill.
22
45
 
23
- ## What an owned engine must give you
46
+ ## The page
24
47
 
25
- 1. A transport that opens no listening port (launch over a pipe), or an explicit local CDP endpoint.
26
- 2. An accessibility snapshot with stable in-page refs, and a **compact** form that drops the ref
27
- map before the tree reaches a model — on a real page that map is roughly half the bytes and the
28
- client never reads it.
29
- 3. Locators that resolve those refs in-page, including refs inside cross-origin frames.
30
- 4. Coordinate input, for what locators cannot address.
31
- 5. A dialog policy, so `alert` / `confirm` / `beforeunload` can never block a run.
48
+ `OmOPage` is Playwright-shaped: `goto`, `snapshot`, `locator(ref | css)`, `click`, `fill`,
49
+ `press`, `hover`, `check`, `selectOption`, `dragTo`, `setInputFiles`, `screenshot`, `pdf`,
50
+ `evaluate`, `waitForURL`, `keyboard`, `mouse`, `frameLocator`. A snapshot is an accessibility tree
51
+ with virtual refs (`[ref=e3]`, cross-origin frames as `f1e3`); `compactSnapshot()` drops the refs
52
+ map, about half the bytes. Readiness is a content probe (body plus interactive elements, landmarks
53
+ or text), not a timer; `goto(url, { waitUntil: "commit" })` is the escape hatch for empty pages.
32
54
 
33
55
  ## Reference
34
56
 
35
- - [ladder.md](ladder.md) — the escalation ladder, viewport pinning, coordinate control, challenge widgets
36
- - [network.md](network.md) — read the network instead of the DOM; traces and request interception
37
- - [frames-and-humans.md](frames-and-humans.md) — cross-origin frames, overlays, dialogs, human handoff
38
-
39
- ## Cleanup is paired
57
+ - [ladder.md](ladder.md) — the escalation ladder, viewport pinning, `createCua`, `createCaptcha`
58
+ - [network.md](network.md) — `createNetworkSnoop`, `collectWhileScrolling`, `createTrace`, `createRoutes`
59
+ - [frames-and-humans.md](frames-and-humans.md) — `snapshotWithFrames`, `describeLayers`, dialog policy, `emulate`, `requestHuman`
40
60
 
41
- Close the browser and remove the profile directory in the same `finally`. A profile left behind is
42
- a logged-in browser nobody is watching.
61
+ The library's own skill (`skills/omowright/SKILL.md` and `presets/*` in the omowright repository)
62
+ is the authoritative, longer treatment of each; these pages are the routing summary.
@@ -2,38 +2,51 @@
2
2
 
3
3
  ## Cross-origin frames and shadow DOM
4
4
 
5
- A cross-origin iframe is a separate target with its own snapshot. Reconcile the child trees into
6
- the parent so one tree describes the whole page, and address child elements through the page-level
7
- ref — never by fetching a frame handle first. Shadow roots are traversed by the snapshot engine;
8
- they are not a special case for you.
5
+ A cross-origin iframe is a separate target with its own snapshot. `snapshotWithFrames(page)`
6
+ reconciles the child trees into the parent so one tree describes the whole page, and reports
7
+ `missingFrames` for any it could not enter; address child elements through the page-level ref
8
+ (`f1e3`) — never by fetching a frame handle first. Shadow roots are traversed by the snapshot
9
+ engine; they are not a special case for you.
9
10
 
10
11
  ## Overlays that swallow clicks
11
12
 
12
13
  Two identical misses on an element that is clearly visible usually means something invisible sits
13
14
  on top: a consent banner, a modal backdrop, a sticky header, a full-viewport tracking layer.
14
- Describe the layers at the click point before you retry. Either the overlay is named — dismiss it
15
- and continue — or nothing is reported, which means the miss has another cause and you climb the
16
- ladder instead.
15
+ `describeLayers(page)` names the topmost fixed or sticky element covering the viewport, and
16
+ `snapshotWithLayers(page)` prefixes a snapshot with `@layers blocking=<role> "<name>"` when one
17
+ exists. Either the overlay is named — dismiss it and continue — or `@layers none`, which means the
18
+ miss has another cause and you climb the ladder instead.
17
19
 
18
20
  ## Dialogs never block
19
21
 
20
- `alert`, `confirm`, `prompt`, and `beforeunload` must be answered by a policy set when the
21
- browser is created, not by a listener you hope registers in time. Default to accepting
22
- (`confirm` true, `prompt` empty). A run that hangs on an unhandled dialog looks exactly like a
23
- hang with no cause, which is the most expensive kind to diagnose.
22
+ `alert`, `confirm`, `prompt`, and `beforeunload` are answered by the `dialogPolicy` passed to
23
+ `connectPipe` (or `browser.setDialogPolicy`), at the protocol layer, before the page sees them.
24
+ Default to accepting (`{ accept: true }`; a function receives `{ type, message }` and returns
25
+ `{ accept, promptText }`). `page.on("dialog")` still fires for observability. A run that hangs on
26
+ an unhandled dialog looks exactly like a hang with no cause, which is the most expensive kind to
27
+ diagnose.
24
28
 
25
29
  ## Device emulation
26
30
 
27
- Emulating a device is viewport plus user agent plus touch, applied together. Changing only the
28
- viewport produces a desktop page at a phone size, which is not what you are testing. Re-read the
29
- viewport after emulating, and re-pin coordinates.
31
+ `emulate(page, "iphone-14")` applies viewport, device scale factor, user agent and touch together;
32
+ changing only the viewport produces a desktop page at a phone size, which is not what you are
33
+ testing. `emulate(page, null)` restores. Re-read the viewport after emulating, and re-pin
34
+ coordinates.
30
35
 
31
36
  ## Handing the page to a human
32
37
 
33
38
  When every rung fails on a login, a one-time code, or a challenge you cannot clear, the human is
34
- the fallback, not the failure. Bring the tab to the front, state plainly what needs doing, and
35
- wait on a **condition** — the URL changed, the element appeared — with a bounded timeout, rather
36
- than on a fixed delay.
37
-
38
- Respect the answer. A cancelled or timed-out handoff is a stop, and the correct response is to
39
- report which rung failed with what evidence. Working around the user's refusal is never correct.
39
+ the fallback, not the failure:
40
+
41
+ ```js
42
+ const { outcome } = await omowright.requestHuman(page, {
43
+ prompt: "Please finish the sign-in in this window.",
44
+ until: { url: /\/dashboard/ }, // or { selector } or async (page) => boolean
45
+ timeoutMs: 300_000,
46
+ })
47
+ ```
48
+
49
+ It brings the window to the front, shows a banner with a Done button, and waits on a
50
+ **condition** with a bounded timeout rather than a fixed delay. Respect the answer: `timed_out`
51
+ or `cancelled` is a stop, and the correct response is to report which rung failed with what
52
+ evidence. Working around the user's refusal is never correct.
@@ -5,12 +5,12 @@ defect.** The failure itself selects the next rung; never pause to ask which.
5
5
 
6
6
  | Rung | Use | Climb when |
7
7
  |---|---|---|
8
- | 1. snapshot + locator(ref) | anything with a usable ref | the ref is absent, stale, obscured, or the click lands on the wrong node twice |
9
- | 1b. layer description | a blocking overlay explains two identical misses | no overlay is reported, or it is gone and the click still misses |
10
- | 2. coordinates | canvas, extension popups, custom controls, drag surfaces | the click misses, or the screenshot and the coordinates disagree |
11
- | 3. pin the viewport, redo rung 2 | coordinate drift after a resize, a DPI change, or a foreign tab | coordinates land correctly but the widget still refuses input |
12
- | 4. the challenge widget | a challenge is the blocker | it clears and the flow still stalls |
13
- | 5. read the browser log | a browser-level failure | the log names a cause outside the page |
8
+ | 1. `page.snapshot()` + `page.locator(ref)` | anything with a usable ref | the ref is absent, stale, obscured, or the click lands on the wrong node twice |
9
+ | 1b. `snapshotWithLayers(page)` / `describeLayers(page)` | a blocking overlay explains two identical misses | `@layers none`, or the overlay is gone and the click still misses |
10
+ | 2. `createCua(page)` coordinates | canvas, extension popups, custom controls, drag surfaces | the click misses, or the screenshot and the coordinates disagree |
11
+ | 3. pin the viewport (`emulate(page, "desktop-1440")` / `repinViewport`), redo rung 2 | coordinate drift after a resize, a DPI change, or a foreign tab | coordinates land correctly but the widget still refuses input |
12
+ | 4. `createCaptcha(page)` | a challenge is the blocker | it clears and the flow still stalls |
13
+ | 5. read the browser log (`browser.close()` surfaces the stdio tail) | a browser-level failure | the log names a cause outside the page |
14
14
 
15
15
  **Rung 5 ends in a written diagnosis, never a speculative code change.** A missing entitlement, a
16
16
  dead extension service worker, an unavailable authenticator — none of those is fixed by editing
@@ -18,38 +18,40 @@ automation code.
18
18
 
19
19
  ## Pin the viewport before trusting any coordinate
20
20
 
21
- Coordinate input acts in viewport pixels. When the render surface and the coordinate space
21
+ `createCua(page)` acts in viewport pixels. When the render surface and the coordinate space
22
22
  disagree, every coordinate is off by the same constant and retrying just repeats the miss. Set the
23
- device metrics explicitly (width, height, `deviceScaleFactor`, and a matching viewport), re-read
24
- the page's viewport size, then take a **fresh** screenshot. Coordinates read off an unpinned
25
- screenshot are stale. Pin every page you act on, including tabs you did not open.
23
+ device metrics explicitly (`emulate` applies width, height, `deviceScaleFactor` and touch
24
+ together), re-read the page's viewport size, then take a **fresh** `cua.getVisibleScreenshot()`.
25
+ Coordinates read off an unpinned screenshot are stale. Pin every page you act on, including tabs
26
+ you did not open (`createAgentTabs` re-pins on create).
26
27
 
27
28
  ## Refs
28
29
 
29
30
  - Refs die on every new snapshot. Pass a ref straight from the latest snapshot; never reuse one
30
31
  across snapshots and never put one in a CSS selector.
31
- - Refs stay page-level. A child-frame ref still resolves through the page, so you never fetch a
32
- frame handle to click inside an iframe.
33
- - Always compact a snapshot before sending it to a model.
32
+ - Refs stay page-level. A child-frame ref (`f1e3`) still resolves through `page.locator`, so you
33
+ never fetch a frame handle to click inside an iframe.
34
+ - Always `compactSnapshot()` before sending a snapshot to a model.
34
35
 
35
36
  ## Challenge widgets
36
37
 
37
38
  A challenge is an obstacle on the path, not a stop sign: clear it, confirm it cleared, continue.
38
- Three shapes, three techniques:
39
+ `createCaptcha(page)` gives three techniques:
39
40
 
40
- - **Checkbox** (the common embedded widgets): the control lives in a nested frame, so address it
41
- by viewport coordinates.
42
- - **Slider / puzzle**: drag along a path with enough intermediate steps that the motion reads as
43
- human. Raise the step count before you change the endpoints.
44
- - **Text or number**: OCR the region. On macOS the system vision framework is the cheapest
45
- accurate option; elsewhere pass your own OCR function or a vision model.
46
- - **Image grid**: annotate a screenshot, then click per cell.
41
+ - **Checkbox** (the common embedded widgets): the control lives in a nested frame, so
42
+ `captcha.click(bounds)` addresses it by viewport coordinates.
43
+ - **Slider / puzzle**: `captcha.drag(from, to, { steps })` with enough intermediate steps that the
44
+ motion reads as human. Raise the step count before you change the endpoints.
45
+ - **Text or number**: `captcha.readText(bounds)` OCRs the region — the macOS Vision framework by
46
+ default, or pass your own `ocr` function or a vision model.
47
+ - **Image grid**: annotate a screenshot, then click per cell with `createCua`.
47
48
 
48
49
  **Bounds measured against an unpinned viewport are wrong by a constant offset.** If clicks have
49
50
  been landing wrong, drop to rung 3 first, then re-read the bounds.
50
51
 
51
52
  Verify with a fresh snapshot that the challenge is gone. Verification is part of the action, not a
52
- separate optimistic assumption.
53
+ separate optimistic assumption. When every technique fails on a page a real browser passes, the
54
+ engine is the variable: relaunch through `connectCloakProfile()`.
53
55
 
54
56
  ## Delegating the pixel loop
55
57
 
@@ -6,37 +6,57 @@ next week. Watching traffic costs nothing on a target you own, and the page cann
6
6
 
7
7
  **Snoop before you scrape.** Scroll-and-parse is the fallback, not the default.
8
8
 
9
+ ```js
10
+ const snoop = omowright.createNetworkSnoop(page, { maxBodyBytes: 512 * 1024 })
11
+ await page.goto(url)
12
+ const hit = await snoop.waitFor({ url: /\/api\/search/, mimeType: "application/json" }, { timeoutMs: 10_000 })
13
+ const rows = snoop.popJson() // every buffered JSON body, drained
14
+ console.log(snoop.summary({ max: 20 })) // one line per request: method status mime size url
15
+ snoop.dispose()
16
+ ```
17
+
9
18
  ## Wait for a request, never for a clock
10
19
 
11
- A fixed sleep is a guess that fails on a slower machine and wastes time on a faster one. Subscribe
12
- to the response you expect **before** triggering the action, then await that signal with a bounded
13
- timeout. This is the same rule that governs test code, for the same reason.
20
+ A fixed sleep is a guess that fails on a slower machine and wastes time on a faster one.
21
+ `snoop.waitFor(match)` subscribes to the response you expect **before** you trigger the action,
22
+ then awaits it with a bounded timeout. This is the same rule that governs test code, for the same
23
+ reason.
14
24
 
15
25
  ## Collecting through infinite scroll
16
26
 
17
- Drive scroll and extraction as a generator: scroll, collect what is new, stop on a target count or
18
- a scroll ceiling. Bound both, so a page that keeps producing cannot run forever.
27
+ ```js
28
+ for await (const batch of omowright.collectWhileScrolling(page, snoop, { minItems: 200, maxScrolls: 10, extract: (json) => json.items })) {
29
+ items.push(...batch)
30
+ }
31
+ ```
32
+
33
+ Scroll, collect what is new, stop on a target count or a scroll ceiling. Bound both, so a page
34
+ that keeps producing cannot run forever.
19
35
 
20
36
  ## Flight traces
21
37
 
22
- For QA evidence, record a trace: one entry per step with before/after screenshots, the network
23
- log, and console output, written as a line-delimited log plus an HAR. That triple is what makes a
24
- failure reconstructable afterwards instead of re-runnable-in-theory.
38
+ For QA evidence, `createTrace(page, { dir })` records one entry per `trace.step(name, fn)` with
39
+ before/after screenshots, the network log and console output, written as `trace.jsonl` plus
40
+ `trace.har` (`toHar` builds the HAR from snoop entries). That triple is what makes a failure
41
+ reconstructable afterwards instead of re-runnable-in-theory. Call `trace.stop()` in `finally`.
25
42
 
26
43
  Cap recorded body sizes. An untrimmed trace of a media-heavy page is mostly bytes nobody reads.
27
44
 
28
45
  ## Request interception
29
46
 
30
- Route matching by glob, regular expression, or predicate lets you stub an endpoint, fail one
31
- request to test an error path, or block third-party noise. Enable interception on the first route
32
- and disable it on dispose — leaving it on slows every later navigation.
47
+ `createRoutes(page)` matches by glob, regular expression, or predicate and lets a handler
48
+ `continue`, `fulfill({ status, body })` or `abort()`: stub an endpoint, fail one request to test an
49
+ error path, block third-party noise. Interception is enabled on the first route and disabled on
50
+ `dispose()` — leaving it on slows every later navigation and changes the timing fingerprint, so
51
+ prefer passive snooping on bot-scored targets.
33
52
 
34
53
  ## Cookies
35
54
 
36
- Injecting a cookie export into your own profile is legitimate for ordinary sessions and useless
37
- for the ones you most want: accounts whose risk engines bind a session to a device will invalidate
38
- it, and a password manager's session is tab-bound and never portable. Sanitize what you do inject
39
- (drop expired entries, keep host-prefixed cookies secure and root-scoped).
55
+ `injectCookies(page, cookies)` sanitizes what it injects (drops expired entries, keeps
56
+ host-prefixed cookies secure and root-scoped). Injecting an export into your own profile is
57
+ legitimate for ordinary sessions and useless for the ones you most want: accounts whose risk
58
+ engines bind a session to a device will invalidate it, and a password manager's session is
59
+ tab-bound and never portable.
40
60
 
41
61
  **Never copy a session out of the user's real browser profile.** If you need their login, that is
42
62
  the attached engine's job.
@@ -16,25 +16,27 @@ not in a cookie. So:
16
16
  Therefore: borrow the existing tab, read, return it. Do not open, do not navigate away, do not
17
17
  "refresh to fix" anything.
18
18
 
19
- ```bash
20
- bsk tab list --scope user # find the already-signed-in tab
21
- bsk tab borrow <tab-id>
22
- # ... read ...
23
- bsk tab return <tab-id>
19
+ ```js
20
+ const { tabs } = await session.tabList({ scope: "user" }) // find the already-signed-in tab by URL
21
+ const vault = tabs.find((t) => /my\.1password\.com\/(?:vaults|app)/.test(t.url))
22
+ await session.tabBorrow(vault.tab_id) // the user confirms
23
+ // ... read ...
24
+ await session.tabReturn(vault.tab_id)
24
25
  ```
25
26
 
26
27
  ## Check liveness by URL, never by title
27
28
 
28
29
  The app mutates its URL hash without updating the document title, so a signed-in vault can still
29
30
  report a sign-in title. A live session's `location.href` contains the app path and never the
30
- sign-in path. Read the URL.
31
+ sign-in path. Read the URL from `tabList`, or `session.evaluate("location.href")`.
31
32
 
32
33
  ## The browser may be shared
33
34
 
34
35
  Other automation may be driving the same window.
35
36
 
36
- - **Clear the search box before typing.** It often holds someone else's query, and typing alone
37
- appends to it, returning confident results for the wrong search.
37
+ - **Clear the search box before typing** (`fill(target, value, { clearBefore: true })`). It often
38
+ holds someone else's query, and typing alone appends to it, returning confident results for the
39
+ wrong search.
38
40
  - **Read the autocomplete listbox, not the results grid.** The grid holds whatever query was last
39
41
  committed, possibly by another actor. Scraping every option on the page silently merges two
40
42
  different searches.
@@ -42,11 +44,11 @@ Other automation may be driving the same window.
42
44
 
43
45
  ## If it is locked
44
46
 
45
- ```bash
46
- bsk request-help --session <id> --prompt "Please unlock 1Password in this tab, then continue."
47
+ ```js
48
+ await session.requestHelp({ prompt: "Please unlock 1Password in this tab, then continue." })
47
49
  ```
48
50
 
49
- Then observe again.
51
+ Then read the page again.
50
52
 
51
53
  ## Not in scope
52
54
 
@@ -6,18 +6,19 @@ nothing in this package needs to bridge it.
6
6
  Shape:
7
7
 
8
8
  - The **browser machine** needs only the extension.
9
- - The **agent machine** runs the `bsk` CLI and this skill.
9
+ - The **agent machine** runs the `bsk` daemon, omowright and this skill.
10
10
  - They are joined by a daemon in server mode plus a pairing link.
11
11
 
12
12
  ```bash
13
- bsk daemon start --mode server # on the machine the agent runs on
13
+ bsk daemon start --mode server # on the machine the agent runs on; WSS is required off loopback
14
14
  ```
15
15
 
16
16
  Then follow upstream's pairing guide, which owns the current flag surface and the TLS
17
17
  prerequisites: https://github.com/Tencent/BrowserSkill/blob/main/docs/remote-extension-connection.md
18
18
 
19
- Once paired, every command in `commands.md` behaves identically; `--out` paths still resolve on
20
- the machine that ran the command.
19
+ Once paired, `connectBrowserSkill()` and every session method behave identically; screenshot
20
+ buffers arrive on the machine that ran the call. Windows named pipes are not discovered
21
+ automatically — pass `sockPath` to `connectBrowserSkill()`.
21
22
 
22
23
  If pairing is not configured, say so and ask. Do not substitute a browser on the agent machine:
23
24
  the point of the attached engine is the sessions that live in the user's browser, and a local