You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Break the 9 server import cycles; promote noImportCycles to error (#1007)
**Nine `lint/suspicious/noImportCycles` violations in
`packages/server/src/` all routed through one bidirectional edge**:
`surface.ts` and four domain modules importing each other in a tangle
that biome had been merely _warning_ about for months. Extract a
`surfaceCtx.ts` Proxy-fronted holder so `surface.ts` registers the typed
mutation map once at startup; domain modules import the ctx from the
holder instead. The bidirectional arrow collapses to a one-way arrow
plus a one-way registration — same shape that PR [#998 cycle
1](#998) prototyped.
With zero cycles remaining, promote the rule from biome's default `warn`
to `error` in `biome.jsonc`. _The TDZ-on-import-reorder hazard that
crashed production in [#1003](#1003)
— biome's alphabetical sort reshuffled imports, the cycle converged via
a different path, `localTerminalBackend` ended up in TDZ at module load,
only `just smoke` caught it on CI — becomes structurally impossible._
### The shape that changed
```
Before After
surface.ts ◀──▶ session.ts surface.ts ──▶ session.ts ──┐
◀──▶ activity.ts (via local.ts) surface.ts ──▶ activity.ts ─┤
◀──▶ terminalBackend/local.ts surface.ts ──▶ local.ts ────┼──▶ surfaceCtx.ts
◀──▶ terminalBackend/metadata.ts surface.ts ──▶ metadata.ts ─┘ ▲
│ │
└────── setSurfaceCtx ─────────┘
(local.ts also pulled surface.ts via unwrapGit; local.ts ──▶ unwrapGit.ts
router.ts pulled it for the same.) router.ts ──▶ unwrapGit.ts
```
`unwrapGit` had to come out alongside `surfaceCtx` —
`terminalBackend/local.ts` imported _both_ from `surface.ts`. Pulling
only the ctx out would leave `local.ts → surface.ts →
terminalBackend/index.ts → local.ts` cycling via `unwrapGit`. It's a
pure `GitResult → ORPCError` adapter; its own neutral file is the right
boundary, and `router.ts` picks up the new import too.
### Refinements during review
| Lens | Finding | Resolution |
|---|---|---|
| **hickey** | `setSurfaceCtx` silently overwrites `held` on a second
call — _"write once" contract is convention, not constraint_ | Guard
added |
| **lowy** _(cross-validate)_ | Strict `held !== undefined` would block
harmless same-ctx re-registration (future test isolation / HMR) |
Refined predicate to `held !== undefined && held !== ctx` — throws only
on a _genuinely different_ ctx |
| **code-police** | `session.test.ts` + `metadata.test.ts` previously
inherited a populated ctx via `surface.ts`'s import side-effect; with
the holder, the Proxy throws when not initialized | Added
`__resetSurfaceCtxForTest()` + `noopSurfaceCtxForTest()` and wired them
into the affected tests |
| **code-police** | Stale doc comment in `router.ts` still pointed at
`./surface.ts` for `surfaceCtx` | Updated |
### Validation
- `just check` — clean (zero `noImportCycles`, zero type errors,
pre-existing 40 warnings unrelated).
- `pnpm vitest run` in `packages/server` — **46/46 unit tests pass**
(the 14 that needed the new test-helper plumbing now have it).
- CI `just smoke` covers the original production-loader hazard
end-to-end.
> _Reviewer note_: also retires the `biome-ignore-start
assist/source/organizeImports` markers in `surface.ts`. With no cycle
for the alphabetical sort to converge along, the load-order constraint
they protected is gone.
Closes#1005.
### Try it locally
```sh
nix run github:juspay/kolu/noImportCycles
```
_Generated by [`/do`](https://github.com/srid/agency) on Claude Code
(model `claude-opus-4-7`)._
0 commit comments