# OpenSpec Change: enterprise-server-linter - **Change ID**: enterprise-server-linter - **Package**: `@suaveplan/linter` - **Category**: server/infra - **Target path**: `server/infra/linter` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/linter.md` --- ## Summary Deliver `@suaveplan/linter` on the genesis branch from scratch at enterprise quality. The package is a shared linting configuration and runtime wrapper for the Suaveplan monorepo. It ships opinionated Biome configuration presets (base, library, react, node, test), a programmatic `LinterRunner` API for running Biome checks in CI pipelines, structured `LintResult` output, and a thin CLI wrapper. No runtime browser deps — this is a Node.js / build-tooling package. --- ## Current-state audit (genesis) Does not exist on genesis — fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | Typed `LINTER.*` error codes | | `@suaveplan/types` (`workspace:^`) | `LoggerLike` | | `@suaveplan/logger` (`workspace:^`) | Structured logs | | `zod` (`catalog:forms`) | Options validation | | `@opentelemetry/api` (`catalog:observability`) | Counters | | `@biomejs/biome` (`catalog:build`) | Linter/formatter engine | | `tslib` (`catalog:build`) | Runtime helpers | --- ## Public API surface ### Programmatic API ```ts class LinterRunner { constructor(options?: LinterOptions) check(targets: string[]): Promise fix(targets: string[]): Promise format(targets: string[]): Promise } function createLinterRunner(options?: LinterOptions): LinterRunner interface LinterOptions { configPath?: string // path to biome.json; default: auto-discover preset?: 'base' | 'library' | 'react' | 'node' | 'test' logger?: LoggerLike } interface LintResult { passed: boolean errorCount: number warningCount: number diagnostics: LintDiagnostic[] duration: number } interface LintDiagnostic { file: string line: number column: number severity: 'error' | 'warning' | 'info' message: string rule: string } type LinterErrorCode = | 'LINTER_CONFIG_NOT_FOUND' | 'LINTER_EXECUTION_FAILED' | 'LINTER_INVALID_TARGET' function registerLinterErrorCodes(): void ``` ### Config presets (re-exported JSON) ```ts // Subpath exports for use in biome.json "extends" // "@suaveplan/linter/presets/base" // "@suaveplan/linter/presets/library" // "@suaveplan/linter/presets/react" // "@suaveplan/linter/presets/node" // "@suaveplan/linter/presets/test" ``` --- ## File layout ```text server/infra/linter/ package.json tsconfig.json vitest.config.ts presets/ base.json library.json react.json node.json test.json src/ index.ts error-codes.ts constants/index.ts types/ linter.types.ts linter.types.md runner/ linter-runner/ linter-runner.ts linter-runner.md linter-runner.types.ts linter-runner.test.ts index.ts tests/ integration.test.ts ``` --- ## Impact Downstream: every genesis package uses `@suaveplan/linter` presets via `biome.json` extends. The programmatic API is used in CI reporting. **Prerequisites on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`.