@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
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
# E2E Output Examples
|
|
2
|
+
|
|
3
|
+
These examples show the shape of QAMap output that should be good enough for the current public release. They are intentionally short snippets, not full generated files. The important property is that they are derived from repository structure, git changes, manifests, and test evidence without an LLM call.
|
|
4
|
+
|
|
5
|
+
## PR QA Skill Preview
|
|
6
|
+
|
|
7
|
+
First contact should work without a manifest:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm dlx @ivorycanvas/qamap qa . --base origin/main --head HEAD
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The output should be specific enough to paste into a PR comment:
|
|
14
|
+
|
|
15
|
+
```txt
|
|
16
|
+
# QAMap QA Draft
|
|
17
|
+
|
|
18
|
+
Summary
|
|
19
|
+
- Project: Web
|
|
20
|
+
- Recommended runner: Playwright
|
|
21
|
+
- Manifest: not found; using repo signals and PR diff only
|
|
22
|
+
- Readiness: near-runnable
|
|
23
|
+
|
|
24
|
+
PR Comment Draft
|
|
25
|
+
- Affected flow: Checkout UI smoke flow
|
|
26
|
+
- User journey: Customer -> Open route /checkout -> Complete checkout with realistic form data
|
|
27
|
+
- Success signal: confirmation state is visible after submit
|
|
28
|
+
- Changed files: src/pages/checkout/index.tsx
|
|
29
|
+
|
|
30
|
+
Suggested E2E / QA Draft
|
|
31
|
+
- tests/e2e/checkout-ui-smoke-flow.spec.ts: near runnable
|
|
32
|
+
- Open route /checkout.
|
|
33
|
+
- Fill checkout email.
|
|
34
|
+
- Submit checkout.
|
|
35
|
+
- Assert confirmation state is visible after submit.
|
|
36
|
+
|
|
37
|
+
Missing evidence before trusting this PR
|
|
38
|
+
- [required] fixture: Add deterministic fixture or mock data.
|
|
39
|
+
- [recommended] selector: Confirm stable selectors.
|
|
40
|
+
|
|
41
|
+
PR checklist
|
|
42
|
+
- [ ] Review the generated draft path.
|
|
43
|
+
- [ ] Answer the reviewer question for the affected flow.
|
|
44
|
+
- [ ] Run local validation: pnpm run test:e2e
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If this recommendation is useful but slightly wrong, the next step is not another long AI prompt. Generate and correct repo-local QA memory:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pnpm exec qamap manifest init .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then future `qamap qa` runs can use `.qamap/manifest.yaml` to produce more precise flow names, checks, anchors, and repair paths.
|
|
54
|
+
|
|
55
|
+
## Verification Manifest Feedback
|
|
56
|
+
|
|
57
|
+
When a repository has `.qamap/manifest.yaml`, QAMap should explain why a recommendation happened and how a maintainer can correct it:
|
|
58
|
+
|
|
59
|
+
```txt
|
|
60
|
+
Manifest recommendations: 3
|
|
61
|
+
|
|
62
|
+
Campaign Application Complete `campaign-application-complete`
|
|
63
|
+
- Kind: flow
|
|
64
|
+
- Confidence: high
|
|
65
|
+
- Why this was recommended: Changed files match anchors for the Campaign Application Complete flow.
|
|
66
|
+
- Evidence sources: product-qa
|
|
67
|
+
- Manifest evidence: .qamap/manifest.yaml > flows.campaign-application-complete.anchors
|
|
68
|
+
- If this is wrong: update .qamap/manifest.yaml > flows.campaign-application-complete.anchors
|
|
69
|
+
- Next actions:
|
|
70
|
+
- Draft or review E2E coverage for the Campaign Application Complete flow.
|
|
71
|
+
- Cover the declared checks: Submit content URL successfully; Show validation error for invalid content URL.
|
|
72
|
+
- Repair hints:
|
|
73
|
+
- If these files do not belong to this flow, update .qamap/manifest.yaml > flows.campaign-application-complete.anchors.
|
|
74
|
+
- If the recommended assertions feel vague, rewrite .qamap/manifest.yaml > flows.campaign-application-complete.checks in team language.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This is the feedback loop: static analysis proposes a baseline, humans correct durable manifest entries, and future E2E recommendations become more specific without spending another LLM prompt on the same explanation.
|
|
78
|
+
|
|
79
|
+
`qamap manifest validate .` checks whether that repo-local knowledge is usable:
|
|
80
|
+
|
|
81
|
+
```txt
|
|
82
|
+
QAMap Manifest Validate
|
|
83
|
+
Status: valid
|
|
84
|
+
Manifest: .qamap/manifest.yaml
|
|
85
|
+
Issues: 0 errors, 0 warnings, 0 info
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`qamap manifest explain . --base origin/main --head HEAD` makes a single branch debuggable:
|
|
89
|
+
|
|
90
|
+
```txt
|
|
91
|
+
QAMap Manifest Explain
|
|
92
|
+
Changed files: 1
|
|
93
|
+
Matches: 3
|
|
94
|
+
|
|
95
|
+
Matches:
|
|
96
|
+
- Campaign Application Complete (flow, high)
|
|
97
|
+
Why: Changed files match anchors for the Campaign Application Complete flow.
|
|
98
|
+
Evidence: .qamap/manifest.yaml > flows.campaign-application-complete.anchors
|
|
99
|
+
If wrong: update .qamap/manifest.yaml > flows.campaign-application-complete.anchors
|
|
100
|
+
Checks: Submit content URL successfully; Show validation error for invalid content URL
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
When that flow includes an entry route and checks, `qamap e2e draft` promotes it ahead of heuristic drafts:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
// Verification manifest evidence:
|
|
107
|
+
// - Flow: Campaign Application Complete (campaign-application-complete)
|
|
108
|
+
// - Entry route: /campaign/official/applicationComplete
|
|
109
|
+
// - Required checks:
|
|
110
|
+
// - [ ] Submit content URL successfully
|
|
111
|
+
// - [ ] Show validation error for invalid content URL
|
|
112
|
+
|
|
113
|
+
test("Campaign Application Complete", async ({ page }) => {
|
|
114
|
+
await test.step("Open route /campaign/official/applicationComplete.", async () => {
|
|
115
|
+
await page.goto("/campaign/official/applicationComplete");
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Web Core Flow
|
|
121
|
+
|
|
122
|
+
When a web app declares a core flow:
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
flows:
|
|
126
|
+
- id: checkout-purchase
|
|
127
|
+
name: Checkout purchase
|
|
128
|
+
priority: critical
|
|
129
|
+
files:
|
|
130
|
+
- src/pages/checkout/**
|
|
131
|
+
routes:
|
|
132
|
+
- /checkout
|
|
133
|
+
checks:
|
|
134
|
+
- Complete checkout with a valid payment method.
|
|
135
|
+
- Verify declined payment recovery.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`qamap e2e plan` should prefer the team-approved name:
|
|
139
|
+
|
|
140
|
+
```txt
|
|
141
|
+
Project: Web
|
|
142
|
+
Recommended runner: Playwright
|
|
143
|
+
Execution profile: high
|
|
144
|
+
Start command: pnpm run dev
|
|
145
|
+
Test command: pnpm run test:e2e
|
|
146
|
+
Base URL: http://127.0.0.1:4173
|
|
147
|
+
Matched core flows: 1
|
|
148
|
+
|
|
149
|
+
Flow: Checkout purchase UI smoke flow
|
|
150
|
+
Actor: Customer
|
|
151
|
+
Trigger: Open route /checkout.
|
|
152
|
+
Success signal: Verify declined payment recovery
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The Playwright draft should read like the product journey:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
test("Checkout purchase", async ({ page }) => {
|
|
159
|
+
await test.step("Open route /checkout.", async () => {
|
|
160
|
+
await page.goto("/checkout");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
await test.step("Complete checkout with a valid payment method.", async () => {
|
|
164
|
+
await page.getByTestId("checkout-submit").click();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
When QAMap can infer durable browser controls, the draft should prefer executable Playwright locators over placeholder text:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
await test.step("Fill profile email.", async () => {
|
|
173
|
+
// Step intent: Fill profile email.
|
|
174
|
+
await page.getByPlaceholder("Profile email").fill("qamap@example.com");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await test.step("Save settings.", async () => {
|
|
178
|
+
// Step intent: Save settings.
|
|
179
|
+
await page.getByRole("button", { name: "Save settings" }).click();
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The draft result should also explain whether the generated file passed static runner checks:
|
|
184
|
+
|
|
185
|
+
```txt
|
|
186
|
+
Draft self-check: pass
|
|
187
|
+
Command: pnpm run test:e2e
|
|
188
|
+
Summary: Playwright draft passed static runner checks.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Before writing files, `--dry-run` should expose the same readiness data with preview status:
|
|
192
|
+
|
|
193
|
+
```txt
|
|
194
|
+
Mode: dry run (no files were written)
|
|
195
|
+
Files: 0 created, 1 previewed, 0 skipped
|
|
196
|
+
|
|
197
|
+
- preview: `tests/e2e/checkout-purchase.spec.ts` (Checkout purchase)
|
|
198
|
+
- source: core-flow
|
|
199
|
+
- runnable status: near-runnable
|
|
200
|
+
- self-check: pass
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
For framework-native routing, QAMap should preserve the route a user can actually open rather than framework-only folder syntax. A Next App Router file such as `src/app/(shop)/products/[productId]/page.tsx` should become `/products/:productId`, and a concrete link such as `/products/demo-product` can seed the generated route params:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
const routeParams = {
|
|
207
|
+
productId: "demo-product",
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
await page.goto(`/products/${routeParams.productId}`);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
React Router config should work similarly when route objects expose path values:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
createBrowserRouter([
|
|
217
|
+
{ path: "/reports/:reportId", element: <ReportPage /> },
|
|
218
|
+
]);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Expo / React Native Flow
|
|
222
|
+
|
|
223
|
+
For an Expo or React Native change, QAMap should recommend Maestro and carry mobile selectors into the draft:
|
|
224
|
+
|
|
225
|
+
```txt
|
|
226
|
+
Project: Expo / React Native
|
|
227
|
+
Recommended runner: Maestro
|
|
228
|
+
|
|
229
|
+
Flow: Ink Drawing UI smoke flow
|
|
230
|
+
Actor: User
|
|
231
|
+
Trigger: Open the Ink Drawing screen.
|
|
232
|
+
Selectors: testID=ink-save-button, testID=record-mode-ink
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Example Maestro draft shape:
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
appId: ${APP_ID}
|
|
239
|
+
---
|
|
240
|
+
- launchApp
|
|
241
|
+
- tapOn: { id: "record-mode-ink" }
|
|
242
|
+
- tapOn: { id: "ink-save-button" }
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
When the changed file name exposes a narrower user action, the generated flow should use that action instead of stopping at a broad domain journey:
|
|
246
|
+
|
|
247
|
+
```txt
|
|
248
|
+
Changed file: src/features/offer/components/ContentUrlSubmitModal.tsx
|
|
249
|
+
Domain term: Offer
|
|
250
|
+
Generated scenario: Offer Content URL Submit
|
|
251
|
+
Generated draft path: .maestro/offer-content-url-submit.yaml
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The draft should then carry the same product-action wording into the runnable skeleton:
|
|
255
|
+
|
|
256
|
+
```yaml
|
|
257
|
+
# Flow: Offer Content URL Submit
|
|
258
|
+
# Domain scenario: Offer Content URL Submit
|
|
259
|
+
# Intent: Verify the changed "Content URL Submit" behavior inside Offer instead of stopping at a generic primary journey.
|
|
260
|
+
appId: ${APP_ID}
|
|
261
|
+
---
|
|
262
|
+
- launchApp
|
|
263
|
+
- tapOn: { id: "offer-content-url-submit" }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## API / Service Contract
|
|
267
|
+
|
|
268
|
+
For backend changes such as `src/v1/offer/utils.ts`, QAMap should not invent a browser journey. It should infer the domain word and stay contract-focused:
|
|
269
|
+
|
|
270
|
+
```txt
|
|
271
|
+
Project: API / service
|
|
272
|
+
Recommended runner: Manual
|
|
273
|
+
|
|
274
|
+
Flow: Offer API contract smoke checklist
|
|
275
|
+
Actor: API consumer or upstream service
|
|
276
|
+
Trigger: Call the endpoint, handler, or service path affected by src/v1/offer/utils.ts.
|
|
277
|
+
Success signal: the changed contract returns the expected status, response shape, auth behavior, and failure handling
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The manual draft should stay actionable:
|
|
281
|
+
|
|
282
|
+
```md
|
|
283
|
+
# Offer API contract
|
|
284
|
+
|
|
285
|
+
## Steps
|
|
286
|
+
|
|
287
|
+
- [ ] Call the changed endpoint, client, command, or handler with a valid request.
|
|
288
|
+
- [ ] Verify the response shape, status, and parsed data match the public contract.
|
|
289
|
+
- [ ] Verify invalid input, authorization failure, timeout, and server-error handling.
|
|
290
|
+
- [ ] Check backward compatibility for existing callers.
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## CLI Command Verification
|
|
294
|
+
|
|
295
|
+
For an npm package that exposes `package.json` bin entries, QAMap should not invent a UI journey. It should stay focused on the command contract users run in terminals, scripts, and CI:
|
|
296
|
+
|
|
297
|
+
```txt
|
|
298
|
+
Project: CLI
|
|
299
|
+
Recommended runner: Manual
|
|
300
|
+
|
|
301
|
+
Flow: CLI command verification checklist
|
|
302
|
+
Actor: CLI user or maintainer
|
|
303
|
+
Trigger: Run the CLI command path affected by src/cli.ts.
|
|
304
|
+
Success signal: the command returns the expected stdout, stderr, generated files, and exit code for valid and invalid inputs
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The manual draft should name concrete command evidence:
|
|
308
|
+
|
|
309
|
+
```md
|
|
310
|
+
# CLI command verification checklist
|
|
311
|
+
|
|
312
|
+
## Steps
|
|
313
|
+
|
|
314
|
+
- [ ] Build or install the package in a clean local environment.
|
|
315
|
+
- [ ] Run the changed command with a representative valid argument set.
|
|
316
|
+
- [ ] Verify stdout, stderr, generated files, and exit code match the intended behavior.
|
|
317
|
+
- [ ] Run one invalid, missing-argument, or unsupported-input path and verify the failure message and exit code.
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Test-Light Project
|
|
321
|
+
|
|
322
|
+
When a project has little or no E2E setup, QAMap should move the user toward a concrete starter draft, not just a task list:
|
|
323
|
+
|
|
324
|
+
```txt
|
|
325
|
+
## First E2E Draft Bootstrap
|
|
326
|
+
|
|
327
|
+
QAMap did not find committed test files for this target. The next step is to create the first runnable starter draft, not to stop at a checklist.
|
|
328
|
+
|
|
329
|
+
- Recommended first runner: Playwright
|
|
330
|
+
- Create command: `qamap e2e setup . --runner playwright`
|
|
331
|
+
- Install command: `pnpm add -D @playwright/test`
|
|
332
|
+
- Draft files QAMap can create:
|
|
333
|
+
- `playwright.config.ts`
|
|
334
|
+
- `tests/e2e/`
|
|
335
|
+
- `tests/e2e/checkout-primary-journey.spec.ts`
|
|
336
|
+
- Files to update: `package.json`
|
|
337
|
+
|
|
338
|
+
Bootstrap summary:
|
|
339
|
+
4 required bootstrap steps must be resolved before generated E2E drafts should be treated as regression coverage.
|
|
340
|
+
|
|
341
|
+
Required:
|
|
342
|
+
- Configure Playwright before making drafts required
|
|
343
|
+
- Create the first changed-flow E2E draft
|
|
344
|
+
- Add deterministic fixture or mock responses
|
|
345
|
+
- Add stable selectors for changed UI surfaces
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Draft action items should make the next developer action explicit:
|
|
349
|
+
|
|
350
|
+
```txt
|
|
351
|
+
Action summary:
|
|
352
|
+
- readiness score: 64/100 (needs-work)
|
|
353
|
+
- runnable status: near-runnable
|
|
354
|
+
- self-check: pass or warning based on generated starter code and execution profile
|
|
355
|
+
- top blocker: No Playwright config file was detected.
|
|
356
|
+
- required runner: Create `playwright.config.ts` with `testDir`, `use.baseURL`, and `webServer.command` when QAMap inferred the dev URL from scripts.
|
|
357
|
+
- required fixture: Add deterministic fixture or mock data
|
|
358
|
+
- required validation: Resolve missing validation evidence
|
|
359
|
+
- recommended manifest: Promote durable product language
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## API-Dependent Client Flow
|
|
363
|
+
|
|
364
|
+
When a client-side change calls an API path but the branch does not include backend or fixture evidence, QAMap should name that as a readiness gap and still give the tester a concrete mock slot:
|
|
365
|
+
|
|
366
|
+
If reusable repo-local evidence already exists, the PR QA output should point at it instead of only saying "add a fixture":
|
|
367
|
+
|
|
368
|
+
```txt
|
|
369
|
+
Missing evidence before trusting this PR
|
|
370
|
+
- [recommended] fixture: Confirm fixture coverage - Reuse or extend existing fixture/mock evidence for this flow: src/services/devSeedService.ts, src/services/reportMockService.ts.
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
const mockApiResponses = {
|
|
375
|
+
"**/api/orders/fixture-order-id": {
|
|
376
|
+
status: 200,
|
|
377
|
+
body: {
|
|
378
|
+
ok: true,
|
|
379
|
+
source: "qamap-draft",
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
// Replace sample responses with deterministic fixtures from the target domain before promoting this draft.
|
|
385
|
+
for (const [urlPattern, response] of Object.entries(mockApiResponses)) {
|
|
386
|
+
await page.route(urlPattern, async (route) => {
|
|
387
|
+
await route.fulfill({
|
|
388
|
+
status: response.status,
|
|
389
|
+
contentType: "application/json",
|
|
390
|
+
body: JSON.stringify(response.body),
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
This is useful for PRs where the UI can be built against mockdata before the server implementation is available. The generated file should still report fixture readiness as missing or partial until a reviewer replaces the sample response with domain-correct success, empty, unauthorized, timeout, or server-error fixtures.
|
|
397
|
+
|
|
398
|
+
When the PR changes the endpoint implementation itself, QAMap should not hide that contract behind a synthetic response. In that case the Playwright draft records the endpoint as an observed API pattern instead of adding a response mock:
|
|
399
|
+
|
|
400
|
+
```ts
|
|
401
|
+
const changedApiEndpointPatterns = [
|
|
402
|
+
"**/api/checkout",
|
|
403
|
+
];
|
|
404
|
+
const observedChangedApiResponses: Array<{ url: string; status: number }> = [];
|
|
405
|
+
page.on("response", (response) => {
|
|
406
|
+
if (changedApiEndpointPatterns.some((pattern) => response.url().includes(pattern.replace(/^\*\*/, "")))) {
|
|
407
|
+
observedChangedApiResponses.push({ url: response.url(), status: response.status() });
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Monorepo Package
|
|
413
|
+
|
|
414
|
+
When run at the workspace root, QAMap should identify changed package targets before asking the maintainer to choose a final runner:
|
|
415
|
+
|
|
416
|
+
```sh
|
|
417
|
+
qamap e2e plan . --base main --head HEAD
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Expected root-level behavior:
|
|
421
|
+
|
|
422
|
+
```txt
|
|
423
|
+
Changed App/Package Targets
|
|
424
|
+
|
|
425
|
+
| Target | Package | Project | Runner | Scoped Command |
|
|
426
|
+
| services/offer | offer | Web | Playwright | qamap e2e plan services/offer --workspace-root . --base main --head HEAD |
|
|
427
|
+
| apps/mobile | @acme/mobile | Expo / React Native | Maestro | qamap e2e plan apps/mobile --workspace-root . --base main --head HEAD |
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
For package scans, QAMap should use workspace policy without leaking workspace-root paths into package-local drafts:
|
|
431
|
+
|
|
432
|
+
```sh
|
|
433
|
+
qamap e2e plan services/offer --workspace-root . --base main --head HEAD
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Expected behavior:
|
|
437
|
+
|
|
438
|
+
```txt
|
|
439
|
+
Workspace root: .
|
|
440
|
+
Package root: services/offer
|
|
441
|
+
Matched core flow: Offer submit
|
|
442
|
+
Changed files: src/features/offer/submit.ts
|
|
443
|
+
Generated draft path: docs/e2e/offer-submit.md
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
The draft should mention package-local files:
|
|
447
|
+
|
|
448
|
+
```md
|
|
449
|
+
Related Changed Files
|
|
450
|
+
|
|
451
|
+
- `src/features/offer/submit.ts`
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## What Good Output Feels Like
|
|
455
|
+
|
|
456
|
+
Good QAMap output should answer these questions quickly:
|
|
457
|
+
|
|
458
|
+
- What behavior did this branch probably change?
|
|
459
|
+
- What does the team call that behavior?
|
|
460
|
+
- Who or what exercises it?
|
|
461
|
+
- Which runner or checklist is the right first shape?
|
|
462
|
+
- Which setup, selector, fixture, or validation gap blocks this from becoming real regression coverage?
|
|
463
|
+
|
|
464
|
+
If the output only says "make an E2E test" without these answers, it is not ready for the current release bar.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Agent Ecosystem Coverage
|
|
2
|
+
|
|
3
|
+
AI coding agents now read repository instructions, connect to MCP servers, run tool hooks, and prepare pull requests. QAMap tracks the repository files that shape those behaviors without executing project code.
|
|
4
|
+
|
|
5
|
+
## Instruction Surfaces
|
|
6
|
+
|
|
7
|
+
QAMap treats these files as agent instruction surfaces:
|
|
8
|
+
|
|
9
|
+
| Ecosystem | Files |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Shared / Codex-style | `AGENTS.md`, `AGENTS.override.md` |
|
|
12
|
+
| Claude Code | `CLAUDE.md`, `.claude/CLAUDE.md`, `.claude/rules/*.md` |
|
|
13
|
+
| Cursor | `.cursorrules`, `.cursor/rules/*.md`, `.cursor/rules/*.mdc` |
|
|
14
|
+
| GitHub Copilot | `.github/copilot-instructions.md`, `.github/instructions/*.instructions.md` |
|
|
15
|
+
| Gemini CLI | `GEMINI.md` |
|
|
16
|
+
|
|
17
|
+
These files are scanned for missing guidance, conflicting guidance, and suspicious instruction text.
|
|
18
|
+
|
|
19
|
+
## Tool And Settings Surfaces
|
|
20
|
+
|
|
21
|
+
QAMap statically inspects committed MCP and agent settings files:
|
|
22
|
+
|
|
23
|
+
| Surface | Files | Checks |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| MCP config | `.mcp.json`, `mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`, `claude_desktop_config.json` | unreadable JSON, risky commands, committed secret-like env values |
|
|
26
|
+
| Agent settings | `.claude/settings.json`, `.claude/settings.local.json`, `.gemini/settings.json` | MCP servers, risky hooks, broad shell permissions |
|
|
27
|
+
|
|
28
|
+
The scanner does not run MCP servers, hooks, package scripts, or project code.
|
|
29
|
+
|
|
30
|
+
## Source Signals
|
|
31
|
+
|
|
32
|
+
These references guide the current coverage:
|
|
33
|
+
|
|
34
|
+
- [OpenAI Codex AGENTS.md](https://developers.openai.com/codex/cloud/agents-md/) and the community [AGENTS.md](https://agents.md/) convention.
|
|
35
|
+
- [Claude Code memory](https://docs.anthropic.com/en/docs/claude-code/memory), [settings](https://docs.anthropic.com/en/docs/claude-code/settings), and [hooks](https://docs.anthropic.com/en/docs/claude-code/hooks).
|
|
36
|
+
- [GitHub Copilot custom instructions](https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot).
|
|
37
|
+
- [Cursor rules](https://cursor.com/docs/rules) and [Cursor MCP](https://cursor.com/docs/mcp).
|
|
38
|
+
- [Gemini CLI configuration](https://google-gemini.github.io/gemini-cli/docs/get-started/configuration.html) and [Gemini MCP servers](https://google-gemini.github.io/gemini-cli/docs/tools/mcp-server.html).
|
|
39
|
+
- [Model Context Protocol security best practices](https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices).
|
|
40
|
+
|
|
41
|
+
QAMap should keep this list practical rather than exhaustive: add a surface when it is common enough that maintainers would reasonably expect a repo preflight check to notice it.
|
package/docs/eval.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# QAMap Eval
|
|
2
|
+
|
|
3
|
+
`qamap eval` scores whether a branch is ready for human review in an AI-assisted workflow.
|
|
4
|
+
|
|
5
|
+
It does not try to prove that the code is correct. Instead, it checks whether reviewers have enough evidence to trust, challenge, and verify the change without absorbing unnecessary cognitive load.
|
|
6
|
+
|
|
7
|
+
For a complete PR-facing report that also includes QAMap review findings and suggested domain tests, use `qamap verify`.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
qamap verify . --base origin/main --head HEAD --pr-body-file pr-body.md
|
|
13
|
+
qamap eval . --base origin/main --head HEAD --format markdown
|
|
14
|
+
qamap eval . --base origin/main --head HEAD --pr-body-file pr-body.md
|
|
15
|
+
qamap eval services/offer --workspace-root . --base origin/main --head HEAD --include-working-tree
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The GitHub Action can append the same report to the PR comment. On pull request events it reads the PR body from `GITHUB_EVENT_PATH`.
|
|
19
|
+
|
|
20
|
+
## Gates
|
|
21
|
+
|
|
22
|
+
Each gate is scored from `0` to `2`.
|
|
23
|
+
|
|
24
|
+
| Gate | What it checks |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| Validation commands | The project exposes a real test command and supporting commands such as typecheck, lint, build, e2e, tox, Ruff, mypy, `go vet`, clippy, or Maven verify. |
|
|
27
|
+
| Changed test coverage | Source changes are paired with changed test files, or at least a runnable test command exists. |
|
|
28
|
+
| Intent capture | The PR body, decision docs, or PR template capture the problem, rationale, context, alternatives, or tradeoffs. |
|
|
29
|
+
| Risk explanation | Risky surfaces such as config, workflows, API contracts, auth, billing, migrations, and env files include risk or rollback context. |
|
|
30
|
+
| Domain test plan | Changed files can be mapped to focused domain verification scenarios. |
|
|
31
|
+
| Review size | The branch is small enough to review without unnecessary verification tax. |
|
|
32
|
+
|
|
33
|
+
`validationCommands` in `qamap.config.json` can supply commands for custom stacks or monorepos when standard project files are not enough.
|
|
34
|
+
|
|
35
|
+
## Ratings
|
|
36
|
+
|
|
37
|
+
| Rating | Meaning |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `strong` | The branch has clear verification evidence and should be easy to review. |
|
|
40
|
+
| `ready` | The branch is probably reviewable, with some follow-up still useful. |
|
|
41
|
+
| `needs-work` | Reviewers should ask for more tests, context, risk notes, or a smaller diff. |
|
|
42
|
+
| `high-risk` | The branch is expensive or risky to verify; add evidence before relying on it. |
|
|
43
|
+
|
|
44
|
+
## Why This Exists
|
|
45
|
+
|
|
46
|
+
AI-assisted code often looks plausible before it is truly understood. That creates verification tax, cognitive debt, and intent debt:
|
|
47
|
+
|
|
48
|
+
- verification tax: humans must spend extra time proving the generated result is safe
|
|
49
|
+
- cognitive debt: reviewers receive more code than they can meaningfully understand
|
|
50
|
+
- intent debt: the reason for a change disappears into a prompt or chat session
|
|
51
|
+
|
|
52
|
+
`qamap eval` turns those risks into a small, static, explainable checklist that can run locally or in CI.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# GitHub Action
|
|
2
|
+
|
|
3
|
+
QAMap ships a composite GitHub Action that can run `scan` or branch-aware `review` inside pull request workflows.
|
|
4
|
+
|
|
5
|
+
The action writes:
|
|
6
|
+
|
|
7
|
+
- a Markdown report file
|
|
8
|
+
- a sticky PR comment body
|
|
9
|
+
- an optional suggested domain test plan
|
|
10
|
+
- an optional verification readiness evaluation
|
|
11
|
+
- GitHub workflow annotations
|
|
12
|
+
- a GitHub step summary
|
|
13
|
+
|
|
14
|
+
## Pull Request Review
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
name: QAMap
|
|
18
|
+
|
|
19
|
+
on:
|
|
20
|
+
pull_request:
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
pull-requests: write
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
qamap:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v7
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 0
|
|
33
|
+
- uses: IvoryCanvas/qamap@main
|
|
34
|
+
with:
|
|
35
|
+
mode: review
|
|
36
|
+
base: ${{ github.event.pull_request.base.sha }}
|
|
37
|
+
head: HEAD
|
|
38
|
+
fail-on: high
|
|
39
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Use `fetch-depth: 0` so QAMap can compare the pull request branch with the base ref.
|
|
43
|
+
For production workflows, pin to a version tag such as `IvoryCanvas/qamap@v0.3.0` after that tag is published. Use `@main` only when intentionally testing unreleased behavior.
|
|
44
|
+
|
|
45
|
+
## Monorepo Package
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
- uses: IvoryCanvas/qamap@main
|
|
49
|
+
with:
|
|
50
|
+
mode: review
|
|
51
|
+
path: services/offer
|
|
52
|
+
workspace-root: .
|
|
53
|
+
base: ${{ github.event.pull_request.base.sha }}
|
|
54
|
+
head: HEAD
|
|
55
|
+
fail-on: high
|
|
56
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Inputs
|
|
60
|
+
|
|
61
|
+
| Input | Default | Description |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `mode` | `auto` | `auto`, `scan`, or `review`. `auto` uses review mode on pull request events. |
|
|
64
|
+
| `path` | `.` | Repository path to scan. |
|
|
65
|
+
| `workspace-root` | | Optional monorepo workspace root. |
|
|
66
|
+
| `base` | | Base ref or SHA for review mode. |
|
|
67
|
+
| `head` | `HEAD` | Head ref or SHA for review mode. |
|
|
68
|
+
| `config` | | Optional QAMap config path. |
|
|
69
|
+
| `max-files` | | Optional maximum file count. |
|
|
70
|
+
| `fail-on` | `high` | Severity threshold that fails the action. |
|
|
71
|
+
| `report-file` | `qamap-report.md` | Markdown report output path. |
|
|
72
|
+
| `comment-file` | `qamap-pr-comment.md` | PR comment body output path. |
|
|
73
|
+
| `test-plan` | `true` | Append suggested domain tests for changed files. |
|
|
74
|
+
| `test-plan-file` | `qamap-test-plan.md` | Markdown test plan output path. |
|
|
75
|
+
| `eval` | `true` | Append a verification readiness evaluation. |
|
|
76
|
+
| `eval-file` | `qamap-eval.md` | Markdown evaluation output path. |
|
|
77
|
+
| `annotations` | `true` | Emit GitHub workflow annotations. |
|
|
78
|
+
| `step-summary` | `true` | Append the report to the GitHub step summary. |
|
|
79
|
+
| `comment` | `true` | Create or update a sticky pull request comment. |
|
|
80
|
+
| `github-token` | | Token for PR comments. Required when `comment` is `true`. |
|
|
81
|
+
|
|
82
|
+
## Notes
|
|
83
|
+
|
|
84
|
+
- Set `pull-requests: write` only when PR comments are enabled.
|
|
85
|
+
- Set `comment: false` for advisory runs that should only use annotations and step summaries.
|
|
86
|
+
- Set `test-plan: false` when the PR comment should contain only QAMap findings.
|
|
87
|
+
- Set `eval: false` when the PR comment should not include readiness scoring.
|
|
88
|
+
- Pass `github-token: ${{ secrets.GITHUB_TOKEN }}` when `comment` is enabled.
|
|
89
|
+
- QAMap still does not execute scanned project code; the action only installs and builds QAMap itself before scanning the checked-out repository.
|