# ADR-0013: Import idiom is `from recoil.X import ...`

**Status:** Accepted
**Date:** 2026-05-07
**Deciders:** JT, Claude (in dialogue, dual-consult round Console v2 + Engine Overhaul; both engines agreed)
**Supersedes:** none directly; deprecates the `from core.X import ...` idiom with a one-cycle warning window.
**Superseded by:** none

## Decision

All NEW code uses the package idiom: `from recoil.core.X import ...`, `from recoil.api.X import ...`, etc.

The legacy `from core.X import ...` idiom (which works only because `ensure_pipeline_importable()` puts `RECOIL_ROOT` first in `sys.path`) is deprecated with a **one-cycle warning window**. Full migration of existing call sites happens in CP-D Phase 22.

CI grep guard (`recoil/scripts/ci_grep_guards.sh` Guard 3) fails the build on `^from core\.` matches **inside `recoil/api/` and `recoil/console-v2/`** — the two surfaces CP-A touches. Rest-of-codebase enforcement turns on in Phase 22.

## Context

The `from core.X` idiom only works because the loader does `sys.path` gymnastics at module import time. That coupling broke `recoil/pipeline/tools/consult.py` on 2026-05-03 — the file used `from core.X` but was invoked through a path where `ensure_pipeline_importable()` had not run, and the import failed at the bottom of a 12-minute consult call. SYNTHESIS.md §4 ("Import idiom decision") records both engines (Gemini + Opus) converging on the package idiom for the durable fix.

The `recoil/api/` layer already uses the package idiom across the board, so making it canonical means newer code is already compliant. `ensure_pipeline_importable()` stays in place as a backwards-compat shim during the deprecation window. New code never calls it.

## Consequences

- New PRs touching `recoil/api/` or `recoil/console-v2/` cannot land with `from core.X` imports — CI fails on Guard 3.
- The bulk migration of existing `from core.X` sites across `recoil/` happens in CP-D Phase 22 (see BUILD_SPEC §"Full import-idiom flip across `recoil/`").
- `ensure_pipeline_importable()` stays callable but stops being needed once Phase 22 ships; removal is a follow-on after one production cycle.
- Cited Laws: Law 1 (SSOT — one canonical import path), Law 4 (errors visible — typed import errors instead of silent `sys.path` ordering bugs), Law 14 (anti-pattern memory — don't reinvent `sys.path` gymnastics).
- Related ADRs: ADR-0011 (locks Hybrid A; this ADR locks how Hybrid A's Python imports work), ADR-0012 (`Project` is reached via `from recoil.core.project import Project`).
