§1 — Why this exists

Worker routing must be tunable from one place without editing a skill. The user-space agent policy forbids skills, plans, schemas and source from prescribing concrete models, model families or relative hierarchies — those are runtime choices for the current task. It permits application configuration. This plan builds that configuration: the single surface where the default backend, its model and effort, concurrency, gate strictness and worker fences are set for every project, and from which the current prompt can always deviate.

The architecture, layer precedence and rejected alternatives are recorded in Agent Fleet Orchestration §4. Read it before implementing; do not restate it here.

Three departures from that sketch were forced during implementation and are recorded, with their reasons, in the landed evidence: shipped defaults became a validated data layer rather than generated model field defaults, gates.enforce: off became disabled because YAML reads the former as a boolean, and authentication probing runs a backend's own declared check rather than anything reckon knows about a provider.

✓ landed 2026-08-12

§2 — Deliverables

Shipped the LinkML source reckon/schema/flight.yaml with both generated artifacts committed, four-layer deep-merge resolution with per-key provenance in reckon/flight.py, PATH and declared-auth_check availability probing, and reckon flight as a sorted-JSON primitive. A wheel-only install resolves configuration in 32 packages with no generator toolchain; the dev group adds 72 for regeneration. The host config is recorded in the evidence rather than committed. Full record: landed evidence (commit 98257f4).

✓ landed 2026-08-12

§3 — Evidence gates

All seven measures produced evidence and passed: schema round-trip byte-identical for both artifacts; a one-key project override left five sibling keys standing; 36 resolved keys each attributed across all four layers; invalid enum, unknown key, out-of-range and bad duration each named file, key path and constraint with no fallback; both CLI backends located on PATH plus the missing-binary report; single-line sorted JSON byte-identical across runs, exit 0 valid / 1 invalid; 1,495 tests pass, 35 of them new. Full record: landed evidence.

Schema round-trip

The committed Pydantic model and JSON Schema are both regenerable from reckon/schema/flight.yaml with no diff, proving the committed artifacts are not hand-edited drift.

Evidence

Layer precedence

A test asserting all four layers, in which a project layer overriding one backend key leaves that backend's other keys at their host or shipped values — deep merge, not replacement.

Evidence

Provenance

reckon flight --project reckon reports, for every resolved key, which layer supplied it. Spot-checked against a deliberately three-layer setup.

Evidence

Malformed config fails loudly

A test proving an invalid enum and an unknown key each raise an error naming file, key path and constraint. No test may show a silent fallback to defaults.

Evidence

Availability

Recorded output showing codex and claude detected on PATH, and the report a missing binary produces.

Evidence

Machine contract

Default stdout parses as JSON with a stable key order; exit code is 0 on a valid config and non-zero on an invalid one.

Evidence

Suite green

The full reckon test suite passes, with the new-test count recorded.

Evidence

§4 — Constraints

No concrete model identifier, provider name or relative model hierarchy may appear in reckon source, the LinkML schema, the generated artifacts, any skill, or this plan's prose. They live only in a config file's values, which is user data. The host config referenced above is illustrative content of a user file, not a default embedded in the package.

pyproject.toml is not a config location. It is absent from the wheel, so a [tool.reckon] section would resolve only from a source checkout.

§ Decisions

How is the flight config schema authored and validated?

Reckon already has a Pydantic + published-JSON-Schema stack for plan state. Adding a second schema system needs justification.

Repairs a stored choice that contradicted its own chosen option, its rationale and the plan prose, all three of which say dev dependency group. Implemented as recorded: linkml>=1.9 sits in [dependency-groups] dev, uv run installs it with no flag, and `uv run python scripts/regen_flight_schema.py` rewrites both committed artifacts. Measured on the built wheel — a runtime install is 32 packages with no LinkML and still resolves configuration; the dev environment is 104.

Where does host-level flight config live?

pyproject.toml is not shipped in the wheel, so it resolves only from a source checkout and would break reckon build and wheel installs. It also conflates build metadata with runtime routing. Host config belongs with host config.

§ Followups

Build the flight-control config surface

Author the LinkML model, generate and commit the Pydantic and JSON-Schema artifacts, implement four-layer deep-merge resolution with per-key provenance, add backend availability probing, and ship reckon flight as a JSON-first agent primitive. Bank each evidence gate before closing.

/reckon-ship flight-control-config

§2 and §3 landed — commit 98257f4. LinkML source plus both generated artifacts committed and round-trip verified byte-identically; four-layer deep merge with per-key provenance (36 keys attributed across all four layers); malformed layers raise naming file, key path and constraint with no fallback; PATH and declared-auth_check availability probing; `reckon flight` emits single-line sorted JSON, byte-identical across runs, exit 0 valid / 1 invalid. All seven declared gates produced evidence and passed. 1,495 tests pass, 35 new. Host config recorded in the evidence rather than committed.

Route worker dispatch through the resolved flight config

The flight surface now resolves and reports routing, but nothing consumes it yet. Uniform worker dispatch is unblocked and is what turns a resolved backend, role overlay, sandbox and concurrency into an actual dispatched worker. Note that role overlays currently resolve as data only — collapsing a role onto its backend is dispatch's job, not the config's.

/reckon-ship uniform-worker-dispatch