problem-frame-gate 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,425 @@
1
+ """Deterministic component replay over a legal envelope log."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping, Sequence
6
+ from copy import deepcopy
7
+ from dataclasses import dataclass
8
+ from fractions import Fraction
9
+ from typing import Any, Protocol
10
+
11
+ from .errors import FoldError, LogVerificationError
12
+ from .model import Envelope, Frame, Horizon, Status
13
+ from .result import CheckBuilder, CheckResult
14
+ from .verifier import EnvelopeVerifier, digest_log
15
+
16
+
17
+ class StateComponent(Protocol):
18
+ name: str
19
+
20
+ def initial_state(self) -> Any: ...
21
+
22
+ def apply(self, state: Any, envelope: Envelope) -> Any: ...
23
+
24
+
25
+ @dataclass(frozen=True, slots=True)
26
+ class FoldState:
27
+ components: Mapping[str, Any]
28
+ ordered_eids: tuple[str, ...]
29
+ log_digest: str
30
+
31
+ def component(self, name: str) -> Any:
32
+ return self.components.get(name, {})
33
+
34
+ def to_json(self) -> dict[str, Any]:
35
+ return {
36
+ "components": self.components,
37
+ "ordered_eids": list(self.ordered_eids),
38
+ "log_digest": self.log_digest,
39
+ }
40
+
41
+
42
+ class FoldKernel:
43
+ """Replay kernel with manifest-supplied components."""
44
+
45
+ footprint = frozenset({"FoldKernel", "EnvelopeVerifier"})
46
+
47
+ def __init__(self, components: Sequence[StateComponent] | None = None) -> None:
48
+ self.components = tuple(components or default_components())
49
+ names = [component.name for component in self.components]
50
+ if len(names) != len(set(names)):
51
+ raise ValueError("component names must be unique")
52
+ self.verifier = EnvelopeVerifier()
53
+
54
+ def fold(self, horizon: Horizon, envelopes: Sequence[Envelope]) -> FoldState:
55
+ legal = self.verifier.verify(horizon, envelopes)
56
+ if not legal.ok:
57
+ raise LogVerificationError("log is not legal")
58
+ ordered = self.verifier.canonical_order(horizon, envelopes)
59
+ states: dict[str, Any] = {component.name: component.initial_state() for component in self.components}
60
+ for env in ordered:
61
+ for component in self.components:
62
+ try:
63
+ states[component.name] = component.apply(states[component.name], env)
64
+ except FoldError:
65
+ raise
66
+ except Exception as exc: # pragma: no cover - defensive wrapper
67
+ raise FoldError(f"{component.name} rejected envelope {env.eid}: {exc}") from exc
68
+ return FoldState(states, tuple(env.eid for env in ordered), digest_log(envelopes))
69
+
70
+ def check_fold(self, horizon: Horizon, envelopes: Sequence[Envelope]) -> CheckResult:
71
+ builder = CheckBuilder(footprint=set(self.footprint))
72
+ legal = self.verifier.verify(horizon, envelopes)
73
+ if not legal.ok:
74
+ return legal.merge(builder.result())
75
+ try:
76
+ state = self.fold(horizon, envelopes)
77
+ except FoldError as exc:
78
+ builder.error("fold-rejected", str(exc))
79
+ return builder.result(digest=legal.digest)
80
+ return builder.result(digest=state.log_digest)
81
+
82
+
83
+ class FrameComponent:
84
+ name = "frames"
85
+
86
+ def initial_state(self) -> dict[str, dict[str, Any]]:
87
+ return {}
88
+
89
+ def apply(self, state: dict[str, dict[str, Any]], envelope: Envelope) -> dict[str, dict[str, Any]]:
90
+ next_state = deepcopy(state)
91
+ kind = envelope.kind
92
+ payload = envelope.payload
93
+ frame_id = str(payload.get("frame_id", payload.get("object", "")))
94
+
95
+ if kind in {"Frame", "ProblemFrame"}:
96
+ frame = Frame.from_payload(payload)
97
+ if not frame.frame_id:
98
+ raise FoldError(f"frame payload in {envelope.eid} has no frame_id")
99
+ record = next_state.setdefault(frame.frame_id, {})
100
+ record["frame"] = frame.to_json()
101
+ record.setdefault("status", Status.INACTIVE.value)
102
+ elif kind == "Proposed":
103
+ _require(frame_id, "frame_id", envelope)
104
+ record = next_state.setdefault(frame_id, {})
105
+ record["status"] = Status.INACTIVE.value
106
+ elif kind == "Activated":
107
+ _require(frame_id, "frame_id", envelope)
108
+ record = next_state.setdefault(frame_id, {})
109
+ record["status"] = Status.ACTIVE.value
110
+ record["activated_by"] = envelope.eid
111
+ elif kind == "DiagnosticActivated":
112
+ _require(frame_id, "frame_id", envelope)
113
+ record = next_state.setdefault(frame_id, {})
114
+ record["status"] = Status.DIAGNOSTIC_ACTIVE.value
115
+ elif kind == "Suspended":
116
+ _require(frame_id, "frame_id", envelope)
117
+ record = next_state.setdefault(frame_id, {})
118
+ record["status"] = Status.SUSPENDED.value
119
+ elif kind == "Invalidated":
120
+ _require(frame_id, "frame_id", envelope)
121
+ record = next_state.setdefault(frame_id, {})
122
+ record["status"] = Status.INVALID.value
123
+ elif kind == "Withdrawn":
124
+ _require(frame_id, "frame_id", envelope)
125
+ record = next_state.setdefault(frame_id, {})
126
+ record["status"] = Status.WITHDRAWN.value
127
+ return next_state
128
+
129
+
130
+ class CertificateComponent:
131
+ name = "certificates"
132
+
133
+ def initial_state(self) -> dict[str, dict[str, Any]]:
134
+ return {}
135
+
136
+ def apply(self, state: dict[str, dict[str, Any]], envelope: Envelope) -> dict[str, dict[str, Any]]:
137
+ next_state = deepcopy(state)
138
+ payload = envelope.payload
139
+ kind = envelope.kind
140
+ if kind == "Issue":
141
+ cert_id = str(payload.get("cert_id", payload.get("object", "")))
142
+ _require(cert_id, "cert_id", envelope)
143
+ if cert_id in next_state and next_state[cert_id].get("issued"):
144
+ raise FoldError(f"certificate {cert_id} is issued twice")
145
+ next_state[cert_id] = {
146
+ "issued": True,
147
+ "issued_at": envelope.commit_time,
148
+ "issuer": payload.get("issuer", envelope.writer),
149
+ "family": payload.get("family", ""),
150
+ "subject": payload.get("subject", payload.get("object", "")),
151
+ "expires_at": payload.get("expires_at"),
152
+ "dependencies": list(payload.get("dependencies", ())),
153
+ "source_ids": list(payload.get("source_ids", ())),
154
+ "dependency_digest": payload.get("dependency_digest"),
155
+ "family_check": payload.get("family_check"),
156
+ "assumption": payload.get("assumption"),
157
+ "revoked_at": None,
158
+ "payload_eid": envelope.eid,
159
+ }
160
+ elif kind in {"Revoke", "CapRevoked"}:
161
+ cert_id = str(payload.get("cert_id", ""))
162
+ if cert_id:
163
+ record = next_state.get(cert_id)
164
+ if record is None:
165
+ raise FoldError(f"cannot revoke unknown certificate {cert_id}")
166
+ if record.get("revoked_at") is not None:
167
+ raise FoldError(f"certificate {cert_id} is revoked twice")
168
+ record["revoked_at"] = envelope.commit_time
169
+ return next_state
170
+
171
+
172
+ class CapabilityComponent:
173
+ name = "capabilities"
174
+
175
+ def initial_state(self) -> dict[str, dict[str, Any]]:
176
+ return {}
177
+
178
+ def apply(self, state: dict[str, dict[str, Any]], envelope: Envelope) -> dict[str, dict[str, Any]]:
179
+ next_state = deepcopy(state)
180
+ payload = envelope.payload
181
+ kind = envelope.kind
182
+ if kind in {"MintCap", "CapMinted"}:
183
+ cap_id = str(payload.get("capability_id", payload.get("cap_id", payload.get("object", ""))))
184
+ _require(cap_id, "capability_id", envelope)
185
+ if cap_id in next_state:
186
+ raise FoldError(f"capability {cap_id} is minted twice")
187
+ next_state[cap_id] = {
188
+ "status": "unused",
189
+ "frame_id": payload.get("frame_id"),
190
+ "action": payload.get("action"),
191
+ "source_digest": payload.get("source_digest"),
192
+ "minted_at": envelope.commit_time,
193
+ "expires_at": payload.get("expires_at"),
194
+ }
195
+ elif kind in {"UseCap", "CapUsed"}:
196
+ cap_id = str(payload.get("capability_id", payload.get("cap_id", "")))
197
+ record = _get(next_state, cap_id, "capability", envelope)
198
+ if record.get("status") != "unused":
199
+ raise FoldError(f"capability {cap_id} is not live")
200
+ record["status"] = "used"
201
+ record["outbox_id"] = payload.get("outbox_id")
202
+ record["used_at"] = envelope.commit_time
203
+ elif kind in {"RevokeCap", "CapRevoked"}:
204
+ cap_id = str(payload.get("capability_id", payload.get("cap_id", "")))
205
+ if cap_id:
206
+ record = _get(next_state, cap_id, "capability", envelope)
207
+ if record.get("status") == "used":
208
+ raise FoldError(f"capability {cap_id} is already used")
209
+ record["status"] = "revoked"
210
+ elif kind in {"ExpireCap", "CapExpired"}:
211
+ cap_id = str(payload.get("capability_id", payload.get("cap_id", "")))
212
+ record = _get(next_state, cap_id, "capability", envelope)
213
+ if record.get("status") == "used":
214
+ raise FoldError(f"capability {cap_id} is already used")
215
+ record["status"] = "expired"
216
+ return next_state
217
+
218
+
219
+ class ResourceComponent:
220
+ name = "resources"
221
+
222
+ def initial_state(self) -> dict[str, dict[str, Any]]:
223
+ return {}
224
+
225
+ def apply(self, state: dict[str, dict[str, Any]], envelope: Envelope) -> dict[str, dict[str, Any]]:
226
+ next_state = deepcopy(state)
227
+ payload = envelope.payload
228
+ kind = envelope.kind
229
+ if kind == "ReserveResource":
230
+ lease_id = str(payload.get("lease_id", payload.get("object", "")))
231
+ _require(lease_id, "lease_id", envelope)
232
+ if lease_id in next_state:
233
+ raise FoldError(f"resource lease {lease_id} is reserved twice")
234
+ next_state[lease_id] = {
235
+ "status": "leased",
236
+ "token_id": payload.get("token_id"),
237
+ "frame_id": payload.get("frame_id"),
238
+ "amount": payload.get("amount", 1),
239
+ "reserved_at": envelope.commit_time,
240
+ }
241
+ elif kind == "ConsumeResource":
242
+ lease_id = str(payload.get("lease_id", payload.get("object", "")))
243
+ record = _get(next_state, lease_id, "resource lease", envelope)
244
+ if record.get("status") != "leased":
245
+ raise FoldError(f"resource lease {lease_id} is not leased")
246
+ record["status"] = "consumed"
247
+ record["consumed_at"] = envelope.commit_time
248
+ record["consumer"] = payload.get("consumer")
249
+ elif kind == "ReleaseResource":
250
+ lease_id = str(payload.get("lease_id", payload.get("object", "")))
251
+ record = _get(next_state, lease_id, "resource lease", envelope)
252
+ if record.get("status") != "leased":
253
+ raise FoldError(f"resource lease {lease_id} is not leased")
254
+ record["status"] = "released"
255
+ return next_state
256
+
257
+
258
+ class OutboxComponent:
259
+ name = "outboxes"
260
+
261
+ def initial_state(self) -> dict[str, dict[str, Any]]:
262
+ return {}
263
+
264
+ def apply(self, state: dict[str, dict[str, Any]], envelope: Envelope) -> dict[str, dict[str, Any]]:
265
+ next_state = deepcopy(state)
266
+ payload = envelope.payload
267
+ kind = envelope.kind
268
+ outbox_id = str(payload.get("outbox_id", payload.get("object", "")))
269
+ if kind == "AuthorizeOutbox":
270
+ _require(outbox_id, "outbox_id", envelope)
271
+ if outbox_id in next_state:
272
+ raise FoldError(f"outbox {outbox_id} is authorized twice")
273
+ next_state[outbox_id] = {
274
+ "status": "authorized",
275
+ "frame_id": payload.get("frame_id"),
276
+ "action": payload.get("action"),
277
+ "authorized_at": envelope.commit_time,
278
+ }
279
+ elif kind == "OutboxClaim":
280
+ record = _get(next_state, outbox_id, "outbox", envelope)
281
+ if record.get("status") != "authorized":
282
+ raise FoldError(f"outbox {outbox_id} is not authorized")
283
+ record["status"] = "claimed"
284
+ record["gate_id"] = payload.get("gate_id")
285
+ record["claimed_at"] = envelope.commit_time
286
+ elif kind == "RevokeOutbox":
287
+ record = _get(next_state, outbox_id, "outbox", envelope)
288
+ if record.get("status") != "authorized":
289
+ raise FoldError(f"outbox {outbox_id} is not authorized")
290
+ record["status"] = "revoked"
291
+ elif kind in {
292
+ "DispatchStarted",
293
+ "ActuatorAccepted",
294
+ "ActuatorRejected",
295
+ "ReceiptCommitted",
296
+ "ReceiptMissing",
297
+ "ReceiptConflict",
298
+ }:
299
+ record = _get(next_state, outbox_id, "outbox", envelope)
300
+ transitions = {
301
+ "DispatchStarted": {"claimed"},
302
+ "ActuatorAccepted": {"dispatchStarted"},
303
+ "ActuatorRejected": {"dispatchStarted"},
304
+ "ReceiptCommitted": {"actuatorAccepted"},
305
+ "ReceiptMissing": {"actuatorAccepted"},
306
+ "ReceiptConflict": {"actuatorAccepted"},
307
+ }
308
+ if record.get("status") not in transitions[kind]:
309
+ raise FoldError(f"outbox {outbox_id} cannot transition to {kind}")
310
+ record["status"] = {
311
+ "DispatchStarted": "dispatchStarted",
312
+ "ActuatorAccepted": "actuatorAccepted",
313
+ "ActuatorRejected": "actuatorRejected",
314
+ "ReceiptCommitted": "receiptCommitted",
315
+ "ReceiptMissing": "receiptMissing",
316
+ "ReceiptConflict": "receiptConflict",
317
+ }[kind]
318
+ return next_state
319
+
320
+
321
+ class RiskComponent:
322
+ name = "risk"
323
+
324
+ def initial_state(self) -> dict[str, Any]:
325
+ return {"hypotheses": {}, "reserves": {}, "spends": {}}
326
+
327
+ def apply(self, state: dict[str, Any], envelope: Envelope) -> dict[str, Any]:
328
+ next_state = deepcopy(state)
329
+ payload = envelope.payload
330
+ kind = envelope.kind
331
+ if kind == "RiskReg":
332
+ hyp = str(payload.get("hypothesis_id", payload.get("hypothesis", payload.get("object", ""))))
333
+ _require(hyp, "hypothesis_id", envelope)
334
+ if hyp in next_state["hypotheses"]:
335
+ raise FoldError(f"hypothesis {hyp} is registered twice")
336
+ next_state["hypotheses"][hyp] = {
337
+ "family": payload.get("family"),
338
+ "registered_at": envelope.commit_time,
339
+ }
340
+ elif kind == "RiskReserve":
341
+ risk_id = str(payload.get("risk_id", payload.get("object", "")))
342
+ _require(risk_id, "risk_id", envelope)
343
+ if risk_id in next_state["reserves"]:
344
+ raise FoldError(f"risk id {risk_id} is reserved twice")
345
+ next_state["reserves"][risk_id] = {
346
+ "hypothesis_id": payload.get("hypothesis_id"),
347
+ "frame_id": payload.get("frame_id"),
348
+ "eta": _fraction_text(payload.get("eta", "0")),
349
+ "reserved_at": envelope.commit_time,
350
+ }
351
+ elif kind == "RiskSpend":
352
+ risk_id = str(payload.get("risk_id", payload.get("object", "")))
353
+ reserve = _get(next_state["reserves"], risk_id, "risk reserve", envelope)
354
+ if risk_id in next_state["spends"]:
355
+ raise FoldError(f"risk id {risk_id} is spent twice")
356
+ next_state["spends"][risk_id] = {
357
+ "hypothesis_id": payload.get("hypothesis_id", reserve.get("hypothesis_id")),
358
+ "frame_id": payload.get("frame_id", reserve.get("frame_id")),
359
+ "eta": _fraction_text(payload.get("eta", reserve.get("eta", "0"))),
360
+ "mode": payload.get("mode"),
361
+ "cert_id": payload.get("cert_id"),
362
+ "ledger_digest": payload.get("ledger_digest"),
363
+ "spent_at": envelope.commit_time,
364
+ "closed_at": None,
365
+ }
366
+ elif kind == "RiskClose":
367
+ risk_id = str(payload.get("risk_id", payload.get("object", "")))
368
+ spend = _get(next_state["spends"], risk_id, "risk spend", envelope)
369
+ if spend.get("closed_at") is not None:
370
+ raise FoldError(f"risk id {risk_id} is closed twice")
371
+ spend["closed_at"] = envelope.commit_time
372
+ return next_state
373
+
374
+
375
+ class EvidenceComponent:
376
+ name = "evidence"
377
+
378
+ def initial_state(self) -> dict[str, dict[str, Any]]:
379
+ return {}
380
+
381
+ def apply(self, state: dict[str, dict[str, Any]], envelope: Envelope) -> dict[str, dict[str, Any]]:
382
+ next_state = deepcopy(state)
383
+ payload = envelope.payload
384
+ kind = envelope.kind
385
+ if kind in {"Record", "Evidence", "Source"}:
386
+ evidence_id = str(payload.get("evidence_id", payload.get("source_id", payload.get("object", ""))))
387
+ _require(evidence_id, "evidence_id", envelope)
388
+ next_state[evidence_id] = {
389
+ "kind": kind,
390
+ "record_id": payload.get("record_id"),
391
+ "digest": payload.get("digest"),
392
+ "committed_at": envelope.commit_time,
393
+ "eid": envelope.eid,
394
+ }
395
+ return next_state
396
+
397
+
398
+ def default_components() -> tuple[StateComponent, ...]:
399
+ return (
400
+ FrameComponent(),
401
+ CertificateComponent(),
402
+ EvidenceComponent(),
403
+ CapabilityComponent(),
404
+ ResourceComponent(),
405
+ OutboxComponent(),
406
+ RiskComponent(),
407
+ )
408
+
409
+
410
+ def _require(value: str, field_name: str, envelope: Envelope) -> None:
411
+ if not value:
412
+ raise FoldError(f"{field_name} is required in envelope {envelope.eid}")
413
+
414
+
415
+ def _get(state: dict[str, Any], key: str, label: str, envelope: Envelope) -> dict[str, Any]:
416
+ if not key or key not in state:
417
+ raise FoldError(f"unknown {label} {key!r} in envelope {envelope.eid}")
418
+ record = state[key]
419
+ if not isinstance(record, dict):
420
+ raise FoldError(f"{label} {key!r} has invalid state")
421
+ return record
422
+
423
+
424
+ def _fraction_text(value: Any) -> str:
425
+ return str(Fraction(str(value)))
@@ -0,0 +1,155 @@
1
+ """Finite problem-frame formation checks."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from dataclasses import dataclass, field
7
+ from typing import Any
8
+
9
+ from .certificates import all_certificates_live
10
+ from .fold import FoldState
11
+ from .model import Frame, Horizon
12
+ from .result import CheckBuilder, CheckResult
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class FormationProof:
17
+ """Finite proof object for activating a bounded decision frame."""
18
+
19
+ frame_id: str
20
+ source_evidence: tuple[str, ...]
21
+ goal_witnesses: tuple[str, ...]
22
+ action_witnesses: tuple[str, ...]
23
+ acceptance_witnesses: tuple[str, ...]
24
+ risk_witnesses: tuple[str, ...] = ()
25
+ obligation_witnesses: tuple[str, ...] = ()
26
+ seed: str = "standard"
27
+ certificate_ids: tuple[str, ...] = ()
28
+ transcript_digest: str | None = None
29
+ metadata: Mapping[str, Any] = field(default_factory=dict)
30
+
31
+ def to_json(self) -> dict[str, Any]:
32
+ return {
33
+ "frame_id": self.frame_id,
34
+ "source_evidence": list(self.source_evidence),
35
+ "goal_witnesses": list(self.goal_witnesses),
36
+ "action_witnesses": list(self.action_witnesses),
37
+ "acceptance_witnesses": list(self.acceptance_witnesses),
38
+ "risk_witnesses": list(self.risk_witnesses),
39
+ "obligation_witnesses": list(self.obligation_witnesses),
40
+ "seed": self.seed,
41
+ "certificate_ids": list(self.certificate_ids),
42
+ "transcript_digest": self.transcript_digest,
43
+ "metadata": dict(self.metadata),
44
+ }
45
+
46
+
47
+ def check_formation(
48
+ state: FoldState, proof: FormationProof, *, at_time: int, horizon: Horizon | None = None
49
+ ) -> CheckResult:
50
+ """Check the semantic fields required before a frame carries authority."""
51
+
52
+ builder = CheckBuilder(
53
+ footprint={
54
+ "FoldKernel",
55
+ "ClauseKernel",
56
+ "IssuerAuthentication",
57
+ "RevocationOracle",
58
+ "ClockWatermark",
59
+ }
60
+ )
61
+ frames: dict[str, dict[str, Any]] = state.component("frames")
62
+ record = frames.get(proof.frame_id)
63
+ if record is None:
64
+ builder.error("frame-missing", "frame is not present in folded state", location=proof.frame_id)
65
+ return builder.result()
66
+
67
+ frame_data = record.get("frame")
68
+ if not isinstance(frame_data, Mapping):
69
+ builder.error(
70
+ "frame-definition-missing",
71
+ "frame definition payload is missing",
72
+ location=proof.frame_id,
73
+ )
74
+ return builder.result()
75
+ frame = Frame.from_payload(frame_data)
76
+
77
+ evidence = state.component("evidence")
78
+ _require_nonempty(proof.source_evidence, "formation-source", "source evidence is required", builder)
79
+ for evidence_id in proof.source_evidence:
80
+ if evidence_id not in evidence:
81
+ builder.error(
82
+ "evidence-missing",
83
+ "source evidence is absent from the folded state",
84
+ location=evidence_id,
85
+ )
86
+ for evidence_id in frame.evidence_ids:
87
+ if evidence_id not in proof.source_evidence:
88
+ builder.error(
89
+ "frame-evidence-unwitnessed",
90
+ "frame evidence id is not cited by proof",
91
+ location=evidence_id,
92
+ )
93
+
94
+ if not frame.goal.strip() or not proof.goal_witnesses:
95
+ builder.error("formation-goal", "frame goal must be finite and witnessed", location=proof.frame_id)
96
+ if not frame.actions or not proof.action_witnesses:
97
+ builder.error(
98
+ "formation-action",
99
+ "frame action set must be finite and witnessed",
100
+ location=proof.frame_id,
101
+ )
102
+ if not frame.acceptance or not proof.acceptance_witnesses:
103
+ builder.error(
104
+ "formation-acceptance",
105
+ "acceptance criteria must be finite and witnessed",
106
+ location=proof.frame_id,
107
+ )
108
+ for risk_id in frame.risk_ids:
109
+ if risk_id not in proof.risk_witnesses:
110
+ builder.error("formation-risk", "frame risk id is not witnessed", location=risk_id)
111
+ for obligation in frame.obligations:
112
+ if obligation not in proof.obligation_witnesses:
113
+ builder.error("formation-obligation", "frame obligation is not witnessed", location=obligation)
114
+
115
+ if proof.seed == "residue" and not (proof.risk_witnesses or proof.obligation_witnesses):
116
+ builder.error(
117
+ "formation-residue-route",
118
+ "residue seed requires either risk evidence or diagnostic obligations",
119
+ location=proof.frame_id,
120
+ )
121
+
122
+ return builder.result().merge(all_certificates_live(state, proof.certificate_ids, at_time, horizon=horizon))
123
+
124
+
125
+ def check_well_audited(state: FoldState) -> CheckResult:
126
+ """Built-in safety checks for the default components."""
127
+
128
+ builder = CheckBuilder(footprint={"ClauseKernel", "FoldKernel"})
129
+ for cap_id, cap in state.component("capabilities").items():
130
+ if cap.get("status") == "used" and not cap.get("outbox_id"):
131
+ builder.error(
132
+ "capability-use-without-outbox",
133
+ "used capability must cite an outbox",
134
+ location=cap_id,
135
+ )
136
+ for lease_id, lease in state.component("resources").items():
137
+ if lease.get("status") == "consumed" and lease.get("consumed_at") is None:
138
+ builder.error(
139
+ "resource-consume-time-missing",
140
+ "consumed resource must record a time",
141
+ location=lease_id,
142
+ )
143
+ for outbox_id, outbox in state.component("outboxes").items():
144
+ if outbox.get("status") in {
145
+ "claimed",
146
+ "dispatchStarted",
147
+ "actuatorAccepted",
148
+ } and not outbox.get("gate_id"):
149
+ builder.error("outbox-claim-without-gate", "claimed outbox must cite a gate", location=outbox_id)
150
+ return builder.result()
151
+
152
+
153
+ def _require_nonempty(values: tuple[str, ...], code: str, message: str, builder: CheckBuilder) -> None:
154
+ if not values:
155
+ builder.error(code, message)