Skip to content

fix(tasks): approving a proposed task keeps it isolated (0.11.0) - #91

Open
stackbilt-admin wants to merge 2 commits into
mainfrom
fix/approve-keeps-isolation
Open

stackbilt-admin wants to merge 2 commits into
mainfrom
fix/approve-keeps-isolation

Conversation

@stackbilt-admin

Copy link
Copy Markdown
Member

Problem

Approving a proposed task (REST POST /api/cc-tasks/:id/approve, MCP aegis_approve_cc_task / aegis_batch_approve) rewrote authority to operator. scripts/taskrunner.sh gives only non-operator tasks a worktree and PR, so approved work, often generated from untrusted issue bodies, ran in the operator's own checkout. Nothing on the row showed it had started as proposed.

Change

  • Approval keeps authority = 'proposed' and sets approved_at = datetime('now') and approved_by (rest / mcp). A task can be approved once (approved_at IS NULL guard).
  • Migration web/migrations/0002_cc_tasks_approval.sql adds the two columns; schema.sql has them for fresh installs.
  • schema-enums.ts: TASK_RUNNABLE_SQL (authority != 'proposed' OR approved_at IS NOT NULL) and TASK_AWAITING_APPROVAL_SQL.
  • Runnable: /api/cc-tasks/next, sandbox dispatch (factory/dispatch.ts) and the sandbox claim (factory/executor-do.ts).
  • Awaiting approval: briefing, digest, task summary, dashboard; the contract gains approvedAt/approvedBy, and invariant proposed_task_needs_approval passes once approved.
  • 0.11.0 + CHANGELOG with upgrade note. Rows approved on earlier versions were already rewritten to operator and can't be restored.

Tests

  • New web/tests/cc-task-approval.test.ts (node:sqlite, the real schema.sql DDL and the migration): REST/MCP/batch approve, double-approve refused, /next, dispatch, summary, the SQL constants and the invariant.
  • Updated expectations in cc-tasks.test.ts, mcp.test.ts and factory/dispatch.test.ts.
  • Local: pnpm typecheck clean; vitest run for those five files plus pr-ready.test.ts: 164 passed.

Daemon follow-up (separate PR in Stackbilt-dev/aegis): the daemon's own MCP approve handlers (web/src/mcp/handlers/cc-tasks.ts) need the same change, and aegis-web needs the D1 migration.

🤖 Generated with Claude Code

kovermier and others added 2 commits October 16, 2026 19:32
Approval rewrote authority to 'operator', so the local task runner ran
approved work -- often from untrusted issue bodies -- in the operator's
own checkout with no branch or PR. Approval now records approved_at and
approved_by (migration 0002) and keeps 'proposed'; the queue, sandbox
dispatch and sandbox claim run approved proposed tasks, and the runner
keeps isolating every non-operator task. Awaiting-approval listings
(briefing, digest, task summary, dashboard, contract invariant) exclude
approved tasks. Shared SQL in schema-enums.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gressions

Review of #91:
- do_sandbox tasks need an acceptance block unless operator-queued;
  approved proposed tasks keep their authority and would otherwise run
  unchecked.
- An approved proposed task on an outside repo is refused with a note to
  requeue it with operator authority, and the changelog says so.
- The sandbox claim moves to factory/claim.ts and the digest's task
  queries to digestTasks(), so both are tested on the real schema; new
  tests fail when the claim, briefing, digest, dashboard or admission
  filters revert.
- setup applies migrations/*.sql, skipping ones already applied.
- Dashboard marks approved tasks; aegis_list_cc_tasks returns the
  approval fields; reject is tested on approved tasks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants