guardian-framework 0.1.98 → 0.1.100

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 (26) 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/extensions/coordinator.ts +13 -3
  5. package/templates/pi/extensions/pipeline.ts +2 -2
  6. package/templates/pi/preflight_report.json +1 -1
  7. package/templates/pi/scripts/languages/go/validate-architecture.sh +5 -5
  8. package/templates/pi/scripts/languages/go/validate-canonical.sh +3 -3
  9. package/templates/pi/scripts/languages/go/validate-integration.sh +1 -1
  10. package/templates/pi/scripts/languages/go/validate-operations.sh +2 -2
  11. package/templates/pi/scripts/languages/go/validate-security.sh +1 -1
  12. package/templates/pi/scripts/languages/java/validate-integration.sh +10 -10
  13. package/templates/pi/scripts/languages/java/validate-operations.sh +4 -4
  14. package/templates/pi/scripts/languages/python/validate-architecture.sh +3 -3
  15. package/templates/pi/scripts/languages/python/validate-canonical.sh +2 -2
  16. package/templates/pi/scripts/languages/python/validate-integration.sh +1 -1
  17. package/templates/pi/scripts/languages/python/validate-security.sh +1 -1
  18. package/templates/pi/scripts/languages/rust/validate-architecture.sh +5 -5
  19. package/templates/pi/scripts/languages/rust/validate-canonical.sh +3 -3
  20. package/templates/pi/scripts/languages/rust/validate-security.sh +2 -2
  21. package/templates/pi/scripts/languages/rust/validate-tests.sh +1 -1
  22. package/templates/pi/scripts/languages/typescript/validate-architecture.sh +3 -3
  23. package/templates/pi/scripts/languages/typescript/validate-canonical.sh +3 -3
  24. package/templates/pi/scripts/languages/typescript/validate-integration.sh +2 -2
  25. package/templates/pi/scripts/languages/typescript/validate-operations.sh +7 -7
  26. package/templates/pi/scripts/languages/typescript/validate-security.sh +4 -4
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.98", 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.100", 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.98", 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.100", 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.98",
3
+ "version": "0.1.100",
4
4
  "description": "Token-optimized agentic framework scaffolder with pi-first architecture",
5
5
  "type": "module",
6
6
  "main": "dist/exports.js",
@@ -10,6 +10,7 @@
10
10
  */
11
11
 
12
12
  type ExtensionContext = {
13
+ cwd: string;
13
14
  ui: { notify(message: string, level?: string): void };
14
15
  shell: {
15
16
  execute(
@@ -179,10 +180,19 @@ export default function (pi: ExtensionAPI) {
179
180
 
180
181
  const scriptPath = VALIDATORS[validator];
181
182
  try {
182
- const result = await ctx.shell.execute(`bash ${scriptPath}`, { signal });
183
- results[validator] = { passed: result.exitCode === 0, output: result.stdout };
183
+ const { execFileSync } = require("node:child_process");
184
+ const cwd = ctx.cwd || process.cwd();
185
+ const result = execFileSync("bash", [scriptPath], {
186
+ cwd,
187
+ timeout: 120_000,
188
+ encoding: "utf-8",
189
+ stdio: ["ignore", "pipe", "pipe"],
190
+ });
191
+ results[validator] = { passed: true, output: (result || "").trim() };
184
192
  } catch (error) {
185
- results[validator] = { passed: false, output: `Error: ${error}` };
193
+ const err = error as { stdout?: string | Buffer; stderr?: string | Buffer };
194
+ const stdout = (err.stdout || "").toString().slice(0, 500);
195
+ results[validator] = { passed: false, output: stdout || String(error) };
186
196
  }
187
197
  }
188
198
 
@@ -647,7 +647,7 @@ class PipelineManager {
647
647
  const scriptPath = VALIDATOR_SCRIPTS[validator];
648
648
  if (!scriptPath) { errors.push(`Unknown validator: ${validator}`); continue; }
649
649
  try {
650
- execFileSync("bash", ["-c", scriptPath], { cwd: this.cwd, timeout: 120_000, encoding: "utf-8" });
650
+ execFileSync("bash", [scriptPath], { cwd: this.cwd, timeout: 120_000, encoding: "utf-8" });
651
651
  } catch (e: unknown) {
652
652
  const err = e as { stdout?: string };
653
653
  errors.push(`${validator}: ${(err.stdout || "").slice(0, 200)}`);
@@ -1344,7 +1344,7 @@ export default function (pi: ExtensionAPI) {
1344
1344
  continue;
1345
1345
  }
1346
1346
  try {
1347
- execFileSync("bash", ["-c", scriptPath], {
1347
+ execFileSync("bash", [scriptPath], {
1348
1348
  cwd: ctx.cwd,
1349
1349
  timeout: 120_000,
1350
1350
  encoding: "utf-8",
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-18T19:39:29Z",
2
+ "timestamp": "2026-07-19T05:59:04Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -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
@@ -22,7 +22,7 @@ echo "--- Architecture Reference Tracing ---"
22
22
  if [ -f "go.mod" ]; then
23
23
  GO_FILES=$(find . -name "*.go" -not -path "./vendor/*" 2>/dev/null | wc -l | tr -d ' ')
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,7 +74,7 @@ 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 ' ')
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
78
  GO_PACKAGES=$(go list ./... 2>/dev/null | wc -l | tr -d ' ')
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"
@@ -93,7 +93,7 @@ echo "--- ADR Linkage ---"
93
93
  if [ -d ".pi/architecture/decisions" ]; then
94
94
  ADR_COUNT=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
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
@@ -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
@@ -100,7 +100,7 @@ echo ""
100
100
  echo "--- Input Validation ---"
101
101
  if [ -f "go.mod" ]; then
102
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 ' ')
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
@@ -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
@@ -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
@@ -28,7 +28,7 @@ SRC_DIR="${1:-src}"
28
28
  echo "--- Architecture Reference Tracing ---"
29
29
  TOTAL_PY_FILES=$(find "$SRC_DIR" -name "*.py" 2>/dev/null | wc -l | tr -d ' ')
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}%)"
@@ -93,7 +93,7 @@ echo ""
93
93
  echo "--- ADR Linkage ---"
94
94
  if [ -d ".pi/architecture/decisions" ]; then
95
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 ' ')
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
@@ -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
@@ -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
@@ -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
@@ -46,7 +46,7 @@ TOTAL_RS=0
46
46
  TOTAL_RS=$(find src -name "*.rs" 2>/dev/null | wc -l | tr -d ' ')
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}%)"
@@ -110,7 +110,7 @@ echo "--- ADR Linkage ---"
110
110
  if [ -d ".pi/architecture/decisions" ]; then
111
111
  ADR_FILES=$(find .pi/architecture/decisions -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
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
@@ -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
@@ -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
@@ -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
@@ -25,7 +25,7 @@ CANONICAL_REFS=0
25
25
  TOTAL_TS_FILES=0
26
26
  if [ -d "$SRC_DIR" ]; then
27
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 ' ')
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
@@ -100,7 +100,7 @@ echo ""
100
100
  echo "--- ADR Linkage ---"
101
101
  if [ -d ".pi/architecture/decisions" ]; then
102
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 ' ')
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
@@ -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
@@ -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,7 +114,7 @@ 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