§05 · Perimeter

The language-model perimeter

Where models live, where they don't, and how the build enforces it.
Reads after
§04 Feed integration
Reads before
Key claim
The “no LM in the decision path” claim is enforced by per-package architecture tests on imports, not just by spec or convention.

Lincoln's central architectural commitment is that no language model is in the engagement decision path after the commander signs the mission artifact. This document shows where that line is drawn, which packages live on which side, the role models play in the packages where they are permitted, and how the build catches a violation. The build refuses to compile if the perimeter is breached.

§1Three zones

Every package in the codebase falls into one of three zones, defined by their relationship to the engagement decision.

COMPILE ZONE LM permitted, gated EXECUTE ZONE NO LM · arch-test enforced EXPLAIN ZONE LM permitted, separate chain @interpretation prose / image → MissionArtifact └ allowlist (deterministic) refuses LM output outside grammar model: gpt-4o-mini text, gpt-4o vision (OpenAI SDK) followed by deterministic gate, operator validation, commander signature @schemas @memory @policy-engine @arbitration @audit arch test fails build on import @narration audit entry → prose rationale @on-device voice query, chain RAG, render @ai-router tier-select frontier vs on-device model: Anthropic Claude (frontier), Gemma 4 E4B (Pixel on-device), Ollama (dev) separate Ed25519 chain, bound to audit tip hash
Figure 1. Three zones, three policies. The compile zone uses an LM but follows it with a deterministic allowlist and a commander signature; the execute zone forbids LM imports and the build enforces it; the explain zone uses LMs for narration and operator UX, on a separate cryptographic chain bound to the audit chain by hash.

§2Per-package, where the line falls

PackageZoneLM allowed?Provider, if anyRole
@lincoln/schemas executenoZod types, canonical JSON, source of truth
@lincoln/memory executenoSpatial index, freshness, snapshots
@lincoln/policy-engine executenoHard-blocks, four-D scoring, decision routing
@lincoln/arbitration executenoPer-proposal orchestration, timeout-to-BLOCK, audit-append serialization
@lincoln/audit executenoHash chain, Ed25519 sign / verify, canonical JSON
@lincoln/tactical-bridge executenoCoT validation, transport adapters, schema boundary
@lincoln/bridge executenoSSE event bus to UI, ring buffer, metrics
@lincoln/scenario executenoDeterministic event replay for the demo
@lincoln/comms-monitor executenoFrontier / tactical / GPS availability probe
@lincoln/runtime executenoSupervisor, CLI, mission boot & close
@lincoln/interpretation compileyesOpenAI gpt-4o-mini, gpt-4o visionProse / image → candidate MissionArtifact fields, gated by allowlist
@lincoln/narration explainyesAnthropic Claude (lazy import())Post-hoc prose rationale on its own signed chain, bound to audit tip
@lincoln/on-device explainyesGemma 4 E4B int4 (MediaPipe), Ollama (dev)Voice query, render rationale, RAG over audit chain
@lincoln/ai-router explainno SDKTier selector — does not import any LM SDK itself; routes to frontier or on-device providers
@lincoln/synthesis explainno SDKDeterministic mission-artifact → scenario-script transform; uses no LM
@lincoln/ui explainno SDKReact surfaces; routes LM calls through ai-router, never imports SDK directly
@lincoln/capacitor explainyesMediaPipe LLM Inference (Kotlin)Pixel 9 Pro Fold wrapper; on-device Gemma plugin lives here

§3What the language model is doing in each permitted zone

Compile zone — @lincoln/interpretation

A frontend pass that converts ROE prose and brief images into candidate fields of a MissionArtifact. The model performs translation: it reads paragraph 8.a and proposes a PROHIB-NFA rule entry with a polygon and a paragraph reference. The rule grammar is fixed in the engine; the model's output runs into the deterministic allowlist gate (§02), then operator validation, then commander signature. Errors are caught by the gates downstream.

Explain zone — @lincoln/narration

A post-mission pass that takes each audit entry and produces a prose rationale suitable for an after-action review or JAG read-out. Narration runs on its own Ed25519-signed hash chain, bound to the audit chain via the audit chain's tip hash. The audit chain is the source of truth; narration is annotation that runs on a separate chain and cannot rewrite it.

The Anthropic SDK is loaded via dynamic import() so offline, cached, and non-narrating runs do not touch the dependency. The build's arch test for @lincoln/narration includes @anthropic-ai/sdk on the allowlist for that package.

Explain zone — @lincoln/on-device

A live-mission pass for operator UX: voice queries (“what's the status of TRK-0x42?”), rendered rationales for QUEUE_APPROVAL modals (“why am I being asked?”), and RAG-style queries over the in-memory audit chain (“has anything blocked in the last five minutes?”). Runs on Gemma 4 E4B int4 via MediaPipe LLM Inference on the Pixel 9 Pro Fold's Tensor G4 GPU; falls back to Ollama for desktop development.

The on-device model reads audit entries and renders prose. Explain-zone code consumes execute-zone outputs and writes neither proposals nor weapons-control state.

§4How the build enforces it

Each execute-zone package contains a test/arch.test.ts that does static-import analysis of the package's src/ tree and fails the build if a forbidden module appears. The forbidden list:

ModuleReason it's forbidden in the execute zone
@anthropic-ai/sdkFrontier LLM client — would put a model in the decision path
anthropic / anthropic-aiOlder / alias forms of the same SDK
openaiOpenAI SDK — same reason
@google/generative-aiGemini SDK — same reason
ollamaLocal LLM dev shim — should never appear in execute-path code even for dev
@mediapipe/tasks-genaiOn-device Gemma client — lives in the explain zone, never here

The arch test is mechanical: it reads every .ts file under src/, parses the import graph, and asserts no import path matches the forbidden list. A pull request that introduces a forbidden import fails CI before review. This is much stronger than a code-review convention — reviewers miss things; tsc doesn't.

On mechanical enforcement The arch test runs in CI and on every local pnpm typecheck. Adding a forbidden import requires both the import statement and a corresponding edit to the arch test, both of which appear in the diff. The perimeter is enforced by the toolchain that compiles the binary.

§5The directive language, mapped to this perimeter

DoDD 3000.09 calls for “appropriate level of human judgment over the use of force.” The compile-and-execute model maps that requirement onto specific architectural commitments. The LM perimeter is the most concrete of them.

Directive intentLincoln architectural commitmentWhere you can verify
Human judgment governs the use of force Commander signs the mission artifact at compile time; runtime refuses to boot on signature mismatch Boot logic in @lincoln/runtime; test that flips a byte and asserts boot fails
Judgment is exercised at an appropriate point Compile time, with full operational picture and staff support — not under engagement-tempo stress The compile pipeline (§02), the operator validation UI
Engagement decisions are traceable Every fired rule cites a paragraph_ref to the artifact, and through it to the source ROE Audit entries' fired_rules[].paragraph_ref field
Decisions are auditable after the fact Hash-chained, Ed25519-signed audit log; verifyChain() recomputes at shutdown Integration test runs verifyChain(); result printed in evidence
Engagement logic is reviewable / certifiable Decision is reproducible from (artifact, snapshot, proposal) — no nondeterministic components on the path Per-package arch tests forbidding LM SDK imports

§6Caveats

The LM perimeter is a structural property, not a sufficiency claim. It does not guarantee:

§7End of series

The five documents together describe the path from a commander's signed prose to a paragraph-cited, signed audit entry, with budgets, perimeter, and limitations stated.