@ivorycanvas/qamap 0.4.0 → 0.4.1

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.
@@ -330,30 +330,17 @@ The manual draft should name concrete command evidence:
330
330
 
331
331
  ## Test-Light Project
332
332
 
333
- When a project has little or no E2E setup, QAMap should move the user toward a concrete starter draft, not just a task list:
333
+ When a project has little or no E2E setup, `qamap qa` still returns the same runner-independent QA judgment. Runner setup remains an explicit team choice:
334
334
 
335
335
  ```txt
336
- ## First E2E Draft Bootstrap
337
-
338
- 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.
339
-
340
- - Recommended first runner: Playwright
341
- - Create command: `qamap e2e setup . --runner playwright`
342
- - Install command: `pnpm add -D @playwright/test`
343
- - Draft files QAMap can create:
344
- - `playwright.config.ts`
345
- - `tests/e2e/`
346
- - `tests/e2e/checkout-primary-journey.spec.ts`
347
- - Files to update: `package.json`
348
-
349
- Bootstrap summary:
350
- 4 required bootstrap steps must be resolved before generated E2E drafts should be treated as regression coverage.
351
-
352
- Required:
353
- - Configure Playwright before making drafts required
354
- - Create the first changed-flow E2E draft
355
- - Add deterministic fixture or mock responses
356
- - Add stable selectors for changed UI surfaces
336
+ ## Optional Automation
337
+
338
+ The QA judgment above does not require adopting this adapter.
339
+
340
+ - Adapter candidate: Playwright
341
+ - Draft target: `tests/e2e/checkout-primary-journey.spec.ts`
342
+ - Preview or create a draft: `qamap e2e draft . --base main --head HEAD`
343
+ - If the team accepts this adapter, inspect its setup proposal: `qamap e2e setup . --runner playwright`
357
344
  ```
358
345
 
359
346
  Draft action items should make the next developer action explicit:
@@ -15,6 +15,7 @@ src/features/checkout/submitCheckout.ts
15
15
  The reviewer wants to know:
16
16
 
17
17
  - Which user flow is affected?
18
+ - Which diff hunk caused each QA scenario to be proposed?
18
19
  - Should this become a Playwright test, a manual checklist, or only a review note?
19
20
  - What blocks the generated draft from being trusted as regression coverage?
20
21
 
@@ -26,9 +27,9 @@ Run QAMap on the branch:
26
27
  pnpm dlx @ivorycanvas/qamap qa . --base origin/main --head HEAD
27
28
  ```
28
29
 
29
- `qa` is important for first contact. It lets maintainers preview the PR comment draft, affected flow, draft path, readiness, and blockers without writing files.
30
+ `qa` is important for first contact. It lets maintainers review change intent, behavior lifecycle, scenario confidence, exact diff sources, and a PR checklist without writing files or selecting a test runner.
30
31
 
31
- When the team wants actual draft files:
32
+ After the team accepts a scenario and wants executable coverage:
32
33
 
33
34
  ```sh
34
35
  pnpm dlx @ivorycanvas/qamap e2e draft . --base origin/main --head HEAD --dry-run
@@ -148,11 +149,12 @@ Output
148
149
  - commit-backed change intent and confidence
149
150
  - ordered behavior lifecycle
150
151
  - primary, failure, boundary, and state-transition QA scenarios
152
+ - scenario-level confidence, review status, and exact commit or head-side `file:line` sources
151
153
  - changed domain language
152
154
  - candidate user flow
153
155
  - manifest evidence when a repo-local flow/check matches
154
- - automation adapter selected after QA design
155
- - draft file path
156
+ - optional automation adapter selected after QA design
157
+ - optional draft file path
156
158
  - flow language brief
157
159
  - runnable status
158
160
  - self-check status
@@ -160,7 +162,7 @@ Output
160
162
  - blockers that explain why a draft is not ready yet
161
163
  ```
162
164
 
163
- 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
+ The result should not stop at "selector needed" or "fixture needed." A useful QAMap report should say which behavior changed, which scenarios follow, which exact hunk supports each scenario, what remains uncertain, and where to update the manifest if the recommendation is wrong. Automation comes after that review.
164
166
 
165
167
  ## Markdown Preview
166
168
 
@@ -168,29 +170,32 @@ The result should not stop at "selector needed" or "fixture needed." A useful QA
168
170
  # QAMap QA Draft
169
171
 
170
172
  At a Glance
171
- - Change intent: Submit checkout and persist the confirmed order [high]
172
- - Behavior lifecycle: trigger: submit checkout -> side-effect: create order -> observable-outcome: show confirmation
173
+ - Change intent: Submit notification preferences and show the saved state [high]
174
+ - Behavior lifecycle: trigger -> state-change -> side-effect -> observable-outcome
173
175
 
174
176
  Summary
175
177
  - Project: Web
176
- - Automation adapter: Playwright
177
178
  - Manifest: .qamap/manifest.yaml
178
- - Stage: almost runnable (3 of 4)
179
179
 
180
- PR Comment Draft
181
- - Affected flow: Checkout purchase
182
- - Suggested draft: tests/e2e/checkout-purchase.spec.ts
183
- - User journey: Customer -> Open route /checkout -> Complete checkout with realistic form data
184
- - Success signal: confirmation state is visible after submit
180
+ QA scenarios
181
+ - [critical] changed preference lifecycle [high]
182
+ - Source: src/pages/preferences.tsx:17, symbol onClick
183
+ - Assert: the saved state is visible
184
+ - [recommended] failure, timeout, and retry handling [medium; review required]
185
+ - Source: src/pages/preferences.tsx:7, symbol fetch
186
+ - Assert: retries do not duplicate requests or side effects
185
187
 
186
- Missing evidence before trusting this PR
187
- - [required] fixture: Add deterministic payment/customer fixture data.
188
- - [recommended] selector: Confirm stable selectors for changed checkout controls.
188
+ Evidence gaps in this QA proposal
189
+ - [required] fixture: Add deterministic response data for /api/preferences.
189
190
 
190
191
  PR checklist
191
- - [ ] Review tests/e2e/checkout-purchase.spec.ts.
192
- - [ ] Confirm success and failed-response assertions.
192
+ - [ ] Review each QA scenario and its diff source.
193
+ - [ ] Confirm success and failed-response assertions for /api/preferences.
193
194
  - [ ] Run pnpm run test:e2e.
195
+
196
+ Optional automation
197
+ - Adapter candidate: Playwright
198
+ - qamap e2e draft . --base origin/main --head HEAD
194
199
  ```
195
200
 
196
201
  ## Draft Shape
@@ -1,5 +1,22 @@
1
1
  # Release Validation
2
2
 
3
+ ## 0.4.1 - 2026-07-13
4
+
5
+ Validated as an evidence-first QA patch. A proposed scenario now exposes the commit or exact base/head diff file, line, symbol, hunk, and direct/supporting/contextual relation that caused it. Removed guards remain visible as base-side critical evidence, contextual-only scenarios cannot become critical, and runner adoption remains an explicit step after review:
6
+
7
+ | Gate | Current result |
8
+ | --- | --- |
9
+ | `pnpm release:check` | Passed end to end |
10
+ | `pnpm test` | 146/146 passing |
11
+ | `pnpm scan` | 0 findings |
12
+ | `pnpm bench:ci` | 12/12 synthetic PR targets pass; web and mobile lifecycle scenarios both retain 4/4 exact diff traces |
13
+ | Coverage | Lines 87.49%, branches 83.99%, functions 95.20% |
14
+ | Agent payload | Evidence-rich lifecycle fixtures are 5,288 and 5,659 bytes; a large real mobile branch compacts from 10,873 to 8,111 bytes while disclosing omitted counts |
15
+ | Package preview | `pnpm pack --dry-run` and `npm publish --dry-run --access public` pass for `@ivorycanvas/qamap@0.4.1`; 129 files, 825.5 kB packed |
16
+ | Read-only repository smoke | A large mobile branch and a web workspace branch were rechecked after base-side evidence and output compaction; both target worktrees remained unchanged |
17
+
18
+ The large mobile branch retained zero untraced critical scenarios. A removed release guard was tied to its exact base-side line and translated into local/development/QA/production configuration checks rather than an unrelated user-authorization scenario. Its agent payload reports 44 total intents, 2 retained intents, and 42 omitted intents within 8,111 bytes. The release-shaped web branch still had no behavior-bearing commit intent and therefore emitted four broader review-only flows with zero critical scenarios; this remains an explicit precision limit rather than promoted confidence.
19
+
3
20
  ## 0.4.0 - 2026-07-12
4
21
 
5
22
  Validated as the first intent-first QA design release. The release contract starts with behavior-bearing commits and diff evidence, reconstructs an ordered behavior lifecycle, proposes runner-independent QA scenarios, and only then compiles an optional automation draft:
package/docs/releasing.md CHANGED
@@ -20,6 +20,7 @@ Version `1.0.0` requires a stable public contract and external adoption, not imp
20
20
  Before publishing, confirm:
21
21
 
22
22
  - `package.json` version matches the intended npm version.
23
+ - The canonical release identifier is `vX.Y.Z` (for example, `v0.4.0`). The Git tag and GitHub Release title must match this identifier exactly.
23
24
  - `CHANGELOG.md` has a dated section for the version being published.
24
25
  - `README.md`, [adoption](adoption.md), [E2E examples](e2e-output-examples.md), and [release validation](release-validation.md) describe the current CLI behavior.
25
26
  - `pnpm run release:check` passes from a clean checkout.
@@ -93,11 +94,20 @@ Use a fresh shell or temporary directory for the smoke check when possible.
93
94
  After npm publish succeeds:
94
95
 
95
96
  ```sh
96
- git tag "v$VERSION"
97
- git push origin "v$VERSION"
97
+ TAG="v$VERSION"
98
+ git tag -a "$TAG" -m "$TAG"
99
+ git push origin "$TAG"
98
100
  ```
99
101
 
100
- Create a GitHub Release for the tag with:
102
+ Create a GitHub Release whose display title is exactly the tag:
103
+
104
+ ```sh
105
+ gh release create "$TAG" --title "$TAG" --notes-file <release-notes.md>
106
+ ```
107
+
108
+ Do not prefix the title with `QAMap` or `CodeWard`, and do not add a descriptive subtitle. Product positioning and highlights belong in the release notes body so the release list remains consistently sortable as `vX.Y.Z`.
109
+
110
+ The release notes body should contain:
101
111
 
102
112
  - a concise release summary
103
113
  - the current `CHANGELOG.md` section
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ivorycanvas/qamap",
3
- "version": "0.4.0",
4
- "description": "Local zero-LLM PR QA designer that turns commit intent and diffs into behavior lifecycles, QA scenarios, and deterministic automation drafts.",
3
+ "version": "0.4.1",
4
+ "description": "Local zero-LLM PR QA designer that maps commit intent and diffs to traceable behavior lifecycles, QA scenarios, and optional automation drafts.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.32.1",
7
7
  "bin": {
@@ -5,6 +5,25 @@
5
5
  "description": "The single-line JSON object printed by `qamap qa --format agent`. Within schema version 1, fields are only ever added — existing fields are never removed or retyped. A breaking change bumps schema.version to 2.",
6
6
  "type": "object",
7
7
  "additionalProperties": true,
8
+ "definitions": {
9
+ "evidenceSource": {
10
+ "type": "object",
11
+ "required": ["kind", "reason"],
12
+ "properties": {
13
+ "kind": { "type": "string", "enum": ["commit", "diff", "source"] },
14
+ "reason": { "type": "string" },
15
+ "commit": { "type": "string" },
16
+ "file": { "type": "string" },
17
+ "previousFile": { "type": "string" },
18
+ "symbol": { "type": "string" },
19
+ "relation": { "type": "string", "enum": ["direct", "supporting", "contextual"] },
20
+ "side": { "type": "string", "enum": ["base", "head"] },
21
+ "startLine": { "type": "integer", "minimum": 0 },
22
+ "endLine": { "type": "integer", "minimum": 0 },
23
+ "hunk": { "type": "string" }
24
+ }
25
+ }
26
+ },
8
27
  "required": [
9
28
  "schema",
10
29
  "base",
@@ -82,6 +101,17 @@
82
101
  "confidence": { "type": "string", "enum": ["low", "medium", "high"] },
83
102
  "reviewRequired": { "type": "boolean" },
84
103
  "evidence": { "type": "array", "items": { "type": "string" } },
104
+ "sources": {
105
+ "type": "array",
106
+ "items": { "$ref": "#/definitions/evidenceSource" },
107
+ "description": "Structured commit and diff locations behind the intent (capped)."
108
+ },
109
+ "scenarioCount": { "type": "integer", "minimum": 0 },
110
+ "omittedScenarioCount": {
111
+ "type": "integer",
112
+ "minimum": 0,
113
+ "description": "Number of lower-ranked scenarios omitted from the compact payload. Use the human or JSON format when non-zero."
114
+ },
85
115
  "lifecycle": {
86
116
  "type": "array",
87
117
  "items": {
@@ -105,6 +135,13 @@
105
135
  "priority": { "type": "string", "enum": ["critical", "recommended"] },
106
136
  "kind": { "type": "string", "enum": ["primary", "failure", "boundary", "state-transition"] },
107
137
  "title": { "type": "string" },
138
+ "confidence": { "type": "string", "enum": ["low", "medium", "high"] },
139
+ "reviewRequired": { "type": "boolean" },
140
+ "sources": {
141
+ "type": "array",
142
+ "items": { "$ref": "#/definitions/evidenceSource" },
143
+ "description": "The strongest diff or commit locations that caused this scenario to be proposed (capped)."
144
+ },
108
145
  "assertions": { "type": "array", "items": { "type": "string" } }
109
146
  }
110
147
  }
@@ -112,9 +149,31 @@
112
149
  }
113
150
  }
114
151
  },
152
+ "intentCount": {
153
+ "type": "integer",
154
+ "minimum": 0,
155
+ "description": "Total inferred intents before compact output capping."
156
+ },
157
+ "omittedIntentCount": {
158
+ "type": "integer",
159
+ "minimum": 0,
160
+ "description": "Intents omitted from the compact payload."
161
+ },
115
162
  "firstDraftCommand": {
116
163
  "type": "string",
117
- "description": "One command that creates the first E2E draft. Only present when the repository has no test suite and the diff reaches a product journey."
164
+ "description": "Deprecated v1 field retained for compatibility. New output uses the opt-in automation object instead of promoting runner setup as the default QA action."
165
+ },
166
+ "automation": {
167
+ "type": "object",
168
+ "description": "Optional adapter handoff after a reviewer accepts the QA scenario. It is not required to use the QA judgment.",
169
+ "required": ["optIn", "adapter", "setupStatus", "draftCommand"],
170
+ "properties": {
171
+ "optIn": { "const": true },
172
+ "adapter": { "type": "string", "enum": ["maestro", "playwright", "manual"] },
173
+ "setupStatus": { "type": "string", "enum": ["ready", "proposed", "not-applicable"] },
174
+ "draftCommand": { "type": "string" },
175
+ "setupCommand": { "type": "string" }
176
+ }
118
177
  },
119
178
  "flows": {
120
179
  "type": "array",
@@ -168,6 +227,25 @@
168
227
  }
169
228
  }
170
229
  },
230
+ "flowCount": {
231
+ "type": "integer",
232
+ "minimum": 0,
233
+ "description": "Total affected flows before compact output capping."
234
+ },
235
+ "omittedFlowCount": {
236
+ "type": "integer",
237
+ "minimum": 0,
238
+ "description": "Flows omitted from the compact payload."
239
+ },
240
+ "compaction": {
241
+ "type": "object",
242
+ "description": "Present when QAMap reduced lower-priority detail to keep the complete line at or below 8KB.",
243
+ "properties": {
244
+ "maxBytes": { "type": "integer", "minimum": 1 },
245
+ "originalBytes": { "type": "integer", "minimum": 1 },
246
+ "emergency": { "type": "boolean" }
247
+ }
248
+ },
171
249
  "requiredEvidence": {
172
250
  "type": "array",
173
251
  "description": "QA evidence the change still needs before merge (required priority only, capped at 8).",
@@ -188,7 +266,7 @@
188
266
  },
189
267
  "requiredBootstrap": {
190
268
  "type": "array",
191
- "description": "Setup steps that must happen before drafts can be treated as regression coverage (capped at 3).",
269
+ "description": "Non-runner repository context steps (capped at 3). Runner adoption is exposed separately under the opt-in automation object.",
192
270
  "items": {
193
271
  "type": "object",
194
272
  "required": ["title", "action"],
@@ -96,6 +96,38 @@
96
96
  "file": {
97
97
  "type": "string",
98
98
  "minLength": 1
99
+ },
100
+ "previousFile": {
101
+ "type": "string",
102
+ "minLength": 1
103
+ },
104
+ "symbol": {
105
+ "type": "string",
106
+ "minLength": 1
107
+ },
108
+ "commit": {
109
+ "type": "string",
110
+ "minLength": 1
111
+ },
112
+ "relation": {
113
+ "type": "string",
114
+ "enum": ["direct", "supporting", "contextual"]
115
+ },
116
+ "side": {
117
+ "type": "string",
118
+ "enum": ["base", "head"]
119
+ },
120
+ "startLine": {
121
+ "type": "integer",
122
+ "minimum": 0
123
+ },
124
+ "endLine": {
125
+ "type": "integer",
126
+ "minimum": 0
127
+ },
128
+ "hunkHeader": {
129
+ "type": "string",
130
+ "minLength": 1
99
131
  }
100
132
  }
101
133
  },
@@ -34,28 +34,28 @@ Use QAMap as a final local QA pass before presenting a pull request for human re
34
34
  ```
35
35
 
36
36
  4. Read and verify intent before generating code. In agent format:
37
- - `intents[]` — commit/diff evidence, confidence, `reviewRequired`, ordered lifecycle, and primary/failure/boundary/state-transition scenarios.
37
+ - `intents[]` — commit/diff evidence, confidence, `reviewRequired`, ordered lifecycle, and primary/failure/boundary/state-transition scenarios. Read each scenario's structured `sources` before accepting it; a diff source carries `file`, head-side line numbers, symbol, and hunk.
38
38
  - If `reviewRequired` is true or the lifecycle conflicts with the PR, ask a human to confirm the intended behavior before promoting a draft.
39
39
  - `flows[]` — affected flows with `draft` path, `runnable` status, entry route, capped steps, and selectors.
40
40
  - `requiredEvidence[]` — evidence that must exist before the PR can be trusted; `recommendedEvidenceCount` for the rest.
41
- - `requiredBootstrap[]` — setup steps that block trusting generated drafts.
41
+ - `requiredBootstrap[]` — non-runner repository context that still needs clarification.
42
+ - `automation` — an optional adapter handoff. It is not required to use the QA judgment.
42
43
  - `prChecklist[]` and `commands[]` — checklist lines and validation commands for the handoff.
43
44
 
44
- 5. If the intent is credible and QAMap prints `First E2E Draft Bootstrap`, create the starter draft instead of stopping at broad QA notes:
45
+ 5. Only after a human or team accepts the scenario and automation adapter, create or preview executable coverage:
45
46
 
46
47
  ```sh
47
- pnpm exec qamap e2e setup . --runner <runner>
48
+ pnpm exec qamap e2e draft . --base <base> --head HEAD
48
49
  ```
49
50
 
50
- Use the exact create command from the output when it differs.
51
- `firstDraftCommand` is present only when the repo has no test suite; run it to create the first starter draft. In markdown format, start from `At a Glance` and `Change Intent Evidence`, then read the PR comment, missing evidence, and checklist sections.
51
+ If the selected adapter is absent, inspect and explicitly accept the `automation.setupCommand` proposal. Never install a runner merely because QAMap detected a web or mobile surface.
52
52
  6. Include the useful parts in the PR body, review note, or handoff summary.
53
53
 
54
54
  ## Output Rules
55
55
 
56
56
  - Treat QAMap output as QA planning evidence, not proof that browser, device, API, or manual QA passed.
57
- - Preserve change intent, confidence, lifecycle, QA scenarios, affected flow, suggested E2E/checklist path, missing evidence, and validation command in the handoff.
58
- - Prefer creating the suggested starter E2E draft over only reporting that a draft is needed.
57
+ - Preserve change intent, confidence, lifecycle, QA scenarios, their strongest file/line sources, affected flow, missing evidence, and validation command in the handoff.
58
+ - Keep automation optional until the scenario and its evidence have been reviewed.
59
59
  - Treat Playwright, Maestro, and manual output as adapters after QA design. Do not let runner selection replace review of the inferred intent and scenarios.
60
60
  - If the output is `review only` or `near runnable`, explain what blocks it from becoming trusted regression evidence.
61
61
  - If `qamap qa` says no manifest was found, do not stop. The first run is allowed to be manifest-free.
@@ -79,6 +79,7 @@ QAMap QA
79
79
  - Change intent and confidence:
80
80
  - Behavior lifecycle:
81
81
  - Required QA scenarios:
82
+ - Scenario source files/lines:
82
83
  - Affected flow:
83
84
  - Suggested E2E/checklist:
84
85
  - Missing evidence: