// Package outcomes contains processing facts shared by proposal generation, // validation, and orchestration. Presentation and filesystem concerns live elsewhere. package outcomes // OperationKind identifies one logical model operation. Validation input failures // occur before a model call and therefore have no batch index. type OperationKind string const ( OperationProposal OperationKind = "proposal" OperationValidation OperationKind = "validation" OperationValidationInput OperationKind = "validation_input" ) // Reference is the stable processing identity of an operation. Proposal indices // are scoped to a module instance, while batch indices are local to a validator // invocation within one section. type Reference struct { ModuleKey string `json:"module_key"` ModuleInstance string `json:"module_instance"` SectionIndex int `json:"section_index"` Kind OperationKind `json:"operation"` ValidatorName string `json:"validator_name,omitempty"` ValidatorOrder *int `json:"validator_order,omitempty"` BatchIndex *int `json:"batch_index,omitempty"` } // ExecutionCounts describe one terminal structured-client call. Available is // false when an external client provides no execution facts; zero is then unknown. type ExecutionCounts struct { Available bool `json:"available"` ProviderAttempts int `json:"provider_attempts"` TransientRetries int `json:"transient_retries"` StructuralRepairs int `json:"structural_repairs"` RetriesExhausted bool `json:"retries_exhausted"` HTTPStatus *int `json:"http_status,omitempty"` } // ReasonCode is a fixed, safe explanation category. Raw provider errors and // prompt content are never stored in an operation outcome. type ReasonCode string const ( ReasonOperationTimeout ReasonCode = "operation_timeout" ReasonCapacityExceeded ReasonCode = "capacity_exceeded" ReasonTransportFailed ReasonCode = "transport_failed" ReasonProviderResponseInvalid ReasonCode = "provider_response_invalid" ReasonProviderFailed ReasonCode = "provider_failed" ReasonInvalidOutputExhausted ReasonCode = "invalid_output_exhausted" ReasonInvalidOutput ReasonCode = "invalid_output" ReasonValidationInputTooLarge ReasonCode = "validation_input_too_large" ReasonValidationDecisionsInvalid ReasonCode = "validation_decisions_invalid" ReasonInputInvalid ReasonCode = "input_invalid" ReasonSetupFailure ReasonCode = "setup_failure" ReasonCanceled ReasonCode = "canceled" ReasonInternalFailure ReasonCode = "internal_failure" ) type RecoveryReason string const ( RecoveryOutputRepaired RecoveryReason = "output_repaired" RecoveryServiceRecovered RecoveryReason = "service_recovered" RecoveryProposalsFiltered RecoveryReason = "proposals_filtered" RecoveryValidationDecisionsFiltered RecoveryReason = "validation_decisions_filtered" ) // FilteredProposal attributes a defective response item to its proposal identity. // Ordinary editorial rejection is a decision, not a filtered proposal. type FilteredProposal struct { ProposalIndex int `json:"proposal_index"` Reason ReasonCode `json:"reason"` Count int `json:"count"` } // Operation is a compact terminal outcome. A successful operation may have one // recovery with several reasons. A failed operation never has recovery reasons. type Operation struct { Reference Reference `json:"reference"` Counts ExecutionCounts `json:"counts"` Succeeded bool `json:"succeeded"` FailureReason ReasonCode `json:"failure_reason,omitempty"` RecoveryReasons []RecoveryReason `json:"recovery_reasons,omitempty"` ProposalIndices []int `json:"proposal_indices,omitempty"` Filtered []FilteredProposal `json:"filtered,omitempty"` } type WorkState string const ( WorkNotStarted WorkState = "not_started" WorkCompleted WorkState = "completed" WorkInterrupted WorkState = "interrupted" ) // ExecutionRecoveries classifies execution counts; callers decide whether their // operation succeeded before recording these reasons. func ExecutionRecoveries(counts ExecutionCounts) []RecoveryReason { var reasons []RecoveryReason if counts.StructuralRepairs > 0 { reasons = append(reasons, RecoveryOutputRepaired) } if counts.TransientRetries > 0 { reasons = append(reasons, RecoveryServiceRecovered) } return reasons }