Status
contract (production hardness)
Conceptual layer
④ Decision
Repo layer
L4 knowledge-reasoning
Source
architecture section 3.6.4, section 13
ADR
027
Gateway (direction)
D21
Siblings
16-operations.md · 26-decision-case-lifecycle.md · 15-l3-l4-interface.md · 11-models-and-seams.md

Purpose#

L4 is a composition of ports. Production readiness is mostly how those ports fail. This doc defines deadlines, retries, circuit breakers, idempotency, and degraded outcomes — so implementers do not invent per-call behaviour.


Port catalog#

PortDirectionSide effect?
ModelSlotOutNo (paid tokens only)
L3MethodsPortOutNo (calculator / condition / sim / verify-builder)
BuilderReadPortOutNo (PSM bulk/list)
AgentZoomPortOutNo (allowlisted zoom)
MemoryPortOutRead plant/dialogue; writes only typed learning via L5 path
OeCorpusPortOutNo (advisory retrieval)
L4StoreIn/outDurable case/trace/ledger/PSM cache
CardSinkOutYes — deliver Prescription draft to L5 (as built: card proposal / prescription.json)
WorkQueueIn/outDurable enqueue

No port writes OT, schedules, or master data.


Per-call contract (every outbound port)#

FieldRequired
deadline_msYes — from registry by port + latency_tier
idempotency_keyYes when side effect or costly duplicate matters
attemptYes
correlation_id / decision_case_idYes
Resultok | retryable | non_retryable | timeout + typed error code

Retries#

ClassPolicy
Retryable (5xx, timeout, rate limit)Exponential backoff + jitter; max attempts from registry
Non-retryable (4xx schema, auth, envelope reject)No retry; case → semantic path or failed_infra
CardSinkRetry with same emit_idempotency_key; L5 must be idempotent on that key
ModelSlotRetry once on timeout; on persistent fail → one-family mode if configured else withhold / failed_infra per seam class

Never retry a successful CardSink. Never invent a second emit key for the same terminalizing attempt.


Circuit breakers#

Per plant + port (+ provider for ModelSlot):

StateBehaviour
closedNormal
openFail fast retryable or degrade (below)
half-openProbe one call

Trip on error rate / consecutive failures (registry thresholds). Open breaker on L3MethodsPort.calculator → no emit with ₹; withhold or abstain — never invent money.


Idempotency keys#

OperationKey material (conceptual)
Finding intakeplant_id + finding_id + finding_version → same DecisionCase
CardSink emit/supersededecision_case_id + operation + proposal_content_hash
Shift sweep enqueueplant_id + shift_id + sweep_kind
Learning fact writeclosure_id + fact_schema_version

At-least-once delivery from L3 is assumed. Duplicate FindingAs-built L3 detector output admitted to L4 (finding.json 1.2.0) → attach to existing case or no-op; never two emits for one finding id.


Degraded modes (normative map)#

FailurePlant path behaviour
Family A downOne-family mode if pinned; else withhold on action seams
Both families downNo draft; failed_infra or abstain with ops alert — no fake card
Calculator downNo priced emit; withhold if card needs ₹
Condition test downNo discovery emit that requires it; Finding path may continue if Finding already carries floor
MemoryPort downContinue without advisory memory; mark freshness/unknown; do not invent memory
OeCorpusPort downContinue without OE advisory
BuilderRead / PSM stale past hard limitWithhold when proof needs fresh state (staleness_hard_limit)
CardSink downRetry; case stays terminalizing; alert; no “tell the model to try another channel”
L4Store downStop leasing new cases; fail closed

Security and tenancy (software strength)#

RuleDetail
Plant isolationEvery port call scoped by plant_id; no cross-plant read in v1
SecretsModel API keys / DB creds never in traces or CardSink payloads
Authn/zService identity between L3/L4/L5; plant-scoped tokens for Ask/ops
PIIRoster/person resolution is L5; L4 holds roles, not personal phone dumps in OE corpus
Supply chainLockfile pins dependency versions for L4 services; SBOMs in release artifact

Rejected alternatives#

AlternativeWhy
Infinite retries on CardSinkDuplicate cards without idempotency
Soft-fail calculator with model-estimated ₹Kernel money rule
Shared ModelSlot breaker across all plantsOne noisy plant takes down fleet
Logging full prompts with secrets to the council exportPrivacy (16)

What would change this#

  • Measured L3 p99 forces higher deadlines → registry by latency_tier after Pilot.
  • Need multi-region CardSink → ADR for cross-region idempotency store.

v1 slice vs later#

v1Later
Deadlines, retries, breakers, idempotency keys as aboveAutomated breaker tuning
Fail closed on L4Store outageRead replicas for PSM build
Manual breaker reset in opsSame + audited

Change class#

Deadlines / retry counts: data. Changing degraded mode so money can be invented: forbidden. New port: this doc + registry + contract delta.

Page history: last 4 changes
  1. 2026-10-07 docs(technical): rewrite l4 21-30, glossary and README; reconcile architecture gaps e7fead7
  2. 2026-10-03 docs(decisions): add ADR-033..038 (twin runtime, fast read path, plant-side writer, message classes, alerts and quality-to-lot link, part-keyed parameters), fast-loop technical set, rebuilt index with renumbering map; fix bare-number link text and ranges 22e2872
  3. 2026-10-03 docs(decisions): renumber live ADRs 001-032 in order, mark withdrawn refs ADR-W###, repoint withdrawn links to archive, note partial supersessions 36c944e
  4. 2026-09-25 docs(l4): agentic decision architecture, ADRs, and production hardness 8275e7c

Diagram

100%

Search the architecture