Skip to content

Instantly share code, notes, and snippets.

@RupertBarrow
Last active March 27, 2026 00:33
Show Gist options
  • Select an option

  • Save RupertBarrow/a7b15eae39104ad25a645aac3aad591f to your computer and use it in GitHub Desktop.

Select an option

Save RupertBarrow/a7b15eae39104ad25a645aac3aad591f to your computer and use it in GitHub Desktop.
FAB Spec Changes: acceptance status (v2.11.0) — for Rupert review

FAB Spec Changes: acceptance Status

Proposed spec version: FAB-PLUGIN-SPEC-v2.11.0 Previous: FAB-PLUGIN-SPEC-v2.10.0 Date: 2026-03-27 Author: Claudia (Operations Director) Status: PROPOSED — awaiting Rupert approval Revision: R2 — incorporates Rupert's feedback


1. Summary

Add a new acceptance status between agent_done and done. After orchestrator validation, tasks enter a human review gate where the user can Accept or Refuse the work.

Current flow:

agent_done → [orchestrator validates] → done

New flow:

agent_done → [orchestrator validates] → acceptance → [human accepts] → done
                                                   → [human refuses] → agent_done (+ rework subtask)

2. State Machine Changes

2.1 VALID_TRANSITIONS (update.ts)

From Current targets New targets Change
agent_done draft, planning, done, assigned, cancelled draft, acceptance, assigned, cancelled done replaced by acceptance; planning removed (was never valid — corrected)
acceptance (new) done, agent_done, cancelled New row. Only human can set done or cancelled.
All others (unchanged) (unchanged)

Key rules:

  • agent_done → done is removed. The only path to done from agent_done is through acceptance.
  • agent_done → planning is removed (was invalid historically — corrected now).
  • acceptance → draft and acceptance → planning are not allowed. Acceptance is a human gate — only Accept (→ done), Refuse (→ agent_done), or Cancel (→ cancelled) are valid.
  • acceptance → cancelled is human-only — only a human caller can cancel a task in acceptance.

2.2 Kanban Column Ordering

draft → planning → assigned → in_progress → blocked → agent_done → acceptance → done → archived → cancelled

2.3 Dashboard Status Filter

acceptance appears as a new filter pill in the dashboard status bar, alongside existing statuses. Tasks in acceptance are visible in their own Kanban column.

When the Accept or Refuse button is clicked, the task disappears immediately from the acceptance column (optimistic UI update before server confirmation).


3. Component Impact

3.1 Spawn Validation (spawn-validation.ts)

After orchestrator validates a task, it sets status: "acceptance" instead of status: "done".

// Before:
fab_task({ status: "done", validationNote: "..." })

// After:
fab_task({ status: "acceptance", validationNote: "..." })

3.2 Dashboard — TaskDetailSidebar

When status === 'acceptance', show two action buttons:

  • ✅ Accept (green/success style) — calls POST /api/tasks/:id/accept
  • ❌ Refuse (red/danger style) — calls POST /api/tasks/:id/refuse

Both buttons hidden for all other statuses.

3.3 Dashboard API — New Endpoints

POST /api/tasks/:id/accept

Sets status: "done". Logs audit event with action: "acceptance-accepted", caller: "human".

POST /api/tasks/:id/refuse

  1. Sets status: "agent_done"
  2. Adds subtask: "Task not accepted by the user. Rework with the agent"
  3. Logs audit event with action: "acceptance-refused", caller: "human"
  4. A validator task is created for the orchestrator to analyse the refusal reason and add specific rework subtasks for the agent

3.4 Completion Detector (completion-detect.ts)

No change. Still promotes fully-done tasks to agent_done. The acceptance status is downstream.

3.5 Dispatch Service (dispatch.ts)

No change to dispatch logic. acceptance is not a dispatchable status (dispatch only picks up assigned).

3.6 Stale Sweep (stale-sweep.ts)

Must exclude acceptance from stale detection. Human review may take hours or days — this is not a stale task.

Add acceptance to the excluded statuses list alongside done, archived, cancelled.

3.7 Task-Orchestrator Skill (SKILL.md)

Update the validation section: orchestrator sets acceptance instead of done after validating agent_done tasks.

3.8 Slack Sync

acceptance is a new valid status value. The Slack List column mapping handles it as text — no schema change needed, just a new value in the status column.

3.9 Post-Validation Merge (post-validation-merge.ts)

No change to the trigger condition — it watches for status = 'done', which now only happens after human acceptance. This is correct: PRs should only merge after the human has accepted the work.


4. Refusal → Rework Cycle (Detail)

When the human clicks Refuse:

  1. Dashboard API sets status: agent_done + adds subtask: "Task not accepted by the user. Rework with the agent"
  2. Completion detector sees agent_done with incomplete subtasks → no action (waits for subtask completion)
  3. Orchestrator creates a validator task to analyse the refusal reason and determine what needs fixing
  4. Validator adds detailed rework subtasks explaining what needs fixing by the agent
  5. addSubtasks on an agent_done task triggers re-dispatch to the agent (existing behaviour)
  6. Agent reworks → marks subtasks done → completion detector → agent_done → orchestrator validates → acceptance → human reviews again

Loop breaker: Existing MAX_VALIDATION_SPAWNS = 5 cap prevents infinite cycles.


5. Permissions

Action Who can do it
Set acceptance Orchestrator only (after validation)
Accept (→ done) Human only (via dashboard)
Refuse (→ agent_done) Human only (via dashboard)
Cancel from acceptance Human only (via dashboard)

Agents and orchestrator cannot Accept, Refuse, or Cancel tasks in acceptance status.


6. Edge Cases

Case Handling
Task stuck in acceptance for days Stale sweep ignores it — human-paced
Human wants to cancel during acceptance acceptance → cancelled is valid (human-only)
Orchestrator wants to demote from acceptance Not allowedacceptance → draft/planning are invalid transitions
Multiple refusal cycles MAX_VALIDATION_SPAWNS (5) caps retries
Refuse without explanation Rework subtask is still added with generic text; validator will add specifics

7. DB Schema

No migration required. The status column is TEXT — adding a new value needs no DDL change. The TypeScript Task type union needs updating.


8. Test Requirements

Unit tests:

  • State machine: acceptance transitions (to done, to agent_done, to cancelled — all valid)
  • State machine: acceptance → draft is rejected
  • State machine: acceptance → planning is rejected
  • State machine: agent_done → done is rejected (must go through acceptance)
  • State machine: agent_done → planning is rejected (corrected historical error)
  • Refuse handler: adds rework subtask + sets agent_done
  • Accept handler: sets done
  • Permission: non-human caller cannot Accept or Refuse

E2E tests:

  • acceptance status appears as filter pill in dashboard
  • acceptance column visible in Kanban board
  • Accept button visible only on acceptance tasks
  • Refuse button visible only on acceptance tasks
  • Accept click → task disappears immediately from acceptance column, moves to done
  • Refuse click → task disappears immediately from acceptance column, moves to agent_done with rework subtask
  • Refuse without explanation → generic rework subtask added
  • Refuse with explanation → explanation captured
  • Buttons hidden on all other statuses (negative test)
  • Multiple refusal cycles work correctly (refuse → rework → agent_done → acceptance again)
  • Cancel from acceptance → task moves to cancelled

9. Files to Modify

File Change
src/task/handlers/update.ts VALID_TRANSITIONS: add acceptance row; agent_done targets: remove done + planning, add acceptance; add permission check for acceptance actions
src/task/db.ts Task type: add acceptance to status union
src/task/services/spawn-validation.ts Set acceptance instead of done
src/task/services/stale-sweep.ts Exclude acceptance from stale detection
packages/dashboard/src/types/fab.ts Add acceptance to status type
packages/dashboard/src/components/TaskDetailSidebar.tsx Accept/Refuse buttons
packages/dashboard/src/components/KanbanBoard.tsx New acceptance column
packages/dashboard/src/api/fab.ts New API calls for accept/refuse
scripts/dashboard-server.mjs New endpoints: /api/tasks/:id/accept, /api/tasks/:id/refuse
skills/task-orchestrator/SKILL.md Update validation flow
tests/task/handlers/update.test.ts New transition tests (including negative tests)
New: tests/task/acceptance.test.ts Accept/refuse handler + permission tests
New: packages/dashboard/e2e/acceptance.spec.ts E2E tests (multiple scenarios)

10. Deployment — Data Migration

On deployment, run a one-time migration:

Set all tasks currently in done status to acceptance so that Rupert can review them all again.

This is a deliberate retroactive review — all previously-completed tasks pass through the new human acceptance gate.

UPDATE tasks SET status = 'acceptance' WHERE status = 'done';

Log this in task_log for each affected task with action: "migration-to-acceptance".


11. Spec Version

v2.10.0 → v2.11.0 (minor bump — additive status, no breaking schema change)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment