# Layer Architecture and Import Cycle Rules in DeepSeek-Reasonix: A Complete Guide

> Explore the DeepSeek-Reasonix layered Go architecture and import cycle rules. Understand how higher-level packages import lower-level ones, enforced by repolint.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: deep-dive
- Published: 2026-08-13

---

**DeepSeek-Reasonix implements a strict layered Go architecture with acyclic dependencies where higher-level packages import lower-level ones but never vice versa, enforced by a custom `repolint` tool.**

DeepSeek-Reasonix is a layered Go application designed for predictable builds and clear separation of concerns. The codebase enforces strict **layer architecture and import cycle rules** that prevent circular dependencies and ensure modular evolution across CLI, agent, plugin, config, tool, and provider layers.

## Understanding the Six-Layer Architecture

The architecture is documented in [`docs/SPEC.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/docs/SPEC.md) and organizes the codebase into six distinct layers with unidirectional dependencies:

- **CLI Layer** (`internal/cli/*`): Handles command-line parsing, sub-command routing, and flag handling. Imports agent, plugin, and config.
- **Agent Layer** (`internal/agent/*`): Manages session loops, message orchestration, and plan/execution coordination. Imported by CLI; imports tool and provider.
- **Plugin Layer** (`internal/plugin/*`): Implements MCP (JSON-RPC) client and transport abstraction. Imported by CLI; imports tool and provider.
- **Config Layer** (`internal/config/*`): Handles TOML loading, hierarchical overrides, and validation. Imported by CLI; imports tool and provider.
- **Tool Layer** (`internal/tool/*`): Contains built-in and plugin-provided tools with schema registry. Imported by agent, plugin, and config.
- **Provider Layer** (`internal/provider/*`): Implements model-provider backends like OpenAI. Imported by agent, plugin, and config.

According to [`docs/SPEC.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/docs/SPEC.md), the dependency direction is strictly **acyclic: `cli → {agent, plugin, config} → {tool, provider}`**【/cache/repos/github.com/esengine/DeepSeek-Reasonix/main-v2/docs/SPEC.md#L54】.

## Core Import Cycle Rules

The codebase enforces six critical rules to maintain architectural integrity.

### 1. Strict Acyclic Dependencies

No package may import any package that eventually imports back to it. The Go compiler rejects cyclic imports at build time, but DeepSeek-Reasonix adds a custom layer of protection through the `repolint` tool.

### 2. Parents Never Import Children

Higher-level packages must never import their children. As documented in [`tools/repolint/layers.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/tools/repolint/layers.go), utility-layer packages "must not import children"【/cache/repos/github.com/esengine/DeepSeek-Reasonix/main-v2/tools/repolint/layers.go#L22-L25】. This ensures that business logic in lower layers cannot be contaminated by presentation or orchestration concerns.

### 3. Utility Layer Purity

Utility packages contain only standard-library code and must remain independent of "kernel" (core) packages. The `repolint` configuration explicitly states that utility layers "carry no knowledge of the kernel"【/cache/repos/github.com/esengine/DeepSeek-Reasonix/main-v2/tools/repolint/layers.go#L22-L24】.

### 4. Self-Registration Pattern

Built-in sub-packages may import their parent solely for self-registration via `init()` functions. For example, `internal/provider/openai` registers itself with the provider registry, but `internal/provider` never imports `openai`. The same pattern applies to `internal/tool/builtin`.

### 5. Remote-SSH Module Compliance

The Remote-SSH subsystem (`remote/bootstrap`, `remote/forward`, `remote/sftpfs`) forms a vertical stack that respects the same layering constraints and does not import higher-level layers like `cli` or `agent`【/cache/repos/github.com/esengine/DeepSeek-Reasonix/main-v2/docs/SPEC.md#L55-L59】.

### 6. Automated Enforcement with repolint

The custom `repolint` linter validates all import relationships against the layering graph. It checks the Go AST and reports failures such as "TypeScript imports must stay out of the layering graph" or layer violations【/cache/repos/github.com/esengine/DeepSeek-Reasonix/main-v2/tools/repolint/size_test.go#L60】. The layering rule is registered in [`tools/repolint/main.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/tools/repolint/main.go)【/cache/repos/github.com/esengine/DeepSeek-Reasonix/main-v2/tools/repolint/main.go#L32】.

## Practical Code Examples

Correct usage follows the dependency arrow from higher to lower layers:

```go
// internal/agent/agent.go
import (
    "github.com/esengine/DeepSeek-Reasonix/internal/tool"
    "github.com/esengine/DeepSeek-Reasonix/internal/provider"
)

```

Incorrect usage attempts to import upward, which `repolint` rejects:

```go
// internal/tool/tool.go   ← ❌ illegal import
import (
    "github.com/esengine/DeepSeek-Reasonix/internal/agent"
)

```

Attempting this import causes `repolint` to fail with a message like *"tool package must not import agent"*.

## Summary

- DeepSeek-Reasonix organizes code into six layers: CLI, Agent, Plugin, Config, Tool, and Provider.
- Dependencies flow strictly downward: `cli → {agent, plugin, config} → {tool, provider}`.
- Higher-level packages must never import lower-level ones, except for self-registration via `init()`.
- Utility packages remain pure with no kernel dependencies.
- The `repolint` tool enforces these rules at build time to guarantee acyclic graphs.

## Frequently Asked Questions

### What happens if I violate the import cycle rules in DeepSeek-Reasonix?

The `repolint` linter will fail the build with a specific error message indicating which layer violated the dependency direction. Since the rules are also enforced by Go's compiler for actual cycles, the codebase provides double protection against architectural decay.

### How does the self-registration pattern work without creating import cycles?

Child packages like `internal/provider/openai` import their parent package to register capabilities via `init()` functions, but the parent never imports the child. This creates a one-way dependency edge that satisfies the acyclic requirement while allowing dynamic plugin discovery.

### Why does DeepSeek-Reasonix use a custom linter instead of standard Go tools?

While Go's compiler prevents circular imports, it does not enforce architectural layering (e.g., preventing `tool` from importing `agent`). The `repolint` tool validates semantic layer boundaries defined in [`docs/SPEC.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/docs/SPEC.md), ensuring that business logic remains properly isolated across the six-layer stack.

### Can I add new layers to the DeepSeek-Reasonix architecture?

New layers must be inserted into the dependency graph defined in [`docs/SPEC.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/docs/SPEC.md) and registered in [`tools/repolint/layers.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/tools/repolint/layers.go). Any new layer must follow the acyclic rule: it can only import layers below it and must not be imported by layers above it unless explicitly designed as a utility layer with no kernel dependencies.