P2: Monte Carlo forecast → real burn-up cone (#10) #38

Merged
christian merged 2 commits from p2/monte-carlo into p2/scheduler-focus 2026-07-08 23:22:51 +00:00
Owner

Stacked on #37 (P2 scheduler). Retarget to main once #37 merges.

What

Replaces the demo burn-up cone on Morning service with a real, seeded Monte Carlo forecast over the open backlog. The LLM never does this — it's plain, reproducible code (evidence-based scheduling).

Core (@commitea/core/forecast-v0)

  • Cold-start lognormal priors (D3), code-resident, per estimate bucket: sampled actual = estimate·exp(N(μ,σ)), μ>0 (actuals run long), σ shrinks as tickets grow. Replaced by the team's empirical fit at n≥20 (#5 supplies the actuals).
  • forecast(): seeded mulberry32 + Box–Muller over the scheduler's deterministic order (order is fixed from estimates/deps; only durations vary, so the cone stretches, never reorders). Returns p50/p80/p95 landing + a per-issue burn-up curve (p10/p50/p90). 12 unit tests, reproducible.

Renderer

  • lib/dates.ts: working-day→calendar mapper (skips weekends) + buildBurnUpData.
  • BurnUpCone gains a data-driven twin; falls back byte-identical to the fixture cone in demo mode.
  • Focus card: real "80% of the open backlog lands by ", real scope count, names the cold-start priors.

v0 scope (each a later slice)

Single serial worker (capacity → #8); cold-start priors only (empirical fit → #5); no historical actual polyline (needs lifecycle events → #5). Header chrome (reconcile time, ahead/behind badge) stays fixture until milestone due dates land.

Verified

51 core tests green · desktop typecheck clean · 14 fixture e2e green · live spec asserts the real cone (25 open issues, "lands by Nov 11–27").

🤖 Generated with Claude Code

Stacked on #37 (P2 scheduler). Retarget to `main` once #37 merges. ## What Replaces the demo burn-up cone on **Morning service** with a real, seeded **Monte Carlo** forecast over the open backlog. The LLM never does this — it's plain, reproducible code (evidence-based scheduling). ## Core (`@commitea/core/forecast-v0`) - **Cold-start lognormal priors (D3)**, code-resident, per estimate bucket: sampled actual = estimate·exp(N(μ,σ)), μ>0 (actuals run long), σ shrinks as tickets grow. Replaced by the team's empirical fit at n≥20 (#5 supplies the actuals). - **`forecast()`**: seeded mulberry32 + Box–Muller over the scheduler's *deterministic* order (order is fixed from estimates/deps; only durations vary, so the cone stretches, never reorders). Returns p50/p80/p95 landing + a per-issue burn-up curve (p10/p50/p90). **12 unit tests, reproducible.** ## Renderer - `lib/dates.ts`: working-day→calendar mapper (skips weekends) + `buildBurnUpData`. - `BurnUpCone` gains a data-driven twin; falls back **byte-identical** to the fixture cone in demo mode. - Focus card: real *"80% of the open backlog lands by <range>"*, real scope count, names the cold-start priors. ## v0 scope (each a later slice) Single serial worker (capacity → #8); cold-start priors only (empirical fit → #5); no historical *actual* polyline (needs lifecycle events → #5). Header chrome (reconcile time, ahead/behind badge) stays fixture until milestone due dates land. ## Verified 51 core tests green · desktop typecheck clean · 14 fixture e2e green · live spec asserts the real cone (25 open issues, *"lands by Nov 11–27"*). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
christian added 1 commit 2026-07-08 23:11:39 +00:00
Replace the demo cone on Morning service with a real, seeded Monte Carlo
forecast over the open backlog. The LLM never does this — it's plain,
reproducible code (evidence-based scheduling).

core (@commitea/core/forecast-v0):
- Code-resident lognormal cold-start priors per estimate bucket (D3):
  sampled actual = estimate * exp(N(mu, sigma)), mu > 0 (actuals run long),
  sigma shrinks as tickets grow. Replaced by the team's empirical fit at
  n >= 20 (#5 supplies the actuals).
- forecast(): seeded mulberry32 + Box-Muller over the scheduler's
  deterministic order (order is fixed from estimates/deps; only durations
  vary, so the cone stretches, never reorders). Returns p50/p80/p95 landing
  + a per-issue burn-up curve (p10/p50/p90). 12 unit tests; reproducible.

renderer:
- lib/dates.ts: working-day -> calendar mapper (skips weekends) + buildBurnUpData.
- BurnUpCone gains a data-driven twin; falls back byte-identical to the
  fixture cone when no forecast (demo mode unchanged).
- Focus card shows the real "80% of the open backlog lands by <range>",
  real scope count, and names the cold-start priors.

v0 scope (each a later slice): single serial worker (capacity is #8);
cold-start priors only (empirical fit is #5); no historical actual polyline
(needs lifecycle events, #5). Header chrome (reconcile time, ahead/behind
badge) stays fixture until milestone due dates land.

Verified: 51 core tests green, desktop typecheck clean, 14 fixture e2e green,
live spec asserts the real cone renders (25 open issues, "lands by Nov 11-27").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
christian added 1 commit 2026-07-08 23:22:47 +00:00
christian merged commit eeaf54c4ab into p2/scheduler-focus 2026-07-08 23:22:51 +00:00
Sign in to join this conversation.
No description provided.