@boyingliu01/xp-gate 0.12.10 → 0.12.13
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/iac.sh +51 -24
- package/adapters/typescript.sh +87 -10
- package/bin/xp-gate.js +2 -2
- 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 +97 -3
- 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 +3 -3
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
- 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
|
@@ -279,13 +279,75 @@ function printCliToolStatus() {
|
|
|
279
279
|
console.log(`CLI tools: ${available.length}/${GATE_CLI_TOOLS.length} available`);
|
|
280
280
|
if (missing.length > 0) {
|
|
281
281
|
console.log(` Missing: ${missing.join(', ')}`);
|
|
282
|
-
console.log(' Quality gates using these tools will silently SKIP until they are installed
|
|
283
|
-
console.log(` Run 'xp-gate bootstrap' to install all missing tools, or 'xp-gate doctor' for details.\n`);
|
|
282
|
+
console.log(' Quality gates using these tools will silently SKIP until they are installed.\n');
|
|
284
283
|
} else {
|
|
285
284
|
console.log('');
|
|
286
285
|
}
|
|
287
286
|
}
|
|
288
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Ask the user for confirmation via stdin.
|
|
290
|
+
* @param {string} question - The yes/no question to display
|
|
291
|
+
* @returns {Promise<boolean>} true if user answered yes
|
|
292
|
+
*/
|
|
293
|
+
function askYesNo(question) {
|
|
294
|
+
return new Promise((resolve) => {
|
|
295
|
+
const rl = require('readline').createInterface({
|
|
296
|
+
input: process.stdin,
|
|
297
|
+
output: process.stdout,
|
|
298
|
+
});
|
|
299
|
+
rl.question(`${question} (Y/n) `, (answer) => {
|
|
300
|
+
rl.close();
|
|
301
|
+
const normalized = answer.trim().toLowerCase();
|
|
302
|
+
// Empty (just Enter) or y/yes → yes; anything else → no
|
|
303
|
+
resolve(normalized === '' || normalized === 'y' || normalized === 'yes');
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Prompt the user to auto-install missing CLI quality-gate tools.
|
|
310
|
+
* Called after installation completes. Interactive only when TTY is available.
|
|
311
|
+
* Skips silently when no tools are missing.
|
|
312
|
+
*
|
|
313
|
+
* @param {boolean} autoYes - If true, skip prompt and auto-install
|
|
314
|
+
* @returns {Promise<number>} 0 on success or skipped, 1 on failure
|
|
315
|
+
*/
|
|
316
|
+
async function promptBootstrap(autoYes) {
|
|
317
|
+
const { bootstrap } = require('./bootstrap.js');
|
|
318
|
+
|
|
319
|
+
// Check what's missing without printing a full header
|
|
320
|
+
const missing = [];
|
|
321
|
+
for (const entry of GATE_CLI_TOOLS) {
|
|
322
|
+
const result = checkCliTool(entry.tool);
|
|
323
|
+
if (!result.available) {
|
|
324
|
+
missing.push(entry.tool);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (missing.length === 0) return 0;
|
|
329
|
+
|
|
330
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
331
|
+
console.log(' Quality Gate CLI Tools');
|
|
332
|
+
console.log('');
|
|
333
|
+
console.log(` ${missing.length} tool(s) required by quality gates are not installed:`);
|
|
334
|
+
for (const tool of missing) {
|
|
335
|
+
console.log(` ✗ ${tool}`);
|
|
336
|
+
}
|
|
337
|
+
console.log('');
|
|
338
|
+
console.log(' Without these tools, the corresponding quality gates will');
|
|
339
|
+
console.log(' silently SKIP during git commits — you may miss issues.');
|
|
340
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
341
|
+
|
|
342
|
+
if (autoYes || (process.stdin.isTTY && await askYesNo('\nInstall missing tools now?'))) {
|
|
343
|
+
console.log('');
|
|
344
|
+
return bootstrap([]);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
console.log('\n Skipped. Run "xp-gate bootstrap" later to install them.');
|
|
348
|
+
return 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
289
351
|
async function init(args) {
|
|
290
352
|
console.log('XP-Gate Initialization');
|
|
291
353
|
console.log('====================\n');
|
|
@@ -384,6 +446,23 @@ async function installLocal(args) {
|
|
|
384
446
|
|
|
385
447
|
console.log('\nInstallation complete!');
|
|
386
448
|
console.log('Run git commit to trigger quality gates');
|
|
449
|
+
|
|
450
|
+
// Auto-install missing CLI tools (prompt user)
|
|
451
|
+
const autoYes = args.includes('--yes') || args.includes('--auto-install');
|
|
452
|
+
await promptBootstrap(autoYes);
|
|
453
|
+
console.log('━━━ FIRST-CLASS TEST QUALITY ━━━');
|
|
454
|
+
console.log('XP-Gate treats test code as a first-class citizen:');
|
|
455
|
+
console.log(' • TypeScript: test files are type-checked, not excluded from tsconfig.json');
|
|
456
|
+
console.log(' • Static analysis: lint/ESLint/Biome check test files alongside source');
|
|
457
|
+
console.log(' • Complexity: cyclomatic complexity is measured on test files too');
|
|
458
|
+
console.log(' • Duplicate code: jscpd scans test files (fixtures/snapshots excluded)');
|
|
459
|
+
console.log(' • Architecture: archlint validates test code structure');
|
|
460
|
+
console.log('');
|
|
461
|
+
console.log(' To include tests in your project:');
|
|
462
|
+
console.log(' 1. Remove __tests__/ from tsconfig.json exclude');
|
|
463
|
+
console.log(' 2. Remove __tests__/ from jscpd.conf.json ignore');
|
|
464
|
+
console.log(' 3. Add tsconfig.json: "types": ["vitest/globals"]');
|
|
465
|
+
console.log(' 4. Run "xp-gate doctor" to verify setup');
|
|
387
466
|
return 0;
|
|
388
467
|
}
|
|
389
468
|
|
|
@@ -441,6 +520,21 @@ async function setupGlobal(args) {
|
|
|
441
520
|
console.log('\nGlobal setup complete!');
|
|
442
521
|
console.log('All git repositories will now use xp-gate quality gates.');
|
|
443
522
|
console.log('Per-project adapters can still override by creating <repo>/githooks/');
|
|
523
|
+
|
|
524
|
+
// Auto-install missing CLI tools (prompt user)
|
|
525
|
+
const autoYes = args.includes('--yes') || args.includes('--auto-install');
|
|
526
|
+
await promptBootstrap(autoYes);
|
|
527
|
+
|
|
528
|
+
console.log('');
|
|
529
|
+
console.log('━━━ FIRST-CLASS TEST QUALITY ━━━');
|
|
530
|
+
console.log('XP-Gate treats test code as a first-class citizen:');
|
|
531
|
+
console.log(' All quality gates apply equally to test files.');
|
|
532
|
+
console.log(' To include tests in your project:');
|
|
533
|
+
console.log(' 1. Remove __tests__/ from tsconfig.json exclude');
|
|
534
|
+
console.log(' 2. Remove __tests__/ from jscpd.conf.json ignore');
|
|
535
|
+
console.log(' 3. Remove test patterns from .archlint.yaml ignore');
|
|
536
|
+
console.log(' 4. Add "types": ["vitest/globals"] to tsconfig.json');
|
|
537
|
+
console.log(' 5. Run "xp-gate doctor" to verify');
|
|
444
538
|
return 0;
|
|
445
539
|
}
|
|
446
540
|
|
|
@@ -532,4 +626,4 @@ function injectKarpathyPrinciples(projectRoot) {
|
|
|
532
626
|
}
|
|
533
627
|
}
|
|
534
628
|
|
|
535
|
-
module.exports = { init };
|
|
629
|
+
module.exports = { init, promptBootstrap };
|
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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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.13",
|
|
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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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-07
|
|
4
|
+
**Commit:** 897f8eb
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.13.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.
|