# Feature Architecture Standard

**Status**: team standard  
**Reference implementation**: `src/features/recent-projects`

This document defines the default architecture for medium and large features in this repository.

## Goals

- keep business rules isolated from Electron-specific runtime details
- make features easier to scale, test, and review
- keep renderer code closer to browser and Tauri portability
- enforce architecture with tooling, not only with code review comments

## Canonical Template

```text
src/features/<feature-name>/
  index.ts
  contracts/
    index.ts
  core/
    domain/
    application/
  main/
    index.ts
    composition/
    application/
    adapters/
      input/
      output/
    infrastructure/
  preload/
    index.ts
  renderer/
    index.ts
```

Use this template by default when a feature:

- spans more than one process boundary
- introduces its own use case or business policy
- needs its own transport bridge or integration surface
- is expected to grow with new providers, sources, or presentation flows

`index.ts` and `main/application/` are optional. Add them only when they have a
clear public or runtime-orchestration role.

## Layer Responsibilities

### `index.ts`

Optional root public barrel for the feature.

Use it for:

- stable type re-exports from `contracts/`
- small pure facades that are intentionally shared across layers
- feature factories when the root barrel is intentionally main-owned and
  imported only from main-process code

Not allowed:

- accidental wildcard exports from implementation folders
- mixing browser-safe exports with main-only exports without making process
  ownership obvious
- replacing the layer entrypoints when callers need a process-specific surface

### `contracts/`

Cross-process public API for the feature.

Allowed content:

- DTOs
- API fragment types
- IPC or route constants

Not allowed:

- store access
- Electron APIs
- business orchestration

### `core/domain/`

Pure business rules and invariants.

Examples:

- merge policies
- provider-agnostic models
- selection rules
- dedupe logic

Not allowed:

- infrastructure access
- framework access
- side effects

### `core/application/`

Use cases and ports.

Examples:

- orchestration flow
- output ports
- cache ports
- source ports
- response models

Not allowed:

- Electron, Fastify, React, Zustand, child processes

### `main/composition/`

Feature composition root in the main process.

Responsibilities:

- instantiate infrastructure
- wire adapters
- wire use cases
- expose a small facade to app shell entrypoints

### `main/adapters/input/`

Driving adapters for the main process.

Examples:

- IPC handlers
- HTTP route registration

Responsibilities:

- translate transport input into use case calls
- keep transport concerns out of use cases

### `main/application/`

Optional main-process application services.

Use this only when code is too runtime-aware for `core/application`, but is not a
transport adapter or low-level infrastructure helper.

Examples:

- main-only readers that orchestrate runtime services
- process-aware tracking or coordination helpers

Not allowed:

- IPC or HTTP handler registration
- renderer or preload dependencies
- pure domain policy that belongs in `core/domain`

### `main/adapters/output/`

Driven adapters that implement application ports.

Examples:

- presenters
- source adapters

Responsibilities:

- translate between external data and core models
- stay thin around infrastructure helpers

### `main/infrastructure/`

Concrete technical implementation details.

Examples:

- file system adapters
- JSON-RPC transport clients
- binary discovery
- cache implementation
- git identity helpers

Responsibilities:

- know about runtime, process, OS, or protocol details

### `preload/`

Thin transport bridge between renderer and main.

Responsibilities:

- expose a feature API fragment
- depend on `contracts/`

Not allowed:

- main composition code
- renderer logic

### `renderer/`

Feature presentation and interaction.

Recommended structure:

```text
renderer/
  index.ts
  adapters/
  hooks/
  ui/
  utils/
```

Responsibilities:

- `ui/` renders
- `hooks/` orchestrate interaction and transport usage
- `adapters/` transform DTOs into view models
- `utils/` contain small pure renderer helpers

## Import Rules

### Public entrypoints only

Outside the feature, import only:

- `@features/<feature>` when the feature owns a deliberate root public barrel
- `@features/<feature>/contracts`
- `@features/<feature>/main`
- `@features/<feature>/preload`
- `@features/<feature>/renderer`

Do not deep-import feature internals from app shell or from other features.
Layer entrypoints should be explicit `index.ts` files that export only supported
surface area. Focused tests may import internals when they are testing that unit
directly, but production integration code should not.

### Core isolation

`core/domain` must not import:

- `@main/*`
- `@renderer/*`
- `@preload/*`
- adapters
- infrastructure
- Electron APIs
- Fastify
- child process modules

`core/application` must not import:

- `@features/<feature>/main/**`
- `@features/<feature>/renderer/**`
- `@main/*`
- `@renderer/*`
- `@preload/*`
- Electron APIs
- Fastify
- child process modules

### UI isolation

`renderer/ui` must not import:

- `@renderer/api`
- `@renderer/store`
- `@main/*`
- Electron APIs

Push transport and store access into feature hooks or adapters.

## Browser and Tauri Friendly Guidance

The default transport direction should be:

`renderer -> feature contracts -> app api abstraction -> preload/http adapter`

This keeps renderer code closer to:

- browser mode through HTTP adapters
- a future Tauri bridge
- alternative shells with minimal feature rewrites

To keep that path clean:

- never call `window.electronAPI` directly inside feature UI or hooks
- go through shared renderer API adapters
- keep Electron-specific concerns in `main/` and `preload/`
- keep business rules in `core/`

## When To Use The Full Slice

Use the full template when a feature has:

- its own business rules
- its own merge or filtering policy
- transport wiring
- more than one adapter
- a roadmap beyond a one-off screen tweak

## When A Thin Slice Is Enough

A smaller feature may skip `core/` and `preload/` when it is:

- purely presentational
- only reshaping already-owned data
- not adding a new use case
- not adding a new transport boundary

If the feature still owns meaningful pure semantics or projection rules, keep
`core/` and skip only the process layers you do not need.

Example:

- `src/features/agent-graph` keeps `core/domain` and `renderer`, but does not add fake `main/` or `preload/` folders because the transport boundary lives elsewhere.

## Current Feature Shape Examples

Use these local examples before inventing a new variant:

- `src/features/recent-projects` - full cross-process reference with
  `contracts`, `core`, `main`, `preload`, and `renderer`.
- `src/features/member-work-sync` - full cross-process feature with a root
  public barrel and broader main-process infrastructure.
- `src/features/member-log-stream` - full cross-process feature that uses
  `main/application/` for main-only runtime orchestration.
- `src/features/agent-graph` - thin renderer integration with `core/domain` and
  `renderer`, no fake process layers.
- `src/features/codex-model-catalog` and `src/features/team-runtime-lanes` -
  process-limited features that omit renderer or preload layers when they do not
  own that boundary.

## Definition Of Done For A Reference Feature

A feature is reference-quality when:

- structure matches the full or thin template chosen for the feature
- core is side-effect free
- app shell imports only public entrypoints
- renderer UI is dumb and presentational
- at least the main domain and application rules are tested when those layers
  exist
- architecture is enforced by lint rules
- feature has a concise standard or plan doc if it introduces a new pattern

## Recommended Test Coverage

For medium and large features, cover at least:

- domain policy tests
- application use case tests
- critical renderer interaction utilities
- one adapter-level mapping test

## Recent Projects As The Reference

`src/features/recent-projects` is the first slice that follows this standard end-to-end.

Use it as the example for:

- contracts ownership
- core/application separation
- composition-root wiring
- renderer dumb UI + hook orchestration
- browser-friendly transport direction
- feature-level lint guard rails

## Agent Graph As The Thin-Slice Reference

`src/features/agent-graph` is the thin-slice example for a renderer integration
feature built on top of a reusable package.

Use it as the example for:

- keeping pure graph semantics in `core/domain`
- exposing a renderer-only public entrypoint
- integrating `packages/agent-graph` without inventing fake process layers
- migrating legacy `src/renderer/features/*` code into the canonical feature root
