@boyingliu01/xp-gate 0.12.10 → 0.12.12

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 (42) hide show
  1. package/adapters/typescript.sh +87 -10
  2. package/gate-3.sh +1 -1
  3. package/hooks/adapter-common.sh +13 -18
  4. package/hooks/pre-commit +166 -27
  5. package/hooks/pre-push +231 -18
  6. package/lib/__tests__/sprint-discovery.test.ts +5 -4
  7. package/lib/__tests__/sprint-status.test.ts +5 -4
  8. package/lib/__tests__/tsconfig.json +8 -0
  9. package/lib/init.js +24 -0
  10. package/mock-policy/AGENTS.md +3 -3
  11. package/mutation/AGENTS.md +3 -3
  12. package/package.json +1 -1
  13. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  14. package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
  15. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  16. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  17. package/plugins/opencode/package.json +1 -1
  18. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  19. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  20. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  21. package/plugins/qoder/plugin.json +1 -1
  22. package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
  23. package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
  24. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
  25. package/principles/AGENTS.md +3 -3
  26. package/principles/__tests__/baseline-storage.test.ts +3 -2
  27. package/principles/__tests__/baseline.test.ts +16 -14
  28. package/principles/__tests__/types.test.ts +1 -0
  29. package/principles/adapters/__tests__/base.test.ts +8 -8
  30. package/principles/adapters/__tests__/cpp.test.ts +26 -26
  31. package/principles/adapters/__tests__/dart.test.ts +11 -11
  32. package/principles/adapters/__tests__/go.test.ts +9 -9
  33. package/principles/adapters/__tests__/java.test.ts +9 -9
  34. package/principles/adapters/__tests__/kotlin.test.ts +10 -10
  35. package/principles/adapters/__tests__/objectivec.test.ts +27 -27
  36. package/principles/adapters/__tests__/python.test.ts +11 -11
  37. package/principles/adapters/__tests__/swift.test.ts +9 -9
  38. package/principles/adapters/__tests__/typescript.test.ts +13 -13
  39. package/principles/rules/__tests__/clean-code/large-file.test.ts +4 -3
  40. package/skills/delphi-review/AGENTS.md +3 -3
  41. package/skills/sprint-flow/AGENTS.md +3 -3
  42. package/skills/test-specification-alignment/AGENTS.md +3 -3
package/hooks/pre-push CHANGED
@@ -47,10 +47,13 @@ report = {
47
47
  {'id': '10', 'name': 'Build Integrity', 'status': '${GATE_10_STATUS:-SKIP}', 'details': {}},
48
48
  {'id': 'M', 'name': 'Mutation Testing', 'status': '${GATE_M_STATUS:-SKIP}', 'details': {}},
49
49
  {'id': 'M-Python', 'name': 'Mutation Testing (Python)', 'status': '${GATE_M_PYTHON_STATUS:-SKIP}', 'details': {}},
50
- {'id': 'M2', 'name': 'Mock Density', 'status': '${GATE_M2_STATUS:-SKIP}', 'details': {}},
51
- {'id': 'M3', 'name': 'Mock Layering', 'status': '${GATE_M3_STATUS:-SKIP}', 'details': {}},
50
+ {'id': 'M-Go', 'name': 'Mutation Testing (Go)', 'status': '${GATE_M_GO_STATUS:-SKIP}', 'details': {}},
51
+ {'id': 'M-Java', 'name': 'Mutation Testing (Java)', 'status': '${GATE_M_JAVA_STATUS:-SKIP}', 'details': {}},
52
+ {'id': 'M-Kotlin', 'name': 'Mutation Testing (Kotlin)', 'status': '${GATE_M_KOTLIN_STATUS:-SKIP}', 'details': {}},
53
+ {'id': 'MD', 'name': 'Mock Density', 'status': '${GATE_M2_STATUS:-SKIP}', 'details': {}},
54
+ {'id': 'ML', 'name': 'Mock Layering', 'status': '${GATE_M3_STATUS:-SKIP}', 'details': {}},
52
55
  {'id': 'UI', 'name': 'UI Sprint Gates', 'status': '${GATE_UI_STATUS:-SKIP}', 'details': {}},
53
- {'id': 'Delphi', 'name': 'Code Walkthrough', 'status': '${GATE_DELPHI_STATUS:-SKIP}', 'details': {'remote': '$REMOTE', 'url': '$URL'}}
56
+ {'id': 'MW', 'name': 'Code Walkthrough', 'status': '${GATE_DELPHI_STATUS:-SKIP}', 'details': {'remote': '$REMOTE', 'url': '$URL'}}
54
57
  ],
55
58
  'warnings': [],
56
59
  'errors': [] if '$verdict' == 'PASS' else ['pre-push hook exited with code $exit_code'],
@@ -161,11 +164,11 @@ fi
161
164
  if [ -n "$SPRINT_GATE_SCRIPT" ]; then
162
165
  if ! bash "$SPRINT_GATE_SCRIPT" --pre-push; then
163
166
  GATE_S_STATUS="BLOCK"
164
- echo "❌ BLOCKED - Gate S: Sprint Flow Enforcement"
167
+ echo "❌ BLOCKED - Gate MS: Sprint Flow Enforcement"
165
168
  exit 1
166
169
  fi
167
170
  else
168
- echo "⏭️ SKIPPED - Gate S: Sprint Flow (sprint-gate.sh not found)"
171
+ echo "⏭️ SKIPPED - Gate MS: Sprint Flow (sprint-gate.sh not found)"
169
172
  GATE_S_STATUS="SKIP"
170
173
  fi
171
174
  echo ""
@@ -390,13 +393,223 @@ else
390
393
  fi
391
394
 
392
395
  # ============================================================================
393
- # GATE M2: MOCK DENSITY CHECK (BLOCK at 30%, configurable via .mockpolicyrc)
396
+ # GATE M (Go): Incremental Mutation Testing via gomutants
397
+ # Uses the same gate-m.ts orchestrator with GoMutantsRunner.
398
+ # ============================================================================
399
+ echo ""
400
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
401
+ echo " GATE M (Go): MUTATION TESTING"
402
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
403
+
404
+ # Collect changed Go source files (exclude tests, vendor)
405
+ GO_FILES=$(echo "$PUSHED_FILES" | grep -E '\.go$' | grep -v '_test\.go$' | grep -v '/vendor/' || true)
406
+
407
+ if [ -z "$GO_FILES" ]; then
408
+ echo "📚 No changed Go source files. SKIP — Gate M (Go)."
409
+ else
410
+ GO_FILE_LIST=$(echo "$GO_FILES" | tr '\n' ',' | sed 's/,$//')
411
+ echo "🔵 Changed Go files: $GO_FILE_LIST"
412
+
413
+ if detect_go_mutation_testable 2>/dev/null; then
414
+ MUTATION_SCRIPT=""
415
+ if [ -f ".xp-gate/modules/mutation/gate-m.ts" ]; then
416
+ MUTATION_SCRIPT=".xp-gate/modules/mutation/gate-m.ts"
417
+ elif [ -f "src/mutation/gate-m.ts" ]; then
418
+ MUTATION_SCRIPT="src/mutation/gate-m.ts"
419
+ elif [ -f "$HOME/.config/xp-gate/modules/mutation/gate-m.ts" ]; then
420
+ MUTATION_SCRIPT="$HOME/.config/xp-gate/modules/mutation/gate-m.ts"
421
+ fi
422
+
423
+ if [ -z "$MUTATION_SCRIPT" ]; then
424
+ echo "⚠ Gate M script not found. SKIP — Gate M (Go)."
425
+ else
426
+ MUTATION_OUTPUT=$(mktemp)
427
+ timeout 120s npx tsx "$MUTATION_SCRIPT" --changed-files "$GO_FILE_LIST" --timeout-ms 120000 > "$MUTATION_OUTPUT" 2>&1
428
+ MUTATION_EXIT=$?
429
+
430
+ case $MUTATION_EXIT in
431
+ 0)
432
+ echo "✅ Gate M (Go): PASS"
433
+ GATE_M_GO_STATUS="PASS"
434
+ ;;
435
+ 1)
436
+ echo ""
437
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
438
+ echo " ❌ GATE M (Go) FAILED - PUSH BLOCKED"
439
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
440
+ echo ""
441
+ cat "$MUTATION_OUTPUT"
442
+ echo ""
443
+ rm -f "$MUTATION_OUTPUT"
444
+ exit 1
445
+ ;;
446
+ 124)
447
+ cat "$MUTATION_OUTPUT"
448
+ echo "⏱ Gate M (Go): TIMEOUT (120s). Allowing push with warning."
449
+ GATE_M_GO_STATUS="TIMEOUT"
450
+ ;;
451
+ *)
452
+ cat "$MUTATION_OUTPUT"
453
+ echo "⚠ Gate M (Go): Unexpected exit code $MUTATION_EXIT. Allowing push with warning."
454
+ GATE_M_GO_STATUS="WARN"
455
+ ;;
456
+ esac
457
+
458
+ rm -f "$MUTATION_OUTPUT"
459
+ fi
460
+ else
461
+ echo "⚠ gomutants not installed. SKIP — Gate M (Go)."
462
+ fi
463
+ fi
464
+
465
+ # ============================================================================
466
+ # GATE M (Java): Incremental Mutation Testing via PITest
467
+ # Uses the same gate-m.ts orchestrator with PitestRunner.
468
+ # ============================================================================
469
+ echo ""
470
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
471
+ echo " GATE M (Java): MUTATION TESTING"
472
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
473
+
474
+ # Collect changed Java source files (exclude tests)
475
+ JAVA_FILES=$(echo "$PUSHED_FILES" | grep -E '\.java$' | grep -v -E '(Test|Tests)\.java$' || true)
476
+
477
+ if [ -z "$JAVA_FILES" ]; then
478
+ echo "📚 No changed Java source files. SKIP — Gate M (Java)."
479
+ else
480
+ JAVA_FILE_LIST=$(echo "$JAVA_FILES" | tr '\n' ',' | sed 's/,$//')
481
+ echo "☕ Changed Java files: $JAVA_FILE_LIST"
482
+
483
+ if detect_pitest_testable 2>/dev/null; then
484
+ MUTATION_SCRIPT=""
485
+ if [ -f ".xp-gate/modules/mutation/gate-m.ts" ]; then
486
+ MUTATION_SCRIPT=".xp-gate/modules/mutation/gate-m.ts"
487
+ elif [ -f "src/mutation/gate-m.ts" ]; then
488
+ MUTATION_SCRIPT="src/mutation/gate-m.ts"
489
+ elif [ -f "$HOME/.config/xp-gate/modules/mutation/gate-m.ts" ]; then
490
+ MUTATION_SCRIPT="$HOME/.config/xp-gate/modules/mutation/gate-m.ts"
491
+ fi
492
+
493
+ if [ -z "$MUTATION_SCRIPT" ]; then
494
+ echo "⚠ Gate M script not found. SKIP — Gate M (Java)."
495
+ else
496
+ MUTATION_OUTPUT=$(mktemp)
497
+ timeout 600s npx tsx "$MUTATION_SCRIPT" --changed-files "$JAVA_FILE_LIST" --timeout-ms 600000 > "$MUTATION_OUTPUT" 2>&1
498
+ MUTATION_EXIT=$?
499
+
500
+ case $MUTATION_EXIT in
501
+ 0)
502
+ echo "✅ Gate M (Java): PASS"
503
+ GATE_M_JAVA_STATUS="PASS"
504
+ ;;
505
+ 1)
506
+ echo ""
507
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
508
+ echo " ❌ GATE M (Java) FAILED - PUSH BLOCKED"
509
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
510
+ echo ""
511
+ cat "$MUTATION_OUTPUT"
512
+ echo ""
513
+ rm -f "$MUTATION_OUTPUT"
514
+ exit 1
515
+ ;;
516
+ 124)
517
+ cat "$MUTATION_OUTPUT"
518
+ echo "⏱ Gate M (Java): TIMEOUT (600s). Allowing push with warning."
519
+ GATE_M_JAVA_STATUS="TIMEOUT"
520
+ ;;
521
+ *)
522
+ cat "$MUTATION_OUTPUT"
523
+ echo "⚠ Gate M (Java): Unexpected exit code $MUTATION_EXIT. Allowing push with warning."
524
+ GATE_M_JAVA_STATUS="WARN"
525
+ ;;
526
+ esac
527
+
528
+ rm -f "$MUTATION_OUTPUT"
529
+ fi
530
+ else
531
+ echo "⚠ PITest not configured. SKIP — Gate M (Java)."
532
+ fi
533
+ fi
534
+
535
+ # ============================================================================
536
+ # GATE M (Kotlin): Incremental Mutation Testing via PITest
537
+ # Uses the same gate-m.ts orchestrator with PitestRunner for Kotlin files.
538
+ # ============================================================================
539
+ echo ""
540
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
541
+ echo " GATE M (Kotlin): MUTATION TESTING"
542
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
543
+
544
+ # Collect changed Kotlin source files (exclude tests)
545
+ KT_FILES=$(echo "$PUSHED_FILES" | grep -E '\.kt$|\.kts$' | grep -v -E '(Test|Tests|Spec)\.kt$' || true)
546
+
547
+ if [ -z "$KT_FILES" ]; then
548
+ echo "📚 No changed Kotlin source files. SKIP — Gate M (Kotlin)."
549
+ else
550
+ KT_FILE_LIST=$(echo "$KT_FILES" | tr '\n' ',' | sed 's/,$//')
551
+ echo "🟣 Changed Kotlin files: $KT_FILE_LIST"
552
+
553
+ if detect_pitest_testable 2>/dev/null; then
554
+ MUTATION_SCRIPT=""
555
+ if [ -f ".xp-gate/modules/mutation/gate-m.ts" ]; then
556
+ MUTATION_SCRIPT=".xp-gate/modules/mutation/gate-m.ts"
557
+ elif [ -f "src/mutation/gate-m.ts" ]; then
558
+ MUTATION_SCRIPT="src/mutation/gate-m.ts"
559
+ elif [ -f "$HOME/.config/xp-gate/modules/mutation/gate-m.ts" ]; then
560
+ MUTATION_SCRIPT="$HOME/.config/xp-gate/modules/mutation/gate-m.ts"
561
+ fi
562
+
563
+ if [ -z "$MUTATION_SCRIPT" ]; then
564
+ echo "⚠ Gate M script not found. SKIP — Gate M (Kotlin)."
565
+ else
566
+ MUTATION_OUTPUT=$(mktemp)
567
+ timeout 600s npx tsx "$MUTATION_SCRIPT" --changed-files "$KT_FILE_LIST" --timeout-ms 600000 > "$MUTATION_OUTPUT" 2>&1
568
+ MUTATION_EXIT=$?
569
+
570
+ case $MUTATION_EXIT in
571
+ 0)
572
+ echo "✅ Gate M (Kotlin): PASS"
573
+ GATE_M_KOTLIN_STATUS="PASS"
574
+ ;;
575
+ 1)
576
+ echo ""
577
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
578
+ echo " ❌ GATE M (Kotlin) FAILED - PUSH BLOCKED"
579
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
580
+ echo ""
581
+ cat "$MUTATION_OUTPUT"
582
+ echo ""
583
+ rm -f "$MUTATION_OUTPUT"
584
+ exit 1
585
+ ;;
586
+ 124)
587
+ cat "$MUTATION_OUTPUT"
588
+ echo "⏱ Gate M (Kotlin): TIMEOUT (600s). Allowing push with warning."
589
+ GATE_M_KOTLIN_STATUS="TIMEOUT"
590
+ ;;
591
+ *)
592
+ cat "$MUTATION_OUTPUT"
593
+ echo "⚠ Gate M (Kotlin): Unexpected exit code $MUTATION_EXIT. Allowing push with warning."
594
+ GATE_M_KOTLIN_STATUS="WARN"
595
+ ;;
596
+ esac
597
+
598
+ rm -f "$MUTATION_OUTPUT"
599
+ fi
600
+ else
601
+ echo "⚠ PITest not configured. SKIP — Gate M (Kotlin)."
602
+ fi
603
+ fi
604
+
605
+ # ============================================================================
606
+ # GATE MD: MOCK DENSITY CHECK (BLOCK at 30%, configurable via .mockpolicyrc)
394
607
  # Phase 1: WARNING mode (collect false positive data before enabling BLOCK)
395
608
  # Per-layer thresholds: .mockpolicyrc layers.*.maxMockDensity
396
609
  # ============================================================================
397
610
  echo ""
398
611
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
399
- echo " GATE M2: MOCK DENSITY CHECK"
612
+ echo " GATE MD: MOCK DENSITY CHECK"
400
613
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
401
614
 
402
615
  # Collect TS and Python test files from pushed files
@@ -486,7 +699,7 @@ else
486
699
  fi
487
700
 
488
701
  # ============================================================================
489
- # Gate M3: Mock Layering Strategy
702
+ # Gate ML: Mock Layering Strategy
490
703
  # Validates mock policies based on test layer and dependency scope
491
704
  # Runs only in non-main branches, TypeScript projects with the module available
492
705
  # ============================================================================
@@ -496,7 +709,7 @@ run_gate_m3() {
496
709
 
497
710
  echo ""
498
711
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
499
- echo " GATE M3: MOCK LAYERING STRATEGY"
712
+ echo " GATE ML: MOCK LAYERING STRATEGY"
500
713
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
501
714
 
502
715
  # Skip on main/master
@@ -540,14 +753,14 @@ run_gate_m3() {
540
753
  done <<< "$test_files"
541
754
 
542
755
  if npx tsx "$GATE_M3_SCRIPT" "${args[@]}"; then
543
- echo "✅ Gate M3: PASS"
756
+ echo "✅ Gate ML: PASS"
544
757
  return 0
545
758
  else
546
759
  local exit_code=$?
547
760
  if [[ "$exit_code" -eq 1 ]]; then
548
761
  echo ""
549
762
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
550
- echo " ❌ GATE M3 FAILED - PUSH BLOCKED"
763
+ echo " ❌ GATE ML FAILED - PUSH BLOCKED"
551
764
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
552
765
  echo ""
553
766
  echo "Mock layering violations found. Review and fix or adjust"
@@ -555,7 +768,7 @@ run_gate_m3() {
555
768
  echo ""
556
769
  return 1
557
770
  fi
558
- echo "⚠️ Gate M3: Unexpected error — allowing push with warning"
771
+ echo "⚠️ Gate ML: Unexpected error — allowing push with warning"
559
772
  return 0
560
773
  fi
561
774
  }
@@ -638,19 +851,19 @@ else
638
851
  fi
639
852
 
640
853
  # ============================================================================
641
- # VALIDATE CODE WALKTHROUGH RESULT FILE
854
+ # GATE MW: VALIDATE CODE WALKTHROUGH RESULT FILE
642
855
  # ============================================================================
643
856
  RESULT_FILE=".code-walkthrough-result.json"
644
857
 
645
- # Skip Delphi walkthrough for main/master (Gate M already ran above)
858
+ # Skip MW walkthrough for main/master (Gate M already ran above)
646
859
  if [[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]]; then
647
- echo "⚠️ Pushing to main/master - Delphi walkthrough skipped"
860
+ echo "⚠️ Pushing to main/master - MW walkthrough skipped"
648
861
  else
649
862
 
650
863
  if [ ! -f "$RESULT_FILE" ]; then
651
864
  echo ""
652
865
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
653
- echo " ❌ CODE WALKTHROUGH REQUIRED - PUSH BLOCKED"
866
+ echo " ❌ GATE MW: CODE WALKTHROUGH REQUIRED - PUSH BLOCKED"
654
867
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
655
868
  echo ""
656
869
  echo "No code walkthrough result found."
@@ -745,7 +958,7 @@ fi
745
958
  if [ "$RESULT_VERDICT" != "APPROVED" ]; then
746
959
  echo ""
747
960
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
748
- echo " ❌ CODE WALKTHROUGH NOT APPROVED - PUSH BLOCKED"
961
+ echo " ❌ GATE MW: CODE WALKTHROUGH NOT APPROVED - PUSH BLOCKED"
749
962
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
750
963
  echo ""
751
964
  echo "Verdict: $RESULT_VERDICT"
@@ -785,7 +998,7 @@ fi
785
998
  # ============================================================================
786
999
  echo ""
787
1000
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
788
- echo " ✅ CODE WALKTHROUGH VERIFIED"
1001
+ echo " ✅ GATE MW: CODE WALKTHROUGH VERIFIED"
789
1002
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
790
1003
  echo ""
791
1004
  echo "Branch: $CURRENT_BRANCH"
@@ -13,7 +13,8 @@ import os from 'os';
13
13
 
14
14
  // Types mirroring DiscoveredSprint interface
15
15
  interface DiscoveredSprint {
16
- state: Record<string, unknown>;
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ state: any;
17
18
  sourcePath: string;
18
19
  worktreeExists: boolean;
19
20
  }
@@ -285,8 +286,8 @@ describe('sprint-discovery: discoverActiveSprints', () => {
285
286
  });
286
287
  const results = sprintDiscovery.discoverActiveSprints(TMP_ROOT);
287
288
  const duplicates = results.filter(r => r.state.id === 'sprint-2026-06-23-01');
288
- expect(duplicates.length).toBe(1, 'Should deduplicate to exactly 1 entry');
289
- expect(duplicates[0].worktreeExists).toBe(true, 'Should prefer worktree version');
289
+ expect(duplicates.length).toBe(1);
290
+ expect(duplicates[0].worktreeExists).toBe(true);
290
291
  });
291
292
 
292
293
  test('tie-breaker: latest started_at wins when same sprint.id in two worktrees', () => {
@@ -324,7 +325,7 @@ describe('sprint-discovery: discoverActiveSprints', () => {
324
325
  // Should not throw, result should be skipped (no valid id)
325
326
  const results = sprintDiscovery.discoverActiveSprints(TMP_ROOT);
326
327
  const partials = results.filter(r => r.state.task_description === 'Partial fields only');
327
- expect(partials.length).toBe(0, 'Sprint without id should be skipped');
328
+ expect(partials.length).toBe(0);
328
329
  });
329
330
 
330
331
  test('handles EACCES on .sprint-state/ directory gracefully', () => {
@@ -101,10 +101,11 @@ describe('sprint-status: readSprintState', () => {
101
101
  writeState(ACTIVE_STATE);
102
102
  const state = sprintStatus!.readSprintState(TMP_DIR);
103
103
  expect(state).not.toBeNull();
104
- expect(state?.task_description).toBe('Test sprint');
105
- expect(state?.phase).toBe(2);
106
- expect(state?.status).toBe('running');
107
- expect(Array.isArray(state?.phase_history)).toBe(true);
104
+ const stateObj = state as Record<string, unknown>;
105
+ expect(stateObj.task_description).toBe('Test sprint');
106
+ expect(stateObj.phase).toBe(2);
107
+ expect(stateObj.status).toBe('running');
108
+ expect(Array.isArray(stateObj.phase_history)).toBe(true);
108
109
  });
109
110
 
110
111
  // AC-SPRINTSTATUS-001-02: No active sprint
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "checkJs": false,
6
+ "types": ["node", "vitest/globals"]
7
+ }
8
+ }
package/lib/init.js CHANGED
@@ -384,6 +384,20 @@ async function installLocal(args) {
384
384
 
385
385
  console.log('\nInstallation complete!');
386
386
  console.log('Run git commit to trigger quality gates');
387
+ console.log('');
388
+ console.log('━━━ FIRST-CLASS TEST QUALITY ━━━');
389
+ console.log('XP-Gate treats test code as a first-class citizen:');
390
+ console.log(' • TypeScript: test files are type-checked, not excluded from tsconfig.json');
391
+ console.log(' • Static analysis: lint/ESLint/Biome check test files alongside source');
392
+ console.log(' • Complexity: cyclomatic complexity is measured on test files too');
393
+ console.log(' • Duplicate code: jscpd scans test files (fixtures/snapshots excluded)');
394
+ console.log(' • Architecture: archlint validates test code structure');
395
+ console.log('');
396
+ console.log(' To include tests in your project:');
397
+ console.log(' 1. Remove __tests__/ from tsconfig.json exclude');
398
+ console.log(' 2. Remove __tests__/ from jscpd.conf.json ignore');
399
+ console.log(' 3. Add tsconfig.json: "types": ["vitest/globals"]');
400
+ console.log(' 4. Run "xp-gate doctor" to verify setup');
387
401
  return 0;
388
402
  }
389
403
 
@@ -441,6 +455,16 @@ async function setupGlobal(args) {
441
455
  console.log('\nGlobal setup complete!');
442
456
  console.log('All git repositories will now use xp-gate quality gates.');
443
457
  console.log('Per-project adapters can still override by creating <repo>/githooks/');
458
+ console.log('');
459
+ console.log('━━━ FIRST-CLASS TEST QUALITY ━━━');
460
+ console.log('XP-Gate treats test code as a first-class citizen:');
461
+ console.log(' All quality gates apply equally to test files.');
462
+ console.log(' To include tests in your project:');
463
+ console.log(' 1. Remove __tests__/ from tsconfig.json exclude');
464
+ console.log(' 2. Remove __tests__/ from jscpd.conf.json ignore');
465
+ console.log(' 3. Remove test patterns from .archlint.yaml ignore');
466
+ console.log(' 4. Add "types": ["vitest/globals"] to tsconfig.json');
467
+ console.log(' 5. Run "xp-gate doctor" to verify');
444
468
  return 0;
445
469
  }
446
470
 
@@ -1,9 +1,9 @@
1
1
  # SRC/MOCK-POLICY KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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.12.10",
3
+ "version": "0.12.12",
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.12.10",
3
+ "version": "0.12.12",
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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → SHIP → LAND → USER ACCEPTANCE → FEEDBACK → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: 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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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.12.10",
3
+ "version": "0.12.12",
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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → SHIP → LAND → USER ACCEPTANCE → FEEDBACK → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: 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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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.12.10",
3
+ "version": "0.12.12",
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-06
4
- **Commit:** 2c7cde4
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.10.0
6
+ **Version:** 0.12.12.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-06
4
- **Commit:** 2c7cde4
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.10.0
6
+ **Version:** 0.12.12.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → USER ACCEPTANCE → FEEDBACK → SHIP → LAND → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: 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-06
4
- **Commit:** 2c7cde4
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.10.0
6
+ **Version:** 0.12.12.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
- **Generated:** 2026-07-03
4
- **Commit:** c3ed581
3
+ **Generated:** 2026-07-06
4
+ **Commit:** 132a12e
5
5
  **Branch:** main
6
- **Version:** 0.12.4.0
6
+ **Version:** 0.12.12.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.
@@ -154,8 +154,9 @@ describe('Baseline Storage', () => {
154
154
  expect(stats.totalFiles).toBe(2);
155
155
  expect(stats.totalWarnings).toBe(7);
156
156
  expect(stats.averageWarningsPerFile).toBe(3.5);
157
- expect(stats.eslint?.totalWarnings).toBe(6);
158
- expect(stats.eslint?.totalErrors).toBe(1);
157
+ const richStats = stats as { totalFiles: number; totalWarnings: number; averageWarningsPerFile: number; eslint: { totalWarnings: number; totalErrors: number } };
158
+ expect(richStats.eslint.totalWarnings).toBe(6);
159
+ expect(richStats.eslint.totalErrors).toBe(1);
159
160
  });
160
161
 
161
162
  it('creates baseline from files with warning data', async () => {