// Runs the debt projection over a captured event log and prints one row per // item, so two builds can be compared on identical input. The point of the // comparison is the signature fix: cross-task incidents must collapse into one // item while genuinely different failures stay separate. package main import ( "encoding/json" "fmt" "os" "sort" "orchestra/internal/domain" "orchestra/internal/operations" "orchestra/internal/store" ) func main() { b, err := os.ReadFile(os.Args[1]) if err != nil { panic(err) } var events []domain.Event if err := json.Unmarshal(b, &events); err != nil { panic(err) } ledger := store.ProjectDebt(events) eligible := map[string]operations.DebtCandidate{} for _, c := range operations.EligibleDebt(ledger) { eligible[c.Item.ID] = c } rows := make([]map[string]any, 0, len(ledger.Items)) for _, item := range ledger.Items { tasks := map[string]bool{} intensity := 0 for _, o := range item.Observations { if o.TaskID != "" { tasks[o.TaskID] = true } intensity += o.Repeats } row := map[string]any{ "signature": item.ID, "class": string(item.Class), "recurrence": len(item.Observations), "intensity": intensity, "tasks": len(tasks), "eligible": false, "reasons": []string{}, } check := operations.CheckDebtEligibility(item) row["eligible"] = check.Eligible row["reasons"] = check.Reasons _ = eligible rows = append(rows, row) } sort.Slice(rows, func(i, j int) bool { return rows[i]["signature"].(string) < rows[j]["signature"].(string) }) out, _ := json.MarshalIndent(map[string]any{"items": rows, "gaps": ledger.Gaps}, "", " ") fmt.Println(string(out)) }