@boyingliu01/xp-gate 0.27.3 → 0.27.5

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 (101) hide show
  1. package/adapter-common.sh +0 -0
  2. package/adapters/cpp.sh +0 -0
  3. package/adapters/dart.sh +0 -0
  4. package/adapters/flutter.sh +0 -0
  5. package/adapters/gate-3.sh +59 -3
  6. package/adapters/gate-4.sh +73 -10
  7. package/adapters/gate-7.sh +4 -0
  8. package/adapters/go.sh +0 -0
  9. package/adapters/iac.sh +0 -0
  10. package/adapters/java.sh +0 -0
  11. package/adapters/kotlin.sh +0 -0
  12. package/adapters/objectivec.sh +0 -0
  13. package/adapters/plugins/book299-20132-python/scripts/install-gradle.sh +0 -0
  14. package/adapters/plugins/book299-20132-python/scripts/install-maven.sh +0 -0
  15. package/adapters/plugins/book299-4081-c/scripts/install-gradle.sh +0 -0
  16. package/adapters/plugins/book299-4081-c/scripts/install-maven.sh +0 -0
  17. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-gradle.sh +0 -0
  18. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-maven.sh +0 -0
  19. package/adapters/powershell.sh +8 -0
  20. package/adapters/python.sh +0 -0
  21. package/adapters/shell.sh +0 -0
  22. package/adapters/swift.sh +0 -0
  23. package/adapters/typescript.sh +0 -0
  24. package/bin/xp-gate.js +0 -0
  25. package/gate-10.sh +11 -0
  26. package/gate-3.sh +8 -0
  27. package/gate-4.sh +8 -0
  28. package/gate-7.sh +4 -0
  29. package/gate-8.sh +0 -0
  30. package/gate-9.sh +0 -0
  31. package/hooks/adapter-common.sh +0 -0
  32. package/hooks/gate-10.sh +11 -0
  33. package/hooks/gate-3.sh +8 -0
  34. package/hooks/gate-4.sh +8 -0
  35. package/hooks/gate-7.sh +4 -0
  36. package/hooks/gate-8.sh +0 -0
  37. package/hooks/gate-9.sh +0 -0
  38. package/hooks/post-merge +0 -0
  39. package/hooks/pre-commit +53 -11
  40. package/hooks/pre-push +0 -0
  41. package/hooks/sprint-gate.sh +0 -0
  42. package/lib/__tests__/doctor-delphi.test.js +293 -244
  43. package/lib/__tests__/sprint-audit.test.js +207 -207
  44. package/lib/doctor.js +46 -3
  45. package/lib/mattpocock-license-verdict.json +1 -1
  46. package/lib/sprint-audit.js +235 -235
  47. package/mock-policy/AGENTS.md +3 -3
  48. package/mutation/AGENTS.md +3 -3
  49. package/package.json +1 -1
  50. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  51. package/plugins/claude-code/bin/delphi-review-guard.sh +0 -0
  52. package/plugins/claude-code/bin/xp-gate-check +0 -0
  53. package/plugins/claude-code/skills/batch-grill-me/SKILL.md +9 -2
  54. package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
  55. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  56. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  57. package/plugins/dsh/package.json +1 -1
  58. package/plugins/dsh/skills/batch-grill-me/SKILL.md +9 -2
  59. package/plugins/dsh/skills/delphi-review/AGENTS.md +3 -3
  60. package/plugins/dsh/skills/sprint-flow/AGENTS.md +3 -3
  61. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +3 -3
  62. package/plugins/dsh/src/delphi-config.ts +15 -2
  63. package/plugins/opencode/package.json +1 -1
  64. package/plugins/opencode/skills/batch-grill-me/SKILL.md +9 -2
  65. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  66. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  67. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  68. package/plugins/qoder/bin/sprint-flow-guard.sh +0 -0
  69. package/plugins/qoder/bin/xp-gate-check +0 -0
  70. package/plugins/qoder/plugin.json +1 -1
  71. package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
  72. package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
  73. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
  74. package/principles/AGENTS.md +3 -3
  75. package/skills/batch-grill-me/SKILL.md +9 -2
  76. package/skills/delphi-review/AGENTS.md +3 -3
  77. package/skills/sprint-flow/AGENTS.md +3 -3
  78. package/skills/test-specification-alignment/AGENTS.md +3 -3
  79. package/sprint-gate.sh +0 -0
  80. package/plugins/dsh/lib/command.d.ts +0 -32
  81. package/plugins/dsh/lib/command.d.ts.map +0 -1
  82. package/plugins/dsh/lib/command.js +0 -81
  83. package/plugins/dsh/lib/delphi-config.d.ts +0 -75
  84. package/plugins/dsh/lib/delphi-config.d.ts.map +0 -1
  85. package/plugins/dsh/lib/delphi-config.js +0 -183
  86. package/plugins/dsh/lib/delphi-run.d.ts +0 -24
  87. package/plugins/dsh/lib/delphi-run.d.ts.map +0 -1
  88. package/plugins/dsh/lib/delphi-run.js +0 -92
  89. package/plugins/dsh/lib/delphi.d.ts +0 -88
  90. package/plugins/dsh/lib/delphi.d.ts.map +0 -1
  91. package/plugins/dsh/lib/delphi.js +0 -161
  92. package/plugins/dsh/lib/dialect.d.ts +0 -24
  93. package/plugins/dsh/lib/dialect.d.ts.map +0 -1
  94. package/plugins/dsh/lib/dialect.js +0 -36
  95. package/plugins/dsh/lib/gate-runner.d.ts +0 -18
  96. package/plugins/dsh/lib/gate-runner.d.ts.map +0 -1
  97. package/plugins/dsh/lib/gate-runner.js +0 -46
  98. package/plugins/dsh/lib/index.d.ts +0 -5
  99. package/plugins/dsh/lib/index.d.ts.map +0 -1
  100. package/plugins/dsh/lib/index.js +0 -162
  101. package/plugins/dsh/node_modules/.vite/vitest/results.json +0 -1
package/hooks/gate-7.sh CHANGED
@@ -10,10 +10,14 @@ GATE_7_START=$(gate_start_ms)
10
10
 
11
11
  # Check if any IaC files are changed
12
12
  IAC_FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null | grep -E "\.(tf|yaml|yml)$|Dockerfile" || true)
13
+ # #536: scanned_files makes a trivial PASS (nothing to scan) auditable in the
14
+ # quality report instead of reading like a covered security check.
15
+ GATE_7_SCANNED_FILES=0
13
16
  if [ -z "$IAC_FILES" ]; then
14
17
  echo "✅ PASSED - No IaC files detected in changes."
15
18
  GATE_7_STATUS="PASS"
16
19
  else
20
+ GATE_7_SCANNED_FILES=$(printf '%s\n' "$IAC_FILES" | sed -n '/./p' | wc -l | tr -d '[:space:]')
17
21
  # Run IaC adapter. Resolution follows the documented 3-tier convention
18
22
  # (adapter-common.sh): global ~/.config/xp-gate/adapters -> project
19
23
  # githooks/adapters -> script dir. The old cwd-only test silently SKIPped
package/hooks/gate-8.sh CHANGED
File without changes
package/hooks/gate-9.sh CHANGED
File without changes
package/hooks/post-merge CHANGED
File without changes
package/hooks/pre-commit CHANGED
@@ -215,34 +215,60 @@ file_exists_in_subdir() {
215
215
  AUDIT_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
216
216
  PROJECT_ROOT_FOR_AUDIT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$AUDIT_SCRIPT_DIR/../..")"
217
217
 
218
+ # Issue #535: a failed `source` used to print one stderr line and keep going,
219
+ # so a missing lib silently removed gate logic from the run while every gate
220
+ # still reported PASS. Fail closed instead: abort with FATAL when the file is
221
+ # absent or its body exits non-zero while being sourced. `exit` inside a
222
+ # sourced file exits the SOURCING shell, so an `if ! source` wrapper cannot
223
+ # catch it — trap EXIT for the duration of the source instead.
224
+ source_gate_lib() {
225
+ local lib_file="$1"
226
+ if [ ! -f "$lib_file" ]; then
227
+ echo "FATAL: cannot load $lib_file (missing)" >&2
228
+ exit 1
229
+ fi
230
+ # Marker the EXIT trap compares against: only a source that never reached
231
+ # its end counts as a load failure. A lib calling `exit` at top level would
232
+ # otherwise be misread as a crash after it already did its job.
233
+ SOURCE_GATE_LIB_COMPLETED=""
234
+ local prev_trap=""
235
+ prev_trap="$(trap -p EXIT || true)"
236
+ # shellcheck disable=SC2064 # expand lib_file NOW: it is the failure target
237
+ trap "[ -n \"\$SOURCE_GATE_LIB_COMPLETED\" ] || { echo 'FATAL: cannot load $lib_file (source failed)' >&2; exit 1; }" EXIT
238
+ # shellcheck disable=SC1090 # sourcing the resolved lib is the contract here
239
+ source "$lib_file"
240
+ SOURCE_GATE_LIB_COMPLETED=1
241
+ eval "$prev_trap"
242
+ }
243
+
218
244
  # Issue #370: source cross-platform now_ms() helper (node-preferred, regex-validated)
219
- source "${AUDIT_SCRIPT_DIR}/lib/now-ms.sh"
245
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/now-ms.sh"
220
246
 
221
247
  # Issue #473 (+ #454): Gate 5's vitest exit-code judgement, sourced as a library
222
248
  # so the fail-closed contract is unit-testable without executing this hook.
223
- source "${AUDIT_SCRIPT_DIR}/lib/test-failure.sh"
249
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/test-failure.sh"
224
250
 
225
251
  # Issue #477: Gate 2's jscpd config probe and outcome classification, same reason.
226
- source "${AUDIT_SCRIPT_DIR}/lib/jscpd-run.sh"
252
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/jscpd-run.sh"
227
253
 
228
254
  # Issue #476: Gate 11's sprint-gate.sh resolution chain and decision translation.
229
- source "${AUDIT_SCRIPT_DIR}/lib/sprint-gate-report.sh"
255
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/sprint-gate-report.sh"
230
256
 
231
257
  # Issue #523: Gate 5's Python coverage parsing and threshold verdict. The old
232
258
  # `grep -o '[0-9]*%'` never matched --format=total's bare number, so the 80%
233
259
  # branch never ran; sourced as a library so the fail-closed contract is
234
260
  # unit-testable without executing this hook.
235
- source "${AUDIT_SCRIPT_DIR}/lib/coverage-total.sh"
261
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/coverage-total.sh"
236
262
 
237
263
  # Issue #399: Python smart test selection — strategy decision + related-test
238
264
  # lookup, kept in a library so the truth table and the path conventions are
239
265
  # unit-testable without executing this hook.
240
- source "${AUDIT_SCRIPT_DIR}/lib/python-test-selection.sh"
266
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/python-test-selection.sh"
241
267
 
242
268
  # Issue #534: incremental Python type-check for the pre-commit python branch —
243
269
  # staged-only mypy (fast) that complements python.sh's CI-aligned full pass.
244
270
  # Kept in a library so the exit-code capture and scope handling are unit-testable.
245
- source "${AUDIT_SCRIPT_DIR}/lib/python-incremental-typecheck.sh"
271
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/python-incremental-typecheck.sh"
246
272
 
247
273
  # Read max_duration_ms from .xp-gate-config.json (default 7200000 = 2 hours)
248
274
  _MAX_DURATION_MS=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('${PROJECT_ROOT_FOR_AUDIT}/.xp-gate-config.json','utf8'));console.log((c.audit&&c.audit.max_duration_ms)||7200000);}catch(e){console.log(7200000);}" 2>/dev/null || echo "7200000")
@@ -1061,7 +1087,7 @@ else
1061
1087
  ; source "${AUDIT_SCRIPT_DIR}/lib/typecheck.sh" && run_typescript_typecheck )
1062
1088
  TS_CHECK_EXIT=$?
1063
1089
  else
1064
- source "${AUDIT_SCRIPT_DIR}/lib/typecheck.sh"
1090
+ source_gate_lib "${AUDIT_SCRIPT_DIR}/lib/typecheck.sh"
1065
1091
  run_typescript_typecheck
1066
1092
  TS_CHECK_EXIT=$?
1067
1093
  fi
@@ -3264,10 +3290,14 @@ if any_changed_files_match "\.(ts|tsx|js|jsx|py|go|java|kt|cpp|c|swift|m|dart|sh
3264
3290
  else
3265
3291
  echo "⏭️ SKIPPED - SAST (gate-10.sh not found)"
3266
3292
  GATE_10_STATUS="SKIP"
3293
+ GATE_10_REASON="gate_script_missing"
3267
3294
  fi
3268
3295
  else
3269
- echo "✅ PASSED - No code files changed, skipping SAST scan."
3270
- GATE_10_STATUS="PASS"
3296
+ echo "⏭️ SKIPPED - No code files changed, skipping SAST scan."
3297
+ # #536: "nothing to scan" is NOT "scanned and clean". Record SKIP with a
3298
+ # reason so the quality report never renders this path as a PASS claim.
3299
+ GATE_10_STATUS="SKIP"
3300
+ GATE_10_REASON="no_code_files_changed"
3271
3301
  fi
3272
3302
  # ============================================================================
3273
3303
 
@@ -3389,6 +3419,11 @@ generate_quality_report() {
3389
3419
  # non-passing gates INSIDE the effective denominator only -- a skipped gate
3390
3420
  # is out of scope, not a failure.
3391
3421
  local gate_status gate_default
3422
+ # #536: a WARN means the check could not run (typically tool_not_installed)
3423
+ # -- degraded coverage, kept in the denominator but flagged separately so a
3424
+ # degraded gate is never confused with a real PASS.
3425
+ local DEGRADED_COUNT=0
3426
+ local DEGRADED_JSON=""
3392
3427
  for gate in 1 2 3 4 5 6 7 8 9 10 11 12; do
3393
3428
  local status_var="GATE_${gate}_STATUS"
3394
3429
  # Default mirrors the JSON report rendering below EXACTLY (gates 1-11
@@ -3401,7 +3436,7 @@ generate_quality_report() {
3401
3436
  case "$gate_status" in
3402
3437
  PASS) PASSED_COUNT=$((PASSED_COUNT + 1)) ;;
3403
3438
  SKIP) SKIP_COUNT=$((SKIP_COUNT + 1)) ;;
3404
- WARN) WARN_COUNT=$((WARN_COUNT + 1)); NONPASS_COUNT=$((NONPASS_COUNT + 1)) ;;
3439
+ WARN) WARN_COUNT=$((WARN_COUNT + 1)); NONPASS_COUNT=$((NONPASS_COUNT + 1)); DEGRADED_COUNT=$((DEGRADED_COUNT + 1)); DEGRADED_JSON="${DEGRADED_JSON:+$DEGRADED_JSON, }\"gate${gate}\"";;
3405
3440
  *) NONPASS_COUNT=$((NONPASS_COUNT + 1)) ;;
3406
3441
  esac
3407
3442
  done
@@ -3480,6 +3515,8 @@ generate_quality_report() {
3480
3515
  "gatesPassed": $PASSED_COUNT,
3481
3516
  "gatesTotal": $TOTAL_GATES,
3482
3517
  "gatesSkipped": $SKIP_COUNT,
3518
+ "gatesDegraded": $DEGRADED_COUNT,
3519
+ "degradedGates": [$DEGRADED_JSON],
3483
3520
  "gatesEffective": $EFFECTIVE_TOTAL,
3484
3521
  "effectivePassRate": $EFFECTIVE_PASS_RATE_JSON,
3485
3522
  "score": $SCORE_JSON,
@@ -3499,6 +3536,7 @@ generate_quality_report() {
3499
3536
  "gate3_complexity": {
3500
3537
  "name": "Cyclomatic Complexity",
3501
3538
  "status": "${GATE_3_STATUS:-PASS}",
3539
+ "reason": "${GATE_3_REASON:-}",
3502
3540
  "threshold": "${CCN_THRESHOLD:-5}",
3503
3541
  "blockThreshold": "${CCN_THRESHOLD:-5}",
3504
3542
  "warnings": ${CC_WARNINGS:-0}
@@ -3506,6 +3544,7 @@ generate_quality_report() {
3506
3544
  "gate4_principles": {
3507
3545
  "name": "Clean Code + SOLID",
3508
3546
  "status": "${GATE_4_STATUS:-PASS}",
3547
+ "reason": "${GATE_4_REASON:-}",
3509
3548
  "warnings": ${WARNING_COUNT:-0}
3510
3549
  },
3511
3550
  "gate5_tests": {
@@ -3524,6 +3563,7 @@ generate_quality_report() {
3524
3563
  "gate7_iac_security": {
3525
3564
  "name": "IaC Security Scanning",
3526
3565
  "status": "${GATE_7_STATUS:-PASS}",
3566
+ "scanned_files": ${GATE_7_SCANNED_FILES:-0},
3527
3567
  "tools": "checkov, hadolint, kube-score, tflint"
3528
3568
  },
3529
3569
  "gate8_secret_scanning": {
@@ -3539,6 +3579,8 @@ generate_quality_report() {
3539
3579
  "gate10_sast": {
3540
3580
  "name": "SAST Security Scan",
3541
3581
  "status": "${GATE_10_STATUS:-PASS}",
3582
+ "reason": "${GATE_10_REASON:-}",
3583
+ "scanned_files": ${GATE_10_SCANNED_FILES:-0},
3542
3584
  "tool": "semgrep"
3543
3585
  },
3544
3586
  "gate11_sprint_flow": {
package/hooks/pre-push CHANGED
File without changes
File without changes