@@ -442,3 +442,58 @@ Going forward:
442442- If a file grows large enough that it's hard to navigate, split by concern
443443 (errors.ts, schema.ts, etc.) for readability. Not for tree-shaking — the
444444 bundler handles that.
445+
446+ ## Circular import rules
447+
448+ Barrel files (` index.ts ` with ` export * as ` ) introduce circular import risks.
449+ These cause ` ReferenceError: Cannot access 'X' before initialization ` at
450+ runtime — not caught by the type checker.
451+
452+ ### Rule 1: Sibling files never import through their own barrel
453+
454+ Files in the same directory must import directly from the source file, never
455+ through ` "." ` or ` "@/<own-dir>" ` :
456+
457+ ``` ts
458+ // BAD — circular: index.ts re-exports both files, so A → index → B → index → A
459+ import { Sibling } from " ."
460+
461+ // GOOD — direct, no cycle
462+ import * as Sibling from " ./sibling"
463+ ```
464+
465+ ### Rule 2: Cross-directory imports must not form cycles through barrels
466+
467+ If ` src/lsp/lsp.ts ` imports ` Config ` from ` "../config" ` , and
468+ ` src/config/config.ts ` imports ` LSPServer ` from ` "../lsp" ` , that's a cycle:
469+
470+ ```
471+ lsp/lsp.ts → config/index.ts → config/config.ts → lsp/index.ts → lsp/lsp.ts 💥
472+ ```
473+
474+ Fix by importing the specific file, breaking the cycle:
475+
476+ ``` ts
477+ // In config/config.ts — import directly, not through the lsp barrel
478+ import * as LSPServer from " ../lsp/server"
479+ ```
480+
481+ ### Why the type checker doesn't catch this
482+
483+ TypeScript resolves types lazily — it doesn't evaluate module-scope
484+ expressions. The ` ReferenceError ` only happens at runtime when a module-scope
485+ ` const ` or function call accesses a value from a circular dependency that
486+ hasn't finished initializing. The SDK build step (`bun run --conditions=browser
487+ ./src/index.ts generate`) is the reliable way to catch these because it
488+ evaluates all modules eagerly.
489+
490+ ### How to verify
491+
492+ After any namespace conversion, run:
493+
494+ ``` bash
495+ cd packages/opencode
496+ bun run --conditions=browser ./src/index.ts generate
497+ ```
498+
499+ If this completes without ` ReferenceError ` , the module graph is safe.
0 commit comments