Implement generated artifact handoff and provenance

This commit is contained in:
2026-07-21 21:39:23 +00:00
parent afb7ed3cf1
commit 22d4f29670
12 changed files with 749 additions and 85 deletions

View File

@@ -30,6 +30,7 @@ type SerializedArtifact struct {
// SerializedOutput associates a domain-neutral artifact with the pipeline
// operation that produced it. Provenance remains outside codec-owned bytes.
type SerializedOutput struct {
StepID string `json:"step_id,omitempty"`
LaneID string `json:"lane_id"`
NormalizerKey string `json:"normalizer_key"`
SourceID string `json:"source_id,omitempty"`

View File

@@ -190,14 +190,64 @@ type ReferenceOrigin struct {
URI string `json:"uri,omitempty"`
}
// ReferenceProducer identifies the operation that produced a generated
// reference. It contains provenance only; referenced bytes remain in Content.
type ReferenceProducer struct {
PipelineID string `json:"pipeline_id,omitempty"`
StepID string `json:"step_id,omitempty"`
LaneID string `json:"lane_id,omitempty"`
ModuleKey string `json:"module_key,omitempty"`
}
type ReferenceItem struct {
SlotName string `json:"slot_name"`
MediaType string `json:"media_type,omitempty"`
Content []byte `json:"-"`
Digest string `json:"digest,omitempty"`
Origin ReferenceOrigin `json:"origin"`
SizeBytes int64 `json:"size_bytes,omitempty"`
BindingSource string `json:"binding_source,omitempty"`
SlotName string `json:"slot_name"`
MediaType string `json:"media_type,omitempty"`
Content []byte `json:"-"`
Digest string `json:"digest,omitempty"`
Origin ReferenceOrigin `json:"origin"`
SizeBytes int64 `json:"size_bytes,omitempty"`
BindingSource string `json:"binding_source,omitempty"`
ArtifactKind ArtifactKind `json:"artifact_kind,omitempty"`
ArtifactSchema ArtifactSchema `json:"artifact_schema,omitempty"`
Producer ReferenceProducer `json:"producer,omitempty"`
}
func CloneReferenceItem(item ReferenceItem) ReferenceItem {
item.Content = append([]byte(nil), item.Content...)
item.ArtifactSchema = CloneArtifactSchema(item.ArtifactSchema)
return item
}
func (item ReferenceItem) MarshalJSON() ([]byte, error) {
type referenceItemJSON struct {
SlotName string `json:"slot_name"`
MediaType string `json:"media_type,omitempty"`
Digest string `json:"digest,omitempty"`
Origin ReferenceOrigin `json:"origin"`
SizeBytes int64 `json:"size_bytes,omitempty"`
BindingSource string `json:"binding_source,omitempty"`
ArtifactKind ArtifactKind `json:"artifact_kind,omitempty"`
ArtifactSchema *ArtifactSchema `json:"artifact_schema,omitempty"`
Producer *ReferenceProducer `json:"producer,omitempty"`
}
encoded := referenceItemJSON{
SlotName: item.SlotName,
MediaType: item.MediaType,
Digest: item.Digest,
Origin: item.Origin,
SizeBytes: item.SizeBytes,
BindingSource: item.BindingSource,
ArtifactKind: item.ArtifactKind,
}
if item.ArtifactSchema.ID != "" || item.ArtifactSchema.Name != "" || item.ArtifactSchema.Version != "" || len(item.ArtifactSchema.JSONSchema) > 0 {
schema := CloneArtifactSchema(item.ArtifactSchema)
encoded.ArtifactSchema = &schema
}
if item.Producer.PipelineID != "" || item.Producer.StepID != "" || item.Producer.LaneID != "" || item.Producer.ModuleKey != "" {
producer := item.Producer
encoded.Producer = &producer
}
return json.Marshal(encoded)
}
type ResolvedReferenceSlot struct {
@@ -261,6 +311,7 @@ type OutputEncoder interface {
type RejectedOutput struct {
Stage string `json:"stage"`
StepID string `json:"step_id,omitempty"`
LaneID string `json:"lane_id,omitempty"`
ModuleKey string `json:"module_key,omitempty"`
ChunkID string `json:"chunk_id,omitempty"`