@boyingliu01/xp-gate 0.13.0 → 0.13.2

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/hooks/pre-commit CHANGED
@@ -1453,6 +1453,7 @@ else
1453
1453
  # No test files AND no source files changed → skip
1454
1454
  echo "✅ PASSED - No test or source files changed, skipping test run."
1455
1455
  TESTS_EXIT_CODE=0
1456
+ TESTS_SKIPPED=true
1456
1457
  fi
1457
1458
  else
1458
1459
  # Fallback: run_tests without coverage
@@ -1496,8 +1497,11 @@ else
1496
1497
  # Smart selection (Issue #286): only runs changed/related tests with --coverage,
1497
1498
  # producing coverage/coverage-summary.json for the tested subset.
1498
1499
  # Stage 2 enforcement reads global coverage from the subset run.
1499
- # If no tests were run (TESTS_EXIT_CODE=0 skip path), warn instead of blocking.
1500
- if [ -f "coverage/coverage-summary.json" ]; then
1500
+ # If no tests were run (TESTS_SKIPPED=true), skip coverage check entirely.
1501
+ if [ "${TESTS_SKIPPED:-false}" = "true" ]; then
1502
+ echo "ℹ️ Test run was skipped — skipping coverage check."
1503
+ COV_EXIT=0
1504
+ elif [ -f "coverage/coverage-summary.json" ]; then
1501
1505
  echo "TypeScript coverage collected during test run."
1502
1506
  COV_EXIT=0
1503
1507
  else
@@ -1566,7 +1570,9 @@ else
1566
1570
  case "$PROJECT_LANG" in
1567
1571
  "typescript")
1568
1572
  COVERAGE_ENFORCED=true
1569
- if [ -f "coverage/coverage-summary.json" ]; then
1573
+ if [ "${TESTS_SKIPPED:-false}" = "true" ]; then
1574
+ echo "✅ PASSED - Coverage check skipped (no test/source files changed)."
1575
+ elif [ -f "coverage/coverage-summary.json" ]; then
1570
1576
  COVERAGE_PERCENT=$(node -e "
1571
1577
  try {
1572
1578
  const fs = require('fs');
@@ -410,4 +410,141 @@ describe('detect-deps', () => {
410
410
  vi.restoreAllMocks();
411
411
  });
412
412
  });
413
+
414
+ // ── checkCliTool tests (Issue #299 — Windows cross-platform) ──
415
+
416
+ describe('checkCliTool', () => {
417
+ const { execSync: realExecSync } = require('child_process');
418
+
419
+ afterEach(() => {
420
+ vi.restoreAllMocks();
421
+ });
422
+
423
+ it('returns available:true when which finds the tool and --version succeeds', () => {
424
+ vi.spyOn(require('child_process'), 'execSync')
425
+ .mockReturnValueOnce('/usr/local/bin/jscpd\n')
426
+ .mockReturnValueOnce('cpd 5.0.11\n');
427
+
428
+ const { checkCliTool } = require('../detect-deps');
429
+ const result = checkCliTool('jscpd');
430
+
431
+ expect(result.available).toBe(true);
432
+ expect(result.path).toBe('/usr/local/bin/jscpd');
433
+ expect(result.version).toBe('cpd 5.0.11');
434
+ });
435
+
436
+ it('returns available:false when which and direct exec both fail', () => {
437
+ vi.spyOn(require('child_process'), 'execSync')
438
+ .mockImplementation(() => { throw new Error('not found'); });
439
+
440
+ const { checkCliTool } = require('../detect-deps');
441
+ const result = checkCliTool('nonexistent-tool');
442
+
443
+ expect(result.available).toBe(false);
444
+ });
445
+
446
+ it('falls through to direct exec when which returns empty', () => {
447
+ vi.spyOn(require('child_process'), 'execSync')
448
+ .mockReturnValueOnce('')
449
+ .mockReturnValueOnce('1.21.3\n');
450
+
451
+ const { checkCliTool } = require('../detect-deps');
452
+ const result = checkCliTool('lizard');
453
+
454
+ expect(result.available).toBe(true);
455
+ expect(result.path).toBe('lizard');
456
+ expect(result.version).toBe('1.21.3');
457
+ });
458
+
459
+ it('uses where on win32 instead of which', () => {
460
+ const originalPlatform = process.platform;
461
+ Object.defineProperty(process, 'platform', { value: 'win32' });
462
+
463
+ const execSpy = vi.spyOn(require('child_process'), 'execSync')
464
+ .mockReturnValueOnce('C:\\Users\\test\\AppData\\Roaming\\npm\\jscpd.cmd\r\n')
465
+ .mockReturnValueOnce('cpd 5.0.11\n');
466
+
467
+ const { checkCliTool } = require('../detect-deps');
468
+ const result = checkCliTool('jscpd');
469
+
470
+ expect(result.available).toBe(true);
471
+ expect(execSpy.mock.calls[0][0]).toMatch(/^where jscpd/);
472
+ expect(execSpy.mock.calls[0][1].shell).toBe('cmd.exe');
473
+
474
+ Object.defineProperty(process, 'platform', { value: originalPlatform });
475
+ });
476
+
477
+ it('uses 2>nul on win32 instead of 2>/dev/null', () => {
478
+ const originalPlatform = process.platform;
479
+ Object.defineProperty(process, 'platform', { value: 'win32' });
480
+
481
+ const execSpy = vi.spyOn(require('child_process'), 'execSync')
482
+ .mockImplementation(() => { throw new Error('not found'); });
483
+
484
+ const { checkCliTool } = require('../detect-deps');
485
+ checkCliTool('jscpd');
486
+
487
+ const versionCallArgs = execSpy.mock.calls.map(c => c[0]);
488
+ const hasUnixRedir = versionCallArgs.some(cmd => typeof cmd === 'string' && cmd.includes('2>/dev/null'));
489
+ expect(hasUnixRedir).toBe(false);
490
+
491
+ Object.defineProperty(process, 'platform', { value: originalPlatform });
492
+ });
493
+
494
+ it('uses 2>/dev/null on linux (not 2>nul)', () => {
495
+ const originalPlatform = process.platform;
496
+ Object.defineProperty(process, 'platform', { value: 'linux' });
497
+
498
+ const execSpy = vi.spyOn(require('child_process'), 'execSync')
499
+ .mockImplementation(() => { throw new Error('not found'); });
500
+
501
+ const { checkCliTool } = require('../detect-deps');
502
+ checkCliTool('jscpd');
503
+
504
+ const versionCallArgs = execSpy.mock.calls.map(c => c[0]);
505
+ const hasWindowsRedir = versionCallArgs.some(cmd => typeof cmd === 'string' && cmd.includes('2>nul'));
506
+ expect(hasWindowsRedir).toBe(false);
507
+
508
+ Object.defineProperty(process, 'platform', { value: originalPlatform });
509
+ });
510
+
511
+ it('explicitly sets shell option for cross-platform consistency', () => {
512
+ const execSpy = vi.spyOn(require('child_process'), 'execSync')
513
+ .mockImplementation(() => { throw new Error('not found'); });
514
+
515
+ const { checkCliTool } = require('../detect-deps');
516
+ checkCliTool('jscpd');
517
+
518
+ for (const call of execSpy.mock.calls) {
519
+ expect(call[1].shell).toBeDefined();
520
+ }
521
+ });
522
+
523
+ it('sets timeout to 15000ms for version checks (Python cold start)', () => {
524
+ const execSpy = vi.spyOn(require('child_process'), 'execSync')
525
+ .mockImplementation(() => { throw new Error('not found'); });
526
+
527
+ const { checkCliTool } = require('../detect-deps');
528
+ checkCliTool('checkov');
529
+
530
+ const locatorCalls = execSpy.mock.calls.filter(c => c[1].timeout === 15000);
531
+ expect(locatorCalls.length).toBeGreaterThan(0);
532
+ });
533
+
534
+ it('checks ~/.local/bin fallback path when tool not in PATH', () => {
535
+ vi.spyOn(require('child_process'), 'execSync')
536
+ .mockImplementation(() => { throw new Error('not found'); });
537
+ vi.spyOn(fs, 'existsSync').mockReturnValue(true);
538
+ vi.spyOn(require('child_process'), 'execSync')
539
+ .mockImplementationOnce(() => { throw new Error('which: not found'); })
540
+ .mockImplementationOnce(() => { throw new Error('direct exec: not found'); })
541
+ .mockReturnValueOnce('hadolint 2.14.0\n');
542
+
543
+ const { checkCliTool } = require('../detect-deps');
544
+ const result = checkCliTool('hadolint');
545
+
546
+ expect(result.available).toBe(true);
547
+ expect(result.path).toContain('.local');
548
+ });
549
+ });
413
550
  });
@@ -107,39 +107,99 @@ const GATE_CLI_TOOLS = [
107
107
  ];
108
108
 
109
109
  /**
110
- * Check if a CLI tool is available.
111
- * Tries the tool name directly, then checks ~/.local/bin/ as fallback.
110
+ * Check if a CLI tool is available in PATH.
111
+ * Cross-platform: uses `where` on Windows, `which` on Unix as primary detection,
112
+ * then falls back to direct `--version` invocation with platform-appropriate
113
+ * stderr redirection.
112
114
  *
115
+ * @covers Issue #299 — Windows false negatives from 2>/dev/null + missing shell
113
116
  * @param {string} toolName
114
117
  * @returns {{available: boolean, path?: string, version?: string}}
115
118
  */
116
119
  function checkCliTool(toolName) {
120
+ const isWindows = process.platform === 'win32';
121
+ const shell = isWindows ? 'cmd.exe' : '/bin/sh';
122
+ const nullRedir = isWindows ? '2>nul' : '2>/dev/null';
123
+ const execOpts = { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], shell, timeout: 15000 };
124
+
125
+ // Step 1: Locate tool in PATH using platform-native resolver
126
+ // `where` (Windows) / `which` (Unix) — more reliable than exec-based detection
117
127
  try {
118
- const result = execSync(`${toolName} --version 2>/dev/null || ${toolName} -v 2>/dev/null`, {
119
- encoding: 'utf8',
120
- stdio: ['ignore', 'pipe', 'pipe'],
128
+ const locator = isWindows ? 'where' : 'which';
129
+ const locatorResult = execSync(`${locator} ${toolName}`, {
130
+ ...execOpts,
121
131
  timeout: 5000,
122
132
  });
133
+ const resolvedPath = locatorResult.trim().split('\n')[0].trim();
134
+ if (resolvedPath) {
135
+ // Step 2: Get version from the located tool
136
+ const version = getVersion(resolvedPath, execOpts, nullRedir);
137
+ return { available: true, path: resolvedPath, version };
138
+ }
139
+ } catch { /* not in PATH, continue to fallback */ }
140
+
141
+ // Step 3: Direct exec fallback (handles edge cases where which/where misses)
142
+ try {
143
+ const result = execSync(
144
+ `${toolName} --version ${nullRedir} || ${toolName} -v ${nullRedir}`,
145
+ execOpts,
146
+ );
123
147
  if (result.trim()) {
124
148
  return { available: true, path: toolName, version: result.trim().split('\n')[0] };
125
149
  }
126
150
  } catch { /* not in PATH, continue to fallback */ }
127
151
 
128
- const localPath = path.join(os.homedir(), '.local', 'bin', toolName);
129
- if (fs.existsSync(localPath)) {
152
+ // Step 4: Check well-known local paths
153
+ const localPaths = getLocalFallbackPaths(toolName, isWindows);
154
+ for (const localPath of localPaths) {
155
+ if (!fs.existsSync(localPath)) continue;
130
156
  try {
131
- const result = execSync(`"${localPath}" --version 2>/dev/null || "${localPath}" -v 2>/dev/null`, {
132
- encoding: 'utf8',
133
- stdio: ['ignore', 'pipe', 'pipe'],
134
- timeout: 5000,
135
- });
136
- return { available: true, path: localPath, version: result.trim().split('\n')[0] };
157
+ const version = getVersion(`"${localPath}"`, execOpts, nullRedir);
158
+ return { available: true, path: localPath, version };
137
159
  } catch { /* path exists but can't execute */ }
138
160
  }
139
161
 
140
162
  return { available: false };
141
163
  }
142
164
 
165
+ function getVersion(execPath, execOpts, nullRedir) {
166
+ try {
167
+ const result = execSync(
168
+ `${execPath} --version ${nullRedir} || ${execPath} -v ${nullRedir}`,
169
+ execOpts,
170
+ );
171
+ return result.trim().split('\n')[0] || undefined;
172
+ } catch {
173
+ return undefined;
174
+ }
175
+ }
176
+
177
+ function getLocalFallbackPaths(toolName, isWindows) {
178
+ const home = os.homedir();
179
+ const paths = [path.join(home, '.local', 'bin', toolName)];
180
+
181
+ if (isWindows) {
182
+ const appData = process.env.APPDATA || path.join(home, 'AppData', 'Roaming');
183
+ const localAppData = process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
184
+ paths.push(
185
+ path.join(appData, 'npm', `${toolName}.cmd`),
186
+ path.join(home, '.local', 'bin', `${toolName}.exe`),
187
+ );
188
+ const pythonBase = path.join(localAppData, 'Programs', 'Python');
189
+ if (fs.existsSync(pythonBase)) {
190
+ try {
191
+ for (const entry of fs.readdirSync(pythonBase)) {
192
+ if (entry.startsWith('Python')) {
193
+ paths.push(path.join(pythonBase, entry, 'Scripts', `${toolName}.exe`));
194
+ }
195
+ }
196
+ } catch { /* readdir failed, skip */ }
197
+ }
198
+ }
199
+
200
+ return paths;
201
+ }
202
+
143
203
  /**
144
204
  * Get install instructions for a CLI tool on the current platform.
145
205
  *
@@ -1,9 +1,9 @@
1
1
  # SRC/MOCK-POLICY KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Mock layering policy enforcement — Gate M3 of pre-push hook. Ensures integration tests use real implementations for internal dependencies, mock external dependencies, and annotate pending mocks with removal plans. Combines project scope scanning, mock decision engine, and per-file validation into a single pipeline.
@@ -1,9 +1,9 @@
1
1
  # SRC/MUTATION KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **Gate M** (incremental mutation testing) + **Gate M2** helpers (test-layer detection used by `src/mock-policy/`). Pre-push quality gate. TypeScript-only; uses Stryker.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boyingliu01/xp-gate",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "AI-driven development workflow: 6 quality gates + Delphi review + Sprint Flow",
5
5
  "bin": {
6
6
  "xp-gate": "./bin/xp-gate.js"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xp-gate",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "displayName": "XP-Gate",
5
5
  "description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 10 quality gates (Gate 0-9), Sprint Flow (11 phases), and Delphi multi-expert review (>=90% consensus).",
6
6
  "author": {
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -9,7 +9,7 @@ const path = require('path');
9
9
 
10
10
  const SKILL_MD_PATH = path.join(__dirname, '..', 'SKILL.md');
11
11
  const REFERENCES_DIR = path.join(__dirname, '..', 'references');
12
- const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-2-build.md');
12
+ const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-3-build.md');
13
13
  const ORCHESTRATION_RULES_PATH = path.join(REFERENCES_DIR, 'orchestration-rules.md');
14
14
 
15
15
  let skillContent = '';
@@ -139,13 +139,12 @@ function testNegativeTestCasesExist() {
139
139
  function testWorkflowStepsOrder() {
140
140
  const frontmatter = parseFrontmatter(skillContent);
141
141
  const steps = frontmatter.workflow_steps || [];
142
- if (steps.length !== 11) {
143
- throw new Error(`workflow_steps must have exactly 11 entries, got ${steps.length}`);
142
+ if (steps.length !== 6) {
143
+ throw new Error(`workflow_steps must have exactly 6 entries, got ${steps.length}`);
144
144
  }
145
145
 
146
146
  const expectedOrder = [
147
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
148
- 'REVIEW', 'FEEDBACK', 'SHIP', 'LAND', 'USER ACCEPTANCE', 'CLEANUP',
147
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
149
148
  ];
150
149
 
151
150
  for (let i = 0; i < expectedOrder.length; i++) {
@@ -155,29 +154,29 @@ function testWorkflowStepsOrder() {
155
154
  );
156
155
  }
157
156
  }
158
- console.log(' ✓ workflow_steps order matches canonical 11-phase sequence');
157
+ console.log(' ✓ workflow_steps order matches canonical 6-phase sequence');
159
158
  }
160
159
 
161
160
  function testPhaseFlowDiagramOrder() {
162
- // The Phase Flow diagram in the body must show: ISOLATE → ... → FEEDBACK → SHIP → LAND → USER ACCEPTANCE → CLEANUP
163
- const flowMatch = skillContent.match(/ISOLATE →.*CLEANUP/);
161
+ // The Phase Flow diagram in the body must show: PREP → ... → SHIP → CLOSE
162
+ const flowMatch = skillContent.match(/PREP →.*CLOSE/);
164
163
  if (!flowMatch) {
165
164
  throw new Error('Phase Flow diagram not found in SKILL.md body');
166
165
  }
167
166
  const flow = flowMatch[0];
168
167
 
169
- // Verify FEEDBACK comes before SHIP (not after USER ACCEPTANCE)
170
- const feedbackPos = flow.indexOf('FEEDBACK');
168
+ // Verify VERIFY comes before SHIP
169
+ const verifyPos = flow.indexOf('VERIFY');
171
170
  const shipPos = flow.indexOf('SHIP');
172
- const userAcceptPos = flow.indexOf('USER ACCEPT');
173
- if (feedbackPos === -1 || shipPos === -1 || userAcceptPos === -1) {
171
+ const closePos = flow.indexOf('CLOSE');
172
+ if (verifyPos === -1 || shipPos === -1 || closePos === -1) {
174
173
  throw new Error('Phase Flow diagram missing required phases');
175
174
  }
176
- if (feedbackPos > shipPos) {
177
- throw new Error('FEEDBACK must come before SHIP in phase flow diagram');
175
+ if (verifyPos > shipPos) {
176
+ throw new Error('VERIFY must come before SHIP in phase flow diagram');
178
177
  }
179
- if (shipPos > userAcceptPos) {
180
- throw new Error('SHIP must come before USER ACCEPTANCE in phase flow diagram');
178
+ if (shipPos > closePos) {
179
+ throw new Error('SHIP must come before CLOSE in phase flow diagram');
181
180
  }
182
181
  console.log(' ✓ Phase Flow diagram has correct ordering');
183
182
  }
@@ -199,15 +198,14 @@ function testCanonicalPhaseOrderTableExists() {
199
198
  function testAll11PhasesInPhaseFlowConsistency() {
200
199
  const section = skillContent.split('Phase Flow Consistency')[1];
201
200
  const requiredPhases = [
202
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
203
- 'REVIEW', 'FEEDBACK', 'SHIP', 'LAND', 'USER ACCEPTANCE', 'CLEANUP',
201
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
204
202
  ];
205
203
  for (const phase of requiredPhases) {
206
204
  if (!section.includes(phase)) {
207
205
  throw new Error(`Phase Flow Consistency section missing phase: ${phase}`);
208
206
  }
209
207
  }
210
- console.log(' ✓ All 11 phases referenced in Phase Flow Consistency section');
208
+ console.log(' ✓ All 6 phases referenced in Phase Flow Consistency section');
211
209
  }
212
210
 
213
211
  // === Force Levels Tests ===
@@ -272,9 +270,9 @@ function testUvpMentionsEmergentRequirements() {
272
270
  function testTimingSectionExists() {
273
271
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
274
272
  if (!phase2BuildContent.includes('Timing & Stability')) {
275
- throw new Error('phase-2-build.md must contain "Timing & Stability" section');
273
+ throw new Error('phase-3-build.md must contain "Timing & Stability" section');
276
274
  }
277
- console.log(' ✓ Timing & Stability section exists in phase-2-build.md');
275
+ console.log(' ✓ Timing & Stability section exists in phase-3-build.md');
278
276
  }
279
277
 
280
278
  function testTimeoutRecommendationsExist() {
@@ -289,7 +287,7 @@ function testTimeoutRecommendationsExist() {
289
287
  function testExecutionTimeEstimatesExist() {
290
288
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
291
289
  if (!phase2BuildContent.includes('Expected Time')) {
292
- throw new Error('phase-2-build.md must include expected execution time estimates');
290
+ throw new Error('phase-3-build.md must include expected execution time estimates');
293
291
  }
294
292
  console.log(' ✓ Expected execution time estimates exist');
295
293
  }
@@ -305,12 +303,8 @@ function testOrchestrationRulesExists() {
305
303
 
306
304
  function testPhaseSubagentMatrixOrder() {
307
305
  const orchContent = fs.readFileSync(ORCHESTRATION_RULES_PATH, 'utf-8');
308
- const expectedOrder = [
309
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
310
- 'REVIEW', 'USER ACCEPT', 'FEEDBACK', 'SHIP', 'LAND', 'CLEANUP',
311
- ];
312
306
  // The matrix order reflects file names, but phases should all be present
313
- for (const phase of ['ISOLATE', 'THINK', 'PLAN', 'BUILD', 'REVIEW', 'CLEANUP']) {
307
+ for (const phase of ['PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE']) {
314
308
  if (!orchContent.includes(phase)) {
315
309
  throw new Error(`orchestration-rules.md missing phase: ${phase}`);
316
310
  }
@@ -336,7 +330,7 @@ function runTests(opts = {}) {
336
330
  { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
337
331
  { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
338
332
  { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
339
- { name: 'All 11 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
333
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
340
334
  { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
341
335
  { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
342
336
  { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
@@ -378,7 +372,7 @@ function runTests(opts = {}) {
378
372
  function testUncommittedGateExists() {
379
373
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
380
374
  if (!phase2BuildContent.includes('Uncommitted Changes Gate')) {
381
- throw new Error('phase-2-build.md must contain "Uncommitted Changes Gate" section');
375
+ throw new Error('phase-3-build.md must contain "Uncommitted Changes Gate" section');
382
376
  }
383
377
  console.log(' ✓ Uncommitted Changes Gate section exists');
384
378
  }
@@ -419,7 +413,7 @@ describe('sprint-flow SKILL.md', () => {
419
413
  { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
420
414
  { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
421
415
  { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
422
- { name: 'All 11 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
416
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
423
417
  { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
424
418
  { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
425
419
  { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boyingliu01/opencode-plugin",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "description": "XP-Gate quality gates + AI workflow skills + Sprint Flow TUI sidebar for OpenCode",
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -9,7 +9,7 @@ const path = require('path');
9
9
 
10
10
  const SKILL_MD_PATH = path.join(__dirname, '..', 'SKILL.md');
11
11
  const REFERENCES_DIR = path.join(__dirname, '..', 'references');
12
- const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-2-build.md');
12
+ const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-3-build.md');
13
13
  const ORCHESTRATION_RULES_PATH = path.join(REFERENCES_DIR, 'orchestration-rules.md');
14
14
 
15
15
  let skillContent = '';
@@ -139,13 +139,12 @@ function testNegativeTestCasesExist() {
139
139
  function testWorkflowStepsOrder() {
140
140
  const frontmatter = parseFrontmatter(skillContent);
141
141
  const steps = frontmatter.workflow_steps || [];
142
- if (steps.length !== 11) {
143
- throw new Error(`workflow_steps must have exactly 11 entries, got ${steps.length}`);
142
+ if (steps.length !== 6) {
143
+ throw new Error(`workflow_steps must have exactly 6 entries, got ${steps.length}`);
144
144
  }
145
145
 
146
146
  const expectedOrder = [
147
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
148
- 'REVIEW', 'FEEDBACK', 'SHIP', 'LAND', 'USER ACCEPTANCE', 'CLEANUP',
147
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
149
148
  ];
150
149
 
151
150
  for (let i = 0; i < expectedOrder.length; i++) {
@@ -155,29 +154,29 @@ function testWorkflowStepsOrder() {
155
154
  );
156
155
  }
157
156
  }
158
- console.log(' ✓ workflow_steps order matches canonical 11-phase sequence');
157
+ console.log(' ✓ workflow_steps order matches canonical 6-phase sequence');
159
158
  }
160
159
 
161
160
  function testPhaseFlowDiagramOrder() {
162
- // The Phase Flow diagram in the body must show: ISOLATE → ... → FEEDBACK → SHIP → LAND → USER ACCEPTANCE → CLEANUP
163
- const flowMatch = skillContent.match(/ISOLATE →.*CLEANUP/);
161
+ // The Phase Flow diagram in the body must show: PREP → ... → SHIP → CLOSE
162
+ const flowMatch = skillContent.match(/PREP →.*CLOSE/);
164
163
  if (!flowMatch) {
165
164
  throw new Error('Phase Flow diagram not found in SKILL.md body');
166
165
  }
167
166
  const flow = flowMatch[0];
168
167
 
169
- // Verify FEEDBACK comes before SHIP (not after USER ACCEPTANCE)
170
- const feedbackPos = flow.indexOf('FEEDBACK');
168
+ // Verify VERIFY comes before SHIP
169
+ const verifyPos = flow.indexOf('VERIFY');
171
170
  const shipPos = flow.indexOf('SHIP');
172
- const userAcceptPos = flow.indexOf('USER ACCEPT');
173
- if (feedbackPos === -1 || shipPos === -1 || userAcceptPos === -1) {
171
+ const closePos = flow.indexOf('CLOSE');
172
+ if (verifyPos === -1 || shipPos === -1 || closePos === -1) {
174
173
  throw new Error('Phase Flow diagram missing required phases');
175
174
  }
176
- if (feedbackPos > shipPos) {
177
- throw new Error('FEEDBACK must come before SHIP in phase flow diagram');
175
+ if (verifyPos > shipPos) {
176
+ throw new Error('VERIFY must come before SHIP in phase flow diagram');
178
177
  }
179
- if (shipPos > userAcceptPos) {
180
- throw new Error('SHIP must come before USER ACCEPTANCE in phase flow diagram');
178
+ if (shipPos > closePos) {
179
+ throw new Error('SHIP must come before CLOSE in phase flow diagram');
181
180
  }
182
181
  console.log(' ✓ Phase Flow diagram has correct ordering');
183
182
  }
@@ -199,15 +198,14 @@ function testCanonicalPhaseOrderTableExists() {
199
198
  function testAll11PhasesInPhaseFlowConsistency() {
200
199
  const section = skillContent.split('Phase Flow Consistency')[1];
201
200
  const requiredPhases = [
202
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
203
- 'REVIEW', 'FEEDBACK', 'SHIP', 'LAND', 'USER ACCEPTANCE', 'CLEANUP',
201
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
204
202
  ];
205
203
  for (const phase of requiredPhases) {
206
204
  if (!section.includes(phase)) {
207
205
  throw new Error(`Phase Flow Consistency section missing phase: ${phase}`);
208
206
  }
209
207
  }
210
- console.log(' ✓ All 11 phases referenced in Phase Flow Consistency section');
208
+ console.log(' ✓ All 6 phases referenced in Phase Flow Consistency section');
211
209
  }
212
210
 
213
211
  // === Force Levels Tests ===
@@ -272,9 +270,9 @@ function testUvpMentionsEmergentRequirements() {
272
270
  function testTimingSectionExists() {
273
271
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
274
272
  if (!phase2BuildContent.includes('Timing & Stability')) {
275
- throw new Error('phase-2-build.md must contain "Timing & Stability" section');
273
+ throw new Error('phase-3-build.md must contain "Timing & Stability" section');
276
274
  }
277
- console.log(' ✓ Timing & Stability section exists in phase-2-build.md');
275
+ console.log(' ✓ Timing & Stability section exists in phase-3-build.md');
278
276
  }
279
277
 
280
278
  function testTimeoutRecommendationsExist() {
@@ -289,7 +287,7 @@ function testTimeoutRecommendationsExist() {
289
287
  function testExecutionTimeEstimatesExist() {
290
288
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
291
289
  if (!phase2BuildContent.includes('Expected Time')) {
292
- throw new Error('phase-2-build.md must include expected execution time estimates');
290
+ throw new Error('phase-3-build.md must include expected execution time estimates');
293
291
  }
294
292
  console.log(' ✓ Expected execution time estimates exist');
295
293
  }
@@ -305,12 +303,8 @@ function testOrchestrationRulesExists() {
305
303
 
306
304
  function testPhaseSubagentMatrixOrder() {
307
305
  const orchContent = fs.readFileSync(ORCHESTRATION_RULES_PATH, 'utf-8');
308
- const expectedOrder = [
309
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
310
- 'REVIEW', 'USER ACCEPT', 'FEEDBACK', 'SHIP', 'LAND', 'CLEANUP',
311
- ];
312
306
  // The matrix order reflects file names, but phases should all be present
313
- for (const phase of ['ISOLATE', 'THINK', 'PLAN', 'BUILD', 'REVIEW', 'CLEANUP']) {
307
+ for (const phase of ['PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE']) {
314
308
  if (!orchContent.includes(phase)) {
315
309
  throw new Error(`orchestration-rules.md missing phase: ${phase}`);
316
310
  }
@@ -336,7 +330,7 @@ function runTests(opts = {}) {
336
330
  { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
337
331
  { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
338
332
  { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
339
- { name: 'All 11 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
333
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
340
334
  { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
341
335
  { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
342
336
  { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
@@ -378,7 +372,7 @@ function runTests(opts = {}) {
378
372
  function testUncommittedGateExists() {
379
373
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
380
374
  if (!phase2BuildContent.includes('Uncommitted Changes Gate')) {
381
- throw new Error('phase-2-build.md must contain "Uncommitted Changes Gate" section');
375
+ throw new Error('phase-3-build.md must contain "Uncommitted Changes Gate" section');
382
376
  }
383
377
  console.log(' ✓ Uncommitted Changes Gate section exists');
384
378
  }
@@ -419,7 +413,7 @@ describe('sprint-flow SKILL.md', () => {
419
413
  { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
420
414
  { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
421
415
  { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
422
- { name: 'All 11 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
416
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
423
417
  { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
424
418
  { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
425
419
  { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xp-gate",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "displayName": "XP-Gate",
5
5
  "description": "Extreme Programming quality gates + AI workflow skills for Qoder. Includes 10 quality gates (Gate 0-9), Sprint Flow (11 phases), and Delphi multi-expert review (>=90% consensus).",
6
6
  "author": {
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
@@ -1,9 +1,9 @@
1
1
  # PRINCIPLES CHECKER MODULE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Clean Code & SOLID principles checker — **Gate 4** of pre-commit. 14 rules × 9 language adapters, SARIF 2.1.0 output. Houses the **Boy Scout Rule** enforcement engine (Gate 6) and warning-baseline storage.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -9,7 +9,7 @@ const path = require('path');
9
9
 
10
10
  const SKILL_MD_PATH = path.join(__dirname, '..', 'SKILL.md');
11
11
  const REFERENCES_DIR = path.join(__dirname, '..', 'references');
12
- const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-2-build.md');
12
+ const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-3-build.md');
13
13
  const ORCHESTRATION_RULES_PATH = path.join(REFERENCES_DIR, 'orchestration-rules.md');
14
14
 
15
15
  let skillContent = '';
@@ -139,13 +139,12 @@ function testNegativeTestCasesExist() {
139
139
  function testWorkflowStepsOrder() {
140
140
  const frontmatter = parseFrontmatter(skillContent);
141
141
  const steps = frontmatter.workflow_steps || [];
142
- if (steps.length !== 11) {
143
- throw new Error(`workflow_steps must have exactly 11 entries, got ${steps.length}`);
142
+ if (steps.length !== 6) {
143
+ throw new Error(`workflow_steps must have exactly 6 entries, got ${steps.length}`);
144
144
  }
145
145
 
146
146
  const expectedOrder = [
147
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
148
- 'REVIEW', 'FEEDBACK', 'SHIP', 'LAND', 'USER ACCEPTANCE', 'CLEANUP',
147
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
149
148
  ];
150
149
 
151
150
  for (let i = 0; i < expectedOrder.length; i++) {
@@ -155,29 +154,29 @@ function testWorkflowStepsOrder() {
155
154
  );
156
155
  }
157
156
  }
158
- console.log(' ✓ workflow_steps order matches canonical 11-phase sequence');
157
+ console.log(' ✓ workflow_steps order matches canonical 6-phase sequence');
159
158
  }
160
159
 
161
160
  function testPhaseFlowDiagramOrder() {
162
- // The Phase Flow diagram in the body must show: ISOLATE → ... → FEEDBACK → SHIP → LAND → USER ACCEPTANCE → CLEANUP
163
- const flowMatch = skillContent.match(/ISOLATE →.*CLEANUP/);
161
+ // The Phase Flow diagram in the body must show: PREP → ... → SHIP → CLOSE
162
+ const flowMatch = skillContent.match(/PREP →.*CLOSE/);
164
163
  if (!flowMatch) {
165
164
  throw new Error('Phase Flow diagram not found in SKILL.md body');
166
165
  }
167
166
  const flow = flowMatch[0];
168
167
 
169
- // Verify FEEDBACK comes before SHIP (not after USER ACCEPTANCE)
170
- const feedbackPos = flow.indexOf('FEEDBACK');
168
+ // Verify VERIFY comes before SHIP
169
+ const verifyPos = flow.indexOf('VERIFY');
171
170
  const shipPos = flow.indexOf('SHIP');
172
- const userAcceptPos = flow.indexOf('USER ACCEPT');
173
- if (feedbackPos === -1 || shipPos === -1 || userAcceptPos === -1) {
171
+ const closePos = flow.indexOf('CLOSE');
172
+ if (verifyPos === -1 || shipPos === -1 || closePos === -1) {
174
173
  throw new Error('Phase Flow diagram missing required phases');
175
174
  }
176
- if (feedbackPos > shipPos) {
177
- throw new Error('FEEDBACK must come before SHIP in phase flow diagram');
175
+ if (verifyPos > shipPos) {
176
+ throw new Error('VERIFY must come before SHIP in phase flow diagram');
178
177
  }
179
- if (shipPos > userAcceptPos) {
180
- throw new Error('SHIP must come before USER ACCEPTANCE in phase flow diagram');
178
+ if (shipPos > closePos) {
179
+ throw new Error('SHIP must come before CLOSE in phase flow diagram');
181
180
  }
182
181
  console.log(' ✓ Phase Flow diagram has correct ordering');
183
182
  }
@@ -199,15 +198,14 @@ function testCanonicalPhaseOrderTableExists() {
199
198
  function testAll11PhasesInPhaseFlowConsistency() {
200
199
  const section = skillContent.split('Phase Flow Consistency')[1];
201
200
  const requiredPhases = [
202
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
203
- 'REVIEW', 'FEEDBACK', 'SHIP', 'LAND', 'USER ACCEPTANCE', 'CLEANUP',
201
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
204
202
  ];
205
203
  for (const phase of requiredPhases) {
206
204
  if (!section.includes(phase)) {
207
205
  throw new Error(`Phase Flow Consistency section missing phase: ${phase}`);
208
206
  }
209
207
  }
210
- console.log(' ✓ All 11 phases referenced in Phase Flow Consistency section');
208
+ console.log(' ✓ All 6 phases referenced in Phase Flow Consistency section');
211
209
  }
212
210
 
213
211
  // === Force Levels Tests ===
@@ -272,9 +270,9 @@ function testUvpMentionsEmergentRequirements() {
272
270
  function testTimingSectionExists() {
273
271
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
274
272
  if (!phase2BuildContent.includes('Timing & Stability')) {
275
- throw new Error('phase-2-build.md must contain "Timing & Stability" section');
273
+ throw new Error('phase-3-build.md must contain "Timing & Stability" section');
276
274
  }
277
- console.log(' ✓ Timing & Stability section exists in phase-2-build.md');
275
+ console.log(' ✓ Timing & Stability section exists in phase-3-build.md');
278
276
  }
279
277
 
280
278
  function testTimeoutRecommendationsExist() {
@@ -289,7 +287,7 @@ function testTimeoutRecommendationsExist() {
289
287
  function testExecutionTimeEstimatesExist() {
290
288
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
291
289
  if (!phase2BuildContent.includes('Expected Time')) {
292
- throw new Error('phase-2-build.md must include expected execution time estimates');
290
+ throw new Error('phase-3-build.md must include expected execution time estimates');
293
291
  }
294
292
  console.log(' ✓ Expected execution time estimates exist');
295
293
  }
@@ -305,12 +303,8 @@ function testOrchestrationRulesExists() {
305
303
 
306
304
  function testPhaseSubagentMatrixOrder() {
307
305
  const orchContent = fs.readFileSync(ORCHESTRATION_RULES_PATH, 'utf-8');
308
- const expectedOrder = [
309
- 'ISOLATE', 'AUTO-ESTIMATE', 'THINK', 'PLAN', 'BUILD',
310
- 'REVIEW', 'USER ACCEPT', 'FEEDBACK', 'SHIP', 'LAND', 'CLEANUP',
311
- ];
312
306
  // The matrix order reflects file names, but phases should all be present
313
- for (const phase of ['ISOLATE', 'THINK', 'PLAN', 'BUILD', 'REVIEW', 'CLEANUP']) {
307
+ for (const phase of ['PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE']) {
314
308
  if (!orchContent.includes(phase)) {
315
309
  throw new Error(`orchestration-rules.md missing phase: ${phase}`);
316
310
  }
@@ -336,7 +330,7 @@ function runTests(opts = {}) {
336
330
  { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
337
331
  { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
338
332
  { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
339
- { name: 'All 11 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
333
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
340
334
  { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
341
335
  { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
342
336
  { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
@@ -378,7 +372,7 @@ function runTests(opts = {}) {
378
372
  function testUncommittedGateExists() {
379
373
  const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
380
374
  if (!phase2BuildContent.includes('Uncommitted Changes Gate')) {
381
- throw new Error('phase-2-build.md must contain "Uncommitted Changes Gate" section');
375
+ throw new Error('phase-3-build.md must contain "Uncommitted Changes Gate" section');
382
376
  }
383
377
  console.log(' ✓ Uncommitted Changes Gate section exists');
384
378
  }
@@ -419,7 +413,7 @@ describe('sprint-flow SKILL.md', () => {
419
413
  { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
420
414
  { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
421
415
  { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
422
- { name: 'All 11 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
416
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
423
417
  { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
424
418
  { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
425
419
  { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-07-08
4
- **Commit:** 6f868ee
5
- **Branch:** sprint/2026-07-07-01
6
- **Version:** 0.13.0.0
4
+ **Commit:** 509be7b
5
+ **Branch:** main
6
+ **Version:** 0.13.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.