Consolidate analyze session execution state
This commit is contained in:
@@ -142,25 +142,7 @@ func (analyzeStage) Run(ctx context.Context, env *Env, m *manifest.Manifest) (*S
|
||||
return nil, fmt.Errorf("analyze: scriptorium adapter is required")
|
||||
}
|
||||
|
||||
logs := []string{}
|
||||
generatedConfigs := []string{}
|
||||
artifactMetadata := make([]map[string]any, 0, len(workPlan.ExecutionOrder))
|
||||
reusedArtifacts := []map[string]any{}
|
||||
reusedSeen := map[string]struct{}{}
|
||||
sessionRecords := manifest.CloneAnalyzeArtifactCollection(workPlan.ProjectedRecords)
|
||||
priorCurrentRecords := make(map[string]manifest.AnalyzeArtifactRecord)
|
||||
for _, item := range reconciliation.Ordered {
|
||||
if item.Stored != nil && item.Stored.Status == manifest.AnalyzeArtifactCurrent {
|
||||
priorCurrentRecords[item.Key] = *item.Stored
|
||||
}
|
||||
}
|
||||
currentKeys := make(map[string]struct{}, len(workPlan.ExecutionOrder)+len(workPlan.ReusedCurrent))
|
||||
for _, item := range workPlan.ExecutionOrder {
|
||||
currentKeys[item.Key] = struct{}{}
|
||||
}
|
||||
for _, item := range workPlan.ReusedCurrent {
|
||||
currentKeys[item.Key] = struct{}{}
|
||||
}
|
||||
state := newAnalyzeExecutionState(execution, workPlan, reconciliation)
|
||||
|
||||
for _, item := range workPlan.ExecutionOrder {
|
||||
artifactCfg := env.Config.Pipeline.Scriptorium.Artifacts[item.Key]
|
||||
@@ -171,158 +153,18 @@ func (analyzeStage) Run(ctx context.Context, env *Env, m *manifest.Manifest) (*S
|
||||
)
|
||||
if err != nil {
|
||||
executionErr := fmt.Errorf("analyze: compute execution fingerprint for artifact %q: %w", item.Key, err)
|
||||
return failedAnalyzeResult(
|
||||
execution,
|
||||
item,
|
||||
artifactCfg,
|
||||
"",
|
||||
executionErr,
|
||||
sessionRecords,
|
||||
), executionErr
|
||||
return state.failedResult(item, artifactCfg, "", executionErr), executionErr
|
||||
}
|
||||
priorRecord, hadPriorRecord := priorCurrentRecords[item.Key]
|
||||
plan := analyzeArtifactExecutionPlan{Name: item.Key, Cfg: artifactCfg}
|
||||
artifactResult, err := executeAnalyzeArtifact(ctx, execution, plan)
|
||||
if err != nil {
|
||||
return failedAnalyzeResult(
|
||||
execution,
|
||||
item,
|
||||
artifactCfg,
|
||||
fingerprint,
|
||||
err,
|
||||
sessionRecords,
|
||||
), err
|
||||
return state.failedResult(item, artifactCfg, fingerprint, err), err
|
||||
}
|
||||
|
||||
logs = append(logs, artifactResult.Logs...)
|
||||
generatedConfigs = append(generatedConfigs, artifactResult.GeneratedConfigs...)
|
||||
if origin, ok := analyzeArtifactOrigin(execution, plan.Name); ok {
|
||||
artifactResult.Metadata["family"] = origin.Family
|
||||
artifactResult.Metadata["character_id"] = origin.CharacterID
|
||||
}
|
||||
artifactMetadata = append(artifactMetadata, artifactResult.Metadata)
|
||||
for _, reused := range artifactResult.ReusedArtifacts {
|
||||
sourceID, _ := reused["source_id"].(string)
|
||||
path, _ := reused["path"].(string)
|
||||
key := sourceID + "|" + path
|
||||
if _, exists := reusedSeen[key]; exists {
|
||||
continue
|
||||
}
|
||||
reusedSeen[key] = struct{}{}
|
||||
reusedArtifacts = append(reusedArtifacts, reused)
|
||||
}
|
||||
|
||||
record, err := currentAnalyzeArtifactRecord(
|
||||
execution,
|
||||
plan,
|
||||
fingerprint,
|
||||
artifactResult,
|
||||
)
|
||||
if err != nil {
|
||||
recordErr := fmt.Errorf("analyze: record artifact %q: %w", plan.Name, err)
|
||||
return failedAnalyzeResult(
|
||||
execution,
|
||||
item,
|
||||
artifactCfg,
|
||||
fingerprint,
|
||||
recordErr,
|
||||
sessionRecords,
|
||||
), recordErr
|
||||
}
|
||||
sessionRecords[plan.Name] = record
|
||||
|
||||
sourceID, ok := runtimeCatalog.SourceIDForConfiguredKey(plan.Name)
|
||||
if !ok {
|
||||
catalogErr := fmt.Errorf("analyze: source id not found for artifact %q", plan.Name)
|
||||
return failedAnalyzeResult(
|
||||
execution, item, artifactCfg, fingerprint, catalogErr,
|
||||
sessionRecords,
|
||||
), catalogErr
|
||||
}
|
||||
if err := runtimeCatalog.MarkAvailableGeneratedEvidence(
|
||||
sourceID,
|
||||
artifactResult.Output.AbsolutePath,
|
||||
record.ProducerRunID,
|
||||
record.Output.Checksum,
|
||||
record.OutputSize,
|
||||
record.Output.Contract,
|
||||
); err != nil {
|
||||
catalogErr := fmt.Errorf("analyze: mark generated artifact %q available: %w", sourceID, err)
|
||||
return failedAnalyzeResult(
|
||||
execution, item, artifactCfg, fingerprint, catalogErr,
|
||||
sessionRecords,
|
||||
), catalogErr
|
||||
}
|
||||
if !hadPriorRecord || !sameAnalyzeOutputIdentity(priorRecord, record) {
|
||||
staleUnscheduledAnalyzeDependents(
|
||||
env.Config.Pipeline.Scriptorium.Artifacts,
|
||||
plan.Name,
|
||||
currentKeys,
|
||||
sessionRecords,
|
||||
)
|
||||
if err := state.acceptArtifact(plan, fingerprint, artifactResult); err != nil {
|
||||
return state.failedResult(item, artifactCfg, fingerprint, err), err
|
||||
}
|
||||
}
|
||||
|
||||
metadata := map[string]any{
|
||||
"stage": "analyze",
|
||||
"selected_artifacts": append([]string(nil), workPlan.ExplicitTargets...),
|
||||
"executed_artifacts": analyzePlanKeysForMetadata(workPlan.ExecutionOrder),
|
||||
"reused_current": analyzePlanKeysForMetadata(workPlan.ReusedCurrent),
|
||||
"generated_artifacts": artifactMetadata,
|
||||
"reused_artifacts": reusedArtifacts,
|
||||
"artifact_count": len(artifactMetadata),
|
||||
"reused_artifact_count": len(reusedArtifacts),
|
||||
}
|
||||
if len(artifactMetadata) == 1 {
|
||||
for k, v := range artifactMetadata[0] {
|
||||
metadata[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return &StageResult{
|
||||
Logs: dedupeAndSortPaths(logs),
|
||||
GeneratedConfigs: dedupeAndSortPaths(generatedConfigs),
|
||||
Metadata: metadata,
|
||||
AnalyzeState: &AnalyzeStateProjection{
|
||||
Session: sessionRecords,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func failedAnalyzeResult(
|
||||
execution analyzeExecutionContext,
|
||||
item analyzePlanItem,
|
||||
artifactCfg config.ScriptoriumArtifactConfig,
|
||||
fingerprint string,
|
||||
cause error,
|
||||
sessionRecords map[string]manifest.AnalyzeArtifactRecord,
|
||||
) *StageResult {
|
||||
record := manifest.AnalyzeArtifactRecord{
|
||||
Key: item.Key,
|
||||
Status: manifest.AnalyzeArtifactFailed,
|
||||
Dependencies: normalizedAnalyzeDependencyKeys(artifactCfg.DependsOn),
|
||||
ProducerRunID: analyzeProducerRunID(execution),
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
Error: NonResumable(cause.Error()).Reason,
|
||||
}
|
||||
if origin, ok := analyzeArtifactOrigin(execution, item.Key); ok {
|
||||
record.Family = origin.Family
|
||||
record.CharacterID = origin.CharacterID
|
||||
}
|
||||
if fingerprint != "" {
|
||||
record.FingerprintVersion = manifest.AnalyzeFingerprintContractVersion
|
||||
record.Fingerprint = fingerprint
|
||||
}
|
||||
if artifactCfg.PromptID != "" || artifactCfg.ProfileID != "" {
|
||||
record.Scriptorium = &manifest.AnalyzeArtifactProvenance{
|
||||
PromptID: artifactCfg.PromptID, ProfileID: artifactCfg.ProfileID,
|
||||
}
|
||||
}
|
||||
sessionRecords[item.Key] = record
|
||||
staleAnalyzeDependents(artifactCfgMap(execution), item.Key, sessionRecords)
|
||||
return &StageResult{AnalyzeState: &AnalyzeStateProjection{
|
||||
Session: manifest.CloneAnalyzeArtifactCollection(sessionRecords),
|
||||
}}
|
||||
return state.successResult(), nil
|
||||
}
|
||||
|
||||
func analyzeArtifactOrigin(execution analyzeExecutionContext, key string) (config.ArtifactFamilyMemberOrigin, bool) {
|
||||
@@ -464,7 +306,7 @@ func staleAnalyzeDependentClosure(
|
||||
if eligible != nil && !eligible(key) {
|
||||
continue
|
||||
}
|
||||
staleProjectedAnalyzeRecord(records, key)
|
||||
staleAnalyzeRecord(records, key)
|
||||
queue = append(queue, reverse[key]...)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user