docs: multi-phase implementation plan (63 tasks across 5 phases)
Phase 1 Stabilize (13), Phase 2 Runtime unification (12), Phase 3 Dev-box surface (11), Phase 4 Sync correctness (12), Phase 5 Notifications & polish (15), plus index.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user