| 273 | } |
| 274 | |
| 275 | func BuildExplain(db *sql.DB, opts ExplainOptions) (ExplainManifest, error) { |
| 276 | target, err := explainTarget(opts) |
| 277 | if err != nil { |
| 278 | return ExplainManifest{}, err |
| 279 | } |
| 280 | manifest := ExplainManifest{ |
| 281 | SchemaVersion: "agentprovenance.explain/v1", |
| 282 | Target: target, |
| 283 | Query: explainQueryFromOptions(opts), |
| 284 | } |
| 285 | switch target.Type { |
| 286 | case "file": |
| 287 | targetID := "workspace_file/" + target.File |
| 288 | diff, err := BuildDiffFile(db, target.Run, target.File) |
| 289 | if err != nil { |
| 290 | return ExplainManifest{}, err |
| 291 | } |
| 292 | blame, err := BuildBlameFile(db, target.Run, target.File) |
| 293 | if err != nil { |
| 294 | return ExplainManifest{}, err |
| 295 | } |
| 296 | events, err := runtimeFileEvents(db, target.Run, target.File) |
| 297 | if err != nil { |
| 298 | return ExplainManifest{}, err |
| 299 | } |
| 300 | manifest.FileDiff = &diff |
| 301 | manifest.FileBlame = &blame |
| 302 | manifest.RuntimeEvents = explainEvents(target.Run, events) |
| 303 | manifest.RuntimeEdges, err = runtimeEdgesForFile(db, target.Run, target.File) |
| 304 | if err != nil { |
| 305 | return ExplainManifest{}, err |
| 306 | } |
| 307 | if err := enrichExplain(db, &manifest, target.Run, targetID, explainIDsFromFile(diff, blame, events), manifest.Query.Depth, manifest.Query.Limit); err != nil { |
| 308 | return ExplainManifest{}, err |
| 309 | } |
| 310 | manifest.Summary = append(manifest.Summary, |
| 311 | fmt.Sprintf("file %s has %d attempt diff entries", target.File, len(diff.Attempts)), |
| 312 | fmt.Sprintf("file %s has %d blame entries", target.File, len(blame.Entries)), |
| 313 | fmt.Sprintf("file %s has %d runtime file events", target.File, len(events)), |
| 314 | ) |
| 315 | default: |
| 316 | edgeID := target.ID |
| 317 | if target.Type == "event" { |
| 318 | edgeID = "runtime_event/" + target.ID |
| 319 | } else if target.Type == "risk" { |
| 320 | edgeID = "policy_decision/" + target.ID |
| 321 | } |
| 322 | runID, err := runIDForExplainTarget(db, target) |
| 323 | if err != nil { |
| 324 | return ExplainManifest{}, err |
| 325 | } |
| 326 | target.Run = runID |
| 327 | manifest.Target.Run = runID |
| 328 | ids, err := resolveExplainIDs(db, target) |
| 329 | if err != nil { |
| 330 | return ExplainManifest{}, err |
| 331 | } |
| 332 | if target.Type == "risk" && ids["event_id"] != "" { |