build(agent): jabba#56a767 iteration

This commit is contained in:
agent-56a7678c6cd71659 2026-04-29 08:10:51 +02:00
parent 669f46bb55
commit 13d435d3b1
3 changed files with 15 additions and 0 deletions

View File

@ -67,6 +67,16 @@ def _merkle_root(items: list[str]) -> str:
return level[0]
def _fingerprint(spec: AttractorSpec, gain: tuple[float, ...], controller_hash: str) -> str:
"""Deterministic fingerprint for quick admission/indexing.
Combines a few stable, low-entropy fields and hashes them. This is
intentionally small and deterministic so it can be exchanged over DTN.
"""
payload = _json({"spec_id": spec.spec_id, "kind": spec.kind, "gain_len": len(gain), "ctrl": controller_hash})
return _hash_text(payload)
class AttractorCompiler:
def compile(self, spec: AttractorSpec) -> CompilationResult:
spec = spec.normalized()
@ -80,6 +90,7 @@ class AttractorCompiler:
estimated_basin_radius=spec.basin_radius,
convergence_rate_bound=spec.convergence_rate,
controller_hash=_hash_text(_json({"gain": gain, "target": spec.target_state, "kind": spec.kind})),
attractor_fingerprint=_fingerprint(spec, gain, _hash_text(_json({"gain": gain, "target": spec.target_state, "kind": spec.kind}))),
dt=spec.dt,
)
return CompilationResult(controller=controller, plan_cert=plan_cert, plan_delta=plan_delta, basin_sketch=basin_sketch)

View File

@ -65,6 +65,7 @@ class BasinSketch:
estimated_basin_radius: float
convergence_rate_bound: float
controller_hash: str
attractor_fingerprint: str
dt: float

View File

@ -23,6 +23,9 @@ def test_motion_template_compiles_and_replays() -> None:
assert replay.matched
assert result.plan_cert.spec_id == spec.spec_id
assert result.basin_sketch.controller_hash
# fingerprint should be a deterministic hex sha256 (64 chars)
assert isinstance(result.basin_sketch.attractor_fingerprint, str)
assert len(result.basin_sketch.attractor_fingerprint) == 64
assert abs(replay.final_state[0]) < 0.8
assert abs(replay.final_state[1]) < 0.8