# CrystFlux v1 Triadic Structure Guide

This guide is an AI-friendly “constitution + signposts” for the triadic directory structure
(`core/`, `boundary/`, `adapters/`) in CrystFlux v1.

Goal: reduce inference cost, avoid early convergence, and prevent dependency backflow
(pulling `core/` outward).

Start here:
- `ESSENTIAL_FILES_MAP.md` (repo root)
- `src/crystflux/v1/core/value_api.py` (public surface)

## Triadic Layers (Nested / Concentric Model)

Think in “center vs outer rings” (no arrows): core is the immutable center; boundary wraps contracts
around it; adapters wrap integrations/IO around the contracts.

### ASCII (always readable)

```text
+-----------------------------------+
| adapters  (integrations / IO)     |
|  +-----------------------------+  |
|  | boundary (contracts)        |  |
|  |  +-----------------------+  |  |
|  |  | core (immutable logic) |  |  |
|  |  +-----------------------+  |  |
|  +-----------------------------+  |
+-----------------------------------+
```

### Mermaid (when rendered)

```mermaid
flowchart TB
  subgraph A[adapters (integrations / IO)]
    subgraph B[boundary (contracts)]
      C[core (immutable logic)]
    end
  end
```

## Layers
- **Core**: Immutable value processing (no external integrations).
  - Key files: `core/value_api.py`, `core/value_modes.py`, `core/value_core.py`, `core/void_value.py`
- **Boundary**: Contracts and schemas (what exists, not how it is wired).
  - Key files: `boundary/crystallizer_port.py`, `boundary/event_schema.py`, `boundary/*_logger.py`
- **Adapters**: Wiring/integrations (how contracts are implemented/connected).
  - Key files: `adapters/crystallizer_impl.py`, `adapters/*_logger_impl.py`, `adapters/pydantic.py`

## Import Rules

Write the dependency rules in plain “may import / must not import” terms.

- `core/` must not import from `boundary/` or `adapters/`.
- `boundary/` may import from `core/`.
- `adapters/` may import from `boundary/` and `core/`.

### Allowed / Forbidden imports (summary table)

| Importer | Allowed to import | Forbidden to import |
|---|---|---|
| `crystflux.v1.core.*` | stdlib, `crystflux.v1.core.*` | `crystflux.v1.boundary.*`, `crystflux.v1.adapters.*` |
| `crystflux.v1.boundary.*` | stdlib, `crystflux.v1.core.*`, `crystflux.v1.boundary.*` | `crystflux.v1.adapters.*` |
| `crystflux.v1.adapters.*` | stdlib, `crystflux.v1.core.*`, `crystflux.v1.boundary.*`, `crystflux.v1.adapters.*` | (none in v1) |

Note: runtime call flow is often “adapters calls core”, but import direction is the rule above.

## Tips for AI Coders

- When changing behavior, start from `src/crystflux/v1/core/value_api.py` and follow `ESSENTIAL_FILES_MAP.md`.
- Keep `core/` pure: prefer adding observation/logging in `boundary/` + `adapters/`.
- Modes: Strict (fail-fast), Latent (collapse missing/mismatch to VOID), Dream (tolerate undefined methods + observe).
- `with_value`/`map` semantics (VOID → None, JSON normalization) are documented in
  `src/crystflux/v1/core/TECH_NOTES.md`; `with_value` returns a new Value and never mutates the
  original.

## Example
`Crystallizer.latent(data).get('key').as_str()` – VOID fallback.

## Resources
- Read order map: `ESSENTIAL_FILES_MAP.md`
- Design Background: `docs/01-concepts/README.md`
