@zhuxixi/pi-agent-board 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/IMPLEMENTATION_PLAN.md +920 -0
  2. package/LICENSE +21 -0
  3. package/PRD.md +484 -0
  4. package/PROGRESS.md +127 -0
  5. package/README.md +131 -0
  6. package/VERIFY.md +113 -0
  7. package/docs/BATCH_SELECTION_READ_FLOW.md +277 -0
  8. package/docs/EXPLORATION.md +187 -0
  9. package/docs/PTY_ATTACH_IMPLEMENTATION_PLAN.md +579 -0
  10. package/docs/superpowers/plans/2026-08-15-screenlog-gc.md +704 -0
  11. package/docs/superpowers/plans/2026-08-16-attach-double-cursor-jiggle-retry.md +499 -0
  12. package/docs/superpowers/plans/2026-08-21-dashboard-keypress-lag.md +366 -0
  13. package/docs/superpowers/specs/2026-08-15-screenlog-gc-design.md +105 -0
  14. package/docs/superpowers/specs/2026-08-16-attach-double-cursor-jiggle-retry-design.md +142 -0
  15. package/docs/superpowers/specs/2026-08-21-dashboard-keypress-lag-design.md +59 -0
  16. package/index.ts +6 -0
  17. package/package.json +81 -0
  18. package/runner/job-runner.mjs +420 -0
  19. package/runner/pty-runner.mjs +310 -0
  20. package/runner/state-runner.mjs +120 -0
  21. package/runner/title-runner.mjs +80 -0
  22. package/scripts/patch-vulns.mjs +59 -0
  23. package/src/commands/agent-board.ts +318 -0
  24. package/src/commands/attach-flow.ts +231 -0
  25. package/src/commands/bg.ts +70 -0
  26. package/src/core/atomic.mjs +145 -0
  27. package/src/core/auto-state.mjs +320 -0
  28. package/src/core/dashboard-render.mjs +10 -0
  29. package/src/core/derive.mjs +114 -0
  30. package/src/core/diagnostics.mjs +109 -0
  31. package/src/core/events.mjs +268 -0
  32. package/src/core/evidence.mjs +242 -0
  33. package/src/core/follow-up-queue.mjs +193 -0
  34. package/src/core/heuristics.mjs +240 -0
  35. package/src/core/ids.mjs +35 -0
  36. package/src/core/invocation.mjs +43 -0
  37. package/src/core/launch-options.mjs +317 -0
  38. package/src/core/launch.mjs +116 -0
  39. package/src/core/locks.mjs +80 -0
  40. package/src/core/paths.mjs +86 -0
  41. package/src/core/pid.mjs +42 -0
  42. package/src/core/prewarm-schedule.mjs +41 -0
  43. package/src/core/prompt-transport.mjs +13 -0
  44. package/src/core/pty-attach-jiggle-retry.mjs +90 -0
  45. package/src/core/pty-attach-render.mjs +51 -0
  46. package/src/core/pty-input.mjs +15 -0
  47. package/src/core/pty-links.mjs +71 -0
  48. package/src/core/pty-scroll.mjs +155 -0
  49. package/src/core/pty-support.mjs +327 -0
  50. package/src/core/repo.mjs +47 -0
  51. package/src/core/rows.mjs +290 -0
  52. package/src/core/screen-log-gc.mjs +198 -0
  53. package/src/core/screen-log.mjs +160 -0
  54. package/src/core/session-view.mjs +174 -0
  55. package/src/core/steering-prompts.mjs +34 -0
  56. package/src/core/steering.mjs +133 -0
  57. package/src/core/store.mjs +308 -0
  58. package/src/core/title.mjs +43 -0
  59. package/src/core/types.mjs +380 -0
  60. package/src/core/worktree.mjs +64 -0
  61. package/src/index.ts +109 -0
  62. package/src/runtime/service.mjs +1194 -0
  63. package/src/ui/dashboard-evidence.mjs +85 -0
  64. package/src/ui/dashboard.ts +1952 -0
  65. package/src/ui/pty-attach.ts +1378 -0
@@ -0,0 +1,920 @@
1
+ # Implementation Plan: Pi Agent Board Extension
2
+
3
+ **Status:** Draft
4
+ **Depends on:** `PRD.md`
5
+ **Last Updated:** 2026-05-30
6
+
7
+ ---
8
+
9
+ ## 1. Purpose
10
+
11
+ This document turns the PRD into an execution-ready technical plan.
12
+
13
+ It answers:
14
+
15
+ 1. what we are building first,
16
+ 2. how the MVP will work internally,
17
+ 3. what files/modules we need,
18
+ 4. what sequence we should implement in,
19
+ 5. what product decisions are now locked.
20
+
21
+ ---
22
+
23
+ ## 2. Version / platform assumptions
24
+
25
+ Implementation will target the **active Pi runtime**:
26
+
27
+ - `/opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent`
28
+
29
+ Key references already validated:
30
+
31
+ - `docs/extensions.md`
32
+ - `docs/tui.md`
33
+ - `docs/sessions.md`
34
+ - `docs/keybindings.md`
35
+ - `examples/extensions/subagent/index.ts`
36
+ - `examples/extensions/plan-mode/index.ts`
37
+ - `~/.pi/agent/npm/node_modules/pi-subagents/README.md`
38
+ - `~/.pi/agent/npm/node_modules/pi-subagents/src/...` (reference only)
39
+
40
+ ### Hard constraints
41
+
42
+ - Use **public Pi extension/session/TUI APIs** first.
43
+ - Do **not** runtime-import `pi-subagents/src/...` internals as if they are a stable library API.
44
+ - Background Pi workers are **headless**; they do not own UI. Parent dashboard owns all visualization.
45
+
46
+ ## 2.1 Product decisions locked on 2026-05-30
47
+
48
+ These decisions are now considered part of the MVP contract unless changed explicitly later.
49
+
50
+ 1. **Dashboard scope is global across projects by default.**
51
+ 2. **Primary MVP entry point is `/agent-board`.**
52
+ 3. **Design should stay extensible for a future `/bg` flow.**
53
+ 4. **Attaching to a running background session should interrupt with confirmation, then attach.**
54
+ 5. **Same-repo parallel writer sessions require worktree isolation.**
55
+ 6. **MVP may use a cheap model summarizer, with heuristics as fallback.**
56
+ 7. **Returning to the dashboard via `/agent-board` is acceptable for MVP.**
57
+
58
+ ---
59
+
60
+ ## 3. MVP implementation strategy
61
+
62
+ ## 3.1 What we will build first
63
+
64
+ We will build a **session-oriented background dashboard** for Pi.
65
+
66
+ Each dashboard row will represent:
67
+
68
+ - a real Pi session file,
69
+ - persisted agent-board metadata,
70
+ - one active or inactive background run history,
71
+ - resumable state even after the worker exits.
72
+
73
+ ## 3.2 What we will *not* build in the first pass
74
+
75
+ We will **not** start with:
76
+
77
+ - a permanent always-on daemon,
78
+ - cloud/remote execution,
79
+ - PR-aware row badges,
80
+ - shell-job rows (`! command`),
81
+ - exact Claude attach/detach parity from day one,
82
+ - direct dependency on `pi-subagents` internals.
83
+
84
+ ## 3.3 Architectural choice for MVP
85
+
86
+ ### Decision
87
+ For MVP, use a **file-backed detached runner model**, not a centralized daemon.
88
+
89
+ That means:
90
+
91
+ 1. the extension owns the dashboard and store,
92
+ 2. each background execution is launched via a detached **runner shim** process,
93
+ 3. the runner shim spawns a headless Pi worker,
94
+ 4. the shim writes durable status/event files,
95
+ 5. the dashboard rehydrates by scanning those files.
96
+
97
+ ### Why this is the best MVP choice
98
+
99
+ It gives us:
100
+
101
+ - persistence across Pi restart,
102
+ - no dependency on current extension process staying alive,
103
+ - real background work,
104
+ - simpler operational model than a per-user supervisor daemon,
105
+ - a clean path to a future daemon if needed.
106
+
107
+ ### Why not a daemon first
108
+
109
+ A real supervisor/daemon is attractive, but it adds early complexity around:
110
+
111
+ - discovery and reconnection,
112
+ - process ownership,
113
+ - shutdown/restart semantics,
114
+ - stale socket/IPC failure modes,
115
+ - multi-instance coordination.
116
+
117
+ We can reach useful Claude-like behavior without paying that cost up front.
118
+
119
+ ---
120
+
121
+ ## 4. High-level architecture
122
+
123
+ ```text
124
+ Pi Extension (interactive parent)
125
+ ├─ /agent-board command
126
+ ├─ dashboard TUI
127
+ ├─ peek panel UI
128
+ ├─ store reader/writer
129
+ ├─ job launcher
130
+ └─ attach/reply controls
131
+
132
+ Detached job-runner shim (one per active run)
133
+ ├─ owns pid/lock/status for that run
134
+ ├─ spawns headless Pi worker
135
+ ├─ parses JSON events from worker stdout
136
+ ├─ updates status.json + events.jsonl
137
+ └─ exits when worker exits
138
+
139
+ Headless Pi worker
140
+ ├─ runs against real session file
141
+ ├─ executes tools / produces assistant output
142
+ └─ exits when that run is complete
143
+ ```
144
+
145
+ ## 4.1 Parent extension responsibilities
146
+
147
+ The extension will:
148
+
149
+ - open and render the dashboard,
150
+ - dispatch new background sessions,
151
+ - tail/poll run status,
152
+ - show grouped rows,
153
+ - let the user peek/reply,
154
+ - attach to a session,
155
+ - stop/delete/pin/rename rows,
156
+ - recover dashboard state on reload/restart.
157
+
158
+ ## 4.2 Detached runner shim responsibilities
159
+
160
+ The shim will:
161
+
162
+ - create/update lock state for one run,
163
+ - spawn Pi in JSON mode,
164
+ - persist raw events,
165
+ - derive summary/state snapshots,
166
+ - mark completion/failure,
167
+ - release lock and exit.
168
+
169
+ ## 4.3 Pi worker responsibilities
170
+
171
+ The Pi worker will:
172
+
173
+ - run a single background turn (which may internally span multiple tool calls/turn loops until Pi completes the request),
174
+ - persist the actual session transcript,
175
+ - emit structured JSON events.
176
+
177
+ ---
178
+
179
+ ## 5. User-visible flows
180
+
181
+ ## 5.1 Open dashboard
182
+
183
+ User runs:
184
+
185
+ - `/agent-board`
186
+
187
+ Result:
188
+
189
+ - full-screen custom TUI component opens,
190
+ - rows across projects are loaded by default,
191
+ - live jobs are watched.
192
+
193
+ ## 5.2 Dispatch new background session
194
+
195
+ 1. User types task in dashboard input.
196
+ 2. Extension creates a new managed session record.
197
+ 3. Extension assigns a session file path.
198
+ 4. Extension launches detached runner shim.
199
+ 5. Dashboard row enters `queued` then `working`.
200
+
201
+ ## 5.3 Peek and reply
202
+
203
+ 1. User selects row and opens peek.
204
+ 2. Peek shows summary + recent output + blocker/question.
205
+ 3. User types reply.
206
+ 4. Extension appends reply by launching a new run for the same session.
207
+ 5. Row re-enters `working`.
208
+
209
+ ## 5.4 Attach
210
+
211
+ 1. User selects row and attaches.
212
+ 2. If row is idle/completed/needs_input, switch into that session file.
213
+ 3. If row is actively running, MVP behavior will be one of:
214
+ - confirm interrupt + attach, or
215
+ - block until idle.
216
+
217
+ (Needs product decision; see section 16.)
218
+
219
+ ## 5.5 Return to dashboard
220
+
221
+ MVP baseline:
222
+
223
+ - user runs `/agent-board` again from attached session.
224
+
225
+ Stretch:
226
+
227
+ - dedicated shortcut / detach flow back to dashboard.
228
+
229
+ ## 5.6 Restart / reload recovery
230
+
231
+ When Pi restarts or `/reload` happens:
232
+
233
+ 1. extension scans managed store,
234
+ 2. reconstructs rows,
235
+ 3. checks whether any runner pids are still alive,
236
+ 4. resumes watching active statuses,
237
+ 5. leaves completed rows intact.
238
+
239
+ ---
240
+
241
+ ## 6. Proposed package / file layout
242
+
243
+ Recommended repo/package structure:
244
+
245
+ ```text
246
+ package.json
247
+ README.md
248
+ PRD.md
249
+ IMPLEMENTATION_PLAN.md
250
+
251
+ src/
252
+ index.ts
253
+
254
+ commands/
255
+ agent-board.ts
256
+ bg.ts
257
+
258
+ dashboard/
259
+ dashboard-component.ts
260
+ dashboard-state.ts
261
+ dashboard-keymap.ts
262
+ peek-panel.ts
263
+ filters.ts
264
+ groups.ts
265
+
266
+ runtime/
267
+ launch-run.ts
268
+ attach-session.ts
269
+ reply-to-session.ts
270
+ derive-row-state.ts
271
+ pid.ts
272
+ locks.ts
273
+
274
+ store/
275
+ paths.ts
276
+ schemas.ts
277
+ roster.ts
278
+ migrations.ts
279
+ files.ts
280
+
281
+ summaries/
282
+ summarize.ts
283
+ heuristics.ts
284
+
285
+ safety/
286
+ worktree.ts
287
+ repo-coordination.ts
288
+
289
+ session/
290
+ session-paths.ts
291
+ session-meta.ts
292
+
293
+ test-support/
294
+ fixtures.ts
295
+ fake-events.ts
296
+
297
+ runner/
298
+ job-runner.mjs
299
+ ```
300
+
301
+ ## Important note about the runner
302
+
303
+ The detached runner should be a **plain `.mjs` file**, not a TypeScript file that assumes Pi’s internal `jiti` loader.
304
+
305
+ Reason:
306
+
307
+ - Pi can load extension TS files internally,
308
+ - but a detached external Node process should not depend on Pi’s extension loader machinery to boot.
309
+
310
+ So:
311
+
312
+ - extension code can stay in TS,
313
+ - detached runner should be plain JS/MJS.
314
+
315
+ ---
316
+
317
+ ## 7. Persistent data model
318
+
319
+ Use a user-scoped store root:
320
+
321
+ ```text
322
+ ~/.pi/agent/agent-board/
323
+ ```
324
+
325
+ Recommended layout:
326
+
327
+ ```text
328
+ ~/.pi/agent/agent-board/
329
+ roster.json
330
+ sessions/
331
+ <viewId>.jsonl
332
+ views/
333
+ <viewId>/
334
+ meta.json
335
+ state.json
336
+ runs/
337
+ <runId>/
338
+ status.json
339
+ events.jsonl
340
+ stdout.log
341
+ stderr.log
342
+ pid.json
343
+ ```
344
+
345
+ ## 7.1 `roster.json`
346
+
347
+ Global index of known rows.
348
+
349
+ Suggested shape:
350
+
351
+ ```json
352
+ {
353
+ "version": 1,
354
+ "views": ["view_abc", "view_def"]
355
+ }
356
+ ```
357
+
358
+ ## 7.2 `meta.json`
359
+
360
+ Stable row metadata.
361
+
362
+ Suggested shape:
363
+
364
+ ```json
365
+ {
366
+ "id": "view_abc",
367
+ "name": "flaky-test-fix",
368
+ "cwd": "/path/to/repo",
369
+ "sessionFile": "/Users/.../.pi/agent/agent-board/sessions/view_abc.jsonl",
370
+ "createdAt": 1760000000000,
371
+ "updatedAt": 1760000010000,
372
+ "pinned": false,
373
+ "kind": "pi-session",
374
+ "defaultModel": null,
375
+ "worktreeMode": "off",
376
+ "worktreePath": null,
377
+ "source": "agent-board"
378
+ }
379
+ ```
380
+
381
+ ## 7.3 `state.json`
382
+
383
+ Current dashboard state snapshot derived from latest run.
384
+
385
+ Suggested shape:
386
+
387
+ ```json
388
+ {
389
+ "viewId": "view_abc",
390
+ "currentRunId": "run_123",
391
+ "semanticState": "working",
392
+ "processState": "alive",
393
+ "summary": "Editing auth middleware",
394
+ "lastActivityAt": 1760000015000,
395
+ "updatedAt": 1760000015000,
396
+ "needsInput": false,
397
+ "hasError": false,
398
+ "latestAssistantPreview": "I found the issue in ...",
399
+ "latestTool": {
400
+ "name": "edit",
401
+ "path": "src/auth/middleware.ts"
402
+ }
403
+ }
404
+ ```
405
+
406
+ ## 7.4 `runs/<runId>/status.json`
407
+
408
+ Per-run durable execution snapshot.
409
+
410
+ Suggested shape:
411
+
412
+ ```json
413
+ {
414
+ "runId": "run_123",
415
+ "viewId": "view_abc",
416
+ "pid": 12345,
417
+ "startedAt": 1760000010000,
418
+ "endedAt": null,
419
+ "exitCode": null,
420
+ "semanticState": "working",
421
+ "processState": "alive",
422
+ "summary": "Running tests",
423
+ "lastActivityAt": 1760000015000,
424
+ "currentTool": "bash",
425
+ "latestAssistantPreview": "Now validating the fix",
426
+ "question": null,
427
+ "error": null
428
+ }
429
+ ```
430
+
431
+ ## 7.5 Why both row state and run state exist
432
+
433
+ We need both because:
434
+
435
+ - a row/session persists across many prompts/replies,
436
+ - a run is a single active execution attempt.
437
+
438
+ This separation makes reply/resume/attach logic much cleaner.
439
+
440
+ ---
441
+
442
+ ## 8. Session creation and execution model
443
+
444
+ ## 8.1 Creating a managed session
445
+
446
+ We will create a predictable managed session file path:
447
+
448
+ ```text
449
+ ~/.pi/agent/agent-board/sessions/<viewId>.jsonl
450
+ ```
451
+
452
+ We do **not** need to manually synthesize the whole session file up front if Pi can create it when launched with `--session <path>`.
453
+
454
+ Recommended first implementation:
455
+
456
+ - choose new session file path,
457
+ - launch Pi against that path with the initial prompt,
458
+ - let Pi create/persist the actual transcript.
459
+
460
+ ## 8.2 Launching a background run
461
+
462
+ The parent extension launches:
463
+
464
+ ```text
465
+ node runner/job-runner.mjs <args>
466
+ ```
467
+
468
+ The runner then launches Pi similar to:
469
+
470
+ ```text
471
+ pi --mode json --session <sessionFile> <prompt>
472
+ ```
473
+
474
+ Notes:
475
+
476
+ - use real cwd for the session or worktree path if isolated,
477
+ - persist stdout JSON events,
478
+ - persist stderr separately,
479
+ - update `status.json` continuously.
480
+
481
+ ## 8.3 Why use a runner shim instead of spawning Pi directly from the dashboard process
482
+
483
+ If we spawn Pi directly from the extension process:
484
+
485
+ - dashboard lifetime and child monitoring are tightly coupled,
486
+ - a parent exit/reload can orphan derived state updates,
487
+ - status persistence becomes fragile.
488
+
489
+ The shim solves that by being the durable monitor for one run.
490
+
491
+ ## 8.4 Runner locking rules
492
+
493
+ A session row should never have two active runs at once.
494
+
495
+ Enforce with:
496
+
497
+ - `pid.json` / lock file in the current run directory,
498
+ - on new run launch, check if prior run pid is alive,
499
+ - if alive, block/interrupt/replace according to user action.
500
+
501
+ ---
502
+
503
+ ## 9. Dashboard state derivation
504
+
505
+ We need deterministic rules to turn raw events into row state.
506
+
507
+ ## 9.1 Semantic state rules
508
+
509
+ ### While runner alive
510
+ - `queued` if worker process started but no meaningful activity yet
511
+ - `working` once assistant/tool activity begins
512
+
513
+ ### After worker exits successfully
514
+ - `needs_input` if final assistant output is asking for a decision / clarification
515
+ - `completed` if task appears finished
516
+ - `idle` only for sessions backgrounded without a one-shot task framing, or when explicitly marked as still open-ended
517
+
518
+ ### After worker exits unsuccessfully
519
+ - `failed`
520
+
521
+ ### If explicitly stopped by user
522
+ - `stopped`
523
+
524
+ ## 9.2 Process/liveness rules
525
+
526
+ - `alive` if run pid exists and is live
527
+ - `exited` otherwise
528
+
529
+ ## 9.3 Summary derivation rules (MVP)
530
+
531
+ MVP summaries should use a **cheap model summarizer when available**, with deterministic heuristics as fallback.
532
+
533
+ Priority order:
534
+
535
+ 1. cheap model summary generated from latest meaningful activity/output
536
+ 2. active tool summary (`Editing …`, `Running tests …`)
537
+ 3. explicit blocker/question extracted from latest assistant text
538
+ 4. first sentence of latest assistant output
539
+ 5. stderr/error summary if failed
540
+ 6. fallback status text (`Queued`, `Running…`, `In Progress`, `Done`)
541
+
542
+ ## 9.4 Needs-input heuristics
543
+
544
+ Initial heuristic triggers:
545
+
546
+ - latest assistant text ends in a direct question,
547
+ - contains phrases like `need your input`, `which option`, `should I`, `please confirm`,
548
+ - runner sees explicit structured blocker markers if we later add them.
549
+
550
+ Later we can replace or augment this with a lightweight classifier.
551
+
552
+ ---
553
+
554
+ ## 10. UI implementation plan
555
+
556
+ ## 10.1 Dashboard surface
557
+
558
+ Use `ctx.ui.custom()` with a full-screen custom TUI component.
559
+
560
+ Why:
561
+
562
+ - it is the strongest documented Pi UI primitive,
563
+ - it can fully own keyboard handling while open,
564
+ - it avoids awkward composition with transcript rows.
565
+
566
+ ## 10.2 Dashboard sections
567
+
568
+ - **Header**: title, global scope/default filters, counts, maybe active defaults
569
+ - **Grouped list**: rows by state
570
+ - **Input bar**: dispatch or filter
571
+ - **Footer**: key hints
572
+
573
+ ## 10.3 Row content (MVP)
574
+
575
+ Each row should show:
576
+
577
+ - icon/state glyph
578
+ - name
579
+ - summary
580
+ - age (`2m`, `10s`)
581
+ - cwd basename or repo label
582
+ - optional pin marker
583
+
584
+ ## 10.4 Peek panel
585
+
586
+ Implement as either:
587
+
588
+ - nested mode inside dashboard component, or
589
+ - secondary `ctx.ui.custom()` component.
590
+
591
+ Recommendation:
592
+
593
+ - keep it inside dashboard component state so navigation remains simple.
594
+
595
+ Peek content:
596
+
597
+ - state
598
+ - summary
599
+ - last meaningful output
600
+ - question/blocker if any
601
+ - reply editor/input
602
+
603
+ ## 10.5 Attach flow
604
+
605
+ Attach uses session switching APIs from Pi.
606
+
607
+ Recommended behavior:
608
+
609
+ - from dashboard, choose attach,
610
+ - if safe to attach, switch to target session file,
611
+ - preserve enough metadata so `/agent-board` can reopen dashboard later.
612
+
613
+ ## 10.6 Why dashboard should not be its own long-lived special session in V1
614
+
615
+ We do not need a dedicated dashboard transcript/session to ship MVP.
616
+
617
+ Using `/agent-board` as a fullscreen transient UI is simpler because:
618
+
619
+ - less session juggling,
620
+ - fewer stale context problems,
621
+ - easier to invoke from any session.
622
+
623
+ ---
624
+
625
+ ## 11. Safety and repository coordination
626
+
627
+ ## 11.1 MVP repo-safety rule
628
+
629
+ Assume every background coding session is **write-capable** unless explicitly read-only.
630
+
631
+ So in MVP:
632
+
633
+ - same-repo parallel writer sessions are allowed **only when each session runs in its own worktree**,
634
+ - otherwise the extension must block the second writer launch.
635
+
636
+ This avoids silent file clobbering and matches the locked product decision that worktree isolation is required for same-repo parallel writers.
637
+
638
+ ## 11.2 Worktree strategy
639
+
640
+ Recommended phased strategy:
641
+
642
+ ### Phase A
643
+ - support explicit `worktree` mode on dispatch
644
+ - create one worktree per managed session in a git repo
645
+ - run that session in the worktree path
646
+ - persist `worktreePath` in metadata
647
+ - require this mode for same-repo parallel writer sessions
648
+
649
+ ### Phase B
650
+ - make worktree isolation the default for same-repo parallel writer sessions
651
+
652
+ ### Phase C
653
+ - consider broader default-on worktrees for all managed writer sessions in git repos if product wants stricter isolation
654
+
655
+ ## 11.3 Cleanup policy
656
+
657
+ Deleting a row should be separate from deleting data.
658
+
659
+ MVP recommendation:
660
+
661
+ - deleting a row removes it from dashboard and marks it archived,
662
+ - transcript/session file is preserved by default,
663
+ - worktree deletion requires explicit confirmation.
664
+
665
+ This is safer than Claude-like destructive cleanup in V1.
666
+
667
+ ---
668
+
669
+ ## 12. Detailed milestone plan
670
+
671
+ ## Milestone 0 — scaffold and primitives
672
+
673
+ ### Goal
674
+ Create the extension skeleton and all core types/paths.
675
+
676
+ ### Tasks
677
+ - Create package structure.
678
+ - Add extension entrypoint.
679
+ - Add constants for agent-board storage root.
680
+ - Add JSON schemas/types for roster/meta/state/status.
681
+ - Add safe file helpers + atomic writes.
682
+ - Add migration/version field support.
683
+
684
+ ### Exit criteria
685
+ - Extension loads cleanly.
686
+ - `/agent-board` command exists and opens a placeholder UI.
687
+ - Store root initializes.
688
+
689
+ ---
690
+
691
+ ## Milestone 1 — detached runner + durable store
692
+
693
+ ### Goal
694
+ Be able to dispatch a background session and persist execution state.
695
+
696
+ ### Tasks
697
+ - Implement `job-runner.mjs`.
698
+ - Implement row/session creation.
699
+ - Implement run directory creation.
700
+ - Launch Pi worker in JSON mode.
701
+ - Capture stdout JSON lines and stderr logs.
702
+ - Update `runs/<runId>/status.json` continuously.
703
+ - Update row `state.json` on run completion/progress.
704
+ - Add lock/pid handling.
705
+
706
+ ### Exit criteria
707
+ - Dispatch creates session file + metadata.
708
+ - Background run survives parent Pi reload/exit.
709
+ - Reopening `/agent-board` can rediscover the row and latest status.
710
+
711
+ ---
712
+
713
+ ## Milestone 2 — dashboard list + live updates
714
+
715
+ ### Goal
716
+ Render useful grouped rows with live status.
717
+
718
+ ### Tasks
719
+ - Implement dashboard component state.
720
+ - Implement list rendering with selection.
721
+ - Implement grouping by semantic state.
722
+ - Implement polling or file-watch refresh loop.
723
+ - Implement dispatch input.
724
+ - Implement text filtering and `s:<state>` filtering.
725
+ - Add footer key hints.
726
+
727
+ ### Exit criteria
728
+ - User can dispatch from dashboard.
729
+ - Row becomes `queued` → `working` → final state.
730
+ - Dashboard reflects updates live enough for practical use.
731
+
732
+ ---
733
+
734
+ ## Milestone 3 — peek + reply
735
+
736
+ ### Goal
737
+ Support lightweight triage without attach.
738
+
739
+ ### Tasks
740
+ - Add peek state mode/panel.
741
+ - Show summary + recent output + blocker.
742
+ - Add reply input.
743
+ - Launch a new run for the same session on reply.
744
+ - Prevent overlapping runs for same session.
745
+
746
+ ### Exit criteria
747
+ - User can answer a blocked session from peek.
748
+ - Session continues from same transcript/session file.
749
+
750
+ ---
751
+
752
+ ## Milestone 4 — attach / running-session handling / recovery polish
753
+
754
+ ### Goal
755
+ Make dashboard useful alongside normal Pi sessions.
756
+
757
+ ### Tasks
758
+ - Implement attach to idle/completed/needs-input sessions.
759
+ - Decide and implement behavior for attach-while-running.
760
+ - Rehydrate dashboard on `/reload` and Pi restart.
761
+ - Add stale pid detection.
762
+ - Add stop action.
763
+ - Add rename + pin actions.
764
+
765
+ ### Exit criteria
766
+ - User can attach to a row and continue in the session.
767
+ - User can come back to `/agent-board` later and see consistent state.
768
+
769
+ ---
770
+
771
+ ## Milestone 5 — repo safety + worktree mode
772
+
773
+ ### Goal
774
+ Prevent or isolate same-repo write conflicts.
775
+
776
+ ### Tasks
777
+ - Implement repo identity detection.
778
+ - Block or warn on second active writer in same repo by default.
779
+ - Implement explicit worktree session mode.
780
+ - Persist worktree path + cleanup hooks.
781
+ - Add delete confirmations with worktree warnings.
782
+
783
+ ### Exit criteria
784
+ - No silent same-repo write collisions in supported flows.
785
+ - Same-repo parallel sessions work when worktree mode is enabled.
786
+
787
+ ---
788
+
789
+ ## Milestone 6 — polish / post-MVP parity work
790
+
791
+ ### Candidates
792
+ - `/bg` for current session
793
+ - better filtering (`a:`, repo, cwd)
794
+ - shell-job rows
795
+ - attach/detach shortcut parity
796
+ - dedicated lightweight supervisor daemon
797
+ - project-scoped filters/views layered on top of the global default dashboard
798
+
799
+ ---
800
+
801
+ ## 13. Testing plan
802
+
803
+ ## 13.1 Unit tests
804
+
805
+ Focus areas:
806
+
807
+ - store migrations
808
+ - atomic file writes
809
+ - row-state derivation
810
+ - needs-input heuristics
811
+ - summary heuristics
812
+ - repo identity detection
813
+ - worktree path handling
814
+
815
+ ## 13.2 Integration tests
816
+
817
+ Use temp dirs/repos and spawned mock/background processes to verify:
818
+
819
+ - dispatch creates durable artifacts
820
+ - runner updates status correctly from streamed JSON events
821
+ - recovery after parent exit/restart
822
+ - attach to managed session path
823
+ - reply launches new run against same session file
824
+ - same-repo concurrency safety
825
+
826
+ ## 13.3 Manual acceptance scenarios
827
+
828
+ Required manual flows:
829
+
830
+ 1. Dispatch one session and watch it finish.
831
+ 2. Dispatch two sessions in different repos.
832
+ 3. Dispatch two sessions in same repo and confirm safety rule.
833
+ 4. Peek and reply to blocked session.
834
+ 5. Attach to completed session and continue.
835
+ 6. Reload Pi and reopen `/agent-board`.
836
+ 7. Kill Pi parent while background run continues; reopen dashboard later.
837
+ 8. Delete row with/without worktree.
838
+
839
+ ---
840
+
841
+ ## 14. Key engineering decisions to lock early
842
+
843
+ 1. **Detached runner shim is plain `.mjs`, not TS.**
844
+ 2. **Managed sessions use predictable agent-board-owned session file paths.**
845
+ 3. **One row = one real session file.**
846
+ 4. **One run = one detached execution attempt against that session.**
847
+ 5. **Dashboard is a fullscreen custom UI, not a special transcript mode.**
848
+ 6. **MVP uses a cheap model summarizer when available, with heuristics fallback for summaries/state.**
849
+ 7. **MVP avoids importing `pi-subagents` internals.**
850
+
851
+ ---
852
+
853
+ ## 15. Risks and fallback choices
854
+
855
+ ## Risk 1: attach while running is messy
856
+
857
+ ### Why
858
+ Concurrent interactive attach and background worker execution against the same session is unsafe/confusing.
859
+
860
+ ### Fallback
861
+ In MVP, require:
862
+
863
+ - interrupt background run before attach, or
864
+ - attach only when run is idle/exited.
865
+
866
+ ## Risk 2: worktree support may slow MVP
867
+
868
+ ### Why
869
+ Git edge cases, dirty repos, cleanup, and path rewriting add complexity.
870
+
871
+ ### Fallback
872
+ Ship with strict same-repo single-writer rule first, then add worktree mode.
873
+
874
+ ## Risk 3: heuristic summaries may misclassify
875
+
876
+ ### Why
877
+ Assistant text is free-form.
878
+
879
+ ### Fallback
880
+ Keep state derivation conservative, and expose raw preview in peek.
881
+
882
+ ## Risk 4: session switching UX may be less seamless than Claude
883
+
884
+ ### Why
885
+ Pi extension APIs differ from Claude’s built-in product surface.
886
+
887
+ ### Fallback
888
+ Use `/agent-board` as explicit re-entry instead of forcing full detach parity early.
889
+
890
+ ---
891
+
892
+ ## 16. Product decisions resolved
893
+
894
+ These product questions have now been answered and are incorporated into the MVP plan.
895
+
896
+ 1. **Dashboard scope:** global across projects by default.
897
+ 2. **Entry point:** `/agent-board` is required for MVP.
898
+ 3. **Future extensibility:** design should remain extensible for `/bg`, but `/bg` is not required in the first implementation slice.
899
+ 4. **Attach while running:** interrupt with confirmation, then attach.
900
+ 5. **Same-repo parallel writers:** require worktree isolation.
901
+ 6. **Summary strategy:** cheap model summarizer is allowed in MVP.
902
+ 7. **Return to dashboard:** `/agent-board` is acceptable for MVP.
903
+
904
+ ---
905
+
906
+ ## 17. Next execution step
907
+
908
+ Once you confirm the product questions (or approve the defaults), the next step is:
909
+
910
+ ### Build milestone 0 + milestone 1
911
+
912
+ That means:
913
+
914
+ - scaffold package/extension,
915
+ - implement store schema,
916
+ - implement detached runner shim,
917
+ - launch first real background managed session,
918
+ - persist durable state.
919
+
920
+ That is the right first coding slice because it validates the hardest architectural assumption early.