| 1 | package evidence |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "strings" |
| 6 | ) |
| 7 | |
| 8 | // MatchStep resolves a step citation against the existing task list. |
| 9 | func MatchStep(step string, todos []TodoItem) (TodoStepMatch, bool) { |
| 10 | m := matchTodoStep(step, todos) |
| 11 | return m, m.Found |
| 12 | } |
| 13 | |
| 14 | // ReplayTodoList leaves new model states intact and reads legacy lists with |
| 15 | // their original serial normalization. Neither path rewrites stored messages. |
| 16 | func ReplayTodoList(todos []TodoItem, output string) []TodoItem { |
| 17 | var result struct { |
| 18 | Todos []struct { |
| 19 | Content string `json:"content"` |
| 20 | Status string `json:"status"` |
| 21 | } `json:"todos"` |
| 22 | } |
| 23 | if json.Unmarshal([]byte(output), &result) == nil && result.Todos != nil { |
| 24 | canonical := make([]TodoItem, len(result.Todos)) |
| 25 | for i, item := range result.Todos { |
| 26 | canonical[i] = TodoItem{Content: item.Content, Status: item.Status} |
| 27 | } |
| 28 | return canonical |
| 29 | } |
| 30 | if strings.HasPrefix(output, "Model task list updated:") { |
| 31 | return append([]TodoItem(nil), todos...) |
| 32 | } |
| 33 | return NormalizeSerialTodos(todos) |
| 34 | } |
| 35 | |
| 36 | const ModelCompletionDeclarationPrefix = "Model completion declaration recorded for todo " |
| 37 | |
| 38 | // ReplayTodoCompletion preserves legacy serial updates while replaying new |
| 39 | // declarations exactly as they happened, without advancing an unrelated item. |
| 40 | func ReplayTodoCompletion(todos []TodoItem, index int, output string) bool { |
| 41 | if strings.HasPrefix(output, ModelCompletionDeclarationPrefix) { |
| 42 | return CompleteDeclaredTodo(todos, index) |
| 43 | } |
| 44 | return AdvanceSerialTodo(todos, index) |
| 45 | } |
| 46 | |
| 47 | // CompleteDeclaredTodo updates only the selected item, without advancing others. |
| 48 | func CompleteDeclaredTodo(todos []TodoItem, index int) bool { |
| 49 | if index < 0 || index >= len(todos) || todos[index].Status == "completed" { |
| 50 | return false |
| 51 | } |
| 52 | todos[index].Status = "completed" |
| 53 | return true |
| 54 | } |
| 55 |