feat(lint): P7 enforcement gates (no-new-throw-error + max-lines) + docs

Epic P7. Locks in the epic's gains with ESLint gates so the adoption work
does not regress.

- ccs/no-new-throw-error (error): custom flat-config rule that flags NEW
  throw new Error(...) outside a generated baseline allowlist. Forces the
  typed-error taxonomy (src/errors/error-types.ts). Existing 338 sites are
  grandfathered in eslint-rules/throw-error-baseline.json; only NEW violations
  error. Rule normalizes the filename to repo-root-relative to match baseline
  keys regardless of how ESLint reports paths.
- max-lines (warn, 400, skipBlankLines/skipComments): warns on files over
  400 LOC (goal of P5/P6 god-file splits). Currently 51 warnings on the
  not-yet-split god-files (P6 territory).
- scripts/generate-throw-error-baseline.js: emits the allowlist from raw
  source (superset of real throws; never undercounts). Run after intentionally
  grandfathering a site, or quarterly to prune.
- tests/unit/eslint-rules/no-throw-new-error.test.ts: rule logic (flags
  off-allowlist, passes on-allowlist/typed/rethrow, line-sensitivity).
- docs/code-standards.md: Lint Enforcement Gates section.
- docs/logging-contract.md: error.code -> ExitCode table (from P4).

validate + validate:ci-parity green.
This commit is contained in:
Tam Nhu Tran committed 2026-06-18 18:48:13 -04:00
1 parent 919be3c722
commit 2f94f35ec3
7 files changed
+642

No files matched your search

+19
View File
@@ -146,6 +146,25 @@ Use `stage()` whenever the entry corresponds to one of the canonical lifecycle s
Default level is `info`. Configure via `logging.level` in `~/.ccs/config.yaml`. Streaming providers MUST gate per-chunk metrics behind `debug`.
## `error.code` values (exit codes)
Typed errors (`src/errors/error-types.ts`) carry an `ExitCode` that `handleError` propagates to `process.exit`. Log readers can branch on `error.code` for differentiated handling. The full mapping lives in `src/errors/exit-codes.ts`; the per-class assignment:
| Typed class | ExitCode | Value |
|---|---|---:|
| `ConfigError` | `CONFIG_ERROR` | 2 |
| `NetworkError` | `NETWORK_ERROR` | 3 (recoverable) |
| `AuthError` | `AUTH_ERROR` | 4 |
| `BinaryError` | `BINARY_ERROR` | 5 |
| `ProviderError` | `PROVIDER_ERROR` | 6 (recoverable) |
| `ProfileError` | `PROFILE_ERROR` | 7 |
| `ProxyError` | `PROXY_ERROR` | 8 |
| `MigrationError` | `MIGRATION_ERROR` | 9 |
| `UserAbortError` | `USER_ABORT` | 130 |
| `ValidationError`, `RetryableError` | `GENERAL_ERROR` | 1 |
New throws must use a typed class (enforced by `ccs/no-new-throw-error`, see `docs/code-standards.md`). Redaction scrubs credential token shapes in both context values and message strings, so routing errors into the logger is safe — but keep messages clean prose and put sensitive data in context under a sensitive key (auto-redacted).
## Backward Compatibility
- All new `LogEntry` fields (`requestId`, `stage`, `latencyMs`, `error`) are optional. Old readers ignore them.