Skip to content

Contributing

Hermes Agent edited this page Oct 1, 2026 · 2 revisions

Contributing

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

Commands

npm test                        # full test suite (Node built-in runner, no build needed)
node --test test/foo.test.mjs   # single file
npm run package                 # build the versioned zip (browsa-vX.Y.Z.zip)
npm run build                   # esbuild vendor bundle (only needed after build.mjs changes)
bash check-compat.sh            # static compatibility check

The 4GB box constraint: the suite is 103 files (~36 jsdom-heavy) on a 2CPU/4GB VPS; the script caps concurrency at 2, prefer --test-concurrency=1 on 4GB. Never allocate tens-of-MB blobs in tests (a single 44MB mock OOM'd the box once — real recurrence); prefer pure-function tests (no DOM, no big buffers).

Testing philosophy

  • Tests mock the chrome global before importing real modules; jsdom tests use the REAL vendored marked/DOMPurify/katex/highlight.js bundles, not stand-ins.
  • sidepanel.js has zero exports — its tests load the whole sidepanel.html into jsdom and drive it black-box (simulated clicks/keys/port messages).
  • Worker clients hold module-level singletons → scenarios needing a fresh singleton MUST be separate test FILES (the runner isolates per file/process).
  • Lockstep discipline: facts mirrored in several places (regexes, field names, CSS/hint pairs, tab order) either collapse into one source or get pinned by source-regex with an AGENTS.md "change both in lockstep" note. Example: subchat.test.mjs regex-locks the exact pushSubChatChunk(… SUBCHAT_DONE …) source line.
  • Detail-thread / streaming tests MUST end the turn (DONE / ■ / close), or the turn port's 20s SW_PING interval leaks and hangs the runner.
  • WASM is the exception to "no real execution": WebAssembly.instantiate runs in Node, so the pdf-inspector tests execute the real vendored binary.

Refactoring principles (earned through incidents; from AGENTS.md)

  • N switch cases differing only by literals → one lookup table; two hand-written implementations of the same wire protocol → one shared function with hooks (the DONE-handler drift was a real bug family).
  • After every extraction run the FULL suite AND check-compat.sh — a syntax check proves nothing.
  • Grep the whole repo (including test/) before declaring an export dead; a test-only export is not automatically dead — read the surrounding comments.

dev-preview (headless-environment extension UI preview)

node dev-preview/gen.mjs        # regenerate preview pages from real sidepanel.html (rerun after HTML changes)
python3 -m http.server 8931     # from the repo root
# http://127.0.0.1:8931/dev-preview/sidepanel.preview.html

A chrome-shim provides the minimal chrome.* surface; seed.js injects a rich history. Screenshots go through CDP Page.captureScreenshot (plain, no clip/scale; page.screenshot() has dark-mode artifacts). A passing preview ≠ a passing real extension: the shim's sendMessage envelopes must mirror the real contract byte-for-byte, and CSP-class verification always requires a real extension load.

Release flow

  1. Bump the version in BOTH manifest.json and package.json.
  2. PR → CI green → squash-merge to main → back-fill dev: git reset --hard origin/main && git push --force-with-lease origin dev (merge-based back-fill pollutes main..dev; the PR page's Delete branch button would delete dev).
  3. Version-bump PRs flow through the reusable release workflows (xiaohuzai/release-flow@v1) with tests waived (PAT mode).
  4. Store listing copy is generated with the .agents/skills/cws-listing skill (the tag is the version source of truth); rejection history is on record.
  5. Docs-sync discipline (any user-visible change, same PR): README in both languages (section-aligned mirrors) → the docs site (both languages) → screenshots/banners/demo GIF/promo video each CONSIDERED (legibility judged at the asset's own resolution; a changed GIF must change filename to defeat caches) → architecture-level facts recorded in AGENTS.md.

Red lines (quick list)

No auto-commit/packaging (wait for explicit instruction) · no full test run before packaging (targeted green is enough) · use the current version, never bump on your own · the extension private key never leaves /root/workspace/browsa-keys/ · user-facing copy avoids jargon (zh carries no English jargon) · stored image pixels are never destroyed · thinking defaults to omit.


Source of truth: AGENTS.md "Testing" / "Refactoring principles" sections; the packaging/commit discipline notes; the docs-sync convention. Synced 2026-10-01.

Clone this wiki locally