What is broken
The reference Guardian's SessionContext hash construction does not match the normative hashing algorithm specified in Instrument Specification §8.2. It uses a custom JSON.stringify([...]) construction instead of the required RFC 8785 JCS construction with the specified predecessor bytes.
Where
reference-implementations/agt/packages/guardian/src/session-context.ts
What the specification says, and what happens instead
What the specification requires
Instrument Specification §8.2 defines the SessionContext chain hashing algorithm as:
entry_hash = lowercase-hex(SHA-256(content_bytes || prev_hash_bytes))
The specification requires:
content_bytes is the UTF-8 encoding of the RFC 8785 (JCS) canonicalization of the ContextEntry object with entry_hash and previous_hash removed.
prev_hash_bytes is the raw 32-byte decoding of previous_hash.
- For the first entry,
prev_hash_bytes is the empty byte string.
- The resulting bytes are SHA-256 hashed and represented as lowercase hexadecimal.
- Section §8.2 explicitly states that alternative canonicalization schemes are not permitted in v0.1.
The specification also states in §8.1 that the storage representation is implementation-defined, but that the canonical form used for hashing is constrained by the specification.
What the reference Guardian does instead
The reference Guardian's hashEntry() implementation in:
reference-implementations/agt/packages/guardian/src/session-context.ts
currently constructs the hash input using:
JSON.stringify([
input.prev_hash,
input.session_id,
input.seq,
input.recorded_at,
input.method,
input.request_id,
input.tool_name,
])
and then applies SHA-256.
The implementation also defines the first-entry predecessor as:
export const GENESIS_HASH = "0".repeat(64);
Therefore, the first entry incorporates a 64-character ASCII string containing zeroes rather than the empty prev_hash_bytes required by §8.2.
This is also not RFC 8785 JCS canonicalization of the ContextEntry object. It is a positional JSON array constructed from the implementation's internal SessionContext fields.
Live reproduction
A live reference Guardian run produced the following first SessionContext entry:
{
"session_id": "44444444-4444-4444-8444-444444444444",
"seq": 1,
"prev_hash": "0000000000000000000000000000000000000000000000000000000000000000",
"recorded_at": "2026-09-15T05:22:00.516Z",
"method": "steps/toolCallRequest",
"request_id": "33333333-3333-4333-8333-333333333333",
"tool_name": "Bash",
"hash": "dca6559ef53ce9ca189fa4c37122e8af4e4877d10df8645a68f148fc9ae97914"
}
Recomputing the hash using the reference Guardian's current hashEntry() algorithm, including the JSON.stringify([...]) construction and the 64 ASCII-zero prev_hash value, reproduces the recorded hash exactly:
dca6559ef53ce9ca189fa4c37122e8af4e4877d10df8645a68f148fc9ae97914
This confirms that the recorded SessionContext chain is being generated using the implementation's current custom construction.
However, that construction is different from the normative §8.2 construction.
Additional evidence
The existing SessionContext tests codify the current internal hash / prev_hash chain behavior. In particular, they assert that:
the first entry's prev_hash equals GENESIS_HASH;
subsequent entries use the previous entry's hash as prev_hash;
hashes are persisted using the internal hash / prev_hash representation.
This indicates that the observed behavior is part of the current reference implementation and is not merely an isolated malformed log entry.
Impact on implementers
A conformant implementation or verification tool following §8.2 cannot independently reproduce the reference Guardian's recorded SessionContext hashes from the log using the normative construction.
As a result, the reference Guardian's SessionContext chain is not interoperable with conformant chain-verification tooling. Independent implementations following §8.2 will derive different hashes from the same logical ContextEntry content, preventing reliable cross-implementation chain verification and audit comparison.
Because SessionContext hashing is intended to provide a portable chain commitment, this difference affects interoperability rather than only internal storage.
Current Priority Scope
Feeds the runnable Guardian reference implementation
What is broken
The reference Guardian's SessionContext hash construction does not match the normative hashing algorithm specified in Instrument Specification §8.2. It uses a custom JSON.stringify([...]) construction instead of the required RFC 8785 JCS construction with the specified predecessor bytes.
Where
reference-implementations/agt/packages/guardian/src/session-context.ts
What the specification says, and what happens instead
What the specification requires
Instrument Specification §8.2 defines the SessionContext chain hashing algorithm as:
entry_hash = lowercase-hex(SHA-256(content_bytes || prev_hash_bytes))The specification requires:
content_bytesis the UTF-8 encoding of the RFC 8785 (JCS) canonicalization of the ContextEntry object withentry_hashandprevious_hashremoved.prev_hash_bytesis the raw 32-byte decoding ofprevious_hash.prev_hash_bytesis the empty byte string.The specification also states in §8.1 that the storage representation is implementation-defined, but that the canonical form used for hashing is constrained by the specification.
What the reference Guardian does instead
The reference Guardian's
hashEntry()implementation in:reference-implementations/agt/packages/guardian/src/session-context.tscurrently constructs the hash input using:
and then applies SHA-256.
The implementation also defines the first-entry predecessor as:
export const GENESIS_HASH = "0".repeat(64);Therefore, the first entry incorporates a 64-character ASCII string containing zeroes rather than the empty prev_hash_bytes required by §8.2.
This is also not RFC 8785 JCS canonicalization of the ContextEntry object. It is a positional JSON array constructed from the implementation's internal SessionContext fields.
Live reproduction
A live reference Guardian run produced the following first SessionContext entry:
{ "session_id": "44444444-4444-4444-8444-444444444444", "seq": 1, "prev_hash": "0000000000000000000000000000000000000000000000000000000000000000", "recorded_at": "2026-09-15T05:22:00.516Z", "method": "steps/toolCallRequest", "request_id": "33333333-3333-4333-8333-333333333333", "tool_name": "Bash", "hash": "dca6559ef53ce9ca189fa4c37122e8af4e4877d10df8645a68f148fc9ae97914" }Recomputing the hash using the reference Guardian's current
hashEntry()algorithm, including theJSON.stringify([...])construction and the 64 ASCII-zeroprev_hashvalue, reproduces the recorded hash exactly:dca6559ef53ce9ca189fa4c37122e8af4e4877d10df8645a68f148fc9ae97914This confirms that the recorded SessionContext chain is being generated using the implementation's current custom construction.
However, that construction is different from the normative §8.2 construction.
Additional evidence
The existing SessionContext tests codify the current internal
hash/prev_hashchain behavior. In particular, they assert that:the first entry's
prev_hashequalsGENESIS_HASH;subsequent entries use the previous entry's hash as
prev_hash;hashes are persisted using the internal
hash/prev_hashrepresentation.This indicates that the observed behavior is part of the current reference implementation and is not merely an isolated malformed log entry.
Impact on implementers
A conformant implementation or verification tool following §8.2 cannot independently reproduce the reference Guardian's recorded SessionContext hashes from the log using the normative construction.
As a result, the reference Guardian's SessionContext chain is not interoperable with conformant chain-verification tooling. Independent implementations following §8.2 will derive different hashes from the same logical ContextEntry content, preventing reliable cross-implementation chain verification and audit comparison.
Because SessionContext hashing is intended to provide a portable chain commitment, this difference affects interoperability rather than only internal storage.
Current Priority Scope
Feeds the runnable Guardian reference implementation