R2: run manifest / provenance writer for reproducible, auditable runs
write_manifest() freezes at circuit-experiment start everything needed to
reproduce and audit a SOR run and writes an immutable
output/sor-runs/<ts>/manifest.json: the R1 --sor-seed, topology/selector/churn
schedule id, one persona fingerprint per participating node, worktree git SHA,
isolated engine kind + image digest, pip/cargo dependency freeze, and
start/stop timestamps. The events.jsonl SHA-256 field is reserved for R3.
Provenance only: no forwarder, no engine spawned. Defense-in-depth to keep
containment load-bearing, the schema refuses to record a non-isolated
("local") engine at run or node level; the binding assertion still lands with
the R4 forwarder.
- cmd_chat/sor/provenance.py: Node/RunManifest, node_fingerprint (bit-for-bit
mirror of persona.rs::fingerprint_of), git/deps capture, explicit
dependency-free schema validator.
- hh/src/persona.rs: fingerprint_of known-vector parity test.
- tests: R2 acceptance predicate (manifest present + schema-valid, non-empty
seed, >=1 fingerprint/node), immutability, containment rejection of local
engines, and cross-language fingerprint parity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -155,4 +155,14 @@ mod tests {
|
||||
assert_eq!(fp.len(), 8, "4 bytes → 8 hex chars");
|
||||
assert_eq!(Some(fp), fingerprint_of(&p.pub_b64()));
|
||||
}
|
||||
|
||||
// Cross-language parity anchor for the R2 manifest writer: the same known
|
||||
// pubkey (raw bytes 0..32) maps to this fingerprint in
|
||||
// cmd_chat/sor/provenance.py (tests/test_sor_provenance.py). If either side
|
||||
// changes the fingerprint formula, one of the two tests fails.
|
||||
#[test]
|
||||
fn fingerprint_of_known_vector() {
|
||||
let pub_b64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=";
|
||||
assert_eq!(fingerprint_of(pub_b64).as_deref(), Some("630dcd29"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user