compute_action_ref and compute_action_ref_v2 in plugins/agt_evidence_anchor/action_ref.py hash inputs that docs/spec/action-ref.md requires a verifier to reject before any digest comparison.
Context for why I have vectors to compare against: the APS SDK ships a cross-ecosystem correlation helper whose stated purpose is to reproduce this derivation byte for byte, with 13 published vectors at conformance/action-ref-v1/vectors.json. Over inputs both profiles accept, the digests agree exactly. The mismatch is in profile enforcement rather than in the hash.
The five timestamp cases. The Domain paragraph requires OUT_OF_PROFILE_DOMAIN and a stop before any digest comparison for malformed timestamp grammar. Both functions hash all five of these and return a normal-looking reference:
2026-05-24t10:30:00.000Z lowercase separator
2026-05-24T10:30:00.000z lowercase suffix
2026-05-24T10:30:00.000+00:00 numeric offset
2026-05-24T10:30:00Z second precision
2026-05-24T10:30:00.000000Z six fractional digits
Worth knowing how this gets reached. The default idiom in Python produces a form the spec rejects:
datetime.now(timezone.utc).isoformat() 2026-07-29T21:49:13.312610+00:00
isoformat(timespec="milliseconds") 2026-07-29T21:49:13.312+00:00
format_timestamp(datetime.now(timezone.utc)) 2026-07-29T21:49:13.312Z
Only the third is conformant. The second still carries a numeric offset. So an implementer reaching for the language default rather than your format_timestamp helper produces two of the five rejected shapes at once, and the function hashes it.
Two other cases that may need clarification.
av-003 carries a scope of scope:звіт/📄, which is non-ASCII and includes an astral-plane character. The Domain paragraph excludes non-ASCII field values and surrogate-pair scope strings by name. The function hashed it and returned my expected digest.
av-007 carries an empty scope. The field table says scope is a free-form non-empty string, and the following line says to pass "" if not applicable. That reads as a wording conflict rather than a real divergence, but the function hashes it either way.
So the written profile and the copyable functions currently accept different input domains. Two fixes look clean from outside:
- Enforce the profile inside both functions before hashing.
- Mark the functions as derivation-only and ship a profile validator that the examples call first.
I have not tried to determine whether any caller validates first, since the documented consumers are external.
Happy to attach the full 13-vector result matrix if that is useful.
compute_action_refandcompute_action_ref_v2inplugins/agt_evidence_anchor/action_ref.pyhash inputs thatdocs/spec/action-ref.mdrequires a verifier to reject before any digest comparison.Context for why I have vectors to compare against: the APS SDK ships a cross-ecosystem correlation helper whose stated purpose is to reproduce this derivation byte for byte, with 13 published vectors at conformance/action-ref-v1/vectors.json. Over inputs both profiles accept, the digests agree exactly. The mismatch is in profile enforcement rather than in the hash.
The five timestamp cases. The Domain paragraph requires
OUT_OF_PROFILE_DOMAINand a stop before any digest comparison for malformed timestamp grammar. Both functions hash all five of these and return a normal-looking reference:2026-05-24t10:30:00.000Zlowercase separator2026-05-24T10:30:00.000zlowercase suffix2026-05-24T10:30:00.000+00:00numeric offset2026-05-24T10:30:00Zsecond precision2026-05-24T10:30:00.000000Zsix fractional digitsWorth knowing how this gets reached. The default idiom in Python produces a form the spec rejects:
Only the third is conformant. The second still carries a numeric offset. So an implementer reaching for the language default rather than your
format_timestamphelper produces two of the five rejected shapes at once, and the function hashes it.Two other cases that may need clarification.
av-003carries a scope ofscope:звіт/📄, which is non-ASCII and includes an astral-plane character. The Domain paragraph excludes non-ASCII field values and surrogate-pair scope strings by name. The function hashed it and returned my expected digest.av-007carries an empty scope. The field table says scope is a free-form non-empty string, and the following line says to pass""if not applicable. That reads as a wording conflict rather than a real divergence, but the function hashes it either way.So the written profile and the copyable functions currently accept different input domains. Two fixes look clean from outside:
I have not tried to determine whether any caller validates first, since the documented consumers are external.
Happy to attach the full 13-vector result matrix if that is useful.