# ENC/TGK1-EDGE/1 — Canonical Encoding for TGK EdgeArtifacts Status: Approved Owner: Niklas Rydberg Version: 0.1.0 SoT: Yes Last Updated: 2025-11-16 Linked Phase Pack: N/A Tags: [binary-minimalism, traceability] **Document ID:** `ENC/TGK1-EDGE/1` **Profile ID:** `TGK1_EDGE_ENC_V1 = 0x0201` (symbolic; concrete assignment lives in encoding-profile registry) **Layer:** Edge Encoding Profile (on top of ASL/1-CORE + TGK/1-CORE) **Depends on (normative):** * `ASL/1-CORE v0.4.x` — value model (`Artifact`, `TypeTag`, `Reference`, `HashId`, identity model) * `ENC/ASL1-CORE v1.x` — canonical encodings for `Artifact` and `Reference` * `TGK/1-CORE v0.7.x` — trace graph kernel (`Node`, `EdgeBody`, `EdgeTypeId`, edgehood invariants) **Integrates with (informative):** * `HASH/ASL1 v0.2.x` — ASL1 hash family for `EdgeRef` identity * `ASL/1-STORE v0.4.x` — content-addressable store holding EdgeArtifacts * `SUBSTRATE/STACK-OVERVIEW v0.2.x` — stack layering discipline * TGK type catalogs (e.g. `TGK/TYPES-CORE`) — `EdgeTypeId` semantics * Future TGK profiles (`TGK/STORE/1`, `TGK/PROV/1`) that interpret edges > The Profile ID `TGK1_EDGE_ENC_V1` is a configuration label. > It is **not** embedded into edge payloads. Encoders and decoders select this encoding by context (type tag + profile configuration), not per value. © 2025 Niklas Rydberg. ## License Except where otherwise noted, this document (text and diagrams) is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0). The identifier registries and mapping tables (e.g. TypeTag IDs, HashId assignments, EdgeTypeId tables) are additionally made available under CC0 1.0 Universal (CC0) to enable unrestricted reuse in implementations and derivative specifications. Code examples in this document are provided under the Apache License 2.0 unless explicitly stated otherwise. Test vectors, where present, are dedicated to the public domain under CC0 1.0. --- ## 0. Overview `ENC/TGK1-EDGE/1` defines the **canonical, streaming-friendly, injective binary encoding** of the `EdgeBody` structure from `TGK/1-CORE`: ```text EdgeBody { type: EdgeTypeId // uint32 from: Node[] // Node = Reference to: Node[] payload: Reference } ``` and its embedding as TGK **EdgeArtifacts**: ```text Artifact { bytes = EdgeBytes // this profile type_tag = TYPE_TAG_TGK1_EDGE_V1 } ``` where `EdgeBytes` is a single `OctetString` (sequence of bytes) used as `Artifact.bytes`. Under this profile: * `EdgeBytes` is the canonical representation of an `EdgeBody`. * Edge identity is the ASL/1 `Reference` over the EdgeArtifact (`EdgeRef`), derived via `ENC/ASL1-CORE` + `HASH/ASL1`. * The encoding is: * **Injective** — distinct `EdgeBody` values → distinct `EdgeBytes`. * **Deterministic & stable** — same `EdgeBody` → same `EdgeBytes` across implementations and time. * **Streaming-friendly** — encoders, decoders, and hashers can operate in a single forward-only pass. In line with `TGK/1-CORE`: * Each EdgeArtifact encodes **exactly one** logical edge (one `EdgeBody`). * All TGK edges are represented as ordinary ASL/1 Artifacts plus their ASL `Reference` identities; this profile introduces no additional identity or node/edge ID layer. > **Non-goal:** This profile does **not** define what any particular `EdgeTypeId` “means”, nor how graphs are stored, indexed, or traversed. Those behaviors are defined by `TGK/1-CORE`, TGK type catalogs, and higher-layer profiles. --- ## 1. Scope & Layering ### 1.1 Purpose This specification defines: * The **binary layout** of: * `EdgeBytes` — canonical encoding for `EdgeBody`. * `EncodedRef` — an internal wrapper for embedding ASL `Reference`s. * Canonical field ordering and integer widths. * How `EdgeBytes` are bound into EdgeArtifacts and converted into `EdgeRef` identity. It does **not** define: * TGK graph semantics or provenance algorithms (`TGK/1-CORE`, `TGK/PROV/1`). * Store or transport APIs (`ASL/1-STORE`, deployment profiles). * Edge-type catalogs (`TGK/TYPES-*`) or policy. ### 1.2 Layering constraints In line with `SUBSTRATE/STACK-OVERVIEW` and `TGK/1-CORE`: * `ENC/TGK1-EDGE/1` is a **TGK edge-encoding profile**, not a kernel primitive. * It MUST NOT: * redefine `Artifact`, `Reference`, `HashId`, or `TypeTag` (from `ASL/1-CORE`); * redefine `Node`, `EdgeBody`, or `EdgeTypeId` (from `TGK/1-CORE`); * embed store, provenance, or policy semantics into its layout. * It defines exactly one canonical encoding for `EdgeBody` values under the profile ID `TGK1_EDGE_ENC_V1`. TGK/1-CORE sees this profile as providing a partial function: ```text decode_edge_payload_TGK1_EDGE : OctetString -> EdgeBody | error ``` that is: * **partial** — may fail with an error for some inputs; * **deterministic** — a pure function of its input bytes, with no dependence on environment or mutable state; * **side-effect free** — decoding does not consult stores, catalogs, or policy. Artifacts whose `type_tag` selects this profile use `decode_edge_payload_TGK1_EDGE` as their TGK edge decoder in the sense of `TGK/1-CORE §3.2`. --- ## 2. Conventions ### 2.1 RFC 2119 terms The key words **MUST**, **MUST NOT**, **SHOULD**, **MAY**, etc. are to be interpreted as described in RFC 2119. ### 2.2 Integer encodings All multi-byte integers are encoded as **big-endian** (network byte order), as in `ENC/ASL1-CORE`: * `u8` — 1 byte * `u16` — 2 bytes * `u32` — 4 bytes * `u64` — 8 bytes Only fixed-width integers are used. ### 2.3 Lists A list of values of some type `T` is encoded as: ```text List :: count (u32) element_0 element_1 ... element_{count-1} ``` * `count` is the number of elements (MAY be zero). * Elements are encoded in order using the canonical encoding of `T`. ### 2.4 Embedded Reference (`EncodedRef`) Within `EdgeBytes`, ASL/1 `Reference` values are embedded using a length-prefixed wrapper over canonical `ReferenceBytes` from `ENC/ASL1-CORE`: ```text EncodedRef :: ref_len (u32) ref_bytes (byte[0..ref_len-1]) // canonical ReferenceBytes ``` Where: * `ref_bytes` MUST be the canonical `ReferenceBytes` encoding of some `Reference` value under `ENC/ASL1-CORE v1.x`: ```text ReferenceBytes :: hash_id (u16) digest (byte[...]) // remaining bytes in the frame ``` * `ref_len` MUST be the exact byte length of `ref_bytes` and MUST be ≥ 2. Decoders MUST: 1. Read `ref_len (u32)`. 2. Read exactly `ref_len` bytes as `ref_bytes`. 3. Decode `ref_bytes` as `ReferenceBytes` per `ENC/ASL1-CORE v1.x`. 4. Reject encodings where: * `ref_len < 2`, or * `ref_bytes` is not a valid `ReferenceBytes` sequence (e.g. truncated or improperly framed in its context). If the implementation also implements `HASH/ASL1` and recognizes the decoded `hash_id`, it MUST apply any length checks required by `ENC/ASL1-CORE` / `HASH/ASL1` for that `HashId` (e.g. fixed digest length). Failures MUST be treated as encoding/integrity errors. `EncodedRef` is purely an internal framing wrapper for this profile; it introduces no additional semantics beyond “a `Reference` encoded canonically and length-prefixed so it can be embedded in larger structures”. This pattern mirrors `EncodedRef` from `ENC/PEL-TRACE-DAG/1` for cross-profile consistency. ### 2.5 Encoding version field (`edge_version`) `EdgeBytes` includes an `edge_version (u16)` field: * For `TGK1_EDGE_ENC_V1`, encoders **MUST** always write `edge_version = 1`. * Decoders for this profile: * **MUST** accept `edge_version = 1`; and * **MUST** treat any other value as “**not this encoding**” and fail decoding. Within this profile, `edge_version` is a **guard word**, not an evolution mechanism: * This document will never assign any other meaning than “constant value 1” to `edge_version` for `TGK1_EDGE_ENC_V1`. * Values other than `1` simply indicate that the bytes are not an `EdgeBytes` value for this profile. Any incompatible change to the `EdgeBytes` layout MUST be expressed as a **new encoding profile** (e.g. `TGK1_EDGE_ENC_V2` with its own Profile ID, and almost certainly a new `TypeTag`), not by reusing this profile with `edge_version = 2`. Append-only extensions that would change the canonical mapping from `EdgeBody` to bytes are also out of scope for this profile; they belong in new profiles. Canonical `EdgeBody → EdgeBytes` mapping for `TGK1_EDGE_ENC_V1` is fixed and permanently tied to `edge_version = 1`. --- ## 3. Logical Model Reference (from TGK/1-CORE) > **Source of truth:** `TGK/1-CORE`. > This section is an informative restatement; in any conflict, `TGK/1-CORE` governs. ### 3.1 Node ```text Node := Reference // ASL/1 Reference ``` Nodes are graph vertices identified solely by their `Reference` value. ### 3.2 EdgeTypeId ```text EdgeTypeId = uint32 ``` Semantics of particular `EdgeTypeId` values are defined by TGK type catalogs and profiles, not by this document. ### 3.3 EdgeBody ```text EdgeBody { type: EdgeTypeId from: Node[] // ordered, MAY be empty to: Node[] // ordered, MAY be empty payload: Reference // always present } ``` Relevant invariant from `TGK/1-CORE`: > **TGK/EDGE-NONEMPTY-ENDPOINT/CORE/1** > For a well-formed `EdgeBody`, at least one of `from` or `to` **MUST** be non-empty. > An `EdgeBody` with both `from = []` and `to = []` is invalid and MUST NOT be produced or accepted as a TGK edge. Other notes from `TGK/1-CORE`: * Duplicates within `from` or `to` are allowed. * `payload` may also appear in `from` or `to`. * Semantics of such patterns, if any, are profile-specific. `ENC/TGK1-EDGE/1` encodes exactly these fields and MUST NOT introduce additional logical data at the `EdgeBody` level. --- ## 4. EdgeBody Encoding ### 4.1 Overall layout: `EdgeBytes` The canonical encoding of an `EdgeBody` under `TGK1_EDGE_ENC_V1` is a single self-contained byte sequence: ```text EdgeBytes :: edge_version (u16) type_id (u32) // EdgeTypeId from_count (u32) from_nodes (EncodedRef[0..from_count-1]) to_count (u32) to_nodes (EncodedRef[0..to_count-1]) payload_ref (EncodedRef) ``` `EdgeBytes` is treated as an indivisible frame. When embedded in larger structures or protocols, the enclosing layer is responsible for providing the frame boundaries (e.g. via a length-prefix or message framing). Field roles: 1. **edge_version (u16)** * Guard word for this encoding profile. * For `TGK1_EDGE_ENC_V1`, encoders **MUST** set `edge_version = 1` for all values. * Decoders for this profile: * **MUST** accept `edge_version = 1`; and * **MUST** treat any other value as “not a `TGK1_EDGE_ENC_V1` edge payload” and fail decoding. `edge_version` is not a version knob for evolving `TGK1_EDGE_ENC_V1`; it is a constant sanity check to quickly reject mismatched bytes. 2. **type_id (u32)** * Encodes `EdgeBody.type : EdgeTypeId`. * The meaning of each `EdgeTypeId` value is external to this spec. 3. **from_count (u32)** and **from_nodes** * `from_count` is the length of `EdgeBody.from`. * `from_nodes` is a list of `from_count` `EncodedRef` entries, each encoding a `Node` (i.e. a `Reference`). * Order MUST match the logical `from` list; duplicates are allowed; MAY be zero-length. 4. **to_count (u32)** and **to_nodes** * `to_count` is the length of `EdgeBody.to`. * `to_nodes` is a list of `to_count` `EncodedRef` entries. * Order MUST match the logical `to` list; duplicates are allowed; MAY be zero-length. 5. **payload_ref (EncodedRef)** * Encodes `EdgeBody.payload : Reference`. * Always present and encoded as a single `EncodedRef`. ### 4.2 Encoding procedure (normative) Let `E` be a logical `EdgeBody` value. The canonical encoding function: ```text encode_edgebody_tgk1_v1 : EdgeBody -> EdgeBytes ``` is defined as: 1. Set `edge_version = 1`. 2. Emit `edge_version` as `u16`. 3. Emit `E.type` as `type_id (u32)`. 4. Let `from_count = len(E.from)`; emit `from_count (u32)`. 5. For each `Node` in `E.from` in order: * Let `R` be that `Node` (an ASL `Reference` value). * Encode `R` as canonical `ReferenceBytes` using `ENC/ASL1-CORE v1.x`. * Wrap as `EncodedRef` (see §2.4) and append. 6. Let `to_count = len(E.to)`; emit `to_count (u32)`. 7. For each `Node` in `E.to` in order: * Encode as `EncodedRef` as above and append. 8. Encode `E.payload` as canonical `ReferenceBytes`, wrap as `EncodedRef`, and append as `payload_ref`. 9. Enforce the TGK non-empty endpoint invariant at encoding time: * If `from_count == 0` **and** `to_count == 0`, the encoder MUST fail and MUST NOT produce `EdgeBytes` for this `EdgeBody` under this profile. > **TGK1-EDGE-NONEMPTY/ENC/1** > Encoders for `TGK1_EDGE_ENC_V1` **MUST** reject any attempt to encode an `EdgeBody` with `from = []` and `to = []`. > Such a value is not a well-formed TGK edge per `TGK/1-CORE` and MUST NOT be emitted as an EdgeArtifact payload. ### 4.3 Decoding procedure (normative) Given a byte slice known to contain exactly one `EdgeBytes` frame under this profile, the canonical decoding function: ```text decode_edgebody_tgk1_v1 : EdgeBytes -> EdgeBody | error ``` is defined as: 1. Read `edge_version (u16)`. * If `edge_version != 1`, fail with an encoding error (e.g. “not `TGK1_EDGE_ENC_V1`”). 2. Read `type_id (u32)`. 3. Read `from_count (u32)`. * For `i = 0 .. from_count-1`, read and decode one `EncodedRef` as a `Reference` and append to `from_nodes`. 4. Read `to_count (u32)`. * For `j = 0 .. to_count-1`, read and decode one `EncodedRef` and append to `to_nodes`. 5. Read `payload_ref` as a single `EncodedRef` and decode to `payload : Reference`. 6. If `from_count == 0` **and** `to_count == 0`, fail with an encoding error: * This violates `TGK/EDGE-NONEMPTY-ENDPOINT/CORE/1` and `TGK1-EDGE-NONEMPTY/ENC/1`. 7. If the decoding context expects an isolated `EdgeBytes` value: * After step 5 (or 6), if any unread bytes remain in the slice, the decoder MUST treat this as an encoding error (trailing data). 8. Construct and return: ```text EdgeBody { type = EdgeTypeId(type_id) from = from_nodes to = to_nodes payload = payload } ``` Decoders MUST additionally treat as encoding errors: * truncated sequences (insufficient bytes for any declared field or `EncodedRef`); * invalid `EncodedRef` encodings (see §2.4); * any integer reads that cannot be completed because the input ends early. `decode_edgebody_tgk1_v1` MUST be deterministic and MUST NOT depend on any external configuration beyond: * the bytes in the `EdgeBytes` frame; and * the static definition of `ENC/ASL1-CORE v1.x` used to decode embedded `ReferenceBytes`. Recognition of `type_id` values (as supported or not in a given ExecutionEnvironment) is handled by `TGK/1-CORE` and the local catalog. This profile always decodes the raw `EdgeBody` structure, regardless of whether the environment later chooses to treat it as an EdgeArtifact. --- ## 5. EdgeArtifact Binding & Profile Selection ### 5.1 EdgeArtifact shape Under this profile, EdgeArtifacts MUST be ASL/1 Artifacts of the form: ```text Artifact { bytes = EdgeBytes type_tag = TYPE_TAG_TGK1_EDGE_V1 } ``` Where: * `TYPE_TAG_TGK1_EDGE_V1` is `TypeTag{ tag_id = 0x0000_0201 }`, assigned in the global TypeTag registry (`TYPE/ASL1`, handle `amduat.type.asl1.tag.00000201@1`). * When this profile is active, the environment’s `EDGE_TAG_SET` **MUST** include `TYPE_TAG_TGK1_EDGE_V1.tag_id`. ExecutionEnvironments that wish to treat such Artifacts as TGK edges MUST: * include `TYPE_TAG_TGK1_EDGE_V1.tag_id` in their configured `EDGE_TAG_SET`; and * register `TGK1_EDGE_ENC_V1` as the edge-encoding profile for that tag, so that `decode_edge_payload_TGK1_EDGE` is used for those Artifacts’ `bytes`. ### 5.2 Integration with TGK/1-CORE’s `decode_edge_payload_P` For ExecutionEnvironments that activate `TGK1_EDGE_ENC_V1` for `TYPE_TAG_TGK1_EDGE_V1`, the corresponding `decode_edge_payload_P` function from `TGK/1-CORE §3.2` is: ```text decode_edge_payload_TGK1_EDGE(bytes: OctetString) -> EdgeBody | error ``` defined by: ```text decode_edgebody_tgk1_v1(bytes) ``` from §4.3. Conformant implementations MUST: * apply `decode_edge_payload_TGK1_EDGE` only to Artifacts whose `type_tag.tag_id` is configured to use this profile; and * treat any decoding failure as “not a valid edge payload for this profile”. Multi-profile behavior (e.g., co-existence with other edge encodings) is governed by `TGK/1-CORE §3.2`. In particular: * If more than one active profile successfully decodes the same `Artifact.bytes`, all such profiles MUST decode to the same logical `EdgeBody` value. * If two active profiles decode the same bytes to different `EdgeBody` values, the ExecutionEnvironment MUST NOT treat that Artifact as an EdgeArtifact until the conflict is resolved. --- ## 6. EdgeRef Identity via ASL/1-CORE Given: * `EdgeBytes` from §4; * an `EdgeArtifact`: ```text A_edge = Artifact { bytes = EdgeBytes type_tag = TYPE_TAG_TGK1_EDGE_V1 } ``` * `ENC/ASL1-CORE v1.x` for canonical `ArtifactBytes`; * a hash algorithm `H` with `HashId = HID` from `HASH/ASL1`, the canonical `EdgeRef : Reference` (the edge identity) is: ```text ArtifactBytes = encode_artifact_core_v1(A_edge) digest = H(ArtifactBytes) EdgeRef = Reference { hash_id = HID, digest = digest } ``` This profile does not introduce any new identity scheme. Edge identity is entirely determined by: * the ASL/1 Artifact identity model, * the selected encoding profile (typically `ASL_ENC_CORE_V1`), and * the selected hash algorithm (`HASH/ASL1`). --- ## 7. Canonicality & Injectivity ### 7.1 Injectivity > **TGK1-EDGE-INJECTIVE/ENC/1** > Under `TGK1_EDGE_ENC_V1`, the mapping: > > ```text > EdgeBody -> EdgeBytes > ``` > > MUST be injective. That is, for any two `EdgeBody` values `E1` and `E2`: > > ```text > E1 != E2 ⇒ encode_edgebody_tgk1_v1(E1) != encode_edgebody_tgk1_v1(E2) > ``` This is ensured by: * encoding all logical fields (`type`, `from`, `to`, `payload`); * preserving list order exactly; * using a fixed, explicit binary layout. ### 7.2 Stability For the fixed profile `TGK1_EDGE_ENC_V1` (with the guard word `edge_version = 1`): * The same logical `EdgeBody` MUST always encode to the same `EdgeBytes` across: * implementations, * platforms, * executions, * and time. Encoders MUST NOT: * reorder elements of `from` or `to`; * alter integer widths or endianness; * introduce alternative layouts for any field; * use any `edge_version` other than `1`. --- ## 8. Error Handling (Encoding Layer) Decoders for this profile MUST treat as **encoding errors** (to be surfaced as some error category at the API boundary): 1. **Guard word mismatch** * `edge_version != 1`. 2. **Truncated fields** * Not enough bytes to read any declared field (`u16`, `u32`, `EncodedRef`, list elements). 3. **Invalid `EncodedRef`** * `ref_len < 2`; or * `ref_bytes` is not a valid `ReferenceBytes` sequence per `ENC/ASL1-CORE v1.x`; or * (when `HASH/ASL1` is implemented and `hash_id` is known) the digest length implied by `ref_bytes` does not match the canonical length for that `HashId`. 4. **Empty endpoints** * `from_count == 0` **and** `to_count == 0` (violation of `TGK/EDGE-NONEMPTY-ENDPOINT/CORE/1`). 5. **Inconsistent list lengths** * Fewer actual `EncodedRef` entries than indicated by `from_count` or `to_count`. 6. **Trailing data in isolated contexts** * Additional bytes remaining after a full `EdgeBytes` value has been decoded, when the decoding context expects exactly one `EdgeBytes` frame. Translating these into concrete error codes (e.g. `ERR_TGK1_EDGE_ENC_INVALID`) is implementation-specific, but MUST result in rejection of the payload as an `EdgeBytes` value under this profile. Semantic errors about `EdgeTypeId` recognition or edge-type-specific constraints are handled by TGK catalogs and higher profiles, not at the encoding layer. --- ## 9. Streaming & Implementation Notes Implementations MUST be able to encode and decode `EdgeBytes` in a **single forward-only pass**: * All length prefixes (`from_count`, `to_count`, `ref_len`) precede their content. * Decoders MUST NOT require backtracking to interpret the structure. For large edges (many endpoints): * Encoders MAY stream `EncodedRef` entries as they are generated. * Decoders MAY stream `EncodedRef` entries to consumers or hashers as they are read. Any such streaming strategy MUST be observationally equivalent to decoding the entire `EdgeBytes` into an `EdgeBody` in memory and MUST respect the canonical layout. --- ## 10. Conformance An implementation is **ENC/TGK1-EDGE/1–conformant** if, for `TGK1_EDGE_ENC_V1`, it: 1. **Implements canonical EdgeBody encoding/decoding** * Implements `encode_edgebody_tgk1_v1` and `decode_edgebody_tgk1_v1` exactly as specified in §4. * Always writes `edge_version = 1` when encoding. * Accepts only `edge_version = 1` and treats any other value as “not this encoding”. 2. **Uses `EncodedRef` correctly** * Embeds `Reference` values via `EncodedRef` as in §2.4. * Uses canonical `ReferenceBytes` from `ENC/ASL1-CORE v1.x` when forming `ref_bytes`. * Applies `HASH/ASL1` length checks for known `HashId`s when available. 3. **Enforces TGK invariants at the encoding layer** * Rejects encodings with both `from` and `to` empty (`TGK1-EDGE-NONEMPTY/ENC/1`). * Treats malformed payloads as encoding errors as per §8. 4. **Binds EdgeBytes into EdgeArtifacts correctly** * When forming EdgeArtifacts, sets: ```text Artifact.bytes = EdgeBytes Artifact.type_tag = TYPE_TAG_TGK1_EDGE_V1 ``` * Does not embed additional logical data into the Artifact beyond `EdgeBody` and `type_tag`. 5. **Derives EdgeRef identity via ASL/1-CORE** * Uses `ENC/ASL1-CORE v1` and `HASH/ASL1` for identity, as in §6. * Does not introduce alternative edge identity mechanisms at this layer. 6. **Integrates with TGK/1-CORE profile selection** * Applies `decode_edge_payload_TGK1_EDGE` only to Artifacts whose `type_tag.tag_id` is configured for this profile. * Respects multi-profile behavior rules from `TGK/1-CORE §3.2` when other edge encodings are also active. 7. **Preserves injectivity and stability** * Distinct `EdgeBody` values always produce distinct `EdgeBytes`. * The same `EdgeBody` always produces the same `EdgeBytes` under this profile. Everything else — storage layout, access protocols, graph indexes, provenance algorithms, and edge-type semantics — is defined by `ASL/1-STORE`, `TGK/1-CORE`, TGK catalogs, and higher-layer profiles. --- ## 11. Informative Example (Sketch) > Non-normative; values and hex are illustrative only. Consider an edge: ```text EdgeBody { type = 0x00000010 // EDGE_EXECUTION (for example) from = [N_prog, N_input] to = [N_output] payload = R_receipt } ``` Where `N_prog`, `N_input`, `N_output`, and `R_receipt` are `Reference` values with canonical `ReferenceBytes`: ```text Ref(N_prog) = ReferenceBytes(N_prog) // length = len_pg, bytes = bytes_pg Ref(N_input) = ReferenceBytes(N_input) // length = len_in, bytes = bytes_in Ref(N_output) = ReferenceBytes(N_output) // length = len_out, bytes = bytes_out Ref(R_receipt) = ReferenceBytes(R_receipt) // length = len_rc, bytes = bytes_rc ``` Then `EdgeBytes` under this profile are: ```text edge_version = 0001 ; u16 (guard word) type_id = 00000010 ; u32 from_count = 00000002 ; 2 sources from_nodes = 000000?? bytes_pg ... ; EncodedRef(N_prog) 000000?? bytes_in ... ; EncodedRef(N_input) to_count = 00000001 ; 1 target to_nodes = 000000?? bytes_out ... ; EncodedRef(N_output) payload_ref = 000000?? bytes_rc ... ; EncodedRef(R_receipt) ``` Where each `EncodedRef(X)` is: ```text ref_len(X) (u32) || ReferenceBytes(X) ``` These `EdgeBytes` become `Artifact.bytes` for an EdgeArtifact with `type_tag = TYPE_TAG_TGK1_EDGE_V1`. All conformant encoders MUST produce the same bytes for the same logical `EdgeBody`; all conformant decoders MUST reconstruct the same `EdgeBody` from those bytes. --- **End of `ENC/TGK1-EDGE/1 v0.1.0 — Canonical Encoding for TGK EdgeArtifacts` (draft).** --- ## Document History * **0.1.0 (2025-11-16):** Registered as Tier-1 spec and aligned to the Amduat 2.0 substrate baseline.