@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.
Files changed (98) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/LICENSE +21 -0
  3. package/README.md +636 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +879 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +5 -0
  8. package/dist/config.js +114 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/context.d.ts +1 -0
  11. package/dist/context.js +126 -0
  12. package/dist/context.js.map +1 -0
  13. package/dist/doctor.d.ts +32 -0
  14. package/dist/doctor.js +200 -0
  15. package/dist/doctor.js.map +1 -0
  16. package/dist/domain-language.d.ts +25 -0
  17. package/dist/domain-language.js +655 -0
  18. package/dist/domain-language.js.map +1 -0
  19. package/dist/domains.d.ts +33 -0
  20. package/dist/domains.js +258 -0
  21. package/dist/domains.js.map +1 -0
  22. package/dist/e2e.d.ts +326 -0
  23. package/dist/e2e.js +6869 -0
  24. package/dist/e2e.js.map +1 -0
  25. package/dist/eval.d.ts +40 -0
  26. package/dist/eval.js +374 -0
  27. package/dist/eval.js.map +1 -0
  28. package/dist/flows.d.ts +32 -0
  29. package/dist/flows.js +246 -0
  30. package/dist/flows.js.map +1 -0
  31. package/dist/fs.d.ts +7 -0
  32. package/dist/fs.js +132 -0
  33. package/dist/fs.js.map +1 -0
  34. package/dist/github.d.ts +34 -0
  35. package/dist/github.js +183 -0
  36. package/dist/github.js.map +1 -0
  37. package/dist/history.d.ts +173 -0
  38. package/dist/history.js +247 -0
  39. package/dist/history.js.map +1 -0
  40. package/dist/index.d.ts +35 -0
  41. package/dist/index.js +20 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/manifest-suggestions.d.ts +67 -0
  44. package/dist/manifest-suggestions.js +673 -0
  45. package/dist/manifest-suggestions.js.map +1 -0
  46. package/dist/manifest.d.ts +212 -0
  47. package/dist/manifest.js +1607 -0
  48. package/dist/manifest.js.map +1 -0
  49. package/dist/qa.d.ts +53 -0
  50. package/dist/qa.js +361 -0
  51. package/dist/qa.js.map +1 -0
  52. package/dist/report.d.ts +5 -0
  53. package/dist/report.js +164 -0
  54. package/dist/report.js.map +1 -0
  55. package/dist/review.d.ts +31 -0
  56. package/dist/review.js +383 -0
  57. package/dist/review.js.map +1 -0
  58. package/dist/scanner.d.ts +3 -0
  59. package/dist/scanner.js +797 -0
  60. package/dist/scanner.js.map +1 -0
  61. package/dist/severity.d.ts +3 -0
  62. package/dist/severity.js +9 -0
  63. package/dist/severity.js.map +1 -0
  64. package/dist/test-evidence.d.ts +39 -0
  65. package/dist/test-evidence.js +303 -0
  66. package/dist/test-evidence.js.map +1 -0
  67. package/dist/test-plan.d.ts +35 -0
  68. package/dist/test-plan.js +573 -0
  69. package/dist/test-plan.js.map +1 -0
  70. package/dist/types.d.ts +60 -0
  71. package/dist/types.js +2 -0
  72. package/dist/types.js.map +1 -0
  73. package/dist/verify.d.ts +27 -0
  74. package/dist/verify.js +244 -0
  75. package/dist/verify.js.map +1 -0
  76. package/dist/version.d.ts +2 -0
  77. package/dist/version.js +3 -0
  78. package/dist/version.js.map +1 -0
  79. package/docs/adoption.md +166 -0
  80. package/docs/agent-skill.md +94 -0
  81. package/docs/api-contracts.md +30 -0
  82. package/docs/assets/qamap-30s-demo.gif +0 -0
  83. package/docs/configuration.md +277 -0
  84. package/docs/e2e-output-examples.md +464 -0
  85. package/docs/ecosystem.md +41 -0
  86. package/docs/eval.md +52 -0
  87. package/docs/github-action.md +89 -0
  88. package/docs/manifest.md +350 -0
  89. package/docs/quickstart-demo.md +268 -0
  90. package/docs/release-validation.md +247 -0
  91. package/docs/releasing.md +112 -0
  92. package/docs/roadmap.md +67 -0
  93. package/docs/rules.md +28 -0
  94. package/docs/verify.md +44 -0
  95. package/package.json +80 -0
  96. package/schema/qamap-manifest.schema.json +323 -0
  97. package/schema/qamap.schema.json +58 -0
  98. package/skills/qamap-pr-qa/SKILL.md +81 -0
@@ -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
+ ![QAMap 30-second PR demo](assets/qamap-30s-demo.gif)
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
+ ```