| 1 | package readcoord |
| 2 | |
| 3 | import "reasonix/internal/tool" |
| 4 | |
| 5 | // Associate runs after the reader captured its source. It reuses a requirement |
| 6 | // on that exact source without reopening completed coverage or resetting budgets. |
| 7 | // The caller owns run/session isolation and serializes this with Observe. |
| 8 | func (c *Coordinator) Associate(env tool.ReadResultEnvelope) string { |
| 9 | if env.Source.Snapshot == "" || env.Source.Identity == "" { |
| 10 | return env.ReadID |
| 11 | } |
| 12 | c.mu.Lock() |
| 13 | defer c.mu.Unlock() |
| 14 | var selected *Obligation |
| 15 | for _, ob := range c.byKey { |
| 16 | if ob.Source != env.Source || ob.Stop != nil || ob.State == StateCancelled { |
| 17 | continue |
| 18 | } |
| 19 | if ob.Key == env.ReadID { |
| 20 | selected = ob |
| 21 | break |
| 22 | } |
| 23 | if selected == nil || ob.Key < selected.Key { |
| 24 | selected = ob |
| 25 | } |
| 26 | } |
| 27 | if selected == nil { |
| 28 | return env.ReadID |
| 29 | } |
| 30 | req := requirementFor(env) |
| 31 | if req.WholeFile { |
| 32 | selected.Requirement = req |
| 33 | } else if !selected.Requirement.WholeFile && req.Intent == tool.ReadIntentRange { |
| 34 | selected.Requirement.Intent = tool.ReadIntentRange |
| 35 | selected.Requirement.Ranges = Normalize(append(selected.Requirement.Ranges, req.Ranges...)) |
| 36 | } |
| 37 | if selected.State == StateSatisfied && evaluate(selected, env) != StateSatisfied { |
| 38 | selected.State = StateFetching |
| 39 | } |
| 40 | return selected.Key |
| 41 | } |
| 42 |