@gavin-hu/my-pi-agent 0.20.0 → 0.22.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 (298) hide show
  1. package/README.md +46 -30
  2. package/README.zh-CN.md +40 -25
  3. package/assets/screens/board.png +0 -0
  4. package/assets/screens/chrome.png +0 -0
  5. package/assets/screens/file-browse.png +0 -0
  6. package/assets/screens/plan-review.png +0 -0
  7. package/assets/screens/plan.png +0 -0
  8. package/docs/extensions/README.md +22 -23
  9. package/docs/extensions/board.md +397 -168
  10. package/docs/extensions/bytefly.md +234 -197
  11. package/docs/extensions/check.md +15 -17
  12. package/docs/extensions/context.md +35 -15
  13. package/docs/extensions/file-browse.md +57 -63
  14. package/docs/extensions/file-open.md +9 -11
  15. package/docs/extensions/file-read.md +12 -14
  16. package/docs/extensions/goal.md +15 -17
  17. package/docs/extensions/job.md +54 -42
  18. package/docs/extensions/memory.md +17 -19
  19. package/docs/extensions/plan.md +197 -140
  20. package/docs/extensions/question.md +16 -18
  21. package/docs/extensions/rewind.md +17 -19
  22. package/docs/extensions/serve.md +145 -0
  23. package/docs/extensions/session-bus.md +38 -16
  24. package/docs/extensions/subagent.md +23 -25
  25. package/docs/extensions/team.md +83 -44
  26. package/docs/extensions/todo.md +18 -18
  27. package/docs/extensions/watch.md +31 -31
  28. package/docs/extensions/web-access.md +2 -4
  29. package/docs/extensions/wechat.md +34 -35
  30. package/docs/extensions/worktree.md +56 -50
  31. package/extensions/board/commands.ts +79 -25
  32. package/extensions/board/format.ts +43 -24
  33. package/extensions/board/index.ts +17 -4
  34. package/extensions/board/input.ts +4 -9
  35. package/extensions/board/join.ts +5 -20
  36. package/extensions/board/lazy-page.ts +40 -0
  37. package/extensions/board/page.ts +65 -93
  38. package/extensions/board/result.ts +30 -39
  39. package/extensions/board/rows.ts +62 -25
  40. package/extensions/board/schema.ts +49 -11
  41. package/extensions/board/snapshot.ts +8 -6
  42. package/extensions/board/tone.ts +22 -0
  43. package/extensions/board/tools.ts +154 -55
  44. package/extensions/board/transport/router.ts +3 -5
  45. package/extensions/board/transport/server.ts +59 -28
  46. package/extensions/board/types.ts +36 -42
  47. package/extensions/board/view/card.ts +229 -0
  48. package/extensions/board/view/client.ts +35 -16
  49. package/extensions/board/view/dialog.ts +169 -6
  50. package/extensions/board/view/empty.ts +47 -0
  51. package/extensions/board/view/keys.ts +13 -2
  52. package/extensions/board/view/live.ts +90 -28
  53. package/extensions/board/view/names.ts +13 -4
  54. package/extensions/board/view/page.ts +38 -13
  55. package/extensions/board/view/render.ts +219 -277
  56. package/extensions/board/view/styles.ts +130 -32
  57. package/extensions/board/view/team.ts +297 -76
  58. package/extensions/bytefly/block/fallback.ts +1 -1
  59. package/extensions/bytefly/doctor/runtime.ts +5 -2
  60. package/extensions/bytefly/footer/collect/label.ts +60 -0
  61. package/extensions/bytefly/footer/collect/snapshot.ts +8 -1
  62. package/extensions/bytefly/footer/config.ts +7 -8
  63. package/extensions/bytefly/footer/register.ts +33 -4
  64. package/extensions/bytefly/footer/render/footer.ts +18 -4
  65. package/extensions/bytefly/footer/render/key.ts +46 -0
  66. package/extensions/bytefly/footer/render/layout.ts +13 -3
  67. package/extensions/bytefly/footer/render/lines.ts +10 -7
  68. package/extensions/bytefly/footer/render/segments.ts +41 -38
  69. package/extensions/bytefly/footer/render/status.ts +0 -11
  70. package/extensions/bytefly/footer/types.ts +7 -0
  71. package/extensions/bytefly/header/component.ts +4 -20
  72. package/extensions/bytefly/header/config.ts +1 -1
  73. package/extensions/bytefly/index.ts +32 -6
  74. package/extensions/bytefly/mode/editor.ts +115 -0
  75. package/extensions/bytefly/panel/commands.ts +210 -120
  76. package/extensions/bytefly/panel/format.ts +4 -4
  77. package/extensions/bytefly/panel/settings.ts +73 -6
  78. package/extensions/bytefly/panel/tui/keys.ts +2 -6
  79. package/extensions/bytefly/update/cache.ts +1 -1
  80. package/extensions/bytefly/update/register.ts +4 -4
  81. package/extensions/bytefly/working/config.ts +5 -7
  82. package/extensions/bytefly/working/format.ts +10 -13
  83. package/extensions/bytefly/working/register.ts +22 -27
  84. package/extensions/check/commands.ts +3 -2
  85. package/extensions/check/render.ts +10 -1
  86. package/extensions/check/{tui.ts → view/check-screens.ts} +14 -19
  87. package/extensions/context/commands.ts +2 -2
  88. package/extensions/context/{tui.ts → view/context-report.ts} +51 -19
  89. package/extensions/file-browse/config/config.ts +4 -19
  90. package/extensions/file-browse/index.ts +89 -79
  91. package/extensions/file-browse/live/live.ts +1 -1
  92. package/extensions/file-browse/transport/router.ts +12 -4
  93. package/extensions/file-browse/transport/server.ts +61 -28
  94. package/extensions/file-browse/view/chrome.ts +4 -4
  95. package/extensions/file-browse/view/client.ts +3 -1
  96. package/extensions/file-browse/view/html.ts +73 -40
  97. package/extensions/file-browse/view/live-client.ts +2 -2
  98. package/extensions/file-browse/view/markdown.ts +13 -14
  99. package/extensions/file-browse/view/palette.ts +2 -2
  100. package/extensions/file-browse/view/raw-html.ts +9 -9
  101. package/extensions/file-browse/view/tree.ts +1 -1
  102. package/extensions/file-browse/view/urls.ts +20 -6
  103. package/extensions/file-read/render.ts +4 -4
  104. package/extensions/goal/plan-route.ts +2 -2
  105. package/extensions/goal/tui.ts +12 -2
  106. package/extensions/job/child.ts +527 -0
  107. package/extensions/job/clock.ts +142 -0
  108. package/extensions/job/commands.ts +4 -2
  109. package/extensions/job/config.ts +8 -1
  110. package/extensions/job/format.ts +22 -1
  111. package/extensions/job/log-writer.ts +13 -2
  112. package/extensions/job/registry.ts +63 -7
  113. package/extensions/job/render.ts +34 -0
  114. package/extensions/job/runtime.ts +296 -655
  115. package/extensions/job/session.ts +132 -19
  116. package/extensions/job/store.ts +7 -7
  117. package/extensions/job/tools.ts +21 -9
  118. package/extensions/job/types.ts +47 -0
  119. package/extensions/job/{tui.ts → view/jobs-screen.ts} +19 -99
  120. package/extensions/job/waiters.ts +44 -1
  121. package/extensions/memory/commands.ts +4 -2
  122. package/extensions/memory/{tui.ts → view/memory-picker.ts} +12 -12
  123. package/extensions/plan/commands.ts +12 -9
  124. package/extensions/plan/feedback.ts +62 -16
  125. package/extensions/plan/format.ts +8 -2
  126. package/extensions/plan/git-bash.ts +115 -16
  127. package/extensions/plan/index.ts +58 -51
  128. package/extensions/plan/plan-index.ts +4 -2
  129. package/extensions/plan/plan-text.ts +114 -0
  130. package/extensions/plan/plans.ts +5 -54
  131. package/extensions/plan/policy.ts +8 -10
  132. package/extensions/plan/review-lazy.ts +85 -0
  133. package/extensions/plan/review.ts +2 -2
  134. package/extensions/plan/runtime.ts +61 -41
  135. package/extensions/plan/sections.ts +1 -1
  136. package/extensions/plan/steps.ts +3 -3
  137. package/extensions/plan/todos.ts +1 -1
  138. package/extensions/plan/tools/cancel.ts +27 -62
  139. package/extensions/plan/tools/enter.ts +55 -81
  140. package/extensions/plan/tools/exit.ts +221 -238
  141. package/extensions/plan/tools/refusal.ts +18 -0
  142. package/extensions/plan/tools/steps.ts +75 -92
  143. package/extensions/plan/tools/write.ts +77 -120
  144. package/extensions/plan/tools.ts +188 -30
  145. package/extensions/plan/tui.ts +5 -5
  146. package/extensions/plan/types.ts +48 -5
  147. package/extensions/plan/web-blocks.ts +76 -5
  148. package/extensions/plan/web-chrome.ts +4 -0
  149. package/extensions/plan/web-client.ts +102 -2
  150. package/extensions/plan/web-collab.ts +4 -4
  151. package/extensions/plan/web-comments.ts +39 -8
  152. package/extensions/plan/web-composer.ts +14 -3
  153. package/extensions/plan/web-keys.ts +149 -25
  154. package/extensions/plan/web-lazy.ts +53 -0
  155. package/extensions/plan/web-markdown.ts +10 -68
  156. package/extensions/plan/web-outline.ts +22 -2
  157. package/extensions/plan/web-page.ts +56 -86
  158. package/extensions/plan/web-payload.ts +188 -0
  159. package/extensions/plan/web-plan.ts +23 -13
  160. package/extensions/plan/web-router.ts +18 -9
  161. package/extensions/plan/web-settle.ts +14 -7
  162. package/extensions/plan/web-share-session.ts +24 -55
  163. package/extensions/plan/web-share.ts +19 -37
  164. package/extensions/plan/web-write.ts +112 -0
  165. package/extensions/plan/web.ts +67 -131
  166. package/extensions/question/tools.ts +6 -2
  167. package/extensions/question/{tui.ts → view/question-screen.ts} +11 -11
  168. package/extensions/rewind/commands/commands.ts +6 -3
  169. package/extensions/rewind/state/runtime.ts +1 -1
  170. package/extensions/rewind/{view/status.ts → status.ts} +4 -4
  171. package/extensions/rewind/view/review-tui.ts +4 -4
  172. package/extensions/serve/config.ts +39 -0
  173. package/extensions/serve/index.ts +85 -0
  174. package/extensions/serve/registry.ts +260 -0
  175. package/extensions/session-bus/commands.ts +11 -6
  176. package/extensions/session-bus/join-request.ts +17 -9
  177. package/extensions/session-bus/mail-watch.ts +26 -17
  178. package/extensions/session-bus/protocol.ts +15 -3
  179. package/extensions/session-bus/resolve.ts +5 -7
  180. package/extensions/session-bus/result.ts +1 -27
  181. package/extensions/session-bus/runtime.ts +40 -12
  182. package/extensions/session-bus/store.ts +101 -19
  183. package/extensions/session-bus/tools.ts +5 -4
  184. package/extensions/session-bus/types.ts +19 -0
  185. package/extensions/session-bus/{tui.ts → view/session-list.ts} +16 -16
  186. package/extensions/subagent/agents.ts +1 -1
  187. package/extensions/subagent/commands.ts +4 -2
  188. package/extensions/subagent/format.ts +15 -15
  189. package/extensions/subagent/index.ts +1 -1
  190. package/extensions/subagent/render.ts +3 -3
  191. package/extensions/subagent/{background-tui.ts → view/agents-board.ts} +11 -11
  192. package/extensions/team/commands.ts +24 -5
  193. package/extensions/team/dispatch.ts +18 -4
  194. package/extensions/team/format.ts +17 -2
  195. package/extensions/team/index.ts +9 -8
  196. package/extensions/team/schema.ts +6 -5
  197. package/extensions/team/tools.ts +107 -45
  198. package/extensions/team/types.ts +3 -2
  199. package/extensions/todo/commands.ts +4 -2
  200. package/extensions/todo/format.ts +11 -0
  201. package/extensions/todo/render.ts +57 -0
  202. package/extensions/todo/runtime.ts +1 -1
  203. package/extensions/todo/tools.ts +1 -1
  204. package/extensions/todo/{tui.ts → view/todo-screen.ts} +18 -90
  205. package/extensions/todo/widget.ts +47 -0
  206. package/extensions/watch/commands.ts +4 -2
  207. package/extensions/watch/format.ts +36 -7
  208. package/extensions/watch/render.ts +57 -0
  209. package/extensions/watch/runtime.ts +27 -22
  210. package/extensions/watch/tools.ts +4 -4
  211. package/extensions/watch/{tui.ts → view/watch-screen.ts} +18 -80
  212. package/extensions/web-access/fetch/tool.ts +12 -4
  213. package/extensions/wechat/commands/commands.ts +18 -14
  214. package/extensions/wechat/index.ts +72 -37
  215. package/extensions/wechat/state/credentials.ts +1 -1
  216. package/extensions/wechat/state/state.ts +1 -1
  217. package/extensions/wechat/text/status.ts +112 -0
  218. package/extensions/wechat/types.ts +2 -2
  219. package/extensions/wechat/view/status-screen.ts +4 -103
  220. package/extensions/worktree/commands.ts +11 -9
  221. package/extensions/worktree/enter.ts +2 -2
  222. package/extensions/worktree/exit.ts +2 -2
  223. package/extensions/worktree/index.ts +5 -5
  224. package/extensions/worktree/screen.ts +3 -3
  225. package/extensions/worktree/status.ts +2 -2
  226. package/extensions/worktree/tools.ts +113 -116
  227. package/lib/README.md +28 -13
  228. package/lib/board/actions.ts +111 -0
  229. package/lib/board/artifact.ts +149 -0
  230. package/lib/board/card.ts +163 -52
  231. package/lib/board/config.ts +58 -0
  232. package/lib/board/contract.ts +113 -0
  233. package/lib/board/join.ts +38 -0
  234. package/lib/board/lanes.ts +182 -0
  235. package/lib/board/lead.ts +130 -0
  236. package/lib/board/limits.ts +78 -0
  237. package/lib/board/links.ts +31 -10
  238. package/lib/board/page-pointer.ts +30 -5
  239. package/lib/board/read.ts +83 -0
  240. package/lib/board/reason.ts +102 -0
  241. package/lib/board/round-text.ts +68 -6
  242. package/lib/board/round.ts +31 -15
  243. package/lib/board/rules.ts +151 -307
  244. package/lib/board/seat.ts +35 -0
  245. package/lib/board/session.ts +199 -51
  246. package/lib/board/skipped.ts +22 -0
  247. package/lib/board/steps.ts +487 -0
  248. package/lib/board/store.ts +119 -36
  249. package/lib/board/tone.ts +92 -0
  250. package/lib/board/view.ts +81 -63
  251. package/lib/bus-request.ts +83 -0
  252. package/{extensions/watch → lib}/child.ts +40 -21
  253. package/lib/env.ts +65 -7
  254. package/lib/format.ts +13 -0
  255. package/lib/http/index.ts +17 -11
  256. package/lib/http/mount.ts +142 -0
  257. package/lib/http/port.ts +30 -0
  258. package/lib/http/serve.ts +170 -46
  259. package/lib/http/server.ts +3 -3
  260. package/lib/lazy.ts +45 -0
  261. package/lib/plan-entry.ts +46 -21
  262. package/lib/plans/paths.ts +82 -0
  263. package/lib/policy.ts +9 -6
  264. package/lib/report.ts +3 -2
  265. package/lib/requirements.ts +10 -10
  266. package/lib/session-label.ts +129 -7
  267. package/lib/session-roster.ts +43 -1
  268. package/lib/session-tool.ts +39 -22
  269. package/lib/stray-fields.ts +7 -2
  270. package/lib/tool-names.ts +5 -10
  271. package/lib/tui/README.md +29 -11
  272. package/lib/tui/chrome.ts +16 -15
  273. package/lib/tui/cursor.ts +18 -3
  274. package/lib/tui/glyphs.ts +11 -11
  275. package/lib/tui/render-cache.ts +29 -0
  276. package/lib/tui/tokens.ts +33 -2
  277. package/lib/tui/tool.ts +33 -4
  278. package/lib/web/README.md +21 -0
  279. package/lib/web/client-runtime.ts +27 -1
  280. package/lib/web/components.ts +5 -1
  281. package/lib/web/index.ts +1 -0
  282. package/lib/web/markdown.ts +83 -0
  283. package/lib/web/markup.ts +20 -2
  284. package/lib/web/runtime.ts +9 -10
  285. package/package.json +8 -2
  286. package/skills/init/SKILL.md +5 -5
  287. package/skills/next/SKILL.md +3 -5
  288. package/extensions/board/config.ts +0 -36
  289. package/extensions/board/seat.ts +0 -28
  290. package/lib/tui/index.ts +0 -34
  291. package/skills/project-docs/SKILL.md +0 -133
  292. package/skills/project-docs/references/audit.md +0 -131
  293. package/skills/project-docs/references/changelog.md +0 -105
  294. package/skills/project-docs/references/discovery.md +0 -127
  295. package/skills/project-docs/references/readme.md +0 -80
  296. package/skills/project-docs/references/release.md +0 -84
  297. package/skills/project-docs/references/roadmap.md +0 -93
  298. package/skills/project-docs/scripts/state.ts +0 -316
@@ -7,25 +7,23 @@ for it, or kill it.
7
7
 
8
8
  ## Capabilities
9
9
 
10
- Status records what a reader can rely on: **Shipped** is in a tagged release, **Unreleased** is complete in the current tree but not yet tagged, and **Partial** has one released part and one unreleased part. Rows are ordered by user value, highest first.
11
-
12
- | Capability | How | What you get | Status |
13
- |---|---|---|---|
14
- | Background execution | `job` (`start`) | A long build, test suite, server, or watcher keeps running while the turn moves on. | Shipped |
15
- | Job listing | `job` (`list`), `/jobs` | This session's jobs with status and elapsed time, and a live peer session's tagged `peer`. | Shipped |
16
- | Polling and waiting | `job` (`status`, `logs`, `wait`) | One call returns a job's status, a bounded output tail, or blocks until it finishes. | Shipped |
17
- | Stopping jobs | `job` (`kill` with `signal`) | A running job receives `SIGTERM`, `SIGKILL`, or `SIGINT`, and a finished one can be cleared. | Shipped |
18
- | Selective clear | `job` (`clear` with `id`, `all`) | Clear one finished record by id, or remove running jobs with `all` after a confirmation in the screen. | Shipped |
19
- | Start deadline | `timeoutMs` on `start` | A job is killed after the requested wall-clock limit instead of running until the session ends. | Shipped |
20
- | Kill escalation | `killGraceMs` | A kill sends `SIGTERM` first, then `SIGKILL` after the grace period, on a user kill and on shutdown. | Shipped |
21
- | Stdin driving | `job` (`send` with `input`, `newline`, `eof`) | A line or a bare keystroke reaches a running job started with `stdin: true`, and `eof` closes its input. | Shipped |
22
- | Rotating logs | `job` (`logs`), `job.maxLogBytes` | stdout and stderr stream to an append-only log that rotates at 8 MiB, so a chatty job cannot fill the disk. | Shipped |
23
- | Status chips | `job.showStatus` | `▸ N` running and `✗ N` unreported-failure counts in the footer. | Shipped |
24
- | Completion reporting | `job` (`wake`), `job.wakeOnFinish` | A finished job is reported at the next turn, or triggers one as soon as the agent is idle. | Shipped |
25
- | Job screen | `/jobs` | Select a job, open its log, kill it, or clear finished ones, with a confirmation on the destructive verbs. | Shipped |
26
- | Detached lifetime | `job` (`start`, `detached`) | A POSIX job outlives the session and is reattached next time; Windows refuses the detach instead of faking one. | Shipped |
27
- | Finished-job pruning | `maxJobs` | The registry drops the oldest finished records once the configured count is exceeded. | Shipped |
28
- | Structured result | tool-result `details` | Every call returns a `JobDetails` record of the job and the action's outcome. | Shipped |
10
+ | Capability | How | What you get |
11
+ |---|---|---|
12
+ | Background execution | `job` (`start`) | A long build, test suite, server, or watcher keeps running while the turn moves on. |
13
+ | Job listing | `job` (`list`), `/jobs` | This session's jobs with status and elapsed time, and a live peer session's tagged `peer`. |
14
+ | Polling and waiting | `job` (`status`, `logs`, `wait`) | One call returns a job's status, a bounded output tail, or blocks until it finishes. |
15
+ | Stopping jobs | `job` (`kill` with `signal`) | A running job receives `SIGTERM`, `SIGKILL`, or `SIGINT`, and a finished one can be cleared. |
16
+ | Selective clear | `job` (`clear` with `id`, `all`) | Clear one finished record by id, or remove running jobs with `all` after a confirmation in the screen. |
17
+ | Start deadline | `timeoutMs` on `start` | A job is killed after the requested wall-clock limit instead of running until the session ends. |
18
+ | Kill escalation | `killGraceMs` | A kill sends `SIGTERM` first, then `SIGKILL` after the grace period, on a user kill and on shutdown. |
19
+ | Stdin driving | `job` (`send` with `input`, `newline`, `eof`) | A line or a bare keystroke reaches a running job started with `stdin: true`, and `eof` closes its input. |
20
+ | Rotating logs | `job` (`logs`), `job.maxLogBytes` | stdout and stderr stream to an append-only log that rotates at 8 MiB, so a chatty job cannot fill the disk. |
21
+ | Status chips | `job.showStatus` | `▸ N` running and `✗ N` unreported-failure counts in the footer. |
22
+ | Completion reporting | `job` (`wake`), `job.wakeOnFinish` | A finished job is reported at the next turn, or triggers one as soon as the agent is idle. |
23
+ | Job screen | `/jobs` | Select a job, open its log, kill it, or clear finished ones, with a confirmation on the destructive verbs. |
24
+ | Detached lifetime | `job` (`start`, `detached`) | A POSIX job outlives the session and is reattached next time; Windows refuses the detach instead of faking one. |
25
+ | Finished-job pruning | `maxJobs` | The registry drops the oldest finished records once the configured count is exceeded. |
26
+ | Structured result | tool-result `details` | Every call returns a `JobDetails` record of the job and the action's outcome. |
29
27
 
30
28
  ## Quickstart
31
29
 
@@ -210,7 +208,7 @@ are in
210
208
  | `maxLogBytes` | `8388608` | Bytes a log segment may reach before it rotates to `<id>.log.1`; `0` keeps logs unbounded. |
211
209
  | `killGraceMs` | `5000` | Grace before SIGTERM escalates to SIGKILL. |
212
210
  | `repaintMs` | `1000` | Status-chip refresh interval while jobs run. |
213
- | `sessionTtlMs` | `60000` | How long a session heartbeat is trusted before its jobs may be reaped. |
211
+ | `sessionTtlMs` | `60000` | How old a session heartbeat may be before its pid is re-checked for reuse. |
214
212
  | `registryDir` | — | Override the registry/log directory. |
215
213
 
216
214
  ## Security
@@ -236,7 +234,9 @@ rewritten.
236
234
  kill or clear it, and the tool's `clear` refuses that record too; the tool can
237
235
  still take one over by explicit id (`status`/`logs`/`kill`, where `kill`
238
236
  adopts it). Chips, completion notices, and pruning stay this session's own, so
239
- a peer's finished job waits for that session to clear it.
237
+ a peer's finished job waits for that session to clear it — including when that
238
+ session has been idle long enough for its heartbeat to age, because the
239
+ heartbeat only ticks while a job is running.
240
240
  - **A carriage return is not a line break.** Output is split on `\n` only; a
241
241
  progress rewrite (`10%\r50%\r100%`) is one line whose sanitized form keeps the
242
242
  text after the last `\r`. A program that only ever emits `\r` therefore
@@ -279,7 +279,7 @@ rewritten.
279
279
  | `outputSchema` / `structuredContent` | None. Results return `JobDetails` in tool-result `details` only. |
280
280
  | State storage | One durable registry file per session, `~/.pi/agent/jobs/<projectKey>/registry-<sessionHash>.json` (keyed by the session cwd, so entering a worktree does not move it), merged from every session file on load; a dead session's records are adopted and a legacy shared `registry.json` is migrated once. Ids are reserved with an atomic `O_EXCL` `<id>.lock` before `start`, and a POSIX job's exit code is written to a per-job `.status` file. Tool results carry `JobDetails`; unreported completions arrive as a shared transcript notice (`my-pi-agent/notice`) at `before_agent_start`. |
281
281
  | Lifecycle | `session_start` loads and reconciles the registry and arms `onFinish` and `onComplete`; `session_shutdown` kills session-owned jobs and clears both status chips. `session_tree` repaints; `agent_start`/`agent_settled` track busy; `context` prunes stale notices of its own source. |
282
- | Event bus | Each job that reaches a terminal state is published on `my-pi-agent/job-finished` (`lib/events.ts`) with its id, label, status, exit code, and signal, from the one `settle` path every transition goes through. bytefly's notify capability subscribes there instead of importing this extension. |
282
+ | Event bus | Each job that reaches a terminal state is published on `my-pi-agent/job-finished` (`lib/events.ts`) with its id, label, status, exit code, and signal, from the one path every transition goes through — a close event, a pid observed gone on the clock, a gone peer's leftover reaped, and an orphan killed while the registry loads — which announces the completion and fires the one wake turn together. A peer's record settled here is adopted, so its completion is this session's to report. bytefly's notify capability subscribes there instead of importing this extension. |
283
283
 
284
284
  ## Design notes
285
285
 
@@ -322,10 +322,13 @@ rewritten.
322
322
  per session, `start` claims the next `j<n>` with an `O_EXCL` `<id>.lock`
323
323
  before spawning, so two sessions cannot pick the same id from a stale read;
324
324
  the reservation is pruned once the id is committed to a registry file.
325
- - **Sessions heartbeat; reconciliation is owner-aware.** Each session writes a
326
- liveness marker, so a peer's live non-detached job is not reaped until its
327
- owner's marker expires. `persist` merges onto a fresh read and drops ids this
328
- session deleted.
325
+ - **Sessions heartbeat; ownership is the process.** Each session writes a liveness
326
+ marker (its pid, that process's start time, and its last beat), and the beat only
327
+ ticks while a job runs — so a session that has finished its work goes quiet rather
328
+ than dying. Only a session that is *gone* — its pid is dead, or a reused one —
329
+ gives up its records: a quiet peer keeps its file, its marker, and its jobs, and a
330
+ peer's live non-detached job is never reaped. `persist` merges onto a fresh read and
331
+ drops ids this session deleted.
329
332
  - **Exit codes survive a session boundary.** A POSIX job is spawned behind an
330
333
  `EXIT` trap that writes `$?` to a per-job `.status` file (path passed in the
331
334
  environment); a later session reads it when it finds a dead pid and reports
@@ -336,14 +339,17 @@ rewritten.
336
339
  `detached` dev server survives.
337
340
  - **Pid reuse is guarded by a start-time token.** Before signalling an unowned
338
341
  pid, its best-effort start token (`ps -o lstart=`) is re-checked; a mismatch
339
- is treated as gone instead of as a signal. Where no token is available the
340
- check degrades to liveness.
342
+ is treated as gone instead of as a signal. The same token is written into a
343
+ session's marker, so a pid that has been reused is a gone session rather than a
344
+ quiet one. Where no token is available the check degrades to liveness.
341
345
  - **Reattached jobs are polled.** A reattached detached job has no child
342
346
  handle, so its `close` event never fires; the repaint clock polls it and
343
347
  settles it (recovering an exit code from the status file, else `unknown`)
344
348
  when the pid disappears.
345
349
  - **Shared seams, job policy.** The spawn/tree-kill/liveness seam
346
- (`lib/spawn.ts`), the byte-safe line splitter (`lib/lines.ts`), the
350
+ (`lib/spawn.ts`), the command supervisor (`lib/child.ts`, which `watch` drives
351
+ too: one SIGTERM → SIGKILL body, each extension's own grace), the byte-safe
352
+ line splitter (`lib/lines.ts`), the
347
353
  untrusted-line boundary (`lib/format.ts`), the pending-report coordinator
348
354
  (`lib/report.ts`), the status chips (`lib/tui/status-controller.ts`), and the
349
355
  `/jobs` screen frame (`lib/tui/dock-screen.ts`) are shared with `watch`; this
@@ -387,19 +393,22 @@ rewritten.
387
393
  | `index.ts` | Factory: registers the tool/command and wires events, including the shared `lib/report.ts` completion reporter. |
388
394
  | `schema.ts` | Parameter schema and pure validation (a `JobCall` union). |
389
395
  | `config.ts` | The `job` section of `bytefly.json`: loading and clamping. |
390
- | `format.ts` | Pure formatting, duration, and transcript outcome-line helpers; sanitization is `lib/format.ts`'s `sanitizeUntrustedLine`. |
396
+ | `format.ts` | Pure formatting, duration, and transcript outcome-line helpers, plus the job row both surfaces draw; sanitization is `lib/format.ts`'s `sanitizeUntrustedLine`. |
391
397
  | `paths.ts` | Session/marker/registry/status file-name helpers. |
392
- | `registry.ts` | Per-session registry load/merge, legacy migration, and pure reconciliation. |
398
+ | `registry.ts` | Per-session registry load/merge under `<agent-dir>/jobs/<project>/`, legacy migration, and the pure reconciliation a load runs — `loadRecords` merges every file, recovers dead pids, and classifies the survivors and orphans. |
393
399
  | `reservations.ts` | Atomic `O_EXCL` job-id reservation and release. |
394
400
  | `status.ts` | `EXIT`-trap exit-status file (write path via env, read on reattach). |
395
- | `session.ts` | Per-session heartbeat markers and owner-liveness rules. |
396
- | `store.ts` | Durable store: registry dir, this session's atomic merge-write, deletions. |
401
+ | `session.ts` | Per-session heartbeat markers and the ownership rule: `live`, `quiet`, or `gone`. |
402
+ | `store.ts` | Durable store: the registry directory (`<agent-dir>/jobs/<project>/`), this session's atomic merge-write, deletions. |
397
403
  | `logs.ts` | Bounded, sanitized log-tail reading. |
398
404
  | `ui.ts` | Footer status chips and the failure alert, over the shared `lib/tui/status-controller.ts` (chips, attached context, `notify`). |
399
405
  | `waiters.ts` | `wait` resolver bookkeeping. |
400
406
  | `log-writer.ts` | Per-job log sink: write stream, line split, rotation queue, and the output-driven repaint window. |
401
- | `runtime.ts` | Composition: job table, child handles, process events, repaint clock. |
402
- | `tui.ts` | The `/jobs` screen (a `DockListScreen` subclass: job rows, focus block, counts, verbs) and the `JobResult` transcript block over the shared `TailResult`. |
407
+ | `runtime.ts` | The job table and the durable record: load and reconcile, the one settle path that announces a completion and its wake turn (holding either until the session arms its listener), waiters, clear, shutdown. |
408
+ | `child.ts` | A job's process and its output: the spawn policy, the handle, the log stream and stdin, close/error settle, the signal and its SIGKILL grace, and the files a job leaves, over the shared `lib/child.ts` supervisor. |
409
+ | `clock.ts` | The periodic work: the repaint clock that re-asserts the chip, and the sweep that polls the jobs this session reattached. |
410
+ | `render.ts` | The `JobResult` transcript block over the shared `TailResult`. |
411
+ | `view/jobs-screen.ts` | The `/jobs` screen (a `DockListScreen` subclass: job rows, focus block, counts, verbs), loaded on first use. |
403
412
  | `tools.ts` | The `job` tool and its transcript rendering. |
404
413
  | `commands.ts` | The `/jobs` command. |
405
414
  | `types.ts` | Shared types. |
@@ -409,10 +418,13 @@ rewritten.
409
418
  `extensions/job/` covers schema validation (`schema`), pure formatting and
410
419
  sanitization (`format`), the durable store (`store`), per-session reconciliation
411
420
  (`registry`), id reservation (`reservations`), exit-status recovery (`status`),
412
- session markers (`session`), bounded log reads and tail flags (`logs`), wait
413
- bookkeeping (`waiters`), the `job` tool (`tools`), the `/jobs` screen (`tui`),
414
- the runtime's session-scoped list and failure notification (`runtime`), `send`
415
- to a job's stdin and the pipe's lifecycle (`runtime`), log rotation, its two
416
- segments, and the cross-segment read (`runtime`), and the
417
- install/resume/shutdown lifecycle (`extension`). Tests drive a scripted
418
- `FakeChild` and a temp registry, so the suite runs without launching a process.
421
+ session markers and the ownership rule (`session`), bounded log reads and tail
422
+ flags (`logs`), log rotation and its two segments (`log-writer`), wait
423
+ bookkeeping and the wait promise (`waiters`), the `job` tool (`tools`), the
424
+ `/jobs` screen (`view/jobs-screen`), the table's session-scoped list,
425
+ reattachment, clear and failure notification (`runtime`), a job's spawn, finish,
426
+ kill, Windows policy, detached output, bounded tail and pid questions (`child`),
427
+ `send` to a job's stdin and the pipe's lifecycle (`stdin`), the repaint clock and
428
+ the external sweep (`clock`), and the install/resume/shutdown lifecycle
429
+ (`extension`). Tests drive a scripted `FakeChild` and a temp registry, so the
430
+ suite runs without launching a process.
@@ -11,22 +11,20 @@ reminded of twice.
11
11
 
12
12
  ## Capabilities
13
13
 
14
- Status records what a reader can rely on: **Shipped** is in a tagged release, **Unreleased** is complete in the current tree but not yet tagged, and **Partial** has one released part and one unreleased part. Rows are ordered by user value, highest first.
15
-
16
- | Capability | How | What you get | Status |
17
- |---|---|---|---|
18
- | Automatic recall | the `[MEMORY]` context message | Stored notes arrive before each run, bounded by a byte cap, without the user asking. | Shipped |
19
- | Durable notes | `memory` | The model adds, updates, forgets, or lists short facts that outlive the session branch. | Shipped |
20
- | Two scopes | the `scope` parameter, `/memory path` | Notes are global or per-project, each a plain markdown file you can edit by hand. | Shipped |
21
- | Repo-root anchor | the `project` store | The project store is anchored at the repository root, so a subdirectory and every worktree read the same file. | Shipped |
22
- | Note picker | `/memory` | Add, edit, forget, merge, or move a note in the TUI, with a scope filter and a reload. | Shipped |
23
- | Whole-file editing | `/memory edit`, `/memory clear` | The file in the multi-line editor, or a scope cleared behind a confirm. | Shipped |
24
- | Duplicate guard | `memory` `add` | Re-stating a stored fact in new words is a no-op that names the existing note. | Shipped |
25
- | Store health | `/memory doctor` | Counts, file bytes, the injection budget with its omissions, and near-duplicate pairs. | Shipped |
26
- | Store freshness | `memory`, `/memory reload` | A hand edit is picked up on the next read, and `reload` forces it. | Shipped |
27
- | Recall off switch | `memory.inject` | Injection can be turned off without deleting the notes, for a session that must not receive them. | Shipped |
28
- | Trust-gated project store | the `project` scope | The project file is read and written only when the project is trusted. | Shipped |
29
- | Headless coverage | `list`, `path`, `reload`, `doctor` outside `tui` | Read-only verbs notify everywhere; picker, edit, and clear require an interactive session. | Shipped |
14
+ | Capability | How | What you get |
15
+ |---|---|---|
16
+ | Automatic recall | the `[MEMORY]` context message | Stored notes arrive before each run, bounded by a byte cap, without the user asking. |
17
+ | Durable notes | `memory` | The model adds, updates, forgets, or lists short facts that outlive the session branch. |
18
+ | Two scopes | the `scope` parameter, `/memory path` | Notes are global or per-project, each a plain markdown file you can edit by hand. |
19
+ | Repo-root anchor | the `project` store | The project store is anchored at the repository root, so a subdirectory and every worktree read the same file. |
20
+ | Note picker | `/memory` | Add, edit, forget, merge, or move a note in the TUI, with a scope filter and a reload. |
21
+ | Whole-file editing | `/memory edit`, `/memory clear` | The file in the multi-line editor, or a scope cleared behind a confirm. |
22
+ | Duplicate guard | `memory` `add` | Re-stating a stored fact in new words is a no-op that names the existing note. |
23
+ | Store health | `/memory doctor` | Counts, file bytes, the injection budget with its omissions, and near-duplicate pairs. |
24
+ | Store freshness | `memory`, `/memory reload` | A hand edit is picked up on the next read, and `reload` forces it. |
25
+ | Recall off switch | `memory.inject` | Injection can be turned off without deleting the notes, for a session that must not receive them. |
26
+ | Trust-gated project store | the `project` scope | The project file is read and written only when the project is trusted. |
27
+ | Headless coverage | `list`, `path`, `reload`, `doctor` outside `tui` | Read-only verbs notify everywhere; picker, edit, and clear require an interactive session. |
30
28
 
31
29
  ## Quickstart
32
30
 
@@ -261,12 +259,12 @@ skill. Mitigations:
261
259
  | `types.ts` | `MemoryScope`, `MemoryAction`, `MemoryDetails`, the context type. |
262
260
  | `config.ts` | Defaults and the `memory` section of `bytefly.json` loading/clamping. |
263
261
  | `schema.ts` | TypeBox params/result and pure validation of action, scope, and text. |
264
- | `store.ts` | Paths, parse/read, file stamps, add/update/forget/merge/clear transforms, atomic queued write. |
262
+ | `store.ts` | Paths (`<agent-dir>/memory.md` and the project's), parse/read, file stamps, add/update/forget/merge/clear transforms, atomic queued write. |
265
263
  | `doctor.ts` | The health report (pure): counts, file bytes, the injection plan's omissions, and near-duplicate pairs. |
266
264
  | `runtime.ts` | Session view of both stores, stamp-based refresh, trust gating, mutations. |
267
265
  | `format.ts` | Pure call/result/notice text and the bounded injection body. |
268
266
  | `errors.ts` | Re-exports `messageOf`, the shared error-text extraction (defined in `lib/errors.ts`) for the tool and command. |
269
- | `tui.ts` | The `/memory` picker component (note list, inline editor, merge mark, scope move, scope filter), drawn from the `lib/tui/` kit (`titleRule`, `dockListFrame`, `listRow`, `emptyState`). |
267
+ | `view/memory-picker.ts` | The `/memory` picker component (note list, inline editor, merge mark, scope move, scope filter), loaded on first use, drawn from the `lib/tui/` kit (`titleRule`, `dockListFrame`, `listRow`, `emptyState`). |
270
268
  | `tools.ts` | `registerTool("memory", …)`. |
271
269
  | `commands.ts` | `registerCommand("memory", …)`. |
272
270
 
@@ -275,7 +273,7 @@ skill. Mitigations:
275
273
  `bun test extensions/memory` covers the pure store transforms (including the
276
274
  near-duplicate comparison key and the `add` guard), file stamps, schema and
277
275
  config validation, formatting/injection truncation, the `/memory` picker
278
- (`tui.test.ts`: rendering, navigation, scope filter, inline add/edit, forget
276
+ (`view/memory-picker.test.ts`: rendering, navigation, scope filter, inline add/edit, forget
279
277
  confirm, trust), and the extension surface (registration, `session_start`
280
278
  loading, injection and dedup, external-edit refresh, `/memory reload`, update
281
279
  and trust gating, and the `/memory` command) through the