@boyingliu01/xp-gate 0.14.13 → 0.14.15

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.
@@ -71,7 +71,7 @@ describe('runTscCheck', () => {
71
71
  process.cwd = originalCwd;
72
72
  }
73
73
  } finally {
74
- await fs.rm(isolatedDir, { recursive: true, force: true }).catch(() => {});
74
+ await fs.rm(isolatedDir, { recursive: true, force: true }).catch(() => { /* ignore cleanup errors */ });
75
75
  }
76
76
  });
77
77
 
@@ -0,0 +1,230 @@
1
+ # ============================================================================
2
+ # GATE 12: File Hygiene Check
3
+ # Detects common file quality issues in staged files:
4
+ # - Trailing whitespace
5
+ # - Missing EOF newline
6
+ # - Merge conflict markers (<<<<<<< , =======, >>>>>>>)
7
+ # - Oversized files (>1MB default, configurable)
8
+ # ============================================================================
9
+
10
+ 2>&1 echo ""
11
+ 2>&1 echo "→ Gate 12: File hygiene check..."
12
+ GATE_12_START=$(gate_start_ms)
13
+
14
+ # Configuration (can be overridden via environment)
15
+ MAX_FILE_SIZE_BYTES="${XP_GATE_MAX_FILE_SIZE:-1048576}" # 1MB default
16
+
17
+ # Get list of staged files (excluding deleted files)
18
+ STAGED_FILES=$(git diff --cached --name-only --diff-filter=d 2>/dev/null)
19
+
20
+ if [ -z "$STAGED_FILES" ]; then
21
+ echo " ℹ️ No staged files — skipping"
22
+ echo " ✅ PASSED - File Hygiene (no files to check)"
23
+ GATE_12_STATUS="SKIP"
24
+ record_gate_audit "gate-12" "file-hygiene" "$GATE_12_STATUS" "0" "$GATE_12_START"
25
+ return 0 2>/dev/null || true
26
+ fi
27
+
28
+ HYGIENE_ISSUES=0
29
+ HYGIENE_FILES=""
30
+
31
+ # --- Check 1: Trailing whitespace ---
32
+ TRAILING_WS_FILES=""
33
+ while IFS= read -r file; do
34
+ [ -z "$file" ] && continue
35
+ # Skip binary files by checking if file contains null bytes
36
+ if git diff --cached --no-color -- "$file" 2>/dev/null | grep -q $'\x00'; then
37
+ continue
38
+ fi
39
+ # Check staged content for trailing whitespace (spaces/tabs at end of lines)
40
+ if git show ":$file" 2>/dev/null | grep -qE '[[:space:]]$'; then
41
+ TRAILING_WS_FILES="$TRAILING_WS_FILES $file"
42
+ fi
43
+ done <<EOF
44
+ $STAGED_FILES
45
+ EOF
46
+
47
+ if [ -n "$TRAILING_WS_FILES" ]; then
48
+ echo " ⚠️ Trailing whitespace detected in:"
49
+ for f in $TRAILING_WS_FILES; do
50
+ echo " - $f"
51
+ done
52
+ HYGIENE_ISSUES=$((HYGIENE_ISSUES + 1))
53
+ HYGIENE_FILES="$HYGIENE_FILES trailing-whitespace"
54
+ fi
55
+
56
+ # --- Check 2: Missing EOF newline ---
57
+ NO_EOF_NEWLINE_FILES=""
58
+ while IFS= read -r file; do
59
+ [ -z "$file" ] && continue
60
+ # Skip binary files
61
+ if git diff --cached --no-color -- "$file" 2>/dev/null | grep -q $'\x00'; then
62
+ continue
63
+ fi
64
+ # Check if file content ends with newline
65
+ FILE_CONTENT=$(git show ":$file" 2>/dev/null)
66
+ if [ -n "$FILE_CONTENT" ]; then
67
+ LAST_CHAR=$(printf '%s' "$FILE_CONTENT" | tail -c 1)
68
+ if [ "$LAST_CHAR" != "" ]; then
69
+ NO_EOF_NEWLINE_FILES="$NO_EOF_NEWLINE_FILES $file"
70
+ fi
71
+ fi
72
+ done <<EOF
73
+ $STAGED_FILES
74
+ EOF
75
+
76
+ if [ -n "$NO_EOF_NEWLINE_FILES" ]; then
77
+ echo " ⚠️ Missing EOF newline in:"
78
+ for f in $NO_EOF_NEWLINE_FILES; do
79
+ echo " - $f"
80
+ done
81
+ HYGIENE_ISSUES=$((HYGIENE_ISSUES + 1))
82
+ HYGIENE_FILES="$HYGIENE_FILES no-eof-newline"
83
+ fi
84
+
85
+ # --- Check 3: Merge conflict markers ---
86
+ CONFLICT_MARKER_FILES=""
87
+ while IFS= read -r file; do
88
+ [ -z "$file" ] && continue
89
+ # Skip binary files
90
+ if git diff --cached --no-color -- "$file" 2>/dev/null | grep -q $'\x00'; then
91
+ continue
92
+ fi
93
+ # Check for conflict markers in staged content
94
+ if git show ":$file" 2>/dev/null | grep -qE '^(<<<<<<<|=======|>>>>>>>)'; then
95
+ CONFLICT_MARKER_FILES="$CONFLICT_MARKER_FILES $file"
96
+ fi
97
+ done <<EOF
98
+ $STAGED_FILES
99
+ EOF
100
+
101
+ if [ -n "$CONFLICT_MARKER_FILES" ]; then
102
+ echo " ❌ Merge conflict markers detected in:"
103
+ for f in $CONFLICT_MARKER_FILES; do
104
+ echo " - $f"
105
+ done
106
+ HYGIENE_ISSUES=$((HYGIENE_ISSUES + 1))
107
+ HYGIENE_FILES="$HYGIENE_FILES conflict-markers"
108
+ fi
109
+
110
+ # --- Check 4: Oversized files ---
111
+ OVERSIZED_FILES=""
112
+ while IFS= read -r file; do
113
+ [ -z "$file" ] && continue
114
+ [ ! -f "$file" ] && continue
115
+ FILE_SIZE=$(wc -c < "$file" 2>/dev/null | tr -d ' ')
116
+ if [ -n "$FILE_SIZE" ] && [ "$FILE_SIZE" -gt "$MAX_FILE_SIZE_BYTES" ]; then
117
+ SIZE_MB=$((FILE_SIZE / 1048576))
118
+ OVERSIZED_FILES="$OVERSIZED_FILES $file(${SIZE_MB}MB)"
119
+ fi
120
+ done <<EOF
121
+ $STAGED_FILES
122
+ EOF
123
+
124
+ if [ -n "$OVERSIZED_FILES" ]; then
125
+ echo " ⚠️ Oversized files (>${MAX_FILE_SIZE_BYTES} bytes):"
126
+ for f in $OVERSIZED_FILES; do
127
+ echo " - $f"
128
+ done
129
+ HYGIENE_ISSUES=$((HYGIENE_ISSUES + 1))
130
+ HYGIENE_FILES="$HYGIENE_FILES oversized-files"
131
+ fi
132
+
133
+ # --- Check 5: YAML/JSON syntax validation (Issue #351) ---
134
+ # Only check staged YAML/JSON files that have changes
135
+ YAML_JSON_ERRORS=""
136
+ YAML_JSON_CHECK_COUNT=0
137
+
138
+ # Detect available validators
139
+ YAML_CMD=""
140
+ if command -v python3 >/dev/null 2>&1; then
141
+ YAML_CMD="python3"
142
+ elif command -v python >/dev/null 2>&1; then
143
+ YAML_CMD="python"
144
+ fi
145
+
146
+ JSON_CMD=""
147
+ if command -v node >/dev/null 2>&1; then
148
+ JSON_CMD="node"
149
+ elif command -v jq >/dev/null 2>&1; then
150
+ JSON_CMD="jq"
151
+ fi
152
+
153
+ while IFS= read -r file; do
154
+ [ -z "$file" ] && continue
155
+ [ ! -f "$file" ] && continue
156
+
157
+ case "$file" in
158
+ *.yml|*.yaml)
159
+ if [ -n "$YAML_CMD" ]; then
160
+ YAML_JSON_CHECK_COUNT=$((YAML_JSON_CHECK_COUNT + 1))
161
+ # Validate YAML syntax using Python's yaml module
162
+ YAML_ERROR=$(git show ":$file" 2>/dev/null | $YAML_CMD -c "
163
+ import sys, yaml
164
+ try:
165
+ yaml.safe_load(sys.stdin.read())
166
+ except yaml.YAMLError as e:
167
+ print(str(e).split(chr(10))[0])
168
+ sys.exit(1)
169
+ except Exception:
170
+ pass
171
+ " 2>&1)
172
+ if [ $? -ne 0 ] && [ -n "$YAML_ERROR" ]; then
173
+ YAML_JSON_ERRORS="$YAML_JSON_ERRORS $file(yaml:$YAML_ERROR)"
174
+ fi
175
+ fi
176
+ ;;
177
+ *.json)
178
+ YAML_JSON_CHECK_COUNT=$((YAML_JSON_CHECK_COUNT + 1))
179
+ if [ "$JSON_CMD" = "node" ]; then
180
+ JSON_ERROR=$(git show ":$file" 2>/dev/null | node -e "
181
+ let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{JSON.parse(d)}catch(e){console.log(e.message.split('\\n')[0]);process.exit(1)}})
182
+ " 2>&1)
183
+ if [ $? -ne 0 ] && [ -n "$JSON_ERROR" ]; then
184
+ YAML_JSON_ERRORS="$YAML_JSON_ERRORS $file(json:$JSON_ERROR)"
185
+ fi
186
+ elif [ "$JSON_CMD" = "jq" ]; then
187
+ JSON_ERROR=$(git show ":$file" 2>/dev/null | jq empty 2>&1)
188
+ if [ $? -ne 0 ] && [ -n "$JSON_ERROR" ]; then
189
+ YAML_JSON_ERRORS="$YAML_JSON_ERRORS $file(json:syntax error)"
190
+ fi
191
+ fi
192
+ ;;
193
+ esac
194
+ done <<EOF
195
+ $STAGED_FILES
196
+ EOF
197
+
198
+ if [ -n "$YAML_JSON_ERRORS" ]; then
199
+ echo " ❌ YAML/JSON syntax errors:"
200
+ for f in $YAML_JSON_ERRORS; do
201
+ echo " - $f"
202
+ done
203
+ HYGIENE_ISSUES=$((HYGIENE_ISSUES + 1))
204
+ HYGIENE_FILES="$HYGIENE_FILES yaml-json-syntax"
205
+ elif [ "$YAML_JSON_CHECK_COUNT" -gt 0 ]; then
206
+ echo " ✅ YAML/JSON syntax OK ($YAML_JSON_CHECK_COUNT file(s) checked)"
207
+ fi
208
+
209
+ # --- Result ---
210
+ if [ "$HYGIENE_ISSUES" -eq 0 ]; then
211
+ echo " ✅ PASSED - No file hygiene issues detected."
212
+ GATE_12_STATUS="PASS"
213
+ else
214
+ # Hard blocks: conflict markers + YAML/JSON syntax errors
215
+ if [ -n "$CONFLICT_MARKER_FILES" ] || [ -n "$YAML_JSON_ERRORS" ]; then
216
+ echo ""
217
+ echo "❌ BLOCKED - File hygiene violations must be fixed before commit."
218
+ GATE_12_STATUS="BLOCK"
219
+ record_gate_audit "gate-12" "file-hygiene" "$GATE_12_STATUS" "$HYGIENE_ISSUES" "$GATE_12_START"
220
+ exit 1
221
+ else
222
+ echo ""
223
+ echo " ⚠️ WARNINGS - $HYGIENE_ISSUES file hygiene issue(s) found."
224
+ echo " Fix recommended but not blocking (no conflict markers or syntax errors)."
225
+ echo " Issues:$HYGIENE_FILES"
226
+ GATE_12_STATUS="WARN"
227
+ fi
228
+ fi
229
+
230
+ record_gate_audit "gate-12" "file-hygiene" "$GATE_12_STATUS" "$HYGIENE_ISSUES" "$GATE_12_START"
package/hooks/gate-8.sh CHANGED
@@ -13,7 +13,7 @@ GITLEAKS_CMD=""
13
13
  if command -v gitleaks >/dev/null 2>&1; then
14
14
  GITLEAKS_CMD="gitleaks"
15
15
  elif [ -f "$HOME/.local/bin/gitleaks" ]; then
16
- GIBLEAKS_CMD="$HOME/.local/bin/gitleaks"
16
+ GITLEAKS_CMD="$HOME/.local/bin/gitleaks"
17
17
  fi
18
18
 
19
19
  if [ -n "$GITLEAKS_CMD" ]; then