lazycodex-ai 5.0.0-beta.85 → 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.
- package/README.md +1 -1
- package/dist/cli/index.js +68 -41
- package/dist/cli-node/index.js +68 -41
- package/package.json +1 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -0
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/README.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +63 -89
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +2 -2
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +63 -89
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +2 -3
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +8 -2
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -2
- package/packages/omo-codex/plugin/skills/browser/ATTRIBUTION.md +26 -14
- package/packages/omo-codex/plugin/skills/browser/SKILL.md +65 -52
- package/packages/omo-codex/plugin/skills/browser/references/commands.md +81 -66
- package/packages/omo-codex/plugin/skills/browser/references/install.md +31 -34
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/README.md +41 -21
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/frames-and-humans.md +33 -20
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/ladder.md +24 -22
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/network.md +35 -15
- package/packages/omo-codex/plugin/skills/browser/references/recipes/1password.md +13 -11
- package/packages/omo-codex/plugin/skills/browser/references/remote.md +5 -4
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/index.js +1534 -0
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +9 -0
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/page-bundle.js +1395 -0
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-doctor.mjs +37 -32
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-install.mjs +31 -44
- package/packages/omo-codex/plugin/skills/browser/scripts/omowright.mjs +25 -0
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +3 -3
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/08-qa.md +1 -1
- package/packages/omo-codex/plugin/skills/debugging/references/tools/browser-qa.md +104 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +12 -18
- package/packages/omo-codex/plugin/skills/programming/references/rust/README.md +43 -15
- package/packages/omo-codex/plugin/skills/programming/references/rust/api-design.md +81 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/async-tokio.md +60 -28
- package/packages/omo-codex/plugin/skills/programming/references/rust/axum-stack.md +1 -13
- package/packages/omo-codex/plugin/skills/programming/references/rust/cargo-strict.md +44 -8
- package/packages/omo-codex/plugin/skills/programming/references/rust/clap-stack.md +8 -3
- package/packages/omo-codex/plugin/skills/programming/references/rust/concurrency.md +66 -52
- package/packages/omo-codex/plugin/skills/programming/references/rust/libraries.md +35 -25
- package/packages/omo-codex/plugin/skills/programming/references/rust/macros.md +63 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/one-liners.md +5 -3
- package/packages/omo-codex/plugin/skills/programming/references/rust/proptest-insta.md +8 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/type-state.md +50 -12
- package/packages/omo-codex/plugin/skills/programming/references/rust/unsafe-discipline.md +34 -6
- package/packages/omo-codex/plugin/skills/programming/references/rust/zero-cost-safety.md +62 -52
- package/packages/omo-codex/plugin/skills/programming/references/rust-ub/miri-sanitizers-loom.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/references/rust-ub/ub-taxonomy.md +6 -3
- package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.sh +86 -75
- package/packages/omo-codex/plugin/skills/programming/scripts/rust/new-project.py +31 -28
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +27 -20
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +32 -100
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +5 -11
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +20 -37
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +63 -89
- package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +2 -3
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +46 -46
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -2
- package/packages/prompts-core/prompts/ultrawork/codex.md +63 -89
- package/packages/shared-skills/skills/browser/ATTRIBUTION.md +26 -14
- package/packages/shared-skills/skills/browser/SKILL.md +65 -52
- package/packages/shared-skills/skills/browser/references/commands.md +81 -66
- package/packages/shared-skills/skills/browser/references/install.md +31 -34
- package/packages/shared-skills/skills/browser/references/owned-engine/README.md +41 -21
- package/packages/shared-skills/skills/browser/references/owned-engine/frames-and-humans.md +33 -20
- package/packages/shared-skills/skills/browser/references/owned-engine/ladder.md +24 -22
- package/packages/shared-skills/skills/browser/references/owned-engine/network.md +35 -15
- package/packages/shared-skills/skills/browser/references/recipes/1password.md +13 -11
- package/packages/shared-skills/skills/browser/references/remote.md +5 -4
- package/packages/shared-skills/skills/browser/runtime/omowright/index.js +1534 -0
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +9 -0
- package/packages/shared-skills/skills/browser/runtime/omowright/page-bundle.js +1395 -0
- package/packages/shared-skills/skills/browser/scripts/browser-doctor.mjs +37 -32
- package/packages/shared-skills/skills/browser/scripts/browser-install.mjs +31 -44
- package/packages/shared-skills/skills/browser/scripts/omowright.mjs +25 -0
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -2
- package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +3 -3
- package/packages/shared-skills/skills/debugging/references/methodology/08-qa.md +1 -1
- package/packages/shared-skills/skills/debugging/references/tools/browser-qa.md +104 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +1 -1
- package/packages/shared-skills/skills/programming/SKILL.md +12 -18
- package/packages/shared-skills/skills/programming/references/rust/README.md +43 -15
- package/packages/shared-skills/skills/programming/references/rust/api-design.md +81 -0
- package/packages/shared-skills/skills/programming/references/rust/async-tokio.md +60 -28
- package/packages/shared-skills/skills/programming/references/rust/axum-stack.md +1 -13
- package/packages/shared-skills/skills/programming/references/rust/cargo-strict.md +44 -8
- package/packages/shared-skills/skills/programming/references/rust/clap-stack.md +8 -3
- package/packages/shared-skills/skills/programming/references/rust/concurrency.md +66 -52
- package/packages/shared-skills/skills/programming/references/rust/libraries.md +35 -25
- package/packages/shared-skills/skills/programming/references/rust/macros.md +63 -0
- package/packages/shared-skills/skills/programming/references/rust/one-liners.md +5 -3
- package/packages/shared-skills/skills/programming/references/rust/proptest-insta.md +8 -0
- package/packages/shared-skills/skills/programming/references/rust/type-state.md +50 -12
- package/packages/shared-skills/skills/programming/references/rust/unsafe-discipline.md +34 -6
- package/packages/shared-skills/skills/programming/references/rust/zero-cost-safety.md +62 -52
- package/packages/shared-skills/skills/programming/references/rust-ub/miri-sanitizers-loom.md +1 -1
- package/packages/shared-skills/skills/programming/references/rust-ub/ub-taxonomy.md +6 -3
- package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.sh +86 -75
- package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.test.ts +83 -0
- package/packages/shared-skills/skills/programming/scripts/rust/new-project.py +31 -28
- package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +27 -20
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +32 -100
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +5 -11
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +20 -37
- package/packages/shared-skills/skills/ulw-execute/SKILL.md +4 -4
- package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
- package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +46 -46
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-env.mjs +0 -41
- package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +0 -112
- package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.py +0 -296
- package/packages/shared-skills/skills/browser/scripts/browser-env.mjs +0 -41
- package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +0 -112
- package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.py +0 -296
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
# uv run new-project.py myproject --path ./workspace
|
|
16
16
|
# ──────────────────
|
|
17
17
|
#
|
|
18
|
-
# Creates a new Rust project with strict lints, deny.toml, rustfmt.toml,
|
|
19
|
-
# rust-toolchain.toml
|
|
18
|
+
# Creates a new Rust project with strict lints, deny.toml, rustfmt.toml, and
|
|
19
|
+
# rust-toolchain.toml pre-configured. The generated project passes its own
|
|
20
|
+
# fmt + clippy gate before any code is written.
|
|
20
21
|
|
|
21
22
|
from __future__ import annotations
|
|
22
23
|
|
|
@@ -50,6 +51,7 @@ non_ascii_idents = "deny"
|
|
|
50
51
|
trivial_numeric_casts = "warn"
|
|
51
52
|
unused_lifetimes = "warn"
|
|
52
53
|
single_use_lifetimes = "warn"
|
|
54
|
+
unexpected_cfgs = { level = "deny", check-cfg = ["cfg(loom)"] }
|
|
53
55
|
|
|
54
56
|
[lints.clippy]
|
|
55
57
|
all = { level = "deny", priority = -1 }
|
|
@@ -66,32 +68,22 @@ unimplemented = "deny"
|
|
|
66
68
|
dbg_macro = "deny"
|
|
67
69
|
print_stdout = "warn"
|
|
68
70
|
print_stderr = "warn"
|
|
71
|
+
allow_attributes = "deny"
|
|
72
|
+
allow_attributes_without_reason = "deny"
|
|
73
|
+
let_underscore_must_use = "deny"
|
|
74
|
+
indexing_slicing = "deny"
|
|
75
|
+
mem_forget = "deny"
|
|
76
|
+
clone_on_ref_ptr = "warn"
|
|
69
77
|
module_name_repetitions = { level = "allow" }
|
|
70
78
|
must_use_candidate = { level = "allow" }
|
|
71
|
-
missing_errors_doc = { level = "allow" }
|
|
72
|
-
missing_panics_doc = { level = "allow" }
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
CARGO_CONFIG_TOML = """\
|
|
76
|
-
[build]
|
|
77
|
-
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
|
|
78
|
-
|
|
79
|
-
[target.x86_64-unknown-linux-gnu]
|
|
80
|
-
linker = "clang"
|
|
81
|
-
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
|
|
82
|
-
|
|
83
|
-
[target.aarch64-apple-darwin]
|
|
84
|
-
rustflags = []
|
|
85
79
|
"""
|
|
86
80
|
|
|
87
81
|
DENY_TOML = """\
|
|
88
82
|
[advisories]
|
|
89
|
-
vulnerability = "deny"
|
|
90
|
-
unmaintained = "warn"
|
|
91
83
|
yanked = "deny"
|
|
92
84
|
|
|
93
85
|
[licenses]
|
|
94
|
-
|
|
86
|
+
private = { ignore = true } # publish = false crates carry no license field
|
|
95
87
|
allow = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "Unicode-3.0", "Zlib"]
|
|
96
88
|
|
|
97
89
|
[bans]
|
|
@@ -103,6 +95,16 @@ unknown-registry = "deny"
|
|
|
103
95
|
unknown-git = "deny"
|
|
104
96
|
"""
|
|
105
97
|
|
|
98
|
+
MAIN_RS = """\
|
|
99
|
+
//! Command-line entry point.
|
|
100
|
+
|
|
101
|
+
use std::io::Write as _;
|
|
102
|
+
|
|
103
|
+
fn main() -> std::io::Result<()> {
|
|
104
|
+
writeln!(std::io::stdout().lock(), "Hello, world!")
|
|
105
|
+
}
|
|
106
|
+
"""
|
|
107
|
+
|
|
106
108
|
RUSTFMT_TOML = """\
|
|
107
109
|
edition = "2024"
|
|
108
110
|
max_width = 100
|
|
@@ -148,18 +150,19 @@ def main(
|
|
|
148
150
|
(project_dir / "rust-toolchain.toml").write_text(RUST_TOOLCHAIN_TOML)
|
|
149
151
|
console.print(" [dim]wrote[/] rust-toolchain.toml")
|
|
150
152
|
|
|
151
|
-
# ──
|
|
153
|
+
# ── Declare the MSRV and append [lints] to Cargo.toml ────────────
|
|
152
154
|
cargo_toml = project_dir / "Cargo.toml"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
manifest = cargo_toml.read_text()
|
|
156
|
+
if 'edition = "2024"\n' not in manifest:
|
|
157
|
+
console.print("[bold red]Error:[/] cargo did not create an edition 2024 package; install Rust >= 1.85")
|
|
158
|
+
sys.exit(1)
|
|
159
|
+
manifest = manifest.replace(
|
|
160
|
+
'edition = "2024"\n', 'edition = "2024"\nrust-version = "1.85"\npublish = false\n', 1
|
|
161
|
+
)
|
|
162
|
+
cargo_toml.write_text(manifest + CARGO_TOML_LINTS)
|
|
163
|
+
(project_dir / "src" / "main.rs").write_text(MAIN_RS)
|
|
155
164
|
console.print(" [dim]appended[/] [lints] to Cargo.toml")
|
|
156
165
|
|
|
157
|
-
# ── .cargo/config.toml ───────────────────────────────────────────
|
|
158
|
-
cargo_config_dir = project_dir / ".cargo"
|
|
159
|
-
cargo_config_dir.mkdir(parents=True, exist_ok=True)
|
|
160
|
-
(cargo_config_dir / "config.toml").write_text(CARGO_CONFIG_TOML)
|
|
161
|
-
console.print(" [dim]wrote[/] .cargo/config.toml")
|
|
162
|
-
|
|
163
166
|
# ── deny.toml ────────────────────────────────────────────────────
|
|
164
167
|
(project_dir / "deny.toml").write_text(DENY_TOML)
|
|
165
168
|
console.print(" [dim]wrote[/] deny.toml")
|
|
@@ -169,7 +169,7 @@ You are the QA lane. Do not delegate hands-on QA to a sub-agent: the orchestrato
|
|
|
169
169
|
2. **Pick the channel that faithfully exercises the surface** and capture the artifact:
|
|
170
170
|
- HTTP: `curl -i` (or an API request context) - status line, headers, body.
|
|
171
171
|
- CLI / TUI: a real pty - drive the command and keep the transcript; for color or layout evidence render through a browser-based terminal, never a `tmux capture-pane` dump.
|
|
172
|
-
- Web: from js eval
|
|
172
|
+
- Web: omowright from js eval (staged in the `browser` skill) — the owned engine (`connectPipe` on a task-owned profile, or `connectCloakProfile` for bot-scored targets) for unauthenticated pages, the attached engine (`connectBrowserSkill()` in the user's signed-in browser) when the page needs their login; never a clone of or a launch against the live profile. Capture action log plus screenshot.
|
|
173
173
|
- Desktop / GUI: OS-level automation against the running app - action log plus screenshot.
|
|
174
174
|
- Library / SDK: a script that imports and exercises the public API - transcript.
|
|
175
175
|
- Data-shaped work (migrations, configs, generated files): the resulting artifact itself, diffed or dumped.
|
|
@@ -7,7 +7,7 @@ description: "Renders, drives, and screenshots web pages: JS-rendered sources, c
|
|
|
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
|
|
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** through omowright from js eval: 2a the owned engine (a browser your code launches, CloakBrowser for stealth), 2b the attached engine (the user's own signed-in browser).
|
|
11
11
|
|
|
12
12
|
## PHASE 0 — ROUTE FIRST (MANDATORY)
|
|
13
13
|
|
|
@@ -23,11 +23,11 @@ User request
|
|
|
23
23
|
+- podcast transcript / stock forum ----------------- TIER 1.5 agent-reach
|
|
24
24
|
+- Twitter feed / LinkedIn profile / GitHub via CLI - TIER 1.5 agent-reach
|
|
25
25
|
|
|
|
26
|
-
+- Tier 1/1.5 returned empty or partial ------------- TIER 2 2a
|
|
27
|
-
+- click / fill form / scroll / interact ------------ TIER 2 2a
|
|
28
|
-
+- screenshot / render / play video ----------------- TIER 2 2a
|
|
29
|
-
+- login session across pages /
|
|
30
|
-
+- test web app / QA / dogfood ---------------------- TIER 2 2a
|
|
26
|
+
+- Tier 1/1.5 returned empty or partial ------------- TIER 2 2a owned engine -> 2b attached engine
|
|
27
|
+
+- click / fill form / scroll / interact ------------ TIER 2 2a owned engine -> 2b attached engine
|
|
28
|
+
+- screenshot / render / play video ----------------- TIER 2 2a owned engine -> 2b attached engine
|
|
29
|
+
+- login session across pages / the user's account --- TIER 2 2b attached engine (their browser)
|
|
30
|
+
+- test web app / QA / dogfood ---------------------- TIER 2 2a owned engine -> 2b attached engine
|
|
31
31
|
|
|
|
32
32
|
+- simple search query ------------------------------ NOT this skill (use web-search)
|
|
33
33
|
```
|
|
@@ -84,28 +84,35 @@ Routing table, per-platform auth (set `TWITTER_*` env vars, `gh auth login`, a t
|
|
|
84
84
|
|
|
85
85
|
**When**: real interaction is needed (clicks, forms, screenshots, video, persistent login), or Tier 1/1.5 failed.
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Both tiers are omowright, staged inside the `browser` skill and loaded from js eval:
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
```js
|
|
90
|
+
const { loadOmowright } = await import("<browser-skill-root>/scripts/omowright.mjs")
|
|
91
|
+
const { omowright } = await loadOmowright()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Tier 2a — owned engine (default)
|
|
95
|
+
|
|
96
|
+
A browser your code launches with a task-owned profile. `connectPipe` opens no listening port; `connectCloakProfile` launches CloakBrowser with a pinned fingerprint seed and is the path for WAF, Cloudflare and bot-scored pages.
|
|
90
97
|
|
|
91
98
|
```js
|
|
92
|
-
const
|
|
99
|
+
const browser = await omowright.connectPipe({ browserPath, browserArgs: ["--headless", `--user-data-dir=${profile}`], storageRoot: profile })
|
|
93
100
|
try {
|
|
94
|
-
await
|
|
95
|
-
const
|
|
96
|
-
|
|
101
|
+
const page = await browser.newTab(url)
|
|
102
|
+
const tree = omowright.compactSnapshot(await page.snapshot()) // the read; refs come from it
|
|
103
|
+
const snoop = omowright.createNetworkSnoop(page) // read the API JSON instead of the DOM when there is one
|
|
104
|
+
await page.locator("e3").click()
|
|
105
|
+
await Bun.write(pngPath, await page.screenshot())
|
|
97
106
|
} finally {
|
|
98
|
-
|
|
107
|
+
await browser.close() // then rm -rf the profile
|
|
99
108
|
}
|
|
100
109
|
```
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
### Tier 2b — Chrome stealth (blocked or logged-in pages)
|
|
111
|
+
The rest of the surface (CUA coordinates, captcha solving, routes, traces, frames, human handoff) is in the `browser` skill's `references/owned-engine/`. A stealth binary is not proof of access: inspect the rendered result and report challenges that remain.
|
|
105
112
|
|
|
106
|
-
|
|
113
|
+
### Tier 2b — attached engine (logged-in pages)
|
|
107
114
|
|
|
108
|
-
|
|
115
|
+
When the page needs the user's account, drive the browser they are already signed into instead of cloning their profile: `connectBrowserSkill()` → `session.navigate` → `bskSnapshot(session)` / `session.observe()` → `session.click` → `session.stop()`. NEVER launch against or clear cookies/cache/site data from the user's live profile, and never fall back to the owned engine for an authenticated criterion: if no extension is connected, run the `browser` skill's onboarding script and relay its one human step. The full loop is the `browser` skill.
|
|
109
116
|
|
|
110
117
|
### Cookie login (cross-platform)
|
|
111
118
|
|
|
@@ -119,7 +126,7 @@ python3 scripts/extract_cookies.py --browser chrome --domain youtube.com --outpu
|
|
|
119
126
|
python3 scripts/extract_cookies.py --browser chrome --domain youtube.com --inject --cdp 9242
|
|
120
127
|
```
|
|
121
128
|
|
|
122
|
-
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. Cookies apply on next navigation — reload after injecting. Google services use fingerprint-bound tokens that may not transfer across browser profiles.
|
|
129
|
+
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. Cookies apply on next navigation — reload after injecting. Google services use fingerprint-bound tokens that may not transfer across browser profiles. Limits in [references/chrome-stealth.md](references/chrome-stealth.md).
|
|
123
130
|
|
|
124
131
|
## Reference docs
|
|
125
132
|
|
|
@@ -127,7 +134,7 @@ Cookie export files are written with owner-only `0600` permissions. Do not place
|
|
|
127
134
|
|------|-------------|
|
|
128
135
|
| [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 |
|
|
129
136
|
| [references/agent-reach/README.md](references/agent-reach/README.md) | Tier-1.5 routing table, platform auth, per-category `*.md` |
|
|
130
|
-
| [references/chrome-stealth.md](references/chrome-stealth.md) | Tier-2
|
|
137
|
+
| [references/chrome-stealth.md](references/chrome-stealth.md) | Tier-2 stealth through omowright + CloakBrowser, cookie login limits |
|
|
131
138
|
|
|
132
139
|
## Environment variables
|
|
133
140
|
|
|
@@ -65,7 +65,7 @@ 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 (
|
|
68
|
+
(agent-reach) and Tier 2 (omowright from js eval: owned and attached engines via the `browser` skill).
|
|
69
69
|
Upstream has no such tiering.
|
|
70
70
|
|
|
71
71
|
### WANT — upstream improvements worth porting forward
|
|
@@ -1,113 +1,45 @@
|
|
|
1
|
-
# Tier 2 —
|
|
1
|
+
# Tier 2 — stealth through omowright and CloakBrowser
|
|
2
2
|
|
|
3
|
-
For real-Chrome semantics, stealth, traces, or authenticated sessions,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`new Bun.WebView()`; Linux/Windows WebView needs installed Chrome/Chromium/Edge.
|
|
7
|
-
Codex's ordinary browser surface is `browser:control-in-app-browser`.
|
|
3
|
+
For real-Chrome semantics, stealth, traces, or authenticated sessions, drive omowright from the
|
|
4
|
+
js-eval kernel. The library is staged inside the `browser` skill; load it with
|
|
5
|
+
`loadOmowright()` from that skill's `scripts/omowright.mjs`.
|
|
8
6
|
|
|
9
|
-
##
|
|
7
|
+
## Stealth is the engine, not a plugin
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
18
|
-
```
|
|
19
|
-
|
|
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.
|
|
24
|
-
|
|
25
|
-
## Launch + drive
|
|
26
|
-
|
|
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:
|
|
9
|
+
Bot-scored pages (Cloudflare Turnstile, FingerprintJS, DataDome) are handled by launching
|
|
10
|
+
**CloakBrowser** — a Chromium build with source-level fingerprint patches — through
|
|
11
|
+
`connectCloakProfile({ profileDir })`. The profile pins a fingerprint seed on first use and
|
|
12
|
+
refuses to change identity silently, so the same site sees the same browser on every run.
|
|
34
13
|
|
|
35
14
|
```js
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
}
|
|
15
|
+
const browser = await omowright.connectCloakProfile({ profileDir })
|
|
16
|
+
try {
|
|
17
|
+
const page = await browser.newTab(url)
|
|
18
|
+
console.log(await page.evaluate("navigator.webdriver")) // must be false
|
|
19
|
+
await Bun.write(pngPath, await page.screenshot())
|
|
20
|
+
} finally {
|
|
21
|
+
await browser.close()
|
|
59
22
|
}
|
|
60
|
-
capture().catch((error) => { console.error(error); process.exitCode = 1; });
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Run the script from js eval with a bounded process lifetime:
|
|
64
|
-
|
|
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)
|
|
70
23
|
```
|
|
71
24
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
only with an available display when headed behavior is the criterion.
|
|
77
|
-
|
|
78
|
-
## Verify stealth
|
|
79
|
-
|
|
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.
|
|
84
|
-
|
|
85
|
-
## Cookie login (cross-platform)
|
|
86
|
-
|
|
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
|
-
|
|
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.
|
|
25
|
+
Do not pass an init-script for `navigator.webdriver` and do not add stealth plugins: CloakBrowser
|
|
26
|
+
patches the engine itself. A launch that still meets a challenge is handled by the `browser`
|
|
27
|
+
skill's ladder (`references/owned-engine/ladder.md`: layers, coordinates, `createCaptcha`), and a
|
|
28
|
+
page that only a signed-in user can reach belongs to the attached engine, not to a cloned profile.
|
|
95
29
|
|
|
96
|
-
##
|
|
30
|
+
## Cookie login limits
|
|
97
31
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
-
|
|
101
|
-
- Never run plugins without explicit user-installed script dependencies.
|
|
32
|
+
`scripts/extract_cookies.py` still exports cookies from a local browser; inject them with
|
|
33
|
+
`injectCookies(page, cookies)` into an **owned** profile. It sanitizes the set (drops expired
|
|
34
|
+
entries, keeps host-prefixed cookies secure and root-scoped). Limits that do not change:
|
|
102
35
|
|
|
103
|
-
|
|
36
|
+
- Accounts whose risk engines bind a session to a device (Google, password managers) invalidate a
|
|
37
|
+
session reused from a new fingerprint; use the attached engine for those.
|
|
38
|
+
- Cookies apply on the next navigation — reload after injecting.
|
|
39
|
+
- NEVER copy a session out of, or clear cookies/cache/site data in, the user's live profile.
|
|
104
40
|
|
|
105
|
-
|
|
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.
|
|
41
|
+
## The extraction engine's own Playwright fallback
|
|
110
42
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
43
|
+
The Tier-1 Python engine (`engine/`) keeps its own script-based Chrome fallback for headless
|
|
44
|
+
extraction; that is an engine internal, not an agent-facing browser path. Interactive work, QA and
|
|
45
|
+
screenshots go through omowright as above.
|
package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md
CHANGED
|
@@ -223,17 +223,11 @@ 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
|
-
브라우저를 직접 제어할 때는 js eval에서
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
```bash
|
|
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
|
|
235
|
-
```
|
|
236
|
-
Chrome은 이미 설치되어 있어야 한다. 인증 프로필은 먼저 복제하고 복제본만 사용한다.
|
|
226
|
+
브라우저를 직접 제어할 때는 js eval에서 omowright를 쓴다(`browser` 스킬에 스테이징됨):
|
|
227
|
+
직접 띄우는 브라우저는 `connectPipe` / 스텔스는 `connectCloakProfile`(CloakBrowser),
|
|
228
|
+
사용자가 로그인해 둔 브라우저는 `connectBrowserSkill`. 이 엔진의 Playwright 템플릿은
|
|
229
|
+
Tier 1 추출 폴백 전용이며 에이전트가 직접 브라우저를 다루는 경로가 아니다.
|
|
230
|
+
인증이 필요한 페이지는 사용자 프로필을 복제하지 말고 attached 엔진으로 간다.
|
|
237
231
|
|
|
238
232
|
## 빠른 참조 — Phase 0 명령어
|
|
239
233
|
|
package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
### 의존성
|
|
18
18
|
|
|
19
19
|
이 항목은 이미 연결된 MCP를 사용하는 엔진 어댑터의 설명이다.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
에이전트가 직접 여는 브라우저 세션은 js eval의 omowright(`browser` 스킬에 스테이징)로
|
|
21
|
+
띄운다: 직접 소유 브라우저는 `connectPipe`, 스텔스는 `connectCloakProfile`, 사용자 로그인이
|
|
22
|
+
필요하면 `connectBrowserSkill`. MCP를 새로 설치하지 않는다.
|
|
23
23
|
|
|
24
24
|
### 기본 워크플로
|
|
25
25
|
|
|
@@ -52,15 +52,14 @@ Linux/Windows는 설치된 Chrome/Chromium/Edge 필요), 그 외 또는 Chrome
|
|
|
52
52
|
|
|
53
53
|
### 의존성 (최초 1회)
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
엔진 템플릿의 스크립트 의존성은 `engine/templates/package.json`에 고정되어 있다.
|
|
56
|
+
엔진 디렉터리에서 한 번만 설치한다. Chrome은 이미 시스템에 설치되어 있어야 하며,
|
|
57
|
+
브라우저 다운로드 명령은 없다.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
```bash
|
|
60
60
|
cd "$SKILL_DIR/engine"
|
|
61
61
|
test -f package.json || cp templates/package.json package.json
|
|
62
|
-
bun
|
|
63
|
-
# Chrome은 이미 시스템에 설치되어 있어야 한다. 브라우저 다운로드 명령은 없다.
|
|
62
|
+
bun install
|
|
64
63
|
```
|
|
65
64
|
|
|
66
65
|
### 호출 (engine 내부)
|
|
@@ -76,39 +75,23 @@ attempt, html = run_playwright_fallback(
|
|
|
76
75
|
)
|
|
77
76
|
```
|
|
78
77
|
|
|
79
|
-
내부에서 `engine/templates/playwright_real_chrome.js` 또는 `playwright_mobile_chrome.js`를 Node로 실행하고 HTML을 받아온다. 템플릿은 **URL과 셀렉터 파라미터만** 받으며 사이트별 분기가 없다.
|
|
78
|
+
내부에서 `engine/templates/playwright_real_chrome.js` 또는 `playwright_mobile_chrome.js`를 Node로 실행하고 HTML을 받아온다. 템플릿은 **URL과 셀렉터 파라미터만** 받으며 사이트별 분기가 없다. 템플릿은 엔진이 실행하는 프로그램이다. 에이전트가 이 템플릿을 본떠 브라우저 스크립트를 새로 쓰지 않는다.
|
|
80
79
|
|
|
81
80
|
### 데스크톱 템플릿 (`playwright_real_chrome.js`)
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const stealth = require('puppeteer-extra-plugin-stealth')();
|
|
87
|
-
chromium.use(stealth);
|
|
88
|
-
|
|
89
|
-
const ctx = await chromium.launchPersistentContext(profileDir, {
|
|
90
|
-
channel: 'chrome', // ← 핵심: 번들 Chromium 아닌 실제 Chrome
|
|
91
|
-
headless: false, // Akamai는 headless 탐지. headful 필요.
|
|
92
|
-
viewport: { width: 1366, height: 900 },
|
|
93
|
-
});
|
|
94
|
-
```
|
|
82
|
+
- 번들 Chromium이 아니라 **시스템에 설치된 실제 Chrome**을 띄운다. TLS 지문이 실제 Chrome이 되는 것이 핵심이다.
|
|
83
|
+
- stealth 플러그인을 적용하고, 작업 전용 영속 프로필 디렉터리를 쓴다.
|
|
84
|
+
- Akamai는 headless를 탐지하므로 **headful**로 실행하고, 뷰포트는 1366×900이다.
|
|
95
85
|
|
|
96
86
|
### 모바일 템플릿 (`playwright_mobile_chrome.js`)
|
|
97
87
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const ctx = await chromium.launchPersistentContext(profileDir, {
|
|
105
|
-
channel: 'chrome', // TLS는 실제 Chrome
|
|
106
|
-
...iPhone, // UA/viewport/isMobile/hasTouch 자동 주입
|
|
107
|
-
headless: false,
|
|
108
|
-
});
|
|
109
|
-
```
|
|
88
|
+
- TLS는 데스크톱과 같은 실제 Chrome이고, iPhone 13 Pro 디바이스 기술자(UA/viewport/isMobile/hasTouch)만 주입한다. headful로 실행한다.
|
|
89
|
+
|
|
90
|
+
**주의**: 실제 Chrome + 모바일 디바이스 기술자 조합은 TLS 핑거프린트를 Chrome으로 유지하면서 HTTP 레이어(UA/viewport)만 모바일로 바꾼다. WAF가 실제 Chrome으로 인식해서 관대한 경우가 많다.
|
|
91
|
+
|
|
92
|
+
### 엔진 밖에서 같은 효과가 필요할 때
|
|
110
93
|
|
|
111
|
-
|
|
94
|
+
엔진 폴백이 아니라 에이전트가 직접 페이지를 조작해야 한다면 js eval에서 omowright(`browser` 스킬에 스테이징)를 쓴다. 지문이 고정된 스텔스 브라우저는 `connectCloakProfile({ profileDir })`, 모바일 뷰는 `emulate(page, "iphone-14")`, 사용자 로그인이 필요하면 `connectBrowserSkill()`이다.
|
|
112
95
|
|
|
113
96
|
## 선택 규칙 (자동)
|
|
114
97
|
|
|
@@ -129,8 +112,8 @@ const ctx = await chromium.launchPersistentContext(profileDir, {
|
|
|
129
112
|
|
|
130
113
|
## 디버깅 팁
|
|
131
114
|
|
|
132
|
-
-
|
|
133
|
-
-
|
|
115
|
+
- 템플릿의 `profileDir`는 작업 전용 경로만 사용한다. 사용자의 실제 프로필을 실행·복제·초기화·삭제하지 않는다.
|
|
116
|
+
- 작업 종료 시 브라우저를 닫고 작업 전용 프로필만 정리한다.
|
|
134
117
|
- 실패 시 `result.trace`의 `error` 필드에 Node stderr 200자가 포함됨
|
|
135
118
|
|
|
136
119
|
## 사이트 예시 (독자 이해용, 코드 분기 근거 아님)
|