@boyingliu01/xp-gate 0.15.1 → 0.15.2

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 (68) 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/go.sh +0 -0
  6. package/adapters/iac.sh +0 -0
  7. package/adapters/java.sh +0 -0
  8. package/adapters/kotlin.sh +0 -0
  9. package/adapters/objectivec.sh +0 -0
  10. package/adapters/plugins/book299-20132-python/scripts/install-gradle.sh +0 -0
  11. package/adapters/plugins/book299-20132-python/scripts/install-maven.sh +0 -0
  12. package/adapters/plugins/book299-4081-c/scripts/install-gradle.sh +0 -0
  13. package/adapters/plugins/book299-4081-c/scripts/install-maven.sh +0 -0
  14. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-gradle.sh +0 -0
  15. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-maven.sh +0 -0
  16. package/adapters/powershell.sh +0 -0
  17. package/adapters/python.sh +0 -0
  18. package/adapters/shell.sh +0 -0
  19. package/adapters/swift.sh +0 -0
  20. package/adapters/typescript.sh +0 -0
  21. package/bin/xp-gate.js +24 -0
  22. package/gate-3.sh +0 -0
  23. package/gate-4.sh +0 -0
  24. package/gate-7.sh +0 -0
  25. package/gate-8.sh +0 -0
  26. package/gate-9.sh +0 -0
  27. package/hooks/adapter-common.sh +0 -0
  28. package/hooks/gate-3.sh +0 -0
  29. package/hooks/gate-4.sh +0 -0
  30. package/hooks/gate-7.sh +0 -0
  31. package/hooks/gate-8.sh +0 -0
  32. package/hooks/gate-9.sh +0 -0
  33. package/hooks/pre-commit +24 -2
  34. package/hooks/pre-push +204 -14
  35. package/lib/__tests__/phase-transition.test.js +272 -272
  36. package/lib/__tests__/sprint-audit.test.js +207 -207
  37. package/lib/doctor.js +50 -0
  38. package/lib/init.js +91 -0
  39. package/lib/language-tools.js +833 -0
  40. package/lib/phase-transition.js +249 -249
  41. package/lib/sprint-audit.js +235 -235
  42. package/mock-policy/AGENTS.md +2 -2
  43. package/mutation/AGENTS.md +2 -2
  44. package/package.json +1 -1
  45. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  46. package/plugins/claude-code/bin/delphi-review-guard.sh +0 -0
  47. package/plugins/claude-code/bin/xp-gate-check +0 -0
  48. package/plugins/claude-code/skills/delphi-review/AGENTS.md +2 -2
  49. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +2 -2
  50. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +2 -2
  51. package/plugins/opencode/package.json +1 -1
  52. package/plugins/opencode/skills/delphi-review/AGENTS.md +2 -2
  53. package/plugins/opencode/skills/sprint-flow/AGENTS.md +2 -2
  54. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +2 -2
  55. package/plugins/qoder/agents/delphi-architecture.md +48 -48
  56. package/plugins/qoder/agents/delphi-feasibility.md +48 -48
  57. package/plugins/qoder/agents/delphi-technical.md +48 -48
  58. package/plugins/qoder/bin/sprint-flow-guard.sh +0 -0
  59. package/plugins/qoder/bin/xp-gate-check +0 -0
  60. package/plugins/qoder/plugin.json +1 -1
  61. package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
  62. package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
  63. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
  64. package/principles/AGENTS.md +2 -2
  65. package/scripts/delphi-external-review.cjs +432 -432
  66. package/skills/delphi-review/AGENTS.md +2 -2
  67. package/skills/sprint-flow/AGENTS.md +2 -2
  68. package/skills/test-specification-alignment/AGENTS.md +2 -2
package/adapter-common.sh CHANGED
File without changes
package/adapters/cpp.sh CHANGED
File without changes
package/adapters/dart.sh CHANGED
File without changes
File without changes
package/adapters/go.sh CHANGED
File without changes
package/adapters/iac.sh CHANGED
File without changes
package/adapters/java.sh CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
package/adapters/shell.sh CHANGED
File without changes
package/adapters/swift.sh CHANGED
File without changes
File without changes
package/bin/xp-gate.js CHANGED
@@ -211,6 +211,30 @@ const COMMANDS = {
211
211
  handleSprintAudit(subargs).then(code => process.exit(code));
212
212
  },
213
213
  usage: 'xp-gate sprint-audit [--dir <path>] [--json]'
214
+ },
215
+ 'detect-languages': {
216
+ description: 'Detect project languages and generate .xp-gate-config.json',
217
+ run: subargs => {
218
+ const { handleDetectLanguages } = require('../lib/language-tools.js');
219
+ handleDetectLanguages(subargs).then(code => process.exit(code));
220
+ },
221
+ usage: 'xp-gate detect-languages [--json] [--write]'
222
+ },
223
+ 'check-tools': {
224
+ description: 'Check quality gate tool availability per language',
225
+ run: subargs => {
226
+ const { handleCheckTools } = require('../lib/language-tools.js');
227
+ handleCheckTools(subargs).then(code => process.exit(code));
228
+ },
229
+ usage: 'xp-gate check-tools [--languages <langs>] [--json]'
230
+ },
231
+ 'install-tools': {
232
+ description: 'Install missing quality gate tools for detected languages',
233
+ run: subargs => {
234
+ const { handleInstallTools } = require('../lib/language-tools.js');
235
+ handleInstallTools(subargs).then(code => process.exit(code));
236
+ },
237
+ usage: 'xp-gate install-tools [--languages <langs>] [--dry-run] [--yes]'
214
238
  }
215
239
  };
216
240
 
package/gate-3.sh CHANGED
File without changes
package/gate-4.sh CHANGED
File without changes
package/gate-7.sh CHANGED
File without changes
package/gate-8.sh CHANGED
File without changes
package/gate-9.sh CHANGED
File without changes
File without changes
package/hooks/gate-3.sh CHANGED
File without changes
package/hooks/gate-4.sh CHANGED
File without changes
package/hooks/gate-7.sh CHANGED
File without changes
package/hooks/gate-8.sh CHANGED
File without changes
package/hooks/gate-9.sh CHANGED
File without changes
package/hooks/pre-commit CHANGED
@@ -375,7 +375,29 @@ if [ -n "$_RESOLVED_LANG_OVERRIDE" ]; then
375
375
  echo " 🔧 LANGUAGE OVERRIDE: $PROJECT_LANG"
376
376
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
377
377
  echo ""
378
- else
378
+ elif [ -f ".xp-gate-config.json" ]; then
379
+ # ---- Read from project config file (v0.15.2+) ----
380
+ # .xp-gate-config.json is generated by `xp-gate init` or `xp-gate detect-languages`
381
+ # It contains detected languages and their tool status.
382
+ _CONFIG_LANGS=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.xp-gate-config.json','utf8'));console.log(Object.keys(c.languages||{}).join(' '));}catch(e){console.log('');}" 2>/dev/null || echo "")
383
+ if [ -n "$_CONFIG_LANGS" ]; then
384
+ PROJECT_LANGS="$_CONFIG_LANGS"
385
+ PROJECT_LANG=$(echo "$_CONFIG_LANGS" | awk '{print $1}')
386
+ echo ""
387
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
388
+ echo " 📋 LANGUAGES FROM .xp-gate-config.json"
389
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
390
+ echo ""
391
+ echo "Detected languages: $PROJECT_LANGS"
392
+ echo ""
393
+ else
394
+ # Config file exists but no languages detected — fall through to extension detection
395
+ _CONFIG_LANGS=""
396
+ fi
397
+ fi
398
+
399
+ # If no languages from override or config, detect from changed files
400
+ if [ -z "$PROJECT_LANGS" ] && [ -z "$_CONFIG_LANGS" ]; then
379
401
  # ---- Extension → language mapping ----
380
402
  # Extracts unique languages from changed file extensions
381
403
  PROJECT_LANGS=""
@@ -676,7 +698,7 @@ CHANGEDFILELIST
676
698
  done
677
699
  echo ""
678
700
  fi
679
- fi
701
+ fi # close language override if/else
680
702
 
681
703
  # Helper: check if a language is in PROJECT_LANGS
682
704
  has_project_lang() {
package/hooks/pre-push CHANGED
@@ -865,16 +865,11 @@ if ! command -v jq &> /dev/null; then
865
865
  fi
866
866
 
867
867
  # Validate result file content
868
- # SHA self-reference paradox fix: if the result file was committed as part of
869
- # HEAD, its content references HEAD^ (the commit being reviewed), not HEAD.
868
+ # SHA self-reference paradox fix (Issue #346):
869
+ # The walkthrough file may reference an earlier commit if it was generated before
870
+ # subsequent walkthrough-only commits. We check if the referenced commit is in
871
+ # the current branch's history and if no functional commits occurred after it.
870
872
  CURRENT_COMMIT=$(git rev-parse HEAD)
871
- if git diff-tree --no-commit-id --name-only -r HEAD 2>/dev/null | grep -qx "$RESULT_FILE"; then
872
- # Result file is part of the latest commit — compare against the reviewed commit
873
- EXPECTED_COMMIT=$(git rev-parse HEAD^ 2>/dev/null || echo "unknown")
874
- else
875
- # Result file is working-tree only — compare against current HEAD
876
- EXPECTED_COMMIT="$CURRENT_COMMIT"
877
- fi
878
873
 
879
874
  # Check JSON validity
880
875
  if ! jq empty "$RESULT_FILE" 2>/dev/null; then
@@ -906,16 +901,42 @@ if [ "$RESULT_BRANCH" != "$CURRENT_BRANCH" ]; then
906
901
  echo "Proceeding with commit verification..."
907
902
  fi
908
903
 
909
- # Commit match check
910
- if [ "$RESULT_COMMIT" != "$EXPECTED_COMMIT" ]; then
904
+ # Commit match check (Issue #346: flexible matching to avoid circular dependency)
905
+ # Check if RESULT_COMMIT is in the current branch's history
906
+ if ! git merge-base --is-ancestor "$RESULT_COMMIT" HEAD 2>/dev/null; then
907
+ echo ""
908
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
909
+ echo " ❌ RESULT FILE INVALID - PUSH BLOCKED"
910
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
911
+ echo ""
912
+ echo "Result file references a commit not in current branch:"
913
+ echo " Referenced: $RESULT_COMMIT"
914
+ echo " Current HEAD: $CURRENT_COMMIT"
915
+ echo ""
916
+ echo "Re-run: /delphi-review --mode code-walkthrough"
917
+ echo ""
918
+ exit 1
919
+ fi
920
+
921
+ # Check if there are any functional commits after RESULT_COMMIT
922
+ # Functional commits are those that are NOT walkthrough-only updates or Gate MW fixes
923
+ FUNCTIONAL_COMMITS_AFTER=$(git log --oneline "$RESULT_COMMIT"..HEAD -- . \
924
+ ':!.code-walkthrough-result.json' \
925
+ ':!.delphi/code-walkthrough.md' \
926
+ ':!githooks/pre-push' \
927
+ ':!src/npm-package/hooks/pre-push' 2>/dev/null | wc -l)
928
+ if [ "$FUNCTIONAL_COMMITS_AFTER" -gt 0 ]; then
911
929
  echo ""
912
930
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
913
931
  echo " ❌ RESULT FILE OUTDATED - PUSH BLOCKED"
914
932
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
915
933
  echo ""
916
- echo "Result file is for a different commit:"
917
- echo " Expected: $EXPECTED_COMMIT"
918
- echo " Found: $RESULT_COMMIT"
934
+ echo "Functional commits found after walkthrough:"
935
+ git log --oneline "$RESULT_COMMIT"..HEAD -- . \
936
+ ':!.code-walkthrough-result.json' \
937
+ ':!.delphi/code-walkthrough.md' \
938
+ ':!githooks/pre-push' \
939
+ ':!src/npm-package/hooks/pre-push' 2>/dev/null | head -5
919
940
  echo ""
920
941
  echo "Re-run: /delphi-review --mode code-walkthrough"
921
942
  echo ""
@@ -961,9 +982,178 @@ if [[ "$CURRENT_TIME" > "$RESULT_EXPIRES" ]]; then
961
982
  exit 1
962
983
  fi
963
984
 
985
+ # ============================================================================
986
+ # PROVENANCE VALIDATION (Issue #339)
987
+ # Validate that the walkthrough was genuinely produced by Delphi review,
988
+ # not fabricated by an LLM.
989
+ # ============================================================================
990
+
991
+ # Check provenance fields exist
992
+ EXPERTS_COUNT=$(jq -r '.experts // [] | length' "$RESULT_FILE")
993
+ CONSENSUS=$(jq -r '.consensus // 0' "$RESULT_FILE")
994
+ WALKTHROUGH_HASH=$(jq -r '.walkthroughHash // empty' "$RESULT_FILE")
995
+ GENERATED_AT=$(jq -r '.generatedAt // empty' "$RESULT_FILE")
996
+
997
+ # Grace period: configurable via env var (default 30 days)
998
+ GRACE_DAYS="${XP_GATE_MW_GRACE_DAYS:-30}"
999
+
1000
+ # Check if this is a "new" walkthrough (has provenance fields)
1001
+ HAS_PROVENANCE="false"
1002
+ if [ -n "$WALKTHROUGH_HASH" ] && [ -n "$GENERATED_AT" ] && [ "$EXPERTS_COUNT" -ge 3 ]; then
1003
+ HAS_PROVENANCE="true"
1004
+ fi
1005
+
1006
+ if [ "$HAS_PROVENANCE" = "true" ]; then
1007
+ # Full provenance validation
1008
+
1009
+ # 1. Experts count check (minimum 3)
1010
+ if [ "$EXPERTS_COUNT" -lt 3 ]; then
1011
+ echo ""
1012
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1013
+ echo " ❌ INSUFFICIENT EXPERTS - PUSH BLOCKED"
1014
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1015
+ echo ""
1016
+ echo "Walkthrough requires minimum 3 experts:"
1017
+ echo " Found: $EXPERTS_COUNT experts"
1018
+ echo ""
1019
+ echo "Re-run: /delphi-review --mode code-walkthrough"
1020
+ echo ""
1021
+ exit 1
1022
+ fi
1023
+
1024
+ # 2. Consensus check (≥90%)
1025
+ # Use integer math: multiply by 10 to avoid bc dependency
1026
+ CONSENSUS_X10=$(echo "$CONSENSUS * 10" | bc -l | cut -d'.' -f1)
1027
+ if [ "$CONSENSUS_X10" -lt 900 ]; then
1028
+ echo ""
1029
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1030
+ echo " ❌ CONSENSUS TOO LOW - PUSH BLOCKED"
1031
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1032
+ echo ""
1033
+ echo "Walkthrough requires ≥90% consensus:"
1034
+ echo " Found: ${CONSENSUS}%"
1035
+ echo ""
1036
+ echo "Re-run: /delphi-review --mode code-walkthrough"
1037
+ echo ""
1038
+ exit 1
1039
+ fi
1040
+
1041
+ # 3. Walkthrough hash verification
1042
+ WALKTHROUGH_DOC=".delphi/code-walkthrough.md"
1043
+ if [ ! -f "$WALKTHROUGH_DOC" ]; then
1044
+ echo ""
1045
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1046
+ echo " ❌ WALKTHROUGH DOC MISSING - PUSH BLOCKED"
1047
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1048
+ echo ""
1049
+ echo "Walkthrough document not found:"
1050
+ echo " Expected: $WALKTHROUGH_DOC"
1051
+ echo ""
1052
+ echo "Re-run: /delphi-review --mode code-walkthrough"
1053
+ echo ""
1054
+ exit 1
1055
+ fi
1056
+
1057
+ # Cross-platform SHA-256 computation
1058
+ COMPUTED_HASH=""
1059
+ if command -v sha256sum &> /dev/null; then
1060
+ COMPUTED_HASH=$(sha256sum "$WALKTHROUGH_DOC" | cut -d' ' -f1)
1061
+ elif command -v shasum &> /dev/null; then
1062
+ COMPUTED_HASH=$(shasum -a 256 "$WALKTHROUGH_DOC" | cut -d' ' -f1)
1063
+ elif command -v openssl &> /dev/null; then
1064
+ COMPUTED_HASH=$(openssl sha256 -r "$WALKTHROUGH_DOC" | cut -d' ' -f1)
1065
+ fi
1066
+
1067
+ if [ -z "$COMPUTED_HASH" ]; then
1068
+ echo ""
1069
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1070
+ echo " ❌ NO SHA-256 TOOL - PUSH BLOCKED"
1071
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1072
+ echo ""
1073
+ echo "No SHA-256 tool available (install sha256sum, shasum, or openssl)"
1074
+ echo ""
1075
+ exit 1
1076
+ fi
1077
+
1078
+ if [ "$WALKTHROUGH_HASH" != "$COMPUTED_HASH" ]; then
1079
+ echo ""
1080
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1081
+ echo " ❌ WALKTHROUGH HASH MISMATCH - PUSH BLOCKED"
1082
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1083
+ echo ""
1084
+ echo "Walkthrough document has been modified after review:"
1085
+ echo " Expected: $WALKTHROUGH_HASH"
1086
+ echo " Found: $COMPUTED_HASH"
1087
+ echo ""
1088
+ echo "Re-run: /delphi-review --mode code-walkthrough"
1089
+ echo ""
1090
+ exit 1
1091
+ fi
1092
+
1093
+ # 4. generatedAt check (replay protection)
1094
+ if [ -z "$GENERATED_AT" ]; then
1095
+ echo ""
1096
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1097
+ echo " ❌ MISSING generatedAt - PUSH BLOCKED"
1098
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1099
+ echo ""
1100
+ echo "Walkthrough result missing generatedAt timestamp"
1101
+ echo ""
1102
+ echo "Re-run: /delphi-review --mode code-walkthrough"
1103
+ echo ""
1104
+ exit 1
1105
+ fi
1106
+ else
1107
+ # Grace period: old walkthroughs without provenance get WARNING
1108
+ echo ""
1109
+ echo "⚠️ WARNING: Legacy walkthrough format (no provenance fields)"
1110
+ echo " Provenance fields will be required after grace period (${GRACE_DAYS} days)"
1111
+ echo " Consider re-running: /delphi-review --mode code-walkthrough"
1112
+ echo ""
1113
+ fi
1114
+
964
1115
  # ============================================================================
965
1116
  # ALL CHECKS PASSED
966
1117
  # ============================================================================
1118
+ echo ""
1119
+
1120
+ # ============================================================================
1121
+ # SPRINT-STATE BACKUP CHECK (WARNING ONLY — Issue #318)
1122
+ # Scan for worktree sprint-state directories that haven't been backed up
1123
+ # to .sprint-history/ before push. WARN only (doesn't block) — sprint-state
1124
+ # inside worktrees is deleted on `git worktree remove`, causing permanent
1125
+ # data loss if orchestrator forgets to back up during CLOSE phase.
1126
+ # ============================================================================
1127
+ if [ -d ".worktrees/sprint" ]; then
1128
+ for worktree_dir in .worktrees/sprint/sprint-*; do
1129
+ [ -d "$worktree_dir" ] || continue
1130
+ [ -d "$worktree_dir/.sprint-state" ] || continue
1131
+ sprint_id=$(basename "$worktree_dir")
1132
+ if [ -f "$worktree_dir/.sprint-state/sprint-state.json" ]; then
1133
+ if [ ! -d ".sprint-history/$sprint_id" ]; then
1134
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1135
+ echo " ⚠️ SPRINT-STATE NOT BACKED UP: $sprint_id"
1136
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1137
+ echo ""
1138
+ echo "Unarchived sprint state found in worktree:"
1139
+ echo " Path: $worktree_dir/.sprint-state/"
1140
+ echo " Backup: .sprint-history/$sprint_id/ (MISSING)"
1141
+ echo ""
1142
+ echo "RISK: If this worktree is removed before CLOSE backup,"
1143
+ echo " design docs, Delphi verdicts, and phase summaries"
1144
+ echo " are permanently lost."
1145
+ echo ""
1146
+ echo "Backup now:"
1147
+ echo " mkdir -p .sprint-history/$sprint_id"
1148
+ echo " cp -r $worktree_dir/.sprint-state/* .sprint-history/$sprint_id/"
1149
+ echo ""
1150
+ echo "See: https://github.com/boyingliu01/xp-gate/issues/318"
1151
+ echo ""
1152
+ fi
1153
+ fi
1154
+ done
1155
+ fi
1156
+
967
1157
  echo ""
968
1158
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
969
1159
  echo " ✅ GATE MW: CODE WALKTHROUGH VERIFIED"