@ivorycanvas/qamap 0.3.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/CHANGELOG.md +93 -0
- package/LICENSE +21 -0
- package/README.md +636 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +879 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +114 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +1 -0
- package/dist/context.js +126 -0
- package/dist/context.js.map +1 -0
- package/dist/doctor.d.ts +32 -0
- package/dist/doctor.js +200 -0
- package/dist/doctor.js.map +1 -0
- package/dist/domain-language.d.ts +25 -0
- package/dist/domain-language.js +655 -0
- package/dist/domain-language.js.map +1 -0
- package/dist/domains.d.ts +33 -0
- package/dist/domains.js +258 -0
- package/dist/domains.js.map +1 -0
- package/dist/e2e.d.ts +326 -0
- package/dist/e2e.js +6869 -0
- package/dist/e2e.js.map +1 -0
- package/dist/eval.d.ts +40 -0
- package/dist/eval.js +374 -0
- package/dist/eval.js.map +1 -0
- package/dist/flows.d.ts +32 -0
- package/dist/flows.js +246 -0
- package/dist/flows.js.map +1 -0
- package/dist/fs.d.ts +7 -0
- package/dist/fs.js +132 -0
- package/dist/fs.js.map +1 -0
- package/dist/github.d.ts +34 -0
- package/dist/github.js +183 -0
- package/dist/github.js.map +1 -0
- package/dist/history.d.ts +173 -0
- package/dist/history.js +247 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest-suggestions.d.ts +67 -0
- package/dist/manifest-suggestions.js +673 -0
- package/dist/manifest-suggestions.js.map +1 -0
- package/dist/manifest.d.ts +212 -0
- package/dist/manifest.js +1607 -0
- package/dist/manifest.js.map +1 -0
- package/dist/qa.d.ts +53 -0
- package/dist/qa.js +361 -0
- package/dist/qa.js.map +1 -0
- package/dist/report.d.ts +5 -0
- package/dist/report.js +164 -0
- package/dist/report.js.map +1 -0
- package/dist/review.d.ts +31 -0
- package/dist/review.js +383 -0
- package/dist/review.js.map +1 -0
- package/dist/scanner.d.ts +3 -0
- package/dist/scanner.js +797 -0
- package/dist/scanner.js.map +1 -0
- package/dist/severity.d.ts +3 -0
- package/dist/severity.js +9 -0
- package/dist/severity.js.map +1 -0
- package/dist/test-evidence.d.ts +39 -0
- package/dist/test-evidence.js +303 -0
- package/dist/test-evidence.js.map +1 -0
- package/dist/test-plan.d.ts +35 -0
- package/dist/test-plan.js +573 -0
- package/dist/test-plan.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +27 -0
- package/dist/verify.js +244 -0
- package/dist/verify.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/docs/adoption.md +166 -0
- package/docs/agent-skill.md +94 -0
- package/docs/api-contracts.md +30 -0
- package/docs/assets/qamap-30s-demo.gif +0 -0
- package/docs/configuration.md +277 -0
- package/docs/e2e-output-examples.md +464 -0
- package/docs/ecosystem.md +41 -0
- package/docs/eval.md +52 -0
- package/docs/github-action.md +89 -0
- package/docs/manifest.md +350 -0
- package/docs/quickstart-demo.md +268 -0
- package/docs/release-validation.md +247 -0
- package/docs/releasing.md +112 -0
- package/docs/roadmap.md +67 -0
- package/docs/rules.md +28 -0
- package/docs/verify.md +44 -0
- package/package.json +80 -0
- package/schema/qamap-manifest.schema.json +323 -0
- package/schema/qamap.schema.json +58 -0
- package/skills/qamap-pr-qa/SKILL.md +81 -0
package/docs/manifest.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Verification Manifest
|
|
2
|
+
|
|
3
|
+
`.qamap/manifest.yaml` is QAMap's repo-local verification memory. It lets a team capture the product domains, flows, anchors, and checks that static analysis cannot reliably infer from code alone.
|
|
4
|
+
|
|
5
|
+
> **Important:** create the shared team baseline from the repository's default branch, after pulling the latest changes. QAMap reads the current checkout and does not silently switch branches, so a manifest generated on a feature branch represents that feature branch rather than the team's default QA map.
|
|
6
|
+
|
|
7
|
+
The intended workflow for the first shared baseline is:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
git switch main
|
|
11
|
+
git pull
|
|
12
|
+
qamap manifest context .
|
|
13
|
+
qamap manifest init .
|
|
14
|
+
qamap manifest validate .
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then use the committed manifest from feature branches or PR branches:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
qamap manifest explain . --base origin/main --head HEAD
|
|
21
|
+
qamap e2e draft . --base origin/main --head HEAD --dry-run
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or preview adoption without writing `.qamap/manifest.yaml` into the target repository:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
qamap manifest init . --write /tmp/qamap-manifest.yaml
|
|
28
|
+
qamap manifest validate . --manifest /tmp/qamap-manifest.yaml
|
|
29
|
+
qamap manifest explain . --manifest /tmp/qamap-manifest.yaml --base origin/main --head HEAD
|
|
30
|
+
qamap e2e draft . --manifest /tmp/qamap-manifest.yaml --base origin/main --head HEAD --dry-run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`manifest init` reads the current checkout on disk. It does not silently switch to the default branch, because changing a developer's branch or working tree would be surprising and unsafe. If the team wants the manifest to represent the default product baseline, run it from the default branch after pulling the latest changes.
|
|
34
|
+
|
|
35
|
+
`manifest context` is the read-only preview step. It shows which repo-local documents QAMap sees, how each source is classified, which validation commands and safety rules were extracted, and which manifest path should be reviewed if the context is missing or stale. Use it before `manifest init` when you want to understand the bootstrap input without writing `.qamap/manifest.yaml`.
|
|
36
|
+
|
|
37
|
+
During baseline generation, QAMap also looks for repo-local context documents that often contain verification knowledge not visible in source files:
|
|
38
|
+
|
|
39
|
+
- `CONTEXT.md` and `CONTEXT-MAP.md`
|
|
40
|
+
- ADRs such as `docs/adr/*.md`
|
|
41
|
+
- goal documents such as `goals/*.md`
|
|
42
|
+
- agent instruction, harness, and skill files such as `AGENTS.md` and project-local instruction folders
|
|
43
|
+
- QA, test, release, and runbook documents under `docs/`
|
|
44
|
+
|
|
45
|
+
These files are used as advisory bootstrap context. They can improve initial naming, validation command hints, and safety rules, but they are not treated as product truth until a human reviews the manifest.
|
|
46
|
+
|
|
47
|
+
## What It Solves
|
|
48
|
+
|
|
49
|
+
QAMap cannot know every team's product priorities from file paths alone. The manifest turns repeated human review knowledge into durable repository context:
|
|
50
|
+
|
|
51
|
+
- which file paths belong to a product domain
|
|
52
|
+
- which routes, components, APIs, or tests anchor an important flow
|
|
53
|
+
- which success, failure, edge, contract, or visual checks matter for that flow
|
|
54
|
+
- which runner usually verifies the flow
|
|
55
|
+
- whether the entry came from QAMap inference or human review
|
|
56
|
+
|
|
57
|
+
When a recommendation is wrong, edit the manifest path shown in QAMap output. The next branch should get better recommendations without another explanation.
|
|
58
|
+
|
|
59
|
+
## Concrete Bootstrap Example
|
|
60
|
+
|
|
61
|
+
A first baseline can be useful before a human writes YAML by hand. Suppose the default branch has:
|
|
62
|
+
|
|
63
|
+
```txt
|
|
64
|
+
CONTEXT.md
|
|
65
|
+
docs/adr/checkout-purchase.md
|
|
66
|
+
AGENTS.md
|
|
67
|
+
src/pages/checkout/index.tsx
|
|
68
|
+
playwright.config.ts
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If the ADR and context docs use the team phrase `Checkout purchase`, and the route file exposes `/checkout`, `qamap manifest init .` can create a manifest flow close to:
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
flows:
|
|
75
|
+
- id: checkout-checkout-purchase
|
|
76
|
+
domain: checkout
|
|
77
|
+
name: Checkout Purchase
|
|
78
|
+
entry:
|
|
79
|
+
route: /checkout
|
|
80
|
+
source: inferred
|
|
81
|
+
runner: playwright
|
|
82
|
+
source:
|
|
83
|
+
kind: inferred
|
|
84
|
+
confidence: medium
|
|
85
|
+
from:
|
|
86
|
+
- route-file
|
|
87
|
+
- adr-context
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
When a later PR changes `src/pages/checkout/index.tsx`, `qamap manifest explain . --base origin/main --head HEAD` should name the same flow, show the manifest evidence, and print the repair path:
|
|
91
|
+
|
|
92
|
+
```txt
|
|
93
|
+
Flow: Checkout Purchase
|
|
94
|
+
Evidence sources: route-file, adr-context
|
|
95
|
+
If this is wrong: update `.qamap/manifest.yaml > flows.checkout-checkout-purchase.anchors`
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then `qamap e2e draft . --base origin/main --head HEAD --dry-run` can preview a concrete draft such as `tests/e2e/checkout-purchase.spec.ts`, using the manifest route, detected selectors, and manifest checks before falling back to generic smoke-test heuristics.
|
|
99
|
+
|
|
100
|
+
## Schema
|
|
101
|
+
|
|
102
|
+
Generated manifests include:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
$schema: https://raw.githubusercontent.com/IvoryCanvas/qamap/main/schema/qamap-manifest.schema.json
|
|
106
|
+
version: 1
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The JSON Schema is shipped in the package at:
|
|
110
|
+
|
|
111
|
+
```txt
|
|
112
|
+
schema/qamap-manifest.schema.json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Editors that understand YAML schema comments or `$schema` fields can use this file for validation and completion.
|
|
116
|
+
|
|
117
|
+
## Context Sources
|
|
118
|
+
|
|
119
|
+
When context documents are present, generated manifests may include a `context` section:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
context:
|
|
123
|
+
instructionFiles:
|
|
124
|
+
- path: CONTEXT.md
|
|
125
|
+
kind: context
|
|
126
|
+
confidence: medium
|
|
127
|
+
roles:
|
|
128
|
+
- domain-context
|
|
129
|
+
signals:
|
|
130
|
+
- role:domain-context
|
|
131
|
+
- domain-language
|
|
132
|
+
- path: docs/adr/checkout-flow.md
|
|
133
|
+
kind: adr
|
|
134
|
+
confidence: medium
|
|
135
|
+
roles:
|
|
136
|
+
- domain-context
|
|
137
|
+
- workflow-lifecycle
|
|
138
|
+
signals:
|
|
139
|
+
- role:domain-context
|
|
140
|
+
- role:workflow-lifecycle
|
|
141
|
+
- architecture-decision
|
|
142
|
+
- path: AGENTS.md
|
|
143
|
+
kind: agent-instruction
|
|
144
|
+
confidence: medium
|
|
145
|
+
roles:
|
|
146
|
+
- verification-rubric
|
|
147
|
+
- test-runner
|
|
148
|
+
- safety-policy
|
|
149
|
+
signals:
|
|
150
|
+
- validation-command
|
|
151
|
+
- safety-rule
|
|
152
|
+
- role:verification-rubric
|
|
153
|
+
- path: .agent-core/skills/verification-layer.md
|
|
154
|
+
kind: agent-instruction
|
|
155
|
+
confidence: medium
|
|
156
|
+
roles:
|
|
157
|
+
- agent-skill
|
|
158
|
+
- harness-config
|
|
159
|
+
- workflow-lifecycle
|
|
160
|
+
- verification-rubric
|
|
161
|
+
signals:
|
|
162
|
+
- role:agent-skill
|
|
163
|
+
- role:workflow-lifecycle
|
|
164
|
+
validationCommands:
|
|
165
|
+
- pnpm test
|
|
166
|
+
safetyRules:
|
|
167
|
+
- Never write generated E2E drafts into target repos during smoke tests; use /tmp outputs.
|
|
168
|
+
source:
|
|
169
|
+
kind: inferred
|
|
170
|
+
confidence: medium
|
|
171
|
+
from:
|
|
172
|
+
- context-document-context
|
|
173
|
+
- adr-context
|
|
174
|
+
- agent-instruction-context
|
|
175
|
+
- verification-rubric-context
|
|
176
|
+
- agent-skill-context
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Use this section to understand which repo-local documents influenced the baseline. Keep the trust boundary clear:
|
|
180
|
+
|
|
181
|
+
- `CONTEXT.md`, ADRs, and goals can carry product language and intent.
|
|
182
|
+
- agent instructions, harness files, skills, and runbooks usually carry workflow, safety, and validation rules.
|
|
183
|
+
- `roles` explain how QAMap classified a context source: product domain context, workflow lifecycle, verification rubric, test runner, safety policy, release policy, agent skill, or harness config.
|
|
184
|
+
- instruction-derived context should start as `inferred` and should not override human-reviewed domains, flows, and checks.
|
|
185
|
+
- if a recommendation is wrong because a context document is stale, update the document or remove the stale context source from the manifest.
|
|
186
|
+
|
|
187
|
+
## Context Report
|
|
188
|
+
|
|
189
|
+
Run `qamap manifest context .` to see the context layer without writing files:
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
qamap manifest context . --format markdown
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The report includes:
|
|
196
|
+
|
|
197
|
+
- role summary by source file, such as `verification-rubric`, `test-runner`, `agent-skill`, or `harness-config`
|
|
198
|
+
- captured context sources with kind, confidence, roles, and signals
|
|
199
|
+
- validation commands and safety rules extracted from local docs
|
|
200
|
+
- diagnostics that point to the manifest path to edit when context is missing, stale, too broad, or not connected to checks
|
|
201
|
+
|
|
202
|
+
This command is useful when an E2E recommendation feels too vague. Instead of asking an LLM to re-read the repository, inspect the report, correct the repo-local context or `.qamap/manifest.yaml`, then rerun `qamap e2e draft`.
|
|
203
|
+
|
|
204
|
+
## Minimal Example
|
|
205
|
+
|
|
206
|
+
```yaml
|
|
207
|
+
$schema: https://raw.githubusercontent.com/IvoryCanvas/qamap/main/schema/qamap-manifest.schema.json
|
|
208
|
+
version: 1
|
|
209
|
+
|
|
210
|
+
domains:
|
|
211
|
+
- id: campaign
|
|
212
|
+
name: Campaign
|
|
213
|
+
paths:
|
|
214
|
+
- src/pages/campaign/**
|
|
215
|
+
criticality: medium
|
|
216
|
+
source:
|
|
217
|
+
kind: declared
|
|
218
|
+
confidence: high
|
|
219
|
+
from:
|
|
220
|
+
- product-qa
|
|
221
|
+
|
|
222
|
+
flows:
|
|
223
|
+
- id: campaign-application-complete
|
|
224
|
+
domain: campaign
|
|
225
|
+
name: Campaign Application Complete
|
|
226
|
+
entry:
|
|
227
|
+
route: /campaign/official/applicationComplete
|
|
228
|
+
source: declared
|
|
229
|
+
runner: playwright
|
|
230
|
+
anchors:
|
|
231
|
+
- kind: route
|
|
232
|
+
path: src/pages/campaign/official/applicationComplete.tsx
|
|
233
|
+
route: /campaign/official/applicationComplete
|
|
234
|
+
source: declared
|
|
235
|
+
confidence: high
|
|
236
|
+
checks:
|
|
237
|
+
- id: happy-path
|
|
238
|
+
title: Submit content URL successfully
|
|
239
|
+
type: success
|
|
240
|
+
selector: "[data-testid=content-url-submit]"
|
|
241
|
+
- id: invalid-input
|
|
242
|
+
title: Show validation error for invalid content URL
|
|
243
|
+
type: failure
|
|
244
|
+
selector: "[data-testid=content-url-error]"
|
|
245
|
+
source:
|
|
246
|
+
kind: declared
|
|
247
|
+
confidence: high
|
|
248
|
+
from:
|
|
249
|
+
- product-qa
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Fields
|
|
253
|
+
|
|
254
|
+
| Field | Purpose |
|
|
255
|
+
| --- | --- |
|
|
256
|
+
| `domains[].id` | Stable machine-readable product area id. |
|
|
257
|
+
| `domains[].name` | Human-facing product term used in reports and draft titles. |
|
|
258
|
+
| `domains[].paths` | Glob-like path patterns relative to the manifest root. |
|
|
259
|
+
| `domains[].criticality` | `low`, `medium`, or `high` attention signal. |
|
|
260
|
+
| `flows[].id` | Stable machine-readable flow id. |
|
|
261
|
+
| `flows[].domain` | Optional domain id that owns the flow. |
|
|
262
|
+
| `flows[].entry.route` | Route hint used by Playwright drafts when available. |
|
|
263
|
+
| `flows[].runner` | Preferred verification runner: `playwright`, `maestro`, or `manual`. |
|
|
264
|
+
| `flows[].anchors` | Matchable route, component, file, API, or test anchors. |
|
|
265
|
+
| `flows[].checks` | Required verification points that should shape E2E drafts. |
|
|
266
|
+
| `flows[].checks[].selector` | Optional stable selector hint for this check, such as `[data-testid=coupon-input]`. |
|
|
267
|
+
| `flows[].checks[].value` | Optional input value for this check, such as `WELCOME10` or `qa@example.com`. |
|
|
268
|
+
| `flows[].checks[].steps` | Optional concrete steps for this check. These are used before the title parser. |
|
|
269
|
+
| `context.instructionFiles` | Advisory repo-local context sources used while bootstrapping the manifest. |
|
|
270
|
+
| `context.instructionFiles[].roles` | Advisory role classification for a context source, such as `verification-rubric`, `workflow-lifecycle`, `agent-skill`, or `harness-config`. |
|
|
271
|
+
| `context.validationCommands` | Validation commands inferred from context documents. |
|
|
272
|
+
| `context.safetyRules` | Workflow or safety rules inferred from context documents, with token-like values redacted. |
|
|
273
|
+
| `source.kind` | `inferred` for QAMap-generated entries or `declared` after human review. |
|
|
274
|
+
| `source.confidence` | `low`, `medium`, or `high` confidence in the entry. |
|
|
275
|
+
| `source.from` | Evidence sources such as `route-file`, `component-file`, `product-qa`, or `human-reviewed`. |
|
|
276
|
+
|
|
277
|
+
## Validate
|
|
278
|
+
|
|
279
|
+
Run:
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
qamap manifest validate .
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The validator checks for:
|
|
286
|
+
|
|
287
|
+
- missing or unparsable manifests
|
|
288
|
+
- duplicate domain, flow, or check ids
|
|
289
|
+
- missing domain path patterns
|
|
290
|
+
- flow references to unknown domains
|
|
291
|
+
- flows without anchors or checks
|
|
292
|
+
- anchor paths that no longer exist
|
|
293
|
+
- duplicate anchors
|
|
294
|
+
- route hints that do not start with `/`
|
|
295
|
+
- missing or unusual `$schema` values
|
|
296
|
+
- low-confidence inferred entries that need human review
|
|
297
|
+
- stale context source paths and advisory instruction-derived context
|
|
298
|
+
|
|
299
|
+
`invalid` and `missing` exit with code `1`. `valid` and `needs-work` exit with code `0` so teams can adopt the manifest gradually before making it a hard CI gate.
|
|
300
|
+
|
|
301
|
+
## Explain
|
|
302
|
+
|
|
303
|
+
Run:
|
|
304
|
+
|
|
305
|
+
```sh
|
|
306
|
+
qamap manifest explain . --base origin/main --head HEAD
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
This command answers:
|
|
310
|
+
|
|
311
|
+
- which changed files matched manifest domains
|
|
312
|
+
- which flow anchors matched the branch
|
|
313
|
+
- which checks are now relevant
|
|
314
|
+
- why the match happened
|
|
315
|
+
- which next verification actions are worth spending time on
|
|
316
|
+
- which repair hints can improve future recommendations
|
|
317
|
+
- which manifest path to edit when the recommendation is wrong
|
|
318
|
+
|
|
319
|
+
## Draft Impact
|
|
320
|
+
|
|
321
|
+
When a matched manifest flow has an entry route and checks, `qamap e2e draft` promotes that flow ahead of heuristic candidates. The generated draft includes:
|
|
322
|
+
|
|
323
|
+
- `source: verification-manifest` in JSON output
|
|
324
|
+
- the manifest route as a Playwright entrypoint when supported
|
|
325
|
+
- manifest checks as draft steps and coverage notes
|
|
326
|
+
- check-level selector/value/steps hints as concrete draft actions when available
|
|
327
|
+
- manifest evidence comments inside generated files
|
|
328
|
+
- promotion guidance that treats strong manifest matches as commit candidates
|
|
329
|
+
|
|
330
|
+
This keeps generated tests explainable. A draft is not promoted because QAMap guessed well once; it is promoted because the repo has durable verification context.
|
|
331
|
+
|
|
332
|
+
Manifest-backed output should reduce repeat reviewer labor. A recommendation is useful only when it answers three questions:
|
|
333
|
+
|
|
334
|
+
- why did this PR touch this product flow?
|
|
335
|
+
- what should a developer verify now?
|
|
336
|
+
- what repo-local manifest or context entry should be repaired if the recommendation is noisy?
|
|
337
|
+
|
|
338
|
+
## Adoption Guidance
|
|
339
|
+
|
|
340
|
+
Start with `manifest init`, but do not expect the first baseline to be perfect. Review the entries that affect your next PR:
|
|
341
|
+
|
|
342
|
+
- rename domains from file-oriented names to product terms
|
|
343
|
+
- mark accepted entries as `declared`
|
|
344
|
+
- raise confidence only when the team agrees
|
|
345
|
+
- add failure, edge, contract, and visual checks where they are truly required
|
|
346
|
+
- keep path patterns narrow enough that recommendations stay explainable
|
|
347
|
+
- review context-derived validation commands and safety rules before treating them as team policy
|
|
348
|
+
- prefer manifest anchors over inline code comments until symbol-level anchors are intentionally adopted
|
|
349
|
+
|
|
350
|
+
For private or complex products, the manifest is the place to encode what humans already know but do not want to repeat in every PR review.
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# 30-Second Quick Start Demo
|
|
2
|
+
|
|
3
|
+
This demo is the shortest way to show what QAMap does in a public README, blog post, or launch thread.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
The GIF shows a simulated local PR where a checkout form changed. QAMap does not report a real browser test pass during `--dry-run`. It reports the generated verification artifact: the affected flow, the planned Playwright draft path, static self-check status, and the remaining work before the draft can be trusted as PR evidence.
|
|
8
|
+
|
|
9
|
+
## Story
|
|
10
|
+
|
|
11
|
+
A reviewer sees a PR that changes a checkout form:
|
|
12
|
+
|
|
13
|
+
```txt
|
|
14
|
+
src/app/checkout/page.tsx
|
|
15
|
+
src/features/checkout/CheckoutForm.tsx
|
|
16
|
+
src/features/checkout/submitCheckout.ts
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The reviewer wants to know:
|
|
20
|
+
|
|
21
|
+
- Which user flow is affected?
|
|
22
|
+
- Should this become a Playwright test, a manual checklist, or only a review note?
|
|
23
|
+
- What blocks the generated draft from being trusted as regression coverage?
|
|
24
|
+
|
|
25
|
+
## Command
|
|
26
|
+
|
|
27
|
+
Run QAMap on the branch:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
pnpm dlx @ivorycanvas/qamap qa . --base origin/main --head HEAD
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`qa` is important for first contact. It lets maintainers preview the PR comment draft, affected flow, draft path, readiness, and blockers without writing files.
|
|
34
|
+
|
|
35
|
+
When the team wants actual draft files:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
pnpm dlx @ivorycanvas/qamap e2e draft . --base origin/main --head HEAD --dry-run
|
|
39
|
+
pnpm dlx @ivorycanvas/qamap e2e draft . --base origin/main --head HEAD
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For a repository adopting QAMap as team QA memory, start with the manifest loop:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pnpm dlx @ivorycanvas/qamap manifest context .
|
|
46
|
+
pnpm dlx @ivorycanvas/qamap manifest init .
|
|
47
|
+
pnpm dlx @ivorycanvas/qamap manifest validate .
|
|
48
|
+
pnpm dlx @ivorycanvas/qamap manifest explain . --base origin/main --head HEAD
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For a read-only smoke test against a repository you do not want to modify, keep the manifest outside the repo and pass it back into the PR commands:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
pnpm dlx @ivorycanvas/qamap manifest init . --write /tmp/qamap-manifest.yaml
|
|
55
|
+
pnpm dlx @ivorycanvas/qamap qa . --manifest /tmp/qamap-manifest.yaml --base origin/main --head HEAD
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The manifest is the durable part. It lets a team correct domains, flows, anchors, and checks once, then reuse that correction across future PRs without re-explaining the same QA context to an LLM.
|
|
59
|
+
|
|
60
|
+
If your coding agent supports reusable local instructions, use the packaged skill template as the PR handoff workflow:
|
|
61
|
+
|
|
62
|
+
```txt
|
|
63
|
+
skills/qamap-pr-qa/SKILL.md
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Manifest-Backed PoC Path
|
|
67
|
+
|
|
68
|
+
The practical PoC is not "QAMap reads every project perfectly." The useful loop is:
|
|
69
|
+
|
|
70
|
+
```txt
|
|
71
|
+
default branch repo context
|
|
72
|
+
-> qamap manifest init
|
|
73
|
+
-> reviewed .qamap/manifest.yaml
|
|
74
|
+
|
|
75
|
+
PR branch diff
|
|
76
|
+
-> qamap manifest explain
|
|
77
|
+
-> qamap e2e draft
|
|
78
|
+
-> draft test file plus manifest repair path
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
For example, a repository can contain:
|
|
82
|
+
|
|
83
|
+
```txt
|
|
84
|
+
CONTEXT.md
|
|
85
|
+
docs/adr/checkout-purchase.md
|
|
86
|
+
AGENTS.md
|
|
87
|
+
src/pages/checkout/index.tsx
|
|
88
|
+
playwright.config.ts
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If `docs/adr/checkout-purchase.md` says the checkout purchase flow must cover success, API failure, and visible confirmation evidence, `manifest init` can bootstrap a flow named `Checkout Purchase` with the route `/checkout`. When a later PR changes `src/pages/checkout/index.tsx`, QAMap can connect the changed route to that manifest flow and preview:
|
|
92
|
+
|
|
93
|
+
```txt
|
|
94
|
+
Manifest Recommendations
|
|
95
|
+
- Flow: Checkout Purchase
|
|
96
|
+
- Entry route: /checkout
|
|
97
|
+
- Evidence sources: route-file, adr-context
|
|
98
|
+
- Required checks:
|
|
99
|
+
- Checkout Purchase uses deterministic success fixture data
|
|
100
|
+
- Checkout Purchase handles failed, empty, or unauthorized responses
|
|
101
|
+
- If this is wrong: update .qamap/manifest.yaml > flows.checkout-checkout-purchase.anchors
|
|
102
|
+
|
|
103
|
+
Draft file
|
|
104
|
+
- tests/e2e/checkout-purchase.spec.ts
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
That draft is intentionally concrete enough to edit, run, and promote:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { expect, test } from "@playwright/test";
|
|
111
|
+
|
|
112
|
+
test("Checkout Purchase", async ({ page }) => {
|
|
113
|
+
// Verification manifest evidence:
|
|
114
|
+
// Flow: Checkout Purchase
|
|
115
|
+
// .qamap/manifest.yaml > flows.checkout-checkout-purchase.anchors
|
|
116
|
+
|
|
117
|
+
await test.step("Open route /checkout.", async () => {
|
|
118
|
+
await page.goto("/checkout");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await test.step("Fill Email with realistic data.", async () => {
|
|
122
|
+
await page.getByPlaceholder("Email").fill("qamap@example.com");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
await test.step("Submit using Checkout Submit.", async () => {
|
|
126
|
+
await page.getByTestId("checkout-submit").click();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await expect(page.getByText("Order confirmed")).toBeVisible();
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The human still owns the final truth: fixture data, auth state, API mocks, and assertions must match the real product. The saving is that the repeated context work moves into repo-local manifest memory, and a wrong recommendation points to the manifest path to repair instead of asking a new AI prompt to re-learn the project.
|
|
134
|
+
|
|
135
|
+
## What QAMap Reads
|
|
136
|
+
|
|
137
|
+
```txt
|
|
138
|
+
Input
|
|
139
|
+
- git diff between origin/main and HEAD
|
|
140
|
+
- package.json scripts and dependencies
|
|
141
|
+
- framework and route files
|
|
142
|
+
- existing E2E runner config
|
|
143
|
+
- stable selectors such as data-testid, aria-label, role text, placeholder text, and testID
|
|
144
|
+
- optional team-owned context in .qamap/manifest.yaml, CONTEXT.md, ADRs, goals, QA runbooks, and agent instructions
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## What QAMap Returns
|
|
148
|
+
|
|
149
|
+
```txt
|
|
150
|
+
Output
|
|
151
|
+
- PR comment/checklist draft
|
|
152
|
+
- changed domain language
|
|
153
|
+
- candidate user flow
|
|
154
|
+
- manifest evidence when a repo-local flow/check matches
|
|
155
|
+
- recommended runner
|
|
156
|
+
- draft file path
|
|
157
|
+
- flow language brief
|
|
158
|
+
- runnable status
|
|
159
|
+
- self-check status
|
|
160
|
+
- required action items
|
|
161
|
+
- blockers that explain why a draft is not ready yet
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The result should not stop at "selector needed" or "fixture needed." A useful QAMap draft should say which flow changed, which test file would be generated, which checks it covers, why those checks were selected, and where to update the manifest if the recommendation is wrong.
|
|
165
|
+
|
|
166
|
+
## Markdown Preview
|
|
167
|
+
|
|
168
|
+
```txt
|
|
169
|
+
# QAMap QA Draft
|
|
170
|
+
|
|
171
|
+
Summary
|
|
172
|
+
- Project: Web
|
|
173
|
+
- Recommended runner: Playwright
|
|
174
|
+
- Manifest: .qamap/manifest.yaml
|
|
175
|
+
- Readiness: near-runnable
|
|
176
|
+
|
|
177
|
+
PR Comment Draft
|
|
178
|
+
- Affected flow: Checkout purchase
|
|
179
|
+
- Suggested draft: tests/e2e/checkout-purchase.spec.ts
|
|
180
|
+
- User journey: Customer -> Open route /checkout -> Complete checkout with realistic form data
|
|
181
|
+
- Success signal: confirmation state is visible after submit
|
|
182
|
+
|
|
183
|
+
Missing evidence before trusting this PR
|
|
184
|
+
- [required] fixture: Add deterministic payment/customer fixture data.
|
|
185
|
+
- [recommended] selector: Confirm stable selectors for changed checkout controls.
|
|
186
|
+
|
|
187
|
+
PR checklist
|
|
188
|
+
- [ ] Review tests/e2e/checkout-purchase.spec.ts.
|
|
189
|
+
- [ ] Confirm success and failed-response assertions.
|
|
190
|
+
- [ ] Run pnpm run test:e2e.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Draft Shape
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { expect, test } from "@playwright/test";
|
|
197
|
+
|
|
198
|
+
test("Checkout purchase", async ({ page }) => {
|
|
199
|
+
await test.step("Open route /checkout.", async () => {
|
|
200
|
+
await page.goto("/checkout");
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await test.step("Fill checkout email.", async () => {
|
|
204
|
+
await page.getByPlaceholder("Email").fill("buyer@example.com");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
await test.step("Fill checkout name.", async () => {
|
|
208
|
+
await page.getByPlaceholder("Name").fill("Ada Lovelace");
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
await test.step("Submit checkout.", async () => {
|
|
212
|
+
await page.getByRole("button", { name: "Complete purchase" }).click();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
await expect(page.getByText("Order confirmed")).toBeVisible();
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
In the demo branch, the generated test is meant to protect this review question:
|
|
220
|
+
|
|
221
|
+
```txt
|
|
222
|
+
Can a customer still complete the Checkout purchase flow after the checkout form change?
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The draft covers:
|
|
226
|
+
|
|
227
|
+
- entering the checkout route
|
|
228
|
+
- using the changed checkout form controls
|
|
229
|
+
- checking the success/confirmation state
|
|
230
|
+
- checking the invalid-input recovery path
|
|
231
|
+
|
|
232
|
+
The dry-run result is intentionally conservative:
|
|
233
|
+
|
|
234
|
+
```txt
|
|
235
|
+
Generated E2E draft: yes
|
|
236
|
+
Static Playwright self-check: pass
|
|
237
|
+
Browser test execution: not run in --dry-run
|
|
238
|
+
Still required: deterministic fixture/mock data and real pnpm run test:e2e execution
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Recording A Short GIF
|
|
242
|
+
|
|
243
|
+
Use a tiny branch where a form, button, route, or API client changed. The recording only needs three terminal moments:
|
|
244
|
+
|
|
245
|
+
```sh
|
|
246
|
+
git diff --stat origin/main...HEAD
|
|
247
|
+
pnpm dlx @ivorycanvas/qamap qa . --base origin/main --head HEAD
|
|
248
|
+
pnpm dlx @ivorycanvas/qamap verify . --base origin/main --head HEAD --format markdown
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The best GIF is not a long terminal scroll. Show:
|
|
252
|
+
|
|
253
|
+
- the changed files
|
|
254
|
+
- the generated flow name
|
|
255
|
+
- the planned draft path
|
|
256
|
+
- the required action items
|
|
257
|
+
- the no-write `--dry-run` line
|
|
258
|
+
|
|
259
|
+
## Launch Message
|
|
260
|
+
|
|
261
|
+
```txt
|
|
262
|
+
QAMap turns a PR diff into affected flows, missing QA evidence, and draft E2E/checklist work.
|
|
263
|
+
|
|
264
|
+
It runs locally, does not upload source code, and does not call an LLM API.
|
|
265
|
+
|
|
266
|
+
Try it:
|
|
267
|
+
pnpm dlx @ivorycanvas/qamap qa . --base origin/main --head HEAD
|
|
268
|
+
```
|