Surface lane-specific throughput on IngestResult and ingestSummary so the
morning digest can show external-watchlist yield without parsing every
sidecar. Update RFC 0001 Decision Record (Proposal 2 first slice landed)
and dream-run-contract.md (name both registered generators).
Changes:
- cli/internal/overnight/ingest.go: add IngestResult.ExternalWatchlistEmitted
field; recordFindingGeneratorResult increments it from sidecar.NewCandidateCount
when the sidecar's Generator name matches externalWatchlistGeneratorName.
Mirrors the pattern used for mine-findings (MineFindingsNew).
- cli/internal/overnight/loop.go: ingestSummary surfaces the counter under
"external_watchlist_emitted".
- cli/internal/overnight/loop_test.go: extend TestIngestSummary to cover the
new field — populates IngestResult with ExternalWatchlistEmitted=3 and
asserts the summary key is present, value matches, and total key count
rises 11 -> 12.
- docs/rfcs/0001-finding-generator-parallelism.md: bump status to "Proposal 1
+ Proposal 2 first slice implemented"; rewrite Decision Ask #3 from
deferred to landed with file:line citations for the generator,
registration, dedup_key fix, PROGRAM.md scope, and fitness counter.
Network fetch / dynamic dedup / goal_weight remain explicitly deferred.
- docs/contracts/dream-run-contract.md: name both registered generators
(mine-findings + external-watchlist) in the INGEST stage description.
Verification:
- cd cli && go test ./internal/overnight/... ./internal/rpi/... -> all PASS
- bash scripts/check-contract-compatibility.sh -> 0 failures
Closes the implementation of RFC 0001 Proposal 2 Wave 4. Subsequent
expansion (HTTP watchlist, dynamic dedup ranking) is a separate slice.
Proposal 2 (external watchlist generator lane) needs the queue selector to
hold candidates that should never auto-execute. RFC 0001 Decision Ask #2
asked whether status / requires / dedup_key should be first-class schema
fields before external generators land. Approved: yes for these three;
goal_weight stays deferred until a selector ranking consumer exists.
Changes:
- cli/internal/rpi/types.go: add Status, Requires, DedupKey to NextWorkItem
with omitempty so existing producers keep round-tripping unchanged.
- cli/internal/rpi/helpers.go: add IsQueueItemHeldForReview; route
IsQueueItemSelectable through it. Items with status=proposed, any
non-empty requires entry, or an unrecognized status are held. status=ready
and status="" remain selectable for backward compatibility. Unknown
statuses fail safe (held), so a future producer can't accidentally bypass
the gate by writing a typo.
- cli/internal/rpi/types_test.go: new round-trip + omitempty tests for the
three fields, plus selector contract coverage (status=proposed alone,
requires=human-review alone, both together, unknown gates).
- docs/contracts/next-work.schema.md: bump schema_version 1.3 -> 1.4,
document the three fields and their lifecycle invariant (selectable iff
claim_status=available AND status in {ready, ""} AND requires empty).
- docs/rfcs/0001-finding-generator-parallelism.md: update Decision Record —
Decision Ask #2 resolved (status/requires/dedup_key first-class,
goal_weight deferred); Decision Ask #3 path is now unblocked for the
external watchlist generator.
Verification: cd cli && go test ./internal/rpi/... -> all PASS.
bash scripts/check-contract-compatibility.sh -> 0 failures.
RFC 0001 finding-generator parallelism: Proposal 1 landed in 1bd2f082 (sidecar
writer) + 08e3a38e (single-writer aggregator wired as REDUCE stage 7). Update
the RFC frontmatter from draft -> accepted and add a Decision Record citing
the implementation files, contract updates, and shipped fitness signals.
Decision Ask #2 partially resolved: dedup_key is now first-class in the
generator-aggregator path, so document it as an optional item field in
next-work.schema.md. status / requires / goal_weight remain deferred until
Proposal 2 (external watchlist) has a concrete consumer. Decision Ask #3
deferred entirely until Proposal 2.