Skip to content

Commit 88410a6

Browse files
committed
feat: add use-log-helpers rule to ARCH-002
Extend ARCH-002 to enforce centralized logging in helper and engine files. The new `use-log-helpers` rule flags direct console.log/warn/info calls, requiring logInfo/logWarn/logDebug from helpers/log.ts instead. Command files are exempt (I/O layer), along with log.ts (canonical implementation), reporter.ts (check output system), and login-flow.ts (interactive device flow UI).
1 parent 1dae7c2 commit 88410a6

3 files changed

Lines changed: 32 additions & 2 deletions

File tree

.archgate/adrs/ARCH-002-error-handling.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Use three exit codes with clear semantics:
5454
- Don't catch and swallow unexpected errors — let them propagate
5555
- Don't show stack traces for user errors
5656
- Don't use `console.error()` directly — use `logError()` for consistent formatting
57+
- Don't use `console.log()` or `console.warn()` directly in helper or engine files — use `logInfo()` or `logWarn()` (command files are the I/O layer and may use console directly)
5758
- Don't exit with code 0 when an operation fails
5859
- Don't use exit codes other than 0, 1, or 2
5960

@@ -122,7 +123,7 @@ try {
122123
### Risks
123124

124125
- **Swallowed errors in async code** — Async functions that catch errors without re-throwing can silently fail. Unhandled promise rejections in Bun terminate the process with a non-zero exit code, which provides a safety net, but the error message may be unclear.
125-
- **Mitigation:** The `logError()` convention makes explicit error handling visible in code review. The `use-log-error` automated rule flags direct `console.error()` usage, nudging developers toward the standard pattern.
126+
- **Mitigation:** The log helper convention makes explicit error handling visible in code review. The `use-log-error` rule flags direct `console.error()` usage, and the `use-log-helpers` rule flags direct `console.log()`/`console.warn()` in helper and engine files, nudging developers toward the standard pattern.
126127
- **Exit code 2 masking real issues** — If an unexpected error occurs in a rule file, the CLI exits with code 2 ("internal error") rather than code 1 ("violations"). This could confuse CI systems that only check for non-zero exit.
127128
- **Mitigation:** The check engine wraps rule execution with timeout and error boundaries, reporting rule errors separately from violations. The `--verbose` flag shows which rules errored.
128129

@@ -131,6 +132,7 @@ try {
131132
### Automated Enforcement
132133

133134
- **Archgate rule** `ARCH-002/use-log-error`: Scans all source files (excluding `helpers/log.ts` and test files) for `console.error()` usage and flags violations. Severity: `error`.
135+
- **Archgate rule** `ARCH-002/use-log-helpers`: Scans helper and engine files for direct `console.log()`, `console.warn()`, or `console.info()` usage. Excludes `helpers/log.ts` (canonical implementation), `engine/reporter.ts` (check output system), `helpers/login-flow.ts` (interactive device flow UI), and test files. Command files are exempt since they are the I/O layer. Severity: `error`.
134136
- **Archgate rule** `ARCH-002/exit-code-convention`: Scans all source files for `process.exit()` calls and verifies the exit code is 0, 1, or 2. Severity: `error`.
135137

136138
### Manual Enforcement

.archgate/adrs/ARCH-002-error-handling.rules.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,34 @@ export default defineRules({
2424
}
2525
},
2626
},
27+
"use-log-helpers": {
28+
description:
29+
"Use log helpers instead of console.log/warn/info in helper and engine files",
30+
async check(ctx) {
31+
const files = ctx.scopedFiles.filter(
32+
(f) =>
33+
(f.includes("helpers/") || f.includes("engine/")) &&
34+
!f.endsWith("helpers/log.ts") &&
35+
!f.endsWith("engine/reporter.ts") &&
36+
!f.endsWith("helpers/login-flow.ts") &&
37+
!f.includes("tests/")
38+
);
39+
const matches = await Promise.all(
40+
files.map((file) => ctx.grep(file, /console\.(log|warn|info)\s*\(/))
41+
);
42+
for (const fileMatches of matches) {
43+
for (const m of fileMatches) {
44+
ctx.report.violation({
45+
message:
46+
"Use logInfo/logWarn/logDebug from helpers/log.ts instead of direct console output",
47+
file: m.file,
48+
line: m.line,
49+
fix: "Import { logInfo, logWarn } from '../helpers/log' and use logInfo() or logWarn()",
50+
});
51+
}
52+
}
53+
},
54+
},
2755
"exit-code-convention": {
2856
description: "Process.exit should use codes 0, 1, or 2 only",
2957
async check(ctx) {

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Bun 1.3.9, Node LTS, npm 11.11.0. Minimum user-facing Bun: `>=1.2.21` (enforced
8282
## Self-Governance ADRs (`.archgate/adrs/`)
8383

8484
- `ARCH-001` — Command structure (register pattern, no business logic)
85-
- `ARCH-002` — Error handling (exit codes, logError)
85+
- `ARCH-002` — Error handling (exit codes, log helpers)
8686
- `ARCH-003` — Output formatting (styleText, --json, no emoji)
8787
- `ARCH-004` — No barrel files (direct imports only)
8888
- `ARCH-005` — Testing standards (Bun test, fixtures, 80% coverage)

0 commit comments

Comments
 (0)