@keber/qa-framework 1.2.0-0 → 1.3.0-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.
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Module Analysis
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-module-analysis/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/00-module-analysis.md`
4
7
  **Purpose**: Instructions for an AI agent to perform complete functional analysis of an application module and produce the 6-file specification set.
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Specification Generation
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-spec-generation/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/01-spec-generation.md`
4
7
  **Purpose**: Detailed instructions for generating the 6-file submodule specification set from a completed module analysis or from existing source material (UI observation, requirements docs, developer input).
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Test Plan Generation
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-test-plan/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/02-test-plan-generation.md`
4
7
  **Purpose**: Instructions for generating a test plan document for a module, after its spec set is complete.
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Test Case Generation
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-test-cases/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/03-test-case-generation.md`
4
7
  **Purpose**: Instructions for writing detailed, standalone test case documents from approved spec scenarios.
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Automation Generation
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-automation/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/04-automation-generation.md`
4
7
  **Purpose**: Instructions for writing Playwright E2E automation tests that trace back to approved test cases in `01-specifications/`.
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Test Stabilization
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-test-stabilization/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/04b-test-stabilization.md`
4
7
  **Purpose**: Instructions for exhaustively reviewing and stabilizing generated Playwright tests to ensure they are logically correct, technically sound, and free of false positives and false negatives before ADO integration.
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Azure DevOps Integration
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-ado-integration/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/05-ado-integration.md`
4
7
  **Purpose**: Instructions for an agent to create, configure, and maintain Azure DevOps Test Plans integration with Playwright automation results.
5
8
 
@@ -1,5 +1,8 @@
1
1
  # Agent Instructions: Maintenance and Updates
2
2
 
3
+ > ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-maintenance/SKILL.md`.
4
+ > Kept as reference during the transition period. Do not update this file.
5
+
3
6
  **File**: `agent-instructions/06-maintenance.md`
4
7
  **Purpose**: Instructions for updating QA artifacts after application code changes.
5
8
 
@@ -15,7 +15,6 @@ qa/
15
15
  ├── QA-STRUCTURE-GUIDE.md ← Copy of this guide (installed by framework)
16
16
  ├── qa-framework.config.json ← Project configuration
17
17
  │
18
- ├── 00-guides/ ← Process guides and agent instructions
19
18
  ├── 00-standards/ ← Naming conventions and artifact templates
20
19
  ├── 01-specifications/ ← Functional specifications per module
21
20
  ├── 02-test-plans/ ← Test plans (scope + priority decisions)
@@ -28,28 +27,30 @@ qa/
28
27
  └── memory/ ← Project QA learnings (project-maintained)
29
28
  ```
30
29
 
30
+ Agent skills live in `.github/skills/` (not inside `qa/`). See the `.github/skills/` section below.
31
+
31
32
  ---
32
33
 
33
- ## 00-guides/
34
+ ## .github/skills/
34
35
 
35
- **Purpose**: Process guides and operating instructions for both humans and agents.
36
+ **Purpose**: 3-layer QA pipeline skills installed by the framework. Loaded by the agent on demand — only the relevant skill for the current task is loaded, not all skills at once.
36
37
 
37
- **Installed by framework** (not project-maintained):
38
+ **Installed by framework** via `npm install @keber/qa-framework`:
38
39
 
39
- | File | Contents |
40
- |---|---|
41
- | `README.md` | Index with reading order by persona |
42
- | `AGENT-INSTRUCTIONS-MODULE-ANALYSIS.md` | How to analyze a module (4-phase process) |
43
- | `AGENT-INSTRUCTIONS-SPEC-GENERATION.md` | How to produce the 6-file spec set |
44
- | `AGENT-INSTRUCTIONS-TEST-CASES.md` | How to write test case tables |
45
- | `AGENT-INSTRUCTIONS-AUTOMATION.md` | How to write Playwright E2E tests |
46
- | `AGENT-INSTRUCTIONS-ADO-INTEGRATION.md` | How to sync results with Azure DevOps |
47
- | `AGENT-INSTRUCTIONS-MAINTENANCE.md` | How to update QA artifacts after code changes |
48
-
49
- **Project-maintained** (added over time):
50
- - `DEBUG-ARTIFACTS-POLICY.md` — where to save screenshots and debug output
51
- - `NOTAS-TECNICAS-PLAYWRIGHT.md` — project-specific Playwright gotchas
52
- - `RETROSPECTIVA-*.md` — session debug chronicles (optional, high value)
40
+ | Skill folder | Stage | When the agent loads it |
41
+ |---|---|---|
42
+ | `qa-module-analysis/` | 1 | Analyzing a new module or refreshing specs |
43
+ | `qa-spec-generation/` | 2 | Writing the 6-file spec set |
44
+ | `qa-test-plan/` | 3 | Creating a test plan document |
45
+ | `qa-test-cases/` | 4 | Writing TC-*.md files |
46
+ | `qa-automation/` | 5 | Implementing Playwright specs |
47
+ | `qa-test-stabilization/` | 5b | Diagnosing and fixing failing tests |
48
+ | `qa-ado-integration/` | opt | Syncing with Azure DevOps Test Plans |
49
+ | `qa-maintenance/` | 6 | Updating specs and tests after app changes |
50
+
51
+ Each skill folder contains:
52
+ - `SKILL.md` — process outline (~400-600 tokens, always loaded when skill applies)
53
+ - `references/` — detailed templates and code patterns (loaded on demand)
53
54
 
54
55
  ---
55
56
 
@@ -0,0 +1,136 @@
1
+ # Skills Architecture
2
+
3
+ > How QA agent skills are organized in `@keber/qa-framework`.
4
+
5
+ ---
6
+
7
+ ## Why Skills, Not Monolithic Instructions
8
+
9
+ The previous `agent-instructions/` model loaded one large file (~2,500 tokens each) per task. For an automation session covering 3 submodules, the agent would load the full automation file whether it needed the ADO config or not. With 8 instruction files, that was 20,000+ tokens of constant context pressure.
10
+
11
+ The 3-layer skill architecture reduces this to ~500 tokens for a typical task, loading detail only when needed.
12
+
13
+ ---
14
+
15
+ ## 3-Layer Model
16
+
17
+ | Layer | Location | Size | Purpose |
18
+ |---|---|---|---|
19
+ | 1 — Descriptor | YAML frontmatter in `SKILL.md` | ~50 tokens | Name + description; used for relevance detection |
20
+ | 2 — Process outline | `SKILL.md` body | ~400–600 tokens | Step-by-step process without code; always loaded when skill applies |
21
+ | 3 — Reference material | `references/*.md` | ~500–1500 tokens each | Detailed templates, code patterns, decision trees; loaded on demand |
22
+
23
+ The agent reads Layer 2 to understand what to do, then loads only the specific `references/` files it needs for the current step.
24
+
25
+ ---
26
+
27
+ ## Pipeline Sequence
28
+
29
+ Skills map to the QA pipeline stages defined in `copilot-instructions.md`. The file acts as a **pipeline sequencer** — it defines which stage comes before which, and what the prerequisite is. Skills are the implementation of each stage.
30
+
31
+ ```
32
+ Stage 1: qa-module-analysis (no prerequisite)
33
+ │
34
+ ▼
35
+ Stage 2: qa-spec-generation (requires 00-inventory.md)
36
+ │
37
+ ▼
38
+ Stage 3: qa-test-plan (requires 05-test-scenarios.md)
39
+ │
40
+ ▼
41
+ Stage 4: qa-test-cases (requires test plan)
42
+ │
43
+ ▼
44
+ Stage 5: qa-automation (requires approved specs, no PENDING-CODE)
45
+ │
46
+ ├─ Stage 5b: qa-test-stabilization (if tests fail)
47
+ │
48
+ ▼
49
+ Stage 6: qa-maintenance (after each application change)
50
+
51
+
52
+ Optional (any time after Stage 4):
53
+ qa-ado-integration (requires ADO enabled in config)
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Skill Inventory
59
+
60
+ | Skill | SKILL.md | References |
61
+ |---|---|---|
62
+ | `qa-module-analysis` | Stage 1 process (4 phases) | `exploration-checklist.md`, `spec-file-formats.md` |
63
+ | `qa-spec-generation` | Stage 2 rules + anti-patterns | `spec-file-formats.md` (shared with qa-module-analysis) |
64
+ | `qa-test-plan` | Stage 3 — priority + feasibility rules | `priority-and-feasibility.md` (includes full template) |
65
+ | `qa-test-cases` | Stage 4 — TC document rules | `test-case-template.md` |
66
+ | `qa-automation` | Stage 5 — patterns + completion checklist | `patterns.md`, `config-checklist.md` |
67
+ | `qa-test-stabilization` | Stage 5b — 8 steps + confidence scoring | `classification-protocol.md` (includes report template) |
68
+ | `qa-ado-integration` | Optional ADO sync — 6 steps | `scripts-and-config.md` |
69
+ | `qa-maintenance` | Stage 6 — update rules | `update-rules.md` |
70
+
71
+ ---
72
+
73
+ ## How Skills Are Installed
74
+
75
+ When a consumer project runs `npm install @keber/qa-framework`, the `postinstall` script (`scripts/init.js`) copies the entire `skills/` directory from the package to `.github/skills/` in the consumer project:
76
+
77
+ ```
78
+ @keber/qa-framework/skills/
79
+ qa-module-analysis/
80
+ SKILL.md
81
+ references/
82
+ exploration-checklist.md
83
+ spec-file-formats.md
84
+ qa-spec-generation/
85
+ SKILL.md
86
+ ...
87
+
88
+ → copies to →
89
+
90
+ {consumer-project}/.github/skills/
91
+ qa-module-analysis/
92
+ SKILL.md
93
+ references/
94
+ exploration-checklist.md
95
+ spec-file-formats.md
96
+ ...
97
+ ```
98
+
99
+ The copy uses `writeIfMissing` — it will not overwrite files that already exist in the consumer project. This allows consumer projects to customize their `.github/skills/` without losing changes on re-install.
100
+
101
+ ---
102
+
103
+ ## How to Add a Project-Specific Skill
104
+
105
+ Consumer projects can extend the skills by adding skill folders directly to `.github/skills/`:
106
+
107
+ 1. Create `.github/skills/{skill-name}/SKILL.md` with YAML frontmatter:
108
+ ```yaml
109
+ ---
110
+ name: my-custom-skill
111
+ description: >
112
+ Describe when this skill should be triggered.
113
+ ---
114
+ ```
115
+ 2. Add the skill body following the same 4-section structure: prerequisite → steps → rules → outputs
116
+ 3. Optionally add `references/*.md` for detailed templates
117
+ 4. Reference the skill from `copilot-instructions.md` if it's part of your pipeline
118
+
119
+ Project-specific skills are not overwritten by `npm install` updates.
120
+
121
+ ---
122
+
123
+ ## Mapping: Old vs New
124
+
125
+ | Former file | New skill | Token reduction |
126
+ |---|---|---|
127
+ | `agent-instructions/00-module-analysis.md` | `.github/skills/qa-module-analysis/SKILL.md` | ~2,500 → ~500 + on-demand references |
128
+ | `agent-instructions/01-spec-generation.md` | `.github/skills/qa-spec-generation/SKILL.md` | ~2,800 → ~400 + shared references |
129
+ | `agent-instructions/02-test-plan-generation.md` | `.github/skills/qa-test-plan/SKILL.md` | ~2,200 → ~400 + test-plan-template |
130
+ | `agent-instructions/03-test-case-generation.md` | `.github/skills/qa-test-cases/SKILL.md` | ~2,100 → ~400 + tc-template |
131
+ | `agent-instructions/04-automation-generation.md` | `.github/skills/qa-automation/SKILL.md` | ~3,500 → ~500 + patterns + config |
132
+ | `agent-instructions/04b-test-stabilization.md` | `.github/skills/qa-test-stabilization/SKILL.md` | ~3,800 → ~500 + classification |
133
+ | `agent-instructions/05-ado-integration.md` | `.github/skills/qa-ado-integration/SKILL.md` | ~2,400 → ~400 + scripts |
134
+ | `agent-instructions/06-maintenance.md` | `.github/skills/qa-maintenance/SKILL.md` | ~1,700 → ~400 + update-rules |
135
+
136
+ **Total context reduction**: ~21,000 tokens → ~3,500 tokens (Layer 2 only) + selective Layer 3 loading
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keber/qa-framework",
3
- "version": "1.2.0-0",
3
+ "version": "1.3.0-0",
4
4
  "description": "Reusable spec-driven QA framework for IDE-agent-assisted automated testing. Installable as an npm package. Provides structure, templates, agent instructions, and optional integrations for Playwright and Azure DevOps.",
5
5
  "keywords": [
6
6
  "qa",
package/scripts/cli.js CHANGED
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * Commands:
10
10
  * init Scaffold a qa/ folder structure from qa-framework.config.json
11
+ * upgrade Update framework-owned files after npm update (skills, copilot-instructions)
11
12
  * generate Generate an artifact (spec template, test plan, etc.)
12
13
  * validate Validate qa/ folder structure and conventions
13
14
  */
@@ -21,6 +22,7 @@ const [, , command, ...args] = process.argv;
21
22
 
22
23
  const commands = {
23
24
  init: 'init.js',
25
+ upgrade: 'upgrade.js',
24
26
  generate: 'generate.js',
25
27
  validate: 'validate.js',
26
28
  };
@@ -54,6 +56,7 @@ Usage:
54
56
 
55
57
  Commands:
56
58
  init [--config <path>] Scaffold qa/ structure from config file
59
+ upgrade [--dry-run] Update framework-owned files after npm update
57
60
  generate <artifact> Generate from template
58
61
  artifact: spec | test-plan | test-case |
59
62
  execution-report | defect-report |
@@ -67,6 +70,8 @@ Options:
67
70
  Examples:
68
71
  qa-framework init
69
72
  qa-framework init --config ./my-project.config.json
73
+ qa-framework upgrade
74
+ qa-framework upgrade --dry-run
70
75
  qa-framework generate spec --module suppliers --submodule create
71
76
  qa-framework validate
72
77
  qa-framework validate --strict
package/scripts/init.js CHANGED
@@ -77,7 +77,6 @@ process.stderr.write(`[qa-framework/init] Using config source: ${configSource}\n
77
77
 
78
78
  // --- Top-level folders ---
79
79
  const topLevelFolders = [
80
- '00-guides',
81
80
  '00-standards',
82
81
  '01-specifications',
83
82
  '02-test-plans',
@@ -222,24 +221,18 @@ const adoDir = path.join(qaRoot, '08-azure-integration');
222
221
  writeIfMissing(path.join(adoDir, 'README.md'), `# ADO Integration\n\nSee keber/qa-framework integrations/ado-powershell/ for setup instructions.\n`);
223
222
  writeIfMissing(path.join(adoDir, 'module-registry.json'), JSON.stringify({ modules: [] }, null, 2));
224
223
 
225
- // --- Agent instructions → qa/00-guides/ ---
226
- const agentInstrSrc = path.resolve(__dirname, '..', 'agent-instructions');
227
- const guidesDir = path.join(qaRoot, '00-guides');
228
- const agentFileMap = {
229
- '00-module-analysis.md': 'AGENT-INSTRUCTIONS-MODULE-ANALYSIS.md',
230
- '01-spec-generation.md': 'AGENT-INSTRUCTIONS-SPEC-GENERATION.md',
231
- '02-test-plan-generation.md': 'AGENT-INSTRUCTIONS-TEST-PLAN.md',
232
- '03-test-case-generation.md': 'AGENT-INSTRUCTIONS-TEST-CASES.md',
233
- '04-automation-generation.md':'AGENT-INSTRUCTIONS-AUTOMATION.md',
234
- '04b-test-stabilization.md': 'AGENT-INSTRUCTIONS-TEST-STABILIZATION.md',
235
- '05-ado-integration.md': 'AGENT-INSTRUCTIONS-ADO-INTEGRATION.md',
236
- '06-maintenance.md': 'AGENT-INSTRUCTIONS-MAINTENANCE.md',
237
- };
238
- for (const [src, dest] of Object.entries(agentFileMap)) {
239
- const srcPath = path.join(agentInstrSrc, src);
240
- const destPath = path.join(guidesDir, dest);
241
- if (fs.existsSync(srcPath)) {
242
- writeIfMissing(destPath, fs.readFileSync(srcPath, 'utf8'));
224
+ // --- Skills → .github/skills/ ---
225
+ const skillsSrc = path.resolve(__dirname, '..', 'skills');
226
+ const skillsDest = path.join(cwd, '.github', 'skills');
227
+ fs.mkdirSync(skillsDest, { recursive: true });
228
+ if (fs.existsSync(skillsSrc)) {
229
+ for (const skillName of fs.readdirSync(skillsSrc)) {
230
+ const skillSrcDir = path.join(skillsSrc, skillName);
231
+ if (!fs.statSync(skillSrcDir).isDirectory()) continue;
232
+ const skillDestDir = path.join(skillsDest, skillName);
233
+ fs.mkdirSync(skillDestDir, { recursive: true });
234
+ // Copy SKILL.md and references/ recursively
235
+ copyDirIfMissing(skillSrcDir, skillDestDir);
243
236
  }
244
237
  }
245
238
 
@@ -288,7 +281,7 @@ This project uses \`@keber/qa-framework\` v${config.frameworkVersion ?? '1.0.0'}
288
281
  ## Agent behavior rules
289
282
 
290
283
  0. **On every conversation start:** check if \`qa/AGENT-NEXT-STEPS.md\` exists. If it does, read it and complete its steps before anything else.
291
- 1. Before performing any QA task, read the relevant instruction file from \`qa/00-guides/\`. For project context, read \`qa/memory/INDEX.md\` if it exists, then load only the memory files relevant to the current task — do not load all memory files unconditionally.
284
+ 1. Before performing any QA task, load the relevant skill from \`.github/skills/\`. For project context, read \`qa/memory/INDEX.md\` if it exists, then load only the memory files relevant to the current task — do not load all memory files unconditionally. Never execute a pipeline stage unless its prerequisite is satisfied.
292
285
  2. Always save artifacts in the correct \`qa/\` subfolder - refer to \`qa/QA-STRUCTURE-GUIDE.md\`
293
286
  3. Never hardcode credentials - always use env vars and \`<PLACEHOLDER>\` in documentation
294
287
  4. Follow the naming conventions in \`qa/00-standards/naming-conventions.md\`
@@ -301,18 +294,20 @@ This project uses \`@keber/qa-framework\` v${config.frameworkVersion ?? '1.0.0'}
301
294
  1. Generate the output in \`UTF-8\` encoding without BOM (\`UTF-8\`, no signature).
302
295
  2. Ensure the raw output is \`UTF-8\` encoded with no \`EF BB BF\` bytes at the beginning.
303
296
 
304
- ## Available agent instructions
297
+ ## QA Pipeline
305
298
 
306
- | Task | Instruction file |
307
- |---|---|
308
- | Analyze a module | \`qa/00-guides/AGENT-INSTRUCTIONS-MODULE-ANALYSIS.md\` |
309
- | Generate specifications | \`qa/00-guides/AGENT-INSTRUCTIONS-SPEC-GENERATION.md\` |
310
- | Generate a test plan | \`qa/00-guides/AGENT-INSTRUCTIONS-TEST-PLAN.md\` |
311
- | Generate test cases | \`qa/00-guides/AGENT-INSTRUCTIONS-TEST-CASES.md\` |
312
- | Generate automation | \`qa/00-guides/AGENT-INSTRUCTIONS-AUTOMATION.md\` |
313
- | Stabilize failing tests | \`qa/00-guides/AGENT-INSTRUCTIONS-TEST-STABILIZATION.md\` |
314
- | Sync with Azure DevOps | \`qa/00-guides/AGENT-INSTRUCTIONS-ADO-INTEGRATION.md\` |
315
- | Maintenance after changes | \`qa/00-guides/AGENT-INSTRUCTIONS-MAINTENANCE.md\` |
299
+ Stages must run in order. Never start a stage unless its prerequisite is met.
300
+
301
+ | Stage | Task | Skill | Prerequisite |
302
+ |---|---|---|---|
303
+ | 1 | Analyze module | \`.github/skills/qa-module-analysis/SKILL.md\` | None |
304
+ | 2 | Generate specifications | \`.github/skills/qa-spec-generation/SKILL.md\` | 00-inventory.md exists |
305
+ | 3 | Generate test plan | \`.github/skills/qa-test-plan/SKILL.md\` | 05-test-scenarios.md exists |
306
+ | 4 | Generate test cases | \`.github/skills/qa-test-cases/SKILL.md\` | Test plan exists |
307
+ | 5 | Generate automation | \`.github/skills/qa-automation/SKILL.md\` | Specs approved, no PENDING-CODE |
308
+ | 5b | Stabilize failing tests | \`.github/skills/qa-test-stabilization/SKILL.md\` | Failing tests exist |
309
+ | 6 | Maintenance | \`.github/skills/qa-maintenance/SKILL.md\` | Application change delivered |
310
+ | — | ADO integration | \`.github/skills/qa-ado-integration/SKILL.md\` | ADO enabled in config |
316
311
 
317
312
  ## Project KB
318
313
  1. \`qa/README.md\` — The Living Index: module status, sprint history, blockers, quick-start commands.
@@ -368,6 +363,19 @@ function writeIfMissing(filePath, content) {
368
363
  }
369
364
  }
370
365
 
366
+ function copyDirIfMissing(srcDir, destDir) {
367
+ for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
368
+ const srcPath = path.join(srcDir, entry.name);
369
+ const destPath = path.join(destDir, entry.name);
370
+ if (entry.isDirectory()) {
371
+ fs.mkdirSync(destPath, { recursive: true });
372
+ copyDirIfMissing(srcPath, destPath);
373
+ } else {
374
+ writeIfMissing(destPath, fs.readFileSync(srcPath, 'utf8'));
375
+ }
376
+ }
377
+ }
378
+
371
379
  function specScaffold(modName, subName, modKey, subKey) {
372
380
  return `import { test, expect } from '@playwright/test';
373
381
 
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/upgrade.js — Upgrade framework-owned files in an existing project
4
+ *
5
+ * Usage:
6
+ * qa-framework upgrade
7
+ * qa-framework upgrade --dry-run
8
+ *
9
+ * What this command does (safe by design):
10
+ * ALWAYS updates (framework-owned):
11
+ * - .github/skills/ ← New skills architecture; always current
12
+ * - .github/copilot-instructions.md ← Pipeline sequencer; framework-owned
13
+ * - qa/QA-STRUCTURE-GUIDE.md ← Folder reference; framework-owned
14
+ *
15
+ * NEVER touches (project-owned):
16
+ * - qa/01-specifications/ ← Your specs
17
+ * - qa/02-test-plans/ ← Your test plans
18
+ * - qa/03-test-cases/ ← Your TCs
19
+ * - qa/07-automation/ ← Your Playwright code
20
+ * - qa/memory/ ← Your learnings
21
+ * - qa/README.md ← Your living index
22
+ * - qa/AGENT-NEXT-STEPS.md ← Your sprint queue
23
+ *
24
+ * REPORTS but does not delete:
25
+ * - qa/00-guides/ ← Old location (can be deleted manually)
26
+ */
27
+
28
+ 'use strict';
29
+
30
+ const fs = require('fs');
31
+ const path = require('path');
32
+
33
+ const args = process.argv.slice(2);
34
+ const dryRun = args.includes('--dry-run');
35
+
36
+ const cwd = process.env.INIT_CWD || process.cwd();
37
+
38
+ // Resolve config (same logic as init.js)
39
+ const rootConfigPath = path.resolve(cwd, 'qa-framework.config.json');
40
+ const qaConfigPath = path.resolve(cwd, 'qa', 'qa-framework.config.json');
41
+ let config = {};
42
+
43
+ const configFlag = args.indexOf('--config');
44
+ if (configFlag !== -1 && args[configFlag + 1]) {
45
+ config = JSON.parse(fs.readFileSync(path.resolve(cwd, args[configFlag + 1]), 'utf8'));
46
+ } else if (fs.existsSync(rootConfigPath)) {
47
+ config = JSON.parse(fs.readFileSync(rootConfigPath, 'utf8'));
48
+ } else if (fs.existsSync(qaConfigPath)) {
49
+ config = JSON.parse(fs.readFileSync(qaConfigPath, 'utf8'));
50
+ }
51
+
52
+ const qaRoot = path.join(cwd, 'qa');
53
+ const githubDir = path.join(cwd, '.github');
54
+ const skillsDest = path.join(githubDir, 'skills');
55
+ const skillsSrc = path.resolve(__dirname, '..', 'skills');
56
+
57
+ const updated = [];
58
+ const skipped = [];
59
+ const warnings = [];
60
+
61
+ console.log(`\n[qa-framework/upgrade] ${dryRun ? '(dry-run) ' : ''}Upgrading framework-owned files`);
62
+ console.log(`[qa-framework/upgrade] Project root: ${cwd}\n`);
63
+
64
+ // ---------------------------------------------------------------------------
65
+ // 1. .github/skills/ — always overwrite (framework-owned)
66
+ // ---------------------------------------------------------------------------
67
+ if (!fs.existsSync(skillsSrc)) {
68
+ warnings.push('skills/ source directory not found in package — skipping skill install');
69
+ } else {
70
+ fs.mkdirSync(skillsDest, { recursive: true });
71
+ copyDirForce(skillsSrc, skillsDest);
72
+ }
73
+
74
+ // ---------------------------------------------------------------------------
75
+ // 2. .github/copilot-instructions.md — overwrite (framework-owned sequencer)
76
+ // ---------------------------------------------------------------------------
77
+ const copilotInstrPath = path.join(githubDir, 'copilot-instructions.md');
78
+ const copilotContent = buildCopilotInstructions(config);
79
+ forceWrite(copilotInstrPath, copilotContent);
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // 3. qa/QA-STRUCTURE-GUIDE.md — overwrite (framework doc)
83
+ // ---------------------------------------------------------------------------
84
+ const structureGuideSrc = path.resolve(__dirname, '..', 'docs', 'folder-structure-guide.md');
85
+ const structureGuideDest = path.join(qaRoot, 'QA-STRUCTURE-GUIDE.md');
86
+ if (fs.existsSync(structureGuideSrc) && fs.existsSync(qaRoot)) {
87
+ forceWrite(structureGuideDest, fs.readFileSync(structureGuideSrc, 'utf8'));
88
+ }
89
+
90
+ // ---------------------------------------------------------------------------
91
+ // 4. Migration: report qa/00-guides/ if still present
92
+ // ---------------------------------------------------------------------------
93
+ const oldGuidesDir = path.join(qaRoot, '00-guides');
94
+ if (fs.existsSync(oldGuidesDir)) {
95
+ warnings.push(
96
+ `qa/00-guides/ still exists (old location). It can be deleted:\n` +
97
+ ` Remove-Item -Recurse -Force qa/00-guides`
98
+ );
99
+ }
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Summary
103
+ // ---------------------------------------------------------------------------
104
+ console.log('\n--- Results ---');
105
+ if (updated.length) {
106
+ console.log('\n Updated (framework-owned):');
107
+ for (const f of updated) console.log(` ✅ ${path.relative(cwd, f)}`);
108
+ }
109
+ if (skipped.length) {
110
+ console.log('\n Skipped (already up to date):');
111
+ for (const f of skipped) console.log(` — ${path.relative(cwd, f)}`);
112
+ }
113
+ if (warnings.length) {
114
+ console.log('\n Warnings:');
115
+ for (const w of warnings) console.log(` ⚠️ ${w}`);
116
+ }
117
+
118
+ console.log('\n[qa-framework/upgrade] Done.\n');
119
+
120
+ // -----------------------------------------------------------------------
121
+ // Helpers
122
+ // -----------------------------------------------------------------------
123
+
124
+ function forceWrite(filePath, content) {
125
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
126
+ const exists = fs.existsSync(filePath);
127
+ const changed = !exists || fs.readFileSync(filePath, 'utf8') !== content;
128
+ if (dryRun) {
129
+ if (changed) updated.push(filePath);
130
+ else skipped.push(filePath);
131
+ return;
132
+ }
133
+ fs.writeFileSync(filePath, content, 'utf8');
134
+ if (changed) updated.push(filePath);
135
+ else skipped.push(filePath);
136
+ }
137
+
138
+ function copyDirForce(srcDir, destDir) {
139
+ for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
140
+ const srcPath = path.join(srcDir, entry.name);
141
+ const destPath = path.join(destDir, entry.name);
142
+ if (entry.isDirectory()) {
143
+ fs.mkdirSync(destPath, { recursive: true });
144
+ copyDirForce(srcPath, destPath);
145
+ } else {
146
+ forceWrite(destPath, fs.readFileSync(srcPath, 'utf8'));
147
+ }
148
+ }
149
+ }
150
+
151
+ function buildCopilotInstructions(cfg) {
152
+ const version = cfg.frameworkVersion ?? '1.0.0';
153
+ return `# QA Framework Instructions
154
+
155
+ This project uses \`@keber/qa-framework\` v${version} for spec-driven automated testing.
156
+
157
+ ## Agent behavior rules
158
+
159
+ 0. **On every conversation start:** check if \`qa/AGENT-NEXT-STEPS.md\` exists. If it does, read it and complete its steps before anything else.
160
+ 1. Before performing any QA task, load the relevant skill from \`.github/skills/\`. For project context, read \`qa/memory/INDEX.md\` if it exists, then load only the memory files relevant to the current task — do not load all memory files unconditionally. Never execute a pipeline stage unless its prerequisite is satisfied.
161
+ 2. Always save artifacts in the correct \`qa/\` subfolder — refer to \`qa/QA-STRUCTURE-GUIDE.md\`
162
+ 3. Never hardcode credentials — always use env vars and \`<PLACEHOLDER>\` in documentation
163
+ 4. Follow the naming conventions in \`qa/00-standards/naming-conventions.md\`
164
+ 5. Project QA config is at \`qa/qa-framework.config.json\`
165
+ 6. Save learnings in \`qa/memory/\` with proper naming and metadata. Always update \`qa/memory/INDEX.md\` after adding or updating any memory file.
166
+ 7. **On module/sprint completion** (all TCs passing): (1) update the module status row in \`qa/README.md\`; (2) move the completed sprint checklist from \`AGENT-NEXT-STEPS.md\` to the \`## Sprint History\` section of \`qa/README.md\`; (3) trim \`AGENT-NEXT-STEPS.md\` so it contains only the next sprint — never let it accumulate more than one active sprint.
167
+
168
+ ## QA Pipeline
169
+
170
+ Stages must run in order. Never start a stage unless its prerequisite is met.
171
+
172
+ | Stage | Task | Skill | Prerequisite |
173
+ |---|---|---|---|
174
+ | 1 | Analyze module | \`.github/skills/qa-module-analysis/SKILL.md\` | None |
175
+ | 2 | Generate specifications | \`.github/skills/qa-spec-generation/SKILL.md\` | 00-inventory.md exists |
176
+ | 3 | Generate test plan | \`.github/skills/qa-test-plan/SKILL.md\` | 05-test-scenarios.md exists |
177
+ | 4 | Generate test cases | \`.github/skills/qa-test-cases/SKILL.md\` | Test plan exists |
178
+ | 5 | Generate automation | \`.github/skills/qa-automation/SKILL.md\` | Specs approved, no PENDING-CODE |
179
+ | 5b | Stabilize failing tests | \`.github/skills/qa-test-stabilization/SKILL.md\` | Failing tests exist |
180
+ | 6 | Maintenance | \`.github/skills/qa-maintenance/SKILL.md\` | Application change delivered |
181
+ | — | ADO integration | \`.github/skills/qa-ado-integration/SKILL.md\` | ADO enabled in config |
182
+
183
+ ## Project KB
184
+ 1. \`qa/README.md\` — The Living Index: module status, sprint history, blockers, quick-start commands.
185
+ 2. \`qa/memory/INDEX.md\` — Index of all memory files; load this before selecting which files to read.
186
+ `;
187
+ }