@pi-unipi/unipi 2.20.5 → 3.0.0-alpha.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 (266) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +21 -19
  3. package/docs/prefix-cache-architecture.md +0 -1
  4. package/package.json +32 -35
  5. package/packages/ask-user/README.md +1 -1
  6. package/packages/ask-user/config.ts +29 -53
  7. package/packages/ask-user/index.ts +2 -4
  8. package/packages/ask-user/package.json +5 -5
  9. package/packages/ask-user/skills/ask-user/SKILL.md +1 -1
  10. package/packages/autocomplete/README.md +2 -2
  11. package/packages/autocomplete/package.json +4 -4
  12. package/packages/autocomplete/src/constants.ts +37 -164
  13. package/packages/autocomplete/src/provider.ts +9 -8
  14. package/packages/autocomplete/src/settings.ts +33 -56
  15. package/packages/autocomplete/src/sorting.ts +2 -2
  16. package/packages/background-tasks/README.md +2 -2
  17. package/packages/background-tasks/package.json +6 -6
  18. package/packages/background-tasks/src/config.ts +69 -22
  19. package/packages/background-tasks/src/index.ts +0 -25
  20. package/packages/background-tasks/src/tools.ts +0 -9
  21. package/packages/background-tasks/src/types.ts +6 -12
  22. package/packages/btw/package.json +6 -6
  23. package/packages/compactor/README.md +4 -4
  24. package/packages/compactor/package.json +7 -7
  25. package/packages/compactor/skills/compactor/SKILL.md +1 -1
  26. package/packages/compactor/skills/compactor-doctor/SKILL.md +1 -1
  27. package/packages/compactor/src/commands/index.ts +12 -43
  28. package/packages/compactor/src/config/manager.ts +80 -17
  29. package/packages/core/command-runner.ts +44 -0
  30. package/packages/core/constants.ts +4 -82
  31. package/packages/core/events.ts +13 -1
  32. package/packages/core/index.ts +19 -1
  33. package/packages/core/long-horizon-status.ts +33 -0
  34. package/packages/core/package.json +8 -5
  35. package/packages/core/plan-permission-status.ts +34 -0
  36. package/packages/core/src/jev/client.ts +143 -0
  37. package/packages/core/src/jev/settings.ts +23 -0
  38. package/packages/core/src/package-colors.ts +57 -0
  39. package/packages/core/src/settings/catalog.ts +89 -0
  40. package/packages/core/src/settings/engine.ts +153 -0
  41. package/packages/core/src/settings/hub.ts +1086 -0
  42. package/packages/core/src/settings/migrations.ts +324 -0
  43. package/packages/core/src/settings/paths.ts +44 -0
  44. package/packages/core/src/settings/schema.ts +266 -0
  45. package/packages/core/src/tui/hub-kit.ts +284 -0
  46. package/packages/core/src/workspace/identity.ts +171 -0
  47. package/packages/core/src/workspace/paths.ts +160 -0
  48. package/packages/core/src/workspace/state-migration.ts +150 -0
  49. package/packages/core/tui-overlay.ts +44 -10
  50. package/packages/core/utils.ts +61 -30
  51. package/packages/footer/README.md +2 -2
  52. package/packages/footer/package.json +6 -6
  53. package/packages/footer/src/commands.ts +3 -47
  54. package/packages/footer/src/config.ts +89 -18
  55. package/packages/footer/src/events.ts +44 -0
  56. package/packages/footer/src/glance-editor.ts +68 -5
  57. package/packages/footer/src/index.ts +25 -3
  58. package/packages/footer/src/presets.ts +6 -6
  59. package/packages/footer/src/segments/core.ts +2 -0
  60. package/packages/footer/src/segments/long-horizon.ts +47 -0
  61. package/packages/fusion/README.md +1 -1
  62. package/packages/fusion/package.json +6 -6
  63. package/packages/fusion/src/index.ts +15 -18
  64. package/packages/fusion/src/picker.ts +19 -5
  65. package/packages/fusion/src/preset-editor.ts +2 -2
  66. package/packages/fusion/src/preset.ts +37 -0
  67. package/packages/image/README.md +3 -3
  68. package/packages/image/package.json +5 -5
  69. package/packages/image/skills/image/SKILL.md +2 -2
  70. package/packages/image/src/generate.ts +1 -1
  71. package/packages/image/src/index.ts +2 -6
  72. package/packages/image/src/models.ts +3 -3
  73. package/packages/image/src/openai-images-api.ts +1 -1
  74. package/packages/image/src/settings.ts +31 -7
  75. package/packages/image/src/tools.ts +2 -2
  76. package/packages/info-screen/README.md +1 -1
  77. package/packages/info-screen/config.ts +69 -19
  78. package/packages/info-screen/index.ts +1 -32
  79. package/packages/info-screen/package.json +5 -6
  80. package/packages/input-shortcuts/README.md +2 -2
  81. package/packages/input-shortcuts/package.json +5 -5
  82. package/packages/input-shortcuts/src/index.ts +4 -30
  83. package/packages/input-shortcuts/src/settings.ts +168 -0
  84. package/packages/kanboard/README.md +184 -66
  85. package/packages/kanboard/index.ts +206 -63
  86. package/packages/kanboard/package.json +18 -23
  87. package/packages/kanboard/skills/kanboard/SKILL.md +106 -0
  88. package/packages/kanboard/src/bin.ts +210 -0
  89. package/packages/kanboard/src/commands.ts +1371 -0
  90. package/packages/kanboard/src/guard.ts +143 -0
  91. package/packages/kanboard/src/runner.ts +817 -0
  92. package/packages/kanboard/src/settings.ts +158 -0
  93. package/packages/kanboard/src/shapes.ts +220 -0
  94. package/packages/long-horizon/README.md +16 -0
  95. package/packages/long-horizon/index.ts +233 -0
  96. package/packages/long-horizon/package.json +55 -0
  97. package/packages/long-horizon/src/commands.ts +225 -0
  98. package/packages/long-horizon/src/engine/continuation.ts +240 -0
  99. package/packages/long-horizon/src/engine/goal-state.ts +491 -0
  100. package/packages/long-horizon/src/engine/ralph.ts +362 -0
  101. package/packages/long-horizon/src/engine/runaway.ts +219 -0
  102. package/packages/long-horizon/src/engine/verifier.ts +206 -0
  103. package/packages/long-horizon/src/gate.ts +261 -0
  104. package/packages/long-horizon/src/judge/omniroute-key.ts +56 -0
  105. package/packages/long-horizon/src/judge/resolve.ts +124 -0
  106. package/packages/long-horizon/src/judge/typesafe.ts +262 -0
  107. package/packages/long-horizon/src/modes.ts +97 -0
  108. package/packages/long-horizon/src/owner.ts +255 -0
  109. package/packages/long-horizon/src/prompts/goal.ts +113 -0
  110. package/packages/long-horizon/src/runtime.ts +254 -0
  111. package/packages/long-horizon/src/settings.ts +227 -0
  112. package/packages/long-horizon/src/tools/goal.ts +287 -0
  113. package/packages/long-horizon/src/tools/graph.ts +356 -0
  114. package/packages/long-horizon/src/tools/ralph.ts +93 -0
  115. package/packages/long-horizon/src/tools/swarm.ts +212 -0
  116. package/packages/long-horizon/src/tools/todo.ts +154 -0
  117. package/packages/mcp/README.md +5 -6
  118. package/packages/mcp/package.json +5 -5
  119. package/packages/mcp/skills/mcp/SKILL.md +4 -4
  120. package/packages/mcp/src/bridge/translator.ts +1 -1
  121. package/packages/mcp/src/index.ts +108 -92
  122. package/packages/mcp/src/tui/add-overlay.ts +10 -3
  123. package/packages/mcp/src/tui/settings-overlay.ts +145 -146
  124. package/packages/memory/commands.ts +22 -26
  125. package/packages/memory/embedding.ts +34 -24
  126. package/packages/memory/index.ts +0 -1
  127. package/packages/memory/package.json +4 -4
  128. package/packages/memory/settings.ts +172 -15
  129. package/packages/memory/skills/memory/SKILL.md +2 -2
  130. package/packages/notify/README.md +5 -10
  131. package/packages/notify/commands.ts +89 -253
  132. package/packages/notify/index.ts +1 -1
  133. package/packages/notify/ntfy-config.ts +18 -6
  134. package/packages/notify/package.json +5 -5
  135. package/packages/notify/settings.ts +137 -12
  136. package/packages/notify/skills/configure-notify/SKILL.md +16 -16
  137. package/packages/notify/tui/gotify-setup.ts +8 -8
  138. package/packages/notify/tui/ntfy-setup.ts +10 -10
  139. package/packages/notify/tui/telegram-setup.ts +6 -6
  140. package/packages/skill-registry/README.md +25 -0
  141. package/packages/skill-registry/package.json +34 -0
  142. package/packages/{workflow → skill-registry}/skills/auto/SKILL.md +12 -12
  143. package/packages/{workflow → skill-registry}/skills/brainstorm/SKILL.md +11 -9
  144. package/packages/{workflow → skill-registry}/skills/chore-create/SKILL.md +15 -13
  145. package/packages/{workflow → skill-registry}/skills/chore-execute/SKILL.md +11 -9
  146. package/packages/{workflow → skill-registry}/skills/consolidate/SKILL.md +2 -2
  147. package/packages/{workflow → skill-registry}/skills/consultant/SKILL.md +2 -2
  148. package/packages/{workflow → skill-registry}/skills/debug/SKILL.md +18 -16
  149. package/packages/{workflow → skill-registry}/skills/document/SKILL.md +6 -6
  150. package/packages/{workflow → skill-registry}/skills/fix/SKILL.md +16 -14
  151. package/packages/{workflow → skill-registry}/skills/gather-context/SKILL.md +4 -4
  152. package/packages/{workflow → skill-registry}/skills/plan/SKILL.md +21 -18
  153. package/packages/{workflow → skill-registry}/skills/quick-fix/SKILL.md +10 -8
  154. package/packages/{workflow → skill-registry}/skills/quick-work/SKILL.md +5 -5
  155. package/packages/{workflow → skill-registry}/skills/research/SKILL.md +8 -8
  156. package/packages/{workflow → skill-registry}/skills/review-work/SKILL.md +15 -15
  157. package/packages/{workflow → skill-registry}/skills/scan-issues/SKILL.md +7 -7
  158. package/packages/{workflow → skill-registry}/skills/work/SKILL.md +10 -10
  159. package/packages/{workflow → skill-registry}/skills/worktree-create/SKILL.md +4 -4
  160. package/packages/{workflow → skill-registry}/skills/worktree-list/SKILL.md +3 -3
  161. package/packages/{workflow → skill-registry}/skills/worktree-merge/SKILL.md +5 -5
  162. package/packages/subagents/package.json +6 -6
  163. package/packages/subagents/src/async-runner.ts +7 -2
  164. package/packages/subagents/src/config.ts +67 -44
  165. package/packages/subagents/src/fleet-data.ts +46 -2
  166. package/packages/subagents/src/fleet-view.ts +8 -2
  167. package/packages/subagents/src/index.ts +3 -1
  168. package/packages/subagents/src/mission-store.ts +5 -3
  169. package/packages/subagents/src/scheduled-runs.ts +3 -5
  170. package/packages/subagents/src/slash-commands.ts +6 -3
  171. package/packages/unipi/bundled.js +18911 -17585
  172. package/packages/unipi/index.ts +16 -8
  173. package/packages/updater/README.md +1 -1
  174. package/packages/updater/package.json +5 -5
  175. package/packages/updater/skills/configure-updater/SKILL.md +3 -5
  176. package/packages/updater/src/changelog.ts +5 -0
  177. package/packages/updater/src/commands.ts +1 -22
  178. package/packages/updater/src/index.ts +1 -2
  179. package/packages/updater/src/readme.ts +1 -2
  180. package/packages/updater/src/settings.ts +37 -12
  181. package/packages/utility/README.md +13 -17
  182. package/packages/utility/package.json +5 -5
  183. package/packages/utility/src/commands.ts +1 -191
  184. package/packages/utility/src/index.ts +79 -16
  185. package/packages/utility/src/settings.ts +160 -16
  186. package/packages/utility/src/skill-discovery.ts +447 -83
  187. package/packages/watchdog/README.md +66 -0
  188. package/packages/watchdog/index.ts +506 -0
  189. package/packages/{milestone → watchdog}/package.json +17 -19
  190. package/packages/watchdog/src/bash-kill.ts +151 -0
  191. package/packages/watchdog/src/config.ts +120 -0
  192. package/packages/watchdog/src/decide.ts +74 -0
  193. package/packages/watchdog/src/extract.ts +17 -0
  194. package/packages/web-api/README.md +6 -6
  195. package/packages/web-api/package.json +4 -4
  196. package/packages/web-api/skills/web/SKILL.md +4 -4
  197. package/packages/web-api/src/cache.ts +1 -1
  198. package/packages/web-api/src/commands.ts +19 -31
  199. package/packages/web-api/src/index.ts +1 -3
  200. package/packages/web-api/src/providers/firecrawl.ts +1 -1
  201. package/packages/web-api/src/providers/perplexity.ts +3 -3
  202. package/packages/web-api/src/providers/serpapi.ts +1 -1
  203. package/packages/web-api/src/providers/tavily.ts +1 -1
  204. package/packages/web-api/src/providers/wigolo-client.ts +2 -2
  205. package/packages/web-api/src/settings.ts +117 -30
  206. package/packages/web-api/src/tools.ts +1 -1
  207. package/packages/workflow/README.md +98 -144
  208. package/packages/workflow/index.ts +55 -211
  209. package/packages/workflow/package.json +14 -16
  210. package/packages/workflow/src/permission/bash.ts +262 -0
  211. package/packages/workflow/src/permission/decide.ts +152 -0
  212. package/packages/workflow/src/permission/index.ts +222 -0
  213. package/packages/workflow/src/permission/prompt.ts +73 -0
  214. package/packages/workflow/src/permission/rules.ts +102 -0
  215. package/packages/workflow/src/permission/settings.ts +131 -0
  216. package/packages/workflow/src/plan/enforce.ts +59 -0
  217. package/packages/workflow/src/plan/index.ts +363 -0
  218. package/packages/workflow/src/plan/review.ts +114 -0
  219. package/packages/workflow/src/plan/state.ts +82 -0
  220. package/packages/ask-user/commands.ts +0 -50
  221. package/packages/ask-user/settings-tui.ts +0 -183
  222. package/packages/background-tasks/src/settings-overlay.ts +0 -208
  223. package/packages/compactor/src/tui/settings-overlay.ts +0 -613
  224. package/packages/core/sandbox.ts +0 -143
  225. package/packages/footer/src/tui/settings-tui.ts +0 -503
  226. package/packages/image/src/commands.ts +0 -17
  227. package/packages/image/src/tui/model-selector.ts +0 -356
  228. package/packages/image/src/tui/settings-dialog.ts +0 -275
  229. package/packages/input-shortcuts/src/settings-overlay.ts +0 -133
  230. package/packages/kanboard/commands.ts +0 -83
  231. package/packages/kanboard/skills/kanboard-doctor/SKILL.md +0 -71
  232. package/packages/kanboard/types.ts +0 -67
  233. package/packages/memory/tui/settings-tui.ts +0 -295
  234. package/packages/milestone/README.md +0 -106
  235. package/packages/milestone/commands.ts +0 -98
  236. package/packages/milestone/hooks.ts +0 -271
  237. package/packages/milestone/index.ts +0 -71
  238. package/packages/milestone/milestone.ts +0 -199
  239. package/packages/milestone/skills/milestone-onboard/SKILL.md +0 -114
  240. package/packages/milestone/skills/milestone-update/SKILL.md +0 -109
  241. package/packages/milestone/types.ts +0 -61
  242. package/packages/notify/tui/recap-model-selector.ts +0 -307
  243. package/packages/notify/tui/settings-overlay.ts +0 -553
  244. package/packages/ralph/README.md +0 -97
  245. package/packages/ralph/SKILL.md +0 -88
  246. package/packages/ralph/completions.ts +0 -170
  247. package/packages/ralph/index.ts +0 -527
  248. package/packages/ralph/package.json +0 -53
  249. package/packages/ralph/ralph-loop.ts +0 -400
  250. package/packages/ralph/reminder.ts +0 -40
  251. package/packages/ralph/tools.ts +0 -160
  252. package/packages/trajectory/README.md +0 -63
  253. package/packages/trajectory/index.ts +0 -100
  254. package/packages/trajectory/package.json +0 -43
  255. package/packages/trajectory/src/capture.ts +0 -203
  256. package/packages/trajectory/src/prefix-integrity.ts +0 -213
  257. package/packages/trajectory/src/project.ts +0 -245
  258. package/packages/trajectory/src/server.ts +0 -95
  259. package/packages/trajectory/src/telemetry.ts +0 -136
  260. package/packages/trajectory/src/tracer.ts +0 -401
  261. package/packages/trajectory/src/ui.ts +0 -69
  262. package/packages/updater/src/tui/settings-overlay.ts +0 -178
  263. package/packages/utility/src/tui/util-settings-tui.ts +0 -315
  264. package/packages/web-api/src/tui/settings-dialog.ts +0 -359
  265. package/packages/workflow/commands.ts +0 -407
  266. package/packages/workflow/lifecycle.ts +0 -43
package/CHANGELOG.md CHANGED
@@ -6,6 +6,92 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Added
10
+
11
+ - **kanboard: the v3 daemon and web UI** (`unipi-kanboard serve`). Single instance via `flock(daemon.lock)` (a second `serve` prints the running `daemon.json` and exits 0), binds `127.0.0.1` with `--port` or an OS-assigned port, writes `daemon.json` atomically, removes it on exit (SIGTERM/SIGINT/idle), and shuts down after `--idle-min` (default 10) with no SSE clients and no requests. A `notify` watcher on `projects/` bumps one revision per content change (access events ignored, bursts coalesced) and `GET /events?project=<slug>` streams it, so CLI and agent writes appear live. `status` reports the daemon + liveness, `stop` SIGTERMs it and waits ≤3s.
12
+
13
+ - **kanboard: JSON API + server-rendered board UI.** `/api/health`, `/api/projects`, task list/show, and create/move/note/edit/link/unlink/order/duplicate — every handler calls the same library functions as the CLI, the actor is always `user`, and rule violations answer 4xx with the rule text (a move that needs a comment answers **409 + `needsComment`**). The UI is Topcoat 0.8.1 (pinned, `router/serve/view/sse/discover` only, no runtime/asset/tailwind): project picker, 7 lanes + Archive toggle, priority/dep/running/stale badges, quick-add, drag to move or reorder (comment modal on 409, toast + snap-back on refusal), card drawer with edit/deps/comment/activity and Duplicate/Cancel/Archive, EventSource live refresh — and no run button: work still starts only from a terminal.
14
+
15
+ - **kanboard: `rust-toolchain.toml` + edition 2024** for the crate (Topcoat's `impl View` idiom requires it), CSS/JS inlined with `include_str!` so the binary stays self-contained.
16
+
17
+ - **watchdog: jev watchdog for long-running tool calls.** New `@pi-unipi/watchdog` package (off by default, configurable in /unipi:settings → Watchdog). Every interval, jev judges whether a running bash tool call or background task is stuck or looping. Kills the process group (bash) or stops the task (bg_run) with the reason injected into the tool result or completion notification. Persistent processes (dev servers, watchers) are vetoed unless they're looping with errors. Configurable: interval, confidence, agreeing checks, action (kill/warn), per-kind toggles, otherTools (warn/abort-turn).
18
+
19
+ - **utility: jev-judged skill exposure.** With many skills installed, `<available_skills>` bloats the system prompt. New `skills.mode` setting (`judged` default / `all` / `off`): on the session's first prompt jev (the long-horizon Decision model) scores every skill's relevance in ONE System One call; only relevant skills stay cataloged (sorted by relevance, capped at `skills.maxSkills`, threshold `skills.threshold`), the set is frozen per session and persisted via a custom session entry so the system prompt stays byte-identical on every later turn. `skills.recheck` (default on) announces newly relevant hidden skills on later prompts via a persisted message (never twice, max 5 per prompt). The old `skills.discovery` boolean migrates (`false` → `off`, `true` → `judged`).
20
+
21
+ - **core: shared jev client** (`askJev`) — native typesafe `/v1/systemone` and OpenRouter `/api/alpha/decisions` transports with the judge's baseUrl/key/timeout rules; fail-open (null) on any error, missing key, or timeout. The long-horizon judge now uses it for its System One transports (chat-model fallback unchanged).
22
+
23
+ - **workflow: permission modes.** Every tool call now passes a gate: `ask` · `auto` (default) · `full`. Read-only tools always run; writes inside the workspace run in auto/full; **dangerous** bash (`rm -rf`, `sudo`, `dd`/`mkfs`, `chmod -R`, `curl|sh`, `git push --force`, `git reset --hard`, `git clean -f`, `git branch -D`, `kill -9`/`pkill`, writes into `~/.ssh`/`~/.aws`/`/etc`, reads of `.env`/`id_rsa`/`*.pem`) always asks; anything else in auto is judged by **jev** (one Decision-model call: `safe` / `needs_approval` / `dangerous`) — `safe` above `jevConfidence` runs, otherwise it prompts. Saved allow/deny glob **rules** are checked first and deny wins in every mode. The prompt is Enter-friendly: `Allow once` (default) · `Always allow <pattern>` (saves a project rule) · `Deny` · `Deny with note…` (the note reaches the agent as the block reason). Without a UI nothing ever prompts: full behaviour, except deny rules and dangerous patterns, which are blocked with a reason. `/unipi:permission [ask|auto|full]` and `Alt+M` (cycles) set the mode; hub → **Permissions** renders mode/jevJudge/jevConfidence plus a clear-rules action showing the saved-rule count. `UNIPI_DEBUG_PERMISSION=1` logs every decision to `~/.unipi/logs/permission.log`.
24
+
25
+ - **workflow: plan mode.** `/unipi:plan [on|off|view|approve]` (no argument toggles) or `Alt+P` turns the session read-only: the only writable file is `.unipi/plans/<YYYY-MM-DD>-<short-session-id>.md`, bash must be a read-only command (no jev), every other mutating tool is refused with `Plan mode is read-only. Write your plan to <path> and call plan_submit.` State is persisted in a session entry (resume keeps it, and the footer re-shows PLAN) and the mode reaches the model as appended messages — never the system prompt — so the provider prefix cache stays intact. `plan_submit` opens the approval prompt: `Approve & implement` (Enter) answers `Plan approved.` and queues the plan as the next user message with `Treat it as authoritative; do not re-plan.`; `Keep planning…` returns your feedback as the tool result; `Discard plan` turns the mode off.
26
+
27
+ - **footer: PLAN badge + permission mode.** The top frame's right side shows a bold `PLAN` badge while plan mode is active and the permission mode just before the top-right corner (dim `auto`, accent `ask`, warning `full`). Narrow terminals drop the permission label first, then truncate.
28
+
29
+ - **`@pi-unipi/skill-registry`** — new code-free package hosting the twenty bundled workflow skills (a future home for registry features).
30
+
31
+ ### Added
32
+
33
+ - **kanboard: remote access with a token gate.** `unipi-kanboard serve --host <addr>` (default `127.0.0.1`); any non-loopback bind generates a 32-byte base64url token, stores `host`/`token` in `daemon.json`, and requires it on every request as `?t=<token>` (sets an `HttpOnly; SameSite=Strict` cookie and 303-redirects to the URL without it), the `kb_token` cookie, or `Authorization: Bearer <token>` — compared in constant time, 401 otherwise. `/api/health` stays open but hides the pid off-loopback, POSTs whose `Origin` disagrees with `Host` are refused in both modes, and loopback binds stay token-free. `/unipi:kanboard open [--host H] [--port N]` (completions: `127.0.0.1`, `0.0.0.0`, `tailscale` → `tailscale ip -4`) overrides the new `host`/`port` settings per invocation, prints every reachable URL with the token (hostname + non-internal IPv4s + tailnet address for a wildcard bind), the `ssh -N -L …` tunnel hint for loopback, and a loud "reachable from the network" warning; a daemon running on another binding is stopped and restarted (`restarted kanboard on 0.0.0.0:37473`).
34
+
35
+ ### Changed
36
+
37
+ - **kanboard: platform binaries and packaging.** Five `@pi-unipi/kanboard-<platform>` packages (`linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`, `win32-x64`) hang off `@pi-unipi/kanboard` as `optionalDependencies`, each with `os`/`cpu` gates so npm installs exactly one. `.github/workflows/kanboard-binaries.yml` builds them per target (Linux via musl → static-pie binaries, ~3.9 MB), runs tests + clippy on native targets, uploads one artifact per platform and, on a `v*` tag, attaches them to the GitHub release; npm publishing happens only when an `NPM_TOKEN` secret exists (there is none today), and `npm run publish:kanboard` **skips any platform package whose `bin/` is empty** with a loud warning and a non-zero exit. `ci.yml` now also runs `cargo test` + `cargo clippy -D warnings` for `crates/kanboard`. A local, offline packaging proof lives in `scripts/test-kanboard-packaging.mjs` (pack both packages, lay them out as `node_modules`, resolve through `src/bin.ts`, run `--version`).
38
+ - **kanboard: one unparseable task file no longer takes the board offline.** The store loads tolerantly — a file that fails validation is skipped (never partially trusted) and reported as `problems: [{file, line, error}]` by `list --json` and the API (`{tasks, problems}`); writing to a broken file answers `UNI-5 is unreadable: <message> (line N); run unipi-kanboard validate --fix`; the board page shows a red "N task file(s) need repair" banner and still renders everything else; `claim-next` ignores broken files.
39
+ - **workflow: the agent's board CLI no longer prompts in auto mode.** A simple command whose program is `unipi-kanboard` and whose args carry `--actor agent` classifies as *kanboard CLI* and runs in `auto`/`full`; `ask` mode still asks, `--actor user|system` is never covered, compound commands keep the per-part rules, and plan mode does not inherit the allowance.
40
+
41
+ ### Changed (earlier)
42
+
43
+ - **`@pi-unipi/kanboard` is now the v3 terminal client** for the Rust board: `/unipi:kanboard [open|onboard|add|work|stop|status]` with arg completions. `open` ensures the daemon (reuse a healthy one, else spawn `serve` detached) and prints the board URL; `onboard` is idempotent and reveals the skill; `add <text>` is quick capture into Backlog with no agent turn; `status` reports daemon, lane counts and the runner. Binary resolution: `UNIPI_KANBOARD_BIN` → `@pi-unipi/kanboard-<platform>-<arch>` → the dev build; nothing found means every command reports `kanboard binary unavailable for <platform>-<arch>` and does nothing else.
44
+ - **kanboard: the task runner (`work`).** One job per session, with the runner owning the transitions agents may not write: `claim-next` → jev picks the mode (`direct`/`plan`/`goal`, null → direct, logged to `~/.unipi/logs/kanboard.log` under `UNIPI_DEBUG_KANBOARD=1`) → `set-run` → the task (title, body, last 10 activity entries, deps with status and last note, and the rules) goes to the agent as a user message. Run end releases to In Review with the last assistant text (≤500 chars); a task the agent blocked is respected and the loop continues; Esc releases to Todo with "interrupted by user" and stops; session shutdown releases to Todo. `plan` mode drives workflow's plan mode through the new `unipi:plan-enter`/`unipi:plan-exit` command runners (a discarded plan releases to Todo); `goal` mode starts a long-horizon goal through `unipi:goal-start`, records the goal id with `set-run --goal`, and reads completion from `unipi:goal-status`. Footer shows `▣ UNI-12 · direct`; the claim is persisted with `appendEntry` so a reload offers resume or release.
45
+ - **kanboard: `skills/kanboard/SKILL.md`** teaches the CLI and the rules (never `--actor user`, never move to in_review/done, block with a comment to ask the user, file follow-ups in Backlog). `onboard`/`work` force-reveal it through the new `unipi:skills:reveal` event, which utility turns into the usual append-only reveal message — the system prompt stays untouched. Hub section "Kanboard" (namespace `kanboard`): `chainGate`, `continue`, `idleMin`, `port`, `archiveAfterDays` (sweep on session start), `openBrowser`, plus "Open board…" and "Stop daemon" actions.
46
+ - **core: `callCommandRunner`** — call another module's registered runner and read its result (`registerCommandRunner` handlers may now take an `args` payload and return a value). Used by kanboard for plan/goal, and by the settings hub as before.
47
+
48
+
49
+ - **kanboard: the Topcoat spike is retired** — its findings live on at `docs/research/2026-09-24-topcoat-spike.md`; Topcoat 0.8.1 is the adopted UI layer for the daemon.
50
+
51
+ - **docs live in the project's `docs/` folder — the `.unipi/docs/` convention is gone.** Skills write to `docs/specs`, `docs/plans`, `docs/debug`, `docs/fix`, `docs/quick-work`, `docs/chore`, `docs/reviews`, `docs/generated` and `docs/research` in the project (creating the folder when it is missing), plan mode writes `docs/plans/<YYYY-MM-DD>-<short-session-id>.md`, and kanboard parses `docs/` (default `docsRoot`). `.unipi/` now holds runtime state only (config, sessions, ralph), nothing is created there eagerly, and `UNIPI_DIRS` + the eager docs-directory creation are removed. **Existing `.unipi/docs/` folders are left untouched — there is no automatic migration.**
52
+
53
+ ### Removed
54
+
55
+ - **kanboard: the old htmx/Alpine board is gone** — `parser/`, `server/`, `ui/`, `commands.ts`, `types.ts` and the `kanboard-doctor` skill (with its autocomplete and core constants). The v3 board is the Rust binary plus the Topcoat UI inside it.
56
+ - **workflow: the twenty workflow slash commands** — `unipi:brainstorm`, `unipi:work`, `unipi:review-work`, `unipi:consolidate`, `unipi:worktree-create`/`-list`/`-merge`, `unipi:consultant`, `unipi:quick-work`, `unipi:gather-context`, `unipi:document`, `unipi:scan-issues`, `unipi:auto`, `unipi:debug`, `unipi:fix`, `unipi:quick-fix`, `unipi:research`, `unipi:chore-create`/`-execute`, plus the old `unipi:plan` pipeline and its per-command tool sandboxes. Replaced by **plan mode** and **permission modes**; their skills moved to the new `@pi-unipi/skill-registry` package (still loadable via `/skill:<name>`, still visible to jev skill judging). `@pi-unipi/workflow` keeps its name and now hosts plan/permission enforcement.
57
+
58
+ - **core: the workflow sandbox module** (`sandbox.ts`) — tool-access levels existed only to back the removed workflow commands. Call-time enforcement is now the permission gate in `@pi-unipi/workflow`.
59
+
60
+ - **Legacy per-module settings commands — use `/unipi:settings`.** Every settings overlay absorbed into the unified hub; only interactive wizards/tools remain as overlays:
61
+ - `unipi:updater-settings` — check interval + auto-update were already in the hub (Updater group).
62
+ - `unipi:ask-user-settings` — tool + format toggles already in the hub (Ask User group).
63
+ - `unipi:stash-settings` — chordKey/tabInsertKey enums (with hint + keybinding validator) in the hub; config/registration moved to `input-shortcuts/src/settings.ts`.
64
+ - `unipi:badge-settings` + `unipi:util-settings` — badge fields already in the hub; disabling the badge still hides it live (hub `onChanged`).
65
+ - `unipi:skills-settings` — `unipi.skills.discovery` migrated into the utility namespace (one-time import); the gate now reads the engine.
66
+ - `unipi:bg-settings` — master toggle/defaults already in the hub; orphan `maxOutputBytes` added.
67
+ - `unipi:image-settings` — `recognize.systemPrompt` added to the hub schema; generate.model presets + recognize image-input capability replace the dialog/model selector.
68
+ - `unipi:web-settings` — provider pages already in the hub; `browser`/`os`/`includeReplies` enums added.
69
+ - `unipi:info-settings` — absorbed as a dynamic "Groups & stats…" page (live from the group registry) + "Group order" reorder field.
70
+ - `unipi:footer-settings` — absorbed: separator + zoneSeparator enums, dynamic "Segments…" page (per-group and per-segment visibility). Zone Headers was a non-functional stub in the old overlay and was not absorbed.
71
+ - `unipi:compact-settings` — absorbed: per-strategy mode enums, Auto (%-trigger) section, Pipeline toggles, and "Apply preset" action rows (precise/balanced/thorough/lean). `/unipi:compact-preset` (CLI args) is kept.
72
+ - `unipi:notify-settings` — absorbed: "Events…" page (enable + platform multiselect per event), defaultPlatforms/silence/renotify fields, per-platform "Setup & test…" wizard actions, and a "Send test notification" action. `/unipi:notify-recap-model` keeps the recap selector overlay.
73
+ - `unipi:memory-settings` — absorbed:
74
+ - `unipi:badge-name` / `unipi:badge-gen` / `unipi:badge-toggle` — hub Badge group: "Show name badge" field + "Set session name…" / "Generate session name" actions.
75
+ - `unipi:notify-set-gotify` / `unipi:notify-set-tg` / `unipi:notify-set-ntfy` / `unipi:notify-test` / `unipi:notify-recap-model` — hub Notify group: per-platform "Setup & test…" actions, "Send test notification" action, and the `recap.model` field.
76
+ - `unipi:compact-preset` — hub Compactor › Presets action rows (precise/balanced/thorough/lean).
77
+ - `unipi:mcp-add` / `unipi:mcp-settings` / `unipi:mcp-sync` / `unipi:mcp-reload` — hub MCP group: "Configure MCP servers…", "Add server…", "Sync catalog…", "Reload servers…" actions.
78
+ - `unipi:fusion-preset` — hub Fusion group: "Edit fusion presets…" action.
79
+ - `unipi:web-cache-clear` — hub Web API group: "Clear web cache…" action (with confirm). provider none/inherit/openrouter/custom with per-provider model presets + baseUrl, and a "Re-embed all memories…" action (confirm + progress toast).
80
+
81
+ ## [3.0.0-alpha.0] — 2026-09-20
82
+
83
+ ### Changed
84
+
85
+ - **Pi SDK 0.84 → 0.86.** All `@earendil-works/{pi-coding-agent,pi-ai,pi-tui,pi-agent-core}` peer dependencies bump from `^0.84.0` to `^0.86.0` (installs 0.86.1). Two 0.86 breaking changes touched unipi:
86
+ - `ToolCall.arguments` / `ToolResultMessage.details` are now JSON-strict (`JsonValue` values). The background-tasks scripted test providers dropped their local `Record<PropertyKey, unknown>` alias and import pi-ai's `JsonObject` instead; production code needed no changes.
87
+ - Raw pi-ai API adapters (`pi-ai/api/*`) now require a normalized `TranscriptContext` — a raw `Context` passed to them silently loses its `systemPrompt` and `tools`. The `tests/prefix-provider-payload.test.js` harness normalizes via `normalizeContext()` (`@earendil-works/pi-ai/utils/transcript`) before invoking the openai-completions adapter. No unipi production code calls raw adapters (all model calls flow through pi's extension API, which normalizes internally).
88
+ - Not adopted yet, but relevant to v3: native prompt-cache warming, transcript-aware prompt/tool updates with cached-prefix preservation, per-model compaction budgets, `ctx.modelRegistry.stream()`, deferred tool loading (`ToolSearch`).
89
+ - `core`, `updater`: **prerelease-aware version comparison.** `compareVersions` in `@pi-unipi/core` previously split on `.` and `-` and compared only the numeric triple, discarding prerelease identifiers entirely — `3.0.0`, `3.0.0-alpha.0` and `3.0.0-alpha.9` all compared equal, so an alpha-channel install would never be prompted when `3.0.0` graduated to stable, and `3.0.0-alpha.10` never looked newer than `3.0.0-alpha.9`. The comparison now orders prerelease identifiers by semver §11 precedence (release > prerelease, numeric ids numerically and below alphanumeric ones). `updater`'s `getNewerVersions` also gains channel discipline: a stable install (npm `latest`) is never offered prerelease changelog entries, while a prerelease install sees every entry newer than itself.
90
+
91
+ ### Added
92
+
93
+ - **Prerelease channel.** The v3 branch publishes as `3.0.0-alpha.N` under npm dist-tags (`--tag alpha`), leaving `latest` on the 2.x line. `scripts/sync-pins.mjs` now accepts prerelease versions, and the full-release chore documents the prerelease rules (never omit `--tag` on a prerelease, fresh suffix per publish, graduation moves `latest`).
94
+
9
95
  ## [2.20.5] — 2026-09-19
10
96
 
11
97
  ### Fixed
@@ -896,3 +982,4 @@ Startup went from **23.1s to 0.75s** — 31× faster, and within ~0.7s of bare `
896
982
  ### Changed
897
983
  - Compactor commands need `unipi:` prefix
898
984
  - Footer icon style now configurable
985
+
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ <p align="center"><img src="docs/assets/unipi-logo.png" width="200" alt="UniPi"></p>
2
+
1
3
  # Unipi
2
4
 
3
5
  23 workspace packages that turn Pi into a full development workstation. Structured workflows, persistent memory, parallel agents, web research, notifications, context management, command autocomplete, and a live status bar — all wired together through a shared event system.
@@ -9,13 +11,13 @@ pi install npm:@pi-unipi/unipi
9
11
 
10
12
  ## Requirements
11
13
 
12
- - **Pi (`@earendil-works/pi-coding-agent`) `^0.84.0`** — Unipi 2.9.0 tracks the Pi 0.84 SDK (extension event map incl. `agent_settled`, `ModelRuntime` session options, kitty-protocol keyboard handling). Older Pi releases (0.80–0.83) still load most extensions, but npm will flag the peer dependency mismatch; pin `@pi-unipi/*@<2.9.0` if you must stay on an older Pi.
14
+ - **Pi (`@earendil-works/pi-coding-agent`) `^0.86.0`** — Unipi 3.0.0-alpha tracks the Pi 0.86 SDK (JSON-strict `ToolCall.arguments` / `ToolResultMessage.details`, `TranscriptContext` custom-provider inputs, native prompt-cache warming, per-model compaction budgets, `ctx.modelRegistry.stream()`). Older Pi releases (0.80–0.85) still load most extensions, but npm will flag the peer dependency mismatch; pin `@pi-unipi/*@<3.0.0` if you must stay on an older Pi.
13
15
 
14
16
  ## What You Get
15
17
 
16
- **[Workflow](./packages/workflow/README.md)** — 20 commands that take ideas to shipped code. Brainstorm, plan, execute in worktrees, review, consolidate. The agent follows skill files step by step.
18
+ **[Workflow](./packages/workflow/README.md)** — **plan mode** (`/unipi:plan`, `Alt+P`) and **permission modes** (`ask` · `auto` · `full`). Plan mode makes a session read-only except for its plan file; auto mode lets jev judge ambiguous bash before it runs. The twenty workflow skills moved to [@pi-unipi/skill-registry](./packages/skill-registry/README.md).
17
19
 
18
- **[Ralph](./packages/ralph/README.md)** — Long-running loops that persist across sessions. Start a task, iterate through checklist items, resume after crashes. Progress tracked, state saved.
20
+ **[Long-Horizon](./packages/long-horizon/)** — Mode-gated long-horizon execution: `/goal` (one objective until verifiably true, propose+verify), `/ralph` (task-file iteration loops), `/swarm` (independent fan-out + synthesis), `/graph` (dependent multi-step work). A TypeSafe jev prompt judge routes each turn; one automation owner per session with park/resume; runaway-guard steering; token/turn/stall budgets.
19
21
 
20
22
  **[Memory](./packages/memory/README.md)** — SQLite + vector search stores facts, preferences, and decisions. Project-scoped and global. The agent remembers what you told it last week.
21
23
 
@@ -43,12 +45,8 @@ pi install npm:@pi-unipi/unipi
43
45
 
44
46
  **[Ask User](./packages/ask-user/README.md)** — Structured input for decision gates. Single-select, multi-select, freeform. The agent asks instead of guessing.
45
47
 
46
- **[Milestone](./packages/milestone/README.md)** — Track project goals across workflow cycles. MILESTONES.md stays in sync with specs, plans, and completed work.
47
-
48
48
  **[Kanboard](./packages/kanboard/README.md)** — Web UI and TUI overlay for kanban boards. Parses all workflow documents into cards with progress indicators.
49
49
 
50
- **[Trajectory](./packages/trajectory/README.md)** — Live localhost session inspector. Explore turns, reasoning, tool payloads/results, timing, token/cache usage, and compactions for the current session.
51
-
52
50
  **[Info Screen](./packages/info-screen/README.md)** — Dashboard overlay showing module status, tools, and custom data groups.
53
51
 
54
52
  **[Utility](./packages/utility/README.md)** — Environment info, diagnostics, cleanup, name badge, and Shiki-powered diff rendering.
@@ -90,27 +88,31 @@ Coexists triggers enhance behavior when packages are installed together. Workflo
90
88
 
91
89
  | Category | Prefix | Examples |
92
90
  |----------|--------|----------|
93
- | Workflow | `/unipi:` | brainstorm, plan, work, review-work, consolidate, quick-work, debug, fix |
94
- | Ralph | `/unipi:ralph` | start, stop, resume, status |
91
+ | Workflow | `/unipi:` | plan (plan mode), permission (permission modes) |
92
+ | Kanboard | `/unipi:` | kanboard (board: capture, work runner, web UI) |
93
+ | Long-Horizon | `/unipi:goal`, `/unipi:ralph`, `/unipi:swarm`, `/unipi:graph` | <prompt>, start, stop, status, resume, clear |
95
94
  | Memory | `/unipi:memory-` | process, search, consolidate, forget |
96
- | Compactor | `/unipi:` | lossless-compact, session-recall, compact-stats, compact-settings, compact-preset, compact-help |
95
+ | Compactor | `/unipi:` | lossless-compact, session-recall, compact-stats, compact-preset, compact-help |
97
96
  | Notify | `/unipi:notify-` | settings, test, set-tg, set-ntfy |
98
97
  | MCP | `/unipi:mcp-` | add, settings, sync, status |
99
98
  | Web | `/unipi:web-` | settings, cache-clear |
100
99
  | BTW | `/unipi:btw` | question, btw-new, btw-tangent, btw-inject, btw-summarize |
101
100
  | Utility | `/unipi:` | env, doctor, status, cleanup, badge-name |
102
- | Milestone | `/unipi:milestone-` | onboard, update |
103
101
  | Kanboard | `/unipi:kanboard` | toggle, doctor |
104
- | Trajectory | `/unipi:trajectory` | open the live current-session inspector |
105
102
  | Footer | `/unipi:footer` | toggle, settings |
106
- | Updater | `/unipi:` | readme, changelog, updater-settings |
103
+ | Watchdog | `/unipi:settings` | jev judges long-running tools; kills or warns when stuck |
104
+ | Updater | `/unipi:` | readme, changelog |
107
105
  | Info | `/unipi:info` | dashboard, settings |
108
106
 
109
107
  ## Agent Tools (Brief)
110
108
 
111
109
  | Tool | Package | What It Does |
112
110
  |------|---------|--------------|
113
- | `ralph_start` / `ralph_done` | ralph | Loop control |
111
+ | `create_goal` / `get_goal` / `update_goal` | long-horizon | Goal propose+verify lifecycle |
112
+ | `todowrite` | long-horizon | Visible session plan |
113
+ | `ralph_done` / `loop_status` | long-horizon | Loop iteration + progress |
114
+ | `swarm_report` / `swarm_status` / `swarm_yield` | long-horizon | Fan-out supervision |
115
+ | `update_agent_graph` / `graph_output` / `view_agent_graph` | long-horizon | Dependent work graph |
114
116
  | `spawn_helper` / `get_helper_result` | subagents | Parallel agents |
115
117
  | `memory_store` / `memory_search` / `memory_delete` | memory | Memory CRUD |
116
118
  | `web_search` / `multi_web_content_read` / `web_llm_summarize` | web-api | Web research |
@@ -138,8 +140,9 @@ npm run typecheck
138
140
  unipi/
139
141
  ├── packages/
140
142
  │ ├── core/ # Shared constants, events, utilities
141
- │ ├── workflow/ # 20 skill-based commands
142
- │ ├── ralph/ # Iterative loops
143
+ │ ├── workflow/ # plan mode + permission modes
144
+ │ ├── skill-registry/ # bundled workflow skills (no code yet)
145
+ │ ├── long-horizon/ # /goal /ralph /swarm /graph mode-gated execution
143
146
  │ ├── memory/ # SQLite + vector search
144
147
  │ ├── compactor/ # Context engine
145
148
  │ ├── subagents/ # Parallel execution
@@ -152,16 +155,15 @@ unipi/
152
155
  │ ├── footer/ # Status bar
153
156
  │ ├── btw/ # Side conversations
154
157
  │ ├── ask-user/ # Structured input
155
- │ ├── milestone/ # Goal tracking
156
158
  │ ├── kanboard/ # Kanban visualization
157
- │ ├── trajectory/ # Live session trajectory inspector
158
159
  │ ├── info-screen/ # Dashboard overlay
159
160
  │ ├── utility/ # Diagnostics, diff rendering
160
161
  │ ├── updater/ # Auto-update, browsers
161
162
  │ ├── input-shortcuts/ # Keyboard shortcuts
162
163
  │ ├── autocomplete/ # Enhanced command autocomplete
163
164
  │ └── unipi/ # Umbrella package
164
- ├── .unipi/ # Runtime data (specs, plans, worktrees)
165
+ ├── docs/ # Project documentation (specs, plans, fixes, …)
166
+ ├── .unipi/ # Runtime data (config, sessions, ralph)
165
167
  └── CHANGELOG.md
166
168
  ```
167
169
 
@@ -31,7 +31,6 @@ This matrix reflects UniPi source and Pi 0.84.1 APIs as audited for the v2.5.x r
31
31
  | Surface | Status | Ownership and behavior |
32
32
  |---|---|---|
33
33
  | Ralph iteration state | Fixed | Hidden `unipi-ralph-loop-reminder` tail snapshots; no system-prompt mutation. |
34
- | Milestone state | Fixed | Workspace-qualified, compaction-aware `unipi-milestone-snapshot` messages append only when state changes. |
35
34
  | Workflow sandbox | Fixed | Stable tool schemas; `tool_call` blocks disallowed execution; active/inactive snapshots supersede prior state. |
36
35
  | Memory reminders | Fixed | First-turn and retrospective reminders are tail messages. |
37
36
  | Compactor resume | Fixed | One-shot hidden resume context extends the post-compaction epoch. Snapshot rendering is deterministic for fixed stored events. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/unipi",
3
- "version": "2.20.5",
3
+ "version": "3.0.0-alpha.0",
4
4
  "description": "All-in-one extension suite for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,7 +28,8 @@
28
28
  "prepublishOnly": "npm run build",
29
29
  "publish:all": "npm publish --workspaces --access public",
30
30
  "test": "npx tsx --test tests/*.test.js packages/memory/tests/*.test.ts && npm test --workspaces --if-present",
31
- "typecheck": "npx tsc --noEmit --skipLibCheck"
31
+ "typecheck": "npx tsc --noEmit --skipLibCheck",
32
+ "publish:kanboard": "node scripts/publish-kanboard-platforms.mjs"
32
33
  },
33
34
  "files": [
34
35
  "CHANGELOG.md",
@@ -58,8 +59,7 @@
58
59
  "packages/unipi/bundled.js"
59
60
  ],
60
61
  "skills": [
61
- "packages/workflow/skills",
62
- "packages/ralph/SKILL.md",
62
+ "packages/skill-registry/skills",
63
63
  "packages/memory/skills",
64
64
  "packages/btw/skills",
65
65
  "packages/ask-user/skills",
@@ -67,7 +67,6 @@
67
67
  "packages/utility/skills",
68
68
  "packages/compactor/skills",
69
69
  "packages/notify/skills",
70
- "packages/milestone/skills",
71
70
  "packages/kanboard/skills",
72
71
  "packages/updater/skills",
73
72
  "packages/image/skills",
@@ -78,41 +77,39 @@
78
77
  ]
79
78
  },
80
79
  "peerDependencies": {
81
- "@earendil-works/pi-ai": "^0.84.0",
82
- "@earendil-works/pi-coding-agent": "^0.84.0",
83
- "@earendil-works/pi-tui": "^0.84.0",
80
+ "@earendil-works/pi-ai": "^0.86.0",
81
+ "@earendil-works/pi-coding-agent": "^0.86.0",
82
+ "@earendil-works/pi-tui": "^0.86.0",
84
83
  "typebox": "^1.1.38"
85
84
  },
86
85
  "dependencies": {
87
- "@pi-unipi/ask-user": "2.20.5",
88
- "@pi-unipi/background-tasks": "2.20.5",
89
- "@pi-unipi/btw": "2.20.5",
90
- "@pi-unipi/command-enchantment": "2.20.5",
91
- "@pi-unipi/compactor": "2.20.5",
92
- "@pi-unipi/core": "2.20.5",
93
- "@pi-unipi/footer": "2.20.5",
94
- "@pi-unipi/image": "2.20.5",
95
- "@pi-unipi/fusion": "2.20.5",
96
- "@pi-unipi/info-screen": "2.20.5",
97
- "@pi-unipi/input-shortcuts": "2.20.5",
98
- "@pi-unipi/kanboard": "2.20.5",
99
- "@pi-unipi/mcp": "2.20.5",
100
- "@pi-unipi/memory": "2.20.5",
101
- "@pi-unipi/milestone": "2.20.5",
102
- "@pi-unipi/notify": "2.20.5",
103
- "@pi-unipi/ralph": "2.20.5",
104
- "@pi-unipi/subagents": "2.20.5",
105
- "@pi-unipi/trajectory": "2.20.5",
106
- "@pi-unipi/updater": "2.20.5",
107
- "@pi-unipi/utility": "2.20.5",
108
- "@pi-unipi/web-api": "2.20.5",
109
- "@pi-unipi/workflow": "2.20.5"
86
+ "@pi-unipi/ask-user": "3.0.0-alpha.0",
87
+ "@pi-unipi/background-tasks": "3.0.0-alpha.0",
88
+ "@pi-unipi/btw": "3.0.0-alpha.0",
89
+ "@pi-unipi/command-enchantment": "3.0.0-alpha.0",
90
+ "@pi-unipi/compactor": "3.0.0-alpha.0",
91
+ "@pi-unipi/core": "3.0.0-alpha.0",
92
+ "@pi-unipi/footer": "3.0.0-alpha.0",
93
+ "@pi-unipi/image": "3.0.0-alpha.0",
94
+ "@pi-unipi/fusion": "3.0.0-alpha.0",
95
+ "@pi-unipi/info-screen": "3.0.0-alpha.0",
96
+ "@pi-unipi/input-shortcuts": "3.0.0-alpha.0",
97
+ "@pi-unipi/kanboard": "3.0.0-alpha.0",
98
+ "@pi-unipi/mcp": "3.0.0-alpha.0",
99
+ "@pi-unipi/memory": "3.0.0-alpha.0",
100
+ "@pi-unipi/notify": "3.0.0-alpha.0",
101
+ "@pi-unipi/skill-registry": "3.0.0-alpha.0",
102
+ "@pi-unipi/subagents": "3.0.0-alpha.0",
103
+ "@pi-unipi/updater": "3.0.0-alpha.0",
104
+ "@pi-unipi/utility": "3.0.0-alpha.0",
105
+ "@pi-unipi/web-api": "3.0.0-alpha.0",
106
+ "@pi-unipi/workflow": "3.0.0-alpha.0"
110
107
  },
111
108
  "devDependencies": {
112
- "@earendil-works/pi-agent-core": "^0.84.0",
113
- "@earendil-works/pi-ai": "^0.84.0",
114
- "@earendil-works/pi-coding-agent": "^0.84.0",
115
- "@earendil-works/pi-tui": "^0.84.0",
109
+ "@earendil-works/pi-agent-core": "^0.86.0",
110
+ "@earendil-works/pi-ai": "^0.86.0",
111
+ "@earendil-works/pi-coding-agent": "^0.86.0",
112
+ "@earendil-works/pi-tui": "^0.86.0",
116
113
  "@types/better-sqlite3": "^9.6.0",
117
114
  "@types/node": "^25.6.0",
118
115
  "diff": "^7.0.0",
@@ -55,7 +55,7 @@ ask_user({
55
55
  label: "Proceed to work",
56
56
  value: "work",
57
57
  action: "new_session",
58
- prefill: "/unipi:work specs:2026-05-06-feature-plan.md",
58
+ prefill: "the implementation step specs:2026-05-06-feature-plan.md",
59
59
  },
60
60
  { label: "Done for now", value: "done", action: "end_turn" },
61
61
  ],
@@ -5,9 +5,7 @@
5
5
  * under the "unipi.askUser" key.
6
6
  */
7
7
 
8
- import { readFileSync, writeFileSync, existsSync } from "node:fs";
9
- import { join } from "node:path";
10
- import { homedir } from "node:os";
8
+ import { getSettings, registerSettings, setSettings } from "@pi-unipi/core";
11
9
 
12
10
  /** Ask-user settings */
13
11
  export interface AskUserSettings {
@@ -37,13 +35,7 @@ export const DEFAULT_SETTINGS: AskUserSettings = {
37
35
  notifyOnAsk: true,
38
36
  };
39
37
 
40
- /** Settings path */
41
- const SETTINGS_PATH = join(homedir(), ".pi", "agent", "settings.json");
42
38
 
43
- /** Settings key within settings.json */
44
- const SETTINGS_KEY = "unipi";
45
-
46
- /** Cached settings */
47
39
  let cachedSettings: AskUserSettings | null = null;
48
40
 
49
41
  /**
@@ -53,46 +45,42 @@ function isRecord(value: unknown): value is Record<string, unknown> {
53
45
  return typeof value === "object" && value !== null && !Array.isArray(value);
54
46
  }
55
47
 
56
- /**
57
- * Read the full settings file.
58
- */
59
- function readSettingsFile(): Record<string, unknown> {
60
- if (!existsSync(SETTINGS_PATH)) return {};
61
- try {
62
- const parsed = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
63
- return isRecord(parsed) ? parsed : {};
64
- } catch {
65
- return {};
66
- }
67
- }
68
-
69
- /**
70
- * Write the full settings file.
71
- */
72
- function writeSettingsFile(data: Record<string, unknown>): void {
73
- const dir = require("node:path").dirname(SETTINGS_PATH);
74
- if (!existsSync(dir)) {
75
- require("node:fs").mkdirSync(dir, { recursive: true });
76
- }
77
- writeFileSync(SETTINGS_PATH, JSON.stringify(data, null, 2) + "\n", "utf-8");
78
- }
79
-
80
48
  /**
81
49
  * Get ask-user settings from settings.json.
82
50
  */
51
+ // Registered with the unified settings hub. The engine's migration imports
52
+ // the legacy ~/.pi/agent/settings.json unipi.askUser block once automatically.
53
+ registerSettings({
54
+ namespace: "ask-user",
55
+ label: "Ask User",
56
+ defaults: DEFAULT_SETTINGS as unknown as Record<string, unknown>,
57
+ schema: [
58
+ {
59
+ title: "Tool",
60
+ fields: [
61
+ { key: "enabled", type: "boolean", label: "Enable ask_user tool", description: "Allow the agent to ask structured questions" },
62
+ { key: "notifyOnAsk", type: "boolean", label: "Notify on ask", description: "Send a notification when the agent pauses to ask" },
63
+ ],
64
+ },
65
+ {
66
+ title: "Allowed formats",
67
+ fields: [
68
+ { key: "allowedFormats.singleSelect", type: "boolean", label: "Single-select", description: "Questions with one correct answer" },
69
+ { key: "allowedFormats.multiSelect", type: "boolean", label: "Multi-select", description: "Questions with several answers" },
70
+ { key: "allowedFormats.freeform", type: "boolean", label: "Freeform", description: "Plain text input" },
71
+ ],
72
+ },
73
+ ],
74
+ });
75
+
83
76
  export function getAskUserSettings(): AskUserSettings {
84
77
  if (cachedSettings) return cachedSettings;
85
-
86
- const settings = readSettingsFile();
87
- const unipi = settings[SETTINGS_KEY];
88
-
89
- if (!isRecord(unipi) || !isRecord(unipi.askUser)) {
78
+ const askUser = getSettings("ask-user", process.cwd()) as Record<string, unknown>;
79
+ if (!isRecord(askUser)) {
90
80
  cachedSettings = { ...DEFAULT_SETTINGS };
91
81
  return cachedSettings;
92
82
  }
93
83
 
94
- const askUser = unipi.askUser as Record<string, unknown>;
95
-
96
84
  const enabled = typeof askUser.enabled === "boolean" ? askUser.enabled : DEFAULT_SETTINGS.enabled;
97
85
 
98
86
  let allowedFormats = DEFAULT_SETTINGS.allowedFormats;
@@ -115,19 +103,7 @@ export function getAskUserSettings(): AskUserSettings {
115
103
  * Save ask-user settings to settings.json.
116
104
  */
117
105
  export function saveAskUserSettings(settings: AskUserSettings): void {
118
- const file = readSettingsFile();
119
-
120
- if (!isRecord(file[SETTINGS_KEY])) {
121
- file[SETTINGS_KEY] = {};
122
- }
123
-
124
- (file[SETTINGS_KEY] as Record<string, unknown>).askUser = {
125
- enabled: settings.enabled,
126
- allowedFormats: settings.allowedFormats,
127
- notifyOnAsk: settings.notifyOnAsk,
128
- };
129
-
130
- writeSettingsFile(file);
106
+ setSettings("ask-user", settings as unknown as Record<string, unknown>, "global", process.cwd());
131
107
  cachedSettings = settings;
132
108
  }
133
109
 
@@ -16,23 +16,21 @@ import {
16
16
  getPackageVersion,
17
17
  } from "@pi-unipi/core";
18
18
  import { registerAskUserTools } from "./tools.js";
19
- import { registerAskUserCommands } from "./commands.js";
20
19
 
21
20
  /** Package version */
22
21
  const VERSION = getPackageVersion(dirname(fileURLToPath(import.meta.url)));
23
22
 
24
23
  export default function (pi: ExtensionAPI) {
25
24
 
26
- // Register tools and commands
25
+ // Register tools
27
26
  registerAskUserTools(pi);
28
- registerAskUserCommands(pi);
29
27
 
30
28
  // Session lifecycle — announce module
31
29
  pi.on("session_start", async () => {
32
30
  emitEvent(pi, UNIPI_EVENTS.MODULE_READY, {
33
31
  name: MODULES.ASK_USER,
34
32
  version: VERSION,
35
- commands: ["unipi:ask-user-settings"],
33
+ commands: [],
36
34
  tools: [ASK_USER_TOOLS.ASK],
37
35
  });
38
36
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pi-unipi/ask-user",
3
- "version": "2.20.5",
4
- "description": "Structured user input tool for Pi coding agent — single-select, multi-select, freeform",
3
+ "version": "3.0.0-alpha.0",
4
+ "description": "Structured user input tool for Pi coding agent \u2014 single-select, multi-select, freeform",
5
5
  "type": "module",
6
6
  "main": "index.ts",
7
7
  "license": "MIT",
@@ -40,11 +40,11 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "@pi-unipi/core": "2.20.5"
43
+ "@pi-unipi/core": "3.0.0-alpha.0"
44
44
  },
45
45
  "peerDependencies": {
46
- "@earendil-works/pi-coding-agent": "^0.84.0",
47
- "@earendil-works/pi-tui": "^0.84.0",
46
+ "@earendil-works/pi-coding-agent": "^0.86.0",
47
+ "@earendil-works/pi-tui": "^0.86.0",
48
48
  "typebox": "^1.1.38"
49
49
  },
50
50
  "pi": {
@@ -161,4 +161,4 @@ When a user selects a `new_session` option, a secondary launcher overlay appears
161
161
  | ▶ Run directly | Queues/submits the prefill immediately as a follow-up message, without compaction |
162
162
  | ✕ Cancel | Cancels the session launch; no prefill is queued |
163
163
 
164
- The prefill can be a slash command (for example `/unipi:work specs:...`) or any non-empty message. If automatic delivery fails, ask_user places the prefill in the editor and warns the user to press Enter. This two-step flow lets the user manage context window usage before starting a new task while avoiding unnecessary LLM follow-up in the old session.
164
+ The prefill can be a slash command (for example `the implementation step specs:...`) or any non-empty message. If automatic delivery fails, ask_user places the prefill in the editor and warns the user to press Enter. This two-step flow lets the user manage context window usage before starting a new task while avoiding unnecessary LLM follow-up in the old session.
@@ -9,9 +9,9 @@ Command Enchantment has no user commands. It improves the editor autocomplete ex
9
9
  ## What It Does
10
10
 
11
11
  - Groups `/unipi:*` commands by package so workflow, memory, web, footer, and other commands are visually distinct.
12
- - Shows full command values like `unipi:brainstorm` while replacing Pi source tags with concise package tags like `[workflow]`.
12
+ - Shows full command values like `unipi:permission` while replacing Pi source tags with concise package tags like `[workflow]`.
13
13
  - Sorts matches in predictable tiers: exact Unipi matches first, then other Unipi matches, then system commands.
14
- - Preserves dynamic argument completions from command providers, including workflow document and worktree suggestions.
14
+ - Preserves dynamic argument completions from command providers (per-command `getArgumentCompletions`).
15
15
  - Ships an audit test that checks registered Unipi commands are represented in the autocomplete registry and have descriptions.
16
16
 
17
17
  ## Development Checks
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pi-unipi/command-enchantment",
3
- "version": "2.20.5",
4
- "description": "Enhanced TUI autocomplete for /unipi:* commands — colored, sorted, and grouped by package",
3
+ "version": "3.0.0-alpha.0",
4
+ "description": "Enhanced TUI autocomplete for /unipi:* commands \u2014 colored, sorted, and grouped by package",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
7
7
  "license": "MIT",
@@ -29,8 +29,8 @@
29
29
  "!src/**/*.test.ts"
30
30
  ],
31
31
  "peerDependencies": {
32
- "@earendil-works/pi-coding-agent": "^0.84.0",
33
- "@earendil-works/pi-tui": "^0.84.0"
32
+ "@earendil-works/pi-coding-agent": "^0.86.0",
33
+ "@earendil-works/pi-tui": "^0.86.0"
34
34
  },
35
35
  "scripts": {
36
36
  "test": "vitest run"