qapture2 0.3.1 → 0.7.0
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 +280 -3
- package/dist/bin/init.cjs +2 -2
- package/dist/{chunk-2CAMCMJP.js → chunk-QBBWY3BF.js} +4723 -803
- package/dist/{chunk-PIN23NW3.cjs → chunk-UOUFJCPF.cjs} +4723 -803
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1 -1
- package/dist/next.cjs +4 -4
- package/dist/next.js +1 -1
- package/dist/standalone.cjs +2 -2
- package/dist/standalone.js +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -14,8 +14,16 @@ npm install qapture2
|
|
|
14
14
|
|
|
15
15
|
## Contents
|
|
16
16
|
|
|
17
|
+
- [What's new in v0.7 "Walk"](#whats-new-in-v07-walk)
|
|
18
|
+
- [What's new in v0.6 "Elbow Room"](#whats-new-in-v06-elbow-room)
|
|
19
|
+
- [What's new in v0.5 "Loop"](#whats-new-in-v05-loop)
|
|
20
|
+
- [What's new in v0.4 "Ledger"](#whats-new-in-v04-ledger)
|
|
17
21
|
- [Breaking Changes (v0.3.0 "Graphite")](#breaking-changes-v030-graphite)
|
|
18
22
|
- [Quick Start](#quick-start)
|
|
23
|
+
- [Steps to reproduce, recorded for you](#steps-to-reproduce-recorded-for-you)
|
|
24
|
+
- [Screenshots: two engines](#screenshots-two-engines)
|
|
25
|
+
- [Saving to a folder](#saving-to-a-folder)
|
|
26
|
+
- [Where notes live, and what "storage full" means](#where-notes-live-and-what-storage-full-means)
|
|
19
27
|
- [Config Reference](#config-reference)
|
|
20
28
|
- [Graded Risk Model](#graded-risk-model)
|
|
21
29
|
- [Guided Walkthrough (Test-Along)](#guided-walkthrough-test-along)
|
|
@@ -32,6 +40,67 @@ npm install qapture2
|
|
|
32
40
|
|
|
33
41
|
---
|
|
34
42
|
|
|
43
|
+
## What's new in v0.7 "Walk"
|
|
44
|
+
|
|
45
|
+
| | |
|
|
46
|
+
|---|---|
|
|
47
|
+
| **The Walk** | One guided sequence over either your test plan or your notes, with a **Take me there** button that actually navigates. Pressing a Guide step now walks from it. |
|
|
48
|
+
| **Walk the re-test queue** | Filter to Re-test, press Walk: each stop takes you to the page, lights up the spot, re-shoots it and takes your verdict. |
|
|
49
|
+
| **A link that starts it** | `?qa=walk:retest` opens the app with the re-test round already running — send that instead of instructions. |
|
|
50
|
+
| **"Doesn't apply"** | A third grade for plan steps that aren't relevant to this build. Removed from coverage totals rather than counted either way. |
|
|
51
|
+
| **Alt+1/2/3** | Set severity while typing a note. |
|
|
52
|
+
| **Session summary** | The export leads with "12 points · 5 bugs · 4 pages · over 38 minutes". |
|
|
53
|
+
|
|
54
|
+
**Two fixes from real use:** the widget could be hidden underneath an app's own high-z-index chrome (it now sits above everything, in its own stacking context, without ever swallowing a click), or removed outright by a framework clearing `<body>` (it now puts itself back). And the panel's open state, tab and walk position survive a reload — the notes always did, the *place in the work* didn't.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## What's new in v0.6 "Elbow Room"
|
|
59
|
+
|
|
60
|
+
| | |
|
|
61
|
+
|---|---|
|
|
62
|
+
| **Bulk actions** | Select many notes → mark them Open / Re-test / Verified, or delete them, in one pass with a single undo. |
|
|
63
|
+
| **Compact list** | One line per note, expanding in place — for when a session has thirty of them. |
|
|
64
|
+
| **Move the panel** | Dock it to the other edge, or collapse it to its header strip, so it stops covering the app you're testing. |
|
|
65
|
+
| **Whole-screen capture** | Grab everything visible without dragging a box across the screen. |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## What's new in v0.5 "Loop"
|
|
70
|
+
|
|
71
|
+
Not a breaking release. Notes from 0.3.x and 0.4.x read back unchanged.
|
|
72
|
+
|
|
73
|
+
| | |
|
|
74
|
+
|---|---|
|
|
75
|
+
| **Steps to reproduce, written for you** | Every note now carries what the tester clicked, typed into, toggled and navigated on the way to it. Never what they typed — see [below](#steps-to-reproduce-recorded-for-you). |
|
|
76
|
+
| **Draw on the screenshot** | Tap the shot, add an arrow / box / pen mark in one of four colours. Burned into the image, so it survives everywhere the screenshot goes. Never interrupts the capture flow. |
|
|
77
|
+
| **A capture shortcut** | `Alt+Shift+C` (`Option+Shift+C` on macOS) jumps straight into capture from anywhere; press again to back out. Configurable via `captureHotkey`. |
|
|
78
|
+
| **A re-test queue** | Note status is now Open → **Re-test** → Verified. "Re-test" is the state that tells a tester what to check on the next build, with a filter chip and a header badge so the queue can't be missed. |
|
|
79
|
+
| **Automatic backups** | A backup ZIP downloads every 5 notes, for everyone who can't use folder saving (Safari, Firefox, phones). Pauses itself while folder saving is on. |
|
|
80
|
+
| **Catches what you miss** | When the page throws an error or a request fails, Qapture offers a one-tap capture with the error already written in — the bug nobody reported because nobody saw it. |
|
|
81
|
+
| **Before / after on a re-test** | A note in the re-test queue gets a "Re-test now" button that re-shoots the same target, so "is it actually fixed?" is answered with a picture. |
|
|
82
|
+
| **Share (phones)** | Hands the campaign ZIP to the OS share sheet — WhatsApp, Mail, Files, AirDrop — because a "download" on a phone lands where nobody finds it. |
|
|
83
|
+
| **A welcome card** | Three lines, shown once, for someone who was just handed a beta link. |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## What's new in v0.4 "Ledger"
|
|
88
|
+
|
|
89
|
+
v0.4 is **not** a breaking release — every 0.3.x config, note and export keeps
|
|
90
|
+
working, and each new feature is off until someone turns it on.
|
|
91
|
+
|
|
92
|
+
| | |
|
|
93
|
+
|---|---|
|
|
94
|
+
| **Screenshots frame the right thing** | Capture mode's own scroll lock used `overflow:hidden`, which **unstuck every `position: sticky` header** just before the screenshot was rendered — measured at 20px of wrongness in a 40px capture, now 0.0px. See [Screenshots: two engines](#screenshots-two-engines). |
|
|
95
|
+
| **Pixel-exact capture (opt-in)** | A real photograph of the tab rather than a redraw — so canvas/WebGL, video, cross-origin iframes and exotic CSS all come out right. One prompt per session, Chromium desktop. |
|
|
96
|
+
| **Save straight to a folder** | Pick a QA folder once; every note is written to disk as it's saved, organised `Project / Campaign / notes + screenshots + REPORT.md`. See [Saving to a folder](#saving-to-a-folder). |
|
|
97
|
+
| **Storage that explains itself** | A real usage meter, WebP screenshots (~10× smaller), a request to stop the browser evicting your data, and a "drop screenshots, keep findings" recovery valve. |
|
|
98
|
+
| **A usable notes list** | Severity/status filter chips with counts, text search, and a "this page" toggle. |
|
|
99
|
+
| **Simple mode** | Hides Logins and Guide for a tester who was just handed a link. |
|
|
100
|
+
| **Minimized capture** | A small box next to your selection instead of the full card — type, Enter, move on. |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
35
104
|
## Breaking Changes (v0.3.0 "Graphite")
|
|
36
105
|
|
|
37
106
|
**v0.3.0 is a breaking release.**
|
|
@@ -146,6 +215,190 @@ Or use the registered `<qapture-widget>` custom element — accepts a `config` a
|
|
|
146
215
|
|
|
147
216
|
---
|
|
148
217
|
|
|
218
|
+
## Steps to reproduce, recorded for you
|
|
219
|
+
|
|
220
|
+
The hardest part of a bug report is the part testers skip: *how do I get to
|
|
221
|
+
this?* They skip it because they were busy testing, and by the time anyone
|
|
222
|
+
asks, the sequence is gone.
|
|
223
|
+
|
|
224
|
+
So every note now carries the run-up automatically:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
**Steps before this** (recorded automatically, oldest first)
|
|
228
|
+
|
|
229
|
+
1. [-18.2s] clicked “Sign in”
|
|
230
|
+
2. [-14.9s] typed in “Email”
|
|
231
|
+
3. [-13.1s] typed in “password field”
|
|
232
|
+
4. [-11.4s] clicked “Continue”
|
|
233
|
+
5. [-9.8s] went to /checkout
|
|
234
|
+
6. [-2.1s] clicked “Place order”
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
It appears in the note, in `notes.md`, in the folder report, and in "Copy as
|
|
238
|
+
agent prompt" — right under the tester's own words, above the runtime console
|
|
239
|
+
and network context, because it is what a human reads first.
|
|
240
|
+
|
|
241
|
+
### What it will not record
|
|
242
|
+
|
|
243
|
+
This is the most sensitive thing Qapture touches, because interactions happen
|
|
244
|
+
directly on the data. The rules are deliberately strict:
|
|
245
|
+
|
|
246
|
+
- **What was typed is never recorded.** An edit records only *that* a field
|
|
247
|
+
was edited, named by its visible label. The value is never read. A password
|
|
248
|
+
field records as `password field`.
|
|
249
|
+
- **A dropdown's chosen option is not recorded** — only that it changed. An
|
|
250
|
+
option's text is routinely a customer name or an address.
|
|
251
|
+
- **Character keys are ignored entirely**, so no keystroke trail can be
|
|
252
|
+
reassembled into typed text. Only Enter, Escape, Tab, Backspace, Delete and
|
|
253
|
+
the arrows are noted.
|
|
254
|
+
- Checkboxes and radios record `on`/`off` — interface state, not content.
|
|
255
|
+
- Navigation is path-only; query strings are redacted to `?…` like every other
|
|
256
|
+
URL.
|
|
257
|
+
- Qapture's own UI is excluded, so your steps are yours, not clicks on the
|
|
258
|
+
widget.
|
|
259
|
+
- 25 steps are kept, 12 travel with a note, labels cap at 60 characters, and
|
|
260
|
+
repeats collapse (typing twenty characters is one step, not twenty).
|
|
261
|
+
|
|
262
|
+
Set `captureContext: false` to switch this off along with all other runtime
|
|
263
|
+
capture — no listener is installed at all. The complete guarantees are in
|
|
264
|
+
[SECURITY.md](SECURITY.md#interaction-steps-steps-before-this).
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Screenshots: two engines
|
|
269
|
+
|
|
270
|
+
Qapture can produce a screenshot two different ways. Both crop the exact
|
|
271
|
+
viewport rectangle you selected; they differ in where the pixels come from.
|
|
272
|
+
|
|
273
|
+
### `dom` — the default, works everywhere
|
|
274
|
+
|
|
275
|
+
html2canvas **re-renders a clone** of your DOM into an offscreen frame and
|
|
276
|
+
rasterises it. No permission prompt, works in every browser, and it is the
|
|
277
|
+
only option on Firefox, Safari and mobile.
|
|
278
|
+
|
|
279
|
+
Because it is a reconstruction rather than a photograph, it has limits worth
|
|
280
|
+
knowing:
|
|
281
|
+
|
|
282
|
+
- `<canvas>` / WebGL, `<video>` and cross-origin `<iframe>` content cannot be
|
|
283
|
+
read and render blank or approximated;
|
|
284
|
+
- CSS the cloner doesn't implement (some `backdrop-filter`, `mask`, exotic
|
|
285
|
+
gradients) renders differently;
|
|
286
|
+
- anything the clone lays out differently is a shot that doesn't match.
|
|
287
|
+
|
|
288
|
+
That last category is what v0.4 fixed. The culprit was Qapture's own scroll
|
|
289
|
+
lock: freezing the page with `overflow: hidden` on `<html>` takes away the
|
|
290
|
+
scrollport that `position: sticky` elements stick to, so every stuck header
|
|
291
|
+
and toolbar jumped back to its natural document position in the instant
|
|
292
|
+
between you choosing a rectangle and the screenshot being rendered. The lock
|
|
293
|
+
now swallows scroll events instead of touching CSS, and stuck elements are
|
|
294
|
+
additionally pinned in html2canvas's clone (it doesn't implement sticky
|
|
295
|
+
either).
|
|
296
|
+
|
|
297
|
+
You can measure this yourself — `npm run capture-accuracy-test` captures a
|
|
298
|
+
rectangle straddling a colour boundary and reports the error in pixels. It
|
|
299
|
+
reads 0.0px on 0.4.0 and 20px (of a 40px capture) on 0.3.1.
|
|
300
|
+
|
|
301
|
+
### `exact` — opt-in, pixel-for-pixel
|
|
302
|
+
|
|
303
|
+
Uses the Screen Capture API to photograph **this tab's real composited
|
|
304
|
+
pixels**, then crops your rectangle out arithmetically. Nothing is
|
|
305
|
+
re-rendered, so it cannot mis-frame, and everything above renders correctly
|
|
306
|
+
because it was never re-drawn in the first place.
|
|
307
|
+
|
|
308
|
+
- **Turn it on** from the capture hint bar ("Pixel-exact shots") or Settings.
|
|
309
|
+
- The browser asks once per session to share this tab. Nothing leaves the
|
|
310
|
+
device — the frames are cropped locally and never uploaded.
|
|
311
|
+
- The QA overlay is hidden for the captured frame, so the scrim, the selection
|
|
312
|
+
outline and the annotation card never appear in the image.
|
|
313
|
+
- **Chromium desktop only** (Chrome, Edge, Brave, Opera), because it depends
|
|
314
|
+
on `preferCurrentTab`. Elsewhere the picker would let a tester share a
|
|
315
|
+
screen or another window, whose pixels have nothing to do with our
|
|
316
|
+
coordinate space — so the option isn't offered, and if a shared surface
|
|
317
|
+
somehow isn't this tab (wrong `displaySurface`, or a frame whose aspect
|
|
318
|
+
ratio doesn't match the viewport), Qapture falls back to `dom` rather than
|
|
319
|
+
returning a confidently wrong image.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Saving to a folder
|
|
324
|
+
|
|
325
|
+
Export-at-the-end only works if nothing goes wrong before the end. Folder
|
|
326
|
+
sync writes each note to disk **the moment it is saved**.
|
|
327
|
+
|
|
328
|
+
Open **Settings → Save to a folder**, pick a folder once, then name the
|
|
329
|
+
project and campaign. From then on:
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
<chosen folder>/
|
|
333
|
+
Project X/
|
|
334
|
+
2026-08-14 smoke test/
|
|
335
|
+
REPORT.md # the whole campaign, agent-ready, rewritten live
|
|
336
|
+
campaign.json # metadata + the note→file index
|
|
337
|
+
notes/
|
|
338
|
+
0001-checkout-button-stays-enabled.md
|
|
339
|
+
0002-arabic-labels-clipped.md
|
|
340
|
+
screenshots/
|
|
341
|
+
0001-checkout-button-stays-enabled.webp
|
|
342
|
+
0002-arabic-labels-clipped.webp
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Ten projects become ten folders, each holding its named campaigns. Nothing
|
|
346
|
+
needs a browser to read.
|
|
347
|
+
|
|
348
|
+
Behaviour worth knowing:
|
|
349
|
+
|
|
350
|
+
- **Existing notes are mirrored** when you open a campaign, so the folder is
|
|
351
|
+
complete rather than "everything from now on".
|
|
352
|
+
- **Editing a note renames its file** and removes the old one — no orphans.
|
|
353
|
+
- **Deleting a note** removes its files after the 5-second undo window, not
|
|
354
|
+
before.
|
|
355
|
+
- **Reloading resumes the same campaign** and continues the numbering, because
|
|
356
|
+
the note index lives in `campaign.json`.
|
|
357
|
+
- **The folder is remembered across sessions.** Browsers intentionally drop
|
|
358
|
+
write permission between visits, so you get a one-click *Reconnect* rather
|
|
359
|
+
than having to find the folder again.
|
|
360
|
+
- Export is unchanged and still works; this is a second, always-on copy.
|
|
361
|
+
|
|
362
|
+
**Chromium desktop only.** The File System Access API has no equivalent in
|
|
363
|
+
Firefox, Safari or any mobile browser — there, Settings says so and points at
|
|
364
|
+
Export.
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Where notes live, and what "storage full" means
|
|
369
|
+
|
|
370
|
+
Notes and screenshots are stored **in the tester's own browser**
|
|
371
|
+
(IndexedDB) — never on the server your app is deployed from. That is what
|
|
372
|
+
makes Qapture keyless and offline, and it is also why a tester on a shared
|
|
373
|
+
beta link can see:
|
|
374
|
+
|
|
375
|
+
> Storage full — this note may not survive a reload
|
|
376
|
+
|
|
377
|
+
Every browser caps how much a single origin may store: usually a share of
|
|
378
|
+
free disk, but as little as a few hundred MB on a busy phone. Safari
|
|
379
|
+
additionally **evicts** data from sites not visited for a week. When the cap
|
|
380
|
+
is hit, the write is refused and the note exists only in the open tab.
|
|
381
|
+
|
|
382
|
+
v0.4 addresses this from four directions:
|
|
383
|
+
|
|
384
|
+
1. **Screenshots are ~10× smaller** — WebP at quality 0.92, capped at 1800px
|
|
385
|
+
on the long edge (PNG fallback where WebP is unsupported). Screenshots are
|
|
386
|
+
essentially all of the footprint, so this alone moves the ceiling a long way.
|
|
387
|
+
2. **You get warned at 70% of quota**, not at the moment a write fails, with a
|
|
388
|
+
usage meter in Settings showing the origin total and Qapture's own share.
|
|
389
|
+
(They differ: `navigator.storage.estimate()` reports the whole origin, so on
|
|
390
|
+
a real app most of it is the host's caches and service worker.)
|
|
391
|
+
3. **"Ask browser to keep my notes"** calls `navigator.storage.persist()`,
|
|
392
|
+
which stops eviction where the browser supports it.
|
|
393
|
+
4. **Folder sync** is the real answer for "I cannot lose this" — a file on
|
|
394
|
+
disk is subject to no browser quota at all.
|
|
395
|
+
|
|
396
|
+
If a tester is stuck mid-session, **Settings → "Free space: drop screenshots,
|
|
397
|
+
keep notes"** removes every stored image while keeping all findings — and if
|
|
398
|
+
folder sync is on, those images are already safe on disk.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
149
402
|
## Config Reference
|
|
150
403
|
|
|
151
404
|
All fields are optional. Passing an empty object (or no config at all) produces a valid, usable widget with sensible defaults.
|
|
@@ -164,7 +417,8 @@ All fields are optional. Passing an empty object (or no config at all) produces
|
|
|
164
417
|
| `rtl` | `boolean` | `false` | When `true`, the UI initialises in Arabic / RTL mode. |
|
|
165
418
|
| `visible` | `boolean \| undefined` | `undefined` | `true` = always show; `false` = always hide; `undefined` = dev-only (hidden in production). |
|
|
166
419
|
| `alwaysVisible` | `boolean` | `false` | When `true`, overrides `visible` and shows the panel even in production. |
|
|
167
|
-
| `hotkey` | `string` | `'shift+alt+q'` |
|
|
420
|
+
| `hotkey` | `string` | `'shift+alt+q'` |
|
|
421
|
+
| `captureHotkey` | `string` | `'shift+alt+c'` — jumps straight into capture mode | Keyboard shortcut that toggles the panel open/closed. |
|
|
168
422
|
| `captureContext` | `boolean` | `true` | Whether to record ambient runtime context (recent console errors/warnings, uncaught errors, failed network calls, and an environment snapshot) into each note as it's captured. Set to `false` to disable entirely. See [Runtime Context Capture](#runtime-context-capture). |
|
|
169
423
|
|
|
170
424
|
### `QaTheme` (deprecated)
|
|
@@ -309,11 +563,15 @@ Outside test-along, a captured note is also auto-linked to a journey step whenev
|
|
|
309
563
|
qa-notes-<timestamp>.zip
|
|
310
564
|
├── notes.md
|
|
311
565
|
└── screenshots/
|
|
312
|
-
├── point-1.
|
|
313
|
-
├── point-2.
|
|
566
|
+
├── point-1.webp
|
|
567
|
+
├── point-2.webp
|
|
314
568
|
└── ...
|
|
315
569
|
```
|
|
316
570
|
|
|
571
|
+
Since v0.4 screenshots are WebP where the browser supports it (PNG
|
|
572
|
+
otherwise). The extension in `screenshots/` and the one referenced from
|
|
573
|
+
`notes.md` come from the same helper, so they always agree.
|
|
574
|
+
|
|
317
575
|
### `notes.md` structure
|
|
318
576
|
|
|
319
577
|
```
|
|
@@ -458,6 +716,10 @@ By default the widget is **dev-only** — hidden when `NODE_ENV === 'production'
|
|
|
458
716
|
|
|
459
717
|
The **hotkey** (default: `Shift+Alt+Q`) toggles the panel open/closed regardless of `visible`. Change it via `hotkey: 'ctrl+shift+q'` or any `modifier+key` combination recognised by the browser `keydown` event.
|
|
460
718
|
|
|
719
|
+
The **capture hotkey** (default: `Shift+Alt+C`, i.e. `Option+Shift+C` on macOS) jumps straight into capture mode from anywhere on the page, and pressing it again backs out. Change it via `captureHotkey`.
|
|
720
|
+
|
|
721
|
+
> Why Alt/Option rather than Cmd/Ctrl: the obvious chords belong to things a web page cannot and must not override — Cmd/Ctrl+C is copy, and on macOS Cmd+Q quits the browser at the OS level, before the page ever sees the key. Alt/Option combinations are the only family a page can claim safely, and the same physical keys behave identically on macOS and Windows.
|
|
722
|
+
|
|
461
723
|
---
|
|
462
724
|
|
|
463
725
|
## Browser and SSR Support
|
|
@@ -468,6 +730,21 @@ The **hotkey** (default: `Shift+Alt+Q`) toggles the panel open/closed regardless
|
|
|
468
730
|
- **Node >= 18** required for the CLI.
|
|
469
731
|
- Heavy dependencies (`jszip`, `html2canvas`) are loaded as **lazy code-split chunks** — they do not affect initial page load and are only fetched when the user triggers a capture or export action.
|
|
470
732
|
|
|
733
|
+
### Feature availability by browser (v0.4)
|
|
734
|
+
|
|
735
|
+
| Feature | Chromium desktop | Firefox / Safari desktop | Mobile |
|
|
736
|
+
|---|---|---|---|
|
|
737
|
+
| Capture, notes, export | ✅ | ✅ | ✅ |
|
|
738
|
+
| `dom` screenshots (default) | ✅ | ✅ | ✅ |
|
|
739
|
+
| Pixel-exact screenshots | ✅ opt-in | — | — |
|
|
740
|
+
| Save to a folder | ✅ opt-in | — | — |
|
|
741
|
+
| Storage meter | ✅ | ✅ (Safari reports coarse numbers) | ✅ |
|
|
742
|
+
| Persistent storage request | ✅ | Firefox prompts; Safari ignores | varies |
|
|
743
|
+
|
|
744
|
+
Nothing here is required. Where a feature is unavailable the UI says so and
|
|
745
|
+
points at the path that always works (Export), and no capability is assumed
|
|
746
|
+
without a runtime check.
|
|
747
|
+
|
|
471
748
|
---
|
|
472
749
|
|
|
473
750
|
## Isolation and Known Limitations
|
package/dist/bin/init.cjs
CHANGED
|
@@ -29,10 +29,10 @@ var fs6 = __toESM(require("fs"), 1);
|
|
|
29
29
|
var process2 = __toESM(require("process"), 1);
|
|
30
30
|
|
|
31
31
|
// src/artifacts/SKILL.md
|
|
32
|
-
var SKILL_default = "---\nname: qapture\ndescription: >\n Activated when the user provides a `qa-notes-*.zip` file exported from\n Qapture. Reads the preamble block in `notes.md` (project context, stack, run\n commands, dev/test login credentials, red-zone coverage report, and\n invariants), flags any uncovered RED risk zones before acting, then\n triages every `## Point N` as a batch \u2014 clustering points that share a\n root cause via their runtime-context evidence \u2014 before orchestrating\n Sonnet subagents (one per point/cluster, parallelized across disjoint\n files) to reproduce each issue live, fix it, and self-verify. Finally\n grades coverage against the red zones and reports, including any adjacent\n improvements noticed along the way. Also activates on a single point\n pasted directly via Qapture's \"Copy as agent prompt\" (no ZIP, no preamble\n \u2014 just one point).\n\n **No AI is bundled in Qapture \u2014 YOU are the AI reading these artifacts.**\n Qapture is a 100% client-side, keyless, network-free capture widget.\ntriggers:\n - qa-notes-*.zip\n---\n\n# Qapture \u2014 Agent Skill\n\n> **Core principle:** Qapture ships zero AI. No model, no API keys, no network\n> calls. The CLI is a plain deterministic scaffolder. **You** \u2014 the coding agent\n> reading this skill \u2014 are the AI. The developer used Qapture to capture\n> annotated screenshots + notes from their live app; your job is to act on them.\n\n---\n\n## What Is Qapture?\n\nQapture is a drop-in in-browser widget (Shadow DOM, keyless, no telemetry).\nTesters annotate the live app: click an element or draw a region, add a note,\nand the widget captures a screenshot automatically. When done, they export a\n`qa-notes-*.zip`. That ZIP is the hand-off to you.\n\n---\n\n## Working Model \u2014 You're the Brain, Subagents Are the Muscle\n\nFor anything past a single trivial point, don't work through the ZIP\npoint-by-point yourself. Orchestrate:\n\n- **You cluster and plan; subagents reproduce, fix, and self-verify.** You\n read every point first (Step 3), decide what's really one bug wearing N\n reports, and spawn one subagent per point or cluster to do the actual work.\n You do the fixing yourself only for a single, obviously trivial point where\n spinning up a subagent is pure overhead.\n- **Every subagent is Sonnet, pinned explicitly on every single call.** Never\n let a spawned agent inherit whatever model you happen to be running as\n orchestrator \u2014 an inherited model silently drifts to whatever you're on,\n and that's the kind of thing nobody notices until the cost or the quality\n looks wrong in hindsight. Pin it every time, no exceptions.\n- **Effort is your judgment call per task, not a formula.** A one-line CSS\n fix gets low effort. A bug whose runtime-context evidence (below) doesn't\n cleanly explain the symptom gets high or max \u2014 you decide based on how\n ambiguous the root cause actually looks, case by case.\n- **Parallelize by file, not by point.** Points/clusters that land in\n disjoint files can run as concurrent subagents safely. Anything that lands\n in the *same* file goes to one agent, or runs serially \u2014 never two agents\n editing the same file at once. This is the actual failure mode to guard\n against, not an abstract \"be careful.\"\n- **Supervise by reality-checking, not re-reading.** Don't reread every\n subagent's full diff. Do: read exactly what each one's own report claims\n changed, at the file/location it names; always personally open and read\n the diff for anything touching a RED zone, no exceptions, regardless of\n what the subagent reports; and treat the project's own test/verify command\n \u2014 run by you, independently, after every subagent lands \u2014 as the actual\n gate. A subagent saying \"done\" is a claim, not a fact.\n\n**Creative suggestions are always welcome; creative *changes* are gated like\neverything else, by risk colour (see Risk Zone Reference below).** Noticing a\npattern, an adjacent bug, or a missing feature costs nothing to write down \u2014\nput it in a `### Suggestions` section in your final report (Step 5) and never\nsuppress it for being out of scope. Whether you're allowed to *implement* it\nwithout being asked depends on where it lands:\n\n| Zone | An idea beyond the literal reported point |\n| --- | --- |\n| **green** | Implement inline, no permission needed \u2014 \"fixed the label, also fixed 3 nearby with the same casing bug\" is fine. |\n| **amber** | Implement it, but call it out explicitly in the report \u2014 the developer should see at a glance what went beyond what was asked. |\n| **red** | Propose only. Write it down, never touch the code. Same rule as everything else in a red zone: no silent business-logic decisions. |\n\nThat keeps the upside of a genuinely observant agent \u2014 catching the adjacent\nbug, proposing the missing feature \u2014 without that same latitude becoming the\nmechanism for quietly rewriting a payment flow nobody asked you to touch.\n\n---\n\n## ZIP Layout\n\n```\nqa-notes-<timestamp>.zip\n\u251C\u2500\u2500 notes.md \u2190 ALWAYS read this first (see Step 1)\n\u2514\u2500\u2500 screenshots/\n \u251C\u2500\u2500 point-1.png\n \u251C\u2500\u2500 point-2.png\n \u2514\u2500\u2500 ...\n```\n\n### `notes.md` structure\n\n```\n[PREAMBLE BLOCK]\n Project name, one-liner, stack, run commands,\n Login Context (dev/test credentials \u2014 see security note below),\n Coverage Report (red/amber/green zone checklist),\n Invariants, Additional Context.\n\n---NOTES---\n\n## Point 1\nPage: /some/path\nSeverity: bug (bug | question | polish \u2014 tester's own triage)\nStatus: open (open | verified)\nJourney step: <lane> \u2192 <path> (present when linked to a journey step)\nSelector: #some-element (or [data-testid=\"foo\"] etc.)\nNote: the tester's free-text description of the issue / request\n\n<details>Runtime context at capture \u2014 recent console/network events + env snapshot</details>\n\n## Point 2\n...\n```\n\nNote: a tester may also hand you a **single point directly**, pasted via\nQapture's \"Copy as agent prompt\" button, with no ZIP and no preamble at all.\nTreat it exactly like one `## Point N` section below \u2014 skip Steps 1 and 2\n(there is no preamble or coverage report to read), and go straight to Step 3.\n\n---\n\n## Step 1 \u2014 Read the Preamble First\n\nBefore touching any code, open `notes.md` and parse everything **above** the\n`---NOTES---` separator. Extract and internalize:\n\n| Section | What to do |\n| ------------------ | --------------------------------------------------------------------- |\n| **Project / Stack** | Understand the framework, router, ORM, and any unusual constraints. |\n| **Run Commands** | Know how to start the dev server and seed the database. |\n| **Login Context** | DEV/TEST/SEED credentials only. Use these to log in during verification. **Never log, forward, or commit these values.** |\n| **Coverage Report**| List of RED / AMBER / GREEN zones and whether they are covered. |\n| **Invariants** | Absolute rules you must never violate (e.g. \"prices \u2265 0\", \"checkout requires auth\"). |\n| **Conventions** | Codebase naming, file organisation, import rules, validation approach. |\n\n---\n\n## Step 2 \u2014 Flag Uncovered RED Zones Before Acting\n\nAfter reading the preamble, check the Coverage Report for any RED zones that\nare **not yet covered** by an annotation in this ZIP.\n\nIf uncovered RED zones exist, **report them to the developer first**:\n\n```\n\u26A0\uFE0F Uncovered RED zones detected:\n \u2022 /checkout/payment \u2014 no annotation in this export\n \u2022 /seller/payouts \u2014 no annotation in this export\n\nThese are money/auth/irreversible flows. Do you want me to proceed with the\ncovered points only, or will you add annotations for the red zones first?\n```\n\nWait for developer confirmation before proceeding if any RED zone is uncovered.\n\n---\n\n## Step 3 \u2014 Triage, Then Act\n\n### 3a. Triage & cluster before touching anything\n\nRead **every** `## Point N` in the ZIP before acting on any of them. Points\nthat look unrelated on the surface (different pages, different testers, even\ndifferent sessions) can share one root cause \u2014 check each point's runtime\ncontext (3c below) for a repeated signature: the same failing network URL,\nthe same status code, the same console error message. Group matches into one\ncluster. A cluster gets one fix and N verifications (one per point in it),\nnot N separate patches that might silently disagree with each other.\n\nWrite the plan down as an actual artifact before editing anything \u2014 a short\nmarkdown list is enough: each point/cluster, your root-cause hypothesis, the\nproposed fix, and its risk zone. This is the thing you hand to subagents in\nStep 3b, and the thing a developer can skim to sanity-check your read of the\nbatch before code starts moving.\n\n### 3b. Decide who does the work\n\nSingle trivial point, obviously green-zone, no ambiguity \u2192 you can just fix\nit. Anything else \u2192 spawn a subagent per point or cluster, per the Working\nModel above (Sonnet, pinned; effort by your judgment; parallel only across\ndisjoint files). Hand each subagent its point(s), the relevant preamble\ncontext (stack, conventions, invariants, login), and its risk zone.\n\n### 3c. Read the annotation\n\n- **Page** \u2014 the route/URL where the issue was captured.\n- **Severity** \u2014 `bug` (default), `question`, or `polish`. A `question` may\n not need a code change at all \u2014 read the note text before assuming one.\n- **Status** \u2014 `open` (default) or `verified`. A `verified` point was already\n re-checked by the tester after a previous fix; treat it as lower priority\n unless the note says otherwise.\n- **Journey step** \u2014 present when the point was captured during the guided\n walkthrough, or auto-linked by route match. Cross-reference it against the\n Coverage Report: a covered RED step usually has one of these attached.\n- **Selector** \u2014 the CSS selector or aria identifier for the element.\n- **Runtime context** (collapsed `<details>` block, when present) \u2014 recent\n `console.error`/`console.warn` output, uncaught errors, and failed/slow\n network calls captured in the moments before the tester clicked capture,\n plus an environment snapshot (viewport, language, timezone, page-load time).\n **Read this before assuming a UI-only cause.** \"The button does nothing\" is\n very often actually a console `TypeError` or a `500` that already happened\n \u2014 the evidence for it is right there, not something you have to reproduce\n blind. Query strings in any URL shown here have already been redacted by\n Qapture before export (see `SECURITY.md`); do not assume you're seeing a\n full URL, and never assume request bodies/headers were captured \u2014 they\n weren't, by design.\n- **Note** \u2014 the tester's description of the problem or change request.\n- **Forensics** (when present, inside the runtime-context `<details>` block)\n \u2014 computed facts about the exact captured element: `contrastFlag`\n (`low`/`ok`), `hasAccessibleName`, `tabReachable`, plus its computed\n styles. This turns \"looks fixed\" into something checkable: if\n `contrastFlag: low`, the fix isn't done until you can show the new colour\n pair actually clears a 4.5:1 ratio; if `tabReachable: false` on something\n that visually reads as interactive, that's an objective bug independent of\n whatever the tester's note text says. Treat these as acceptance criteria,\n not supplementary trivia.\n\n### 3d. Open the screenshot\n\nLoad `screenshots/point-N.png` to visually confirm what the tester saw.\nThe screenshot is truth \u2014 if the selector doesn't resolve, the screenshot tells\nyou what element they meant.\n\n### 3e. Locate the code\n\nUse the selector priority chain below to find the relevant source:\n\n| Priority | Selector type | Action |\n| -------- | -------------------------------------------------- | --------------------------------------------------- |\n| 1 | `#some-id` | `grep -r 'some-id'` in `src/` |\n| 2 | `[data-testid=\"foo\"]` / `[data-test]` / `[data-cy]` | grep for the attribute value |\n| 3 | `aria-label` on interactive elements | grep for the label string |\n| 4 | `name` attribute on form fields | grep for `name=\"...\"` in the relevant form file |\n| 5 | Structural (e.g. `.card:nth-of-type(2) > button`) | narrow by page route \u2192 component file \u2192 visual match with screenshot |\n| Fallback | Selector didn't resolve | Use the screenshot: identify the element visually, search by text content or component name |\n\nNarrow your search by the **Page** field to avoid editing the wrong route's code.\n\n### 3f. Reproduce it live, before writing a fix\n\nDon't go straight from \"read the note\" to \"guess the fix.\" Run the app, log\nin as the relevant role using **Login Context**, navigate to **Page**, and \u2014\nif the point has a **Journey step** with an `expect` field \u2014 try to actually\ntrigger the failure the way the journey step describes. This catches two\nthings a static screenshot can't: a report that's already stale (fixed\nelsewhere, doesn't reproduce), and a bug whose real trigger is an\ninteraction, not the state the screenshot happened to capture. Only once\nyou've confirmed the failure and understand *why* it happens do you move to\n3g \u2014 writing a fix against a guess is how you end up patching the symptom\nin the screenshot instead of the actual defect.\n\n### 3g. Make the change\n\n- Follow the project's **Conventions** (from the preamble).\n- Respect all **Invariants** \u2014 never violate them even if the annotation implies it.\n- If the change touches a RED zone (money / auth / irreversible state), add an\n explicit comment: `// QA: red-zone change \u2014 reviewed <date>`.\n- Do **not** edit `qa.config.ts`, `qa.preamble.md`, or any qapture plugin files.\n\n---\n\n## Step 4 \u2014 Verify the Fix\n\n1. Run the app using the **Run Commands** from the preamble.\n2. Log in as the relevant role using **Login Context** credentials.\n (These are DEV/TEST/SEED only \u2014 never use production credentials.)\n3. Navigate to the **Page** listed in the annotation.\n4. **Reproduce** the original issue to confirm it existed, then verify it is fixed.\n5. In the browser console, run `document.querySelector('<selector>')` to confirm\n the element resolves as expected.\n6. Check adjacent paths for regressions, especially if the change is in a shared\n component.\n\n---\n\n## Step 5 \u2014 Grade and Report\n\nAfter acting on all points, produce a short report:\n\n```markdown\n## Qapture \u2014 Changes Summary\n\n| Point | Page | Severity | Change made | Verified | Risk |\n| ----- | --------------- | -------- | ----------------------------- | -------- | ----- |\n| 1 | /products | bug | Fixed button label | \u2713 | green |\n| 2 | /checkout | bug | Corrected total calculation | \u2713 | red |\n\n### Coverage vs Red Zones\n- [x] /checkout/payment \u2014 covered by Point 2\n- [ ] /seller/payouts \u2014 NOT covered (flagged in Step 2)\n\n### Uncovered items\nNone (all annotated points addressed).\n\n### Suggestions (proposed, not implemented)\n- [amber] /cart \u2014 quantity stepper has no debounce; noticed while fixing\n Point 1, not part of the report, flagging rather than touching it.\n```\n\nAn **amber** suggestion you *did* implement inline still gets called out\nhere, same as above but phrased as done, not proposed. A **green** one\ndoesn't need a separate line at all \u2014 just mention it in the affected\npoint's \"Change made\" cell. **Red** ideas are always proposal-only, never a\nline item that reads as if it happened.\n\n---\n\n## Risk Zone Reference\n\n| Risk | Examples | Rule |\n| ------- | ----------------------------------------------------------------- | ------------------------------------------------ |\n| **red** | Payment, checkout, auth, order state, refunds, payouts, user data | Never change without developer review + comment |\n| **amber** | Cart, product listings, search, seller dashboard, inventory | Change carefully; verify end-to-end |\n| **green** | Static content, labels, colours, copy, tooltips, layout | Change freely; quick smoke-test |\n\n---\n\n## Security Note\n\n- **Dev/test/seed credentials only.** The Login Context in `notes.md` contains\n credentials from `.env.example` or seeder files \u2014 never from production.\n- **Never log, forward, store, or commit** Login Context values outside the\n development environment.\n- **Never read** `.env`, `.env.local`, `.env.production`, or any `secrets/`\n path. Qapture's CLI enforces this; you must too.\n- Qapture is **100% client-side** \u2014 it makes no network calls, holds no API\n keys, and sends no data anywhere.\n- **Runtime context evidence is already redacted for you.** Any URL shown in\n a point's runtime-context block has had its query string stripped by\n Qapture before export, and request/response bodies, headers, cookies, and\n storage values were never captured in the first place \u2014 treat this section\n as safe local debugging evidence, not as something you need to further\n sanitize.\n- **Never push, publish, or deploy** changes without explicit human approval,\n regardless of risk level.\n\n---\n\n## Common Pitfalls\n\n- **Don't assume selectors always resolve.** Selector strings may be stale if\n the DOM changed after annotation. When in doubt, use the screenshot.\n- **Don't skip the preamble.** Acting without reading the invariants or run\n commands is the most common source of broken fixes.\n- **Don't edit qapture config or plugin files** (`qa.config.ts`,\n `qa.preamble.md`, `.claude/skills/qapture/`, `src/components/qa-overlay/`).\n- **Don't use production credentials** \u2014 ever.\n- **Don't push/publish without human approval** \u2014 always present the changes\n for review first.\n- **Don't violate invariants** even if the annotation seems to imply it.\n Surface the conflict to the developer instead.\n- **Don't ignore the runtime context block.** A point's collapsed \"Runtime\n context at capture\" section is often the actual root cause, not\n supplementary detail \u2014 check it before guessing at one from the note text\n and screenshot alone.\n- **Don't treat a `question`-severity or `verified`-status point like a\n routine bug fix.** A `question` may just need an answer, not code; a\n `verified` point was already re-confirmed once and should be double-checked\n before you assume it's still broken.\n- **Don't work every point serially when they could parallelize.** If you\n catch yourself fixing point after point one at a time on a batch of five\n independent-file points, stop and re-read the Working Model section above.\n- **Don't let two subagents touch the same file at once.** File overlap, not\n point count, is what decides parallel vs serial \u2014 check this before you\n spawn anything.\n- **Don't treat a subagent's \"done\" as the verification gate.** Run the\n project's own test/verify command yourself, independently, after every\n subagent lands its change.\n- **Don't silently implement a creative idea beyond a green zone.** Amber\n gets implemented-and-disclosed; red gets proposed-and-left-alone. Never\n implemented-and-undisclosed.\n\n---\n\n_Qapture \u2014 https://github.com/mohammed-farhood/qapture_\n";
|
|
32
|
+
var SKILL_default = "---\nname: qapture\ndescription: >\n Activated when the user provides a `qa-notes-*.zip` file exported from\n Qapture. Reads the preamble block in `notes.md` (project context, stack, run\n commands, dev/test login credentials, red-zone coverage report, and\n invariants), flags any uncovered RED risk zones before acting, then\n triages every `## Point N` as a batch \u2014 clustering points that share a\n root cause via their runtime-context evidence \u2014 before orchestrating\n Sonnet subagents (one per point/cluster, parallelized across disjoint\n files) to reproduce each issue live, fix it, and self-verify. Finally\n grades coverage against the red zones and reports, including any adjacent\n improvements noticed along the way. Also activates on a single point\n pasted directly via Qapture's \"Copy as agent prompt\" (no ZIP, no preamble\n \u2014 just one point).\n\n **No AI is bundled in Qapture \u2014 YOU are the AI reading these artifacts.**\n Qapture is a 100% client-side, keyless, network-free capture widget.\ntriggers:\n - qa-notes-*.zip\n---\n\n# Qapture \u2014 Agent Skill\n\n> **Core principle:** Qapture ships zero AI. No model, no API keys, no network\n> calls. The CLI is a plain deterministic scaffolder. **You** \u2014 the coding agent\n> reading this skill \u2014 are the AI. The developer used Qapture to capture\n> annotated screenshots + notes from their live app; your job is to act on them.\n\n---\n\n## What Is Qapture?\n\nQapture is a drop-in in-browser widget (Shadow DOM, keyless, no telemetry).\nTesters annotate the live app: click an element or draw a region, add a note,\nand the widget captures a screenshot automatically. When done, they export a\n`qa-notes-*.zip`. That ZIP is the hand-off to you.\n\n---\n\n## Working Model \u2014 You're the Brain, Subagents Are the Muscle\n\nFor anything past a single trivial point, don't work through the ZIP\npoint-by-point yourself. Orchestrate:\n\n- **You cluster and plan; subagents reproduce, fix, and self-verify.** You\n read every point first (Step 3), decide what's really one bug wearing N\n reports, and spawn one subagent per point or cluster to do the actual work.\n You do the fixing yourself only for a single, obviously trivial point where\n spinning up a subagent is pure overhead.\n- **Every subagent is Sonnet, pinned explicitly on every single call.** Never\n let a spawned agent inherit whatever model you happen to be running as\n orchestrator \u2014 an inherited model silently drifts to whatever you're on,\n and that's the kind of thing nobody notices until the cost or the quality\n looks wrong in hindsight. Pin it every time, no exceptions.\n- **Effort is your judgment call per task, not a formula.** A one-line CSS\n fix gets low effort. A bug whose runtime-context evidence (below) doesn't\n cleanly explain the symptom gets high or max \u2014 you decide based on how\n ambiguous the root cause actually looks, case by case.\n- **Parallelize by file, not by point.** Points/clusters that land in\n disjoint files can run as concurrent subagents safely. Anything that lands\n in the *same* file goes to one agent, or runs serially \u2014 never two agents\n editing the same file at once. This is the actual failure mode to guard\n against, not an abstract \"be careful.\"\n- **Supervise by reality-checking, not re-reading.** Don't reread every\n subagent's full diff. Do: read exactly what each one's own report claims\n changed, at the file/location it names; always personally open and read\n the diff for anything touching a RED zone, no exceptions, regardless of\n what the subagent reports; and treat the project's own test/verify command\n \u2014 run by you, independently, after every subagent lands \u2014 as the actual\n gate. A subagent saying \"done\" is a claim, not a fact.\n\n**Creative suggestions are always welcome; creative *changes* are gated like\neverything else, by risk colour (see Risk Zone Reference below).** Noticing a\npattern, an adjacent bug, or a missing feature costs nothing to write down \u2014\nput it in a `### Suggestions` section in your final report (Step 5) and never\nsuppress it for being out of scope. Whether you're allowed to *implement* it\nwithout being asked depends on where it lands:\n\n| Zone | An idea beyond the literal reported point |\n| --- | --- |\n| **green** | Implement inline, no permission needed \u2014 \"fixed the label, also fixed 3 nearby with the same casing bug\" is fine. |\n| **amber** | Implement it, but call it out explicitly in the report \u2014 the developer should see at a glance what went beyond what was asked. |\n| **red** | Propose only. Write it down, never touch the code. Same rule as everything else in a red zone: no silent business-logic decisions. |\n\nThat keeps the upside of a genuinely observant agent \u2014 catching the adjacent\nbug, proposing the missing feature \u2014 without that same latitude becoming the\nmechanism for quietly rewriting a payment flow nobody asked you to touch.\n\n---\n\n## ZIP Layout\n\n```\nqa-notes-<timestamp>.zip\n\u251C\u2500\u2500 notes.md \u2190 ALWAYS read this first (see Step 1)\n\u2514\u2500\u2500 screenshots/\n \u251C\u2500\u2500 point-1.webp\n \u251C\u2500\u2500 point-2.webp\n \u2514\u2500\u2500 ...\n```\n\n### `notes.md` structure\n\n```\n[PREAMBLE BLOCK]\n Project name, one-liner, stack, run commands,\n Login Context (dev/test credentials \u2014 see security note below),\n Coverage Report (red/amber/green zone checklist),\n Invariants, Additional Context.\n\n---NOTES---\n\n## Point 1\nPage: /some/path\nSeverity: bug (bug | question | polish \u2014 tester's own triage)\nStatus: open (open | verified)\nJourney step: <lane> \u2192 <path> (present when linked to a journey step)\nSelector: #some-element (or [data-testid=\"foo\"] etc.)\nNote: the tester's free-text description of the issue / request\n\n<details>Runtime context at capture \u2014 recent console/network events + env snapshot</details>\n\n## Point 2\n...\n```\n\nNote: a tester may also hand you a **single point directly**, pasted via\nQapture's \"Copy as agent prompt\" button, with no ZIP and no preamble at all.\nTreat it exactly like one `## Point N` section below \u2014 skip Steps 1 and 2\n(there is no preamble or coverage report to read), and go straight to Step 3.\n\n---\n\n## Step 1 \u2014 Read the Preamble First\n\nBefore touching any code, open `notes.md` and parse everything **above** the\n`---NOTES---` separator. Extract and internalize:\n\n| Section | What to do |\n| ------------------ | --------------------------------------------------------------------- |\n| **Project / Stack** | Understand the framework, router, ORM, and any unusual constraints. |\n| **Run Commands** | Know how to start the dev server and seed the database. |\n| **Login Context** | DEV/TEST/SEED credentials only. Use these to log in during verification. **Never log, forward, or commit these values.** |\n| **Coverage Report**| List of RED / AMBER / GREEN zones and whether they are covered. |\n| **Invariants** | Absolute rules you must never violate (e.g. \"prices \u2265 0\", \"checkout requires auth\"). |\n| **Conventions** | Codebase naming, file organisation, import rules, validation approach. |\n\n---\n\n## Step 2 \u2014 Flag Uncovered RED Zones Before Acting\n\nAfter reading the preamble, check the Coverage Report for any RED zones that\nare **not yet covered** by an annotation in this ZIP.\n\nIf uncovered RED zones exist, **report them to the developer first**:\n\n```\n\u26A0\uFE0F Uncovered RED zones detected:\n \u2022 /checkout/payment \u2014 no annotation in this export\n \u2022 /seller/payouts \u2014 no annotation in this export\n\nThese are money/auth/irreversible flows. Do you want me to proceed with the\ncovered points only, or will you add annotations for the red zones first?\n```\n\nWait for developer confirmation before proceeding if any RED zone is uncovered.\n\n---\n\n## Step 3 \u2014 Triage, Then Act\n\n### 3a. Triage & cluster before touching anything\n\nRead **every** `## Point N` in the ZIP before acting on any of them. Points\nthat look unrelated on the surface (different pages, different testers, even\ndifferent sessions) can share one root cause \u2014 check each point's runtime\ncontext (3c below) for a repeated signature: the same failing network URL,\nthe same status code, the same console error message. Group matches into one\ncluster. A cluster gets one fix and N verifications (one per point in it),\nnot N separate patches that might silently disagree with each other.\n\nWrite the plan down as an actual artifact before editing anything \u2014 a short\nmarkdown list is enough: each point/cluster, your root-cause hypothesis, the\nproposed fix, and its risk zone. This is the thing you hand to subagents in\nStep 3b, and the thing a developer can skim to sanity-check your read of the\nbatch before code starts moving.\n\n### 3b. Decide who does the work\n\nSingle trivial point, obviously green-zone, no ambiguity \u2192 you can just fix\nit. Anything else \u2192 spawn a subagent per point or cluster, per the Working\nModel above (Sonnet, pinned; effort by your judgment; parallel only across\ndisjoint files). Hand each subagent its point(s), the relevant preamble\ncontext (stack, conventions, invariants, login), and its risk zone.\n\n### 3c. Read the annotation\n\n- **Page** \u2014 the route/URL where the issue was captured.\n- **Severity** \u2014 `bug` (default), `question`, or `polish`. A `question` may\n not need a code change at all \u2014 read the note text before assuming one.\n- **Status** \u2014 `open` (default) or `verified`. A `verified` point was already\n re-checked by the tester after a previous fix; treat it as lower priority\n unless the note says otherwise.\n- **Journey step** \u2014 present when the point was captured during the guided\n walkthrough, or auto-linked by route match. Cross-reference it against the\n Coverage Report: a covered RED step usually has one of these attached.\n- **Selector** \u2014 the CSS selector or aria identifier for the element.\n- **Runtime context** (collapsed `<details>` block, when present) \u2014 recent\n `console.error`/`console.warn` output, uncaught errors, and failed/slow\n network calls captured in the moments before the tester clicked capture,\n plus an environment snapshot (viewport, language, timezone, page-load time).\n **Read this before assuming a UI-only cause.** \"The button does nothing\" is\n very often actually a console `TypeError` or a `500` that already happened\n \u2014 the evidence for it is right there, not something you have to reproduce\n blind. Query strings in any URL shown here have already been redacted by\n Qapture before export (see `SECURITY.md`); do not assume you're seeing a\n full URL, and never assume request bodies/headers were captured \u2014 they\n weren't, by design.\n- **Note** \u2014 the tester's description of the problem or change request.\n- **Forensics** (when present, inside the runtime-context `<details>` block)\n \u2014 computed facts about the exact captured element: `contrastFlag`\n (`low`/`ok`), `hasAccessibleName`, `tabReachable`, plus its computed\n styles. This turns \"looks fixed\" into something checkable: if\n `contrastFlag: low`, the fix isn't done until you can show the new colour\n pair actually clears a 4.5:1 ratio; if `tabReachable: false` on something\n that visually reads as interactive, that's an objective bug independent of\n whatever the tester's note text says. Treat these as acceptance criteria,\n not supplementary trivia.\n\n### 3c-bis. Read \"Steps before this\"\n\nMost points carry a numbered **Steps before this** list \u2014 what the tester\nclicked, typed into, toggled and navigated on the way to the bug, recorded\nautomatically with timings. Treat it as the steps to reproduce: replay it\nbefore you theorise. Note that field CONTENTS are deliberately never\nrecorded, so \"typed in Email\" tells you a field was filled, not with what.\n\n### 3d. Open the screenshot\n\nLoad the screenshot named in that point's **Screenshot** line (\n`screenshots/point-N.webp`, or `.png` on browsers without WebP) to visually\nconfirm what the tester saw.\nThe screenshot is truth \u2014 if the selector doesn't resolve, the screenshot tells\nyou what element they meant.\n\n### 3e. Locate the code\n\nUse the selector priority chain below to find the relevant source:\n\n| Priority | Selector type | Action |\n| -------- | -------------------------------------------------- | --------------------------------------------------- |\n| 1 | `#some-id` | `grep -r 'some-id'` in `src/` |\n| 2 | `[data-testid=\"foo\"]` / `[data-test]` / `[data-cy]` | grep for the attribute value |\n| 3 | `aria-label` on interactive elements | grep for the label string |\n| 4 | `name` attribute on form fields | grep for `name=\"...\"` in the relevant form file |\n| 5 | Structural (e.g. `.card:nth-of-type(2) > button`) | narrow by page route \u2192 component file \u2192 visual match with screenshot |\n| Fallback | Selector didn't resolve | Use the screenshot: identify the element visually, search by text content or component name |\n\nNarrow your search by the **Page** field to avoid editing the wrong route's code.\n\n### 3f. Reproduce it live, before writing a fix\n\nDon't go straight from \"read the note\" to \"guess the fix.\" Run the app, log\nin as the relevant role using **Login Context**, navigate to **Page**, and \u2014\nif the point has a **Journey step** with an `expect` field \u2014 try to actually\ntrigger the failure the way the journey step describes. This catches two\nthings a static screenshot can't: a report that's already stale (fixed\nelsewhere, doesn't reproduce), and a bug whose real trigger is an\ninteraction, not the state the screenshot happened to capture. Only once\nyou've confirmed the failure and understand *why* it happens do you move to\n3g \u2014 writing a fix against a guess is how you end up patching the symptom\nin the screenshot instead of the actual defect.\n\n### 3g. Make the change\n\n- Follow the project's **Conventions** (from the preamble).\n- Respect all **Invariants** \u2014 never violate them even if the annotation implies it.\n- If the change touches a RED zone (money / auth / irreversible state), add an\n explicit comment: `// QA: red-zone change \u2014 reviewed <date>`.\n- Do **not** edit `qa.config.ts`, `qa.preamble.md`, or any qapture plugin files.\n\n---\n\n## Step 4 \u2014 Verify the Fix\n\n1. Run the app using the **Run Commands** from the preamble.\n2. Log in as the relevant role using **Login Context** credentials.\n (These are DEV/TEST/SEED only \u2014 never use production credentials.)\n3. Navigate to the **Page** listed in the annotation.\n4. **Reproduce** the original issue to confirm it existed, then verify it is fixed.\n5. In the browser console, run `document.querySelector('<selector>')` to confirm\n the element resolves as expected.\n6. Check adjacent paths for regressions, especially if the change is in a shared\n component.\n\n---\n\n## Step 5 \u2014 Grade and Report\n\nAfter acting on all points, produce a short report:\n\n```markdown\n## Qapture \u2014 Changes Summary\n\n| Point | Page | Severity | Change made | Verified | Risk |\n| ----- | --------------- | -------- | ----------------------------- | -------- | ----- |\n| 1 | /products | bug | Fixed button label | \u2713 | green |\n| 2 | /checkout | bug | Corrected total calculation | \u2713 | red |\n\n### Coverage vs Red Zones\n- [x] /checkout/payment \u2014 covered by Point 2\n- [ ] /seller/payouts \u2014 NOT covered (flagged in Step 2)\n\n### Uncovered items\nNone (all annotated points addressed).\n\n### Suggestions (proposed, not implemented)\n- [amber] /cart \u2014 quantity stepper has no debounce; noticed while fixing\n Point 1, not part of the report, flagging rather than touching it.\n```\n\nAn **amber** suggestion you *did* implement inline still gets called out\nhere, same as above but phrased as done, not proposed. A **green** one\ndoesn't need a separate line at all \u2014 just mention it in the affected\npoint's \"Change made\" cell. **Red** ideas are always proposal-only, never a\nline item that reads as if it happened.\n\n---\n\n## Risk Zone Reference\n\n| Risk | Examples | Rule |\n| ------- | ----------------------------------------------------------------- | ------------------------------------------------ |\n| **red** | Payment, checkout, auth, order state, refunds, payouts, user data | Never change without developer review + comment |\n| **amber** | Cart, product listings, search, seller dashboard, inventory | Change carefully; verify end-to-end |\n| **green** | Static content, labels, colours, copy, tooltips, layout | Change freely; quick smoke-test |\n\n---\n\n## Security Note\n\n- **Dev/test/seed credentials only.** The Login Context in `notes.md` contains\n credentials from `.env.example` or seeder files \u2014 never from production.\n- **Never log, forward, store, or commit** Login Context values outside the\n development environment.\n- **Never read** `.env`, `.env.local`, `.env.production`, or any `secrets/`\n path. Qapture's CLI enforces this; you must too.\n- Qapture is **100% client-side** \u2014 it makes no network calls, holds no API\n keys, and sends no data anywhere.\n- **Runtime context evidence is already redacted for you.** Any URL shown in\n a point's runtime-context block has had its query string stripped by\n Qapture before export, and request/response bodies, headers, cookies, and\n storage values were never captured in the first place \u2014 treat this section\n as safe local debugging evidence, not as something you need to further\n sanitize.\n- **Never push, publish, or deploy** changes without explicit human approval,\n regardless of risk level.\n\n---\n\n## Common Pitfalls\n\n- **Don't assume selectors always resolve.** Selector strings may be stale if\n the DOM changed after annotation. When in doubt, use the screenshot.\n- **Don't skip the preamble.** Acting without reading the invariants or run\n commands is the most common source of broken fixes.\n- **Don't edit qapture config or plugin files** (`qa.config.ts`,\n `qa.preamble.md`, `.claude/skills/qapture/`, `src/components/qa-overlay/`).\n- **Don't use production credentials** \u2014 ever.\n- **Don't push/publish without human approval** \u2014 always present the changes\n for review first.\n- **Don't violate invariants** even if the annotation seems to imply it.\n Surface the conflict to the developer instead.\n- **Don't ignore the runtime context block.** A point's collapsed \"Runtime\n context at capture\" section is often the actual root cause, not\n supplementary detail \u2014 check it before guessing at one from the note text\n and screenshot alone.\n- **Don't treat a `question`-severity, `fixed`- or `verified`-status point\n like a routine bug fix.** A `question` may just need an answer, not code; a\n `fixed` point is already claimed done and is sitting in the tester's\n re-test queue, so re-fixing it blindly risks undoing someone's work; a\n `verified` point was re-confirmed once and should be double-checked before\n you assume it's still broken.\n- **Don't work every point serially when they could parallelize.** If you\n catch yourself fixing point after point one at a time on a batch of five\n independent-file points, stop and re-read the Working Model section above.\n- **Don't let two subagents touch the same file at once.** File overlap, not\n point count, is what decides parallel vs serial \u2014 check this before you\n spawn anything.\n- **Don't treat a subagent's \"done\" as the verification gate.** Run the\n project's own test/verify command yourself, independently, after every\n subagent lands its change.\n- **Don't silently implement a creative idea beyond a green zone.** Amber\n gets implemented-and-disclosed; red gets proposed-and-left-alone. Never\n implemented-and-undisclosed.\n\n---\n\n_Qapture \u2014 https://github.com/mohammed-farhood/qapture_\n";
|
|
33
33
|
|
|
34
34
|
// src/artifacts/AGENTS_SECTION.md
|
|
35
|
-
var AGENTS_SECTION_default = "<!-- qa-studio-section -->\n\n## Qapture\n\nThis project uses **Qapture** \u2014 an in-browser QA capture widget that ships\n**zero AI** (no model, no API keys, no network calls). **You** are the AI.\n\n### When you receive a `qa-notes-*.zip`\n\n1. **Unzip** the file.\n2. **Read `notes.md` top-to-bottom**, starting with everything above the\n `---NOTES---` separator:\n - **Project context** \u2014 name, stack, run commands, conventions.\n - **Login Context** \u2014 dev/test/seed credentials for the relevant roles.\n _(DEV/TEST/SEED only \u2014 never commit, log, or forward these values.)_\n - **Coverage Report** \u2014 red/amber/green zone checklist.\n - **Invariants** \u2014 rules you must never violate (e.g. \"prices \u2265 0\",\n \"checkout requires auth\").\n3. **Flag uncovered RED zones** before acting. RED = money / auth / irreversible\n state. If any red zone has no annotation in this ZIP, report it and ask the\n developer whether to proceed.\n4. **Triage the whole batch before touching code.** Read every point first \u2014\n points on different pages can share one root cause (check their runtime\n context for a repeated failing URL or error message) and deserve one fix,\n not N. Write the plan down before editing anything.\n5. **Orchestrate, don't grind through it yourself.** For anything past a\n single trivial point: you're the brain, not the muscle. Spawn one Sonnet\n subagent per point/cluster (model pinned explicitly on every call, never\n inherited; effort is your judgment call per task), parallelized across\n points that touch disjoint files \u2014 never two agents on the same file. You\n supervise by checking what each subagent's report actually claims and by\n running the project's own verify/test command yourself afterward, not by\n rereading every diff or trusting a subagent's \"done.\"\n6. **Each point/cluster, before fixing:**\n - **Page** + **Selector** + **Note** \u2192 locate the element in the source\n (priority: `#id` \u2192 `[data-testid]` \u2192 `aria-label` \u2192 `name` \u2192 visual match\n via the `screenshots/point-N.png`).\n - **Severity** (`bug`/`question`/`polish`) and **Status
|
|
35
|
+
var AGENTS_SECTION_default = "<!-- qa-studio-section -->\n\n## Qapture\n\nThis project uses **Qapture** \u2014 an in-browser QA capture widget that ships\n**zero AI** (no model, no API keys, no network calls). **You** are the AI.\n\n### When you receive a `qa-notes-*.zip`\n\n1. **Unzip** the file.\n2. **Read `notes.md` top-to-bottom**, starting with everything above the\n `---NOTES---` separator:\n - **Project context** \u2014 name, stack, run commands, conventions.\n - **Login Context** \u2014 dev/test/seed credentials for the relevant roles.\n _(DEV/TEST/SEED only \u2014 never commit, log, or forward these values.)_\n - **Coverage Report** \u2014 red/amber/green zone checklist.\n - **Invariants** \u2014 rules you must never violate (e.g. \"prices \u2265 0\",\n \"checkout requires auth\").\n3. **Flag uncovered RED zones** before acting. RED = money / auth / irreversible\n state. If any red zone has no annotation in this ZIP, report it and ask the\n developer whether to proceed.\n4. **Triage the whole batch before touching code.** Read every point first \u2014\n points on different pages can share one root cause (check their runtime\n context for a repeated failing URL or error message) and deserve one fix,\n not N. Write the plan down before editing anything.\n5. **Orchestrate, don't grind through it yourself.** For anything past a\n single trivial point: you're the brain, not the muscle. Spawn one Sonnet\n subagent per point/cluster (model pinned explicitly on every call, never\n inherited; effort is your judgment call per task), parallelized across\n points that touch disjoint files \u2014 never two agents on the same file. You\n supervise by checking what each subagent's report actually claims and by\n running the project's own verify/test command yourself afterward, not by\n rereading every diff or trusting a subagent's \"done.\"\n6. **Each point/cluster, before fixing:**\n - **Page** + **Selector** + **Note** \u2192 locate the element in the source\n (priority: `#id` \u2192 `[data-testid]` \u2192 `aria-label` \u2192 `name` \u2192 visual match\n via the screenshot named in the point's **Screenshot** line \u2014\n `screenshots/point-N.webp`, or `.png` on browsers without WebP).\n - **Severity** (`bug`/`question`/`polish`) and **Status**\n (`open`/`fixed`/`verified` \u2014 `fixed` means someone says it is done but\n nobody has re-tested it yet)\n tell you how to treat the point \u2014 a `question` may not need a code\n change; a `verified` point was already re-checked once.\n - **Runtime context** (when present, in a collapsed `<details>` block) \u2014\n recent console errors/warnings and failed network calls captured right\n before the tester clicked capture, plus an environment snapshot, plus\n **forensics** (contrast/accessibility flags on the captured element) when\n present \u2014 treat these as objective acceptance criteria, not just the\n tester's prose. Read it before assuming a UI-only cause. Query strings in\n any URL there are already redacted; bodies, headers, cookies, and storage\n were never captured at all.\n - **Reproduce it live first** \u2014 run the app, log in as the relevant role,\n navigate to the page, actually trigger the failure \u2014 before writing a\n fix. A static screenshot can hide a stale report or an interaction-only\n bug.\n - Make the change following the project conventions and invariants, then\n re-verify the same repro.\n7. **Report** a summary table of changes, risk levels, and coverage status,\n plus a `### Suggestions` section for anything noticed beyond the reported\n points. Whether you may *implement* an extra idea (not just suggest it)\n follows the same red/amber/green gating as everything else: green \u2014 do it\n inline; amber \u2014 do it and disclose it; red \u2014 propose only, never touch it.\n\n### A single point, no ZIP\n\nA tester can also send you **one point directly**, pasted via Qapture's\n\"Copy as agent prompt\" button, with no ZIP and no preamble. Treat it exactly\nlike one point from step 6 above \u2014 there's nothing to cluster or triage with\nonly one point, and there's no Coverage Report to check or RED-zone flag to\nraise, since there's no journey context at all. Just fix it yourself if it's\ntrivial, or spawn a single subagent if it isn't.\n\n### Full protocol\n\n`.claude/skills/qapture/SKILL.md` (always kept current by `qapture init`).\n\n### Rules\n\n- Never read `.env`, `.env.local`, `.env.production`, or any `secrets/` path.\n- Never edit `qa.config.ts`, `qa.preamble.md`, or any qapture plugin files.\n- Never push/publish/deploy without explicit human approval.\n- Dev/test/seed credentials only \u2014 never use or request production credentials.\n\n_Qapture \u2014 https://github.com/mohammed-farhood/qapture_\n\n<!-- /qa-studio-section -->\n";
|
|
36
36
|
|
|
37
37
|
// src/bin/utils/args.ts
|
|
38
38
|
function parseArgs(argv2) {
|