Take the indexer's verdict on a manifest instead of judging it in the controller

Issue 1585, S18 (ADR 0578 §3, §6): a done key's manifest is decoded leniently and the verdict read from the
indexer's state; a refused one is held and named, an unread word set aside and named, never a wait. The
module check command, which judged files with no mesh and which nothing calls any more, goes with its tests.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-01 02:07:44 +01:00
parent dc90b3f5bd
commit 8b4d536a11
20 changed files with 102 additions and 887 deletions
+25
View File
@@ -255,6 +255,31 @@ func (r Reader) Manifest(ctx context.Context, digest string) (delivery.Manifest,
return m, nil
}
// Verdict is the indexer's verdict on the manifest of digest (ADR 0578 §3), or nil when it holds none (no bucket yet,
// no key): a reader takes that as accepted (delivery.TakeManifestVerdict).
func (r Reader) Verdict(ctx context.Context, digest string) (*delivery.ManifestVerdict, error) {
key, err := delivery.VerdictsKey(digest)
if err != nil {
return nil, err
}
kv, err := r.bucket(ctx, delivery.VerdictsBucket)
if err != nil || kv == nil {
return nil, err
}
e, err := kv.Get(ctx, key)
if errors.Is(err, jetstream.ErrKeyNotFound) {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("the verdict on %s: %w", short(digest), err)
}
v, err := delivery.DecodeManifestVerdict(e.Value())
if err != nil {
return nil, fmt.Errorf("the verdict on %s is not read: %w", short(digest), err)
}
return &v, nil
}
// Watch calls wake with the module of every key the builder or the indexer writes from now on, until ctx ends: what
// wakes a plan waiting on a key, with no timer (ADR 0501; the R4e context's A7). A bucket not there yet is watched once
// it is: the watch looks again each time wake would have been called for the other bucket, and at every retry.