Skip to content

fix(forecast): resolve judged entries from deadline evidence#5196

Merged
koala73 merged 3 commits into
mainfrom
codex/issue-5183-deadline-archive-window
Jul 10, 2026
Merged

fix(forecast): resolve judged entries from deadline evidence#5196
koala73 merged 3 commits into
mainfrom
codex/issue-5183-deadline-archive-window

Conversation

@koala73

@koala73 koala73 commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Long-horizon judged forecasts can now resolve from evidence around their deadline instead of remaining pending until the retry safety net forces a VOID. The resolver uses a configurable seven-day deadline window, reads up to a hard configurable 14-day Redis ceiling, and filters the shared archive back to each forecast's own window before judging.

Hash-cap truncation is now treated as bounded recency sampling, so a covered window can honestly terminate on agreement, disagreement, or no evidence. Genuine incompleteness remains fail-closed: unavailable archives, explicit incomplete coverage, missing Redis rows, invalid pipeline rows, and exhausted read budgets keep entries pending.

The larger 15,000-hash read is split into 500-command pipelines under a shared 25-second budget. The new knobs are:

  • FORECAST_RESOLUTION_JUDGE_EVIDENCE_LOOKBACK_MS (default 7 days)
  • FORECAST_RESOLUTION_JUDGE_EVIDENCE_MAX_LOOKBACK_MS (default 14 days, enforced as a hard ceiling)
  • FORECAST_RESOLUTION_JUDGE_ARCHIVE_HASH_LIMIT (default 15,000)

Validation

  • npm run test:data: 14,552 passed, 6 skipped, 0 failed
  • Focused resolver and batch-reader suites: 62 passed, 0 failed
  • npm run typecheck:all: passed
  • npm run lint: passed; only existing repository warnings/info were reported
  • VITE_VARIANT=full vite build: passed, including dashboard critical-CSS checks
  • Pre-push gate: passed typechecks, boundaries, safe HTML, rate-limit policy, premium-fetch parity, edge bundle checks, changed tests, and version sync
  • Multi-persona code review and follow-up: all actionable findings applied; no residual findings

Post-deploy monitoring and validation

Owner: forecast service on-call / repository maintainer. Observe the first manual seed-service deployment through the first judged deadlines around 2026-07-14.

Healthy signals:

  • forecast:scorecard:v1.pendingJudge falls as due judged entries terminate, while scored and void rise.
  • Scorecard-watch M2 fires on the first judged resolution.
  • Resolver runs remain within FORECAST_RESOLUTION_JUDGE_RUN_BUDGET_MS without repeated judged archive unavailable or archive-budget errors.
  • Covered disagreements and no-evidence cases terminate directly rather than accumulating judge_retry_exhausted outcomes.

Failure signals and response:

  • If judged voidRate rises above roughly 40%, preserve the receipts and investigate judge agreement/evidence quality before considering a tiebreaker follow-up.
  • If archive timeouts or run-budget exhaustion repeat, reduce the evidence pool or tune the bounded timeout/hash limit, then redeploy.
  • Roll back this commit's service deployment if pending judged entries or forced-VOID behavior regress.

The seed-forecast-resolutions service still requires a manual Railway deployment after merge because its automatic deploy is blocked by the existing checkSuites skip. Use the established serviceInstanceDeployV2 followed by deploymentInstanceExecutionCreate flow documented in #5062; this PR does not deploy or merge the service.

Fixes #5183


Compound Engineering
GPT-5

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
worldmonitor Ignored Ignored Preview Jul 10, 2026 4:26pm

Request Review

@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR allows long-horizon judged forecasts to resolve against evidence collected around their deadline (a configurable 7-day window anchored on the deadline, bounded by a 14-day Redis ceiling) instead of remaining pending until the retry safety net forces a VOID. Hash-cap truncation is deliberately reclassified as bounded recency sampling so a deadline-window-covered archive can terminate on agreement, disagreement, or no-evidence.

  • Core resolver logic (seed-forecast-resolutions.mjs): evidence window anchored on deadline, normalizeJudgedArchiveInput made idempotent via a Symbol marker, truncated separated from incomplete (only missing Redis rows keep the archive incomplete), and a single shared archive is filtered per-entry rather than re-fetched.
  • Chunked Redis reads: the previous single pipeline call is replaced by 500-command batches under a shared 25-second deadline clock via readStoryTracksChunked, with a new context parameter to distinguish log sources.
  • Test suite (forecast-resolutions-seeder.test.mjs): new tests cover deadline windowing, the hard max-lookback ceiling, hash-alignment across chunks, budget-expiry fail-closed behaviour, and the renamed incomplete field semantics; env teardown for the two new env vars is correctly extended.

Confidence Score: 4/5

Safe to merge; the new resolution path is fail-closed for every genuine-incompleteness case and the test suite directly exercises deadline windowing, budget expiry, and chunk alignment.

The new resolution path is carefully fail-closed for every genuine-incompleteness case. The two areas worth a second look: the silent drop of newsArchive.truncated from the incompleteness check in normalizeJudgedArchiveInput (intentional but invisible to future callers), and the lack of a guard ensuring LOOKBACK_MS does not exceed MAX_LOOKBACK_MS (misconfiguration would silently prevent all resolutions until retry exhaustion).

The central logic in scripts/seed-forecast-resolutions.mjs — specifically normalizeJudgedArchiveInput (the truncated field drop) and resolveJudgedEvidenceLookbackMs (no guard against lookback > max-lookback) — deserves a second look before the first judged deadline lands.

Important Files Changed

Filename Overview
scripts/lib/story-track-batch-reader.mjs Adds a context parameter to readStoryTracksChunked so the error log is caller-aware; minor wording issue remains for the forecast-resolutions path (null → throw, not a tick-skip).
scripts/seed-forecast-resolutions.mjs Core resolver change: evidence window anchored on deadline, hash-cap truncation reclassified as bounded recency sampling, normalizeJudgedArchiveInput idempotency via Symbol, chunked Redis reads with a shared 25-second budget; no logic bugs found.
tests/forecast-resolutions-seeder.test.mjs Tests updated to cover deadline-anchored windowing, coverage checking, chunked reads, budget expiry, and the new incomplete field semantics; env teardown properly extended for the two new env vars.

Reviews (1): Last reviewed commit: "fix(forecast): resolve judged entries fr..." | Re-trigger Greptile

Comment thread scripts/lib/story-track-batch-reader.mjs Outdated
Comment thread scripts/seed-forecast-resolutions.mjs
Comment thread scripts/seed-forecast-resolutions.mjs
koala73 added 2 commits July 10, 2026 19:06
- make chunk-read failure logs caller-aware
- document cap sampling versus incomplete coverage
- clamp evidence lookback to the archive read ceiling
- derive coverage from retained Redis scores
- preserve partial-response alignment handling
- degrade isolated row errors to incomplete evidence
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(forecast): judged resolver perpetual-pends/forced-VOIDs long-horizon specs — deadline-centric archive window (blocks #5091)

1 participant