@boyingliu01/xp-gate 0.31.4 → 0.32.1

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 (144) hide show
  1. package/adapters/java.sh +256 -4
  2. package/adapters/powershell.sh +45 -6
  3. package/bin/xp-gate.js +8 -2
  4. package/build-integrity/__tests__/gate-10.test.ts +88 -1
  5. package/build-integrity/gate-10.ts +51 -16
  6. package/dsh.bundle.patch.yml +15 -0
  7. package/gate-13-compiler-strictness.sh +1031 -0
  8. package/gate-3.sh +65 -16
  9. package/hooks/gate-13-compiler-strictness.sh +1031 -0
  10. package/hooks/gate-3.sh +65 -16
  11. package/hooks/lib/coverage-total.sh +18 -2
  12. package/hooks/lib/java-test-selection.sh +251 -0
  13. package/hooks/lib/jscpd-run.sh +101 -0
  14. package/hooks/lib/validate-code-walkthrough.cjs +186 -29
  15. package/hooks/pre-commit +259 -57
  16. package/lib/__tests__/detect-deps-dsh-profile.test.js +106 -0
  17. package/lib/__tests__/doctor-tui-skill-freshness.test.js +140 -0
  18. package/lib/__tests__/gate-runner.test.js +29 -2
  19. package/lib/__tests__/issue-586-principles-cmdline.test.js +35 -0
  20. package/lib/__tests__/issue-618-gate-not-run.test.js +100 -0
  21. package/lib/__tests__/shared-utils.test.js +21 -0
  22. package/lib/check.js +6 -2
  23. package/lib/detect-deps.js +42 -10
  24. package/lib/doctor-tui.js +111 -21
  25. package/lib/gate-runner.js +111 -37
  26. package/lib/mattpocock-license-verdict.json +1 -1
  27. package/lib/principles.js +48 -6
  28. package/lib/shared-utils.js +8 -0
  29. package/mock-policy/AGENTS.md +3 -3
  30. package/mock-policy/gate-m3.ts +57 -23
  31. package/mutation/AGENTS.md +3 -3
  32. package/mutation/__tests__/pitest-gradle-availability.test.ts +74 -0
  33. package/mutation/__tests__/test-filter-parity.test.ts +5 -2
  34. package/mutation/gate-m.ts +30 -24
  35. package/mutation/runners/mutmut-runner.ts +80 -30
  36. package/mutation/runners/pitest-runner.ts +60 -42
  37. package/package.json +14 -2
  38. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  39. package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
  40. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  41. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  42. package/plugins/dsh/lib/command.d.ts +38 -0
  43. package/plugins/dsh/lib/command.d.ts.map +1 -0
  44. package/plugins/dsh/lib/command.js +87 -0
  45. package/plugins/dsh/lib/credentials.d.ts +39 -0
  46. package/plugins/dsh/lib/credentials.d.ts.map +1 -0
  47. package/plugins/dsh/lib/credentials.js +57 -0
  48. package/plugins/dsh/lib/delphi-config.d.ts +129 -0
  49. package/plugins/dsh/lib/delphi-config.d.ts.map +1 -0
  50. package/plugins/dsh/lib/delphi-config.js +369 -0
  51. package/plugins/dsh/lib/delphi-run.d.ts +24 -0
  52. package/plugins/dsh/lib/delphi-run.d.ts.map +1 -0
  53. package/plugins/dsh/lib/delphi-run.js +113 -0
  54. package/plugins/dsh/lib/delphi.d.ts +94 -0
  55. package/plugins/dsh/lib/delphi.d.ts.map +1 -0
  56. package/plugins/dsh/lib/delphi.js +207 -0
  57. package/plugins/dsh/lib/dialect.d.ts +24 -0
  58. package/plugins/dsh/lib/dialect.d.ts.map +1 -0
  59. package/plugins/dsh/lib/dialect.js +36 -0
  60. package/plugins/dsh/lib/evidence.d.ts +70 -0
  61. package/plugins/dsh/lib/evidence.d.ts.map +1 -0
  62. package/plugins/dsh/lib/evidence.js +92 -0
  63. package/plugins/dsh/lib/gate-runner.d.ts +49 -0
  64. package/plugins/dsh/lib/gate-runner.d.ts.map +1 -0
  65. package/plugins/dsh/lib/gate-runner.js +95 -0
  66. package/plugins/dsh/lib/git-context.d.ts +26 -0
  67. package/plugins/dsh/lib/git-context.d.ts.map +1 -0
  68. package/plugins/dsh/lib/git-context.js +30 -0
  69. package/plugins/dsh/lib/hooks.d.ts +42 -0
  70. package/plugins/dsh/lib/hooks.d.ts.map +1 -0
  71. package/plugins/dsh/lib/hooks.js +113 -0
  72. package/plugins/dsh/lib/index.d.ts +20 -0
  73. package/plugins/dsh/lib/index.d.ts.map +1 -0
  74. package/plugins/dsh/lib/index.js +430 -0
  75. package/plugins/dsh/lib/skill-provider.d.ts +15 -0
  76. package/plugins/dsh/lib/skill-provider.d.ts.map +1 -0
  77. package/plugins/dsh/lib/skill-provider.js +205 -0
  78. package/plugins/dsh/lib/sprint.d.ts +60 -0
  79. package/plugins/dsh/lib/sprint.d.ts.map +1 -0
  80. package/plugins/dsh/lib/sprint.js +92 -0
  81. package/plugins/dsh/package.json +14 -8
  82. package/plugins/dsh/scripts/verify-skill-provider.mjs +113 -0
  83. package/plugins/dsh/skills/delphi-review/AGENTS.md +3 -3
  84. package/plugins/dsh/skills/sprint-flow/AGENTS.md +3 -3
  85. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +3 -3
  86. package/plugins/dsh/src/command-single-form.test.ts +67 -0
  87. package/plugins/dsh/src/command.test.ts +21 -17
  88. package/plugins/dsh/src/command.ts +19 -21
  89. package/plugins/dsh/src/compat.test.ts +200 -0
  90. package/plugins/dsh/src/contract.test.ts +7 -1
  91. package/plugins/dsh/src/credentials.test.ts +93 -0
  92. package/plugins/dsh/src/credentials.ts +71 -0
  93. package/plugins/dsh/src/delphi-cancellation.test.ts +71 -0
  94. package/plugins/dsh/src/delphi-config-apikey-override.test.ts +94 -0
  95. package/plugins/dsh/src/delphi-config-credential-refs.test.ts +75 -0
  96. package/plugins/dsh/src/delphi-config.ts +146 -53
  97. package/plugins/dsh/src/delphi-run.ts +27 -4
  98. package/plugins/dsh/src/delphi.ts +133 -65
  99. package/plugins/dsh/src/evidence.test.ts +74 -0
  100. package/plugins/dsh/src/evidence.ts +141 -0
  101. package/plugins/dsh/src/gate-runner.test.ts +14 -6
  102. package/plugins/dsh/src/gate-runner.ts +68 -5
  103. package/plugins/dsh/src/git-context.test.ts +39 -0
  104. package/plugins/dsh/src/git-context.ts +38 -0
  105. package/plugins/dsh/src/hooks.test.ts +87 -0
  106. package/plugins/dsh/src/hooks.ts +126 -0
  107. package/plugins/dsh/src/index.test.ts +63 -6
  108. package/plugins/dsh/src/index.ts +340 -13
  109. package/plugins/dsh/src/skill-provider.test.ts +194 -0
  110. package/plugins/dsh/src/skill-provider.ts +231 -0
  111. package/plugins/dsh/src/sprint.test.ts +64 -0
  112. package/plugins/dsh/src/sprint.ts +122 -0
  113. package/plugins/dsh/src/tri-state.test.ts +123 -0
  114. package/plugins/opencode/index.ts +192 -58
  115. package/plugins/opencode/package.json +1 -1
  116. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  117. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  118. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  119. package/plugins/qoder/plugin.json +1 -1
  120. package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
  121. package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
  122. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
  123. package/principles/AGENTS.md +3 -3
  124. package/principles/__tests__/analyze-read-failure.test.ts +70 -0
  125. package/principles/__tests__/baseline-prune.test.ts +61 -0
  126. package/principles/__tests__/cli-files-separators.test.ts +69 -0
  127. package/principles/__tests__/config-merge-warnings.test.ts +148 -0
  128. package/principles/adapters/java.ts +22 -3
  129. package/principles/adapters/typescript.ts +70 -29
  130. package/principles/analyzer.ts +36 -3
  131. package/principles/baseline-prune.ts +19 -7
  132. package/principles/config.ts +56 -35
  133. package/principles/index.ts +122 -40
  134. package/principles/rules/clean-code/deep-nesting.ts +36 -22
  135. package/principles/rules/clean-code/unused-imports.ts +30 -19
  136. package/principles/rules/solid/dip.ts +30 -20
  137. package/principles/rules/solid/lsp.ts +17 -2
  138. package/principles/rules/solid/ocp.ts +33 -23
  139. package/principles/rules/solid/srp.ts +65 -23
  140. package/scripts/delphi-external-review.cjs +25 -2
  141. package/scripts/sync-package-content.js +28 -1
  142. package/skills/delphi-review/AGENTS.md +3 -3
  143. package/skills/sprint-flow/AGENTS.md +3 -3
  144. package/skills/test-specification-alignment/AGENTS.md +3 -3
package/gate-3.sh CHANGED
@@ -329,27 +329,62 @@ else
329
329
  # is reverted at the next publish, so grading it cannot be acted
330
330
  # on (doctorDelphi CCN=106 blocked every src/npm-package commit,
331
331
  # on HEAD too — no baseline entry could ever exist for it).
332
- # test __tests__/, *.test.*, *_test.{py,go}, *Test(s).java — recorded
333
- # in the report's test bucket, never in the baseline.
332
+ # test test dirs (tests/, test/, __tests__/), *.test.*, test_*.py,
333
+ # *_test.{py,go}, *Test(s).java — recorded in the report's test
334
+ # bucket, never in the baseline.
334
335
  # Both prefixes and the test pattern mirror ccn-report.cjs so the gate and
335
336
  # the writer cannot drift apart again (pinned by __tests__/gate-3-*.bats).
337
+ #
338
+ # #634: pytest's default is `python_files = test_*.py` under a `tests/`
339
+ # root. The previous pattern only knew the SUFFIX form `_test.{py,go}` and
340
+ # `*.test.*`, so a pytest-laid-out project had every test module graded as
341
+ # production source: test-helper complexity was reported as source debt and
342
+ # the ratchet could block on files the baseline deliberately never records
343
+ # (bucket === 'test').
344
+ # `(^|/)(tests?)/` — a tests/ or test/ directory anywhere in the tree
345
+ # `(^|/)test_[^/]*\.py$` — pytest default filenames at any depth
346
+ # Both are anchored with (^|/) so `latest/`, `contest/`, `attest/` and
347
+ # `my_test_dir/` are NOT caught (a leading `_?test_.*\.py$` would have
348
+ # swallowed `src/my_test_dir/bar.py`).
349
+ # Must stay equivalent to TEST_PATH in scripts/ccn-report.cjs.
336
350
  CC_FILES=$(echo "$CC_FILES" | grep -vE \
337
- '^"?src/npm-package/|^"?plugins/[^/]+/src/|(^|/)__tests__?/|\.test\.[cm]?[jt]sx?$|_test\.(py|go)$|Test(s)?\.java$' || true)
351
+ '^"?src/npm-package/|^"?plugins/[^/]+/src/|(^|/)__tests?__/|(^|/)(tests?)/|\.test\.[cm]?[jt]sx?$|(^|/)test_[^/]*\.py$|_test\.(py|go)$|Test(s)?\.java$' || true)
338
352
 
339
353
  if [ -n "$CC_FILES" ]; then
340
354
  echo "Checking complexity for source files..."
341
355
 
342
- # Run lizard with CCN threshold
343
- # One path per line, into an array. Unquoted $CC_FILES relied on word
344
- # splitting, which also splits any path containing a space -- handing
345
- # lizard two bogus paths and checking neither (#457 defect class, same
346
- # fix as gate-4's PRINCIPLES_ARGS). Quoting the scalar would instead
347
- # collapse the list into one argument. An array does both.
348
- CC_FILES_ARGS=()
349
- while IFS= read -r _cc_file; do
350
- [ -n "$_cc_file" ] && CC_FILES_ARGS+=("$_cc_file")
351
- done <<< "$CC_FILES"
352
- CC_OUTPUT=$("$LIZARD_PATH" -C "$CCN_THRESHOLD" ${CC_FILES_ARGS[@]+"${CC_FILES_ARGS[@]}"} 2>&1 || true)
356
+ # Run lizard in chunks. Two reasons, both load-bearing:
357
+ # - One path per line, into an array. Unquoted $CC_FILES relied on word
358
+ # splitting, which also splits any path containing a space -- handing
359
+ # lizard two bogus paths and checking neither (#457 defect class, same
360
+ # fix as gate-4's PRINCIPLES_ARGS). Quoting the scalar would instead
361
+ # collapse the list into one argument. An array does both.
362
+ # - Chunked instead of one argv. Windows caps a single command line at
363
+ # 32,767 characters, and under `--all` the population is the whole tree
364
+ # (1,000+ sources on a mid-sized repo). The oversized argv never reached
365
+ # lizard, nothing was printed, and the gate graded an empty CSV as if the
366
+ # tree were clean. XP_GATE_LIZARD_ARGV_BUDGET lets a probe force a split
367
+ # without needing a huge fixture.
368
+ LIZARD_ARGV_BUDGET="${XP_GATE_LIZARD_ARGV_BUDGET:-8000}"
369
+ lizard_batches() {
370
+ # stdin: one path per line. stdout: lizard output, batches concatenated.
371
+ local _batch=() _size=0 _path
372
+ while IFS= read -r _path; do
373
+ [ -n "$_path" ] || continue
374
+ if [ "${#_batch[@]}" -gt 0 ] && [ $((_size + ${#_path} + 1)) -gt "$LIZARD_ARGV_BUDGET" ]; then
375
+ "$LIZARD_PATH" "$@" "${_batch[@]}" 2>/dev/null || true
376
+ _batch=()
377
+ _size=0
378
+ fi
379
+ _batch+=("$_path")
380
+ _size=$((_size + ${#_path} + 1))
381
+ done
382
+ if [ "${#_batch[@]}" -gt 0 ]; then
383
+ "$LIZARD_PATH" "$@" "${_batch[@]}" 2>/dev/null || true
384
+ fi
385
+ return 0
386
+ }
387
+ CC_OUTPUT=$(printf '%s\n' "$CC_FILES" | lizard_batches -C "$CCN_THRESHOLD" 2>&1)
353
388
 
354
389
  # REQ-D (sprint-20261018-quality): baseline ratchet. When
355
390
  # .ccn-baseline.json exists it replaces the flat threshold verdict:
@@ -366,7 +401,7 @@ else
366
401
  # Route the CSV through the same verifier; on rows it cannot verify the
367
402
  # helper exits non-zero, and this gate fails closed instead of passing
368
403
  # an unvalidated number.
369
- CC_CSV=$("$LIZARD_PATH" --csv ${CC_FILES_ARGS[@]+"${CC_FILES_ARGS[@]}"} 2>/dev/null || true)
404
+ CC_CSV=$(printf '%s\n' "$CC_FILES" | lizard_batches --csv)
370
405
  CC_REPORT="$(git rev-parse --show-toplevel 2>/dev/null)/scripts/ccn-report.cjs"
371
406
  # Fail closed when the verifier is unavailable. Previously this fell
372
407
  # through and graded the RAW lizard CSV, while CI hard-fails on the same
@@ -392,6 +427,20 @@ else
392
427
  fi
393
428
  RATCHET_LIB="$GATE_DIR/lib/ccn-ratchet.sh"
394
429
  [ -f "$RATCHET_LIB" ] || RATCHET_LIB="$(git rev-parse --show-toplevel 2>/dev/null)/githooks/lib/ccn-ratchet.sh"
430
+ # Fail closed when the ratchet library is missing. Sourcing a nonexistent
431
+ # file only prints "No such file or directory" and leaves
432
+ # evaluate_ccn_ratchet undefined; the verdict then came back empty, every
433
+ # counter read 0 and the gate printed "✅ PASSED" — a CCN regression graded
434
+ # green with nothing compared. The installer never created this path
435
+ # (copyAdapters skipped hooks/lib), so this was the normal state after a
436
+ # global install, not an exotic one.
437
+ if [ ! -f "$RATCHET_LIB" ]; then
438
+ echo "❌ BLOCKED - complexity ratchet library unavailable (ccn-ratchet.sh)."
439
+ echo "Expected at \$GATE_DIR/lib/ccn-ratchet.sh or <repo>/githooks/lib/ccn-ratchet.sh."
440
+ echo "Reinstall with 'xp-gate init --global' (or 'xp-gate update-hooks') to restore it."
441
+ GATE_3_DETAIL="mode=ratchet ratchet=MISSING"
442
+ exit 1
443
+ fi
395
444
  # shellcheck source=/dev/null
396
445
  . "$RATCHET_LIB"
397
446
  # NOTE: the thresholds must be plain assignments BEFORE the pipe. As a
@@ -436,7 +485,7 @@ else
436
485
  # file,name,signature,...), so the verdict comes from the same numbers
437
486
  # lizard uses, independent of version and table formatting. --csv here is
438
487
  # the flat-threshold run; the ratchet branch above builds its own.
439
- CC_CSV_FLAT=$("$LIZARD_PATH" --csv -C "$CCN_THRESHOLD" ${CC_FILES_ARGS[@]+"${CC_FILES_ARGS[@]}"} 2>/dev/null || true)
488
+ CC_CSV_FLAT=$(printf '%s\n' "$CC_FILES" | lizard_batches --csv -C "$CCN_THRESHOLD")
440
489
  CC_WARNINGS=$(printf '%s\n' "$CC_CSV_FLAT" | awk -F, -v t="$CCN_THRESHOLD" '
441
490
  NF > 1 && $2 + 0 > t + 0 { c++ }
442
491
  END { print c + 0 }