guardian-framework 0.1.99 → 0.1.101

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 (29) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/exports.js +1 -1
  3. package/package.json +1 -1
  4. package/templates/pi/preflight_report.json +1 -1
  5. package/templates/pi/scripts/languages/go/validate-architecture.sh +6 -6
  6. package/templates/pi/scripts/languages/go/validate-canonical.sh +6 -6
  7. package/templates/pi/scripts/languages/go/validate-ci.sh +1 -1
  8. package/templates/pi/scripts/languages/go/validate-integration.sh +2 -2
  9. package/templates/pi/scripts/languages/go/validate-operations.sh +2 -2
  10. package/templates/pi/scripts/languages/go/validate-security.sh +3 -3
  11. package/templates/pi/scripts/languages/java/validate-annotations.sh +1 -1
  12. package/templates/pi/scripts/languages/java/validate-architecture.sh +1 -1
  13. package/templates/pi/scripts/languages/java/validate-canonical.sh +2 -2
  14. package/templates/pi/scripts/languages/java/validate-integration.sh +10 -10
  15. package/templates/pi/scripts/languages/java/validate-operations.sh +4 -4
  16. package/templates/pi/scripts/languages/python/validate-architecture.sh +5 -5
  17. package/templates/pi/scripts/languages/python/validate-canonical.sh +4 -4
  18. package/templates/pi/scripts/languages/python/validate-integration.sh +2 -2
  19. package/templates/pi/scripts/languages/python/validate-security.sh +2 -2
  20. package/templates/pi/scripts/languages/rust/validate-architecture.sh +6 -6
  21. package/templates/pi/scripts/languages/rust/validate-canonical.sh +5 -5
  22. package/templates/pi/scripts/languages/rust/validate-integration.sh +3 -3
  23. package/templates/pi/scripts/languages/rust/validate-security.sh +2 -2
  24. package/templates/pi/scripts/languages/rust/validate-tests.sh +3 -3
  25. package/templates/pi/scripts/languages/typescript/validate-architecture.sh +4 -4
  26. package/templates/pi/scripts/languages/typescript/validate-canonical.sh +5 -5
  27. package/templates/pi/scripts/languages/typescript/validate-integration.sh +6 -6
  28. package/templates/pi/scripts/languages/typescript/validate-operations.sh +7 -7
  29. package/templates/pi/scripts/languages/typescript/validate-security.sh +6 -6
package/dist/cli.js CHANGED
@@ -3197,7 +3197,7 @@ __export(exports_package, {
3197
3197
  bin: () => bin,
3198
3198
  author: () => author
3199
3199
  });
3200
- var name = "guardian-framework", version = "0.1.99", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
3200
+ var name = "guardian-framework", version = "0.1.101", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
3201
3201
  var init_package = __esm(() => {
3202
3202
  exports = {
3203
3203
  ".": {
package/dist/exports.js CHANGED
@@ -1982,7 +1982,7 @@ __export(exports_package, {
1982
1982
  bin: () => bin,
1983
1983
  author: () => author
1984
1984
  });
1985
- var name = "guardian-framework", version = "0.1.99", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
1985
+ var name = "guardian-framework", version = "0.1.101", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
1986
1986
  var init_package = __esm(() => {
1987
1987
  exports = {
1988
1988
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardian-framework",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "description": "Token-optimized agentic framework scaffolder with pi-first architecture",
5
5
  "type": "module",
6
6
  "main": "dist/exports.js",
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-19T05:50:01Z",
2
+ "timestamp": "2026-07-19T06:04:23Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -40,7 +40,7 @@ fi
40
40
  echo ""
41
41
  echo "--- Canonical References ---"
42
42
  if [ -d ".pi/architecture/modules" ]; then
43
- MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
43
+ MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
44
44
  pass "Canonical architecture documents found ($MODULE_COUNT modules)"
45
45
  else
46
46
  warn "No canonical architecture directory (.pi/architecture/modules) found"
@@ -54,7 +54,7 @@ echo "--- Domain Models ---"
54
54
  DOMAIN_FILES=0
55
55
  for dir in "internal/domain" "pkg/domain"; do
56
56
  if [ -d "$dir" ]; then
57
- COUNT=$(grep -rlE 'type\s+\w+\s+struct' "$dir" --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
57
+ COUNT=$(grep -rlE 'type\s+\w+\s+struct' "$dir" --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
58
58
  DOMAIN_FILES=$((DOMAIN_FILES + COUNT))
59
59
  fi
60
60
  done
@@ -73,7 +73,7 @@ VIOLATIONS=0
73
73
  for dir in "internal/domain" "pkg/domain"; do
74
74
  if [ -d "$dir" ]; then
75
75
  # Domain should not import from infrastructure or cmd
76
- VIOLATIONS=$((VIOLATIONS + $(grep -rlE 'import.*"(.*/infrastructure|/cmd)"' "$dir" --include="*.go" 2>/dev/null | wc -l | tr -d ' ')))
76
+ VIOLATIONS=$((VIOLATIONS + $(grep -rlE 'import.*"(.*/infrastructure|/cmd)"' "$dir" --include="*.go" 2>/dev/null | wc -l | tr -d ' '))) || true
77
77
  fi
78
78
  done
79
79
  if [ "$VIOLATIONS" -eq 0 ]; then
@@ -88,8 +88,8 @@ fi
88
88
  echo ""
89
89
  echo "--- Error Handling ---"
90
90
  if [ -f "go.mod" ]; then
91
- ERROR_VARIABS=$(grep -rE 'var\s+Err\w+\s*=\s*(errors\.New|fmt\.Errorf)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
92
- ERROR_STRUCTS=$(grep -rE 'type\s+\w*Error\w*\s+struct' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
91
+ ERROR_VARIABS=$(grep -rE 'var\s+Err\w+\s*=\s*(errors\.New|fmt\.Errorf)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
92
+ ERROR_STRUCTS=$(grep -rE 'type\s+\w*Error\w*\s+struct' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
93
93
  TOTAL=$((ERROR_VARIABS + ERROR_STRUCTS))
94
94
  if [ "$TOTAL" -gt 0 ]; then
95
95
  pass "Custom error types defined ($TOTAL definitions)"
@@ -106,7 +106,7 @@ fi
106
106
  echo ""
107
107
  echo "--- Interfaces ---"
108
108
  if [ -f "go.mod" ]; then
109
- INTERFACE_COUNT=$(grep -rE 'type\s+\w+\s+interface' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
109
+ INTERFACE_COUNT=$(grep -rE 'type\s+\w+\s+interface' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
110
110
  if [ "$INTERFACE_COUNT" -gt 0 ]; then
111
111
  pass "Interface definitions found ($INTERFACE_COUNT interfaces)"
112
112
  else
@@ -20,9 +20,9 @@ echo ""
20
20
  # ---------------------------------------------------------------------------
21
21
  echo "--- Architecture Reference Tracing ---"
22
22
  if [ -f "go.mod" ]; then
23
- GO_FILES=$(find . -name "*.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ')
23
+ GO_FILES=$(find . -name "*.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ') || true
24
24
  if [ "$GO_FILES" -gt 0 ]; then
25
- CANONICAL_REFS=$(grep -rlE '//\s*(Canonical:|@canonical|Reference:|Canonical\s+ref)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
25
+ CANONICAL_REFS=$(grep -rlE '//\s*(Canonical:|@canonical|Reference:|Canonical\s+ref)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
26
26
  if [ "$CANONICAL_REFS" -gt 0 ]; then
27
27
  PCT=$((CANONICAL_REFS * 100 / GO_FILES))
28
28
  pass "Canonical references found in ${CANONICAL_REFS}/${GO_FILES} Go files (${PCT}%)"
@@ -74,8 +74,8 @@ fi
74
74
  echo ""
75
75
  echo "--- Package Documentation ---"
76
76
  if [ -f "go.mod" ]; then
77
- PKG_FILES_WITH_DOC=$(grep -rlE '//\s*Package\s+\w+\s+(implements|provides|defines|is|contains)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
78
- GO_PACKAGES=$(go list ./... 2>/dev/null | wc -l | tr -d ' ')
77
+ PKG_FILES_WITH_DOC=$(grep -rlE '//\s*Package\s+\w+\s+(implements|provides|defines|is|contains)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
78
+ GO_PACKAGES=$(go list ./... 2>/dev/null | wc -l | tr -d ' ') || true
79
79
  if [ "$GO_PACKAGES" -gt 0 ] && [ "$PKG_FILES_WITH_DOC" -gt 0 ]; then
80
80
  pass "Package documentation found in $PKG_FILES_WITH_DOC files"
81
81
  else
@@ -91,9 +91,9 @@ fi
91
91
  echo ""
92
92
  echo "--- ADR Linkage ---"
93
93
  if [ -d ".pi/architecture/decisions" ]; then
94
- ADR_COUNT=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
94
+ ADR_COUNT=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
95
95
  if [ "$ADR_COUNT" -gt 0 ]; then
96
- ADR_REFS=$(grep -rlE '//\s*ADR[-_]?\d+' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
96
+ ADR_REFS=$(grep -rlE '//\s*ADR[-_]?\d+' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
97
97
  if [ "$ADR_REFS" -gt 0 ]; then
98
98
  pass "ADR references found in $ADR_REFS Go files"
99
99
  else
@@ -42,7 +42,7 @@ fi
42
42
  echo ""
43
43
  echo "--- Tests ---"
44
44
  if [ -f "go.mod" ]; then
45
- TEST_FILES=$(find . -name "*_test.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ')
45
+ TEST_FILES=$(find . -name "*_test.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ') || true
46
46
  if [ "$TEST_FILES" -gt 0 ]; then
47
47
  if go test ./... -count=1 2>/dev/null; then
48
48
  pass "All tests passed"
@@ -65,7 +65,7 @@ fi
65
65
  echo ""
66
66
  echo "--- Contract Tests ---"
67
67
  if [ -f "go.mod" ]; then
68
- CONTRACT_FILES=$(find . -name "*_contract_test.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ')
68
+ CONTRACT_FILES=$(find . -name "*_contract_test.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ') || true
69
69
  if [ "$CONTRACT_FILES" -gt 0 ]; then
70
70
  pass "Contract test files found ($CONTRACT_FILES files)"
71
71
  else
@@ -123,7 +123,7 @@ fi
123
123
  echo ""
124
124
  echo "--- HTTP Integration ---"
125
125
  if [ -f "go.mod" ]; then
126
- HTTPTEST_COUNT=$(grep -rl '"net/http/httptest"' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
126
+ HTTPTEST_COUNT=$(grep -rl '"net/http/httptest"' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
127
127
  if [ "$HTTPTEST_COUNT" -gt 0 ]; then
128
128
  pass "HTTP integration tests found (httptest in $HTTPTEST_COUNT files)"
129
129
  else
@@ -40,7 +40,7 @@ fi
40
40
  echo ""
41
41
  echo "--- Health Checks ---"
42
42
  if [ -f "go.mod" ]; then
43
- HEALTH_ENDPOINTS=$(grep -rE '("/health|/healthz|/ready|/readiness)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
43
+ HEALTH_ENDPOINTS=$(grep -rE '("/health|/healthz|/ready|/readiness)' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
44
44
  if [ "$HEALTH_ENDPOINTS" -gt 0 ]; then
45
45
  pass "Health/readiness endpoint handlers found ($HEALTH_ENDPOINTS references)"
46
46
  else
@@ -94,7 +94,7 @@ fi
94
94
  echo ""
95
95
  echo "--- Error Wrapping ---"
96
96
  if [ -f "go.mod" ]; then
97
- WRAP_COUNT=$(grep -rE 'fmt\.Errorf\(.*%w' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
97
+ WRAP_COUNT=$(grep -rE 'fmt\.Errorf\(.*%w' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
98
98
  if [ "$WRAP_COUNT" -gt 0 ]; then
99
99
  pass "Error wrapping with %w found ($WRAP_COUNT usages)"
100
100
  else
@@ -67,7 +67,7 @@ if command -v govulncheck &>/dev/null && [ -f "go.mod" ]; then
67
67
  warn "govulncheck reported findings (review manually)"
68
68
  fi
69
69
  elif [ -f "go.mod" ]; then
70
- DEP_COUNT=$(go list -m all 2>/dev/null | wc -l | tr -d ' ')
70
+ DEP_COUNT=$(go list -m all 2>/dev/null | wc -l | tr -d ' ') || true
71
71
  warn "govulncheck not available; $DEP_COUNT dependencies require manual review"
72
72
  else
73
73
  warn "Not in a Go module, skipping dependency audit"
@@ -99,8 +99,8 @@ fi
99
99
  echo ""
100
100
  echo "--- Input Validation ---"
101
101
  if [ -f "go.mod" ]; then
102
- TEXT_TEMPLATE=$(grep -rl '"text/template"' . --include="*.go" 2>/dev/null | grep -v "_test.go" | wc -l | tr -d ' ')
103
- HTML_TEMPLATE=$(grep -rl '"html/template"' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ')
102
+ TEXT_TEMPLATE=$(grep -rl '"text/template"' . --include="*.go" 2>/dev/null | grep -v "_test.go" | wc -l | tr -d ' ') || true
103
+ HTML_TEMPLATE=$(grep -rl '"html/template"' . --include="*.go" 2>/dev/null | wc -l | tr -d ' ') || true
104
104
  if [ "$TEXT_TEMPLATE" -eq 0 ]; then
105
105
  pass "No text/template usage in production code (html/template auto-escapes)"
106
106
  elif [ "$HTML_TEMPLATE" -gt 0 ]; then
@@ -95,7 +95,7 @@ if [ -d "$SRC_DIR" ]; then
95
95
  if [ -n "$FIELD_AUTOWIRED" ]; then
96
96
  # Count field-level @Autowired (not constructor)
97
97
  FIELD_COUNT=$(echo "$FIELD_AUTOWIRED" | wc -l | tr -d ' ')
98
- CONSTRUCTOR_COUNT=$(grep -rn "@Autowired\s*$" "$SRC_DIR" --include="*.java" 2>/dev/null | grep -v "//\|/\*" | wc -l | tr -d ' ')
98
+ CONSTRUCTOR_COUNT=$(grep -rn "@Autowired\s*$" "$SRC_DIR" --include="*.java" 2>/dev/null | grep -v "//\|/\*" | wc -l | tr -d ' ') || true
99
99
 
100
100
  # Heuristic: more field injections than constructor injections
101
101
  if [ "$FIELD_COUNT" -gt "$CONSTRUCTOR_COUNT" ]; then
@@ -86,7 +86,7 @@ fi
86
86
  echo ""
87
87
  echo "--- Canonical References ---"
88
88
  if [ -d ".pi/architecture/modules" ]; then
89
- MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
89
+ MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
90
90
  pass "Canonical architecture documents found ($MODULE_COUNT modules)"
91
91
  else
92
92
  warn "No .pi/architecture/modules directory found"
@@ -39,7 +39,7 @@ fi
39
39
  echo ""
40
40
  echo "--- Implementation File References ---"
41
41
  if [ -d "$SRC_DIR" ]; then
42
- JAVA_FILES=$(find "$SRC_DIR" -name "*.java" 2>/dev/null | wc -l | tr -d ' ')
42
+ JAVA_FILES=$(find "$SRC_DIR" -name "*.java" 2>/dev/null | wc -l | tr -d ' ') || true
43
43
  if [ "$JAVA_FILES" -gt 0 ]; then
44
44
  # Check for canonical reference headers in Java files
45
45
  WITH_REFS=0
@@ -81,7 +81,7 @@ fi
81
81
  echo ""
82
82
  echo "--- ADR References ---"
83
83
  if [ -d ".pi/architecture/decisions" ]; then
84
- ADR_COUNT=$(find .pi/architecture/decisions -name "*.md" -not -name "ADR-template.md" 2>/dev/null | wc -l | tr -d ' ')
84
+ ADR_COUNT=$(find .pi/architecture/decisions -name "*.md" -not -name "ADR-template.md" 2>/dev/null | wc -l | tr -d ' ') || true
85
85
  if [ "$ADR_COUNT" -gt 0 ]; then
86
86
  pass "Architecture Decision Records found ($ADR_COUNT ADRs)"
87
87
  else
@@ -24,12 +24,12 @@ TEST_DIR="${2:-src/test/java}"
24
24
  echo "--- Test Slice Correctness ---"
25
25
  if [ -d "$TEST_DIR" ]; then
26
26
  # Check for @SpringBootTest usage (no slice annotations)
27
- FULL_CONTEXT_TESTS=$(grep -r "@SpringBootTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
27
+ FULL_CONTEXT_TESTS=$(grep -r "@SpringBootTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
28
28
  # Check for slice test annotations
29
- WEB_MVC_TESTS=$(grep -r "@WebMvcTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
30
- DATA_JPA_TESTS=$(grep -r "@DataJpaTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
31
- JSON_TESTS=$(grep -r "@JsonTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
32
- REST_CLIENT_TESTS=$(grep -r "@RestClientTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
29
+ WEB_MVC_TESTS=$(grep -r "@WebMvcTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
30
+ DATA_JPA_TESTS=$(grep -r "@DataJpaTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
31
+ JSON_TESTS=$(grep -r "@JsonTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
32
+ REST_CLIENT_TESTS=$(grep -r "@RestClientTest" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
33
33
 
34
34
  TOTAL_SLICE_TESTS=$((WEB_MVC_TESTS + DATA_JPA_TESTS + JSON_TESTS + REST_CLIENT_TESTS))
35
35
 
@@ -52,7 +52,7 @@ fi
52
52
  echo ""
53
53
  echo "--- Context Caching ---"
54
54
  if [ -d "$TEST_DIR" ]; then
55
- DIRTY_CONTEXT=$(grep -r "@DirtiesContext" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
55
+ DIRTY_CONTEXT=$(grep -r "@DirtiesContext" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
56
56
  if [ "$DIRTY_CONTEXT" -gt 0 ]; then
57
57
  warn "$DIRTY_CONTEXT @DirtiesContext annotations found — these disable context caching and slow tests"
58
58
  else
@@ -74,7 +74,7 @@ if [ -d "$TEST_DIR" ]; then
74
74
  TRANSACTIONAL_TESTS=$(echo "$DATA_JPA_CLASSES" | wc -l | tr -d ' ')
75
75
  fi
76
76
 
77
- ROLLBACK_COUNT=$(grep -r "@Rollback" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
77
+ ROLLBACK_COUNT=$(grep -r "@Rollback" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
78
78
 
79
79
  if [ "$TRANSACTIONAL_TESTS" -gt 0 ] || [ "$ROLLBACK_COUNT" -gt 0 ]; then
80
80
  pass "Database state management found (@DataJpaTest: $TRANSACTIONAL_TESTS, @Rollback: $ROLLBACK_COUNT)"
@@ -103,7 +103,7 @@ fi
103
103
  echo ""
104
104
  echo "--- Mockito Usage ---"
105
105
  if [ -d "$TEST_DIR" ]; then
106
- MOCKITO_ANNOTATIONS=$(grep -r "@Mock\|@InjectMocks\|@MockBean\|@SpyBean" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
106
+ MOCKITO_ANNOTATIONS=$(grep -r "@Mock\|@InjectMocks\|@MockBean\|@SpyBean" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
107
107
  if [ "$MOCKITO_ANNOTATIONS" -gt 0 ]; then
108
108
  pass "Mockito usage detected ($MOCKITO_ANNOTATIONS annotations)"
109
109
  else
@@ -117,8 +117,8 @@ fi
117
117
  echo ""
118
118
  echo "--- Assertions ---"
119
119
  if [ -d "$TEST_DIR" ]; then
120
- ASSERTJ=$(grep -r "assertThat\|Assertions.assertThat" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
121
- JUNIT_ASSERT=$(grep -r "assertEquals\|assertTrue\|assertNotNull\|assertThrows" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
120
+ ASSERTJ=$(grep -r "assertThat\|Assertions.assertThat" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
121
+ JUNIT_ASSERT=$(grep -r "assertEquals\|assertTrue\|assertNotNull\|assertThrows" "$TEST_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
122
122
  if [ "$ASSERTJ" -gt 0 ] || [ "$JUNIT_ASSERT" -gt 0 ]; then
123
123
  pass "Assertions found (AssertJ: $ASSERTJ, JUnit: $JUNIT_ASSERT)"
124
124
  else
@@ -44,10 +44,10 @@ fi
44
44
  echo ""
45
45
  echo "--- @Scheduled Tasks ---"
46
46
  if [ -d "$SRC_DIR" ]; then
47
- SCHEDULED_COUNT=$(grep -r "@Scheduled" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
47
+ SCHEDULED_COUNT=$(grep -r "@Scheduled" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
48
48
  if [ "$SCHEDULED_COUNT" -gt 0 ]; then
49
49
  # Check if @EnableScheduling is present
50
- ENABLED_SCHEDULING=$(grep -r "@EnableScheduling" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
50
+ ENABLED_SCHEDULING=$(grep -r "@EnableScheduling" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
51
51
  if [ "$ENABLED_SCHEDULING" -gt 0 ]; then
52
52
  pass "$SCHEDULED_COUNT @Scheduled tasks found with @EnableScheduling"
53
53
  else
@@ -64,9 +64,9 @@ fi
64
64
  echo ""
65
65
  echo "--- @Async Tasks ---"
66
66
  if [ -d "$SRC_DIR" ]; then
67
- ASYNC_COUNT=$(grep -r "@Async" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
67
+ ASYNC_COUNT=$(grep -r "@Async" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
68
68
  if [ "$ASYNC_COUNT" -gt 0 ]; then
69
- ENABLED_ASYNC=$(grep -r "@EnableAsync" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ')
69
+ ENABLED_ASYNC=$(grep -r "@EnableAsync" "$SRC_DIR" --include="*.java" 2>/dev/null | wc -l | tr -d ' ') || true
70
70
  if [ "$ENABLED_ASYNC" -gt 0 ]; then
71
71
  pass "$ASYNC_COUNT @Async methods found with @EnableAsync"
72
72
  else
@@ -41,7 +41,7 @@ fi
41
41
  echo ""
42
42
  echo "--- Canonical References ---"
43
43
  if [ -d ".pi/architecture/modules" ]; then
44
- MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
44
+ MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
45
45
  pass "Canonical architecture documents found ($MODULE_COUNT modules)"
46
46
  else
47
47
  warn "No canonical architecture directory found"
@@ -50,7 +50,7 @@ fi
50
50
  # Domain models
51
51
  echo ""
52
52
  echo "--- Domain Models ---"
53
- DOMAIN_FILES=$(find "$SRC_DIR" -path "*/domain/*.py" 2>/dev/null | wc -l | tr -d ' ')
53
+ DOMAIN_FILES=$(find "$SRC_DIR" -path "*/domain/*.py" 2>/dev/null | wc -l | tr -d ' ') || true
54
54
  if [ "$DOMAIN_FILES" -gt 0 ]; then
55
55
  pass "Domain model files found ($DOMAIN_FILES files)"
56
56
  else
@@ -60,7 +60,7 @@ fi
60
60
  # Dependency direction
61
61
  echo ""
62
62
  echo "--- Dependency Direction ---"
63
- DOMAIN_INFRA_IMPORTS=$(find "$SRC_DIR" -path "*/domain/*.py" -exec grep -l "from.*infrastructure" {} + 2>/dev/null | wc -l | tr -d ' ')
63
+ DOMAIN_INFRA_IMPORTS=$(find "$SRC_DIR" -path "*/domain/*.py" -exec grep -l "from.*infrastructure" {} + 2>/dev/null | wc -l | tr -d ' ') || true
64
64
  if [ "$DOMAIN_INFRA_IMPORTS" -eq 0 ]; then
65
65
  pass "Domain layer has no infrastructure dependencies (clean architecture)"
66
66
  else
@@ -70,7 +70,7 @@ fi
70
70
  # Error handling
71
71
  echo ""
72
72
  echo "--- Error Handling ---"
73
- ERROR_COUNT=$(grep -r "class.*Error" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ')
73
+ ERROR_COUNT=$(grep -r "class.*Error" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ') || true
74
74
  if [ "$ERROR_COUNT" -gt 0 ]; then
75
75
  pass "Custom exception classes defined ($ERROR_COUNT found)"
76
76
  else
@@ -80,7 +80,7 @@ fi
80
80
  # Typed models
81
81
  echo ""
82
82
  echo "--- Typed Models ---"
83
- MODEL_COUNT=$(grep -r "@dataclass" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ')
83
+ MODEL_COUNT=$(grep -r "@dataclass" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ') || true
84
84
  if [ "$MODEL_COUNT" -gt 0 ]; then
85
85
  pass "Typed dataclass models found ($MODEL_COUNT definitions)"
86
86
  else
@@ -26,9 +26,9 @@ SRC_DIR="${1:-src}"
26
26
 
27
27
  # ── Architecture reference tracing ──
28
28
  echo "--- Architecture Reference Tracing ---"
29
- TOTAL_PY_FILES=$(find "$SRC_DIR" -name "*.py" 2>/dev/null | wc -l | tr -d ' ')
29
+ TOTAL_PY_FILES=$(find "$SRC_DIR" -name "*.py" 2>/dev/null | wc -l | tr -d ' ') || true
30
30
  if [ "$TOTAL_PY_FILES" -gt 0 ]; then
31
- FILES_WITH_REFS=$(grep -rlE "(Canonical:|@canonical|Reference:.*\.pi/architecture)" "$SRC_DIR" --include="*.py" 2>/dev/null | wc -l | tr -d ' ')
31
+ FILES_WITH_REFS=$(grep -rlE "(Canonical:|@canonical|Reference:.*\.pi/architecture)" "$SRC_DIR" --include="*.py" 2>/dev/null | wc -l | tr -d ' ') || true
32
32
  PCT=$((FILES_WITH_REFS * 100 / TOTAL_PY_FILES))
33
33
  if [ "$FILES_WITH_REFS" -gt 0 ]; then
34
34
  pass "Canonical references detected in $FILES_WITH_REFS/$TOTAL_PY_FILES files (${PCT}%)"
@@ -92,8 +92,8 @@ fi
92
92
  echo ""
93
93
  echo "--- ADR Linkage ---"
94
94
  if [ -d ".pi/architecture/decisions" ]; then
95
- ADR_COUNT=$(find .pi/architecture/decisions -name "ADR-*.md" 2>/dev/null | wc -l | tr -d ' ')
96
- ADR_REFS=$(grep -rlE "ADR-[0-9]+" "$SRC_DIR" --include="*.py" 2>/dev/null | wc -l | tr -d ' ')
95
+ ADR_COUNT=$(find .pi/architecture/decisions -name "ADR-*.md" 2>/dev/null | wc -l | tr -d ' ') || true
96
+ ADR_REFS=$(grep -rlE "ADR-[0-9]+" "$SRC_DIR" --include="*.py" 2>/dev/null | wc -l | tr -d ' ') || true
97
97
  if [ "$ADR_REFS" -gt 0 ]; then
98
98
  pass "ADR references found in $ADR_REFS source files ($ADR_COUNT ADRs exist)"
99
99
  else
@@ -49,7 +49,7 @@ fi
49
49
  # ── Contract Tests ──
50
50
  echo ""
51
51
  echo "--- Contract Tests ---"
52
- CONTRACT_COUNT=$(find tests -name "*contract*" -o -name "*pact*" 2>/dev/null | wc -l | tr -d ' ')
52
+ CONTRACT_COUNT=$(find tests -name "*contract*" -o -name "*pact*" 2>/dev/null | wc -l | tr -d ' ') || true
53
53
  if [ "$CONTRACT_COUNT" -gt 0 ]; then
54
54
  pass "Contract test files found ($CONTRACT_COUNT)"
55
55
  else
@@ -75,7 +75,7 @@ fi
75
75
  # ── Database Integration Tests ──
76
76
  echo ""
77
77
  echo "--- Database Integration Tests ---"
78
- DB_TEST_COUNT=$(grep -rlE "(pytest.*db|session_scope|test_db|database_url|SQLALCHEMY)" tests/ --include="*.py" 2>/dev/null | wc -l | tr -d ' ')
78
+ DB_TEST_COUNT=$(grep -rlE "(pytest.*db|session_scope|test_db|database_url|SQLALCHEMY)" tests/ --include="*.py" 2>/dev/null | wc -l | tr -d ' ') || true
79
79
  if [ "$DB_TEST_COUNT" -gt 0 ]; then
80
80
  pass "Database integration tests found ($DB_TEST_COUNT files)"
81
81
  else
@@ -23,7 +23,7 @@ echo "============================================"
23
23
 
24
24
  # Hardcoded secrets
25
25
  echo "--- Hardcoded Secrets ---"
26
- SECRET_COUNT=$(grep -rE "(api_key|secret_key|password|token)\s*=\s*['\"][^'\"]{8,}" "$SRC_DIR" --include="*.py" 2>/dev/null | grep -v "__init__" | grep -v "test" | wc -l | tr -d ' ')
26
+ SECRET_COUNT=$(grep -rE "(api_key|secret_key|password|token)\s*=\s*['\"][^'\"]{8,}" "$SRC_DIR" --include="*.py" 2>/dev/null | grep -v "__init__" | grep -v "test" | wc -l | tr -d ' ') || true
27
27
  if [ "$SECRET_COUNT" -eq 0 ]; then
28
28
  pass "No hardcoded secrets detected"
29
29
  else
@@ -33,7 +33,7 @@ fi
33
33
  # SQL injection
34
34
  echo ""
35
35
  echo "--- Injection Patterns ---"
36
- INJECT_COUNT=$(grep -rE "(execute|cursor\.execute)\s*\(\s*['\"]" "$SRC_DIR" --include="*.py" 2>/dev/null | wc -l | tr -d ' ')
36
+ INJECT_COUNT=$(grep -rE "(execute|cursor\.execute)\s*\(\s*['\"]" "$SRC_DIR" --include="*.py" 2>/dev/null | wc -l | tr -d ' ') || true
37
37
  if [ "$INJECT_COUNT" -eq 0 ]; then
38
38
  pass "No obvious injection patterns"
39
39
  else
@@ -64,7 +64,7 @@ fi
64
64
  echo ""
65
65
  echo "--- Canonical References ---"
66
66
  if [ -d ".pi/architecture/modules" ]; then
67
- MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
67
+ MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
68
68
  if [ "$MODULE_COUNT" -gt 0 ]; then
69
69
  pass "Architecture modules defined ($MODULE_COUNT module files)"
70
70
  else
@@ -82,7 +82,7 @@ echo "--- Domain Models ---"
82
82
  DOMAIN_MODELS=0
83
83
  for dir in src/domain src/models; do
84
84
  if [ -d "$dir" ]; then
85
- MODELS=$(grep -rlE '^\s*(pub\s+)?struct\s' "$dir" 2>/dev/null | wc -l | tr -d ' ')
85
+ MODELS=$(grep -rlE '^\s*(pub\s+)?struct\s' "$dir" 2>/dev/null | wc -l | tr -d ' ') || true
86
86
  DOMAIN_MODELS=$((DOMAIN_MODELS + MODELS))
87
87
  fi
88
88
  done
@@ -90,7 +90,7 @@ if [ "$DOMAIN_MODELS" -gt 0 ]; then
90
90
  pass "Domain models found ($DOMAIN_MODELS files with struct definitions)"
91
91
  else
92
92
  # Check all of src as fallback
93
- ALL_MODELS=$(grep -rlE '^\s*(pub\s+)?struct\s' src/ 2>/dev/null | wc -l | tr -d ' ')
93
+ ALL_MODELS=$(grep -rlE '^\s*(pub\s+)?struct\s' src/ 2>/dev/null | wc -l | tr -d ' ') || true
94
94
  if [ "$ALL_MODELS" -gt 0 ]; then
95
95
  pass "Struct definitions found in src/ ($ALL_MODELS files)"
96
96
  else
@@ -104,7 +104,7 @@ fi
104
104
  echo ""
105
105
  echo "--- Dependency Direction ---"
106
106
  if [ -d "src/domain" ]; then
107
- DOMAIN_DEPS=$(grep -rE 'use\s+crate::infrastructure' src/domain/ 2>/dev/null | wc -l | tr -d ' ')
107
+ DOMAIN_DEPS=$(grep -rE 'use\s+crate::infrastructure' src/domain/ 2>/dev/null | wc -l | tr -d ' ') || true
108
108
  if [ "$DOMAIN_DEPS" -eq 0 ]; then
109
109
  pass "Domain layer does not depend on infrastructure"
110
110
  else
@@ -127,7 +127,7 @@ if command -v cargo &>/dev/null; then
127
127
  fi
128
128
  fi
129
129
  # Also check for custom error enum definitions
130
- CUSTOM_ERRORS=$(grep -rE 'enum\s+\w*Error' src/ 2>/dev/null | wc -l | tr -d ' ')
130
+ CUSTOM_ERRORS=$(grep -rE 'enum\s+\w*Error' src/ 2>/dev/null | wc -l | tr -d ' ') || true
131
131
  if [ "$HAS_ERROR_TYPES" -eq 1 ] || [ "$CUSTOM_ERRORS" -gt 0 ]; then
132
132
  pass "Custom error handling detected"
133
133
  else
@@ -139,7 +139,7 @@ fi
139
139
  # ---------------------------------------------------------------------------
140
140
  echo ""
141
141
  echo "--- Trait Definitions ---"
142
- TRAITS=$(grep -rE '^\s*(pub\s+)?trait\s+' src/ 2>/dev/null | wc -l | tr -d ' ')
142
+ TRAITS=$(grep -rE '^\s*(pub\s+)?trait\s+' src/ 2>/dev/null | wc -l | tr -d ' ') || true
143
143
  if [ "$TRAITS" -gt 0 ]; then
144
144
  pass "Trait definitions found ($TRAITS interfaces)"
145
145
  else
@@ -43,10 +43,10 @@ CANONICAL_REFS=0
43
43
  TOTAL_RS=0
44
44
 
45
45
  # Count all Rust source files
46
- TOTAL_RS=$(find src -name "*.rs" 2>/dev/null | wc -l | tr -d ' ')
46
+ TOTAL_RS=$(find src -name "*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
47
47
  if [ "$TOTAL_RS" -gt 0 ]; then
48
48
  # Look for canonical reference patterns in doc comments
49
- CANONICAL_REFS=$(grep -rE '(///\s*Canonical:|//!\s*@canonical|///\s*Reference:)' src/ 2>/dev/null | wc -l | tr -d ' ')
49
+ CANONICAL_REFS=$(grep -rE '(///\s*Canonical:|//!\s*@canonical|///\s*Reference:)' src/ 2>/dev/null | wc -l | tr -d ' ') || true
50
50
  if [ "$CANONICAL_REFS" -gt 0 ]; then
51
51
  PCT=$((CANONICAL_REFS * 100 / TOTAL_RS))
52
52
  pass "Canonical references found: ${CANONICAL_REFS} files (${PCT}% of ${TOTAL_RS} Rust files)"
@@ -91,7 +91,7 @@ fi
91
91
  echo ""
92
92
  echo "--- Module Documentation ---"
93
93
  if [ "$TOTAL_RS" -gt 0 ]; then
94
- MOD_DOCS=$(grep -rlE '^//!\s' src/ 2>/dev/null | wc -l | tr -d ' ')
94
+ MOD_DOCS=$(grep -rlE '^//!\s' src/ 2>/dev/null | wc -l | tr -d ' ') || true
95
95
  if [ "$MOD_DOCS" -gt 0 ]; then
96
96
  PCT=$((MOD_DOCS * 100 / TOTAL_RS))
97
97
  pass "Module documentation found in ${MOD_DOCS}/${TOTAL_RS} files (${PCT}%)"
@@ -108,9 +108,9 @@ fi
108
108
  echo ""
109
109
  echo "--- ADR Linkage ---"
110
110
  if [ -d ".pi/architecture/decisions" ]; then
111
- ADR_FILES=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
111
+ ADR_FILES=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
112
112
  if [ "$ADR_FILES" -gt 0 ]; then
113
- ADR_REFS=$(grep -rE '///\s*ADR-' src/ 2>/dev/null | wc -l | tr -d ' ')
113
+ ADR_REFS=$(grep -rE '///\s*ADR-' src/ 2>/dev/null | wc -l | tr -d ' ') || true
114
114
  if [ "$ADR_REFS" -gt 0 ]; then
115
115
  pass "ADR references found in code ($ADR_REFS references)"
116
116
  else
@@ -40,7 +40,7 @@ fi
40
40
  # ---------------------------------------------------------------------------
41
41
  echo "--- Integration Test Runner ---"
42
42
  if [ -d "tests" ]; then
43
- INT_TEST_FILES=$(find tests -name "*.rs" 2>/dev/null | wc -l | tr -d ' ')
43
+ INT_TEST_FILES=$(find tests -name "*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
44
44
  if [ "$INT_TEST_FILES" -gt 0 ]; then
45
45
  if cargo test --test '*' --quiet 2>/dev/null; then
46
46
  pass "Integration tests passed ($INT_TEST_FILES test files)"
@@ -70,7 +70,7 @@ fi
70
70
  # ---------------------------------------------------------------------------
71
71
  echo ""
72
72
  echo "--- Contract Tests ---"
73
- CONTRACT_TESTS=$(find . -name "*contract*test*.rs" -o -name "*test*contract*.rs" 2>/dev/null | wc -l | tr -d ' ')
73
+ CONTRACT_TESTS=$(find . -name "*contract*test*.rs" -o -name "*test*contract*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
74
74
  if [ "$CONTRACT_TESTS" -gt 0 ]; then
75
75
  pass "Contract test files found ($CONTRACT_TESTS)"
76
76
  else
@@ -101,7 +101,7 @@ fi
101
101
  # ---------------------------------------------------------------------------
102
102
  echo ""
103
103
  echo "--- Database Integration ---"
104
- DB_INTEG=$(find . -name "*_integration_test.rs" -o -name "*db*test*.rs" 2>/dev/null | wc -l | tr -d ' ')
104
+ DB_INTEG=$(find . -name "*_integration_test.rs" -o -name "*db*test*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
105
105
  if [ "$DB_INTEG" -gt 0 ]; then
106
106
  pass "Database integration test files found ($DB_INTEG)"
107
107
  else
@@ -59,7 +59,7 @@ echo "--- SQL Injection ---"
59
59
  SQL_INJECT=0
60
60
  if grep -qE 'sqlx' Cargo.toml 2>/dev/null; then
61
61
  # Check for unsafe query patterns: format! inside query! or query()
62
- SQL_INJECT=$(grep -rE 'query\s*\(\s*(format!|format_args!)' src/ --include="*.rs" 2>/dev/null | wc -l | tr -d ' ')
62
+ SQL_INJECT=$(grep -rE 'query\s*\(\s*(format!|format_args!)' src/ --include="*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
63
63
  fi
64
64
  if [ "$SQL_INJECT" -gt 0 ]; then
65
65
  fail "Potential SQL injection patterns found ($SQL_INJECT occurrences — avoid format! inside query)"
@@ -94,7 +94,7 @@ fi
94
94
  # ---------------------------------------------------------------------------
95
95
  echo ""
96
96
  echo "--- Unsafe Code ---"
97
- UNSAFE_BLOCKS=$(grep -rE 'unsafe\s*\{' --include="*.rs" src/ 2>/dev/null | wc -l | tr -d ' ')
97
+ UNSAFE_BLOCKS=$(grep -rE 'unsafe\s*\{' --include="*.rs" src/ 2>/dev/null | wc -l | tr -d ' ') || true
98
98
  if [ "$UNSAFE_BLOCKS" -gt 0 ]; then
99
99
  warn "Unsafe code blocks found ($UNSAFE_BLOCKS occurrences — recommend manual audit)"
100
100
  else
@@ -42,7 +42,7 @@ echo "--- Unit Tests ---"
42
42
  if cargo test --lib --quiet 2>/dev/null; then
43
43
  pass "Library unit tests passed"
44
44
  else
45
- LIB_SOURCES=$(find src -name "*.rs" 2>/dev/null | wc -l | tr -d ' ')
45
+ LIB_SOURCES=$(find src -name "*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
46
46
  if [ "$LIB_SOURCES" -eq 0 ]; then
47
47
  pass "No library source files (skipped)"
48
48
  else
@@ -65,7 +65,7 @@ if [ -d "tests" ]; then
65
65
  fi
66
66
  else
67
67
  # Run all integration test files
68
- TEST_COUNT=$(find tests -name "*.rs" 2>/dev/null | wc -l | tr -d ' ')
68
+ TEST_COUNT=$(find tests -name "*.rs" 2>/dev/null | wc -l | tr -d ' ') || true
69
69
  if [ "$TEST_COUNT" -gt 0 ]; then
70
70
  if cargo test --test '*' --quiet 2>/dev/null; then
71
71
  pass "Integration tests passed"
@@ -88,7 +88,7 @@ echo "--- Doctests ---"
88
88
  if cargo test --doc --quiet 2>/dev/null; then
89
89
  pass "Doctests passed"
90
90
  else
91
- DOCS=$(grep -rl '//!\|///' src/ 2>/dev/null | wc -l | tr -d ' ')
91
+ DOCS=$(grep -rl '//!\|///' src/ 2>/dev/null | wc -l | tr -d ' ') || true
92
92
  if [ "$DOCS" -eq 0 ]; then
93
93
  pass "No doc comments found (no doctests to run)"
94
94
  else
@@ -44,7 +44,7 @@ fi
44
44
  echo ""
45
45
  echo "--- Canonical References ---"
46
46
  if [ -d ".pi/architecture/modules" ]; then
47
- MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
47
+ MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
48
48
  pass "Canonical architecture documents found ($MODULE_COUNT modules)"
49
49
  else
50
50
  warn "No .pi/architecture/modules directory found"
@@ -56,7 +56,7 @@ fi
56
56
  echo ""
57
57
  echo "--- Domain Models ---"
58
58
  if [ -d "$SRC_DIR/domain" ]; then
59
- DOMAIN_MODELS=$(find "$SRC_DIR/domain" -name "*.ts" -o -name "*.tsx" 2>/dev/null | xargs grep -lE '\b(interface|type|class)\b' 2>/dev/null | wc -l | tr -d ' ')
59
+ DOMAIN_MODELS=$(find "$SRC_DIR/domain" -name "*.ts" -o -name "*.tsx" 2>/dev/null | xargs grep -lE '\b(interface|type|class)\b' 2>/dev/null | wc -l | tr -d ' ') || true
60
60
  if [ "$DOMAIN_MODELS" -gt 0 ]; then
61
61
  pass "Domain model definitions found ($DOMAIN_MODELS files with interface/type/class)"
62
62
  else
@@ -93,7 +93,7 @@ fi
93
93
  echo ""
94
94
  echo "--- Error Handling ---"
95
95
  if [ -d "$SRC_DIR" ]; then
96
- ERROR_CLASSES=$(grep -rE "class\s+\w+Error.*extends\s+(Error|AppError)" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ')
96
+ ERROR_CLASSES=$(grep -rE "class\s+\w+Error.*extends\s+(Error|AppError)" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ') || true
97
97
  if [ "$ERROR_CLASSES" -gt 0 ]; then
98
98
  pass "Custom error classes defined ($ERROR_CLASSES found)"
99
99
  else
@@ -109,7 +109,7 @@ fi
109
109
  echo ""
110
110
  echo "--- Interfaces / Contracts ---"
111
111
  if [ -d "$SRC_DIR" ]; then
112
- INTERFACE_COUNT=$(grep -rE "^\s*(export\s+)?interface\s+" "$SRC_DIR" --include="*.ts" --include="*.tsx" 2>/dev/null | wc -l | tr -d ' ')
112
+ INTERFACE_COUNT=$(grep -rE "^\s*(export\s+)?interface\s+" "$SRC_DIR" --include="*.ts" --include="*.tsx" 2>/dev/null | wc -l | tr -d ' ') || true
113
113
  if [ "$INTERFACE_COUNT" -gt 0 ]; then
114
114
  pass "Interface contracts defined ($INTERFACE_COUNT found)"
115
115
  else
@@ -24,8 +24,8 @@ echo "--- Architecture Reference Tracing ---"
24
24
  CANONICAL_REFS=0
25
25
  TOTAL_TS_FILES=0
26
26
  if [ -d "$SRC_DIR" ]; then
27
- TOTAL_TS_FILES=$(find "$SRC_DIR" -name "*.ts" -o -name "*.tsx" 2>/dev/null | wc -l | tr -d ' ')
28
- CANONICAL_REFS=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -exec grep -lE '(// Canonical:|@canonical).*\.pi/architecture/' {} + 2>/dev/null | wc -l | tr -d ' ')
27
+ TOTAL_TS_FILES=$(find "$SRC_DIR" -name "*.ts" -o -name "*.tsx" 2>/dev/null | wc -l | tr -d ' ') || true
28
+ CANONICAL_REFS=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -exec grep -lE '(// Canonical:|@canonical).*\.pi/architecture/' {} + 2>/dev/null | wc -l | tr -d ' ') || true
29
29
  if [ "$TOTAL_TS_FILES" -gt 0 ] && [ "$CANONICAL_REFS" -gt 0 ]; then
30
30
  PCT=$((CANONICAL_REFS * 100 / TOTAL_TS_FILES))
31
31
  pass "Canonical references found: $CANONICAL_REFS / $TOTAL_TS_FILES files ($PCT%)"
@@ -77,7 +77,7 @@ if [ -d "$SRC_DIR" ]; then
77
77
  EXPORT_WITH_DOCS=0
78
78
  EXPORTS_TOTAL=0
79
79
  # Check for documented exports: JSDoc comment (/** ... */) immediately before export
80
- EXPORTS_TOTAL=$(grep -rE "^\s*(export\s+(const|function|class|interface|type|default))" "$SRC_DIR" --include="*.ts" --include="*.tsx" 2>/dev/null | wc -l | tr -d ' ')
80
+ EXPORTS_TOTAL=$(grep -rE "^\s*(export\s+(const|function|class|interface|type|default))" "$SRC_DIR" --include="*.ts" --include="*.tsx" 2>/dev/null | wc -l | tr -d ' ') || true
81
81
  EXPORT_WITH_DOCS=$(grep -B1 -rE "^\s*(export\s+(const|function|class|interface|type|default))" "$SRC_DIR" --include="*.ts" --include="*.tsx" 2>/dev/null | grep -c '\*/' 2>/dev/null || echo "0")
82
82
  if [ "$EXPORTS_TOTAL" -gt 0 ]; then
83
83
  if [ "$EXPORT_WITH_DOCS" -gt 0 ]; then
@@ -99,8 +99,8 @@ fi
99
99
  echo ""
100
100
  echo "--- ADR Linkage ---"
101
101
  if [ -d ".pi/architecture/decisions" ]; then
102
- ADR_FILES=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
103
- ADR_REFS=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -exec grep -rlE '(@adr|ADR-)' {} + 2>/dev/null | wc -l | tr -d ' ')
102
+ ADR_FILES=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ') || true
103
+ ADR_REFS=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -exec grep -rlE '(@adr|ADR-)' {} + 2>/dev/null | wc -l | tr -d ' ') || true
104
104
  if [ "$ADR_FILES" -gt 0 ] && [ "$ADR_REFS" -gt 0 ]; then
105
105
  pass "ADR references found: $ADR_REFS files link to $ADR_FILES decisions"
106
106
  elif [ "$ADR_FILES" -gt 0 ]; then
@@ -64,9 +64,9 @@ fi
64
64
  echo ""
65
65
  echo "--- Docker/Compose ---"
66
66
  if [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ]; then
67
- SERVICES=$(grep -E "^\s{2}\w+:" docker-compose.yml 2>/dev/null | grep -vE "^\s{2}version:|^\s{2}services:" | wc -l | tr -d ' ')
67
+ SERVICES=$(grep -E "^\s{2}\w+:" docker-compose.yml 2>/dev/null | grep -vE "^\s{2}version:|^\s{2}services:" | wc -l | tr -d ' ') || true
68
68
  if [ -f "docker-compose.yaml" ] && [ "$SERVICES" -eq 0 ]; then
69
- SERVICES=$(grep -E "^\s{2}\w+:" docker-compose.yaml 2>/dev/null | grep -vE "^\s{2}version:|^\s{2}services:" | wc -l | tr -d ' ')
69
+ SERVICES=$(grep -E "^\s{2}\w+:" docker-compose.yaml 2>/dev/null | grep -vE "^\s{2}version:|^\s{2}services:" | wc -l | tr -d ' ') || true
70
70
  fi
71
71
  pass "Docker Compose found ($SERVICES services — integration tests may require running services)"
72
72
  else
@@ -81,7 +81,7 @@ echo "--- Contract Tests ---"
81
81
  CONTRACT_FILES=0
82
82
  for dir in tests test; do
83
83
  if [ -d "$dir" ]; then
84
- COUNT=$(find "$dir" -name "*.contract.test.ts" -o -name "*.contract.test.tsx" 2>/dev/null | wc -l | tr -d ' ')
84
+ COUNT=$(find "$dir" -name "*.contract.test.ts" -o -name "*.contract.test.tsx" 2>/dev/null | wc -l | tr -d ' ') || true
85
85
  CONTRACT_FILES=$((CONTRACT_FILES + COUNT))
86
86
  fi
87
87
  done
@@ -99,7 +99,7 @@ echo "--- Mock/Stub Detection ---"
99
99
  MOCK_USAGE=0
100
100
  for ext in ts tsx; do
101
101
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./dist/*" \
102
- -exec grep -lE "(vitest\.mock|jest\.mock|from\s+['\"]msw['\"]|from\s+['\"]@testing-library)" {} + 2>/dev/null | wc -l | tr -d ' ')
102
+ -exec grep -lE "(vitest\.mock|jest\.mock|from\s+['\"]msw['\"]|from\s+['\"]@testing-library)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
103
103
  MOCK_USAGE=$((MOCK_USAGE + COUNT))
104
104
  done
105
105
  if [ "$MOCK_USAGE" -gt 0 ]; then
@@ -116,7 +116,7 @@ echo "--- Database Integration ---"
116
116
  DB_INTEGRATION_FILES=0
117
117
  for dir in tests test; do
118
118
  if [ -d "$dir" ]; then
119
- COUNT=$(find "$dir" -name "*_integration.test.ts" -o -name "*_integration.test.tsx" -o -name "*.db.test.ts" -o -name "*.db.test.tsx" 2>/dev/null | wc -l | tr -d ' ')
119
+ COUNT=$(find "$dir" -name "*_integration.test.ts" -o -name "*_integration.test.tsx" -o -name "*.db.test.ts" -o -name "*.db.test.tsx" 2>/dev/null | wc -l | tr -d ' ') || true
120
120
  DB_INTEGRATION_FILES=$((DB_INTEGRATION_FILES + COUNT))
121
121
  fi
122
122
  done
@@ -134,7 +134,7 @@ echo "--- HTTP Integration ---"
134
134
  HTTP_LIBS=0
135
135
  for ext in ts tsx; do
136
136
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./dist/*" \
137
- -exec grep -lE "(supertest|msw|@testing-library)" {} + 2>/dev/null | wc -l | tr -d ' ')
137
+ -exec grep -lE "(supertest|msw|@testing-library)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
138
138
  HTTP_LIBS=$((HTTP_LIBS + COUNT))
139
139
  done
140
140
  if [ "$HTTP_LIBS" -gt 0 ]; then
@@ -32,7 +32,7 @@ if [ -d "$SRC_DIR" ] || [ -d "." ]; then
32
32
  for dir in $SEARCH_DIRS; do
33
33
  [ -d "$dir" ] || continue
34
34
  FOUND=$(find "$dir" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
35
- -exec grep -lE "(winston|pino|bunyan|console\.(log|info|warn|error))" {} + 2>/dev/null | wc -l | tr -d ' ')
35
+ -exec grep -lE "(winston|pino|bunyan|console\.(log|info|warn|error))" {} + 2>/dev/null | wc -l | tr -d ' ') || true
36
36
  LOGGING_LIBS=$((LOGGING_LIBS + FOUND))
37
37
  done
38
38
  if [ "$LOGGING_LIBS" -gt 0 ]; then
@@ -52,7 +52,7 @@ echo "--- Health Checks ---"
52
52
  HEALTH_ROUTES=0
53
53
  if [ -d "$SRC_DIR" ]; then
54
54
  HEALTH_ROUTES=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
55
- -exec grep -lE "(/health[^/]?|/healthz|/ready|/readiness)" {} + 2>/dev/null | wc -l | tr -d ' ')
55
+ -exec grep -lE "(/health[^/]?|/healthz|/ready|/readiness)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
56
56
  if [ "$HEALTH_ROUTES" -gt 0 ]; then
57
57
  pass "Health check endpoints found ($HEALTH_ROUTES files)"
58
58
  else
@@ -70,7 +70,7 @@ echo "--- Graceful Shutdown ---"
70
70
  SHUTDOWN_HANDLERS=0
71
71
  if [ -d "$SRC_DIR" ]; then
72
72
  SHUTDOWN_HANDLERS=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
73
- -exec grep -lE "process\.on\(['\"]SIG(TERM|INT)['\"]" {} + 2>/dev/null | wc -l | tr -d ' ')
73
+ -exec grep -lE "process\.on\(['\"]SIG(TERM|INT)['\"]" {} + 2>/dev/null | wc -l | tr -d ' ') || true
74
74
  if [ "$SHUTDOWN_HANDLERS" -gt 0 ]; then
75
75
  pass "Graceful shutdown handlers found ($SHUTDOWN_HANDLERS files)"
76
76
  else
@@ -88,7 +88,7 @@ echo "--- Metrics ---"
88
88
  METRICS_LIBS=0
89
89
  if [ -d "$SRC_DIR" ]; then
90
90
  METRICS_LIBS=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
91
- -exec grep -lE "(prom-client|@opentelemetry|statsd|hot-shots|dd-trace)" {} + 2>/dev/null | wc -l | tr -d ' ')
91
+ -exec grep -lE "(prom-client|@opentelemetry|statsd|hot-shots|dd-trace)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
92
92
  if [ "$METRICS_LIBS" -gt 0 ]; then
93
93
  pass "Metrics/observability libraries detected ($METRICS_LIBS files)"
94
94
  else
@@ -107,10 +107,10 @@ ERROR_PATTERNS=0
107
107
  if [ -d "$SRC_DIR" ]; then
108
108
  # Check for try/catch blocks
109
109
  TRY_CATCH=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
110
- -exec grep -lE "try\s*\{" {} + 2>/dev/null | wc -l | tr -d ' ')
110
+ -exec grep -lE "try\s*\{" {} + 2>/dev/null | wc -l | tr -d ' ') || true
111
111
  # Check for error middleware (Express-style)
112
112
  ERROR_MIDDLEWARE=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
113
- -exec grep -lE "error.*:.*Error.*req.*res" {} + 2>/dev/null | wc -l | tr -d ' ')
113
+ -exec grep -lE "error.*:.*Error.*req.*res" {} + 2>/dev/null | wc -l | tr -d ' ') || true
114
114
  ERROR_PATTERNS=$((TRY_CATCH + ERROR_MIDDLEWARE))
115
115
  if [ "$ERROR_PATTERNS" -gt 0 ]; then
116
116
  pass "Error handling patterns found ($ERROR_PATTERNS files with try/catch or error middleware)"
@@ -129,7 +129,7 @@ echo "--- Configuration ---"
129
129
  CONFIG_FOUND=0
130
130
  if [ -d "$SRC_DIR" ]; then
131
131
  CONFIG_FOUND=$(find "$SRC_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" \
132
- -exec grep -lE "(dotenv|require\(['\"]config['\"]\)|process\.env)" {} + 2>/dev/null | wc -l | tr -d ' ')
132
+ -exec grep -lE "(dotenv|require\(['\"]config['\"]\)|process\.env)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
133
133
  if [ "$CONFIG_FOUND" -gt 0 ]; then
134
134
  pass "Configuration management detected ($CONFIG_FOUND files with dotenv/config/process.env)"
135
135
  else
@@ -32,7 +32,7 @@ echo "--- Hardcoded Secrets ---"
32
32
  SECRET_COUNT=0
33
33
  for ext in ts tsx; do
34
34
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" \
35
- -exec grep -E "(apiKey|api_key|apiKey|secret|password|token|privateKey)\s*[:=]\s*['\"][^'\"]{8,}['\"]" {} + 2>/dev/null | wc -l | tr -d ' ')
35
+ -exec grep -E "(apiKey|api_key|apiKey|secret|password|token|privateKey)\s*[:=]\s*['\"][^'\"]{8,}['\"]" {} + 2>/dev/null | wc -l | tr -d ' ') || true
36
36
  SECRET_COUNT=$((SECRET_COUNT + COUNT))
37
37
  done
38
38
  if [ "$SECRET_COUNT" -eq 0 ]; then
@@ -50,7 +50,7 @@ INJECTION_PATTERNS=0
50
50
  for ext in ts tsx; do
51
51
  # Template literals used with query/exec calls
52
52
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" \
53
- -exec grep -E "\.(query|exec)\(\s*\`" {} + 2>/dev/null | wc -l | tr -d ' ')
53
+ -exec grep -E "\.(query|exec)\(\s*\`" {} + 2>/dev/null | wc -l | tr -d ' ') || true
54
54
  INJECTION_PATTERNS=$((INJECTION_PATTERNS + COUNT))
55
55
  done
56
56
  if [ "$INJECTION_PATTERNS" -eq 0 ]; then
@@ -97,7 +97,7 @@ echo "--- eval / Dangerous Patterns ---"
97
97
  DANGEROUS_COUNT=0
98
98
  for ext in ts tsx; do
99
99
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" \
100
- -exec grep -E "(eval\(|innerHTML\s*=|dangerouslySetInnerHTML)" {} + 2>/dev/null | wc -l | tr -d ' ')
100
+ -exec grep -E "(eval\(|innerHTML\s*=|dangerouslySetInnerHTML)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
101
101
  DANGEROUS_COUNT=$((DANGEROUS_COUNT + COUNT))
102
102
  done
103
103
  if [ "$DANGEROUS_COUNT" -eq 0 ]; then
@@ -114,14 +114,14 @@ echo "--- XSS Prevention ---"
114
114
  SANITIZE_LIBS=0
115
115
  for ext in ts tsx; do
116
116
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" \
117
- -exec grep -lE "(DOMPurify|sanitize-html|xss|sanitize)" {} + 2>/dev/null | wc -l | tr -d ' ')
117
+ -exec grep -lE "(DOMPurify|sanitize-html|xss|sanitize)" {} + 2>/dev/null | wc -l | tr -d ' ') || true
118
118
  SANITIZE_LIBS=$((SANITIZE_LIBS + COUNT))
119
119
  done
120
120
  if [ "$SANITIZE_LIBS" -gt 0 ]; then
121
121
  pass "Sanitization libraries detected ($SANITIZE_LIBS files)"
122
122
  else
123
123
  # Only warn if there are TSX files (likely has JSX/DOM rendering)
124
- TSX_COUNT=$(find . -name "*.tsx" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" 2>/dev/null | wc -l | tr -d ' ')
124
+ TSX_COUNT=$(find . -name "*.tsx" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" 2>/dev/null | wc -l | tr -d ' ') || true
125
125
  if [ "$TSX_COUNT" -gt 0 ]; then
126
126
  warn "No sanitization library found in TSX files (consider DOMPurify or sanitize-html)"
127
127
  else
@@ -137,7 +137,7 @@ echo "--- HTTPS Enforcement ---"
137
137
  HTTP_ONLY=0
138
138
  for ext in ts tsx; do
139
139
  COUNT=$(find . -name "*.$ext" -not -path "./node_modules/*" -not -path "./.next/*" -not -path "./dist/*" \
140
- -exec grep -E "['\"]http://(?!localhost)" {} + 2>/dev/null | grep -ivE "(test|spec|mock|example|dev)" | wc -l | tr -d ' ')
140
+ -exec grep -E "['\"]http://(?!localhost)" {} + 2>/dev/null | grep -ivE "(test|spec|mock|example|dev)" | wc -l | tr -d ' ') || true
141
141
  HTTP_ONLY=$((HTTP_ONLY + COUNT))
142
142
  done
143
143
  if [ "$HTTP_ONLY" -eq 0 ]; then