feat(perception): add bounded binary stream ingress

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 12:21:25 +03:00
parent 85349f42f9
commit da60feff90
6 changed files with 1262 additions and 1 deletions
@@ -0,0 +1,312 @@
"""CPU-only, bounded IPC evidence on Worker; NOT a model/network qualification.
Recorded mode transfers original fMP4 init/media plus existing normalized
point/pose increments at original 1x release times. Receiver is never told the
source length. The consumer only hashes raw input, it does not decode/infer.
Truncated mode is explicitly synthetic and exercises multi-fragment failure.
"""
import argparse
import hashlib
import json
import resource
import socket
import struct
import subprocess
import sys
import threading
import time
from datetime import UTC, datetime
from pathlib import Path
from pilot_source import SensorArchive, camera_events, merged_events
from k1link.compute.live_perception import LiveIngressEvent
from k1link.perception import streaming_wire as wire
from k1link.perception.realtime_contract import StreamStart
from k1link.perception.streaming_ingress import StreamingIngress
from k1link.perception.streaming_lifecycle import StreamingLifecycle
from k1link.perception.streaming_queue import StreamMailbox
from k1link.perception.streaming_sender import StreamingSender
def record(event):
return {
**wire.event_metadata(event),
"payload_bytes": len(event.payload),
"payload_sha256": hashlib.sha256(event.payload).hexdigest(),
}
def emit_json(stream, value):
stream.write(json.dumps(value, sort_keys=True) + "\n")
stream.flush()
def bounded_file(path, maximum):
with path.open("rb") as stream:
raw = stream.read(maximum + 1)
if not 0 < len(raw) <= maximum:
raise ValueError("source member exceeds bound")
return raw
def recorded_events(root):
camera_root = Path("/camera")
camera_index = camera_root / "index.jsonl"
first = next(camera_events(camera_index, 1)).time_ns
zero = first - 500_000_000
wall = time.monotonic_ns() + 50_000_000
seq = 1
yield (
LiveIngressEvent(
seq,
"recorded-acquisition",
1,
"camera-init",
"sensor.camera.right",
0,
0,
zero,
bounded_file(camera_root / "init.mp4", wire.MAX_FRAGMENT),
),
wall,
)
archive = SensorArchive(Path("/sensor-source.npz"))
try:
for observation in merged_events(archive, camera_index, 32):
if observation.time_ns < zero:
continue
due = wall + observation.time_ns - zero
threading.Event().wait(max(0, (due - time.monotonic_ns()) / 1e9))
seq += 1
utc = 0 # The normalized sensor archive has no UTC evidence; do not invent it.
if observation.channel == "camera":
row = observation.value
path = (camera_root / row["path"]).resolve()
if not path.is_relative_to(camera_root):
raise ValueError("camera member escaped source root")
raw = bounded_file(path, wire.MAX_FRAGMENT)
if len(raw) != row["length"] or hashlib.sha256(raw).hexdigest() != row["sha256"]:
raise ValueError("camera chunk integrity failed")
modality, source_id, utc = (
"camera-frame",
"sensor.camera.right",
row["host_epoch_ns"],
)
elif observation.channel == "points":
xyz, intensity = observation.value
raw = struct.pack("<I", len(xyz)) + xyz.tobytes() + intensity.tobytes()
modality, source_id = "lidar", "normalized-map-point-increments"
else:
position, quaternion = observation.value
raw = position.tobytes() + quaternion.tobytes()
modality, source_id = "pose", "normalized-map-from-lidar-pose"
yield (
LiveIngressEvent(
seq,
"recorded-acquisition",
1,
modality,
source_id,
observation.sequence,
utc,
observation.time_ns,
raw,
),
due,
)
if observation.channel == "camera" and observation.sequence == 31:
break
finally:
(root / "source-reads.json").write_text(json.dumps(archive.counters(), indent=2))
archive.close()
def producer(args):
root = Path(args.output)
identity = StreamStart.from_dict(json.loads((root / "start.json").read_text()))
connection = socket.socket(fileno=args.fd)
if connection.recv(1) != b"R":
raise ValueError("runtime did not become ready")
with (root / "sent.jsonl").open("w") as journal:
if args.case == "recorded":
sender = StreamingSender(connection, identity, "recorded-acquisition", 1, lambda: None)
for event, due in recorded_events(root):
sent = time.monotonic_ns()
sender.send(event)
emit_json(
journal,
{
**record(event),
"due_monotonic_ns": str(due),
"send_start_monotonic_ns": str(sent),
"send_end_monotonic_ns": str(time.monotonic_ns()),
},
)
end_ns = time.monotonic_ns()
sender.end()
else:
connection.sendall(wire.open_packet(identity, "recorded-acquisition", 1))
event = LiveIngressEvent(
1,
"recorded-acquisition",
1,
"lidar",
"synthetic",
1,
0,
1,
b"x" * (wire.MAX_FRAGMENT + 17),
)
header, payload = next(wire.event_packets(identity, event))
connection.sendall(header)
connection.sendall(payload)
emit_json(journal, record(event))
end_ns = time.monotonic_ns()
connection.close() # Deliberate EOF between fragments; no End.
(root / "source-end.json").write_text(json.dumps({"end_monotonic_ns": str(end_ns)}))
# The supervised source child remains alive until owned-group cleanup.
# Its normal completion is not mistaken for an unexpected model death.
threading.Event().wait(30)
def run_case(base, case, generation):
root = base / case
root.mkdir()
specification = {
"case": case,
"transport": wire.SCHEMA,
"consumer": "raw-digest-only",
"camera": "original-fmp4-init-and-media",
"points": "u32le-count+xyz-f64le+intensity-u8",
"pose": "position-f64le3+map-from-lidar-quaternion-f64le4",
"fragment_timeout_ms": 250,
"idle_timeout_ms": 2000,
}
identity = StreamStart(
run_id=f"binary-ingress-{case}",
source_id="RAVNOVES00-prefix" if case == "recorded" else "synthetic",
worker_id="worker-006",
epoch_id=f"ipc-{generation}",
lease_generation=generation,
profile_sha256=hashlib.sha256(
bounded_file(base / "candidate-profile.json", 65536)
).hexdigest(),
image_sha256="664824aa25de1db178f177d67a81b01541a938b479812b9383ddbf03f6b59dbe",
effective_config_sha256=hashlib.sha256(wire.canonical(specification)).hexdigest(),
# Opaque passthrough doesn't resolve or use calibration. Explicit synthetic
# identity is NOT eligible for a real perception scene.
calibration_sha256=hashlib.sha256(b"opaque-transport-no-calibration-use").hexdigest(),
clock_domain_id="original-host-arrival-clock",
input_mode="recorded-source-paced",
)
(root / "start.json").write_text(json.dumps(identity.to_dict(), indent=2))
run = StreamingLifecycle(
identity, Path("/tmp/worker-lease"), StreamMailbox(), threading.Event()
)
heartbeat_stop = threading.Event()
def renew():
while not heartbeat_stop.wait(0.25):
run.renew(identity)
heartbeat = threading.Thread(target=renew, daemon=True)
heartbeat.start()
left, right = socket.socketpair()
receiver = None
started = time.monotonic_ns()
with (root / "producer.log").open("wb") as log, (root / "received.jsonl").open("w") as journal:
try:
run.spawn(
lambda: subprocess.Popen(
[
sys.executable,
"-B",
__file__,
"--producer",
"--case",
case,
"--fd",
str(left.fileno()),
"--output",
str(root),
],
pass_fds=(left.fileno(),),
start_new_session=True,
stdin=subprocess.DEVNULL,
stdout=log,
stderr=log,
)
)
left.close()
def consume(event):
emit_json(
journal,
{
**record(event),
"received_monotonic_ns": str(time.monotonic_ns()),
"original_received_monotonic_ns": str(event.received_monotonic_ns),
},
)
receiver = StreamingIngress(
right,
run,
"recorded-acquisition",
1,
consume,
lambda notice: emit_json(journal, {"notice": notice}),
)
run.ready()
right.sendall(b"R")
receiver.start()
if not receiver.join(timeout=15):
raise TimeoutError("bounded stream probe did not finish")
finally:
run.request_stop("completed" if receiver and receiver.terminal == "end" else "failed")
run.stop_children()
left.close()
right.close()
if receiver:
receiver.join()
heartbeat_stop.set()
heartbeat.join(timeout=1)
released = run.close()
result = {
"created_utc": datetime.now(UTC).isoformat(),
"started_monotonic_ns": str(started),
"finished_monotonic_ns": str(time.monotonic_ns()),
"specification": specification,
"receiver": receiver.snapshot(),
"lifecycle": run.snapshot(),
"released": released,
"peak_input_bytes": run.mailbox.peak_bytes,
"residual_input_bytes": run.mailbox.bytes,
"maximum_rss_kib": resource.getrusage(resource.RUSAGE_SELF).ru_maxrss,
"child_maximum_rss_kib": resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss,
"cgroup_memory_peak": Path("/sys/fs/cgroup/memory.peak").read_text().strip(),
"model_runs": 0,
"network_qualified": False,
"actuation_allowed": False,
}
(root / "report.json").write_text(json.dumps(result, indent=2))
assert released and run.mailbox.bytes == 0
assert receiver.terminal == ("end" if case == "recorded" else "failed")
assert receiver.snapshot()["incomplete_observations"] == (0 if case == "recorded" else 1)
print(json.dumps(result), flush=True)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--producer", action="store_true")
parser.add_argument("--fd", type=int)
parser.add_argument("--case", choices=("recorded", "truncated"))
parser.add_argument("--output", default="/out")
args = parser.parse_args()
if args.producer:
producer(args)
else:
for generation, case in enumerate(("recorded", "truncated"), 1):
run_case(Path(args.output), case, generation)