# Spoon: Stabilize → Unify → Build — Implementation Plan Index

> **For agentic workers:** Execute the phase plans **in order**. Each phase is a
> standalone plan that ships working, tested software on its own. Use
> `superpowers:subagent-driven-development` (fresh subagent per task, review
> between tasks) or `superpowers:executing-plans` (batched with checkpoints).

**Spec:** [`../specs/2026-07-10-spoon-stabilize-unify-build-design.md`](../specs/2026-07-10-spoon-stabilize-unify-build-design.md)
**Design review:** Gib, 2026-07-10 (tenancy = owner + trusted friends; runtimes =
Codex + OpenCode + Claude Code, all in the per-user box; all four feature tracks;
ordering = stabilize → unify → build).

## Phases

| # | Plan | Tasks | Scope |
| - | ---- | ----- | ----- |
| 1 | [phase1-stabilize](2026-07-10-spoon-phase1-stabilize.md) | 13 | Critical/High bug fixes on the current architecture: home-deletion data loss, box lifecycle races/leaks, symlink escape, job-lifecycle recovery (heartbeat/timeout/cancel), auto-sync gating, terminal sizing, workspace shell keying, not-found handling. |
| 2 | [phase2-runtime-unification](2026-07-10-spoon-phase2-runtime-unification.md) | 12 | `AgentRuntime` adapter interface; Codex/OpenCode/Claude Code all exec into the box; delete the legacy per-job OpenCode container; runtime picker + queue-time validation; Fedora image + smoke; secrets hygiene. |
| 3 | [phase3-dev-box-surface](2026-07-10-spoon-phase3-dev-box-surface.md) | 11 | `/machine` page (box status/lifecycle + full-page terminal + home file browser); user-scoped `/box/*` worker routes + HMAC tokens; persistent workspace terminal (survives tab switch); terminal QoL. |
| 4 | [phase4-sync-correctness](2026-07-10-spoon-phase4-sync-correctness.md) | 12 | Correct head-SHA (branch ref, not truncated compare); stable maintenance-thread dedup; GitHub webhooks (push + installation lifecycle); Octokit retry/throttle + `rate_limited` status; bound unbounded queries; surface `needs_reauth`. |
| 5 | [phase5-notifications-polish](2026-07-10-spoon-phase5-notifications-polish.md) | 15 | `notifications` + `notificationPreferences` tables, in-app bell, preference-gated UseSend email; polish sweep (skeletons, error handling, form re-sync, auth copy, workspace UX, a11y, dead-code removal); docs rewrite. |

**Total: 63 tasks**, each ending in an independently testable, committed deliverable.

## Cross-phase dependencies

- **Phase 1 → 2, 3.** Phases 2 and 3 consume the Phase-1 box-lifecycle API:
  `export type BoxHandle = { boxName: string; release: () => void }` and
  `acquireUserBox(args: { username; workdir; containerHome }) => Promise<BoxHandle>`
  (idempotent `release`, per-username mutex, `--init`, startup reconcile of
  `spoon-box-*`). Both later plans carry a fallback note for the pre-Phase-1
  `Promise<string>` + `releaseUserBox(username)` signature — **build Phase 1
  first and the `BoxHandle` form is what lands.**
- **Phase 1 → 5.** Phase 5's `agent_turn_finished` / `agent_needs_input`
  notifications emit at the job-status transitions that Phase 1 hardens
  (`updateStatus`, `applyMaintenanceDecision`).
- **Phase 4 → 5.** Phase 5's `connection_needs_reauth` email emits where the
  Phase-4 webhook sets `gitConnections.status = needs_reauth`; Phase 5 Task 3
  marks that emit point defensively if Phase 4 hasn't landed.
- **Phase 4 depends on Phase 1's auto-sync gating** (`autoSyncEnabled` etc.
  land in Phase 1 Task 8) and layers head-SHA/dedup/webhooks on top.

Phases 3 and 4 are otherwise independent and could be reordered or parallelized
after Phases 1–2. The recommended sequential order matches the spec.

## Deliberate deferrals (documented by the plan authors)

These are called out inline in the plans, not gaps:

- **Phase 1:** `updateStatus` implements the terminal-state guard (the
  cancel-revert fix) rather than a full forward-only transition matrix — no
  illegal transition is otherwise exercised. Stale-job recovery **times out**
  rather than requeues (requeue-with-attempt-limit needs a new `claimAttempts`
  field — deferred). `requireAiLowRiskForSync` is scoped to Phase 4 (the
  AI-review→merge path it guards doesn't exist yet).
- **Phase 2:** exact `opencode run` / `claude -p` flags and the
  `@anthropic-ai/claude-code` version pin are reconciled at implementation time
  via the extended `scripts/smoke-agent-container` (`--help` probes + `npm view`),
  since the live CLIs aren't available while planning.
- **Phase 3:** dotfiles re-materialization for the `/box` surface is out of
  scope (the persistent home already carries dotfiles from prior job runs);
  box start only ensures a login-shell `.bash_profile`. Docker-touching code is
  verified by documented manual steps; only pure logic is unit-tested.
- **Phase 4:** the webhook route test cannot assert the scheduled `'use node'`
  refresh ran in-process (convex-test VM limitation) — covered by the manual
  checklist. Octokit plugin versions may need a bump on `bun install`.
- **Phase 5:** `(app)/error.tsx` + not-found handling lives in **Phase 1**
  (finding #14), not here.

## Testing

Every task is test-first where a test is meaningful. Test surfaces:

- **Worker** (`apps/agent-worker/tests/unit/`, vitest): box-registry
  mutex/handle semantics, path containment incl. symlinks, terminal
  resize-message parsing, runtime-adapter fixture-stream parsing.
- **Backend** (`packages/backend/tests/unit/`, `convex-test`): claim
  validation/rollback, heartbeat-timeout cron, transition guard incl.
  cancel-vs-worker race, auto-sync gating matrix, maintenance-thread dedup,
  webhook signature verification, notification emit/preferences.
- **Next** (`apps/next/tests/component`, jsdom + testing-library): terminal
  fit-on-fonts-ready + resize, workspace shell remount on job switch, form
  re-sync, not-found states, notification bell.
- **Docker-touching worker code** (box `--init`, dockerode TTY exec, `/box`
  lifecycle) uses documented manual verification — needs a live daemon.

## How to run each phase

```
Subagent-driven (recommended): one fresh subagent per task, two-stage review between tasks.
Inline: superpowers:executing-plans, batched with checkpoints.
```

Start with Phase 1, Task 1 (`cleanupOrphanedWorkspaces` layout-awareness) — it
closes the highest-severity bug (a cleanup call deletes every user's home).
