@keber/qa-framework 1.10.0 → 1.12.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 (113) hide show
  1. package/CHANGELOG.md +63 -18
  2. package/README.md +2 -2
  3. package/docs/architecture.md +30 -26
  4. package/docs/decisions/lane-heartbeat-caller.md +86 -0
  5. package/docs/final-report.md +23 -23
  6. package/docs/folder-structure-guide.md +106 -80
  7. package/docs/installation.md +35 -7
  8. package/docs/skills-architecture.md +23 -23
  9. package/docs/spec-driven-philosophy.md +9 -9
  10. package/docs/usage-with-agent.md +83 -9
  11. package/docs/visuals/diag-01-ejecutivo-1.png +0 -0
  12. package/docs/visuals/diag-02-tactico-1.png +0 -0
  13. package/docs/visuals/diag-03-tecnico-1.png +0 -0
  14. package/docs/visuals/info-01-ejecutivo-1.png +0 -0
  15. package/docs/visuals/info-02-tactico-1.png +0 -0
  16. package/docs/visuals/info-03-tecnico-1.png +0 -0
  17. package/docs/visuals/pres-01-ejecutivo-1.png +0 -0
  18. package/docs/visuals/pres-02-tactico-1.png +0 -0
  19. package/docs/visuals/pres-03-tecnico-1.png +0 -0
  20. package/docs/visuals/qa-01-problema-1.png +0 -0
  21. package/docs/visuals/qa-02-que-es-1.png +0 -0
  22. package/docs/visuals/qa-03-pipeline-1.png +0 -0
  23. package/docs/visuals/qa-04-6-archivos-1.png +0 -0
  24. package/docs/visuals/qa-05-humano-1.png +0 -0
  25. package/docs/visuals/qa-06-agente-1.png +0 -0
  26. package/docs/visuals/qa-07-skills-arch-1.png +0 -0
  27. package/docs/visuals/qa-08-traceability-1.png +0 -0
  28. package/docs/visuals/qa-en-01-problem-1.png +0 -0
  29. package/docs/visuals/qa-en-02-what-is-1.png +0 -0
  30. package/docs/visuals/qa-en-03-pipeline-1.png +0 -0
  31. package/docs/visuals/qa-en-04-6files-1.png +0 -0
  32. package/docs/visuals/qa-en-05-human-1.png +0 -0
  33. package/docs/visuals/qa-en-06-agent-1.png +0 -0
  34. package/docs/visuals/qa-en-07-skills-arch-1.png +0 -0
  35. package/docs/visuals/qa-en-08-traceability-1.png +0 -0
  36. package/examples/module-example/suppliers/00-inventory.md +1 -1
  37. package/examples/module-example/suppliers/suppliers-create.spec.ts +8 -8
  38. package/integrations/ado-powershell/README.md +1 -1
  39. package/integrations/ado-powershell/pipelines/azure-pipeline-qa.yml +92 -25
  40. package/integrations/ado-powershell/scripts/sync-ado-titles.ps1 +2 -2
  41. package/integrations/playwright/README.md +128 -4
  42. package/package.json +9 -6
  43. package/qa-framework.config.json +24 -3
  44. package/scripts/check-forbidden-chars.js +187 -0
  45. package/scripts/check-spanish-accents.js +159 -0
  46. package/scripts/cli.js +1 -1
  47. package/scripts/generate.js +2 -2
  48. package/scripts/init.js +108 -45
  49. package/scripts/lib/claude-agents.js +78 -0
  50. package/scripts/lib/claude-commands.js +56 -0
  51. package/scripts/sync-version.js +36 -0
  52. package/scripts/upgrade.js +461 -30
  53. package/scripts/validate.js +17 -17
  54. package/skills/qa-ado-integration/SKILL.md +19 -19
  55. package/skills/qa-ado-integration/references/scripts-and-config.md +6 -6
  56. package/skills/qa-automation/SKILL.md +49 -27
  57. package/skills/qa-automation/references/config-checklist.md +4 -4
  58. package/skills/qa-automation/references/dom-inspection-template.js +7 -7
  59. package/skills/qa-automation/references/patterns.md +20 -20
  60. package/skills/qa-automation/references/pom-template.md +161 -0
  61. package/skills/qa-maintenance/SKILL.md +11 -11
  62. package/skills/qa-maintenance/references/update-rules.md +8 -8
  63. package/skills/qa-module-analysis/SKILL.md +20 -19
  64. package/skills/qa-module-analysis/references/exploration-checklist.md +4 -4
  65. package/skills/qa-module-analysis/references/output-verification.md +69 -0
  66. package/skills/qa-module-analysis/references/spec-file-formats.md +14 -14
  67. package/skills/qa-spec-generation/SKILL.md +13 -7
  68. package/skills/qa-test-cases/SKILL.md +11 -81
  69. package/skills/qa-test-cases/references/test-case-template.md +5 -5
  70. package/skills/qa-test-plan/SKILL.md +22 -86
  71. package/skills/qa-test-plan/references/plan-de-pruebas-template.md +24 -24
  72. package/skills/qa-test-stabilization/SKILL.md +59 -30
  73. package/skills/qa-test-stabilization/references/classification-protocol.md +35 -35
  74. package/templates/agent-next-steps.md +10 -10
  75. package/templates/agents/qa-analisis.md +142 -0
  76. package/templates/agents/qa-asesoria.md +48 -0
  77. package/templates/agents/qa-informe-resultados.md +234 -0
  78. package/templates/agents/qa-plan.md +131 -0
  79. package/templates/automation-scaffold/.env.example +52 -3
  80. package/templates/automation-scaffold/fixtures/auth.ts +27 -5
  81. package/templates/automation-scaffold/fixtures/base.ts +130 -0
  82. package/templates/automation-scaffold/fixtures/test-helpers.ts +1 -1
  83. package/templates/automation-scaffold/global-setup.ts +196 -37
  84. package/templates/automation-scaffold/playwright.config.ts +74 -10
  85. package/templates/automation-scaffold/scripts/global-setup-guards.js +184 -0
  86. package/templates/automation-scaffold/scripts/lane-config.js +269 -0
  87. package/templates/automation-scaffold/scripts/lane-lock.js +589 -0
  88. package/templates/defect-report.md +18 -4
  89. package/templates/execution-report.md +9 -9
  90. package/templates/integration-scaffold/.env.example +40 -0
  91. package/templates/integration-scaffold/README.md +77 -0
  92. package/templates/integration-scaffold/global-setup.ts +119 -0
  93. package/templates/integration-scaffold/package.json +15 -0
  94. package/templates/integration-scaffold/playwright.config.ts +92 -0
  95. package/templates/integration-scaffold/tests/example.spec.ts +43 -0
  96. package/templates/memory/ci-pipeline-findings.md +36 -0
  97. package/templates/memory/data-volatility-strategies.md +70 -0
  98. package/templates/memory/e2e-stabilization-patterns.md +54 -0
  99. package/templates/qa-framework.instructions.md +16 -7
  100. package/templates/qa-framework.rules.md +53 -0
  101. package/templates/qa-readme.md +26 -5
  102. package/templates/session-summary.md +2 -2
  103. package/templates/specification/00-inventory.md +3 -3
  104. package/templates/specification/01-business-rules.md +6 -6
  105. package/templates/specification/02-workflows.md +1 -1
  106. package/templates/specification/03-roles-permissions.md +1 -1
  107. package/templates/specification/04-test-data.md +8 -8
  108. package/templates/specification/05-test-scenarios.md +5 -5
  109. package/templates/test-case.md +3 -3
  110. package/templates/test-data-guidelines.md +7 -7
  111. package/templates/test-plan-sprint.md +13 -13
  112. package/templates/test-plan.md +3 -3
  113. package/skills/qa-test-plan/references/priority-and-feasibility.md +0 -159
@@ -0,0 +1,161 @@
1
+ # Reference: Page Object Template
2
+
3
+ > Loaded by `skills/qa-automation/` at Step 1b, when the POM decision criteria are met.
4
+
5
+ A Page Object owns **locators and interactions** for one submodule. It never owns assertions about
6
+ business rules - those belong in the spec file, where they can be traced to a TC ID.
7
+
8
+ ---
9
+
10
+ ## Two-layer structure
11
+
12
+ Most modules end up with the same shape: one abstract base per module holding the CRUD interaction
13
+ vocabulary shared by every submodule, and one thin concrete class per submodule holding only its
14
+ route, its identity, and whatever it genuinely does differently.
15
+
16
+ ```
17
+ page-objects/
18
+ {module}/
19
+ Base{MODULE}CRUDPage.ts <- shared interactions, abstract
20
+ {MODULE}{Sub}Page.ts <- route + submodule-specific overrides only
21
+ ```
22
+
23
+ Write the concrete class first with inline locators. Promote a method to the base class on the
24
+ **second** submodule that needs it, not in anticipation of the first.
25
+
26
+ ---
27
+
28
+ ## Base class template
29
+
30
+ ```typescript
31
+ import { Page, Locator } from '@playwright/test';
32
+ import { expect } from '../../fixtures/base';
33
+
34
+ /**
35
+ * Shared CRUD interactions for {MODULE} submodules.
36
+ *
37
+ * Locators here must match the UI framework the app actually renders. Confirm them
38
+ * against a real DOM inspection (Step 0) before writing tests - never from assumption.
39
+ */
40
+ export abstract class Base{MODULE}CRUDPage {
41
+ readonly page: Page;
42
+
43
+ constructor(page: Page) {
44
+ this.page = page;
45
+ }
46
+
47
+ async navigateTo(route: string): Promise<void> {
48
+ await this.page.goto(route);
49
+ await this.page.waitForLoadState('domcontentloaded');
50
+ }
51
+
52
+ async waitForGrid(): Promise<void> {
53
+ await this.page.locator('{GRID_ROW_SELECTOR}').first().waitFor({ timeout: 20_000 });
54
+ }
55
+
56
+ // Label-driven field access. See "Accent-insensitive label matching" below before
57
+ // writing this for a Spanish-language UI.
58
+ fieldInput(label: string): Locator {
59
+ return this.page.getByLabel(label);
60
+ }
61
+
62
+ async fillField(label: string, value: string): Promise<void> {
63
+ await this.fieldInput(label).fill(value);
64
+ }
65
+
66
+ async clickNuevoRegistro(): Promise<void> {
67
+ await this.page.getByRole('button', { name: /{CREATE_BUTTON_PATTERN}/i }).click();
68
+ }
69
+
70
+ async clickGuardar(): Promise<void> {
71
+ await this.page.getByRole('button', { name: /{SAVE_BUTTON_PATTERN}/i }).click();
72
+ }
73
+
74
+ async verifyValidationError(fieldLabel: string): Promise<void> {
75
+ await expect(
76
+ this.fieldInput(fieldLabel).locator('{VALIDATION_MESSAGE_SELECTOR}')
77
+ ).toBeVisible({ timeout: 5_000 });
78
+ }
79
+
80
+ async verifyRowInGrid(text: string | RegExp): Promise<void> {
81
+ await expect(this.page.locator('{GRID_ROW_SELECTOR}').filter({ hasText: text }))
82
+ .toBeVisible();
83
+ }
84
+ }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Concrete submodule template
90
+
91
+ ```typescript
92
+ import { Page } from '@playwright/test';
93
+ import { Base{MODULE}CRUDPage } from './Base{MODULE}CRUDPage';
94
+
95
+ // {SUBMODULE_CODE}: {display name} ({route})
96
+ // Fields: {field} (required), {field} (auto/read-only), ...
97
+ // Known defects affecting this submodule: {DEF-ID}: {one-line description}
98
+ export class {MODULE}{Sub}Page extends Base{MODULE}CRUDPage {
99
+ static readonly route = '{route}';
100
+ static readonly submoduleCode = '{SUBMODULE_CODE}';
101
+ static readonly displayName = '{display name}';
102
+
103
+ constructor(page: Page) {
104
+ super(page);
105
+ }
106
+
107
+ // Only what this submodule does differently. If a second submodule needs this
108
+ // method, move it to the base class then - not before.
109
+ }
110
+ ```
111
+
112
+ The three `static readonly` fields let a spec file reference the submodule without duplicating
113
+ string literals, and make the POM self-describing when read on its own.
114
+
115
+ ---
116
+
117
+ ## Accent-insensitive label matching (Spanish-language UIs)
118
+
119
+ **This is a measured failure mode, not a precaution.** In one project, 24 of 39 CAT smoke tests
120
+ failed because the specs were written with unaccented Spanish labels (`Codigo`, `Compania naviera`,
121
+ `Tipo de emision`) while the DOM renders the correct accents (`Código`, `Compañía naviera`,
122
+ `Tipo de emisión`). An exact-text selector never matches. Two unrelated mitigations were attempted
123
+ first - raising the grid timeout and forcing HTTP/1.1 - because the failure presents as a timeout,
124
+ not as a text mismatch.
125
+
126
+ The durable fix is to write specs with correct accents in the first place (they describe a Spanish
127
+ UI, so they must carry Spanish orthography). Where a base class must tolerate both, match the
128
+ whole label accent-insensitively:
129
+
130
+ ```typescript
131
+ // Anchored with ^...$ on purpose: unanchored, :text-matches() matches as a SUBSTRING of the
132
+ // element's full text, so a short label can match several elements and trip strict mode.
133
+ accentInsensitiveRegex(text: string): RegExp {
134
+ const accentClass: Record<string, string> = {
135
+ a: 'aá', e: 'eé', i: 'ií', o: 'oó', u: 'uúü', n: 'nñ',
136
+ };
137
+ const escaped = text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
138
+ const pattern = escaped.replace(/[aeioun]/gi, (ch) => {
139
+ const cls = accentClass[ch.toLowerCase()];
140
+ return cls ? `[${cls}]` : ch;
141
+ });
142
+ return new RegExp(`^${pattern}$`, 'i');
143
+ }
144
+ ```
145
+
146
+ Apply it in **every** label-driven method - field inputs, validation messages, and foreign-key
147
+ selectors alike. In the project above, only two of the three families were overridden on the first
148
+ pass, and the FK selectors kept failing for another two days until the same fix reached them.
149
+
150
+ ---
151
+
152
+ ## Rules
153
+
154
+ | Rule | Correct | Wrong |
155
+ |---|---|---|
156
+ | Assertions | Business assertions live in the spec, traced to a TC ID | POM asserts business rules |
157
+ | Locators | Confirmed against a real DOM inspection (Step 0) | Guessed from the spec's prose |
158
+ | Waiting | `waitFor` on a state or a response | `waitForTimeout` |
159
+ | Promotion to base | On the second submodule that needs it | Anticipated on the first |
160
+ | Credentials | Fixture-provided | Referenced inside the POM |
161
+ | Header comment | Records inspection date, fields, known defects | Undocumented selectors |
@@ -11,10 +11,10 @@ description: >
11
11
 
12
12
  # QA Skill: Maintenance (Stage 6 of 6)
13
13
 
14
- **Stage**: 6 — Maintenance
14
+ **Stage**: 6 - Maintenance
15
15
  **Prerequisite**: An application change (bug fix, feature change, new requirement) has been delivered
16
16
  **Output**: Updated specs, TCs, and automation aligned with the new application behavior
17
- **Cycle**: Returns to Stage 2 (spec update) → Stage 4 (TC update) → Stage 5 (automation update) as needed
17
+ **Cycle**: Returns to Stage 2 (spec update) -> Stage 4 (TC update) -> Stage 5 (automation update) as needed
18
18
 
19
19
  > **Rule**: Never update specs to match an incorrect application behavior. Specs define correct behavior; automation reflects specs. If the app is wrong, file a defect, don't update the spec.
20
20
 
@@ -22,16 +22,16 @@ description: >
22
22
 
23
23
  ## Inputs Required
24
24
 
25
- 1. Description of the change — which submodule, what changed, and why
26
- 2. `qa/01-specifications/{module}/` — specs affected by the change
27
- 3. `qa/07-automation/e2e/tests/{module}/` — automation affected by the change
25
+ 1. Description of the change - which submodule, what changed, and why
26
+ 2. `qa/01-specifications/{module}/` - specs affected by the change
27
+ 3. `qa/07-automation/e2e/tests/{module}/` - automation affected by the change
28
28
  4. Optionally: ADO work item or defect report describing the change
29
29
 
30
30
  ---
31
31
 
32
32
  ## Process
33
33
 
34
- ### Step 1 — Identify affected artifacts
34
+ ### Step 1 - Identify affected artifacts
35
35
 
36
36
  For the delivered change, identify:
37
37
  - Which spec files reference the changed behavior (search for affected term/field/flow)
@@ -39,7 +39,7 @@ For the delivered change, identify:
39
39
  - Which automation files implement those TCs
40
40
  - Whether any test data in `04-test-data.md` is affected
41
41
 
42
- ### Step 2 — Update specs first
42
+ ### Step 2 - Update specs first
43
43
 
44
44
  Update spec files before touching automation. Spec update rules:
45
45
 
@@ -54,14 +54,14 @@ Update spec files before touching automation. Spec update rules:
54
54
 
55
55
  Detailed rules: `references/update-rules.md`
56
56
 
57
- ### Step 3 — Update TCs
57
+ ### Step 3 - Update TCs
58
58
 
59
59
  After specs are updated:
60
60
  - Update step text in affected `TC-*.md` files
61
61
  - If a TC no longer applies: mark as `[OBSOLETE]` in the index, do not delete the file
62
62
  - If a new scenario added to specs: generate new TC following Stage 4
63
63
 
64
- ### Step 4 — Update automation
64
+ ### Step 4 - Update automation
65
65
 
66
66
  After TCs are updated:
67
67
  - Update locators for changed UI elements
@@ -71,7 +71,7 @@ After TCs are updated:
71
71
 
72
72
  Automation update rules: `references/update-rules.md`
73
73
 
74
- ### Step 5 — Bump spec version and log change
74
+ ### Step 5 - Bump spec version and log change
75
75
 
76
76
  In the spec file's YAML frontmatter (or header block):
77
77
  ```
@@ -80,7 +80,7 @@ last-updated: {date}
80
80
  change-summary: {one-line description of what changed}
81
81
  ```
82
82
 
83
- ### Step 6 — Update README and close session
83
+ ### Step 6 - Update README and close session
84
84
 
85
85
  - Update `qa/README.md` module row (spec version, TC count if changed, automation status)
86
86
  - Update `AGENT-NEXT-STEPS.md`:
@@ -17,7 +17,7 @@
17
17
 
18
18
  ### Field removed from UI
19
19
 
20
- 1. Mark row in `00-inventory.md` as `[REMOVED - {YYYY-MM-DD}]` — do NOT delete the row
20
+ 1. Mark row in `00-inventory.md` as `[REMOVED - {YYYY-MM-DD}]` - do NOT delete the row
21
21
  2. Mark the related business rule in `01-business-rules.md` as `[DEPRECATED - {YYYY-MM-DD}]`
22
22
  3. Mark related TCs in `05-test-scenarios.md` as `[DEPRECATED]` for traceability
23
23
  4. Update or skip automation tests that reference the removed element's selector
@@ -26,7 +26,7 @@
26
26
 
27
27
  1. Update `02-workflows.md` with the new flow diagram
28
28
  2. Mark the old version as `[PREVIOUS - {YYYY-MM-DD}]` inside the same file (keep for reference)
29
- 3. Review all TCs that test the affected steps — update expected results in `05-test-scenarios.md`
29
+ 3. Review all TCs that test the affected steps - update expected results in `05-test-scenarios.md`
30
30
 
31
31
  ### New submodule added
32
32
 
@@ -47,7 +47,7 @@ Follow the full module analysis process: `skills/qa-module-analysis/`.
47
47
  ### Selectors changed (redesign or framework update)
48
48
 
49
49
  1. Locate the spec file or page object containing the old selector
50
- 2. Update the selector — prefer `getByRole`, `getByLabel`, `getByTestId`
50
+ 2. Update the selector - prefer `getByRole`, `getByLabel`, `getByTestId`
51
51
  3. Run the affected test 2+ times to confirm stability
52
52
  4. Add an entry to the correction log at top of the spec file:
53
53
 
@@ -83,7 +83,7 @@ Add to the bottom of each updated spec file:
83
83
  | Version | Date | Description |
84
84
  |---------|------|-------------|
85
85
  | 1.0 | YYYY-MM-DD | Initial creation |
86
- | 1.1 | YYYY-MM-DD | Added RN-{MODULE}-{NNN}: {rule title}. TC count: N → M |
86
+ | 1.1 | YYYY-MM-DD | Added RN-{MODULE}-{NNN}: {rule title}. TC count: N -> M |
87
87
  | 1.2 | YYYY-MM-DD | Removed field {name} (deprecated) |
88
88
  ```
89
89
 
@@ -94,7 +94,7 @@ Add to the bottom of each updated spec file:
94
94
  Create at: `qa/SESSION-SUMMARY-{YYYY-MM-DD}-maintenance.md`
95
95
 
96
96
  ```markdown
97
- # Maintenance Session — {YYYY-MM-DD}
97
+ # Maintenance Session - {YYYY-MM-DD}
98
98
 
99
99
  ## Change trigger
100
100
  {Brief description of the application change that triggered this session}
@@ -108,11 +108,11 @@ Create at: `qa/SESSION-SUMMARY-{YYYY-MM-DD}-maintenance.md`
108
108
  ## TC changes
109
109
  - New TCs: {IDs} (+N total)
110
110
  - Deprecated TCs: {IDs} (-N total)
111
- - Net TC count: {module} → {N}
111
+ - Net TC count: {module} -> {N}
112
112
 
113
113
  ## Tests reactivated
114
- - {TC-ID}: removed test.skip() — DEF-{NNN} resolved
114
+ - {TC-ID}: removed test.skip() - DEF-{NNN} resolved
115
115
 
116
116
  ## Tests newly skipped
117
- - {TC-ID}: test.skip() added — DEF-{NNN} filed for {bug description}
117
+ - {TC-ID}: test.skip() added - DEF-{NNN} filed for {bug description}
118
118
  ```
@@ -10,10 +10,10 @@ description: >
10
10
 
11
11
  # QA Skill: Module Analysis (Stage 1 of 6)
12
12
 
13
- **Stage**: 1 — Module Analysis
14
- **Prerequisite**: None — this is the first stage
13
+ **Stage**: 1 - Module Analysis
14
+ **Prerequisite**: None - this is the first stage
15
15
  **Output**: `qa/01-specifications/module-{name}/submodule-{name}/` with 6 spec files
16
- **Next stage**: Stage 2 — Specification Generation (`qa-spec-generation`)
16
+ **Next stage**: Stage 2 - Specification Generation (`qa-spec-generation`)
17
17
 
18
18
  > **Pipeline rule**: This stage must be completed before any spec generation, test planning,
19
19
  > or automation can begin. Do not skip to a later stage.
@@ -33,32 +33,32 @@ Before starting:
33
33
 
34
34
  ---
35
35
 
36
- ## Phase 1 — Preparation
36
+ ## Phase 1 - Preparation
37
37
 
38
38
  1. Check if `qa/01-specifications/module-{name}/` already exists
39
39
  - **Exists**: read all existing files; only re-analyze what changed
40
40
  - **New**: create the directory and plan submodules
41
- 2. Allocate a unique 2–6 letter uppercase module code (check naming-conventions.md for conflicts)
41
+ 2. Allocate a unique 2-6 letter uppercase module code (check naming-conventions.md for conflicts)
42
42
  3. Create `qa/01-specifications/module-{name}/README.md` listing all planned submodules before analysis begins
43
43
 
44
44
  ---
45
45
 
46
- ## Phase 2 — Exploration (one pass per submodule)
46
+ ## Phase 2 - Exploration (one pass per submodule)
47
47
 
48
48
  For each submodule, use browser automation to collect:
49
49
 
50
- 1. **Navigation** — URLs, page titles, breadcrumbs
51
- 2. **UI inventory** — all inputs (type, required, validation), dropdowns (options), buttons, tables, modals, badges
52
- 3. **API endpoints** — observe network requests during create/read/update/delete; record method, path, payload shape
53
- 4. **Role access** — log in as each configured role; record `can access / cannot access / permission error`
54
- 5. **Workflow** — execute the primary happy path; record steps, branch points, state transitions
55
- 6. **Business rules** — attempt invalid inputs and boundary conditions; record validation messages exactly
50
+ 1. **Navigation** - URLs, page titles, breadcrumbs
51
+ 2. **UI inventory** - all inputs (type, required, validation), dropdowns (options), buttons, tables, modals, badges
52
+ 3. **API endpoints** - observe network requests during create/read/update/delete; record method, path, payload shape
53
+ 4. **Role access** - log in as each configured role; record `can access / cannot access / permission error`
54
+ 5. **Workflow** - execute the primary happy path; record steps, branch points, state transitions
55
+ 6. **Business rules** - attempt invalid inputs and boundary conditions; record validation messages exactly
56
56
 
57
57
  Detailed exploration checklist: `references/exploration-checklist.md`
58
58
 
59
59
  ---
60
60
 
61
- ## Phase 3 — Documentation (6-file output)
61
+ ## Phase 3 - Documentation (6-file output)
62
62
 
63
63
  Produce 6 files per submodule. File formats and templates: `references/spec-file-formats.md`
64
64
 
@@ -69,13 +69,13 @@ Produce 6 files per submodule. File formats and templates: `references/spec-file
69
69
  | `02-workflows.md` | `FL-{MODULE}-{NNN}` flows with ASCII/Mermaid diagrams |
70
70
  | `03-roles-permissions.md` | Role × feature access matrix; env var references for test users |
71
71
  | `04-test-data.md` | Prerequisites, data shapes per scenario, EXEC_IDX pattern |
72
- | `05-test-scenarios.md` | TC table: 50–85 TCs per submodule, all mandatory coverage categories |
72
+ | `05-test-scenarios.md` | TC table: 50-85 TCs per submodule, all mandatory coverage categories |
73
73
 
74
- TC target: **50–85 per submodule**. Mark origin as `UI-OBSERVED`, `PENDING-CODE`, or `BLOCKED-PERMISSIONS`.
74
+ TC target: **50-85 per submodule**. Mark origin as `UI-OBSERVED` (element and behavior both confirmed this session), `PENDING-BROWSER` (element observed but the behavior could not be exercised end-to-end this session, e.g. a disabled control or an unmet precondition), `PENDING-CODE` (feature not present or not reachable in this environment), or `BLOCKED-PERMISSIONS` (blocked by role/access, not by feature absence).
75
75
 
76
76
  ---
77
77
 
78
- ## Phase 4 — Review
78
+ ## Phase 4 - Review
79
79
 
80
80
  Completeness checklist before closing the stage:
81
81
 
@@ -85,11 +85,12 @@ Completeness checklist before closing the stage:
85
85
  - [ ] All TC IDs are unique across the module
86
86
  - [ ] Module README updated with submodule table and TC counts
87
87
  - [ ] `qa/README.md` module status row updated
88
+ - [ ] Output verification run and the counts reported (see `references/output-verification.md`) - report the command output, never a compliance claim
88
89
 
89
90
  ---
90
91
 
91
92
  ## Outputs
92
93
 
93
- - `qa/01-specifications/module-{name}/` — fully populated spec tree
94
- - `qa/01-specifications/module-{name}/README.md` — updated with submodule table
95
- - `qa/README.md` — module status row updated
94
+ - `qa/01-specifications/module-{name}/` - fully populated spec tree
95
+ - `qa/01-specifications/module-{name}/README.md` - updated with submodule table
96
+ - `qa/README.md` - module status row updated
@@ -63,9 +63,9 @@ For each configured test user role:
63
63
 
64
64
  ```
65
65
  Execute the primary happy path with appropriate test data
66
- Record each step (clickable element → navigation result → system state change)
66
+ Record each step (clickable element -> navigation result -> system state change)
67
67
  Identify branch points (e.g., approve vs reject)
68
- Record state transitions (pending → approved → rejected)
68
+ Record state transitions (pending -> approved -> rejected)
69
69
  ```
70
70
 
71
71
  ---
@@ -100,7 +100,7 @@ After completing all submodule files:
100
100
  ## Session Summary Template
101
101
 
102
102
  ```markdown
103
- # Session Summary — {YYYY-MM-DD}
103
+ # Session Summary - {YYYY-MM-DD}
104
104
 
105
105
  ## Module analyzed
106
106
  {module-name} ({module-code})
@@ -114,7 +114,7 @@ After completing all submodule files:
114
114
  - {path/to/file.md}
115
115
 
116
116
  ## Blockers
117
- - {any features marked PENDING-CODE or BLOCKED-PERMISSIONS}
117
+ - {any features marked PENDING-CODE, PENDING-BROWSER, or BLOCKED-PERMISSIONS}
118
118
 
119
119
  ## Next steps
120
120
  - {what remains before automation can begin}
@@ -0,0 +1,69 @@
1
+ # Reference: Output Verification (measure, do not assert)
2
+
3
+ > Shared by every skill that generates documentation: `qa-module-analysis`, `qa-spec-generation`,
4
+ > `qa-test-plan`, `qa-test-cases`.
5
+
6
+ A compliance claim is not evidence. When a stage ends, report the **command output** that proves the
7
+ artifact is correct - never the sentence "it complies".
8
+
9
+ This exists because the failure it prevents is measured, not hypothetical. In one project a
10
+ sub-agent wrote 5 memory files, 5 index rows and a task section entirely without Spanish accents,
11
+ then reported explicitly that it had complied with the accent rule - the rule having been passed to
12
+ it in full. The defect was caught only because the orchestrator ran the count by hand. Asked for the
13
+ count instead of the claim, the same agent produced the real numbers and corrected itself.
14
+
15
+ ---
16
+
17
+ ## Run before closing any stage that wrote a `.md`
18
+
19
+ Replace `<file>` with each file the stage created or modified.
20
+
21
+ ```bash
22
+ # 1. Spanish orthography - accented characters must be present in Spanish prose.
23
+ # A Spanish document scoring 0 is defective, not stylistically different.
24
+ rg -c '[áéíóúÁÉÍÓÚñÑüÜ]' <file>
25
+
26
+ # 2. Forbidden characters - must return nothing.
27
+ # em-dash, en-dash, ellipsis, smart quotes, arrows.
28
+ rg -n $'[\u2013\u2014\u2018\u2019\u201c\u201d\u2026\u2190-\u21ff]' <file>
29
+
30
+ # 3. No BOM - must not print EF BB BF.
31
+ head -c3 <file> | od -An -tx1
32
+ ```
33
+
34
+ Report the actual numbers per file. If a count is missing, the stage is not closed.
35
+
36
+ Check 1 is also available as a script that classifies the file's language first, so English
37
+ artifacts are not asked for accents they should not have:
38
+
39
+ ```bash
40
+ node node_modules/@keber/qa-framework/scripts/check-spanish-accents.js <file|dir>
41
+ node node_modules/@keber/qa-framework/scripts/check-spanish-accents.js --staged # pre-commit
42
+ node node_modules/@keber/qa-framework/scripts/check-spanish-accents.js --report <paths>
43
+ ```
44
+
45
+ It exits 1 when a Spanish file has no accented characters. Wire the `--staged` form into a
46
+ pre-commit hook to make the rule a control rather than an expectation.
47
+
48
+ ---
49
+
50
+ ## Why the accent check is not cosmetic
51
+
52
+ Specs written without accents propagate into automation. Page objects locate fields by their visible
53
+ label, so a spec that says `Codigo` while the UI renders `Código` produces a selector that never
54
+ matches. In one project this caused 24 of 39 smoke tests to fail, and cost two wrong mitigations
55
+ (raising a timeout, forcing HTTP/1.1) before the real cause was found - because the failure presents
56
+ as a timeout, not as a text mismatch. See `skills/qa-automation/references/pom-template.md`.
57
+
58
+ Write the accents at the source. Every downstream stage inherits them.
59
+
60
+ ---
61
+
62
+ ## Language boundary
63
+
64
+ Spanish artifacts (specs, plans, test cases, reports, defect files) must carry Spanish orthography.
65
+
66
+ Artifacts that are legitimately English - the framework's own skill files, English documentation -
67
+ score `0` on check 1 and that is correct. Never fabricate Spanish prose to satisfy the metric; report
68
+ the language of the artifact and move on. The check applies to content that **is** Spanish, and
69
+ `conventions.language` in `qa/qa-framework.config.json` says which that is.
@@ -8,7 +8,7 @@
8
8
  ## `00-inventory.md`
9
9
 
10
10
  ```markdown
11
- # MODULE: {Module Display Name} — Submodule: {Submodule Display Name}
11
+ # MODULE: {Module Display Name} - Submodule: {Submodule Display Name}
12
12
 
13
13
  | Field | Value |
14
14
  |-------|-------|
@@ -47,11 +47,11 @@
47
47
  ```
48
48
 
49
49
  **Rule identification tips**:
50
- - Every required field → at least 1 RN
51
- - Every unique constraint → 1 RN (duplicate not allowed)
52
- - Every state transition → 1 RN (can only approve if status=pending)
53
- - Every role restriction → 1 RN
54
- - Every auto-calculated field → 1 RN
50
+ - Every required field -> at least 1 RN
51
+ - Every unique constraint -> 1 RN (duplicate not allowed)
52
+ - Every state transition -> 1 RN (can only approve if status=pending)
53
+ - Every role restriction -> 1 RN
54
+ - Every auto-calculated field -> 1 RN
55
55
 
56
56
  ---
57
57
 
@@ -88,7 +88,7 @@
88
88
  ## `03-roles-permissions.md`
89
89
 
90
90
  ```markdown
91
- # Roles and Permissions — {Submodule}
91
+ # Roles and Permissions - {Submodule}
92
92
 
93
93
  ## Access Matrix
94
94
 
@@ -115,7 +115,7 @@
115
115
  ## `04-test-data.md`
116
116
 
117
117
  ```markdown
118
- # Test Data — {Submodule}
118
+ # Test Data - {Submodule}
119
119
 
120
120
  ## Prerequisites
121
121
 
@@ -129,7 +129,7 @@
129
129
  - Field A: {value type}
130
130
  - User: role `{ROLE_NAME}`, credentials from `QA_USER_{ROLE}_EMAIL` env var
131
131
 
132
- ### Scenario: {negative — duplicate}
132
+ ### Scenario: {negative - duplicate}
133
133
  - Precondition: {entity} with the same key already exists
134
134
  - Field A: {same value as existing record}
135
135
  - Expected: {system rejection behavior}
@@ -153,7 +153,7 @@ const uniqueTitle = `Test-${EXEC_IDX}`;
153
153
  ## `05-test-scenarios.md`
154
154
 
155
155
  ```markdown
156
- # Test Scenarios — {Module}: {Submodule}
156
+ # Test Scenarios - {Module}: {Submodule}
157
157
 
158
158
  **Module code**: {MODULE_CODE}
159
159
  **Submodule code**: {SUBMODULE_CODE}
@@ -177,7 +177,7 @@ const uniqueTitle = `Test-${EXEC_IDX}`;
177
177
  |-------|-------|
178
178
  | Priority | P0 / P1 / P2 / P3 |
179
179
  | Type | Functional / Negative / Regression / Security / Integration |
180
- | Origin | UI-OBSERVED / PENDING-CODE / BLOCKED-PERMISSIONS |
180
+ | Origin | UI-OBSERVED / PENDING-BROWSER / PENDING-CODE / BLOCKED-PERMISSIONS |
181
181
  | Automation | Yes / Partial / No |
182
182
  | Playwright | (fill after automation is written) |
183
183
 
@@ -199,9 +199,9 @@ const uniqueTitle = `Test-${EXEC_IDX}`;
199
199
  - [ ] Access: unauthenticated user redirected to login
200
200
  - [ ] Access: role without permission receives error or empty page
201
201
  - [ ] Happy path: primary workflow with valid data succeeds
202
- - [ ] Negative: required field missing → validation error shown
203
- - [ ] Negative: duplicate record → system rejects with error message
204
- - [ ] Negative: invalid format → format error shown
202
+ - [ ] Negative: required field missing -> validation error shown
203
+ - [ ] Negative: duplicate record -> system rejects with error message
204
+ - [ ] Negative: invalid format -> format error shown
205
205
  - [ ] State transition: state changes correctly on action
206
206
  - [ ] Export/download: file is generated (if feature exists)
207
207
  - [ ] Pagination/search: filtering works correctly (if feature exists)
@@ -10,10 +10,10 @@ description: >
10
10
 
11
11
  # QA Skill: Specification Generation (Stage 2 of 6)
12
12
 
13
- **Stage**: 2 — Specification Generation
13
+ **Stage**: 2 - Specification Generation
14
14
  **Prerequisite**: `00-inventory.md` must exist (Stage 1 complete)
15
15
  **Output**: Complete 6-file spec set under `qa/01-specifications/module-{name}/submodule-{name}/`
16
- **Next stage**: Stage 3 — Test Plan (`qa-test-plan`)
16
+ **Next stage**: Stage 3 - Test Plan (`qa-test-plan`)
17
17
 
18
18
  > **Pipeline rule**: Do not generate specs for features marked `PENDING-CODE` in the inventory.
19
19
  > Do not create TCs without having observed or been given the behavior being tested.
@@ -31,7 +31,7 @@ description: >
31
31
 
32
32
  ## File Generation Rules
33
33
 
34
- Generate or update each file following the formats in `references/spec-file-formats.md`.
34
+ Generate or update each file following the formats in `../qa-module-analysis/references/spec-file-formats.md` (shared reference, not duplicated per skill).
35
35
 
36
36
  ### `00-inventory.md`
37
37
  - Header block: module/submodule codes, primary URL, status, last updated date
@@ -41,8 +41,8 @@ Generate or update each file following the formats in `references/spec-file-form
41
41
 
42
42
  ### `01-business-rules.md`
43
43
  - Format: `RN-{MODULE}-{NNN}` with type, trigger, behavior, error message (exact UI text)
44
- - **Rule sources**: every required field → 1 RN; every unique constraint → 1 RN; every state transition → 1 RN; every role restriction → 1 RN
45
- - Minimum 5 rules per submodule; typical 8–15
44
+ - **Rule sources**: every required field -> 1 RN; every unique constraint -> 1 RN; every state transition -> 1 RN; every role restriction -> 1 RN
45
+ - Minimum 5 rules per submodule; typical 8-15
46
46
 
47
47
  ### `02-workflows.md`
48
48
  - Format: `FL-{MODULE}-{NNN}` with actor, trigger, precondition, ASCII/Mermaid flow diagram, postcondition
@@ -61,7 +61,7 @@ Generate or update each file following the formats in `references/spec-file-form
61
61
  ### `05-test-scenarios.md`
62
62
  - Summary table at top (total TCs by priority and type)
63
63
  - TC format: `TC-{MODULE}-{SUBMODULE}-{NNN}` with priority, type, origin, automation feasibility, preconditions, steps, expected result
64
- - **Target**: 50–85 TCs per submodule
64
+ - **Target**: 50-85 TCs per submodule
65
65
  - **Mandatory coverage categories** (≥1 TC each where applicable):
66
66
  - Access: unauthenticated user; role without permission
67
67
  - Happy path: primary workflow end-to-end
@@ -70,7 +70,7 @@ Generate or update each file following the formats in `references/spec-file-form
70
70
  - Export/download (if feature exists)
71
71
  - Pagination/search (if feature exists)
72
72
 
73
- Full format templates: `references/spec-file-formats.md`
73
+ Full format templates: `../qa-module-analysis/references/spec-file-formats.md`
74
74
 
75
75
  ---
76
76
 
@@ -86,6 +86,12 @@ Full format templates: `references/spec-file-formats.md`
86
86
 
87
87
  ---
88
88
 
89
+ ## Quality gates before marking complete
90
+
91
+ - [ ] Output verification run and the counts reported (see `../qa-module-analysis/references/output-verification.md`) - report the command output, never a compliance claim
92
+
93
+ ---
94
+
89
95
  ## Outputs
90
96
 
91
97
  - 6 spec files per submodule in `qa/01-specifications/module-{name}/submodule-{name}/`