Fountain Coach Gitowner-controlled · read only

LaneResolutionKit.git · README.md

LaneResolutionKit.git / README.md

revision d17d1c98e91b4db8a754a121cc96cac1f3d1814b · complete file

# LaneResolutionKit

Which lane serves this role, right now?

Answered **once**, into a value that carries its own client budget — so no part of a system can size a request for
one lane and spend it on another, and no sentence about a lane costs the user their password.

Pure Swift, **zero dependencies**. The resolver takes configuration, consent, credential state, health and a clock,
and returns a decision or a typed refusal. It performs no I/O, and it cannot: a package with no dependencies cannot
reach a credential store, which is what makes "the suite never prompts" a structural guarantee rather than a habit.

## The problem

Systems that talk to several model providers tend to answer "which lane?" in several places — an availability
probe, a route builder, a budget calculator, a status line. Each is reasonable alone. Together they drift, and the
drift is invisible until a request sized for a 30,000-token lane executes against a 4,096-token one.

`docs/INCIDENTS.md` records the measured failures this kit exists to end.

## Use

```swift
import LaneResolutionKit

let resolver = LaneResolver(lanes: [
    LaneDeclaration(
        identity: LaneIdentity("local"),
        displayName: "On-device model",
        costClass: .free,
        contextWindowTokens: 4_096,
        outputReserveTokens: 1_100
    ),
    LaneDeclaration(
        identity: LaneIdentity("hosted"),
        displayName: "Your hosted plan",
        costClass: .paid,
        contextWindowTokens: 30_000,
        outputReserveTokens: 4_000,
        requiredCredential: CredentialIdentity("api.key")
    )
])

let resolution = resolver.resolve(
    role: LaneRole("read"),
    request: LaneResolutionRequest(
        configured: [LaneIdentity("local"), LaneIdentity("hosted")],
        consent: .scoped("this-document"),
        scope: "this-document",
        credentialIsPresent: { store.hasItem(for: $0) },   // attributes only — never prompts
        credentialState: { store.state(of: $0) },          // reads data — may prompt
        constructible: [LaneIdentity("local"), LaneIdentity("hosted")],
        health: [LaneIdentity("hosted"): .ready(detail: "3% headroom")],
        preferredOrder: [LaneIdentity("hosted"), LaneIdentity("local")],
        now: Date()
    )
)

guard let decision = resolution.decision else {
    // A refusal is a value with a reason and one remedy — never a nil.
    return report(resolution.outcome)
}
let room = decision.budget.payloadTokens   // belongs to the lane that was decided, by construction
```

To say which lane *would* serve without unlocking anything, use `name(role:request:)`. Same lanes, same gates, same
order; only the credential gate is answered from attributes.

## How it decides

Five ordered gates, each of which may only **narrow**:

```
configured → permitted → credentialed → constructible → healthy
```

`permitted` sits before `credentialed` deliberately: under `localOnly`, a paid lane is removed before anything asks
its credential, so no consent means no credential read and therefore no prompt.

`preferredOrder` orders survivors. It can widen nothing — a lane that failed a gate is not resurrected by being
preferred.

## What it deliberately does not do

- **No lane inventory.** No enum of providers. Lanes are declared by the caller, so adding one edits no file here.
- **No `Optional` for unavailability.** Every refusal names the role, the lane, the gate, the reason and one remedy.
- **No budget without a decision.** `LaneBudget` has no public initialiser taking a number.
- **No narrowing from the wrong evidence.** Only an explicit window overflow — carrying input, window *and* the
  payload that was sent — may narrow a size budget. A timeout is latency.
- **No memory.** Health is an input, not state. The kit does not remember that a lane failed; the caller supplies
  current health each time.

## Tests

19 tests, no network, no credential store, no prompts. An exhaustive truth table over
`permitted × credentialState × constructible × health × role` (864 cells), three properties over ~27,000 reachable
resolutions, and a named regression per incident. The budget property is accompanied by a test proving it *can*
fail — an assertion that cannot fail proves nothing.

```sh
swift test
```

## Governance

`AGENTS.md` (law), `PLANS.md` (intent), `.codex/skills/` (procedures), `FCIS_COMPLIANCE.md` (which organization
standards bind this repository, with the evidence and the commands to falsify it).