fraim-framework 2.0.37 â 2.0.41
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/README.md +8 -0
- package/dist/src/ai-manager/ai-manager.js +162 -0
- package/dist/src/cli/commands/init-project.js +74 -0
- package/dist/src/cli/commands/setup.js +176 -0
- package/dist/src/cli/commands/test-mcp.js +135 -0
- package/dist/src/cli/fraim.js +6 -0
- package/dist/src/cli/setup/auto-mcp-setup.js +367 -0
- package/dist/src/cli/setup/ide-detector.js +165 -0
- package/dist/src/cli/setup/mcp-config-generator.js +144 -0
- package/dist/src/cli/setup/token-validator.js +49 -0
- package/dist/src/fraim-mcp-server.js +198 -0
- package/dist/tests/debug-tools.js +2 -2
- package/dist/tests/shared-server-utils.js +57 -0
- package/dist/tests/test-ai-manager.js +113 -0
- package/dist/tests/test-client-scripts-validation.js +27 -5
- package/dist/tests/test-complete-setup-flow.js +110 -0
- package/dist/tests/test-ide-detector.js +46 -0
- package/dist/tests/test-improved-setup.js +121 -0
- package/dist/tests/test-mcp-config-generator.js +99 -0
- package/dist/tests/test-mcp-connection.js +58 -117
- package/dist/tests/test-mcp-issue-integration.js +2 -2
- package/dist/tests/test-mcp-lifecycle-methods.js +34 -100
- package/dist/tests/test-mcp-shared-server.js +308 -0
- package/dist/tests/test-package-size.js +21 -8
- package/dist/tests/test-script-location-independence.js +39 -62
- package/dist/tests/test-server-utils.js +32 -0
- package/dist/tests/test-session-rehydration.js +2 -2
- package/dist/tests/test-setup-integration.js +98 -0
- package/dist/tests/test-standalone.js +2 -2
- package/dist/tests/test-stub-registry.js +23 -7
- package/dist/tests/test-telemetry.js +2 -2
- package/dist/tests/test-token-validator.js +30 -0
- package/dist/tests/test-user-journey.js +2 -1
- package/package.json +3 -2
- package/registry/scripts/code-quality-check.sh +566 -559
- package/registry/scripts/prep-issue.sh +7 -0
- package/registry/scripts/verify-pr-comments.sh +74 -70
- /package/registry/stubs/workflows/{convert-to-pdf.md â marketing/convert-to-pdf.md} +0 -0
|
@@ -1,559 +1,566 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Unified code quality check script
|
|
3
|
-
# Can be run at different stages: pre-commit, pre-pr, or ci
|
|
4
|
-
# Usage: bash code-quality-check.sh [pre-commit|pre-pr|ci]
|
|
5
|
-
|
|
6
|
-
MODE="${1:-pre-pr}" # Default to pre-pr if not specified
|
|
7
|
-
|
|
8
|
-
set -e
|
|
9
|
-
|
|
10
|
-
echo "đ Running code quality checks (mode: $MODE)..."
|
|
11
|
-
echo ""
|
|
12
|
-
|
|
13
|
-
FAILED=0
|
|
14
|
-
WARNINGS=0
|
|
15
|
-
|
|
16
|
-
# Determine what files to check based on mode
|
|
17
|
-
if [ "$MODE" = "pre-commit" ]; then
|
|
18
|
-
# Pre-commit: only check staged files
|
|
19
|
-
TS_FILES=$(git diff --cached --name-only | grep -E '\.(ts|tsx)$' || true)
|
|
20
|
-
CHECK_SCOPE="staged files"
|
|
21
|
-
elif [ "$MODE" = "ci" ]; then
|
|
22
|
-
# CI: check only files changed in this PR
|
|
23
|
-
# Compare against the base branch (e.g., master or feature/*)
|
|
24
|
-
BASE_BRANCH="${GITHUB_BASE_REF:-origin/master}"
|
|
25
|
-
echo "âšī¸ Comparing against base: $BASE_BRANCH"
|
|
26
|
-
|
|
27
|
-
# Get all changed TypeScript files in the PR
|
|
28
|
-
TS_FILES=$(git diff --name-only $BASE_BRANCH...HEAD | grep -E '\.(ts|tsx)$' || true)
|
|
29
|
-
|
|
30
|
-
if [ -z "$TS_FILES" ]; then
|
|
31
|
-
echo "âšī¸ No TypeScript files changed in this PR"
|
|
32
|
-
CHECK_SCOPE="no files changed"
|
|
33
|
-
else
|
|
34
|
-
FILE_COUNT=$(echo "$TS_FILES" | wc -l | tr -d ' ')
|
|
35
|
-
CHECK_SCOPE="$FILE_COUNT changed file(s) in PR"
|
|
36
|
-
fi
|
|
37
|
-
elif [ "$MODE" = "pre-pr" ]; then
|
|
38
|
-
# Pre-PR: check entire src directory (local development)
|
|
39
|
-
TS_FILES=$(find src -name "*.ts" -o -name "*.tsx" 2>/dev/null || true)
|
|
40
|
-
CHECK_SCOPE="entire codebase"
|
|
41
|
-
fi
|
|
42
|
-
# Load configuration from config.json
|
|
43
|
-
CONFIG_FILE=".fraim/config.json"
|
|
44
|
-
if [ -f "$CONFIG_FILE" ]; then
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
echo ""
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
echo "
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
echo ""
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
echo "
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
echo ""
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
echo "
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
echo "
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
echo "
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
echo "
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
echo "
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
echo "
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
echo "
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
echo "
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
echo "
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
#
|
|
305
|
-
if [ -f "test.log" ] &&
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
echo "
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
echo "
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
echo "
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
echo "
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
echo "
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
echo "
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
echo "
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
echo "
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
fi
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
echo ""
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
echo ""
|
|
538
|
-
echo "
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Unified code quality check script
|
|
3
|
+
# Can be run at different stages: pre-commit, pre-pr, or ci
|
|
4
|
+
# Usage: bash code-quality-check.sh [pre-commit|pre-pr|ci]
|
|
5
|
+
|
|
6
|
+
MODE="${1:-pre-pr}" # Default to pre-pr if not specified
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
echo "đ Running code quality checks (mode: $MODE)..."
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
FAILED=0
|
|
14
|
+
WARNINGS=0
|
|
15
|
+
|
|
16
|
+
# Determine what files to check based on mode
|
|
17
|
+
if [ "$MODE" = "pre-commit" ]; then
|
|
18
|
+
# Pre-commit: only check staged files
|
|
19
|
+
TS_FILES=$(git diff --cached --name-only | grep -E '\.(ts|tsx)$' || true)
|
|
20
|
+
CHECK_SCOPE="staged files"
|
|
21
|
+
elif [ "$MODE" = "ci" ]; then
|
|
22
|
+
# CI: check only files changed in this PR
|
|
23
|
+
# Compare against the base branch (e.g., master or feature/*)
|
|
24
|
+
BASE_BRANCH="${GITHUB_BASE_REF:-origin/master}"
|
|
25
|
+
echo "âšī¸ Comparing against base: $BASE_BRANCH"
|
|
26
|
+
|
|
27
|
+
# Get all changed TypeScript files in the PR
|
|
28
|
+
TS_FILES=$(git diff --name-only $BASE_BRANCH...HEAD | grep -E '\.(ts|tsx)$' || true)
|
|
29
|
+
|
|
30
|
+
if [ -z "$TS_FILES" ]; then
|
|
31
|
+
echo "âšī¸ No TypeScript files changed in this PR"
|
|
32
|
+
CHECK_SCOPE="no files changed"
|
|
33
|
+
else
|
|
34
|
+
FILE_COUNT=$(echo "$TS_FILES" | wc -l | tr -d ' ')
|
|
35
|
+
CHECK_SCOPE="$FILE_COUNT changed file(s) in PR"
|
|
36
|
+
fi
|
|
37
|
+
elif [ "$MODE" = "pre-pr" ]; then
|
|
38
|
+
# Pre-PR: check entire src directory (local development)
|
|
39
|
+
TS_FILES=$(find src -name "*.ts" -o -name "*.tsx" 2>/dev/null || true)
|
|
40
|
+
CHECK_SCOPE="entire codebase"
|
|
41
|
+
fi
|
|
42
|
+
# Load configuration from config.json
|
|
43
|
+
CONFIG_FILE=".fraim/config.json"
|
|
44
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
45
|
+
echo "Error: Config file not found at $CONFIG_FILE" >&2
|
|
46
|
+
echo "Make sure you're running this script from the project root directory" >&2
|
|
47
|
+
echo "Current directory: $(pwd)" >&2
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
echo "Using config file: $CONFIG_FILE"
|
|
52
|
+
# Extract OpenAPI path using node
|
|
53
|
+
OPENAPI_PATH=$(node -e "const fs = require('fs'); try { const config = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf-8')); console.log(config.paths?.openapi || 'src/openapi/OpenAPI.json'); } catch(e) { console.log('src/openapi/OpenAPI.json'); }")
|
|
54
|
+
ARCH_DOC=$(node -e "const fs = require('fs'); try { const config = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf-8')); console.log('rules/' + (config.persona?.name?.toLowerCase() || 'persona') + '-architecture.md'); } catch(e) { console.log('rules/persona-architecture.md'); }")
|
|
55
|
+
else
|
|
56
|
+
OPENAPI_PATH="src/openapi/OpenAPI.json"
|
|
57
|
+
ARCH_DOC="rules/persona-architecture.md"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
echo "Checking: $CHECK_SCOPE"
|
|
61
|
+
echo ""
|
|
62
|
+
|
|
63
|
+
# GATE 1: Check for 'as any' type bypassing
|
|
64
|
+
echo "================================================"
|
|
65
|
+
echo "đ GATE 1: No 'as any' Type Bypassing"
|
|
66
|
+
echo "================================================"
|
|
67
|
+
|
|
68
|
+
if [ -z "$TS_FILES" ]; then
|
|
69
|
+
echo "âšī¸ No TypeScript files to check"
|
|
70
|
+
else
|
|
71
|
+
if echo "$TS_FILES" | xargs grep -n ' as any' 2>/dev/null; then
|
|
72
|
+
echo ""
|
|
73
|
+
echo "â FAILED: Found 'as any' type assertions"
|
|
74
|
+
echo " Rule: Use proper TypeScript interfaces, not 'as any'"
|
|
75
|
+
echo " See: rules/code-quality-and-debugging-patterns.md#rule-1"
|
|
76
|
+
FAILED=1
|
|
77
|
+
else
|
|
78
|
+
echo "â
PASSED: No 'as any' type bypassing found"
|
|
79
|
+
fi
|
|
80
|
+
fi
|
|
81
|
+
echo ""
|
|
82
|
+
|
|
83
|
+
# GATE 1.5: Tautological Tests Check
|
|
84
|
+
echo "================================================"
|
|
85
|
+
echo "đ GATE 1.5: No Tautological Test Patterns"
|
|
86
|
+
echo "================================================"
|
|
87
|
+
|
|
88
|
+
if bash "$(dirname "$0")/detect-tautological-tests.sh"; then
|
|
89
|
+
echo "â
PASSED: No tautological tests found"
|
|
90
|
+
else
|
|
91
|
+
echo "â FAILED: Tautological test patterns detected"
|
|
92
|
+
echo " Rule: Tests must fail if product code is removed. Don't test types/constants."
|
|
93
|
+
echo " See: rules/integrity-and-test-ethics.md#critical-invalid-test-patterns-tautology-type-testing"
|
|
94
|
+
FAILED=1
|
|
95
|
+
fi
|
|
96
|
+
echo ""
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# GATE 2: TypeScript Compilation
|
|
100
|
+
echo "================================================"
|
|
101
|
+
echo "đ GATE 2: TypeScript Compilation"
|
|
102
|
+
echo "================================================"
|
|
103
|
+
|
|
104
|
+
if command -v npx &> /dev/null; then
|
|
105
|
+
if npx tsc --noEmit --skipLibCheck 2>&1 | head -50; then
|
|
106
|
+
echo "â
PASSED: TypeScript compilation successful"
|
|
107
|
+
else
|
|
108
|
+
echo "â FAILED: TypeScript compilation errors"
|
|
109
|
+
echo " Fix all TypeScript errors before proceeding"
|
|
110
|
+
FAILED=1
|
|
111
|
+
fi
|
|
112
|
+
else
|
|
113
|
+
echo "âšī¸ npx not found - skipping TypeScript check"
|
|
114
|
+
fi
|
|
115
|
+
echo ""
|
|
116
|
+
|
|
117
|
+
# GATE 3: Linter
|
|
118
|
+
echo "================================================"
|
|
119
|
+
echo "đ GATE 3: Linter (ESLint)"
|
|
120
|
+
echo "================================================"
|
|
121
|
+
|
|
122
|
+
if command -v npm &> /dev/null; then
|
|
123
|
+
if npm run lint 2>&1 | head -50; then
|
|
124
|
+
echo "â
PASSED: Linter checks passed"
|
|
125
|
+
else
|
|
126
|
+
echo "â ī¸ WARNING: Linter has issues"
|
|
127
|
+
WARNINGS=1
|
|
128
|
+
fi
|
|
129
|
+
else
|
|
130
|
+
echo "âšī¸ npm not found - skipping lint check"
|
|
131
|
+
fi
|
|
132
|
+
echo ""
|
|
133
|
+
|
|
134
|
+
# GATE 4: Git Status (pre-pr and ci only)
|
|
135
|
+
if [ "$MODE" != "pre-commit" ]; then
|
|
136
|
+
echo "================================================"
|
|
137
|
+
echo "đ GATE 4: Git Status"
|
|
138
|
+
echo "================================================"
|
|
139
|
+
|
|
140
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
141
|
+
echo "â ī¸ WARNING: Uncommitted changes detected"
|
|
142
|
+
git status --short
|
|
143
|
+
WARNINGS=1
|
|
144
|
+
else
|
|
145
|
+
echo "â
PASSED: Working directory is clean"
|
|
146
|
+
fi
|
|
147
|
+
echo ""
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# GATE 5: Commits Pushed (pre-pr only)
|
|
151
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
152
|
+
echo "================================================"
|
|
153
|
+
echo "đ GATE 5: Commits Pushed to Remote"
|
|
154
|
+
echo "================================================"
|
|
155
|
+
|
|
156
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
157
|
+
if git log origin/$CURRENT_BRANCH..$CURRENT_BRANCH --oneline 2>/dev/null | grep . > /dev/null; then
|
|
158
|
+
echo "â ī¸ WARNING: Unpushed commits detected"
|
|
159
|
+
git log origin/$CURRENT_BRANCH..$CURRENT_BRANCH --oneline
|
|
160
|
+
WARNINGS=1
|
|
161
|
+
else
|
|
162
|
+
echo "â
PASSED: All commits pushed to remote"
|
|
163
|
+
fi
|
|
164
|
+
echo ""
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# GATE 6: PR Comments Addressed (pre-pr only)
|
|
168
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
169
|
+
echo "================================================"
|
|
170
|
+
echo "đ GATE 6: PR Comments Addressed"
|
|
171
|
+
echo "================================================"
|
|
172
|
+
|
|
173
|
+
# Check if gh CLI is available
|
|
174
|
+
if ! command -v gh &> /dev/null; then
|
|
175
|
+
echo "âšī¸ gh CLI not found - skipping PR comment check"
|
|
176
|
+
echo ""
|
|
177
|
+
else
|
|
178
|
+
# Try to get PR number for current branch
|
|
179
|
+
PR_NUMBER=$(gh pr view --json number --jq '.number' 2>/dev/null || echo "")
|
|
180
|
+
|
|
181
|
+
if [ -z "$PR_NUMBER" ]; then
|
|
182
|
+
echo "âšī¸ No PR found for current branch - skipping comment check"
|
|
183
|
+
else
|
|
184
|
+
echo "Found PR #$PR_NUMBER"
|
|
185
|
+
|
|
186
|
+
# Get PR comments count
|
|
187
|
+
COMMENT_COUNT=$(gh api repos/:owner/:repo/pulls/$PR_NUMBER/comments --jq 'length' 2>/dev/null || echo "0")
|
|
188
|
+
|
|
189
|
+
if [ "$COMMENT_COUNT" -gt 0 ]; then
|
|
190
|
+
echo "â ī¸ WARNING: PR has $COMMENT_COUNT review comments"
|
|
191
|
+
echo " Please ensure all comments are addressed before marking ready for review"
|
|
192
|
+
echo ""
|
|
193
|
+
echo " To view comments:"
|
|
194
|
+
echo " gh pr view $PR_NUMBER --comments"
|
|
195
|
+
echo ""
|
|
196
|
+
echo " To reply to a comment:"
|
|
197
|
+
echo " gh api repos/:owner/:repo/pulls/comments/{comment_id}/replies -X POST -f body='your response'"
|
|
198
|
+
WARNINGS=1
|
|
199
|
+
else
|
|
200
|
+
echo "â
PASSED: No outstanding PR comments"
|
|
201
|
+
fi
|
|
202
|
+
fi
|
|
203
|
+
fi
|
|
204
|
+
echo ""
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# GATE 7: Build Evidence Verification (pre-pr only)
|
|
208
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
209
|
+
echo "================================================"
|
|
210
|
+
echo "đ GATE 7: Build Evidence Verification"
|
|
211
|
+
echo "================================================"
|
|
212
|
+
|
|
213
|
+
# Check if build has been run (look for build output or recent dist/ directory)
|
|
214
|
+
BUILD_EVIDENCE_FOUND=0
|
|
215
|
+
|
|
216
|
+
# Method 1: Check if dist/ directory exists and has recent files
|
|
217
|
+
if [ -d "dist" ]; then
|
|
218
|
+
# Check if dist has files modified in last 2 hours
|
|
219
|
+
if find dist -type f -newermt "2 hours ago" 2>/dev/null | grep -q .; then
|
|
220
|
+
BUILD_EVIDENCE_FOUND=1
|
|
221
|
+
echo "â
Found: Recent files in dist/ directory"
|
|
222
|
+
fi
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# Method 2: Check for build logs
|
|
226
|
+
if [ -f "server.log" ] && tail -50 server.log 2>/dev/null | grep -qiE "(Build.*success|Compiled successfully|build.*complete)"; then
|
|
227
|
+
BUILD_EVIDENCE_FOUND=1
|
|
228
|
+
echo "â
Found: Build success in server.log"
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# Method 3: Check if TypeScript compilation succeeds now
|
|
232
|
+
if command -v npx &> /dev/null; then
|
|
233
|
+
if npx tsc --noEmit --skipLibCheck > /dev/null 2>&1; then
|
|
234
|
+
BUILD_EVIDENCE_FOUND=1
|
|
235
|
+
echo "â
Found: TypeScript compilation succeeds (runtime check)"
|
|
236
|
+
fi
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
if [ $BUILD_EVIDENCE_FOUND -eq 0 ]; then
|
|
240
|
+
echo "â FAILED: No build evidence found"
|
|
241
|
+
echo " Required: Run 'npm run build' and verify it succeeds before marking PR ready"
|
|
242
|
+
echo " Evidence can be: dist/ files, build logs, or successful compilation"
|
|
243
|
+
FAILED=1
|
|
244
|
+
else
|
|
245
|
+
echo "â
PASSED: Build evidence verified"
|
|
246
|
+
fi
|
|
247
|
+
echo ""
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
# GATE 8: Test Execution Verification (pre-pr only)
|
|
251
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
252
|
+
echo "================================================"
|
|
253
|
+
echo "đ GATE 8: Test Execution Verification"
|
|
254
|
+
echo "================================================"
|
|
255
|
+
|
|
256
|
+
# Check if test files were created in this PR/branch
|
|
257
|
+
NEW_TEST_FILES=$(find . -name "test-*.ts" -newer .git/HEAD 2>/dev/null | grep -v node_modules | head -10 || true)
|
|
258
|
+
|
|
259
|
+
if [ -n "$NEW_TEST_FILES" ]; then
|
|
260
|
+
echo "â ī¸ WARNING: New test files detected:"
|
|
261
|
+
echo "$NEW_TEST_FILES" | sed 's/^/ - /'
|
|
262
|
+
echo " Rule: All new test files must be executed before submitting evidence"
|
|
263
|
+
echo " Check: Verify test execution results are included in PR evidence"
|
|
264
|
+
WARNINGS=1
|
|
265
|
+
else
|
|
266
|
+
echo "â
PASSED: No new test files detected (or tests were executed)"
|
|
267
|
+
fi
|
|
268
|
+
|
|
269
|
+
# Check evidence files for "pending" automated validations
|
|
270
|
+
EVIDENCE_FILES=$(find . -name "implementation-evidence-*.md" -o -name "*evidence*.md" 2>/dev/null | head -5 || true)
|
|
271
|
+
if [ -n "$EVIDENCE_FILES" ]; then
|
|
272
|
+
PENDING_AUTO=$(grep -l "pending.*automated\|pending.*test\|manual validation.*pending" $EVIDENCE_FILES 2>/dev/null | head -3 || true)
|
|
273
|
+
if [ -n "$PENDING_AUTO" ]; then
|
|
274
|
+
echo "â ī¸ WARNING: Evidence files mention 'pending' automated validations:"
|
|
275
|
+
echo "$PENDING_AUTO" | sed 's/^/ - /'
|
|
276
|
+
echo " Rule: Cannot mark automated validations as 'pending' without attempting them first"
|
|
277
|
+
echo " Check: Verify all test files have been executed before submitting evidence"
|
|
278
|
+
WARNINGS=1
|
|
279
|
+
fi
|
|
280
|
+
fi
|
|
281
|
+
echo ""
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
# GATE 9: Test Evidence Verification (pre-pr only)
|
|
285
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
286
|
+
echo "================================================"
|
|
287
|
+
echo "đ GATE 9: Test Evidence Verification"
|
|
288
|
+
echo "================================================"
|
|
289
|
+
|
|
290
|
+
TEST_EVIDENCE_FOUND=0
|
|
291
|
+
|
|
292
|
+
# Method 1: Check PR comments for test evidence
|
|
293
|
+
if command -v gh &> /dev/null; then
|
|
294
|
+
PR_NUMBER=$(gh pr view --json number --jq '.number' 2>/dev/null || echo "")
|
|
295
|
+
if [ -n "$PR_NUMBER" ]; then
|
|
296
|
+
# Search PR comments for test evidence keywords
|
|
297
|
+
if gh api repos/:owner/:repo/pulls/$PR_NUMBER/comments --jq '.[].body' 2>/dev/null | grep -qiE "(test.*pass|test.*evidence|test.*result|exit code.*0|â
.*test)" 2>/dev/null; then
|
|
298
|
+
TEST_EVIDENCE_FOUND=1
|
|
299
|
+
echo "â
Found: Test evidence in PR comments"
|
|
300
|
+
fi
|
|
301
|
+
fi
|
|
302
|
+
fi
|
|
303
|
+
|
|
304
|
+
# Method 2: Check for test log files with pass indicators
|
|
305
|
+
if [ -f "test.log" ] && grep -qE "(pass|PASS|â
|exit code.*0)" test.log 2>/dev/null; then
|
|
306
|
+
TEST_EVIDENCE_FOUND=1
|
|
307
|
+
echo "â
Found: Test evidence in test.log"
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
# Method 3: Check for npm test exit codes (if test.log exists and shows recent runs)
|
|
311
|
+
# Note: We don't run tests here (too slow), just check for evidence of recent test runs
|
|
312
|
+
if [ -f "test.log" ] && [ -n "$(find test.log -mmin -60 2>/dev/null)" ]; then
|
|
313
|
+
# If test.log was modified in last hour, assume tests were run
|
|
314
|
+
if grep -qE "(pass|PASS|â
)" test.log 2>/dev/null; then
|
|
315
|
+
TEST_EVIDENCE_FOUND=1
|
|
316
|
+
echo "â
Found: Recent test run in test.log"
|
|
317
|
+
fi
|
|
318
|
+
fi
|
|
319
|
+
|
|
320
|
+
if [ $TEST_EVIDENCE_FOUND -eq 0 ]; then
|
|
321
|
+
echo "â FAILED: No test evidence found"
|
|
322
|
+
echo " Required: Provide test evidence before marking PR ready"
|
|
323
|
+
echo " Evidence can be: PR comment with test results, test.log file, or passing test run"
|
|
324
|
+
echo " Evidence must include exit codes and test names"
|
|
325
|
+
FAILED=1
|
|
326
|
+
else
|
|
327
|
+
echo "â
PASSED: Test evidence verified"
|
|
328
|
+
fi
|
|
329
|
+
echo ""
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
# GATE 11: Issue Label Verification (pre-pr only)
|
|
333
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
334
|
+
echo "================================================"
|
|
335
|
+
echo "đ GATE 10: Issue Label Verification"
|
|
336
|
+
echo "================================================"
|
|
337
|
+
|
|
338
|
+
if ! command -v gh &> /dev/null; then
|
|
339
|
+
echo "âšī¸ gh CLI not found - skipping issue label check"
|
|
340
|
+
echo ""
|
|
341
|
+
else
|
|
342
|
+
# Extract issue number from branch name
|
|
343
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
344
|
+
ISSUE_NUMBER=$(echo "$CURRENT_BRANCH" | sed -n 's/feature\/\([0-9]\+\).*/\1/p')
|
|
345
|
+
|
|
346
|
+
if [ -z "$ISSUE_NUMBER" ]; then
|
|
347
|
+
echo "â ī¸ WARNING: Could not extract issue number from branch: $CURRENT_BRANCH"
|
|
348
|
+
echo " Expected format: feature/533-slug"
|
|
349
|
+
echo " Skipping label verification"
|
|
350
|
+
else
|
|
351
|
+
echo "Checking labels for issue #$ISSUE_NUMBER"
|
|
352
|
+
|
|
353
|
+
# Get issue labels
|
|
354
|
+
LABELS=$(gh api repos/:owner/:repo/issues/$ISSUE_NUMBER --jq '.labels[].name' 2>/dev/null || echo "")
|
|
355
|
+
|
|
356
|
+
if [ -z "$LABELS" ]; then
|
|
357
|
+
echo "â FAILED: Could not fetch issue labels"
|
|
358
|
+
echo " Check that issue #$ISSUE_NUMBER exists and is accessible"
|
|
359
|
+
FAILED=1
|
|
360
|
+
else
|
|
361
|
+
# Check for phase label
|
|
362
|
+
HAS_PHASE_LABEL=false
|
|
363
|
+
PHASE_LABEL=""
|
|
364
|
+
while IFS= read -r label; do
|
|
365
|
+
case "$label" in
|
|
366
|
+
phase:spec|phase:design|phase:impl|phase:tests)
|
|
367
|
+
HAS_PHASE_LABEL=true
|
|
368
|
+
PHASE_LABEL="$label"
|
|
369
|
+
break
|
|
370
|
+
;;
|
|
371
|
+
esac
|
|
372
|
+
done <<< "$LABELS"
|
|
373
|
+
|
|
374
|
+
# Check status labels
|
|
375
|
+
HAS_STATUS_WIP=false
|
|
376
|
+
HAS_STATUS_NEEDS_REVIEW=false
|
|
377
|
+
while IFS= read -r label; do
|
|
378
|
+
case "$label" in
|
|
379
|
+
status:wip)
|
|
380
|
+
HAS_STATUS_WIP=true
|
|
381
|
+
;;
|
|
382
|
+
status:needs-review)
|
|
383
|
+
HAS_STATUS_NEEDS_REVIEW=true
|
|
384
|
+
;;
|
|
385
|
+
esac
|
|
386
|
+
done <<< "$LABELS"
|
|
387
|
+
|
|
388
|
+
# Validation
|
|
389
|
+
if [ "$HAS_PHASE_LABEL" = false ]; then
|
|
390
|
+
echo "â FAILED: Issue missing phase label"
|
|
391
|
+
echo " Required: phase:spec, phase:design, phase:impl, or phase:tests"
|
|
392
|
+
echo " Current labels: $LABELS"
|
|
393
|
+
FAILED=1
|
|
394
|
+
elif [ "$HAS_STATUS_NEEDS_REVIEW" = true ] && [ "$HAS_STATUS_WIP" = true ]; then
|
|
395
|
+
echo "â FAILED: Issue has both status:wip and status:needs-review"
|
|
396
|
+
echo " Remove status:wip before marking ready for review"
|
|
397
|
+
echo " Current labels: $LABELS"
|
|
398
|
+
FAILED=1
|
|
399
|
+
else
|
|
400
|
+
echo "â
PASSED: Issue labels correct"
|
|
401
|
+
echo " Phase: $PHASE_LABEL"
|
|
402
|
+
if [ "$HAS_STATUS_NEEDS_REVIEW" = true ]; then
|
|
403
|
+
echo " Status: status:needs-review"
|
|
404
|
+
elif [ "$HAS_STATUS_WIP" = true ]; then
|
|
405
|
+
echo " Status: status:wip"
|
|
406
|
+
else
|
|
407
|
+
echo " Status: (none)"
|
|
408
|
+
fi
|
|
409
|
+
fi
|
|
410
|
+
fi
|
|
411
|
+
fi
|
|
412
|
+
fi
|
|
413
|
+
echo ""
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
# GATE 10: Validation Plan Coverage (pre-pr only)
|
|
417
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
418
|
+
echo "================================================"
|
|
419
|
+
echo "đ GATE 9: Test Coverage Alignment"
|
|
420
|
+
echo "================================================"
|
|
421
|
+
|
|
422
|
+
# Extract issue number from branch
|
|
423
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
424
|
+
ISSUE_NUMBER=$(echo "$CURRENT_BRANCH" | sed -n 's/feature\/\([0-9]\+\).*/\1/p')
|
|
425
|
+
|
|
426
|
+
if [ -z "$ISSUE_NUMBER" ]; then
|
|
427
|
+
echo "âšī¸ Could not extract issue number from branch - skipping validation plan check"
|
|
428
|
+
elif command -v npx &> /dev/null; then
|
|
429
|
+
# Run validation coverage checker
|
|
430
|
+
COVERAGE_OUTPUT=$(GIT_BRANCH="$CURRENT_BRANCH" npx tsx "$(dirname "$0")/validate-test-coverage.ts" "$ISSUE_NUMBER" 2>&1)
|
|
431
|
+
COVERAGE_EXIT=$?
|
|
432
|
+
|
|
433
|
+
echo "$COVERAGE_OUTPUT"
|
|
434
|
+
|
|
435
|
+
if [ $COVERAGE_EXIT -eq 1 ]; then
|
|
436
|
+
# Coverage incomplete
|
|
437
|
+
FAILED=1
|
|
438
|
+
elif echo "$COVERAGE_OUTPUT" | grep -qi "skipped\|no.*validation plan\|no spec"; then
|
|
439
|
+
# No spec/design or no validation plan - Gate 9 warns but doesn't block
|
|
440
|
+
echo "â ī¸ WARNING: Validation plan check skipped (no spec/design or no validation plan)"
|
|
441
|
+
echo " This is acceptable, but consider adding validation plan to spec/design for future issues"
|
|
442
|
+
WARNINGS=1
|
|
443
|
+
fi
|
|
444
|
+
else
|
|
445
|
+
echo "âšī¸ npx not available - skipping validation plan coverage check"
|
|
446
|
+
echo " Install: npm (Node.js package manager)"
|
|
447
|
+
fi
|
|
448
|
+
echo ""
|
|
449
|
+
fi
|
|
450
|
+
|
|
451
|
+
# GATE 12: ChatGPT Length Limits (pre-pr only)
|
|
452
|
+
if [ "$MODE" = "pre-pr" ]; then
|
|
453
|
+
echo "================================================"
|
|
454
|
+
echo "đ GATE 11: ChatGPT Length Limits"
|
|
455
|
+
echo "================================================"
|
|
456
|
+
|
|
457
|
+
CHATGPT_LIMITS_FAILED=0
|
|
458
|
+
|
|
459
|
+
# Check instructions.txt length (8,000 char limit)
|
|
460
|
+
if [ -f "src/openapi/instructions.txt" ]; then
|
|
461
|
+
if command -v python &> /dev/null || command -v python3 &> /dev/null; then
|
|
462
|
+
PYTHON_CMD=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
|
|
463
|
+
INST_LENGTH=$($PYTHON_CMD -c "f = open('src/openapi/instructions.txt', 'r', encoding='utf-8'); content = f.read(); f.close(); print(len(content))" 2>/dev/null || echo "0")
|
|
464
|
+
|
|
465
|
+
if [ "$INST_LENGTH" -gt 8000 ]; then
|
|
466
|
+
echo "â FAILED: instructions.txt exceeds 8,000 character limit"
|
|
467
|
+
echo " Current length: $INST_LENGTH characters"
|
|
468
|
+
echo " Limit: 8,000 characters"
|
|
469
|
+
echo " Solution: Move detailed content to KB files (KB-*.txt) and reference them"
|
|
470
|
+
echo " See: $ARCH_DOC#chatgpt-length-limitations"
|
|
471
|
+
CHATGPT_LIMITS_FAILED=1
|
|
472
|
+
else
|
|
473
|
+
echo "â
PASSED: instructions.txt length ($INST_LENGTH chars) within limit (8,000)"
|
|
474
|
+
fi
|
|
475
|
+
else
|
|
476
|
+
echo "âšī¸ python not found - skipping instructions.txt length check"
|
|
477
|
+
fi
|
|
478
|
+
fi
|
|
479
|
+
|
|
480
|
+
# Check OpenAPI operation description lengths (300 char limit)
|
|
481
|
+
if [ -f "$OPENAPI_PATH" ]; then
|
|
482
|
+
if command -v python &> /dev/null || command -v python3 &> /dev/null; then
|
|
483
|
+
PYTHON_CMD=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
|
|
484
|
+
LONG_DESCS=$($PYTHON_CMD -c "
|
|
485
|
+
import json
|
|
486
|
+
try:
|
|
487
|
+
f = open('$OPENAPI_PATH', 'r', encoding='utf-8')
|
|
488
|
+
spec = json.load(f)
|
|
489
|
+
f.close()
|
|
490
|
+
violations = []
|
|
491
|
+
for path, methods in spec.get('paths', {}).items():
|
|
492
|
+
for method, details in methods.items():
|
|
493
|
+
if isinstance(details, dict) and 'description' in details:
|
|
494
|
+
desc = details['description']
|
|
495
|
+
if len(desc) > 300:
|
|
496
|
+
violations.append(f'{path} {method.upper()}: {len(desc)} chars')
|
|
497
|
+
if violations:
|
|
498
|
+
print('\n'.join(violations))
|
|
499
|
+
else:
|
|
500
|
+
print('OK')
|
|
501
|
+
except Exception as e:
|
|
502
|
+
print(f'ERROR: {e}')
|
|
503
|
+
" 2>/dev/null || echo "ERROR")
|
|
504
|
+
|
|
505
|
+
if [ "$LONG_DESCS" != "OK" ] && [ -n "$LONG_DESCS" ] && [ "$LONG_DESCS" != "ERROR" ]; then
|
|
506
|
+
echo "â FAILED: OpenAPI operation descriptions exceed 300 character limit"
|
|
507
|
+
echo "$LONG_DESCS" | while IFS= read -r line; do
|
|
508
|
+
echo " $line"
|
|
509
|
+
done
|
|
510
|
+
echo " Solution: Shorten descriptions, move details to KB files, reference KB files"
|
|
511
|
+
echo " See: $ARCH_DOC#chatgpt-length-limitations"
|
|
512
|
+
CHATGPT_LIMITS_FAILED=1
|
|
513
|
+
elif [ "$LONG_DESCS" = "ERROR" ]; then
|
|
514
|
+
echo "â ī¸ WARNING: Could not validate OpenAPI description lengths (JSON parsing error)"
|
|
515
|
+
WARNINGS=1
|
|
516
|
+
else
|
|
517
|
+
echo "â
PASSED: All OpenAPI operation descriptions within limit (300 chars)"
|
|
518
|
+
fi
|
|
519
|
+
else
|
|
520
|
+
echo "âšī¸ python not found - skipping OpenAPI description length check"
|
|
521
|
+
fi
|
|
522
|
+
fi
|
|
523
|
+
|
|
524
|
+
if [ $CHATGPT_LIMITS_FAILED -eq 1 ]; then
|
|
525
|
+
FAILED=1
|
|
526
|
+
fi
|
|
527
|
+
echo ""
|
|
528
|
+
fi
|
|
529
|
+
|
|
530
|
+
# Summary
|
|
531
|
+
echo "================================================"
|
|
532
|
+
echo "đ QUALITY CHECK SUMMARY ($MODE mode)"
|
|
533
|
+
echo "================================================"
|
|
534
|
+
echo ""
|
|
535
|
+
|
|
536
|
+
if [ $FAILED -eq 1 ]; then
|
|
537
|
+
echo "â CHECKS FAILED"
|
|
538
|
+
echo ""
|
|
539
|
+
echo "Critical issues found. Cannot proceed."
|
|
540
|
+
echo "See rules/code-quality-and-debugging-patterns.md"
|
|
541
|
+
exit 1
|
|
542
|
+
elif [ $WARNINGS -gt 0 ]; then
|
|
543
|
+
echo "â ī¸ CHECKS PASSED WITH WARNINGS"
|
|
544
|
+
echo ""
|
|
545
|
+
echo "Some warnings found. Consider addressing before proceeding."
|
|
546
|
+
|
|
547
|
+
if [ "$MODE" = "pre-commit" ]; then
|
|
548
|
+
echo "You can still commit, but consider fixing warnings."
|
|
549
|
+
exit 0
|
|
550
|
+
else
|
|
551
|
+
exit 0
|
|
552
|
+
fi
|
|
553
|
+
else
|
|
554
|
+
echo "â
ALL CHECKS PASSED"
|
|
555
|
+
echo ""
|
|
556
|
+
|
|
557
|
+
if [ "$MODE" = "pre-commit" ]; then
|
|
558
|
+
echo "Ready to commit!"
|
|
559
|
+
elif [ "$MODE" = "pre-pr" ]; then
|
|
560
|
+
echo "Ready to create PR!"
|
|
561
|
+
echo "Run: gh pr create --title \"your title\" --body \"your description\""
|
|
562
|
+
else
|
|
563
|
+
echo "CI checks complete!"
|
|
564
|
+
fi
|
|
565
|
+
exit 0
|
|
566
|
+
fi
|