Skip to content

Wave 3 — budgets, cyclic rework, first-class approvals, budget dashboard - #4

Merged
tobyvee merged 3 commits into
mainfrom
wave-3-governance
Jun 27, 2026
Merged

tobyvee merged 3 commits into
mainfrom
wave-3-governance

Conversation

@tobyvee

@tobyvee tobyvee commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Wave 3 — governance & observability

Implements Wave 3 of the roadmap — and completes the whole backlog (Waves 0–3, all 16 tickets).
Stacked on #3 (base wave-2-repo-context); this diff is Wave 3 only. Merge order: #1 ← #2 ← #3 ← #4.

ENG-007 — Budget model (reset + reservation)

  • Real monthly reset: period_start column (migration 0003) + lazy rolloverIfExpired in
    getBudgetRemaining, so monthlyBudgetCents is a true monthly window rather than an ever-growing
    total. Applies to every activity automatically.
  • Atomic reservation: reserveBudget (conditional UPDATE that can't exceed the limit) +
    reconcileSpend (settle hold → actual); estimateRunCostCents sizes the worst-case hold. All four
    agent activities now reserve→run→reconcile (release on failure, skip on exhaustion), closing the
    read-then-spend TOCTOU. Pure helpers periodExpired / canReserve unit-tested.

ENG-008 — Cyclic rework routing

  • ticketLifecycle runs a bounded rework loop: implement → review → QA, bouncing back to
    in_progress with the QA feedback on a fail, up to MAX_IMPLEMENT_ATTEMPTS (2), then blocked.
    verifyTicket returns { passed, feedback }; implementTicket threads the feedback into the next
    coding prompt. New @temporalio/testing tests: rework-once-then-pass, exhaust-then-blocked.

ENG-006 — First-class approvals

  • Added epic_id to the approvals table (core schema + migration 0004) so roadmap/epic gates fit.
    Repo createApproval / resolveApproval / listPendingApprovals. Each gate persists a pending
    record (roadmap + a new requestApproval activity before the merge and deploy conditions), resolved
    with decidedBy (the ENG-004 principal). /api/approvals now covers all gate kinds; the web
    Approvals page dispatches the right approve call per kind.

ENG-010 — Budget/cost dashboard

  • listBudgets repo helper + typed /api/budgets; a new web Budgets page (per-role
    limit/spent/remaining + unit total) with nav link and route.

Verification

pnpm typecheck · pnpm lint · pnpm test (94 tests) · pnpm build all green.

Deferred (noted in the tickets)

  • Real GitHub re-push on a rework retry (the per-ticket branch already exists).
  • DB-layer atomicity isn't unit-tested (no live DB in CI — consistent with the rest of repo.ts).

🤖 Generated with Claude Code

tobyvee and others added 3 commits June 27, 2026 12:34
…04, ENG-009, ENG-005)

ENG-004: bearer-token auth middleware on /api/* (apps/server/src/auth.ts) — mutating requests require Authorization: Bearer $API_AUTH_TOKEN (timing-safe), GET read views open; principal from X-Actor; approval endpoints append an approval_decided audit event stamped with the principal; open dev-mode + startup warning when unset. ENG-009: WorkerInput.outputSchema; API backend emits output_config.format (json_schema); hand-written schemas for proposal/tickets/verdict; CLI keeps prose fallback; ProposedChanges.parsed distinguishes parse failure from empty change set. ENG-005: sandboxEnv() forwards only an allow-list to the claude -p child, withholding host secrets. typecheck + lint + 73 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… ENG-001)

ENG-013: two-root workspace (workspace.ts) — persistent working-code root for cloned target repos (AGENT_CODE_WORKSPACE), distinct from throwaway agent-state sandboxes; PM granted git/gh (ROLES.pm.tools + prompt); sandboxEnv(source, role) forwards a PM-scoped AGENT_PM_GITHUB_TOKEN only to the PM sandbox (host token never forwarded); idempotent ensureRepoCloned (provision.ts) shallow clone/ff-pull with token via http.extraheader, no-op when unconfigured, wired+audited in implementTicket. ENG-001: WorkerInput.workdir — CLI backend runs the agent in the cloned repo cwd (persistent, not cleaned up) so it reads/edits real source; implementTicket passes the clone path; product tree never touched. typecheck + lint + 85 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dashboard (ENG-007/008/006/010)

ENG-007: monthly budget reset (period_start, migration 0003, lazy rollover) + atomic reserveBudget/reconcileSpend wired across all agent activities; estimateRunCostCents sizes the hold; pure periodExpired/canReserve tested. ENG-008: bounded implement->review->QA rework loop in ticketLifecycle with QA feedback threaded into re-implementation, then blocked; verifyTicket returns {passed,feedback}; harness tests. ENG-006: first-class persisted approvals (added epic_id, migration 0004); createApproval/resolveApproval/listPendingApprovals; pending records per gate resolved with decidedBy; /api/approvals covers roadmap/merge/deploy; web Approvals handles all kinds. ENG-010: /api/budgets + web Budgets page. typecheck + lint + 94 tests + build green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tobyvee
tobyvee changed the base branch from wave-2-repo-context to main June 27, 2026 03:40
@tobyvee
tobyvee merged commit c282f56 into main Jun 27, 2026
@tobyvee
tobyvee deleted the wave-3-governance branch June 27, 2026 03:45
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.

1 participant