Fail empty ideas jobs, clear ideas on failure, show each idea as it grounds
CI / ci (push) Successful in 5m24s
CI / ci (pull_request) Successful in 6m11s

- A run that keeps no idea fails with no_ideas_found instead of ending
  done with an empty list.
- Before an ideas job fails it republishes its result with no ideas, so
  GET /api/v1/jobs/{id} never shows ideas on a failed job, even ones a
  previous grounding round already published.
- Each idea is published as soon as its grounding finishes, placed in the
  model's order. recipes.GroundEach reports items as they finish;
  GroundMany is rebuilt on it with unchanged semantics.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 19:22:51 -04:00
co-authored by Claude Opus 5.5
parent b566be7ddc
commit 4146f31275
6 changed files with 325 additions and 68 deletions
+14 -4
View File
@@ -23,12 +23,16 @@ import (
)
// Search is a recipes.SearchSource and recipes.SearchProvider answering
// each query from Results. Err, when set, fails every search. Gate, when
// set, makes every search wait for it to close.
// each query from Results. Err, when set, fails every search, and Fail
// fails the searches for its queries. Gate, when set, makes every search
// wait for it to close, and Gates makes the searches for its queries wait
// for theirs.
type Search struct {
Results map[string][]recipes.Candidate
Err error
Fail map[string]error
Gate chan struct{}
Gates map[string]chan struct{}
mu sync.Mutex
queries []string
@@ -40,9 +44,12 @@ func (s *Search) Search(ctx context.Context, query string, n int) ([]recipes.Can
s.mu.Lock()
s.queries = append(s.queries, query)
s.mu.Unlock()
if s.Gate != nil {
for _, gate := range []chan struct{}{s.Gate, s.Gates[query]} {
if gate == nil {
continue
}
select {
case <-s.Gate:
case <-gate:
case <-ctx.Done():
return nil, ctx.Err()
}
@@ -50,6 +57,9 @@ func (s *Search) Search(ctx context.Context, query string, n int) ([]recipes.Can
if s.Err != nil {
return nil, s.Err
}
if err := s.Fail[query]; err != nil {
return nil, err
}
c := s.Results[query]
return c[:min(n, len(c))], nil
}