@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.
- package/adapters/typescript.sh +87 -10
- package/gate-3.sh +1 -1
- package/hooks/adapter-common.sh +13 -18
- package/hooks/pre-commit +166 -27
- package/hooks/pre-push +231 -18
- package/lib/__tests__/sprint-discovery.test.ts +5 -4
- package/lib/__tests__/sprint-status.test.ts +5 -4
- package/lib/__tests__/tsconfig.json +8 -0
- package/lib/init.js +24 -0
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- package/package.json +1 -1
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
- package/principles/AGENTS.md +3 -3
- package/principles/__tests__/baseline-storage.test.ts +3 -2
- package/principles/__tests__/baseline.test.ts +16 -14
- package/principles/__tests__/types.test.ts +1 -0
- package/principles/adapters/__tests__/base.test.ts +8 -8
- package/principles/adapters/__tests__/cpp.test.ts +26 -26
- package/principles/adapters/__tests__/dart.test.ts +11 -11
- package/principles/adapters/__tests__/go.test.ts +9 -9
- package/principles/adapters/__tests__/java.test.ts +9 -9
- package/principles/adapters/__tests__/kotlin.test.ts +10 -10
- package/principles/adapters/__tests__/objectivec.test.ts +27 -27
- package/principles/adapters/__tests__/python.test.ts +11 -11
- package/principles/adapters/__tests__/swift.test.ts +9 -9
- package/principles/adapters/__tests__/typescript.test.ts +13 -13
- package/principles/rules/__tests__/clean-code/large-file.test.ts +4 -3
- package/skills/delphi-review/AGENTS.md +3 -3
- package/skills/sprint-flow/AGENTS.md +3 -3
- 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': '
|
|
51
|
-
{'id': '
|
|
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': '
|
|
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
|
|
167
|
+
echo "❌ BLOCKED - Gate MS: Sprint Flow Enforcement"
|
|
165
168
|
exit 1
|
|
166
169
|
fi
|
|
167
170
|
else
|
|
168
|
-
echo "⏭️ SKIPPED - Gate
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 -
|
|
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
|
-
|
|
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
|
|
289
|
-
expect(duplicates[0].worktreeExists).toBe(true
|
|
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
|
|
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
|
-
|
|
105
|
-
expect(
|
|
106
|
-
expect(
|
|
107
|
-
expect(
|
|
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
|
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
|
|
package/mock-policy/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MOCK-POLICY KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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.
|
package/mutation/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MUTATION KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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": "xp-gate",
|
|
3
|
-
"version": "0.12.
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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.
|
|
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:**
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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:**
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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:**
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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.
|
package/principles/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# PRINCIPLES CHECKER MODULE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-06
|
|
4
|
+
**Commit:** 132a12e
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
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
|
-
|
|
158
|
-
expect(
|
|
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 () => {
|