You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First post-2.7.9 export to RATCHET (per #4) shows that 14 of 89 traces are dual-emitted at both detailed and generic tiers — same trace_id, same signing_key_id, but the generic copies systematically drop agent identity. Spec §3.1 says this shouldn't happen.
0/14 populated (entry_hash + sequence_number ARE populated)
Critical observation: the 265 generic-tier rows are signed by signing_key_id="agent-ee2271f272d2" — the same key as detailed-tier agent ee2271f272d21fff. Spec §3.1 says agent_id_hash MUST be sha256(public_key_bytes)[..16] of the signing key. Same key implies same hash. Reality: the same key produces agent_id_hash="ee2271f272d21fff" on 309 detailed-tier rows and agent_id_hash="unknown" on 265 generic-tier rows.
Pattern is byte-equivalent in structure: the 14 dual-emitted traces each have 21-row detailed copies and 21-row generic copies with identical event_type distributions (THOUGHT_START, SNAPSHOT_AND_CONTEXT, LLM_CALL×N, DMA_RESULTS, IDMA_RESULT, ASPDMA_RESULT×N, CONSCIENCE_RESULT, ACTION_RESULT).
agent_id_hash appears at BOTH the CompleteTrace envelope level (§3) AND on every TraceComponent (§4). The two values MUST be equal — agents emit them locked at build time; persistence MAY reject mismatches as malformed.
§3, agent_id_hash definition:
First 16 hex characters (8 bytes) of sha256(public_key_bytes), lowercase. Canonical derivation: hashlib.sha256(public_key_bytes).hexdigest()[:16] over the agent's Ed25519 signing key bytes. ... implementations MUST use exactly this derivation so the values are interchangeable across consumers.
"unknown" is not a valid output of sha256(public_key_bytes).hexdigest()[:16]. The generic-tier path is bypassing the canonical derivation.
Audit-signature gap is a corollary
Of 103 ACTION_RESULT rows, 89 have full audit anchor (audit_entry_hash, audit_sequence_number, audit_signature all populated) and 14 have a partial anchor (entry_hash + sequence_number populated, signature null). The 14 partial-anchor rows are exactly the 14 generic-tier ACTION_RESULT rows. So generic-tier emission also drops the audit-chain signature, leaving the chain entries unverifiable.
Same root cause: whatever the generic-tier emission path is doing, it's not running the same identity-derivation + signing logic as the detailed path.
Possible root causes
Privacy-by-tier intent (undocumented): generic tier deliberately strips agent identity for privacy. If so, spec §3.1 needs an exception clause. But this contradicts the "MUST be equal" clause and breaks N_eff measurement at generic tier.
Generic-tier emission path bug: the lens-side or persist-side path that emits the generic-tier copy doesn't propagate the agent's agent_id_hash from the envelope, defaulting to "unknown". Same path doesn't sign the audit anchor.
Schema-version mismatch: the generic-tier copy may have been emitted at schema_version="2.7.0" (envelope-only agent_id_hash) and the export query coerced it to "2.7.9". But export filter is schema_version='2.7.9', so this shouldn't slip through.
Why this matters for RATCHET
265 of 1,901 rows (13.9%) are unusable for per-agent or N_eff analysis — they have no resolvable agent identity.
14 of 89 traces (16%) have weakened audit-chain integrity at the seal event.
The 14 dual-emitted traces represent the same thoughts as the detailed-tier copies; deduplicating them at analysis time leaves only the detailed copy. Functional workaround for RATCHET, but doubles the storage cost in the corpus.
What this repo needs to do
Document the intent: is generic-tier supposed to strip agent identity? If yes, this is a spec issue (§3.1 needs exception clause + audit-anchor handling for generic). If no, this is a code bug.
If bug: trace the generic-tier emission path — likely on the lens or persist side, since the agent's signing key is the same one used for detailed-tier emission.
If intent: open a CIRISAgent spec PR to add the generic-tier exception, and clarify how N_eff measurement is supposed to work without per-agent attribution at that tier.
Non-blocking for RATCHET
Detailed-tier subset (1,636 rows, 9 agents, 75 detailed-only traces + 14 dual-emitted) is sufficient for Layer 1/2 federation analysis. Filing so the convergence happens before quarterly cadence settles.
References
Spec being violated: CIRISAgent/FSD/TRACE_WIRE_FORMAT.md @ v2.7.9-stable §3 + §3.1
Spec lock-in commit: CIRISAgent 4c28910d8 ("denormalize agent_id_hash onto every TraceComponent for 2.7.9")
Persist threat model AV-9 (cross-agent dedup-key collision): closure depends on agent_id_hash being correctly populated; "unknown" agent_id_hash creates a single-tenant collision space at generic tier
Context
First post-2.7.9 export to RATCHET (per #4) shows that 14 of 89 traces are dual-emitted at both
detailedandgenerictiers — sametrace_id, samesigning_key_id, but the generic copies systematically drop agent identity. Spec §3.1 says this shouldn't happen.Export:
release_v2/data/lens_export_v2_fixed_2026-05-03T04-00-04Z/Rows examined: 1,901 trace_events
Finding
agent_id_hashagent_namedetailedgeneric"unknown"on 100%nullon 100%Critical observation: the 265 generic-tier rows are signed by
signing_key_id="agent-ee2271f272d2"— the same key as detailed-tier agentee2271f272d21fff. Spec §3.1 says agent_id_hash MUST besha256(public_key_bytes)[..16]of the signing key. Same key implies same hash. Reality: the same key producesagent_id_hash="ee2271f272d21fff"on 309 detailed-tier rows andagent_id_hash="unknown"on 265 generic-tier rows.Pattern is byte-equivalent in structure: the 14 dual-emitted traces each have 21-row detailed copies and 21-row generic copies with identical
event_typedistributions (THOUGHT_START,SNAPSHOT_AND_CONTEXT,LLM_CALL×N,DMA_RESULTS,IDMA_RESULT,ASPDMA_RESULT×N,CONSCIENCE_RESULT,ACTION_RESULT).Spec text being violated
CIRISAgent/FSD/TRACE_WIRE_FORMAT.md @ v2.7.9-stable§3.1:§3,
agent_id_hashdefinition:"unknown"is not a valid output ofsha256(public_key_bytes).hexdigest()[:16]. The generic-tier path is bypassing the canonical derivation.Audit-signature gap is a corollary
Of 103 ACTION_RESULT rows, 89 have full audit anchor (
audit_entry_hash,audit_sequence_number,audit_signatureall populated) and 14 have a partial anchor (entry_hash + sequence_number populated, signature null). The 14 partial-anchor rows are exactly the 14 generic-tier ACTION_RESULT rows. So generic-tier emission also drops the audit-chain signature, leaving the chain entries unverifiable.Same root cause: whatever the generic-tier emission path is doing, it's not running the same identity-derivation + signing logic as the detailed path.
Possible root causes
agent_id_hashfrom the envelope, defaulting to"unknown". Same path doesn't sign the audit anchor.schema_version="2.7.0"(envelope-only agent_id_hash) and the export query coerced it to"2.7.9". But export filter isschema_version='2.7.9', so this shouldn't slip through.Why this matters for RATCHET
What this repo needs to do
Non-blocking for RATCHET
Detailed-tier subset (1,636 rows, 9 agents, 75 detailed-only traces + 14 dual-emitted) is sufficient for Layer 1/2 federation analysis. Filing so the convergence happens before quarterly cadence settles.
References
CIRISAgent/FSD/TRACE_WIRE_FORMAT.md @ v2.7.9-stable§3 + §3.1CIRISLens/docs/THREAT_MODEL.md§1