## Coding Conventions — Priority 5

These rules govern how you write, import, and verify code in this repository. They override any implicit assumptions about TypeScript/Node.js conventions. Violating them produces code the build rejects.

### ESM Import Extensions

ALWAYS use `.js` extension for relative imports. TypeScript with ESM (`"module": "NodeNext"`) requires file extensions in relative import paths. The compiled output is `.js`, so the import target is `.js`.

- ✅ `import { foo } from "./bar.js"`
- ❌ `import { foo } from "./bar"`
- ❌ `import { foo } from "./bar.ts"`

Exception: Package-name imports never need extensions:

- ✅ `import { foo } from "@omnius/memory"`

### Type Imports

When `verbatimModuleSyntax` is enabled (it is), types must use `import type`:

- ✅ `import type { Foo } from "./bar.js"`
- ✅ `import { type Foo, bar } from "./baz.js"`
- ❌ `import { Foo } from "./bar.js"` (Foo is type-only)

When in doubt, prefer a separate `import type` line.

### Cross-Package Imports

Use the package name, never a relative source path.

- ✅ `import { EpisodeStore } from "@omnius/memory"`
- ❌ `import { EpisodeStore } from "../../memory/src/store.js"`

Package names are defined in each workspace package's `package.json` `name` field. Known packages: `@omnius/core`, `@omnius/memory`, `@omnius/orchestrator`, `@omnius/execution`, `@omnius/cli`, `@omnius/integrations`.

### Build Verification

ALWAYS verify the build after modifying TypeScript files. Type errors that look subtle at write time are often caught by the compiler.

```
pnpm -r build
```

If errors appear, fix them before proceeding. Do not mark the task complete until `pnpm -r build` exits 0.

### Check Existing Conventions First

Before writing new code, check 2-3 existing files in the same directory for patterns:

- Import style (extensions, grouping, quoting)
- Function / class naming conventions
- Error handling patterns
- Export style (named vs default)

### Never Assume File Format

Do not guess a file's format from its extension alone. Check how existing code reads the file, or use `file <path>` to inspect it.

- `.db` files are SQLite, not JSON — use a SQLite library, not `JSON.parse`
- `.bin` files are binary
- `.json` files are JSON

### Wire New Commands Into the Dispatcher

New CLI slash commands require two things:

1. The handler file (e.g., `mem-metabolize.ts`)
2. Registration in the command dispatcher (`commands.ts`) — both a `case "name"` branch AND a `registerSlashCommand()` call

### Export New Modules From Package Index

Any new module added to a package must be re-exported from that package's `src/index.ts` so consumers can import it by package name.

### Create Type Dependencies First

If your code imports from a file you are creating (e.g., `./types`), create that file before writing the import — or at least in the same batch. A missing file causes a build failure invisible until you run the compiler.

### Type Annotations in Callbacks

Always provide explicit type parameters for generic array methods:

- ✅ `arr.sort((a: MyType, b: MyType) => a.order - b.order)`
- ✅ `arr.map((item: InputType): OutputType => transform(item))`
- ❌ `arr.sort((a, b) => a.order - b.order)`

### Read Before Editing

Always read the current target before editing. For existing non-trivial files, use `file_patch` for a contiguous range or `file_edit` for exact text, inspect the changed range/diff, then run the verifier. Use `file_write` only for new, empty/placeholder, or genuinely small files needing deliberate total replacement. Never turn a stale hash, exact-match failure, or patch-schema mistake into a whole-file rewrite.
