Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion skill-src/webcmd-browser/SKILL.src.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,20 @@ JS

If you split work across calls, use fresh snapshots between page transitions. Do not assume an observation from a prior route is still valid.

To contend for one Session, issue a second `webcmd --session <session-id> …` while the first invocation is still running. Do not start a second driver inside one `run` (`Promise.all` of two writes, a homemade busy flag, or `page.evaluate` locking).

```bash
# Terminal A — long run holding the Session
webcmd --session session_abc browser run --file long.js

# Terminal B — second command against the same Session
webcmd --session session_abc browser run --stdin --no-snapshot-diff <<'JS'
return { url: page.url() };
JS
```

If the second command returns `SESSION_BUSY`, wait for the listed holder, then retry that same command. Do not `--force` close a live holder.

---

## Sitemaps
Expand Down Expand Up @@ -248,6 +262,7 @@ Use `run` and inspect `page.frames()`; target the frame by URL/name and keep ifr

- **Do not submit forms via `page.evaluate(() => document.forms[0].submit())`.** Modern sites intercept real click/submit events and silently drop direct DOM submission. Use Playwright locators and verify the post-action state.
- **Do not reuse observations across a page transition.** Navigations, form submits, SPA route changes, login, and human handoff invalidate earlier observations. Take a fresh snapshot.
- **Do not implement Session occupancy inside the page.** Overlap two CLI invocations on the same `--session` id. A homemade busy flag is not `SESSION_BUSY`.
- **Do not run a trigger before arming the waiter.** If a request matters, create `page.waitForResponse(...)` before the click/fill/keypress that triggers it.
- **Do not trust autocomplete or masked inputs blindly.** Fill/type can appear to work while the app rejects the value. Verify visible text, `inputValue()`, or post-action state.
- **Do not solve CAPTCHA or auth challenges programmatically.** Use human handoff and verification.
Expand All @@ -270,7 +285,7 @@ Use `run` and inspect `page.frames()`; target the frame by URL/name and keep ifr
| `run` times out before returning | Increase `--timeout` only after checking whether the wait condition is wrong. |
| Write may have happened before timeout | Take a fresh snapshot before retrying. Avoid duplicate submissions. |
| `SESSION_REQUIRED` | Create a Session, then retry with root `--session <session-id>`. |
| `SESSION_BUSY` | Wait for the listed holder; if it is dead, `webcmd session close <session-id> --force` is the last resort. |
| `SESSION_BUSY` | Wait for the listed holder, then retry the same command. If it is dead, `webcmd session close <session-id> --force` is the last resort. Do not lock inside `page.evaluate`. |
| `SESSION_PAUSED_FOR_HUMAN_HANDOFF` | Finish the handoff and run the returned verifier before retrying. |
| Login wall appears | Use the Authentication and human handoff recipe. |
| User reports login complete | Run the returned verifier first. Without one, inspect fresh state and verify identity/post-action state. |
Expand All @@ -294,4 +309,8 @@ Author-only. Stripped by litprompt, so it costs the running agent nothing.
Append one dated line whenever a correction lands, or whenever an approach
is tried and rejected. Record what was tried and why it failed, not just
what won.

- 2026-08-20: Agents treated an in-page mutex as the session safety signal.
`SESSION_BUSY` is a CLI error from a second `webcmd --session` invocation, not
a flag inside `page.evaluate`.
-->
14 changes: 9 additions & 5 deletions skill-src/webcmd-usage/SKILL.src.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ webcmd session close session_abc
Adapter commands may omit `--session` and use the selected profile's adapter-default session. Pass `--session <session-id>` to route one into an explicit session. Raw browser commands never omit it; the retired positional session form is invalid.

Structured Session failures are runtime state, not adapter breakage. `SESSION_REQUIRED`
means add a root `--session <session-id>` selector before `browser`; `SESSION_BUSY`
means another holder owns the same Session or site scope, so wait, inspect
`webcmd session list`, and use `webcmd session close <session-id> --force` only
when the holder is dead. `SESSION_PAUSED_FOR_HUMAN_HANDOFF` means finish the
handoff and run its verifier before retrying.
means add a root `--session <session-id>` selector before `browser`. `SESSION_BUSY`
means another CLI invocation already drives that Session: wait for the listed holder,
then retry the same command. Produce it by issuing a second `webcmd --session <id> …`
while the first is still running — not by locking inside `page.evaluate`. Use
`webcmd session close <session-id> --force` only when the holder is dead.
`SESSION_PAUSED_FOR_HUMAN_HANDOFF` means finish the handoff and run its verifier before retrying.

## Prerequisites By Strategy

Expand Down Expand Up @@ -282,4 +283,7 @@ Author-only. Stripped by litprompt, so it costs the running agent nothing.
Append one dated line whenever a correction lands, or whenever an approach
is tried and rejected. Record what was tried and why it failed, not just
what won.

- 2026-08-20: `SESSION_BUSY` was named in troubleshooting but not as two overlapping
CLI invocations. In-page locks are not that error.
-->
17 changes: 16 additions & 1 deletion skills/webcmd-browser/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,20 @@ JS

If you split work across calls, use fresh snapshots between page transitions. Do not assume an observation from a prior route is still valid.

To contend for one Session, issue a second `webcmd --session <session-id> …` while the first invocation is still running. Do not start a second driver inside one `run` (`Promise.all` of two writes, a homemade busy flag, or `page.evaluate` locking).

```bash
# Terminal A — long run holding the Session
webcmd --session session_abc browser run --file long.js

# Terminal B — second command against the same Session
webcmd --session session_abc browser run --stdin --no-snapshot-diff <<'JS'
return { url: page.url() };
JS
```

If the second command returns `SESSION_BUSY`, wait for the listed holder, then retry that same command. Do not `--force` close a live holder.

---

## Sitemaps
Expand Down Expand Up @@ -248,6 +262,7 @@ Use `run` and inspect `page.frames()`; target the frame by URL/name and keep ifr

- **Do not submit forms via `page.evaluate(() => document.forms[0].submit())`.** Modern sites intercept real click/submit events and silently drop direct DOM submission. Use Playwright locators and verify the post-action state.
- **Do not reuse observations across a page transition.** Navigations, form submits, SPA route changes, login, and human handoff invalidate earlier observations. Take a fresh snapshot.
- **Do not implement Session occupancy inside the page.** Overlap two CLI invocations on the same `--session` id. A homemade busy flag is not `SESSION_BUSY`.
- **Do not run a trigger before arming the waiter.** If a request matters, create `page.waitForResponse(...)` before the click/fill/keypress that triggers it.
- **Do not trust autocomplete or masked inputs blindly.** Fill/type can appear to work while the app rejects the value. Verify visible text, `inputValue()`, or post-action state.
- **Do not solve CAPTCHA or auth challenges programmatically.** Use human handoff and verification.
Expand All @@ -270,7 +285,7 @@ Use `run` and inspect `page.frames()`; target the frame by URL/name and keep ifr
| `run` times out before returning | Increase `--timeout` only after checking whether the wait condition is wrong. |
| Write may have happened before timeout | Take a fresh snapshot before retrying. Avoid duplicate submissions. |
| `SESSION_REQUIRED` | Create a Session, then retry with root `--session <session-id>`. |
| `SESSION_BUSY` | Wait for the listed holder; if it is dead, `webcmd session close <session-id> --force` is the last resort. |
| `SESSION_BUSY` | Wait for the listed holder, then retry the same command. If it is dead, `webcmd session close <session-id> --force` is the last resort. Do not lock inside `page.evaluate`. |
| `SESSION_PAUSED_FOR_HUMAN_HANDOFF` | Finish the handoff and run the returned verifier before retrying. |
| Login wall appears | Use the Authentication and human handoff recipe. |
| User reports login complete | Run the returned verifier first. Without one, inspect fresh state and verify identity/post-action state. |
Expand Down
11 changes: 6 additions & 5 deletions skills/webcmd-usage/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ webcmd session close session_abc
Adapter commands may omit `--session` and use the selected profile's adapter-default session. Pass `--session <session-id>` to route one into an explicit session. Raw browser commands never omit it; the retired positional session form is invalid.

Structured Session failures are runtime state, not adapter breakage. `SESSION_REQUIRED`
means add a root `--session <session-id>` selector before `browser`; `SESSION_BUSY`
means another holder owns the same Session or site scope, so wait, inspect
`webcmd session list`, and use `webcmd session close <session-id> --force` only
when the holder is dead. `SESSION_PAUSED_FOR_HUMAN_HANDOFF` means finish the
handoff and run its verifier before retrying.
means add a root `--session <session-id>` selector before `browser`. `SESSION_BUSY`
means another CLI invocation already drives that Session: wait for the listed holder,
then retry the same command. Produce it by issuing a second `webcmd --session <id> …`
while the first is still running — not by locking inside `page.evaluate`. Use
`webcmd session close <session-id> --force` only when the holder is dead.
`SESSION_PAUSED_FOR_HUMAN_HANDOFF` means finish the handoff and run its verifier before retrying.

## Prerequisites By Strategy

Expand Down
2 changes: 2 additions & 0 deletions src/skills.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ describe('webcmd skills content', () => {
expect(browser).toContain('SESSION_BUSY');
expect(browser).toContain('SESSION_PAUSED_FOR_HUMAN_HANDOFF');
expect(browser).toContain('webcmd session close <session-id> --force');
expect(usage).toMatch(/second `webcmd --session <id>/);
expect(browser).toContain('Do not implement Session occupancy inside the page');
for (const skill of [usage, browser, autofix]) {
expect(skill).toMatch(/handoff is scoped to (?:its|the) Session/i);
expect(skill).toMatch(/(?:verify_command|handoff\.verifyCommand)[\s\S]{0,200}verbatim[\s\S]{0,120}`--session`/i);
Expand Down
Loading