@pi-unipi/unipi 3.0.0-alpha.2 → 3.0.0-alpha.21

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 (359) hide show
  1. package/CHANGELOG.md +292 -0
  2. package/README.md +8 -11
  3. package/docs/prefix-cache-architecture.md +14 -0
  4. package/package.json +22 -24
  5. package/packages/ask-user/README.md +55 -107
  6. package/packages/ask-user/ask-ui.ts +306 -732
  7. package/packages/ask-user/clipboard.ts +50 -0
  8. package/packages/ask-user/config.ts +74 -78
  9. package/packages/ask-user/package.json +2 -2
  10. package/packages/ask-user/questions.ts +151 -0
  11. package/packages/ask-user/skills/ask-user/SKILL.md +59 -133
  12. package/packages/ask-user/tools.ts +198 -432
  13. package/packages/autocomplete/package.json +1 -1
  14. package/packages/autocomplete/src/constants.ts +38 -43
  15. package/packages/autocomplete/src/sorting.ts +8 -0
  16. package/packages/background-tasks/package.json +2 -2
  17. package/packages/background-tasks/src/config.ts +0 -73
  18. package/packages/background-tasks/src/index.ts +20 -16
  19. package/packages/background-tasks/src/registry.ts +1 -171
  20. package/packages/background-tasks/src/types.ts +0 -32
  21. package/packages/btw/README.md +13 -56
  22. package/packages/btw/extensions/btw.ts +403 -1796
  23. package/packages/btw/package.json +5 -2
  24. package/packages/btw/skills/btw/SKILL.md +7 -143
  25. package/packages/compactor/README.md +56 -287
  26. package/packages/compactor/package.json +5 -9
  27. package/packages/compactor/skills/compactor/SKILL.md +13 -20
  28. package/packages/compactor/src/card.ts +90 -0
  29. package/packages/compactor/src/commands/index.ts +73 -130
  30. package/packages/compactor/src/compaction/compact-args.ts +5 -3
  31. package/packages/compactor/src/compaction/filter-noise.ts +1 -1
  32. package/packages/compactor/src/compaction/hooks.ts +487 -311
  33. package/packages/compactor/src/compaction/source.ts +178 -0
  34. package/packages/compactor/src/compaction/summarize.ts +586 -52
  35. package/packages/compactor/src/config/manager.ts +130 -127
  36. package/packages/compactor/src/config/schema.ts +32 -48
  37. package/packages/compactor/src/index.ts +40 -431
  38. package/packages/compactor/src/info-screen.ts +44 -190
  39. package/packages/compactor/src/session/recall-blocks.ts +1 -1
  40. package/packages/compactor/src/stats.ts +76 -0
  41. package/packages/compactor/src/tools/context-budget.ts +17 -34
  42. package/packages/compactor/src/tools/ctx-doctor.ts +45 -36
  43. package/packages/compactor/src/tools/register.ts +29 -269
  44. package/packages/compactor/src/types.ts +47 -186
  45. package/packages/core/README.md +25 -0
  46. package/packages/core/child-agent.ts +1 -0
  47. package/packages/core/command-echo.ts +63 -0
  48. package/packages/core/compaction-context.ts +41 -0
  49. package/packages/core/constants.ts +8 -38
  50. package/packages/core/events.ts +0 -53
  51. package/packages/core/fusion-status.ts +4 -0
  52. package/packages/core/global.d.ts +10 -0
  53. package/packages/core/harness-messages.ts +392 -0
  54. package/packages/core/index.ts +14 -0
  55. package/packages/core/kanboard-status.ts +49 -0
  56. package/packages/core/long-horizon-owner-status.ts +46 -0
  57. package/packages/core/model-cache.ts +81 -7
  58. package/packages/core/package.json +6 -3
  59. package/packages/core/src/attach/detect.ts +163 -0
  60. package/packages/core/src/child-agent/child-args.ts +31 -0
  61. package/packages/core/src/child-agent/delivery.ts +41 -0
  62. package/packages/core/src/child-agent/index.ts +5 -0
  63. package/packages/core/src/child-agent/readers.ts +203 -0
  64. package/packages/core/src/child-agent/runtime.ts +584 -0
  65. package/packages/core/src/evidence.ts +78 -0
  66. package/packages/core/src/hints/browser.ts +278 -0
  67. package/packages/core/src/hints/crab-data.ts +19 -0
  68. package/packages/core/src/hints/index.ts +865 -0
  69. package/packages/core/src/hints/lines.ts +607 -0
  70. package/packages/core/src/hints/store.ts +120 -0
  71. package/packages/core/src/jev/chatter.ts +24 -0
  72. package/packages/core/src/jev/settings.ts +177 -14
  73. package/packages/core/src/package-colors.ts +2 -0
  74. package/packages/core/src/settings/catalog.ts +39 -15
  75. package/packages/core/src/settings/engine.ts +48 -2
  76. package/packages/core/src/settings/hub.ts +83 -20
  77. package/packages/core/src/settings/open.ts +49 -0
  78. package/packages/core/src/settings/schema.ts +27 -7
  79. package/packages/core/src/tui/hub-kit.ts +18 -5
  80. package/packages/core/src/tui/kit.ts +198 -0
  81. package/packages/core/src/tui/progress.ts +73 -0
  82. package/packages/core/src/turn/arbiter.ts +290 -0
  83. package/packages/footer/README.md +4 -6
  84. package/packages/footer/package.json +3 -3
  85. package/packages/footer/src/glance-editor.ts +19 -11
  86. package/packages/footer/src/help.ts +1 -1
  87. package/packages/footer/src/index.ts +36 -3
  88. package/packages/footer/src/presets.ts +3 -4
  89. package/packages/footer/src/rendering/icons.ts +0 -20
  90. package/packages/footer/src/segments/compactor.ts +52 -142
  91. package/packages/footer/src/segments/status-ext.ts +0 -1
  92. package/packages/fusion/README.md +14 -4
  93. package/packages/fusion/package.json +4 -3
  94. package/packages/fusion/src/child-args.ts +1 -0
  95. package/packages/fusion/src/index.ts +161 -8
  96. package/packages/fusion/src/pi-settings.ts +57 -0
  97. package/packages/fusion/src/picker.ts +186 -51
  98. package/packages/fusion/src/preset.ts +56 -2
  99. package/packages/fusion/src/prompts.ts +1 -1
  100. package/packages/fusion/src/sidekick-runtime.ts +1 -420
  101. package/packages/fusion/src/tools.ts +107 -128
  102. package/packages/fusion/src/transcript.ts +27 -85
  103. package/packages/info-screen/package.json +2 -2
  104. package/packages/input-shortcuts/README.md +18 -30
  105. package/packages/input-shortcuts/package.json +2 -2
  106. package/packages/input-shortcuts/src/burst.ts +88 -0
  107. package/packages/input-shortcuts/src/chord-overlay.ts +20 -70
  108. package/packages/input-shortcuts/src/cleared-input.ts +97 -0
  109. package/packages/input-shortcuts/src/index.ts +99 -193
  110. package/packages/input-shortcuts/src/last-response.ts +40 -0
  111. package/packages/input-shortcuts/src/registers.ts +8 -23
  112. package/packages/input-shortcuts/src/types.ts +4 -16
  113. package/packages/input-shortcuts/src/undo-redo.ts +59 -47
  114. package/packages/kanboard/README.md +51 -47
  115. package/packages/kanboard/index.ts +293 -55
  116. package/packages/kanboard/package.json +8 -8
  117. package/packages/kanboard/skills/kanboard/SKILL.md +61 -27
  118. package/packages/kanboard/src/badges.ts +93 -0
  119. package/packages/kanboard/src/bin.ts +4 -2
  120. package/packages/kanboard/src/commands.ts +218 -84
  121. package/packages/kanboard/src/debug.ts +20 -0
  122. package/packages/kanboard/src/guard.ts +267 -109
  123. package/packages/kanboard/src/monitor.ts +330 -0
  124. package/packages/kanboard/src/notice-buffer.ts +74 -0
  125. package/packages/kanboard/src/progress.ts +27 -0
  126. package/packages/kanboard/src/reminders.ts +234 -0
  127. package/packages/kanboard/src/settings.ts +69 -15
  128. package/packages/kanboard/src/shapes.ts +5 -0
  129. package/packages/long-horizon/index.ts +190 -13
  130. package/packages/long-horizon/package.json +3 -3
  131. package/packages/long-horizon/src/commands.ts +103 -7
  132. package/packages/long-horizon/src/compaction-brief.ts +35 -0
  133. package/packages/long-horizon/src/engine/continuation.ts +84 -15
  134. package/packages/long-horizon/src/engine/goal-state.ts +64 -13
  135. package/packages/long-horizon/src/engine/nudge-stash.ts +71 -0
  136. package/packages/long-horizon/src/engine/ralph.ts +3 -2
  137. package/packages/long-horizon/src/engine/runaway.ts +68 -11
  138. package/packages/long-horizon/src/engine/verifier.ts +19 -0
  139. package/packages/long-horizon/src/gate.ts +37 -12
  140. package/packages/long-horizon/src/judge/resolve.ts +1 -0
  141. package/packages/long-horizon/src/owner.ts +35 -2
  142. package/packages/long-horizon/src/progress.ts +87 -0
  143. package/packages/long-horizon/src/prompts/goal.ts +1 -1
  144. package/packages/long-horizon/src/runtime.ts +172 -18
  145. package/packages/long-horizon/src/settings.ts +54 -39
  146. package/packages/long-horizon/src/tools/goal.ts +6 -0
  147. package/packages/long-horizon/src/tools/graph.ts +1 -1
  148. package/packages/long-horizon/src/tools/swarm.ts +3 -3
  149. package/packages/mcp/package.json +2 -2
  150. package/packages/memory/commands.ts +7 -2
  151. package/packages/memory/index.ts +210 -32
  152. package/packages/memory/package.json +3 -3
  153. package/packages/memory/save-session.ts +264 -0
  154. package/packages/memory/settings.ts +17 -0
  155. package/packages/memory/tools.ts +253 -203
  156. package/packages/notify/package.json +2 -2
  157. package/packages/skill-registry/README.md +53 -16
  158. package/packages/skill-registry/index.ts +230 -0
  159. package/packages/skill-registry/package.json +19 -8
  160. package/packages/skill-registry/src/editor.ts +206 -0
  161. package/packages/skill-registry/src/judge.ts +289 -0
  162. package/packages/skill-registry/src/registry.ts +87 -0
  163. package/packages/skill-registry/src/settings.ts +259 -0
  164. package/packages/skill-registry/src/vault.ts +80 -0
  165. package/packages/subagents/README.md +39 -119
  166. package/packages/subagents/package.json +6 -13
  167. package/packages/subagents/skills/subagents/SKILL.md +18 -42
  168. package/packages/subagents/src/agents.ts +213 -0
  169. package/packages/subagents/src/cards.ts +182 -0
  170. package/packages/subagents/src/index.ts +609 -1084
  171. package/packages/subagents/src/manager.ts +429 -0
  172. package/packages/subagents/src/profiles.ts +130 -0
  173. package/packages/subagents/src/transcript.ts +154 -0
  174. package/packages/subagents/src/ui.ts +389 -0
  175. package/packages/unipi/bundled.js +39756 -45569
  176. package/packages/unipi/index.ts +55 -10
  177. package/packages/updater/package.json +2 -2
  178. package/packages/utility/README.md +76 -69
  179. package/packages/utility/package.json +2 -2
  180. package/packages/utility/skills/image/SKILL.md +37 -0
  181. package/packages/utility/skills/utility/SKILL.md +17 -60
  182. package/packages/utility/src/answer/extract.ts +128 -0
  183. package/packages/utility/src/answer/index.ts +213 -0
  184. package/packages/utility/src/answer/reply.ts +133 -0
  185. package/packages/utility/src/answer/web.ts +167 -0
  186. package/packages/utility/src/attach/index.ts +205 -0
  187. package/packages/utility/src/commands.ts +38 -142
  188. package/packages/utility/src/diagnostics/engine.ts +50 -5
  189. package/packages/utility/src/image/index.ts +33 -0
  190. package/packages/utility/src/image/models.ts +221 -0
  191. package/packages/{image/src → utility/src/image}/recognize.ts +2 -2
  192. package/packages/utility/src/image/settings.ts +178 -0
  193. package/packages/{image/src/image-source.ts → utility/src/image/source.ts} +1 -1
  194. package/packages/utility/src/image/tools.ts +168 -0
  195. package/packages/utility/src/image/transports.ts +186 -0
  196. package/packages/utility/src/index.ts +68 -389
  197. package/packages/utility/src/lifecycle/cleanup.ts +116 -311
  198. package/packages/utility/src/rename/gate.ts +102 -0
  199. package/packages/utility/src/rename/index.ts +191 -0
  200. package/packages/utility/src/rename/session.ts +170 -0
  201. package/packages/utility/src/render/delegated.ts +285 -0
  202. package/packages/utility/src/render/harness.ts +683 -0
  203. package/packages/utility/src/render/parse.ts +156 -0
  204. package/packages/utility/src/render/pi-settings.ts +38 -0
  205. package/packages/utility/src/render/reply-bg.ts +307 -0
  206. package/packages/utility/src/render/simple.ts +724 -0
  207. package/packages/utility/src/render/spacing.ts +235 -0
  208. package/packages/utility/src/render/styled.ts +251 -0
  209. package/packages/utility/src/render/tools.ts +353 -0
  210. package/packages/utility/src/settings.ts +166 -233
  211. package/packages/utility/src/types.ts +1 -222
  212. package/packages/watchdog/index.ts +17 -6
  213. package/packages/watchdog/package.json +3 -3
  214. package/packages/watchdog/src/config.ts +3 -2
  215. package/packages/web-api/package.json +2 -2
  216. package/packages/workflow/README.md +3 -0
  217. package/packages/workflow/index.ts +0 -2
  218. package/packages/workflow/package.json +2 -2
  219. package/packages/workflow/src/permission/decide.ts +6 -4
  220. package/packages/workflow/src/permission/index.ts +17 -7
  221. package/packages/workflow/src/permission/settings.ts +39 -4
  222. package/packages/workflow/src/plan/index.ts +19 -4
  223. package/packages/background-tasks/extensions/delegate-child.ts +0 -1
  224. package/packages/background-tasks/src/context-parent-snapshot.ts +0 -142
  225. package/packages/background-tasks/src/context-token-budget.ts +0 -903
  226. package/packages/background-tasks/src/context-visible-conversation-v2.ts +0 -551
  227. package/packages/background-tasks/src/delegate/artifacts.ts +0 -487
  228. package/packages/background-tasks/src/delegate/budget.ts +0 -415
  229. package/packages/background-tasks/src/delegate/hook-contract-evidence.json +0 -18
  230. package/packages/background-tasks/src/delegate/hook-contract.ts +0 -154
  231. package/packages/background-tasks/src/delegate/launch.ts +0 -484
  232. package/packages/background-tasks/src/delegate/result-package.ts +0 -459
  233. package/packages/background-tasks/src/delegate/runner.ts +0 -430
  234. package/packages/background-tasks/src/delegate/seed.ts +0 -423
  235. package/packages/background-tasks/src/delegate/types.ts +0 -323
  236. package/packages/background-tasks/src/delegate-child-extension.ts +0 -978
  237. package/packages/background-tasks/src/delegate-extension.ts +0 -654
  238. package/packages/background-tasks/src/fixtures/delegate-context-incident.json +0 -17
  239. package/packages/compactor/skills/compactor-detail/SKILL.md +0 -116
  240. package/packages/compactor/skills/compactor-doctor/SKILL.md +0 -71
  241. package/packages/compactor/skills/compactor-stats/SKILL.md +0 -51
  242. package/packages/compactor/src/compaction/build-sections.ts +0 -76
  243. package/packages/compactor/src/compaction/extract/goals.ts +0 -36
  244. package/packages/compactor/src/compaction/extract/preferences.ts +0 -40
  245. package/packages/compactor/src/compaction/format.ts +0 -53
  246. package/packages/compactor/src/compaction/merge.ts +0 -143
  247. package/packages/compactor/src/config/presets.ts +0 -160
  248. package/packages/compactor/src/executor/executor.ts +0 -233
  249. package/packages/compactor/src/executor/runtime.ts +0 -115
  250. package/packages/compactor/src/security/evaluator.ts +0 -89
  251. package/packages/compactor/src/security/policy.ts +0 -96
  252. package/packages/compactor/src/security/scanner.ts +0 -65
  253. package/packages/compactor/src/session/auto-inject.ts +0 -60
  254. package/packages/compactor/src/session/db.ts +0 -325
  255. package/packages/compactor/src/session/extract.ts +0 -144
  256. package/packages/compactor/src/session/resume-inject.ts +0 -64
  257. package/packages/compactor/src/session/snapshot.ts +0 -327
  258. package/packages/compactor/src/tools/ctx-batch-execute.ts +0 -41
  259. package/packages/compactor/src/tools/ctx-execute-file.ts +0 -23
  260. package/packages/compactor/src/tools/ctx-execute.ts +0 -23
  261. package/packages/compactor/src/tools/ctx-stats.ts +0 -96
  262. package/packages/image/README.md +0 -99
  263. package/packages/image/package.json +0 -61
  264. package/packages/image/skills/image/SKILL.md +0 -76
  265. package/packages/image/src/generate.ts +0 -256
  266. package/packages/image/src/index.ts +0 -135
  267. package/packages/image/src/models.ts +0 -519
  268. package/packages/image/src/openai-images-api.ts +0 -282
  269. package/packages/image/src/register-providers.ts +0 -209
  270. package/packages/image/src/settings.ts +0 -173
  271. package/packages/image/src/tools.ts +0 -326
  272. package/packages/input-shortcuts/src/clipboard.ts +0 -119
  273. package/packages/kanboard/src/runner.ts +0 -817
  274. package/packages/skill-registry/skills/auto/SKILL.md +0 -465
  275. package/packages/skill-registry/skills/brainstorm/SKILL.md +0 -219
  276. package/packages/skill-registry/skills/chore-create/SKILL.md +0 -315
  277. package/packages/skill-registry/skills/chore-execute/SKILL.md +0 -314
  278. package/packages/skill-registry/skills/consolidate/SKILL.md +0 -142
  279. package/packages/skill-registry/skills/consultant/SKILL.md +0 -97
  280. package/packages/skill-registry/skills/debug/SKILL.md +0 -228
  281. package/packages/skill-registry/skills/document/SKILL.md +0 -120
  282. package/packages/skill-registry/skills/fix/SKILL.md +0 -212
  283. package/packages/skill-registry/skills/gather-context/SKILL.md +0 -145
  284. package/packages/skill-registry/skills/plan/SKILL.md +0 -231
  285. package/packages/skill-registry/skills/quick-fix/SKILL.md +0 -135
  286. package/packages/skill-registry/skills/quick-work/SKILL.md +0 -110
  287. package/packages/skill-registry/skills/research/SKILL.md +0 -251
  288. package/packages/skill-registry/skills/review-work/SKILL.md +0 -187
  289. package/packages/skill-registry/skills/scan-issues/SKILL.md +0 -195
  290. package/packages/skill-registry/skills/work/SKILL.md +0 -218
  291. package/packages/skill-registry/skills/worktree-create/SKILL.md +0 -69
  292. package/packages/skill-registry/skills/worktree-list/SKILL.md +0 -78
  293. package/packages/skill-registry/skills/worktree-merge/SKILL.md +0 -89
  294. package/packages/subagents/agents/delegate.md +0 -14
  295. package/packages/subagents/agents/oracle.md +0 -78
  296. package/packages/subagents/agents/researcher.md +0 -52
  297. package/packages/subagents/agents/reviewer.md +0 -80
  298. package/packages/subagents/agents/scout.md +0 -50
  299. package/packages/subagents/agents/worker.md +0 -59
  300. package/packages/subagents/prompts/council.md +0 -48
  301. package/packages/subagents/prompts/gather-context-and-clarify.md +0 -13
  302. package/packages/subagents/prompts/parallel-cleanup.md +0 -59
  303. package/packages/subagents/prompts/parallel-research.md +0 -50
  304. package/packages/subagents/prompts/parallel-review.md +0 -54
  305. package/packages/subagents/prompts/review-loop.md +0 -43
  306. package/packages/subagents/skills/council-mode/SKILL.md +0 -230
  307. package/packages/subagents/skills/subagents/references/constraints-and-recipes.md +0 -259
  308. package/packages/subagents/skills/subagents/references/execution-controls.md +0 -454
  309. package/packages/subagents/skills/subagents/references/management-authoring-rpc.md +0 -161
  310. package/packages/subagents/skills/subagents/references/multi-lane-orchestration.md +0 -39
  311. package/packages/subagents/skills/subagents/references/prompting-and-roles.md +0 -267
  312. package/packages/subagents/src/acceptance.ts +0 -331
  313. package/packages/subagents/src/agent-manager.ts +0 -405
  314. package/packages/subagents/src/agent-memory.ts +0 -300
  315. package/packages/subagents/src/agent-overrides.ts +0 -183
  316. package/packages/subagents/src/agent-runner.ts +0 -271
  317. package/packages/subagents/src/async-runner.ts +0 -422
  318. package/packages/subagents/src/authority-policy.ts +0 -47
  319. package/packages/subagents/src/budgets.ts +0 -285
  320. package/packages/subagents/src/child-safety.ts +0 -140
  321. package/packages/subagents/src/config.ts +0 -249
  322. package/packages/subagents/src/conversation-viewer.ts +0 -281
  323. package/packages/subagents/src/core-compat.ts +0 -94
  324. package/packages/subagents/src/custom-agents.ts +0 -343
  325. package/packages/subagents/src/file-system-retry.ts +0 -50
  326. package/packages/subagents/src/fleet-data.ts +0 -105
  327. package/packages/subagents/src/fleet-view.ts +0 -322
  328. package/packages/subagents/src/foreground-detach.ts +0 -59
  329. package/packages/subagents/src/fork-context.ts +0 -285
  330. package/packages/subagents/src/global.d.ts +0 -7
  331. package/packages/subagents/src/guide.ts +0 -129
  332. package/packages/subagents/src/mission-state.ts +0 -133
  333. package/packages/subagents/src/mission-store.ts +0 -436
  334. package/packages/subagents/src/output-limits.ts +0 -142
  335. package/packages/subagents/src/parity-types.ts +0 -315
  336. package/packages/subagents/src/pi-args.ts +0 -167
  337. package/packages/subagents/src/result-files.ts +0 -232
  338. package/packages/subagents/src/result-watcher.ts +0 -221
  339. package/packages/subagents/src/retained-children.ts +0 -176
  340. package/packages/subagents/src/run-fanout-budget.ts +0 -356
  341. package/packages/subagents/src/scheduled-runs.ts +0 -349
  342. package/packages/subagents/src/schemas.ts +0 -263
  343. package/packages/subagents/src/slash-commands.ts +0 -80
  344. package/packages/subagents/src/supervisor-channel.ts +0 -249
  345. package/packages/subagents/src/tool-handler.ts +0 -1144
  346. package/packages/subagents/src/types.ts +0 -238
  347. package/packages/subagents/src/widget.ts +0 -457
  348. package/packages/subagents/src/workflow-script.ts +0 -737
  349. package/packages/subagents/src/workflow-worker.ts +0 -384
  350. package/packages/subagents/src/worktree.ts +0 -614
  351. package/packages/utility/src/analytics/collector.ts +0 -293
  352. package/packages/utility/src/info-screen.ts +0 -80
  353. package/packages/utility/src/lifecycle/process.ts +0 -162
  354. package/packages/utility/src/prefix-cache.ts +0 -263
  355. package/packages/utility/src/skill-discovery.ts +0 -542
  356. package/packages/utility/src/tools/env.ts +0 -113
  357. package/packages/utility/src/tui/name-badge-state.ts +0 -315
  358. package/packages/utility/src/tui/name-badge.ts +0 -109
  359. /package/packages/{subagents/src → core/src/child-agent}/pi-spawn.ts +0 -0
@@ -2,40 +2,57 @@
2
2
  * @pi-unipi/kanboard — pi extension.
3
3
  *
4
4
  * Bridges the terminal to the board: `/unipi:kanboard` (open/close/onboard/
5
- * status/doctor — bare lists the commands), `/unipi:kanboard-add`,
6
- * `/unipi:kanboard-do` (opens the board-write window for one turn),
7
- * `/unipi:kanboard-autowork` (the runner loop: queue first, then claim-next).
8
- * The runner owns claim → In Progress and run-end → In Review. The board itself
9
- * is written by the Rust binary (`crates/kanboard`); this extension never edits
10
- * task files. Bash calls into the binary are gated by the write window
11
- * (src/guard.ts): reads always pass, writes need a -do turn or a running task.
5
+ * status/doctor/show — bare lists the commands), `/unipi:kanboard-add`,
6
+ * `/unipi:kanboard-do` (grants task slots + a write budget for one prompt),
7
+ * `/unipi:kanboard-autowork` (work every ready task in this session). The
8
+ * session works tasks itself — there is no runner. Continuation is the turn
9
+ * arbiter's job: src/monitor.ts proposes at most one nudge per settle (claims
10
+ * first, then the next ready autowork task). Bash calls into the Rust binary
11
+ * are gated by src/guard.ts: reads always pass, children never write, writes
12
+ * cost the -do budget (own-claim closes are free). The board itself is
13
+ * written by the binary; this extension never edits task files.
12
14
  */
13
15
 
14
16
  import { dirname } from "node:path";
15
17
  import { fileURLToPath } from "node:url";
16
18
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
19
+ import { Text } from "@earendil-works/pi-tui";
17
20
  import {
18
21
  MODULES,
19
22
  UNIPI_EVENTS,
20
23
  emitEvent,
21
24
  getPackageVersion,
25
+ getSettings,
26
+ getSharedKanboardStatus,
27
+ getSharedOwnerStatus,
22
28
  initUnipiDirs,
29
+ isChildProcess,
23
30
  registerCommandRunner,
24
- getSettings,
31
+ registerEvidenceContributor,
32
+ registerNudgeProvider,
33
+ registerProgressRenderer,
34
+ setSharedKanboardStatus,
35
+ appendProgress,
25
36
  } from "@pi-unipi/core";
26
37
 
27
38
  import { openCli, type KanboardCli } from "./src/bin.js";
28
- import { createWriteGuard } from "./src/guard.js";
39
+ import { kanboardInvocations } from "./src/guard.js";
40
+ import { maybeBadgeToolResult, registerBadgeRenderer } from "./src/badges.js";
29
41
  import {
30
- drainQueueAfterDo,
31
42
  registerKanboardCommands,
32
43
  runOpen,
33
44
  syncPiRuntime,
34
45
  runRotateTokenAction,
35
46
  runStopDaemon,
47
+ captureToBacklog,
36
48
  type CommandDeps,
37
49
  } from "./src/commands.js";
38
- import { createDebugLog, createRunner, registerPlanEventListener, type Runner } from "./src/runner.js";
50
+ import { createWriteGuard } from "./src/guard.js";
51
+ import { NOTICE_ENTRY, flushNotices, NoticeBuffer } from "./src/notice-buffer.js";
52
+ import { createKanboardMonitor } from "./src/monitor.js";
53
+ import { createDebugLog } from "./src/debug.js";
54
+ import { createProgressTracker, registerProgressReminders, ANTI_POISONING_SUFFIX } from "./src/reminders.js";
55
+ import { asTaskList, type KanboardTask } from "./src/shapes.js";
39
56
  import {
40
57
  ACTION_OPEN,
41
58
  ACTION_STOP_DAEMON,
@@ -52,8 +69,12 @@ export const SKILL_REVEAL_EVENT = "unipi:skills:reveal";
52
69
  export const KANBOARD_SKILL = "kanboard";
53
70
 
54
71
  export default function (pi: ExtensionAPI) {
55
- // One session id shared by the runner and the agent's bash calls.
72
+ // One session id shared by the agent's bash calls (refined at session_start
73
+ // from the pi session id; children keep the value they inherited).
56
74
  process.env.UNIPI_KANBOARD_SESSION ??= `pi-${process.pid}`;
75
+ // `start` claims belong to this pi process: the stale-claim reaper releases
76
+ // them to Todo when it dies (the agent's bash inherits the env).
77
+ process.env.UNIPI_KANBOARD_PID ??= String(process.pid);
57
78
  // Limits travel through the environment; refresh on load and before every
58
79
  // tool_call (see the guard registration in commands.ts).
59
80
  applyLimitEnv(readKanboardSettings());
@@ -62,14 +83,11 @@ export default function (pi: ExtensionAPI) {
62
83
 
63
84
  let cli: KanboardCli | null = null;
64
85
  let unavailable: string | null = null;
65
- let runner: Runner | null = null;
66
- const guard = createWriteGuard(
67
- () => {
68
- const status = runner?.status();
69
- return status?.phase === "running" ? status.taskId : null;
70
- },
71
- () => readKanboardSettings().turnAddLimit,
72
- );
86
+ const guard = createWriteGuard({
87
+ addLimit: () => readKanboardSettings().turnAddLimit,
88
+ doTasks: () => readKanboardSettings().doTasks,
89
+ doWrites: () => readKanboardSettings().doWrites,
90
+ });
73
91
  const sessionId = (): string => process.env.UNIPI_KANBOARD_SESSION ?? `pi-${process.pid}`;
74
92
 
75
93
  const projectSlug = (): string => {
@@ -83,8 +101,87 @@ export default function (pi: ExtensionAPI) {
83
101
  }
84
102
  };
85
103
 
86
- // Live getters: the command is registered before the binary is resolved, so
87
- // the deps object must read the current state at call time.
104
+ // ── board reads (lead monitor/evidence/holder/notice) ────────────────
105
+ const listTasks = async (args: string[] = []): Promise<KanboardTask[]> => {
106
+ const client = cli;
107
+ const slug = projectSlug();
108
+ if (!client || !slug) return [];
109
+ const payload = await client.run<unknown>(["list", ...args, "--json"], {
110
+ extraEnv: { UNIPI_KANBOARD_PROJECT: slug, UNIPI_KANBOARD_SESSION: sessionId() },
111
+ });
112
+ return asTaskList(payload).tasks;
113
+ };
114
+ const ownClaims = async (): Promise<KanboardTask[]> => {
115
+ try {
116
+ const session = sessionId();
117
+ return (await listTasks()).filter((task) => {
118
+ const run = task.run as { session?: string } | null | undefined;
119
+ return task.status === "in_progress" && run?.session === session;
120
+ });
121
+ } catch {
122
+ return [];
123
+ }
124
+ };
125
+
126
+ // ── monitor: the arbiter's kanboard nudge provider (lead only) ───────
127
+ // User-only notices queue here and flush at agent_settled (post boundary).
128
+ const pendingNotices = new NoticeBuffer();
129
+ const monitor = createKanboardMonitor({
130
+ list: () => listTasks(),
131
+ listReady: () => listTasks(["--ready"]),
132
+ session: sessionId,
133
+ ownerStatus: () => getSharedOwnerStatus(),
134
+ now: () => Date.now(),
135
+ // User-only: only QUEUE here — a sendMessage custom message would be
136
+ // converted to a user-role LLM message (never what a notice wants).
137
+ // kanboard's agent_settled handler drains the buffer (appendEntry + toast).
138
+ notify: (text, level) => {
139
+ pendingNotices.queue(text, level);
140
+ },
141
+ // The monitor turned autowork off itself (done / stalled): the guard's
142
+ // budget and the footer's `▣ autowork` flag must follow.
143
+ onAutoworkOff: () => {
144
+ guard.setAutowork(false);
145
+ void refreshHolder();
146
+ },
147
+ cliPrefix: () => {
148
+ const slug = projectSlug();
149
+ return cli && slug ? `${cli.binary.path} --actor agent --project ${slug}` : null;
150
+ },
151
+ debug,
152
+ });
153
+
154
+ const refreshHolder = async (): Promise<void> => {
155
+ try {
156
+ setSharedKanboardStatus({
157
+ claims: (await ownClaims()).map((task) => task.id),
158
+ autowork: guard.remaining().autowork,
159
+ });
160
+ } catch {
161
+ // The footer simply shows nothing until the next refresh.
162
+ }
163
+ };
164
+
165
+ if (!isChildProcess()) {
166
+ try {
167
+ registerNudgeProvider("kanboard", 50, (info) => monitor.propose(info));
168
+ } catch {
169
+ // Registration must never block module load.
170
+ }
171
+ try {
172
+ registerEvidenceContributor("kanboard", async () => ({
173
+ blocking: (await ownClaims()).map(
174
+ (task) => `${task.id} is still In Progress (claimed by this session) — finish it or move it to blocked`,
175
+ ),
176
+ notes: [],
177
+ }));
178
+ } catch {
179
+ // Registration must never block module load.
180
+ }
181
+ registerBadgeRenderer(pi);
182
+ }
183
+
184
+ // ── command plumbing ─────────────────────────────────────────────────
88
185
  const buildDeps = (): CommandDeps => ({
89
186
  get cli() {
90
187
  return cli;
@@ -94,13 +191,16 @@ export default function (pi: ExtensionAPI) {
94
191
  },
95
192
  settings: () => readKanboardSettings(process.cwd()),
96
193
  revealSkill,
97
- work: (ctx) => runner?.work(ctx) ?? Promise.resolve(),
98
- stop: (ctx) => runner?.stop(ctx),
99
- drainQueue: (ctx) => runner?.drain(ctx) ?? Promise.resolve(),
100
- status: () => runner?.status() ?? { taskId: null, mode: null, phase: "idle" },
194
+ setAutowork: (on) => {
195
+ guard.setAutowork(on);
196
+ monitor.setAutowork(on);
197
+ if (on) monitor.arm("autowork");
198
+ void refreshHolder();
199
+ },
101
200
  guard,
102
201
  session: sessionId,
103
202
  debug,
203
+ progress: (data) => appendProgress(pi, data),
104
204
  }) as CommandDeps;
105
205
 
106
206
  const revealSkill = (ctx: ExtensionContext | { cwd?: string }): void => {
@@ -119,22 +219,33 @@ export default function (pi: ExtensionAPI) {
119
219
  cli = opened;
120
220
  unavailable = null;
121
221
  debug(`binary: ${opened.binary.path} (${opened.binary.source})`);
122
- if (!runner) {
123
- runner = createRunner({
124
- pi,
125
- cli,
126
- project: projectSlug,
127
- cwd: ctx.cwd,
128
- settings: () => readKanboardSettings(ctx.cwd),
129
- debug,
130
- });
131
- registerPlanEventListener(pi, runner);
132
- }
133
222
  return true;
134
223
  };
135
224
 
225
+ registerProgressRenderer(pi);
136
226
  registerKanboardCommands(pi, buildDeps());
137
227
 
228
+ // ── API for other extensions (input-shortcuts K chord) ──────────────
229
+ // Add the editor text to this project's Backlog as a body-only task.
230
+ (globalThis as { __unipi_kanboard_api?: unknown }).__unipi_kanboard_api = {
231
+ captureToBacklog: (opts: { cwd: string; text: string }) => captureToBacklog(buildDeps(), opts),
232
+ };
233
+
234
+ // R1 progress reminders for hand-worked tasks (silent in child sessions).
235
+ registerProgressReminders(
236
+ pi,
237
+ createProgressTracker({
238
+ enabled: () => readKanboardSettings().reminders,
239
+ session: sessionId,
240
+ list: () => listTasks(),
241
+ cliPrefix: () => {
242
+ const slug = projectSlug();
243
+ return cli && slug ? `${cli.binary.path} --actor agent --project ${slug}` : null;
244
+ },
245
+ debug,
246
+ }),
247
+ );
248
+
138
249
  registerCommandRunner(ACTION_OPEN, async (ctx) => {
139
250
  const context = ctx as ExtensionContext | undefined;
140
251
  if (!context?.ui) return;
@@ -157,10 +268,78 @@ export default function (pi: ExtensionAPI) {
157
268
  await runRotateTokenAction(buildDeps(), context);
158
269
  });
159
270
 
271
+ // ── run hooks: monitor, badges, holder (lead only) ───────────────────
272
+ pi.on("before_agent_start", async (event) => {
273
+ try {
274
+ await monitor.onUserPrompt(String((event as { prompt?: unknown }).prompt ?? ""));
275
+ } catch {
276
+ // Prompt handling must never abort a turn.
277
+ }
278
+ return undefined;
279
+ });
280
+ pi.on("agent_start", () => {
281
+ try {
282
+ monitor.onAgentStart();
283
+ } catch {
284
+ // Accounting must never abort a turn.
285
+ }
286
+ });
287
+ pi.on("agent_end", async (event) => {
288
+ try {
289
+ guard.onAgentEnd();
290
+ monitor.onAgentEnd((event as { messages?: unknown[] }).messages);
291
+ } catch {
292
+ // Monitoring must never abort a turn.
293
+ }
294
+ });
295
+ // Post-boundary: entries append fine here (they are dropped inside the
296
+ // settle path), and the toast gives the notice a life outside the transcript.
297
+ pi.on("agent_settled", async (_event, ctx) => {
298
+ try {
299
+ const ui = ctx as unknown as { hasUI?: boolean; ui?: { notify?: (t: string, l?: string) => void } } | undefined;
300
+ flushNotices(
301
+ pi,
302
+ pendingNotices,
303
+ {
304
+ hasUI: ui?.hasUI,
305
+ notify: (text, level) => ui?.ui?.notify?.(text, level ?? "info"),
306
+ },
307
+ debug,
308
+ );
309
+ void refreshHolder();
310
+ } catch {
311
+ // The footer simply shows nothing until the next refresh.
312
+ }
313
+ });
314
+ pi.on("tool_result", async (event) => {
315
+ const toolEvent = event as { toolName?: string; input?: Record<string, unknown>; isError?: boolean };
316
+ try {
317
+ if (isChildProcess()) return undefined;
318
+ if (toolEvent.toolName !== "bash" && toolEvent.toolName !== "powershell") return undefined;
319
+ maybeBadgeToolResult(pi, String(toolEvent.toolName), toolEvent.input, toolEvent.isError === true);
320
+ if (toolEvent.isError) return undefined;
321
+ const invocations = kanboardInvocations(String(toolEvent.input?.command ?? ""));
322
+ if (invocations.some((inv) => inv.sub === "start" || inv.sub === "finish" || inv.sub === "move")) {
323
+ if (invocations.some((inv) => inv.sub === "start")) monitor.arm("start");
324
+ void refreshHolder();
325
+ }
326
+ } catch {
327
+ // Badges and holder refreshes must never abort a turn.
328
+ }
329
+ return undefined;
330
+ });
331
+
332
+ // ── session lifecycle ────────────────────────────────────────────────
160
333
  pi.on("session_start", async (_event, ctx) => {
161
334
  // Kanboard's own ambient children (summaries, --list-models) get this env:
162
335
  // they must not re-sync the runtime or spawn a daemon.
163
336
  if (process.env.UNIPI_KANBOARD_CHILD) return;
337
+ // Children keep the session id they inherited from the lead.
338
+ if (!isChildProcess()) {
339
+ // Step 0: reason is "startup" even for -c/-r — never branch on it.
340
+ process.env.UNIPI_KANBOARD_SESSION = `pi-${ctx.sessionManager.getSessionId()}`;
341
+ process.env.UNIPI_KANBOARD_PID = String(process.pid);
342
+ }
164
343
  initUnipiDirs();
165
344
  if (attach(ctx as unknown as ExtensionContext)) {
166
345
  const deps = buildDeps();
@@ -177,6 +356,50 @@ export default function (pi: ExtensionAPI) {
177
356
  debug(`unavailable: ${unavailable}`);
178
357
  return;
179
358
  }
359
+ // Reap claims whose pid died with the process (the runner used to do
360
+ // this): released tasks get the "session lost: <session>" activity the
361
+ // resume notice below keys on. The reaper acts as the system actor.
362
+ if (!isChildProcess()) {
363
+ try {
364
+ const reaped = await cli!.run<unknown>(["reap", "--json"], {
365
+ extraEnv: { UNIPI_KANBOARD_PROJECT: projectSlug(), UNIPI_KANBOARD_SESSION: sessionId() },
366
+ });
367
+ debug(`reap: ${JSON.stringify(reaped)}`);
368
+ } catch (error) {
369
+ debug(`reap failed: ${error instanceof Error ? error.message : String(error)}`);
370
+ }
371
+ }
372
+ void refreshHolder();
373
+
374
+ // Resume notice: claims the reaper released when a previous run of THIS
375
+ // session died ("session lost: <session> …"), or that a shutdown released
376
+ // ("released: … session ended mid-task (<session>)"). Once per start.
377
+ // Activity entries are ordered oldest-first — the LAST one must be the
378
+ // release (a task that moved on afterwards is not news).
379
+ if (!isChildProcess()) {
380
+ try {
381
+ const session = sessionId();
382
+ const stale = (await listTasks()).filter((task) => {
383
+ if (task.status !== "todo") return false;
384
+ const last = task.activity?.at(-1);
385
+ if (!last) return false;
386
+ return (
387
+ last.text.startsWith(`session lost: ${session}`) ||
388
+ last.text.includes(`released: session ended mid-task (${session})`)
389
+ );
390
+ });
391
+ if (stale.length > 0) {
392
+ const ids = stale.map((task) => task.id).join(", ");
393
+ (ctx as unknown as { ui?: { notify?: (t: string, l?: string) => void } }).ui?.notify?.(
394
+ `kanboard: ${ids} was released when the last run ended — ask me to re-start it`,
395
+ "info",
396
+ );
397
+ }
398
+ } catch (error) {
399
+ debug(`resume notice failed: ${error instanceof Error ? error.message : String(error)}`);
400
+ }
401
+ }
402
+
180
403
  const client = cli!;
181
404
  const settings = readKanboardSettings(ctx.cwd);
182
405
  if (settings.archiveAfterDays > 0 || settings.retentionDays > 0) {
@@ -192,26 +415,41 @@ export default function (pi: ExtensionAPI) {
192
415
  .then((payload) => debug(`archive-sweep: ${JSON.stringify(payload)}`))
193
416
  .catch((error) => debug(`archive-sweep failed: ${error instanceof Error ? error.message : String(error)}`));
194
417
  }
195
- await runner?.onSessionStart(ctx as unknown as ExtensionContext);
196
- });
197
-
198
- let drainPending = false;
199
- pi.on("agent_end", async (event, ctx) => {
200
- runner?.onAgentEnd(event as { messages?: unknown[] }, ctx as unknown as ExtensionContext);
201
- // A -do window closes on the first real agent_end (the 150ms echo guard
202
- // inside onAgentEnd skips the previous turn's late end). The drain itself
203
- // runs at agent_settled: sending a task prompt while the turn is still
204
- // finalizing would queue it as a follow-up that never gets delivered.
205
- if (guard.onAgentEnd()) drainPending = true;
206
- });
207
-
208
- pi.on("agent_settled", async (_event, ctx) => {
209
- if (!drainPending) return;
210
- drainPending = false;
211
- await drainQueueAfterDo(buildDeps(), ctx as unknown as ExtensionContext);
212
418
  });
213
419
 
214
420
  pi.on("session_shutdown", async (_event, ctx) => {
215
- await runner?.onSessionShutdown(ctx as unknown as ExtensionContext);
421
+ // Release this session's open claims so the board shows the truth. The
422
+ // in_progress → todo transition allows the system actor only (the agent
423
+ // cannot release), and release requires a comment — the next run's resume
424
+ // notice keys on it. Best effort: a dead pid is reaped with "session
425
+ // lost" anyway.
426
+ // Children (subagents, fusion sidekicks, kanboard's own helpers) inherit
427
+ // the lead's session id: their shutdown must never release the lead's
428
+ // claims (a finished subagent used to bounce the lead's task to Todo).
429
+ if (isChildProcess() || process.env.UNIPI_KANBOARD_CHILD) return;
430
+ try {
431
+ const session = sessionId();
432
+ const claims = await ownClaims();
433
+ const client = cli;
434
+ const slug = projectSlug();
435
+ if (!client || !slug || claims.length === 0) return;
436
+ for (const task of claims) {
437
+ await client
438
+ .run([
439
+ "--actor", "system",
440
+ "--project", slug,
441
+ "release", task.id, "--to", "todo",
442
+ "--comment", `released: session ended mid-task (${session})`,
443
+ ], {
444
+ extraEnv: { UNIPI_KANBOARD_PROJECT: slug, UNIPI_KANBOARD_SESSION: session },
445
+ })
446
+ .then(() => debug(`released ${task.id} at shutdown`))
447
+ .catch((error) => debug(`shutdown release ${task.id} failed: ${error instanceof Error ? error.message : String(error)}`));
448
+ }
449
+ setSharedKanboardStatus({ claims: [], autowork: guard.remaining().autowork });
450
+ } catch {
451
+ // Shutdown must never hang the session teardown.
452
+ }
453
+ void ctx;
216
454
  });
217
455
  }
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@pi-unipi/kanboard",
3
- "version": "3.0.0-alpha.2",
3
+ "version": "3.0.0-alpha.21",
4
4
  "description": "Kanboard v3 — deferred-work board: CLI/daemon bridge, task runner and skill",
5
5
  "type": "module",
6
6
  "main": "index.ts",
7
7
  "license": "MIT",
8
8
  "author": "Neuron Mr White",
9
9
  "scripts": {
10
- "test": "npx tsx --test tests/**/*.test.ts"
10
+ "test": "UNIPI_FUSION_CHILD= UNIPI_SUBAGENT_CHILD= UNIPI_KANBOARD_CHILD= npx tsx --test tests/*.test.ts tests/*/*.test.ts"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "dependencies": {
34
- "@pi-unipi/core": "3.0.0-alpha.2"
34
+ "@pi-unipi/core": "3.0.0-alpha.21"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@earendil-works/pi-coding-agent": "^0.87.1",
@@ -48,10 +48,10 @@
48
48
  "themes": []
49
49
  },
50
50
  "optionalDependencies": {
51
- "@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.2",
52
- "@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.2",
53
- "@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.2",
54
- "@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.2",
55
- "@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.2"
51
+ "@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.21",
52
+ "@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.21",
53
+ "@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.21",
54
+ "@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.21",
55
+ "@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.21"
56
56
  }
57
57
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: kanboard
3
- description: "Kanboard — the project's deferred-work board. Use when the user asks to note a task for later, to see what is on the board, or while working a board task: read it with `unipi-kanboard show`, add notes, block with a question, or file follow-up work."
3
+ description: "Kanboard — the project's deferred-work board. Use when the user asks to note a task for later, to see what is on the board, or to work board tasks (e.g. do UNI-5): `start` a task before working on it and `finish` it with a summary when done; while working a board task: read it with `unipi-kanboard show`, add notes, block with a question, or file follow-up work."
4
4
  ---
5
5
 
6
6
  # Kanboard
@@ -16,27 +16,35 @@ Always pass the actor and the project, and call it by absolute path (it may not
16
16
  be on `PATH`):
17
17
 
18
18
  ```sh
19
- <binary> --actor agent --project <slug> list [--ready] [--json]
19
+ <binary> --actor agent --project <slug> list [--ready] [--all] [--json] # bare list = todo/in_progress/blocked/in_review/done only; --all adds backlog/cancelled/archived
20
20
  <binary> --actor agent --project <slug> show <ID>
21
- <binary> --actor agent --project <slug> next # what claim-next would pick + why
21
+ <binary> --actor agent --project <slug> next # what would be picked next + why (read-only)
22
22
  <binary> --actor agent --project <slug> chain <ID> # upstream deps + downstream dependents
23
23
  <binary> --actor agent --project <slug> search "<text>" [--all] # id/title/body, archived excluded unless --all
24
24
  <binary> --actor agent --project <slug> add "<title>" [--status todo] [--after <ID>] [--body-file <f>] [--attach <file>]…
25
- <binary> --actor agent --project <slug> note <ID> "<text>"
25
+ <binary> --actor agent --project <slug> note <ID> "<text>" [--attach <file>]…
26
26
  <binary> --actor agent --project <slug> attach <ID> <file> --note "<what it shows>"
27
27
  <binary> --actor agent --project <slug> attachments <ID>
28
28
  <binary> --actor agent --project <slug> edit <ID> --title|--body|--labels … # only tasks you created, while in backlog/todo
29
- <binary> --actor agent --project <slug> move <ID> blocked --comment "<what you need>"
29
+ <binary> --actor agent --project <slug> start <ID> # todo → in progress, claimed for your session (costs a -do slot)
30
+ <binary> --actor agent --project <slug> finish <ID> --comment "<summary>" [--attach <file>]… # in progress → in review, only a task you started (free)
31
+ <binary> --actor agent --project <slug> move <ID> blocked --comment "<what you need>" [--attach <file>]…
30
32
  <binary> --actor agent --project <slug> link <ID> --after <DEP>
31
33
  <binary> --actor agent --project <slug> unlink <ID> --after <DEP>
32
34
  <binary> --actor agent --project <slug> order <ID> --top|--bottom|--before <ID>
33
- <binary> --actor agent --project <slug> queue <ID>… | queue --list # your session's work queue (limit: setting queueMax, default 10)
34
- <binary> --actor agent --project <slug> unqueue [<ID>…] # no ids clears it
35
35
  ```
36
36
 
37
+ There is **no queue and no runner** — the session works tasks itself
38
+ (`/unipi:kanboard-autowork` just keeps offering the next ready task).
39
+ `queue`, `unqueue`, `claim-next`, `set-run` and `edit --strategy/--plan` are
40
+ removed and refused.
41
+
37
42
  `--json` gives machine-readable output for every subcommand (task objects carry
38
43
  `ready`, `waitingFor`, `depsStatus` and `staleness`).
39
44
 
45
+ `list`/`search` show a one-line body excerpt; read a task's full description with
46
+ `show <ID>` before editing or starting it.
47
+
40
48
  `settings show` reads the pi runtime and effective limits; `settings set`
41
49
  and `rotate-token` are user-only — the agent is refused.
42
50
 
@@ -45,10 +53,11 @@ and `rotate-token` are user-only — the agent is refused.
45
53
  | Move | Who |
46
54
  |---|---|
47
55
  | backlog ↔ todo | user, agent |
48
- | todo → in progress | **the runner only** (`claim-next`) |
56
+ | todo → in progress | the agent with `start <ID>` (claims it for its session; costs a `-do` slot) |
49
57
  | edit a task | agent — only tasks it created, and only in backlog/todo |
50
- | in progress → in review | **the runner only** (when your turn ends) |
58
+ | in progress → in review | the agent with `finish <ID> --comment` — only a task its own session `start`ed |
51
59
  | in progress → blocked | agent, system — **comment required** (what you need) |
60
+ | in progress → todo | user or system `release` — comment required (the session died or gave the task up) |
52
61
  | blocked → todo | user only — comment required (the answer) |
53
62
  | in review → done | user only |
54
63
  | in review → todo/backlog | user only — comment required (rework note) |
@@ -65,26 +74,45 @@ lists them — read the files there directly if you need one.
65
74
 
66
75
  1. **Never pass `--actor user`.** That is an honour system: pretending to be the
67
76
  user to cancel a task or mark it done breaks the board's whole contract.
68
- 2. **Never move a task to `in_review` or `done`.** The runner writes those when
69
- your turn ends; claiming them yourself loses the summary and the review step.
77
+ 2. **Work the tasks yourself, in this session** (the user says "do UNI-5"):
78
+ **`start` a task before working on it, `finish` it with a summary when done**
79
+ — `start <ID>` before your first edit, `finish <ID> --comment "<what you
80
+ did>"` before your turn ends (or `move <ID> blocked --comment "<what you
81
+ need>"` if you cannot). `finish` and own-claim `blocked`/`note` are always
82
+ free; **`start` costs one of your `-do` task slots** — count the tasks a
83
+ request needs BEFORE starting anything, and if that is more than your
84
+ remaining slots, start none of them: say what you can do now and ask whether
85
+ to raise `kanboard.doTasks` or work in batches. In Review means "the agent
86
+ did the work, a human reviews" — never leave a task you started In Progress
87
+ (the board monitor will nudge you back to it). **Never move a task to
88
+ `done`.**
70
89
  3. **Never cancel.** If a task should be dropped, block it with
71
90
  `move <ID> blocked --comment "suggest cancel: <why>"` and let the user decide.
72
- 4. **To ask the user something, block the task and stop**: `move <ID> blocked
73
- --comment "<exactly what you need>"`. The answer arrives as a comment the next
74
- time the task is claimed.
91
+ 4. **Follow the blocking rule in your task prompt**: by default work
92
+ autonomously and record assumptions with `note <ID> "assumed: <what/why>"`;
93
+ block (with a comment saying exactly what you need) only when you truly
94
+ cannot continue — `move <ID> blocked --comment "<what you need>"`.
75
95
  5. **Work only on the task you were given.** Follow-up work goes to the board as
76
96
  a new task in Backlog (`add "<title>"`), optionally `link <new> --after <ID>`.
77
- A session holds one claim at a time, and at most `maxSessions` (default 2)
78
- sessions may run tasks in a project — if the board refuses a claim, that is
79
- why. You may
97
+ At most `maxSessions` (default 2) sessions may hold tasks in a project at
98
+ once — if the board refuses a `start`, that is why. You may
80
99
  block only the task your own session is running (`move <ID> blocked` checks
81
100
  `--session`/`UNIPI_KANBOARD_SESSION` against the claim).
82
- 6. **To have tasks worked during a `/unipi:kanboard-do` turn, queue them** with
83
- `queue <IDs>` (Todo tasks, up to the queue limit — setting `queueMax`, default 10) — the runner starts them one by one
84
- after the turn ends. Never claim or start them yourself.
101
+ 6. **Sidekicks and subagents can read the board but never write it** — every
102
+ write is refused with "board writes are the lead's job". Brief them with the
103
+ task, then update the board yourself from their reports. (The lead session
104
+ works tasks itself; `/unipi:kanboard-autowork` just keeps offering the next
105
+ ready task in the same session — there is no separate worker.)
85
106
  7. Use `note <ID> "<text>"` for progress worth remembering (decisions, what you
86
107
  verified, what you left undone) — it is the activity log the next reader sees.
87
- 8. Dependencies form a DAG: a task is ready only when every dep reached the chain
108
+ 8. **Write the `finish` / `blocked` comment as the report the user reads.** It
109
+ is shown as the task's status banner and opens in a reader, rendered as
110
+ markdown. Lead with one plain sentence (what you did, or what stops you),
111
+ then short paragraphs or `-` bullets separated by blank lines; put questions
112
+ for the user as a numbered list under `**Need from you:**`. Name files and
113
+ commands in backticks. Do not repeat a note you already wrote — the report
114
+ replaces it. Attach evidence with `--attach <file>`.
115
+ 9. Dependencies form a DAG: a task is ready only when every dep reached the chain
88
116
  gate (`in_review` by default, `done` when configured). Cancelled deps block
89
117
  forever, so unlink or re-plan instead of waiting. `chain <ID>` shows the
90
118
  whole line, `next` shows what would be picked and why others wait.
@@ -92,15 +120,21 @@ lists them — read the files there directly if you need one.
92
120
  ## Terminal-only execution
93
121
 
94
122
  The web UI can create, edit, reorder, link and move tasks, but it **never runs a
95
- task** — there is no run button. Work starts only from a terminal with
96
- `/unipi:kanboard-autowork start` (or the queue after a `/unipi:kanboard-do`). (The Done column's "Summarize & archive" does call the
97
- agent command set in the board's Settings, but only to write a summary.)
123
+ task** — there is no run button. Work starts only from a terminal: the session
124
+ itself, driven by `/unipi:kanboard-do` (a task-slot + write budget for one
125
+ request) or `/unipi:kanboard-autowork` (the monitor keeps offering the next
126
+ ready task in this session — no separate worker exists). (The Done column's
127
+ "Summarize & archive" does call the agent command set in the board's Settings,
128
+ but only to write a summary.)
98
129
 
99
130
  ## Attachments
100
131
 
101
132
  Users attach screenshots, logs and documents in the board UI; they appear in the
102
133
  text as markdown with `att:<ID>/<name>` references, and `show <ID> --json` lists
103
134
  them under `attachments` with an absolute `path` — read the file from there
104
- (use your image-reading tool for images). To hand back evidence, `attach` a file:
105
- it is stored beside the board and the comment embeds it, so the user sees the
106
- image or file inline.
135
+ (use your image-reading tool for images). To hand back evidence (a screenshot,
136
+ a log, a report), pass `--attach <file>` (repeatable) to `finish`, `move … blocked`
137
+ or `note`, or use `attach <ID> <file> --note "…"`: the file is stored beside the
138
+ board and the comment embeds it, so the user sees the image or file inline. A
139
+ file's path written in the comment is replaced by the embed; otherwise the
140
+ embed is appended. Attaching to a task you started is free.