L4 kernel (normative)
Version: l4-kernel.v1
Status: contract · Conceptual layer: ④ Decision · Repo layer: L4 knowledge-reasoning · Source: architecture section 3.6.4, section 5.3, section 8 · ADRs: 020 · 025 · 026
Frozen surface — changes only through an ADR, a kernel version bump, and a full replay. Sibling docs link here; they must not restate these rules in softer language.
“Frozen” means replay has a fixed yardstick and the plant has a stable promise. It does not mean the kernel never changes. It is kept small and parameterised by registries, so most expansions never touch it.
1. Terminals#
Every DecisionCaseOne run unit: intake + snapshot + obligations + candidates + terminal ends in exactly one terminal, always with a DecisionTraceAlways-on record: observed, context, action, policy, approval, outcome (and seam decisions):
| Terminal | Meaning |
|---|---|
emit | Send one Prescription to L5 (as built: card proposal / prescription.json 1.0.0) |
supersede | Replace a prior L4 proposal for the same condition key before owner acceptance |
withhold | Do not send; reason recorded (constraint, disagreement, proof floor, etc.) |
abstain | Insufficient case to decide; reason recorded |
Portfolio hold is not a terminal. It is L4-internal: the proposal stays in the L4 store, visible to staff, and is not sent to L5.
2. One-card rule#
- One card per condition keyStable id for “this plant condition”; one open card per key.
- One recommended action; at most two alternatives; one alternative is always no action.
- One owner role from the configured role set.
- Primary domain is a domain registry id, taken from the family registry (Findings) or the pattern registry (discoveries).
- The kernel refers to registries by id. It never lists domains by name.
3. Write ban#
No L4 tool writes equipment, schedules, dispatch, quality holds, maintenance authorization, master data, or customer commitments. Reads only. Side effects belong to L5 policy (default off) after a human accepts.
4. Money#
Rupees only from L3 calculator references. An unreferenced rupee (or any money field without a calculator citation) → drop the claim; if the candidate still depends on that unreferenced rupee → withhold. Models never invent or assign a rupee. Non-money quantities without citations are dropped as uncited claims (section 13); they do not by themselves force withhold unless a family proof obligation requires them. Section wallets are never summed into one hero number.
5. Constraint evaluator#
Code evaluates typed constraints. Result:
| Result | Kernel action |
|---|---|
violated | withhold |
unknown on a hard constraint | withhold (reason=constraint_unknown) |
| LLM “possible conflict” without a code result | withhold (gate_id=llm_possible_conflict, hard) |
None of these can be overridden by modeled benefit. Code always evaluates every hard constraint row whose footprint intersects the candidate. Models may only add advisory rows to evaluate; they may never omit a matching hard row.
6. Verification plan#
A verification plan may only narrow its source plan (FindingAs-built L3 detector output admitted to L4 (finding.json 1.2.0) plan or L3-built discovery plan): same boundary, equal or tighter bounds. It may not invent new signals or widen scope.
7. Supersede#
Supersede only before owner acceptance. After acceptance → a separate card or a conflict note — never silent replace. Wire fields: 18-contract-deltas.md.
8. Simulator output#
L3 simulator output is evidence tierContract tier on claims: measured / confirmed / modeled / unknown; quantity labels per D13 Modeled, cites method and version, and must sit inside that method’s validated envelope to support emit. Out-of-envelope → withhold (gate_id=simulator_out_of_envelope, hard).
9. Hard stops#
Hard stops from the master document section 7 always apply: no silent safety or critical-equipment control; no quality hold release, conformance sign-off, or process acceptance; no maintenance authorization or lockout bypass; no silent change to customer priority, promise dates, routing, master data, or the full dispatch sequence. A quality correction and a near-term sequence are allowed when a named person accepts them before any write-back. No constraint override for a model benefit alone.
10. No self-promotion#
Nothing in procedural memory, prompts, registries, thresholds, or model pins promotes itself. Changes go through release lockfile, replay, and a named owner where required. A global pin applies at a plant only after that plant’s named owner accepts it (or has opted in to automatic acceptance of global pins).
11. Gates: hard vs soft#
Every gate is typed hard or soft. Every block records the gate idStable id of the hard or soft gate that blocked a candidate (canonical table below). Detail and exploration eligibility: 22-missed-opportunities.md.
Hard gates (never tunable, never in backlog, never explored)#
gate_id | Trigger |
|---|---|
hard_stop | ADR-018 sacred constraints |
constraint_violated | Code evaluator violated |
constraint_unknown_hard | unknown on hard / conditional-hard neighbourhood |
llm_possible_conflict | Model flags conflict without code result |
unreferenced_rupee | Money without calculator citation after claim drop |
write_tool | Write / OT side-effect tool attempted |
proof_floor | Missing asset bind, verification path, or L3 condition test (discoveries) |
simulator_out_of_envelope | Modeled support outside validated use |
action_seam_disagreement | Dual-family disagreement on action / owner / constraint-affecting / verification / terminal seams |
uncertified_detector | Uncertified detector version (shadow / withhold — never emit) |
supersede_after_accept | Attempt to supersede after owner acceptance |
staleness_hard_limit | Freshness past the hard staleness limit |
Action-seam disagreement is hard, not soft. Two families either picked the same closed option or they did not — there is no tunable “agreement floor” for action-affecting seams.
Soft gates (thresholds in registry; tuned by evidence; exploration-eligible only when listed in 22)#
gate_id | Trigger |
|---|---|
routing_agreement | Disagreement on routing-class seams only (workflow, optional analysis, …) — uses registry default; soft for calibration of whether default was right |
one_family_confidence | One-family mode numeric floors |
evidence_tier_min | Soft minimum tier for emit path |
freshness_margin | Soft freshness (hard limit is staleness_hard_limit) |
attention_budget | Over per-role shift budget → hold |
reproposal_cooldown | Negative memory cooldown |
hypothesis_volume_cap | Grounded-hypothesis lane volume |
pattern_precision | Pattern demotion to shadow |
12. Stage-graph checkpoints#
Every stage graph (see 21-registries-and-stage-graph.md) must still pass:
- Constraint evaluator before portfolio
- Portfolio before terminal
- Card minimizer (one primary domain, wallets not summed, verification narrowed) before kernel re-check
- Kernel re-check on the chosen set before terminal
Default order: candidates → constraint evaluator → portfolio → card minimizer → kernel re-check → terminal.
Kernel re-check (normative list)#
On the chosen set, code re-verifies: money references; write ban; constraint results for intersecting hard rows; proof floorMinimum evidence/structure required before emit (asset bound, verification path, L3 condition test for discoveries); one-card / one-owner shape; verification narrow-only; action-seam disagreement not present; simulator envelope if Modeled supports emit. Failure → withhold / abstain with reason — never quiet emit.
13. Evidence#
- Every claim cites a ledger row id. Uncited claims are dropped by code (
gate_idrecorded when drop invalidates the candidate). - EvidenceLayer contract for detector output (direction; as built: Finding finding.json 1.2.0) tiers are assigned by code from source type (as built ledger: Measured / Confirmed / Modeled / Unknown; direction: evidence labels and contract tiers per D13). Models never assign a tier.
- Partitions (measured, advisory, model) are never merged.
14. Primary domain#
Primary domain is a domain registry id:
- Findings → from the family registry
- Certified patterns → from the pattern registry
- Grounded hypotheses → from the hypothesis type’s registry entry (required field before the lane may emit)
The kernel never lists domain names.
Change control#
| Change | Path |
|---|---|
| Soft-gate threshold | Registry + replay + owner acceptance |
| New domain / stage / pattern | Registry + replay (17-change-guide.md) |
| Any rule in this file | ADR + l4-kernel version bump + full replay |
v1 slice vs later#
| v1 | Later |
|---|---|
This kernel version (l4-kernel.v1) as the yardstick | New version only via ADR + full replay |
| Hard vs soft gate split as listed | Soft list may grow via registry; hard list only via ADR |
| Dual-family disagreement → withhold on action-affecting seams | Same unless an ADR changes disagreement policy |
Page history: last 5 changes
- docs: keep agents out of archive; changelog; final check suite
fd7f122 - docs(technical): rewrite l4 00-10 to the architecture
c52a111 - 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 - docs(decisions): renumber live ADRs 001-032 in order, mark withdrawn refs ADR-W###, repoint withdrawn links to archive, note partial supersessions
36c944e - docs(l4): agentic decision architecture, ADRs, and production hardness
8275e7c