* refactor(tests): reorganize into tests/unit and tests/integration
Moves all root-level test_*.py files into a structured tests/ directory:
- tests/unit/ — admin, helpers (was test_screenshot), run
- tests/integration/ — js expression tests
- tests/conftest.py — shared fake_png pytest fixture, eliminating duplication
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: move to src layout, agent-workspace, and fix SKILL.md invocation format
- Move package to src/browser_harness/ and domain-skills/interaction-skills to agent-workspace/
- Fix all browser-harness <<'PY' heredoc examples in SKILL.md and run.py HELP string to use the correct -c '...' flag format (heredoc was never supported by the CLI)
- Update SKILL.md path references from domain-skills/ to agent-workspace/domain-skills/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- goto() → goto_url()
- click() → click_at_xy()
- screenshot() → capture_screenshot()
These three shared exact names with Playwright but different argument
shapes, causing agent confusion. Updated helpers.py and all markdown
skill files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two new domain skills for amazon.com derived from a logged-in session:
- cart.md: documents the empty-cart trap where `[data-asin]` selectors
match recommendation widgets even on an empty cart, plus the stable
subtotal selectors and the price-change banner format.
- orders.md: covers the order-list card structure, the order-search
quirk (the `?search=` URL param doesn't filter — must submit the
form or hit the post-submit `/your-orders/search/` URL), and the
tracking page (whose `data-test-id` selectors are all null — extract
from `body.innerText` anchored on the "Arriving" line).
Ran actual browser-harness sessions against each site and rewrote
the skill files from live test findings. Key corrections:
GitHub: wait(2) after wait_for_load() for React hydration; search API
separate 10 req/min limit; search/code needs auth (401 unauthed)
HackerNews: athing also matches comment rows (use 'athing submission');
job posts break naive score-zip; html.unescape() required for titles
Amazon: .zg-item-immersion gone from Best Sellers; #priceblock_ourprice
returns null (legacy); review count selector collides with cross-sell
widget — use [aria-label*='ratings'] instead
News: The Verge is Atom not RSS (namespace dict required); Reuters
hard-blocks http_get with 403 even with User-Agent; BBC shows no
consent banner from US IP; parallel fetch is 4.3x faster (0.16s vs 0.70s)
ProductHunt: goto() ERR_ABORTED — always use new_tab(); /posts/ URLs
don't exist (it's /products/); homepage has 30 fixed items no lazy load;
[data-test^='post-item-'] is the correct card selector