34 KiB
ENC/PEL1-RESULT/1 — Canonical Encoding for PEL/1 Execution Results
Status: Approved Owner: Niklas Rydberg Version: 0.3.0 SoT: Yes Last Updated: 2025-11-30 Linked Phase Pack: PH06 Tags: [binary-minimalism, deterministic, execution]
Document ID: ENC/PEL1-RESULT/1
Profile ID: PEL_ENC_EXECUTION_RESULT_V1 = 0x0103
Layer: Scheme Encoding Profile (PEL/1 Surface Result)
Depends on (normative):
ASL/1-CORE v0.4.x— value model (Artifact,TypeTag,Reference,OctetString)ENC/ASL1-CORE v1.0.x— canonical encodings forArtifactandReferencePEL/1-CORE v0.3.x—ExecutionResultValue,ExecutionStatus,ExecutionErrorSummary,DiagnosticEntryPEL/1-SURF v0.2.x— surface execution result model (SurfaceExecutionResultshape)
Integrates with (informative):
HASH/ASL1 v0.2.x— ASL1 hash family for result Artifact identitySUBSTRATE/STACK-OVERVIEW v0.4.x— layering disciplineENC/PEL-PROGRAM-DAG/1 v0.2.x— list / Utf8 / params encoding conventionsENC/PEL-TRACE-DAG/1 v0.1.x—DiagnosticEntryencoding pattern- TypeTag registry (for
TYPE_TAG_PEL1_RESULT_1assignment)
The Profile ID
PEL_ENC_EXECUTION_RESULT_V1is a configuration label. It is not embedded into payloads. Encoders and decoders select this encoding profile by context (scheme descriptor, engine/store 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/PEL1-RESULT/1 defines the canonical binary encoding of the surface-level
execution result structure defined by PEL/1-SURF for PEL/1 executions.
Concretely, this profile specifies:
-
the binary layout of the PEL/1 surface result value (
SurfaceExecutionResult), including:scheme_ref,program_ref,input_refs,output_refs,params_ref,store_failure,trace_ref,- an inline encoding of
ExecutionResultValuefromPEL/1-CORE;
-
how that value is embedded into ASL/1
Artifact.bytesasResultBytes; -
the dedicated
TypeTagused for result Artifacts under this profile.
Result Artifacts are ordinary ASL/1 Artifacts with:
Artifact.type_tag = TYPE_TAG_PEL1_RESULT_1
Artifact.bytes = ResultBytes
Identity of a result Artifact is then derived from canonical ArtifactBytes
(ENC/ASL1-CORE v1) and a chosen HashId (typically HASH-ASL1-256), but hash
algorithm choice is not part of this encoding spec.
This profile is:
- injective — distinct logical surface result values → distinct
ResultBytes; - stable and deterministic — same logical value → same bytes across implementations and time;
- streaming-friendly — encoders/decoders can operate in a single forward pass.
It does not redefine PEL/1 execution semantics or store behavior; it only
fixes the layout of the surface result value described by PEL/1-SURF.
Encoding vs PEL versioning
pel1_versionfields in this profile encode the PEL/1-CORE major version (1), not the encoding profile version. Encoding version is selected by context viaPEL_ENC_EXECUTION_RESULT_V1andTYPE_TAG_PEL1_RESULT_1, not by any on-wire version field.
1. Scope & Layering
1.1 Purpose
This specification defines:
-
The binary layout of:
ResultBytes— top-level surface result encoding (SurfaceExecutionResult);ExecutionResultValueBytes— inline encoding ofExecutionResultValue(PEL/1-CORE);DiagnosticEntryBytes— scheme diagnostics, reusing the pattern fromENC/PEL-TRACE-DAG/1;StoreFailureBytes— store-resolution diagnostics, aligned withPEL/1-SURF;- an internal wrapper for embedded
Referencevalues (EncodedRef).
-
The field ordering, integer widths, list framing, and presence flags.
-
The binding between
ResultBytesand a dedicated resultTypeTag.
It does not define:
- PEL/1-CORE execution semantics (
Exec_s) or scheme semantics; - PEL/1-SURF surface semantics (how stores are wired, which Artifacts must be persisted);
- hash algorithms or Reference derivation (from
ASL/1-CORE+HASH/ASL1); - trace graph semantics or edges (
TGK/1-COREand profiles).
1.2 Layering constraints
In line with SUBSTRATE/STACK-OVERVIEW:
-
ENC/PEL1-RESULT/1is a scheme-specific encoding profile for a PEL/1 surface result structure. -
It MUST NOT redefine:
Artifact,TypeTag,Reference,HashId(ASL/1-CORE);ExecutionResultValue,ExecutionStatus,ExecutionErrorSummary,DiagnosticEntry(PEL/1-CORE);- the logical surface result structure (from
PEL/1-SURF).
-
It is storage-neutral and policy-neutral:
- it does not talk about particular stores, transports, or policies;
- it does not depend on TGK, CIL, FER, FCT, OI, or any domain profiles.
This profile defines exactly one canonical encoding for PEL/1 surface result values of the shape described in §3.1.
2. Conventions
RFC 2119 terms (MUST, SHOULD, MAY, etc.) are normative.
2.1 Integer encodings
All multi-byte integers in this profile are encoded as big-endian (network
byte order), as in ENC/ASL1-CORE and other PEL encodings:
u8— 1 byteu16— 2 bytesu32— 4 bytesu64— 8 bytes
Only fixed-width integers are used in this specification.
2.2 Lists
A list of values of some type T is encoded as:
List<T> =
count (u32)
element_0
element_1
...
element_{count-1}
countis the number of elements (MAY be zero).- Elements are encoded in order using the canonical encoding for
T.
This u32 length + elements pattern matches ENC/PEL-PROGRAM-DAG/1 and
ENC/PEL-TRACE-DAG/1.
2.3 Utf8String
If this profile needs UTF-8 strings, it uses the same Utf8String encoding as
other PEL encodings:
Utf8String =
length (u32)
bytes[0..length-1]
lengthis the number of bytes.bytesMUST be well-formed UTF-8.- There is no terminator or padding.
The core surface result structure currently does not include free-form text fields; diagnostics use an opaque blob type instead (§2.4).
2.4 Blob32 (Octet blob with 32-bit length)
For diagnostic messages and other opaque payloads, we use:
Blob32 =
length (u32)
bytes[0..length-1]
bytesis an arbitraryOctetString; interpretation is profile- or scheme-specific.lengthMAY be zero.
This is the same Blob32 convention used by ENC/PEL-TRACE-DAG/1. It is a
profile-local convenience; it does not override the general OctetString
encoding from ENC/ASL1-CORE (which uses u64 lengths at the ASL core level).
2.5 Embedded Reference (EncodedRef)
Within this encoding, Reference values are embedded using a length-prefixed
wrapper over canonical ReferenceBytes from ENC/ASL1-CORE v1:
EncodedRef =
ref_len (u32)
ref_bytes (byte[0..ref_len-1]) // canonical ReferenceBytes
Where:
-
ref_bytesMUST be the canonicalReferenceBytesencoding for aReference:ReferenceBytes :: hash_id (u16) digest (byte[...]) // remaining bytes in the frame -
ref_lenMUST be the exact length (in bytes) ofref_bytes, and MUST be ≥ 2.
Decoders MUST:
-
Read
ref_len (u32), thenref_bytes[0..ref_len-1]. -
Decode
ref_bytesasReferenceBytesperENC/ASL1-CORE v1. -
Reject encodings where:
ref_len < 2, orref_bytesis not a validReferenceBytessequence.
This pattern is identical to the EncodedRef used by ENC/PEL-TRACE-DAG/1.
2.5.1 Optional EncodedRef
Optional Reference fields are encoded as:
OptionalEncodedRef =
has_ref (u8)
[ EncodedRef ] // only if has_ref = 0x01
has_ref = 0x00→ no value present; noEncodedReffollows.has_ref = 0x01→ exactly oneEncodedReffollows.- Any other
has_refvalue MUST be treated as an encoding error.
2.6 Embedded StoreFailure (EncodedStoreFailure)
StoreFailure (see §3.3) is embedded using:
StoreFailureBytes ::
phase (u8) // StoreFailurePhase
error_code (u8) // StoreErrorCode
failing_ref (EncodedRef)
Optional StoreFailure is encoded as:
OptionalStoreFailureBytes ::
has_store_failure (u8)
[ store_failure (StoreFailureBytes) ] // if has_store_failure = 0x01
has_store_failure = 0x00→ nostore_failurepresent.has_store_failure = 0x01→ exactly oneStoreFailureBytesfollows.- Any other value MUST be treated as an encoding error.
Decoders MUST:
- Validate
phaseanderror_codeare within the sets defined inPEL/1-SURF(or treat out-of-range values as encoding errors or semantic errors per policy). - Decode
failing_refviaEncodedRef.
3. Logical Surface Result Model (Reference)
This section restates, in condensed form, the logical PEL/1 surface result
structure from PEL/1-SURF. The normative source for semantics is PEL/1-SURF;
this profile only encodes the agreed structure.
3.1 SurfaceExecutionResult structure
PEL/1-SURF defines the logical payload of the surface ExecutionResult artifact
as:
SurfaceExecutionResult {
pel1_version : uint16
core_result : ExecutionResultValue
scheme_ref : SchemeRef // echo
program_ref : ProgramRef
input_refs : InputRefList
output_refs : OutputRefList
params_ref : optional ParamsRef
store_failure: optional StoreFailure
trace_ref : optional TraceRef
}
Where ExecutionResultValue is from PEL/1-CORE (§3.2), and:
SchemeRef = Reference
ProgramRef = Reference
InputRef = Reference
OutputRef = Reference
ParamsRef = Reference
TraceRef = Reference
InputRefList = list<InputRef>
OutputRefList = list<OutputRef>
Semantics (summarised from PEL/1-SURF):
pel1_versionreaffirms the PEL major version (1forPEL/1-CORE).core_resultis the PEL/1-CORE execution result for this run.scheme_ref,program_ref,input_refs,params_refreflect the artifacts used to start the execution.output_refsreflect the artifacts produced and successfully persisted by the surface for this run.store_failure, when present, describes a store-resolution error that preventedExec_sfrom being called, or prevented inputs/params from being resolved, in which casecore_result.statusisINVALID_PROGRAMorINVALID_INPUTSfor store-level reasons.trace_ref, when present, points at a trace Artifact whose logical value is defined by some trace profile (e.g.PEL/TRACE-DAG/1).
Store failures, transport errors, or environment failures that prevent
construction of this artifact are not part of SurfaceExecutionResult;
those are handled at the surface/API layer, not via this encoding.
3.2 ExecutionResultValue (from PEL/1-CORE)
From PEL/1-CORE:
ExecutionStatus = uint8
ExecutionErrorKind = uint8
ExecutionErrorSummary {
kind : ExecutionErrorKind
status_code : uint32
}
DiagnosticEntry {
code : uint32
message : OctetString // scheme-defined; SHOULD be UTF-8 text
}
ExecutionResultValue {
pel1_version : uint16
status : ExecutionStatus
scheme_ref : SchemeRef // Reference
summary : ExecutionErrorSummary
diagnostics : list<DiagnosticEntry>
}
Invariants (from PEL/1-CORE):
-
pel1_versionMUST be 1. -
statusandsummaryMUST satisfy:status = OK→summary.kind = NONE,summary.status_code = 0.status = SCHEME_UNSUPPORTED→summary.kind = SCHEME.status = INVALID_PROGRAM→summary.kind = PROGRAM.status = INVALID_INPUTS→summary.kind = INPUTS.status = RUNTIME_FAILED→summary.kind = RUNTIMEandsummary.status_code != 0.
-
scheme_refMUST match the scheme under which execution was interpreted. -
diagnosticsMUST be deterministic for a given(scheme_ref, program, inputs, params).
This profile defines a canonical inline encoding for ExecutionResultValue and
DiagnosticEntry inside ResultBytes.
3.3 StoreFailure (from PEL/1-SURF)
PEL/1-SURF refines store-resolution errors via:
StoreErrorCode = uint8
StoreErrorCode {
NOT_FOUND = 1 // Store returned ERR_NOT_FOUND
INTEGRITY = 2 // Store returned ERR_INTEGRITY
UNSUPPORTED = 3 // Store returned ERR_UNSUPPORTED
}
StoreFailurePhase = uint8
StoreFailurePhase {
PROGRAM = 1
INPUT = 2
}
StoreFailure {
phase : StoreFailurePhase
error_code : StoreErrorCode
failing_ref : Reference
}
Semantics:
phase = PROGRAMindicates the failure happened while resolvingprogram_ref.phase = INPUTindicates it happened while resolving an input orparams_ref.failing_refMUST be the exactReferencepassed togetthat produced the error.error_codeMUST match the store’s reported error.
This encoding profile provides a canonical encoding for StoreFailure via
StoreFailureBytes and OptionalStoreFailureBytes (§2.6, §4.3).
4. Encoding
This section defines:
DiagnosticEntryBytes— inline diagnostic entry encoding;ExecutionResultValueBytes— inlineExecutionResultValueencoding;StoreFailureBytes/OptionalStoreFailureBytes— store-resolution diagnostics;ResultBytes— top-level PEL/1 surface result encoding.
Field ordering, integer widths, and presence flags are fixed and MUST NOT vary.
4.1 DiagnosticEntry encoding
Logical:
DiagnosticEntry {
code : uint32
message : OctetString
}
Canonical encoding (matching ENC/PEL-TRACE-DAG/1):
DiagnosticEntryBytes ::
code (u32)
message (Blob32)
Where Blob32 is defined in §2.4.
code (u32)encodes the diagnostic or error code.messageis an opaque byte blob. Schemes MAY agree to use UTF-8 text here, but this encoding does not enforce it.
Decoders MUST:
- Read
code (u32). - Read
messageasBlob32. - Treat truncated blobs as encoding errors.
4.2 ExecutionResultValue encoding
Logical:
ExecutionResultValue {
pel1_version : uint16
status : ExecutionStatus
scheme_ref : SchemeRef
summary : ExecutionErrorSummary
diagnostics : list<DiagnosticEntry>
}
Canonical encoding:
ExecutionResultValueBytes ::
pel1_version (u16)
status (u8) // ExecutionStatus
scheme_ref (EncodedRef)
summary_kind (u8) // ExecutionErrorKind
summary_status_code (u32) // ExecutionErrorSummary.status_code
diag_count (u32)
diagnostics (DiagnosticEntryBytes[0..diag_count-1])
Field semantics:
-
pel1_version (u16)-
MUST be
1forExecutionResultValuevalues defined byPEL/1-CORE v0.3.x. -
Decoders:
- MUST accept
pel1_version = 1. - MUST treat other values as encoding errors for this profile revision.
- MUST accept
-
-
status (u8)- Encodes
ExecutionStatusas defined inPEL/1-CORE. - Decoders SHOULD treat out-of-range
statusvalues as encoding errors (rather than attempting to map them to an “unknown” variant).
- Encodes
-
scheme_ref (EncodedRef)- Encodes the
SchemeRef(Reference) under which the scheme was interpreted. - MUST match the
scheme_refat the surface level (§4.4.2, §6.2).
- Encodes the
-
summary_kind (u8)andsummary_status_code (u32)- Encode
ExecutionErrorSummary.kindandExecutionErrorSummary.status_coderespectively. - Encoders MUST set these to satisfy the invariants from
PEL/1-CORE §2.4for the chosenstatus. - Decoders MAY validate consistency; inconsistency is a semantic error, not strictly an encoding error, but implementations MAY choose to reject such values.
- Encode
-
diag_count (u32)anddiagnostics (DiagnosticEntryBytes[..])- Encodes the list of diagnostics as a
List<DiagnosticEntry>. diag_countis the number of entries; MAY be zero.- Decoders MUST reject truncated sequences where fewer than
diag_countentries are present.
- Encodes the list of diagnostics as a
This layout is also suitable for use by other profiles that choose to store
ExecutionResultValue as a dedicated Artifact; see §5 (informative note).
4.3 StoreFailure encoding
Logical:
StoreFailure {
phase : StoreFailurePhase
error_code : StoreErrorCode
failing_ref : Reference
}
Canonical encoding:
StoreFailureBytes ::
phase (u8) // StoreFailurePhase
error_code (u8) // StoreErrorCode
failing_ref (EncodedRef)
Optional presence:
OptionalStoreFailureBytes ::
has_store_failure (u8)
[ store_failure (StoreFailureBytes) ] // if has_store_failure = 0x01
Field semantics:
-
phase (u8)-
Encodes
StoreFailurePhase:1→ PROGRAM2→ INPUT
-
Decoders SHOULD treat other values as encoding errors or semantic errors per implementation policy.
-
-
error_code (u8)-
Encodes
StoreErrorCode:1→ NOT_FOUND2→ INTEGRITY3→ UNSUPPORTED
-
Decoders SHOULD treat other values as encoding errors or semantic errors per implementation policy.
-
-
failing_ref (EncodedRef)- Encodes the
Referencethat failed to resolve.
- Encodes the
-
has_store_failure (u8)0x00→ nostore_failurepresent.0x01→ exactly oneStoreFailureBytesfollows.- Any other value MUST be treated as an encoding error.
Decoders MUST reject truncated values (e.g., missing failing_ref bytes).
4.4 Surface Result encoding (ResultBytes)
Logical (from §3.1):
SurfaceExecutionResult {
pel1_version : uint16
core_result : ExecutionResultValue
scheme_ref : SchemeRef
program_ref : ProgramRef
input_refs : InputRefList
output_refs : OutputRefList
params_ref : optional ParamsRef
store_failure: optional StoreFailure
trace_ref : optional TraceRef
}
Canonical encoding:
ResultBytes ::
pel1_version (u16)
scheme_ref (EncodedRef)
program_ref (EncodedRef)
input_ref_count (u32)
input_refs (EncodedRef[0..input_ref_count-1])
output_ref_count (u32)
output_refs (EncodedRef[0..output_ref_count-1])
has_params_ref (u8)
[ params_ref (EncodedRef) ] // if has_params_ref == 0x01
has_store_failure (u8)
[ store_failure (StoreFailureBytes) ] // if has_store_failure == 0x01
has_trace_ref (u8)
[ trace_ref (EncodedRef) ] // if has_trace_ref == 0x01
core_result (ExecutionResultValueBytes)
Field semantics:
-
pel1_version (u16)- MUST be
1for surface results representingPEL/1-CORE v0.3.xexecutions. - Decoders MUST treat any other value as an encoding error for this profile revision.
- MUST be
-
scheme_ref (EncodedRef)- Encodes the scheme descriptor
SchemeRef(Reference) for the run. - MUST match
ExecutionResultValue.scheme_refencoded insidecore_result.scheme_ref; see §6.2.
- Encodes the scheme descriptor
-
program_ref (EncodedRef)- Encodes the program Artifact reference used for this run.
-
input_ref_count (u32)andinput_refs (EncodedRef[..])- Encodes the ordered list of input references provided to the surface.
input_ref_countMAY be zero.- Encoders MUST preserve the logical order of
inputs. - Decoders MUST reject truncated sequences with fewer than
input_ref_countentries.
-
output_ref_count (u32)andoutput_refs (EncodedRef[..])- Encodes the ordered list of output references produced and successfully persisted by the surface.
output_ref_countMAY be zero even whencore_result.status = OKfor schemes that legitimately produce no outputs.- Encoders MUST preserve the logical output order defined by the scheme/surface.
- Decoders MUST reject truncated sequences.
-
has_params_ref (u8)andparams_ref (EncodedRef)- Encodes an optional parameters Artifact reference.
has_params_ref = 0x00→ noparams_refpresent.has_params_ref = 0x01→ exactly oneEncodedReffollows and encodesparams_ref.- Any other
has_params_refvalue MUST be treated as an encoding error. - Surfaces that do not support parameter Artifacts MUST always emit
has_params_ref = 0x00.
-
has_store_failure (u8)andstore_failure (StoreFailureBytes)-
Encodes an optional
StoreFailureas defined in §3.3 and §4.3. -
has_store_failure = 0x00→ nostore_failurepresent. -
has_store_failure = 0x01→ exactly oneStoreFailureBytesfollows. -
Any other
has_store_failurevalue MUST be treated as an encoding error. -
When
store_failureis present:core_result.statusMUST beINVALID_PROGRAMorINVALID_INPUTSaccording to the phase (PROGRAM or INPUT) as defined inPEL/1-SURF.core_result.summary.kindMUST bePROGRAMorINPUTSaccordingly.
-
-
has_trace_ref (u8)andtrace_ref (EncodedRef)- Encodes an optional reference to a trace Artifact (e.g. a
PEL/TRACE-DAG/1value encoded underENC/PEL-TRACE-DAG/1). has_trace_refuses the same conventions ashas_params_ref.- Surfaces that never produce traces MUST always emit
has_trace_ref = 0x00.
- Encodes an optional reference to a trace Artifact (e.g. a
-
core_result (ExecutionResultValueBytes)- Encodes the inline
ExecutionResultValuefor this run as defined in §4.2. - The
pel1_version,status,scheme_ref,summary, anddiagnosticsfields MUST respectPEL/1-COREinvariants. core_result.scheme_refMUST equal the surface-levelscheme_ref.
- Encodes the inline
5. Result Artifact Binding
5.1 TypeTag
Result Artifacts for this profile MUST be ASL/1 Artifacts with:
Artifact {
bytes = ResultBytes
type_tag = TYPE_TAG_PEL1_RESULT_1
}
Where:
TYPE_TAG_PEL1_RESULT_1is aTypeTagwith a concretetag_idassigned in the global TypeTag registry for PEL/1 surface results.
This encoding profile:
- refers to
TYPE_TAG_PEL1_RESULT_1symbolically; and - does not assign a numeric
tag_id(that belongs in the registry).
5.2 Identity via ASL/1-CORE
With ENC/ASL1-CORE v1 and the "ASL1" hash family (HASH/ASL1):
-
Canonical
ArtifactBytesfor a result Artifact:ArtifactBytes = encode_artifact_core_v1( Artifact{ bytes = ResultBytes, type_tag = TYPE_TAG_PEL1_RESULT_1 } ) -
Canonical
Referencefor any chosenHashId = HID:digest = H(ArtifactBytes) // H from HASH/ASL1 for HID reference = Reference { hash_id = HID, digest = digest }
All conformant implementations using the same (EncodingProfileId, HashId) pair
MUST agree on:
ResultBytesfor a given logical surface result value,- the resulting
ArtifactBytesfor the result Artifact, - the resulting
Reference.
Informative note (ExecutionResultValue as Artifact) Other profiles MAY choose to store
ExecutionResultValueas a dedicated Artifact usingExecutionResultValueBytesasArtifact.bytesand a dedicated TypeTag (e.g.TYPE_TAG_PEL_EXECUTION_RESULT_VALUE_1). Such a binding is intentionally left out of this version; if introduced, it SHOULD reuseExecutionResultValueBytesexactly to preserve injectivity across inline and stored forms.
6. Canonicality & Determinism
6.1 Injectivity
The mapping:
SurfaceExecutionResult -> ResultBytes
defined by this profile MUST be injective:
-
If two logical
SurfaceExecutionResultvalues differ (perPEL/1-SURFandPEL/1-COREsemantics), then:ResultBytes(V1) != ResultBytes(V2)
Injectivity is ensured by:
- fixed field ordering;
- explicit presence flags for all optional references and store failures;
- deterministic list ordering (
input_refs,output_refs,diagnostics); - inclusion of all logically relevant fields.
Similarly, the mapping:
ExecutionResultValue -> ExecutionResultValueBytes
MUST be injective.
6.2 Stability & consistency
For any fixed logical value and encoding profile version:
- All conformant encoders MUST produce the same
ExecutionResultValueBytesandResultBytes. - Encodings MUST be stable across implementations, platforms, and time.
Encoders MUST NOT:
- reorder list elements (
input_refs,output_refs,diagnostics); - omit or reorder fields;
- vary integer widths or encodings;
- introduce alternative layouts for version negotiation.
In addition, encoders MUST enforce:
pel1_versionfields for both the surface result and the inlineExecutionResultValueare1.scheme_refin the surface header andscheme_refinsideExecutionResultValueare identical.- When
store_failureis present,core_result.statusandcore_result.summary.kindreflectINVALID_PROGRAM/PROGRAMorINVALID_INPUTS/INPUTSas mandated byPEL/1-SURF.
6.3 Extension and evolution (informative)
ENC/PEL1-RESULT/1 is intended to evolve additively:
- New optional fields SHOULD be introduced via new encoding profiles or clearly versioned layouts, rather than overloading this layout in incompatible ways.
- Any future revision that extends
ResultBytesorExecutionResultValueBytesMUST preserve all existing fields, their order, and their semantics forpel1_version = 1. - Changes that would alter the meaning of existing bytes (for the same logical value) MUST be expressed as a new profile or a new result TypeTag, not as a silent change to this profile.
7. Error Handling (Encoding Layer)
Decoders for this profile MUST treat as encoding errors:
-
Truncated values
- Insufficient bytes to read any declared integer, length prefix,
EncodedRef,DiagnosticEntryBytes,StoreFailureBytes, orExecutionResultValueBytes.
- Insufficient bytes to read any declared integer, length prefix,
-
Invalid
pel1_version-
pel1_version != 1in either:- the surface-level header (§4.4), or
ExecutionResultValueBytes(§4.2).
-
-
Invalid presence flags
has_params_ref,has_store_failure, orhas_trace_refnot in{0x00, 0x01}.
-
Invalid
EncodedRefref_len < 2, orref_bytescannot be decoded as canonicalReferenceBytesunderENC/ASL1-CORE v1.
-
Invalid list counts
- Fewer entries than indicated by
input_ref_count,output_ref_count, ordiag_count.
- Fewer entries than indicated by
-
Invalid
Utf8String(if used)- Any
Utf8Stringfield present in a future extension that is not valid UTF-8.
- Any
Decoders SHOULD also treat as encoding errors:
statusvalues outside the range defined byPEL/1-COREforExecutionStatus;summary_kindvalues outside the range defined forExecutionErrorKind;phaseorerror_codevalues outside the ranges defined forStoreFailurePhaseandStoreErrorCode, if the implementation chooses to enforce these at the encoding layer.
Decoders MAY treat as either encoding errors or semantic errors (per implementation policy):
- mismatches between
statusandsummaryinvariants (e.g.status = OKbutsummary.kind != NONEorsummary.status_code != 0); - inconsistencies between
store_failurepresence andcore_result.status/core_result.summary.kind.
Mapping from encoding errors to external error codes (e.g.
ERR_PEL_RESULT_ENC_INVALID) is implementation-specific. These are strictly
encoding-layer issues; store failures, scheme errors, and runtime failures are
represented inside ExecutionResultValue and StoreFailure and handled by
PEL/1-CORE and PEL/1-SURF.
8. Streaming & Implementation Notes
Encoders and decoders MUST support single-pass operation:
-
Encoding:
- Encoders MUST be able to generate
ResultBytesin a single forward pass over the logicalSurfaceExecutionResult, assuming the structure is known in memory (or the list counts are precomputed). - They MAY need to compute
input_ref_count,output_ref_count, anddiag_countbefore emitting the corresponding lists.
- Encoders MUST be able to generate
-
Decoding:
- Decoders MUST be able to decode
ResultBytesin a single forward pass, with no backtracking. - All length prefixes appear before their content; no speculative reads are required.
- Decoders MUST be able to decode
For large results:
- Implementations MAY stream lists (e.g.
input_refs,output_refs,diagnostics) to consumers as they decode them. - Implementations MUST ensure that any observable behavior (including error reporting and any reconstructed value) is independent of I/O chunking or buffer boundaries.
Implementations may also:
- compute hashes incrementally over
ArtifactBytes(for result Artifacts), - pipeline decoding of
ResultBytesdirectly into downstream consumers (e.g. inspection, provenance edge generators) without materializing the entire object in memory, as long as the logical value is representable.
9. Conformance
An implementation is ENC/PEL1-RESULT/1–conformant if it:
-
Implements the layouts exactly
- Encodes and decodes
ExecutionResultValueBytes,StoreFailureBytes, andResultBytesexactly as defined in §4.2, §4.3, and §4.4. - Uses the correct field ordering, integer widths, list framing, and presence flags.
- Encodes and decodes
-
Uses canonical sub-encodings
- Embeds
Referencevalues usingEncodedRefover canonicalReferenceBytes(ENC/ASL1-CORE v1). - Encodes
DiagnosticEntryusingDiagnosticEntryByteswithBlob32as in §4.1. - Encodes
StoreFailureusingStoreFailureBytesas in §4.3.
- Embeds
-
Preserves injectivity and stability
- Ensures distinct logical
SurfaceExecutionResultvalues produce distinctResultBytes. - Ensures distinct logical
ExecutionResultValuevalues produce distinctExecutionResultValueBytes. - Ensures the same logical values always encode to the same bytes (no configuration or environment affecting layout).
- Ensures distinct logical
-
Binds to result Artifacts correctly
-
When forming surface result Artifacts, sets:
Artifact.bytes = ResultBytes Artifact.type_tag = TYPE_TAG_PEL1_RESULT_1 -
Uses
ENC/ASL1-CORE v1andHASH/ASL1for identity derivation.
-
-
Respects layering
- Does not depend on TGK, CIL, FER, FCT, or OI to encode or decode result values.
- Does not reinterpret or override
ExecutionResultValueorStoreFailuresemantics beyond what is specified inPEL/1-COREandPEL/1-SURF.
Everything else — storage configuration, trace persistence, provenance edges, receipts, facts, overlays — is outside the scope of this encoding profile, provided it does not contradict the rules above.
10. Informative Example
This example illustrates field layout only. Values and hex are illustrative, not normative test vectors.
Consider a simple run with:
-
pel1_version = 1 -
scheme_ref = S -
program_ref = P -
Inputs:
input_refs = [I0, I1] -
Outputs:
output_refs = [O0] -
params_ref = absent -
store_failure = absent -
trace_ref = T -
Inline
core_result : ExecutionResultValue:pel1_version = 1 status = OK scheme_ref = S summary.kind = NONE summary.status_code = 0 diagnostics = [] // empty
Then ResultBytes are:
pel1_version = 0001 ; u16
scheme_ref = EncodedRef(S)
program_ref = EncodedRef(P)
input_ref_count = 00000002 ; 2
input_refs = EncodedRef(I0)
EncodedRef(I1)
output_ref_count = 00000001 ; 1
output_refs = EncodedRef(O0)
has_params_ref = 00 ; none
has_store_failure = 00 ; none
has_trace_ref = 01
trace_ref = EncodedRef(T)
; Inline core_result (ExecutionResultValueBytes)
pel1_version = 0001
status = 00 ; OK (ExecutionStatus)
scheme_ref = EncodedRef(S)
summary_kind = 00 ; NONE (ExecutionErrorKind)
summary_status_code = 00000000 ; 0
diag_count = 00000000 ; no diagnostics
; (no DiagnosticEntryBytes follow)
Where each EncodedRef(X) is:
ref_len(X) (u32) || ReferenceBytes(X)
with ReferenceBytes(X) = hash_id (u16) + digest bytes, per
ENC/ASL1-CORE v1.
All conformant encoders MUST produce the same ResultBytes for this logical
surface result value; all conformant decoders MUST reconstruct the same logical
value from those bytes.
Document History
- 0.3.0 (2025-11-17): Promoted the ExecutionResult encoding profile to Approved status and pinned PH06 vectors/tests to this canonical layout.
- 0.2.3 (2025-11-17): Aligned logical shape and encoding with
PEL/1-SURF v0.2.1(addedStoreFailureencoding, removedexec_result_ref, renamed inlineresult_valuetocore_result). - 0.2.2 (2025-11-16): Tightened consistency rules between surface header and inline
ExecutionResultValue, clarified PEL vs encoding versioning, and strengthened decoding recommendations for out-of-range status values. - 0.2.1 (2025-11-16): Aligned
ExecutionResultValueBytesfield order withPEL/1-CORE, clarified flag semantics for unsupported optional fields, and added an evolution note for future extensions. - 0.2.0 (2025-11-16): Integrated earlier CODEx draft ideas; defined explicit
ExecutionResultValueBytes, aligned diagnostics encoding withENC/PEL-TRACE-DAG/1, and fixed fullResultByteslayout withEncodedRef/u32list framing. - 0.1.0 (2025-11-16): Initial skeleton for
ENC/PEL1-RESULT/1(high-level scope, dependencies, and rough layout outline).