
The recommended directory structure for Vary applications.

## Single-module project

A small project or library with a flat source structure:

```text
my-project/
├── vary.toml              # Project configuration
├── src/
│   ├── main.vary          # Entry point
│   ├── store.vary         # Core logic (pure)
│   └── service.vary       # Boundary / effectful code
├── tests/
│   └── store_test.vary    # Unit tests
├── contracts/
│   └── store.md           # Informal contracts / design notes
├── .vary/                 # Compiler state (do not commit)
└── .gitignore
```

`src/` holds all source files. `tests/` holds test files (discovery patterns are `test_*.vary` and `*_test.vary`). `contracts/` is a conventional directory for design notes, not compiled. `.vary/` is generated by the compiler; never commit it.

### Minimal `vary.toml`

```toml
[project]
name = "my-project"
version = "0.1.0"

[source]
directories = ["src"]
test_directories = ["tests"]
```

---

## Multi-module project

A larger application with domain separation:

```text
market-simulator/
├── vary.toml
├── src/
│   ├── main.vary                # Entry point
│   ├── domain/                  # Pure core logic
│   │   ├── account.vary
│   │   ├── order.vary
│   │   ├── trade.vary
│   │   └── types.vary
│   ├── engine/                  # Internal algorithms
│   │   ├── book.vary
│   │   └── matching.vary
│   ├── api/                     # HTTP boundary (effectful)
│   │   ├── state.vary
│   │   ├── books.vary
│   │   └── accounts.vary
│   ├── agents/                  # Simulation agents
│   │   └── random_agent.vary
│   └── metrics/                 # Observability
│       └── scale_metrics.vary
├── tests/
│   ├── domain/
│   │   ├── account_test.vary    # Unit tests for pure core
│   │   └── order_test.vary
│   ├── engine/
│   │   └── matching_test.vary
│   ├── api/
│   │   └── books_test.vary      # Integration tests
│   └── test_e2e.vary            # End-to-end tests
├── contracts/
│   ├── order-lifecycle.md       # Domain invariants
│   └── api-surface.md           # API contract documentation
├── .vary/
└── .gitignore
```

Subdirectories become module prefixes in imports:

```vary-snippet
import domain.order
from domain.account import Account
from engine.matching import match_orders
```

---

## Directory roles

### `src/`: source code

All application source lives under `src/` by default. Organize subdirectories by domain concern:

| Directory pattern | Purpose | Effect profile |
|-------------------|---------|----------------|
| `domain/` | Core types and pure business logic | Pure, no I/O, no network |
| `engine/` | Algorithms and processing | Pure or minimal effects |
| `api/` | HTTP endpoints, service boundaries | Effectful: NETWORK, IO |
| `agents/` | Active components, background workers | Effectful |
| `metrics/` | Observability and reporting | Effectful: IO |
| `sim/` | Simulation orchestration | Mixed |

The architectural principle here is separating pure core logic from effectful boundaries.

Pure core (`domain/`, `engine/`) contains business rules, data transformations, algorithms. These functions have no side effects: they take values and return values. They are straightforward to test and safe to mutate.

Effectful boundaries (`api/`, `agents/`) talk to the network, filesystem, or external services. Keep these thin; they should delegate to pure core functions for actual logic.

This separation is not just convention. Vary's effect system tracks it:

```toml
# vary.toml: deny network effects in pure core modules
[check.effects]
deny = ["NETWORK"]
```

You can also use the `require_pure` compiler option to enforce purity in core modules.

### `tests/`: test code

Test files live under `tests/` by default. Mirror the `src/` subdirectory structure:

```text
src/domain/order.vary      →  tests/domain/order_test.vary
src/engine/matching.vary   →  tests/engine/matching_test.vary
```

Tests use the `test` DSL:

```vary-snippet
test "order total is price times quantity" {
    let order = Order(price: 100, qty: 5)
    observe order.total() == 500
}
```

| Location | Category | What to test |
|----------|----------|--------------|
| `tests/domain/` | Unit | Pure functions, type invariants |
| `tests/engine/` | Unit | Algorithm correctness |
| `tests/api/` | Integration | HTTP endpoints with mock transport |
| `tests/` (root) | End-to-end | Full application flows |

### `contracts/`: design documentation

A conventional directory for domain invariants, API surface contracts, cross-module interface expectations, and design decisions. This directory is not compiled or enforced by the toolchain; it exists for human readers.

For compiler-enforced contracts, use `in {}` / `out {}` blocks on functions:

```vary-snippet
def withdraw(account: Account, amount: Int) -> Account {
    in {
        amount > 0
        account.balance >= amount
    }
    out (result) {
        old(account.balance) - amount == result.balance
    }
    return Account(balance: account.balance - amount)
}
```

### `.vary/`: compiler state

Generated automatically. Contains:

| Path | Purpose |
|------|---------|
| `artifacts/` | Content-addressed compilation cache (SHA-256) |
| `project.json` | Detected project environment |
| `status.json` | Last command status |
| `history.jsonl` | Command history |
| `runs/` | Test and mutation run artifacts |

Add to `.gitignore`:

```text
.vary/
.vary-logs/
.vary-mutation-cache-*
```

---

## Configuration reference

The `vary.toml` file at the project root controls project layout and toolchain behaviour.

### Layout options

```toml
[project]
name = "my-project"
version = "0.1.0"
edition = "1"

[source]
directories = ["src"]           # Where source files live
test_directories = ["tests"]    # Where test files live
excludes = [".vary/**"]         # Glob patterns to skip
strict_imports = false          # Require explicit imports

[build]
entry = "main.vary:main"       # Entry point (module:function)
output_dir = "build"           # Compiled output
```

### Quality enforcement

```toml
[compiler]
strict_null_checks = true       # Enforce null safety
require_contracts = false       # Require contracts on functions
min_contract_percent = 0        # Minimum % of functions with contracts
require_pure = false            # Require pure function markers
min_pure_percent = 0            # Minimum % of pure functions

[test]
parallel = 4                    # Parallel test runners
coverage = true                 # Enable coverage tracking
coverage_threshold = 80         # Minimum coverage %

[mutation]
profile = "ci"                  # "ci" for JSON + score gate
ci_score_threshold = 80.0       # Minimum mutation score
min_observability = 75.0        # Minimum observability score

[check.effects]
deny = ["NETWORK"]              # Deny network effects in checked code

[services]
allowed_hosts = ["api.example.com"]   # Restrict outbound service calls
denied_hosts = ["*.internal.corp"]
```

### Per-module mutation rules

```toml
[[mutation.module]]
pattern = "domain/**"
min_score = 90.0                # Pure core should have high mutation score
max_survivors = 3

[[mutation.module]]
pattern = "api/**"
min_score = 60.0                # Boundaries are harder to mutate
```

---

## Choosing a layout

| Project size | Layout | Notes |
|-------------|--------|-------|
| Script or spike | Flat files, no subdirs | `vary run main.vary` is enough |
| Small library | Single `src/` + `tests/` | The minimal layout above |
| Application | Multi-module with domain separation | Mirror `src/` structure in `tests/` |
| Monorepo module | Same as application, with `[dependencies]` for cross-project imports | Use path dependencies in `vary.toml` |

### Path dependencies for multi-project setups

```toml
# In consumer/vary.toml
[dependencies]
shared-types = { version = "1.0.0", path = "../shared-types" }
```

```vary-snippet
# In consumer source
from shared_types.domain import Order
```
