This repository has been archived on 2026-06-01. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
nerve/.knowledge/coding-conventions.md

2.8 KiB

Nerve Coding Conventions

Functional-First

  • type over interface, function over class
  • No this, no inheritance, composition over inheritance
  • Immutability first: Readonly<T>, as const

No Optional Properties

Never use ?:. Use T | null for nullable fields. Use discriminated unions for mutually exclusive fields.

// ✅ Good
type Config = { throttle: string | null }

// ❌ Bad
type Config = { throttle?: string }

Error Handling

  • Result<T, E> for expected failures
  • throw only for programmer errors (bugs)
  • No try-catch for flow control

Result<T, E> Type

Defined in @uncaged/nerve-core (packages/core/src/result.ts):

export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };

Discriminated union with tagged ok field. Helper functions:

  • ok(value){ ok: true, value }
  • err(error){ ok: false, error }

Exhaustive handling: Pattern is if (!result.ok) { handle error } then access result.value. No compiler enforcement - relies on manual discipline and TypeScript's flow control analysis.

Naming

Type Style
Files kebab-case.ts
Types PascalCase
Functions/vars camelCase
Constants UPPER_SNAKE

Exports

  • Always named exports, never default
  • One module = one responsibility

Module Naming Conventions

Primary exports use descriptive, unambiguous names:

  • Functions: createXxx(), parseXxx(), xxxAgent() (e.g., createCursorAdapter, cursorAgent)
  • Types: Domain-specific prefixes (e.g., CursorAgentOptions, SenseComputeFn, ThreadContext)
  • Constants: UPPER_SNAKE_CASE with context (e.g., DEFAULT_SENSE_SIGNAL_RETENTION, CURSOR_ADAPTER_DEFAULT_MS)

Avoiding ambiguity:

  • Package-scoped naming: @uncaged/nerve-adapter-cursor exports cursorAgent, createCursorAdapter
  • Factory pattern: createXxxAdapter() for configurable instances, xxxAdapter for defaults
  • Descriptive type prefixes prevent collision (e.g., CursorAgentOptions vs HermesAgentOptions)

Async

  • Always async/await, never .then() chains
  • Use AbortSignal for cancellation: AbortController to create signals, pass to long-running operations
  • spawn-safe.ts and adapter functions accept abortSignal: AbortSignal | null parameter
  • On abort: child processes receive SIGTERM, async operations should check signal.aborted
  • No enforced Biome/Vitest rules for AbortSignal usage (manual discipline required)

No Dynamic Import

Static import only. Exceptions: sense-runtime.ts, workflow-worker.ts (runtime module paths).

Toolchain

pnpm + TypeScript (strict) + Biome (lint/format) + Vitest (test)

pnpm run check   # biome check
pnpm test        # vitest
pnpm run build   # full build