docs(roadmap): mark Wave 1-4 done (8 shipped), leave Wave 5 open

This commit is contained in:
Yaojia Wang
2026-07-13 04:25:16 +02:00
parent a7eba2d43b
commit 6541246fc9

View File

@@ -1,5 +1,7 @@
# Roadmap # Roadmap
> **Status (2026-07-13):** Wave 1-4 (all 8 items) implemented + committed on `develop` — see docs/PROGRESS_LOG.md for the per-feature commits. Remaining: Wave 5 (fan-out board, access token, Android parity) + the deferred backlog.
Prioritized backlog of features to build next, derived from a grounded analysis of Prioritized backlog of features to build next, derived from a grounded analysis of
the codebase + the existing planning docs (5 exploration lenses → 24 candidates → the codebase + the existing planning docs (5 exploration lenses → 24 candidates →
this synthesis). Each item keeps **what it touches** (real files/subsystems) and a this synthesis). Each item keeps **what it touches** (real files/subsystems) and a
@@ -29,7 +31,7 @@ build sequence (dependencies noted).
## Wave 1 — ship first (high-trust / high-delight, independent) ## Wave 1 — ship first (high-trust / high-delight, independent)
- [ ] **Approval preview — see-what-you-approve**_(strongest)_ - [x] **Approval preview — see-what-you-approve**_(strongest)_
Show the pending `Bash` command or `Edit`/`Write` diff *above* Approve/Reject, so remote Show the pending `Bash` command or `Edit`/`Write` diff *above* Approve/Reject, so remote
one-tap approval stops being blind (today you could tap Approve on `rm -rf build`). one-tap approval stops being blind (today you could tap Approve on `rm -rf build`).
*The core walk-away trust gap.* *The core walk-away trust gap.*
@@ -41,7 +43,7 @@ build sequence (dependencies noted).
Pure side-channel. **Effort: M.** Risk: truncate + strip control chars + cap bytes, Pure side-channel. **Effort: M.** Risk: truncate + strip control chars + cap bytes,
`textContent`/diff-render only, unknown tools fall back to today's name-only bar. `textContent`/diff-render only, unknown tools fall back to today's name-only bar.
- [ ] **Clickable URLs & file paths in the terminal** - [x] **Clickable URLs & file paths in the terminal**
Tap the dev-server URL or file path Claude prints instead of soft-keyboard copy gymnastics Tap the dev-server URL or file path Claude prints instead of soft-keyboard copy gymnastics
(paths reuse `POST /open-in-editor`). TECH_DOC named `@xterm/addon-web-links` in v0.2; never built. (paths reuse `POST /open-in-editor`). TECH_DOC named `@xterm/addon-web-links` in v0.2; never built.
**Touches:** frontend only — `public/terminal-session.ts` (add the addon + a path-matcher **Touches:** frontend only — `public/terminal-session.ts` (add the addon + a path-matcher
@@ -51,7 +53,7 @@ build sequence (dependencies noted).
## Wave 2 — the unlocking primitive ## Wave 2 — the unlocking primitive
- [ ] **Server-side PTY-inject + queued follow-up prompt** _(unlocks a family)_ - [x] **Server-side PTY-inject + queued follow-up prompt** _(unlocks a family)_
A thin Origin/loopback-guarded route that writes text into a session's PTY, plus a A thin Origin/loopback-guarded route that writes text into a session's PTY, plus a
per-session queue that fires one entry when Claude goes idle ("now run the tests", then per-session queue that fires one entry when Claude goes idle ("now run the tests", then
"now open a PR"). Walk-away = give a task and leave; queuing lets the session advance itself. "now open a PR"). Walk-away = give a task and leave; queuing lets the session advance itself.
@@ -66,21 +68,21 @@ build sequence (dependencies noted).
## Wave 3 — read-only side-channel batch (review from the phone) ## Wave 3 — read-only side-channel batch (review from the phone)
- [ ] **Diff against a base branch** (`?base=<rev>`) - [x] **Diff against a base branch** (`?base=<rev>`)
Review a whole agent branch vs `main` before landing, not just uncommitted changes. Review a whole agent branch vs `main` before landing, not just uncommitted changes.
`src/http/diff.ts` already deferred this (FR-B1.9) and named its mitigation: `src/http/diff.ts` already deferred this (FR-B1.9) and named its mitigation:
`git rev-parse --verify` allow-list before any revision reaches the CLI. `git rev-parse --verify` allow-list before any revision reaches the CLI.
**Touches:** optional `base` on `getDiff()` (guarded `git rev-parse --verify <base>` + **Touches:** optional `base` on `getDiff()` (guarded `git rev-parse --verify <base>` +
trailing `--`, then `git diff <base>...`); branch-picker in `public/diff.ts`. **Effort: S/M.** trailing `--`, then `git diff <base>...`); branch-picker in `public/diff.ts`. **Effort: S/M.**
- [ ] **PR + CI/checks status via `gh`** (read-only) - [x] **PR + CI/checks status via `gh`** (read-only)
Per-project/session chip: PR state · checks passing · mergeable — glance from the phone, Per-project/session chip: PR state · checks passing · mergeable — glance from the phone,
re-engage only when red. No `gh` usage exists in `src/` yet; `gh` emits JSON (no parsing pain). re-engage only when red. No `gh` usage exists in `src/` yet; `gh` emits JSON (no parsing pain).
**Touches:** new `src/http/gh.ts` (mirror `diff.ts`'s `runGit`); `GET /projects/pr?path=` **Touches:** new `src/http/gh.ts` (mirror `diff.ts`'s `runGit`); `GET /projects/pr?path=`
guarded by `isValidGitDir`; `PrStatus` in `src/types.ts`; FE chip in project detail. guarded by `isValidGitDir`; `PrStatus` in `src/types.ts`; FE chip in project detail.
Capability-probe + empty-degrade when `gh` absent/unauthed. **Effort: M.** Capability-probe + empty-degrade when `gh` absent/unauthed. **Effort: M.**
- [ ] **Quick wins** (small, cheap, high-delight) - [x] **Quick wins** (small, cheap, high-delight)
- [ ] **Sync chip on project cards** — ahead/behind + last-commit, folded into the existing - [ ] **Sync chip on project cards** — ahead/behind + last-commit, folded into the existing
per-repo metadata pass in `src/http/projects.ts` (no new route). **S.** per-repo metadata pass in `src/http/projects.ts` (no new route). **S.**
- [ ] **Cost budget guard + push alert**`costUsd` already flows via statusLine - [ ] **Cost budget guard + push alert**`costUsd` already flows via statusLine
@@ -95,7 +97,7 @@ build sequence (dependencies noted).
## Wave 4 — close the git loop ## Wave 4 — close the git loop
- [ ] **Worktree lifecycle: remove / prune** (create is now fixed) - [x] **Worktree lifecycle: remove / prune** (create is now fixed)
Delete losing worktrees + land the winner from any device — closes the create-only loop. Delete losing worktrees + land the winner from any device — closes the create-only loop.
**Touches:** `removeWorktree`/`pruneWorktrees` in `src/http/worktrees.ts` (same execFile **Touches:** `removeWorktree`/`pruneWorktrees` in `src/http/worktrees.ts` (same execFile
no-shell + timeout, validate target in `git worktree list` & not main, reuse realpath no-shell + timeout, validate target in `git worktree list` & not main, reuse realpath
@@ -103,7 +105,7 @@ build sequence (dependencies noted).
make the existing `locked`/`prunable` tags actionable. **Effort: SM.** Risk: destructive — make the existing `locked`/`prunable` tags actionable. **Effort: SM.** Risk: destructive —
require `--force` + confirm for dirty trees, reject the main worktree, safe error messages. require `--force` + confirm for dirty trees, reject the main worktree, safe error messages.
- [ ] **Stage / commit / push from the diff viewer** - [x] **Stage / commit / push from the diff viewer**
Claude's done, you reviewed on the phone — now commit + push without typing git into a Claude's done, you reviewed on the phone — now commit + push without typing git into a
mobile terminal. Highest-risk git write; bound the MVP to per-file stage-toggle + commit + mobile terminal. Highest-risk git write; bound the MVP to per-file stage-toggle + commit +
push-current-branch only; **defer discard/checkout**; realpath-contain paths, cap msg length, push-current-branch only; **defer discard/checkout**; realpath-contain paths, cap msg length,