# BugSketch 0.2.0

A local-first issue-reporting widget for websites. No account, default upload or report backend. MIT licensed. The source archive contains only BugSketch and its pinned renderer, not the private website repository.

## Install

Add one deferred script before `</body>`:

```html
<script defer src="https://aviralgarg.com/bugsketch/bugsketch-0.2.0.js"></script>
```

A bug button appears. Choose Visible area, Full page (loaded content), Import PNG, or the original note/mark workflow. Add rectangles, circles and short callouts, then one issue note. Review before downloading a flattened PNG/JSON or copying readable text. No upload happens by default.

## Self-host

Download this archive and serve all three files in `dist/` together from your HTTPS site: `bugsketch-0.2.0.js`, `bugsketch-recorder-0.2.0.js` and `recorder.html`. The widget opens the sibling recorder page in a separate tab. For a different location, set `window.BugSketchConfig = {recorderUrl: "https://your-site.example/tools/recorder.html"}` before the widget loads. Keep LICENSE and THIRD-PARTY-NOTICES.txt with redistributed files. No runtime CDN, account or API key is needed. The reviewed modern-screenshot 4.7.0 distribution and MIT license are in `vendor/modern-screenshot/`.

To rebuild: use Node 20 or later, run `npm install --ignore-scripts`, then `npm run build`. Exact dependency versions are pinned in package.json. The renderer is vendored so the build uses exactly the reviewed release.

## Host integration (optional)

After the script loads, `BugSketch.open()` opens the widget. A button marked `data-bugsketch-open` present when the deferred script initializes also opens it.

`BugSketch.setReceiver(async ({report, image}) => { /* your receiver */ })` enables a separate Share with this website button. It runs only after review consent and an explicit share click. `report` is a cloned bugsketch/1 JSON object and `image` is the final flattened PNG Blob. Your host code controls any further network delivery and must accurately explain it. The widget does not infer delivery from a successful callback. Set `null` to remove the callback. No receiver is configured on the public demo.

`BugSketch.cancel()` cancels the image flow, aborts pending capture and dictation, clears image/history buffers and revokes owned object URLs. The original note/mark UI and schema remain available separately.

## Privacy and fidelity

- Capture is explicitly requested. Inputs, textareas, selects, editable content and `[data-bugsketch-private]`, `[data-private]` or `[data-sensitive]` elements are masked. Use `data-bugsketch-private` on your app's sensitive regions. This cannot identify every visible secret: review and redact manually.
- Redaction writes opaque pixels permanently, removes intersecting annotation text and clears annotation undo history. Redactions cannot be undone. Review issue notes/callout text too; image redaction does not edit your note.
- Exports contain the flattened PNG and explicit report text/geometry only. No original image/file, raw DOM/SVG, hidden text, cookies, browser storage, console/network logs or automatically collected URL query/hash is attached. Image imports are re-encoded without original PNG metadata. File names are not collected.
- The default URL is origin+path, and can be removed. Ordinary same-origin, credential-free image/font reads may occur while rendering; no report upload or third-party proxy occurs.
- DOM rendering is not a native or pixel-exact browser screenshot. The pinned modern-screenshot renderer is used directly. Renderer warnings/errors reject capture instead of accepting placeholders. Cross-origin/query-bearing assets/stylesheets, iframe/media/canvas/WebGL/web components and fixed/sticky content require screenshot import. Custom/advanced CSS may differ: inspect the result.
- Full page means currently loaded DOM, not unloaded lazy/virtualized content. Scrollable subregions are rejected for full capture. Full images are not silently scaled/cropped. Visible capture renders a bounded prefix then explicitly crops the chosen viewport.
- Limits: PNG imports ≤ 20 MB, dimensions 128 × 96 px minimum through 4096 px wide / 8192 px high and 8 megapixels maximum; 12,000 DOM elements; 16 marks, 140 characters/callout, 3,000 characters/issue note; 20 annotation undo states; 15 s capture cancellation budget and 8 s resource timeout. Invalid/unsupported captures offer import or note-only fallback.
- Test evidence covers synthetic Chromium cases. Do not assume every browser, CSS feature or host site is supported. Media/screenshots are never obtained by silently changing browser permissions.

## Keyboard and touch

Buttons are 44 px and fields 16 px. Scroll mode allows touch scrolling through a tall image. Move mode drags a mark or its callout. Select a mark in the list, then use arrow keys (Shift = 10 pixels); Alt+arrows moves its callout. Delete removes it; Ctrl/Cmd+Z undoes annotations. Automatic label placement stays in bounds and avoids existing callout boxes where space allows. Shorten text if it cannot fit legibly in the image.

## Schemas

New image reports use `bugsketch/1`. Legacy text/mark reports retain `issue-reporter/0.2`, document CSS coordinates and explicit selected text. The new format does not mix image coordinates with legacy document coordinates. Existing report files are not overwritten or migrated.

## Walkthrough recording

Choose **Record a walkthrough** to open a dedicated tab. Keep it open and select the original site tab/window in the browser screen picker. The original site can navigate without unloading this recorder. Start/Stop and an elapsed timer are explicit. No account or upload. Optional microphone recording is off by default; system/tab audio is off. Closing this recorder ends capture and discards unsaved data.

Recording contains the selected surface as displayed. It does **not** mask forms or redact video. Review the local replay and edit/remove timed notes before enabling downloads. Export the browser-supported WebM/MP4 video and `bugsketch-walkthrough/1` JSON. Typed notes have approximate elapsed offsets; final speech results are timestamped when received, not aligned to words. Source window titles and page URLs are not collected.

Limits: 5 minutes, 64 MB encoded media and 100 notes of up to 1,000 characters. The duration limit stops and finalizes recording. Exceeding the memory limit discards the recording with a clear message. Tracks, listeners, intervals and speech are stopped on Stop, cancellation/error or recorder unload. Replay/download URLs are revoked on discard/new recording/unload; each download URL also expires after 10 seconds.

Screen recording requires a supported desktop HTTPS browser and the user's actual screen-selection prompt. Unsupported MIME formats, permission denial or missing APIs produce an explicit fallback message. The widget does not change browser/OS permissions. Saved checks use only synthetic video/audio and fake recognition results, with actual Chromium MediaRecorder encoding and decoded replay; no real screen/microphone/speech access was tested.

## Optional speech

Dictation is available both for screenshot issue notes and recorder timed notes. Typing always works. Start/stop dictation is explicit, independent of the recording-audio microphone checkbox. On-device is the default: the browser must expose `processLocally` and confirm an already-installed English (US) dictation language pack. No language-pack installation or online fallback starts automatically. If unavailable, type or deliberately choose a browser speech service.

Online mode requires a separate checkbox explaining that microphone audio may leave the device and the browser service's processing/retention policies apply. The widget has no speech API key or provider/backend. Only final text is appended, and the user can edit it. Browser recognition can stop early; it does not automatically restart. Screenshot dictation stops after 60 seconds; recorder dictation stops no later than 5 minutes and always stops with recording. Reviewing/closing/discarding an image or ending a recorder aborts recognition and ignores late results.

## Remaining scope

Hosted report intake remains optional and unselected. The MIT tool is usable locally without a backend. Universal browser/CSS fidelity, automatic secret detection and remote delivery are not claimed.
