feat(perception): enforce six-layer freshness through receipt

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 10:14:28 +03:00
parent 4e633a662c
commit 097e450a87
9 changed files with 1067 additions and 43 deletions
@@ -0,0 +1,139 @@
"""Pilot adapter for the shared six-layer ABI; source arrival clock, local receipt.
Not a live clock synchronizer or lease authority. Domain history/unknown motion
stays in existing payloads. An unavailable layer may retain diagnostic fields in
the scene, but makes no valid payload/terrain-permission claim in the ABI.
"""
import hashlib
import json
from k1link.perception.realtime_contract import LayerEvidence
from k1link.perception.realtime_scene import DEPENDENCIES, SceneFreshness, derive_layer
CLOCK_DOMAIN = "pilot-original-host-arrival"
def payload_digest(scene, layer):
if layer == "segmentation":
return scene["segmentation_sha256"]
fields = {
"objects": ("proposals",),
"geometry": ("observations", "surface_state", "range_estimator"),
"motion": ("tracks", "threats"),
"costmap": ("costmap_states", "costmap_material"),
"policy": ("policy_actions", "policy_counts"),
}[layer]
value = {key: scene[key] for key in fields}
return hashlib.sha256(
json.dumps(value, sort_keys=True, allow_nan=False, separators=(",", ":")).encode()
).hexdigest()
def build_freshness(scene, bundle, ddr_layer, epoch_id):
stamp, sequence = bundle["time_ns"], bundle["sequence"]
segmentation = LayerEvidence(
"segmentation",
epoch_id,
ddr_layer["source_sequence"],
ddr_layer["source_host_monotonic_ns"],
"current" if ddr_layer["state"] == "current" else "held",
payload_digest(scene, "segmentation"),
ddr_layer["source_host_monotonic_ns"],
)
objects = LayerEvidence(
"objects", epoch_id, sequence, stamp, "current", payload_digest(scene, "objects"), stamp
)
layers = {"segmentation": segmentation, "objects": objects}
for name in ("geometry", "motion", "costmap", "policy"):
oldest = stamp
if name == "geometry":
if not bundle["available"] or scene["surface_state"] != "valid":
layers[name] = LayerEvidence(name, epoch_id, None, None, "unavailable", None)
continue
lineage = bundle["lineage"]
oldest = min(
lineage["pose_host_monotonic_ns"],
*(item["host_monotonic_ns"] for item in lineage["point_increments"]),
)
if name == "costmap" and bundle["available"]:
# A rolling window can retain old occupied/unknown cells to prohibit
# terrain. Permissive cells must keep their own observation age.
oldest = scene["tgs_counts"]["oldest_permissive_cell_source_ns"]
layers[name] = derive_layer(
name,
epoch_id=epoch_id,
source_sequence=sequence,
source_time_ns=stamp,
payload_sha256=payload_digest(scene, name),
inputs=tuple(layers[key] for key in DEPENDENCIES[name]),
oldest_required_input_time_ns=oldest,
)
return SceneFreshness(epoch_id, CLOCK_DOMAIN, sequence, stamp, tuple(layers.values()))
def assess(freshness, *, bundle, now_ns):
# Both sides of this pilot use the SAME monotonic clock. Map it back to
# original source arrival time; zero mapping uncertainty is local-only and
# is not a claim of hardware camera/LiDAR synchronization or network quality.
return freshness.assess(
epoch_id=freshness.epoch_id,
clock_domain_id=CLOCK_DOMAIN,
observed_source_time_ns=bundle["time_ns"] + now_ns - bundle["due_ns"],
clock_uncertainty_ms=0,
maximum_clock_uncertainty_ms=5,
maximum_layer_age_ms=250,
)
def suppress_policy(scene):
scene["policy_actions"] = [2] * len(scene["policy_actions"])
scene["policy_counts"] = {
"ALLOW_candidate": 0,
"HIGH_COST": 0,
"NO_GO": len(scene["policy_actions"]),
}
def prepare_publication(scene, bundle, ddr_layer, *, epoch_id, now_ns):
freshness = build_freshness(scene, bundle, ddr_layer, epoch_id)
checked = assess(freshness, bundle=bundle, now_ns=now_ns)
if not checked.fresh_complete:
suppress_policy(scene)
# The envelope hashes the actual guarded policy, not the discarded one.
freshness = build_freshness(scene, bundle, ddr_layer, epoch_id)
checked = assess(freshness, bundle=bundle, now_ns=now_ns)
scene["freshness"] = freshness.to_dict()
scene["freshness_at_publication"] = checked.to_dict()
scene["stale_at_publication"] = any(item.state == "stale" for item in checked.layers)
scene["oldest_required_input_age_ms"] = max(
(age for age in checked.age_upper_bound_ms if age is not None), default=None
)
def validate_receipt(scene, bundle, *, epoch_id):
freshness = SceneFreshness.from_dict(scene["freshness"])
if (
freshness.epoch_id,
freshness.clock_domain_id,
freshness.source_sequence,
freshness.source_time_ns,
) != (epoch_id, CLOCK_DOMAIN, bundle["sequence"], bundle["time_ns"]):
raise ValueError("collector freshness identity mismatch")
if scene["commands_enabled"] is not False or scene["actuation_allowed"] is not False:
raise ValueError("pilot result attempted control authority")
for item in freshness.layers:
if (
item.payload_sha256 is not None
and payload_digest(scene, item.layer) != item.payload_sha256
):
raise ValueError("collector layer payload digest mismatch")
return freshness
def receipt_view(scene, checked):
"""A consumer view; never mutate the hashed published evidence."""
view = dict(scene)
if not checked.fresh_complete:
suppress_policy(view)
return view
@@ -444,7 +444,7 @@ class JointGraph:
for index in diagnostic_cells:
matching = np.flatnonzero(good & (cell_ids == index))
diagnostics[str(index)] = {
"votes": dict(zip(self.material_names, votes[index].tolist())),
"votes": dict(zip(self.material_names, votes[index].tolist(), strict=True)),
"projected_ground_points": len(matching),
"points_truncated": len(matching) > 128,
"points": [
@@ -467,6 +467,12 @@ class JointGraph:
if index is not None:
cells[index] = 2
actions = self.action_lut[material, cells]
permissive_stamps = last_seen[actions != 2]
if np.any(permissive_stamps < 0):
raise ValueError("permissive TGS cell lacks source observation")
oldest_permissive = (
int(permissive_stamps.min()) if len(permissive_stamps) else bundle["time_ns"]
)
return (
cells,
actions,
@@ -478,6 +484,7 @@ class JointGraph:
"occupied": int(np.count_nonzero(states == 2)),
"rejected": int(np.count_nonzero(states == 3)),
"stale_cells": int(np.count_nonzero(stale)),
"oldest_permissive_cell_source_ns": oldest_permissive,
"state_counts": dict(Counter(int(x) for x in cells)),
**({"diagnostic_cells": diagnostics} if diagnostics else {}),
},
@@ -24,6 +24,7 @@ from datetime import UTC, datetime
from pathlib import Path
import numpy as np
from pilot_freshness import assess, prepare_publication, receipt_view, validate_receipt
from pilot_ipc import receive, send
from pilot_queue import Mailbox
from pilot_scheduler import GpuStage
@@ -482,44 +483,11 @@ def run(args):
proposals=proposals,
detector_ms=(gpu_done - ddr_done) / 1e6,
)
# Late evidence remains inspectable but cannot authorize terrain.
policy_age_ms = (time.monotonic_ns() - bundle["due_ns"]) / 1e6
sensor_source_age_ms = max(
bundle["lineage"]["pose_age_ms"] or 0,
bundle["lineage"]["oldest_point_age_ms"] or 0,
freshness_started = time.monotonic_ns()
prepare_publication(
scene, bundle, ddr_layer, epoch_id=args.run_id,
now_ns=freshness_started,
)
scene["layer_freshness"] = {
"segmentation": {
**ddr_layer,
"age_at_policy_ms": policy_age_ms + ddr_layer["source_age_ms"],
},
"detection": {
"state": "current",
"source_sequence": bundle["sequence"],
"source_host_monotonic_ns": bundle["time_ns"],
"source_age_ms": 0.0,
"age_at_policy_ms": policy_age_ms,
},
"geometry": {
"state": "current" if bundle["available"] else "unavailable",
"source_sequence": bundle["sequence"],
"source_host_monotonic_ns": bundle["time_ns"],
"source_age_ms": sensor_source_age_ms,
"age_at_policy_ms": policy_age_ms + sensor_source_age_ms,
},
}
scene["oldest_required_input_age_ms"] = policy_age_ms + max(
sensor_source_age_ms,
ddr_layer["source_age_ms"],
)
scene["stale_at_publication"] = scene["oldest_required_input_age_ms"] > 250
if scene["stale_at_publication"]:
scene["policy_actions"] = [2] * len(scene["policy_actions"])
scene["policy_counts"] = {
"ALLOW_candidate": 0,
"HIGH_COST": 0,
"NO_GO": len(scene["policy_actions"]),
}
scene.update(
sequence=bundle["sequence"],
lineage=bundle["lineage"],
@@ -534,6 +502,10 @@ def run(args):
received = json.loads(encoded)
if received["sequence"] != bundle["sequence"]:
raise ValueError("collector identity mismatch")
freshness = validate_receipt(received, bundle, epoch_id=args.run_id)
checked_at = time.monotonic_ns()
checked = assess(freshness, bundle=bundle, now_ns=checked_at)
view = receipt_view(received, checked)
finished = time.monotonic_ns()
timing = {
**scene["timing_ms"],
@@ -549,6 +521,7 @@ def run(args):
"cpu_tail_to_receiver_ms": (finished - cpu_started) / 1e6,
"compute_to_receiver_ms": (finished - begin) / 1e6,
"source_due_to_receiver_ms": (finished - bundle["due_ns"]) / 1e6,
"freshness_encode_receive_ms": (finished - freshness_started) / 1e6,
}
result = {
"sequence": bundle["sequence"],
@@ -565,7 +538,9 @@ def run(args):
x["metric_geometry"] is not None for x in scene["observations"]
),
"tgs_counts": scene["tgs_counts"],
"policy_counts": scene["policy_counts"],
"policy_counts": view["policy_counts"],
"freshness_at_receipt": checked.to_dict(),
"policy_counts_at_publication": scene["policy_counts"],
"scene_bytes": len(encoded),
"scene_sha256": hashlib.sha256(encoded).hexdigest(),
}
@@ -711,8 +686,8 @@ def run(args):
and max(s.get("cgroup_memory_mib", 99999) for s in samples) <= 8192,
"all_modalities_fresh": len(results) == args.frames
and all(r["available"] for r in results),
"layer_source_age_250ms": bool(results)
and all(r["ddrnet_source_age_ms"] <= 250 for r in results),
"all_six_layers_fresh_at_receipt": bool(results)
and all(r["freshness_at_receipt"]["fresh_complete"] for r in results),
"network_end_to_end_qualified": False,
}
report["profile_realtime_qualified"] = False