Skip to main content

uor_addr/json/
verbs.rs

1//! `uor-addr`'s ψ-chain content-address derivation verbs
2//! (wiki ADR-024, ADR-035, ADR-036) — one per admissible σ-axis.
3//!
4//! The address-derivation inference is the **k-invariant branch** of
5//! the ψ-pipeline applied to a `JsonInput`:
6//!
7//! ```text
8//! JsonInput  (canonical-form JCS+NFC bytes)
9//!    ↓ ψ_1 Nerve            (Constraints → SimplicialComplex)
10//!    ↓ ψ_7 PostnikovTower   (SimplicialComplex → PostnikovTower)
11//!    ↓ ψ_8 HomotopyGroups   (PostnikovTower → HomotopyGroups)
12//!    ↓ ψ_9 KInvariants      (HomotopyGroups → KInvariants)
13//! AddressLabel — the κ-label (`<algorithm>:<hex>`)
14//! ```
15//!
16//! The verb body is identical across σ-axes — only the output-shape return
17//! type differs (one per axis). Foundation's catamorphism evaluates the
18//! chain end-to-end via the application's `ResolverTuple`
19//! ([`crate::resolvers::AddressResolverTuple`]); the canonical hash axis is
20//! consumed by ψ_9's resolver
21//! ([`crate::resolvers::AddressKInvariantResolver`]), **never** by the verb
22//! body's term composition (ADR-035 ψ-residuals discipline; the
23//! `verb_arena_contains_no_sigma_residuals` test pins it).
24
25use crate::json::value::JsonCarrier;
26use crate::label::{
27    AddressLabelBlake3, AddressLabelKeccak256, AddressLabelSha256, AddressLabelSha3_256,
28    AddressLabelSha512,
29};
30
31addr_verbs! {
32    input: JsonCarrier<'_>,
33    { shape: AddressLabelSha256, verb: address_inference },
34    { shape: AddressLabelBlake3, verb: address_inference_blake3 },
35    { shape: AddressLabelSha3_256, verb: address_inference_sha3_256 },
36    { shape: AddressLabelKeccak256, verb: address_inference_keccak256 },
37    { shape: AddressLabelSha512, verb: address_inference_sha512 },
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43    use prism::operation::Term;
44
45    #[test]
46    fn verb_term_arena_is_emitted_and_nonempty() {
47        let arena = address_inference_term_arena::<{ crate::ADDR_INLINE_BYTES }>();
48        assert!(!arena.is_empty());
49    }
50
51    #[test]
52    fn verb_arena_contains_psi_1_nerve() {
53        let arena = address_inference_term_arena::<{ crate::ADDR_INLINE_BYTES }>();
54        assert!(arena.iter().any(|t| matches!(t, Term::Nerve { .. })));
55    }
56
57    #[test]
58    fn verb_arena_contains_psi_7_postnikov_tower() {
59        let arena = address_inference_term_arena::<{ crate::ADDR_INLINE_BYTES }>();
60        assert!(arena
61            .iter()
62            .any(|t| matches!(t, Term::PostnikovTower { .. })));
63    }
64
65    #[test]
66    fn verb_arena_contains_psi_8_homotopy_groups() {
67        let arena = address_inference_term_arena::<{ crate::ADDR_INLINE_BYTES }>();
68        assert!(arena
69            .iter()
70            .any(|t| matches!(t, Term::HomotopyGroups { .. })));
71    }
72
73    #[test]
74    fn verb_arena_contains_psi_9_k_invariants() {
75        let arena = address_inference_term_arena::<{ crate::ADDR_INLINE_BYTES }>();
76        assert!(arena.iter().any(|t| matches!(t, Term::KInvariants { .. })));
77    }
78
79    #[test]
80    fn verb_arena_contains_no_sigma_residuals() {
81        // Wiki ADR-035 ψ-residuals discipline: no σ-enumeration in the
82        // verb body. The canonical hash axis is consumed by resolvers per
83        // ADR-046's discipline boundary — never by the verb body.
84        let arena = address_inference_term_arena::<{ crate::ADDR_INLINE_BYTES }>();
85        let has_first_admit = arena.iter().any(|t| matches!(t, Term::FirstAdmit { .. }));
86        let has_axis_invocation = arena
87            .iter()
88            .any(|t| matches!(t, Term::AxisInvocation { .. }));
89        let has_le_or_concat = arena.iter().any(|t| {
90            matches!(
91                t,
92                Term::Application {
93                    operator: prism::operation::PrimitiveOp::Le
94                        | prism::operation::PrimitiveOp::Concat
95                        | prism::operation::PrimitiveOp::Lt
96                        | prism::operation::PrimitiveOp::Ge
97                        | prism::operation::PrimitiveOp::Gt,
98                    ..
99                }
100            )
101        });
102        assert!(
103            !has_first_admit,
104            "FirstAdmit is a σ-enumeration residual — must not appear in the pure-prism verb body"
105        );
106        assert!(
107            !has_axis_invocation,
108            "AxisInvocation belongs in resolvers, not in the verb body's composition"
109        );
110        assert!(
111            !has_le_or_concat,
112            "byte-comparison/concat ops are σ-residuals — admission is structural"
113        );
114    }
115}