apiVersion: conventions/v1 version: 0.1.0 updated: "2026-06-29" name: code_standards title: TypeScript code standards scope: ts status: active summary: Portable TS conventions — strict typing, ESM, typed errors, named exports, Vitest. Project-specific architecture (kernels, golden-vectors, file-size caps) lives with the project, not here. appliesTo: ["**/*.ts", "**/*.tsx"] rules: - id: strict level: must text: "tsconfig strict:true; prefer noUncheckedIndexedAccess + exactOptionalPropertyTypes. No escape hatches." - id: no_any level: must text: No `any`; use `unknown` at boundaries and narrow with type guards. Never `as unknown as T`. - id: no_ts_ignore level: must text: No `@ts-ignore`; fix the type, or `@ts-expect-error` with a reason. - id: explicit_return_types level: should text: Explicit return types on exported functions and React components. - id: discriminated_unions level: should text: Discriminated unions over boolean flags; add variants via switch, don't branch on strings. - id: typed_errors level: must text: Typed Error subclasses with cause chaining. Never empty catch; never catch-and-only-console. - id: esm_named_exports level: must text: ESM only; named exports in libraries (default exports only in app pages/components); index.ts is the public manifest. - id: no_link_file level: must text: Monorepo deps via workspace:* or the registry — never file:/link:. - id: vitest level: must text: Vitest (not Jest); *.test.ts co-located, full-sentence it(...); mocks only in test files. - id: structured_logging level: must text: No console.log in library code — use a structured logger. - id: no_dead_code level: must text: Delete unused code entirely; no _unused prefixes, no commented-out blocks.