@ivorycanvas/qamap 0.4.1 → 0.4.3

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 CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.4.3 - 2026-07-14
6
+
7
+ ### Added
8
+
9
+ - Added evidence-ranked QA scenario routing. Each intent-backed scenario is now classified as `required`, `recommended`, or `review-only` from its priority, confidence, review requirement, and exact diff sources instead of treating every inferred path as equally actionable.
10
+ - Added scenario-level automation receipts to human, JSON, and agent output. QAMap reports whether each selected scenario was `compiled`, `partial`, `not-compiled`, or `review-only`, including mapped step and assertion counts plus a concrete blocker when automation is incomplete.
11
+ - Added benchmark contracts for selected-to-compiled coverage so public fixtures fail CI when required QA is proposed without a traceable automation handoff.
12
+
13
+ ### Changed
14
+
15
+ - E2E readiness now includes required scenario compilation gaps. A syntactically valid draft cannot be promoted as runnable evidence when a required QA scenario was omitted or only partially mapped.
16
+ - Playwright failure-path generation now requires an unchanged mockable endpoint boundary, an action selector related to the changed flow, and a repository-observed failure outcome before it emits executable setup, action, and assertion steps.
17
+ - Contributor guidance now requires domain-neutral product rules, positive evidence combinations, negative controls, and unrelated fixture coverage before a specialized inference can enter the shared engine.
18
+
19
+ ### Fixed
20
+
21
+ - Unrelated controls can no longer be reused merely because they are the first stable selector near a changed endpoint.
22
+ - Maestro automation receipts now reflect commands and assertions that were actually generated instead of assuming coverage from the selected runner alone.
23
+
24
+ ## 0.4.2 - 2026-07-13
25
+
26
+ ### Added
27
+
28
+ - Added benchmark contracts for draft readiness, runnable candidates, self-check passes, review-only files, TODO markers, and execution blockers. Public fixtures can now fail CI when QAMap finds the right flow but produces an unusable automation draft.
29
+ - Added deterministic Playwright failure-path compilation when repository evidence exposes a mockable endpoint, a stable action control, and an observable failure message. Generated drafts replace the success route with a 4xx/5xx response, repeat the user action, and assert the failure UI instead of falling back to a body-visible smoke check.
30
+
31
+ ### Changed
32
+
33
+ - Draft execution readiness now measures whether a generated file can be tried locally from runner, entrypoint, selector, fixture, and self-check evidence. Missing pre-existing validation coverage remains required PR guidance, but no longer falsely claims that the new file cannot execute.
34
+ - A partial fixture match can qualify as a runnable candidate when QAMap generated executable mock scaffolding and every other execution check passes. It still remains a review item before the draft becomes trusted regression evidence.
35
+ - Playwright self-checks now report body-only smoke assertions as domain-assertion warnings. Such files remain tryable, but cannot be called runnable candidates until they assert an observable product outcome.
36
+
37
+ ### Fixed
38
+
39
+ - Draft reports no longer tell users to replace TODO locators when the generated files contain no TODO markers.
40
+
5
41
  ## 0.4.1 - 2026-07-13
6
42
 
7
43
  ### Added
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
  [![npm version](https://img.shields.io/npm/v/@ivorycanvas/qamap.svg)](https://www.npmjs.com/package/@ivorycanvas/qamap)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
 
7
+ ![QAMap: local PR QA design from commits and diffs](docs/assets/qamap-cover.png)
8
+
7
9
  **A local, zero-LLM PR QA designer. QAMap turns commit intent and code diffs into evidence-backed behavior lifecycles, missing QA, and deterministic automation drafts. No cloud. No source upload. No token.**
8
10
 
9
11
  QAMap reads commit subjects and bodies, git changes, project structure, selectors, existing tests, and optional repo QA memory, then answers the question every reviewer asks: *"What behavior did this PR intend to change, how does that behavior move through the product, and what should we verify before merge?"* Playwright, Maestro, and manual checklists are output adapters after that judgment, not the product recommendation itself.
@@ -26,7 +28,7 @@ Run one read-only command on a branch. A manifest and test runner are not requir
26
28
  pnpm dlx @ivorycanvas/qamap qa . --base origin/main --head HEAD
27
29
  ```
28
30
 
29
- The report starts with the inferred behavior and keeps each proposed scenario connected to the commit or exact base/head diff line that caused it. Removed guards and validation remain visible as base-side evidence; each source is labeled `direct`, `supporting`, or `contextual` (trimmed from the committed lifecycle benchmark):
31
+ The report starts with the inferred behavior and keeps each proposed scenario connected to the commit or exact base/head diff line that caused it. Removed guards and validation remain visible as base-side evidence; each source is labeled `direct`, `supporting`, or `contextual`. QAMap then shows two separate receipts: why the scenario was routed as `required`, `recommended`, or `review-only`, and whether the E2E adapter compiled it fully, partially, or not at all (trimmed from the committed lifecycle benchmark):
30
32
 
31
33
  ```txt
32
34
  Change intent: Submit notification preferences and show the saved state [high]
@@ -34,15 +36,21 @@ Behavior lifecycle: trigger -> state-change -> side-effect -> observable-outcome
34
36
 
35
37
  QA scenarios:
36
38
  - [critical] changed preference lifecycle (confidence: high)
39
+ - Routing: required — 3 supporting diff hunks
40
+ - E2E mapping: partial — steps 0/3, assertions 1/1
37
41
  - Source: src/pages/preferences.tsx:17, symbol onClick [supporting, head]
38
42
  - Source: src/pages/preferences.tsx:8, symbol setSaved [supporting, head]
39
43
  - Assert: the saved state becomes observable
40
44
  - [recommended] failure, timeout, and retry handling (confidence: medium; review required)
45
+ - Routing: recommended — 1 supporting diff hunk
46
+ - E2E mapping: not compiled — no deterministic failure compiler matched all required evidence
41
47
  - Source: src/pages/preferences.tsx:7, symbol fetch [supporting, head]
42
48
  - Assert: retries do not duplicate requests or side effects
43
49
 
44
50
  Optional automation:
45
51
  - Adapter candidate: Playwright
52
+ - Scenario routing: 2 required, 2 recommended, 0 review-only
53
+ - E2E mapping: 0 compiled, 1 partial, 3 not compiled
46
54
  - qamap e2e draft . --base origin/main --head HEAD
47
55
  ```
48
56
 
@@ -76,6 +84,7 @@ One minified JSON object (`schema: qamap.qa`) with change intents, lifecycle sta
76
84
  - **Judgment first, generation second.** Deciding *what deserves testing* for a given change is the missing layer. QAMap makes that judgment statically, deterministically, and locally for free.
77
85
  - **The repo remembers.** Team QA knowledge lives in `.qamap/manifest.yaml`, reviewed once and reused on every PR — instead of re-prompting an agent each session.
78
86
  - **Honest output.** Drafts state what blocks them from being trusted; changed endpoints are observed, never mocked away; generated specs never assert what cannot pass. Configuration, docs, generated artifacts, and changed tests stay in verification mode instead of fabricating a product-journey E2E.
87
+ - **Selected is not compiled.** Every evidence-routed scenario keeps a static automation receipt. Required behavior that remains partial or not compiled lowers readiness instead of being hidden behind a smoke test. `compiled` still does not claim the application was executed.
79
88
 
80
89
  Positioning against recorders, LLM test generation, and impact-analysis tools: [where QAMap fits](docs/adoption.md#where-qamap-fits).
81
90
 
package/dist/e2e.d.ts CHANGED
@@ -8,6 +8,7 @@ import type { LocalHistoryReference } from "./history.js";
8
8
  import type { CoverageEvidence, TestSuiteSummary } from "./test-evidence.js";
9
9
  import type { BehaviorGraph } from "./behavior.js";
10
10
  import type { BehaviorLifecycleStage, ChangeIntentAnalysis, ChangeIntentConfidence, ChangeIntentEvidence, IntentQaScenario } from "./change-intent.js";
11
+ import type { QaScenarioDecision } from "./scenario-routing.js";
11
12
  export type E2eProjectType = "expo-react-native" | "react-native" | "web" | "api-service" | "design-tokens" | "data-catalog" | "cli" | "unknown";
12
13
  export type E2eRunnerName = "maestro" | "playwright" | "manual";
13
14
  export type E2eFlowKind = "ui" | "api" | "state" | "content" | "config" | "test-evidence" | "documentation" | "generated-artifact" | "artifact" | "catalog" | "command" | "domain" | "changed-file";
@@ -247,6 +248,23 @@ export interface E2eDraftFile {
247
248
  intentConfidence?: ChangeIntentConfidence;
248
249
  lifecycle?: BehaviorLifecycleStage[];
249
250
  qaScenarios?: IntentQaScenario[];
251
+ scenarioAutomation?: E2eScenarioAutomationReceipt[];
252
+ }
253
+ export type E2eScenarioAutomationStatus = "compiled" | "partial" | "not-compiled" | "review-only";
254
+ export interface E2eScenarioAutomationReceipt {
255
+ scenarioId: string;
256
+ title: string;
257
+ kind: IntentQaScenario["kind"];
258
+ priority: IntentQaScenario["priority"];
259
+ decision: QaScenarioDecision;
260
+ status: E2eScenarioAutomationStatus;
261
+ requiredSourceCount: number;
262
+ referenceSourceCount: number;
263
+ mappedSteps: number;
264
+ totalSteps: number;
265
+ mappedAssertions: number;
266
+ totalAssertions: number;
267
+ blockers: string[];
250
268
  }
251
269
  export type E2eDraftActionKind = "assertion" | "fixture" | "manifest" | "runner" | "selector" | "setup" | "validation";
252
270
  export type E2eDraftActionPriority = "required" | "recommended";
@@ -299,6 +317,13 @@ export interface E2eDraftReadinessSummary {
299
317
  totalTodos: number;
300
318
  filesWithExecutionBlockers: number;
301
319
  totalExecutionBlockers: number;
320
+ requiredScenarios: number;
321
+ recommendedScenarios: number;
322
+ reviewOnlyScenarios: number;
323
+ compiledScenarios: number;
324
+ partialScenarios: number;
325
+ notCompiledScenarios: number;
326
+ requiredScenarioGaps: number;
302
327
  topBlockers: string[];
303
328
  }
304
329
  export declare function formatDraftReadinessStage(summary: Pick<E2eDraftReadinessSummary, "level" | "score">): string;