You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Execute PRP-33 — build the app/features/batch/ vertical slice that orchestrates portfolio forecasting batches.
Spec:PRPs/PRP-33-batch-runner-mvp.md (1177 lines, landed in #279). Read end-to-end before starting — every column, JSONB key, index predicate, and CHECK constraint is pinned.
Scope (10 dependency-ordered tasks per PRP-33)
Pre-add batch to .claude/rules/commit-format.md (local prerequisite — .claude/ is gitignored).
Alembic migration: batch_job + batch_job_item tables, enums, CHECK constraints, partial picker index with predicate exactly WHERE (status = 'pending').
Frontend stub: types, hooks, placeholder frontend/src/pages/visualize/batch.tsx (no slider, no cancel button, no retry, no heatmap — per PRP narrowing).
Goal
Execute PRP-33 — build the
app/features/batch/vertical slice that orchestrates portfolio forecasting batches.Spec:
PRPs/PRP-33-batch-runner-mvp.md(1177 lines, landed in #279). Read end-to-end before starting — every column, JSONB key, index predicate, and CHECK constraint is pinned.Scope (10 dependency-ordered tasks per PRP-33)
batchto.claude/rules/commit-format.md(local prerequisite —.claude/is gitignored).batch_job+batch_job_itemtables, enums, CHECK constraints, partial picker index with predicate exactlyWHERE (status = 'pending').app/features/batch/models.py) + status-transition table.ConfigDict(strict=True)+Field(strict=False)on date fields (per SECURITY.md § "Pydantic v2 strict mode").BatchService—submit,_expand_scope(lazy-importsAnalyticsServicefortop_revenue,DimensionsServiceforregion/category),_pick_next(withFOR UPDATE SKIP LOCKED),_execute_item(lazy-importsJobService),_shape_metrics(pinned 5-key JSONB;sample_sizederived inside the slice fromfold_metricsper PRP § "Why not 10"),_settle,get,list_items.app/main.pybetweenjobs_routerandingest_router.Settings.batch_max_scope_expansion = 1000+.env.exampleentry.BatchScope.kinds, lifecycle structlog events withrequest_id, picker SKIP LOCKED, status-settlement matrix, pinned JSONB shape).frontend/src/pages/visualize/batch.tsx(no slider, no cancel button, no retry, no heatmap — per PRP narrowing).Success criteria (from PRP § "What → Success Criteria")
alembic upgrade headon fresh Postgres creates both tables + every CHECK + the partial picker index with predicate exactlyWHERE (status = 'pending').backtestscope settlescompletedwithcompleted_items=3; every item'smetricsJSONB carries exactly{wape, smape, mae, bias, sample_size}— no extras, no missing.grep -rn "for_update" app/features/batch/service.pyreturns at least one line withskip_locked=True.Settings.agent_require_approvalgains zero entries (MVP exposes zero mutating agent tools).app/features/jobs/,app/features/forecasting/,tests/test_e2e_demo.pyunmodified.ruff check,ruff format --check,mypy app/,pyright app/,pytest -v -m "not integration",pytest -v -m integration,frontend pnpm tsc --noEmit && pnpm lint && pnpm test --run.Off-limits (PRP non-regression boundary)
app/features/jobs/— no edits.app/features/forecasting/— no edits.tests/test_e2e_demo.py— no edits.References
PRPs/PRP-33-batch-runner-mvp.md(df90d22)PRPs/INITIAL/INITIAL-batch-runner-mvp.mdINITIAL-batch-parallel-execution.md,INITIAL-batch-priority-queue.md,INITIAL-batch-export-and-retry.md,INITIAL-batch-champion-and-heatmap.mdBranch + commit conventions
feat/prp-33-batch-runner-mvpoffdev.feat(batch): <description> (#<this-issue>)after Task 1 addsbatchto the gitignored scope allow-list locally.dev; maintainer merges.Refs #277.