@pi-unipi/unipi 3.0.0-alpha.11 → 3.0.0-alpha.12
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.
- package/CHANGELOG.md +14 -0
- package/package.json +21 -21
- package/packages/ask-user/package.json +2 -2
- package/packages/autocomplete/package.json +1 -1
- package/packages/background-tasks/package.json +2 -2
- package/packages/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/package.json +1 -1
- package/packages/footer/package.json +3 -3
- package/packages/footer/src/glance-editor.ts +8 -6
- package/packages/fusion/package.json +3 -3
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/README.md +1 -0
- package/packages/kanboard/index.ts +35 -4
- package/packages/kanboard/package.json +7 -7
- package/packages/kanboard/skills/kanboard/SKILL.md +21 -10
- package/packages/kanboard/src/commands.ts +1 -1
- package/packages/kanboard/src/guard.ts +14 -2
- package/packages/kanboard/src/reminders.ts +284 -0
- package/packages/kanboard/src/settings.ts +11 -0
- package/packages/kanboard/src/shapes.ts +2 -0
- package/packages/long-horizon/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/package.json +2 -2
- package/packages/subagents/package.json +2 -2
- package/packages/unipi/bundled.js +265 -20
- package/packages/updater/package.json +2 -2
- package/packages/utility/README.md +1 -1
- package/packages/utility/package.json +2 -2
- package/packages/utility/src/settings.ts +1 -1
- package/packages/watchdog/package.json +3 -3
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.0.0-alpha.12] — 2026-09-29
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- `kanboard`: **agent `start` / `finish`** — an agent working board tasks by hand ("do UNI-5 and UNI-8") now moves them itself: `start <ID>` (todo → in_progress, self-claimed for the session; deps satisfied, not already claimed, per-project session cap) and `finish <ID> --comment "<summary>"` (in_progress → in_review; only a task this session `start`ed — another session's or a runner claim is refused; summary required). Both are free (no write credit) and need no `/unipi:kanboard-do`. A session may have several tasks started. Agent claims carry `run.owner: agent` (runner claims are unchanged on disk) and belong to the pi process (`UNIPI_KANBOARD_PID`), so the stale-claim reaper releases them to Todo when the session dies. `move` as an agent points at `start`/`finish` for those two transitions.
|
|
13
|
+
- `kanboard`: **progress reminders** (setting `kanboard.reminders`, default on; no LLM, never blocking) — R1: on the first file-changing tool call of a turn, while a task named in the prompt (or `show`n) is still Todo and nothing is started, a steer is appended to that tool result; R2: at the end of a turn with a started task still In Progress, a follow-up asks to `finish` it or say what remains / block it (at most 2 per task each). Silent in runner-owned runs.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- `kanboard`: transition table — `todo → in_progress` and `in_progress → in_review` allow the agent actor (via `start`/`finish`) besides the runner; in_review → done/todo stays user-only. The kanboard skill and the `/unipi:kanboard-do` prompt now say "`start` a task before working on it, `finish` it with a summary when done".
|
|
17
|
+
- `kanboard` web UI: claimed cards distinguish an agent claim (`start`ed by a session) from a runner claim.
|
|
18
|
+
- `footer`: the glance input frame is open-sided — `GlanceEditor` body rows drop the `│` rails; only the rounded corners on the top/bottom borders frame the prompt (content keeps its column via a one-space indent, rows are truncated to the inner width).
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- `utility`: the Response formatting → Style description no longer claims the change applies "in a new session" — tool renderers are registered once at extension load, so only a restart or `/reload` applies it. The setting now reads "applies after /reload" (utility README updated to match).
|
|
22
|
+
|
|
9
23
|
## [3.0.0-alpha.11] — 2026-09-29
|
|
10
24
|
|
|
11
25
|
### Removed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/unipi",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "All-in-one extension suite for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,26 +82,26 @@
|
|
|
82
82
|
"typebox": "^1.1.38"
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"@pi-unipi/ask-user": "3.0.0-alpha.
|
|
86
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
87
|
-
"@pi-unipi/btw": "3.0.0-alpha.
|
|
88
|
-
"@pi-unipi/command-enchantment": "3.0.0-alpha.
|
|
89
|
-
"@pi-unipi/compactor": "3.0.0-alpha.
|
|
90
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
91
|
-
"@pi-unipi/footer": "3.0.0-alpha.
|
|
92
|
-
"@pi-unipi/fusion": "3.0.0-alpha.
|
|
93
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
94
|
-
"@pi-unipi/input-shortcuts": "3.0.0-alpha.
|
|
95
|
-
"@pi-unipi/kanboard": "3.0.0-alpha.
|
|
96
|
-
"@pi-unipi/mcp": "3.0.0-alpha.
|
|
97
|
-
"@pi-unipi/memory": "3.0.0-alpha.
|
|
98
|
-
"@pi-unipi/notify": "3.0.0-alpha.
|
|
99
|
-
"@pi-unipi/skill-registry": "3.0.0-alpha.
|
|
100
|
-
"@pi-unipi/subagents": "3.0.0-alpha.
|
|
101
|
-
"@pi-unipi/updater": "3.0.0-alpha.
|
|
102
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
103
|
-
"@pi-unipi/web-api": "3.0.0-alpha.
|
|
104
|
-
"@pi-unipi/workflow": "3.0.0-alpha.
|
|
85
|
+
"@pi-unipi/ask-user": "3.0.0-alpha.12",
|
|
86
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.12",
|
|
87
|
+
"@pi-unipi/btw": "3.0.0-alpha.12",
|
|
88
|
+
"@pi-unipi/command-enchantment": "3.0.0-alpha.12",
|
|
89
|
+
"@pi-unipi/compactor": "3.0.0-alpha.12",
|
|
90
|
+
"@pi-unipi/core": "3.0.0-alpha.12",
|
|
91
|
+
"@pi-unipi/footer": "3.0.0-alpha.12",
|
|
92
|
+
"@pi-unipi/fusion": "3.0.0-alpha.12",
|
|
93
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.12",
|
|
94
|
+
"@pi-unipi/input-shortcuts": "3.0.0-alpha.12",
|
|
95
|
+
"@pi-unipi/kanboard": "3.0.0-alpha.12",
|
|
96
|
+
"@pi-unipi/mcp": "3.0.0-alpha.12",
|
|
97
|
+
"@pi-unipi/memory": "3.0.0-alpha.12",
|
|
98
|
+
"@pi-unipi/notify": "3.0.0-alpha.12",
|
|
99
|
+
"@pi-unipi/skill-registry": "3.0.0-alpha.12",
|
|
100
|
+
"@pi-unipi/subagents": "3.0.0-alpha.12",
|
|
101
|
+
"@pi-unipi/updater": "3.0.0-alpha.12",
|
|
102
|
+
"@pi-unipi/utility": "3.0.0-alpha.12",
|
|
103
|
+
"@pi-unipi/web-api": "3.0.0-alpha.12",
|
|
104
|
+
"@pi-unipi/workflow": "3.0.0-alpha.12"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
107
|
"@earendil-works/pi-agent-core": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ask-user",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Structured user input tool for Pi coding agent — single-select, multi-select, freeform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
43
|
+
"@pi-unipi/core": "3.0.0-alpha.12"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/background-tasks",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Background tasks for UniPi — durable shell jobs and delegated background agents with a footer dock",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@earendil-works/pi-ai": "^0.87.1",
|
|
13
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
13
|
+
"@pi-unipi/core": "3.0.0-alpha.12",
|
|
14
14
|
"turndown": "^7.2.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/btw",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "A pi extension for parallel side conversations with /unipi:btw — part of the Unipi suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "extensions/btw.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@earendil-works/pi-tui": "^0.87.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
40
|
+
"@pi-unipi/core": "3.0.0-alpha.12"
|
|
41
41
|
},
|
|
42
42
|
"pi": {
|
|
43
43
|
"extensions": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/compactor",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Compaction for Pi — lossless zero-LLM or model summaries, rebuilt from full history, with session recall",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.12",
|
|
37
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.12",
|
|
38
38
|
"@earendil-works/pi-agent-core": "^0.87.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/footer",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Persistent status bar for Unipi — subscribes to UNIPI_EVENTS and renders key stats from all unipi packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.12",
|
|
36
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.12"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
* subclass CustomEditor, use super.render() ONLY to obtain editor content
|
|
6
6
|
* lines, then compose our own rounded frame. Layout per the v3 design:
|
|
7
7
|
*
|
|
8
|
-
* ╭─UNIPI │ feat/footer-default-v2
|
|
9
|
-
*
|
|
8
|
+
* ╭─UNIPI │ feat/footer-default-v2 ─────────────────────╮
|
|
9
|
+
* Type your prompt here...
|
|
10
10
|
* ╰─ unipi ────────── 42%/1.0M │ Claude Opus 4.5 │ thinking:high ╯
|
|
11
11
|
*
|
|
12
12
|
* Top border carries the UNIPI brand + git branch. Bottom border right side
|
|
13
13
|
* carries workspace · context%/window · model · thinking level; left filler.
|
|
14
|
+
* The body is open-sided: no vertical rails — the rounded corners are the
|
|
15
|
+
* only frame marks (content keeps its column via a one-space indent).
|
|
14
16
|
* All keybindings/autocomplete/history/paste behavior inherited.
|
|
15
17
|
*/
|
|
16
18
|
|
|
@@ -296,10 +298,10 @@ export class GlanceEditor extends CustomEditor {
|
|
|
296
298
|
topCluster +
|
|
297
299
|
border(BORDER.topRight);
|
|
298
300
|
|
|
299
|
-
// ── Body rows:
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
);
|
|
301
|
+
// ── Body rows: open sides — the corner curves are the only frame marks.
|
|
302
|
+
// One-space indent keeps content in the column it had between the old
|
|
303
|
+
// rails; no trailing padding (rows may end short of the frame width).
|
|
304
|
+
const bodyRows = contentLines.map(row => " " + truncateToWidth(row, inner, ""));
|
|
303
305
|
|
|
304
306
|
// ── Bottom frame: ╰─ unipi ─────── [RIGHT CLUSTER] ─╯ ──
|
|
305
307
|
// Right cluster: workspace · pct%/window │ model │ thinking:level
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/fusion",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Devin-style model picker, fusion presets (lead + sidekick), and Local Fusion runtime for UniPi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/subagents": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.12",
|
|
36
|
+
"@pi-unipi/subagents": "3.0.0-alpha.12"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-ai": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.12"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/input-shortcuts",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Keyboard shortcuts for stash/restore, undo/redo, clipboard, and thinking toggle — chord-based overlay system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.12"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -91,6 +91,7 @@ resume it or releases it to Todo.
|
|
|
91
91
|
| `queueMax` | `10` | Tasks a session may queue (0 = unlimited); passed to the CLI as `UNIPI_KANBOARD_QUEUE_MAX` |
|
|
92
92
|
| `maxSessions` | `2` | Distinct sessions running tasks per project (`UNIPI_KANBOARD_MAX_SESSIONS`) |
|
|
93
93
|
| `turnAddLimit` | `20` | `add` calls allowed per -do turn or runner task (0 = unlimited) |
|
|
94
|
+
| `reminders` | `true` | Progress reminders for hand-worked tasks: a steer on the first file-changing call while a mentioned task is still Todo (R1), and a follow-up at turn end while a started task is still In Progress (R2, max 2 per task). Text only, silent in runner runs |
|
|
94
95
|
| *actions* | | `Open board…`, `Stop daemon`, `Summary agent command…`, `Rotate access token` |
|
|
95
96
|
|
|
96
97
|
`Summary agent command…` writes through `settings set agent-command` and
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* status/doctor — bare lists the commands), `/unipi:kanboard-add`,
|
|
6
6
|
* `/unipi:kanboard-do` (opens the board-write window for one turn),
|
|
7
7
|
* `/unipi:kanboard-autowork` (the runner loop: queue first, then claim-next).
|
|
8
|
-
* The runner owns claim → In Progress and run-end → In Review
|
|
8
|
+
* The runner owns claim → In Progress and run-end → In Review for queued work;
|
|
9
|
+
* an agent working a task by hand uses `start`/`finish` (free), nudged by the
|
|
10
|
+
* progress reminders (src/reminders.ts). The board itself
|
|
9
11
|
* is written by the Rust binary (`crates/kanboard`); this extension never edits
|
|
10
12
|
* task files. Bash calls into the binary are gated by the write window
|
|
11
13
|
* (src/guard.ts): reads always pass, writes need a -do turn or a running task.
|
|
@@ -38,6 +40,8 @@ import {
|
|
|
38
40
|
type CommandDeps,
|
|
39
41
|
} from "./src/commands.js";
|
|
40
42
|
import { createDebugLog, createRunner, registerPlanEventListener, type Runner } from "./src/runner.js";
|
|
43
|
+
import { createProgressTracker, registerProgressReminders, sendReminder } from "./src/reminders.js";
|
|
44
|
+
import { asTaskList } from "./src/shapes.js";
|
|
41
45
|
import {
|
|
42
46
|
ACTION_OPEN,
|
|
43
47
|
ACTION_STOP_DAEMON,
|
|
@@ -56,6 +60,9 @@ export const KANBOARD_SKILL = "kanboard";
|
|
|
56
60
|
export default function (pi: ExtensionAPI) {
|
|
57
61
|
// One session id shared by the runner and the agent's bash calls.
|
|
58
62
|
process.env.UNIPI_KANBOARD_SESSION ??= `pi-${process.pid}`;
|
|
63
|
+
// `start` claims belong to this pi process: the stale-claim reaper releases
|
|
64
|
+
// them to Todo when it dies (the agent's bash inherits the env).
|
|
65
|
+
process.env.UNIPI_KANBOARD_PID ??= String(process.pid);
|
|
59
66
|
// Limits travel through the environment; refresh on load and before every
|
|
60
67
|
// tool_call (see the guard registration in commands.ts).
|
|
61
68
|
applyLimitEnv(readKanboardSettings());
|
|
@@ -140,6 +147,26 @@ export default function (pi: ExtensionAPI) {
|
|
|
140
147
|
registerProgressRenderer(pi);
|
|
141
148
|
registerKanboardCommands(pi, buildDeps());
|
|
142
149
|
|
|
150
|
+
// R1/R2 progress reminders for hand-worked tasks (silent in runner runs).
|
|
151
|
+
const reminders = registerProgressReminders(
|
|
152
|
+
pi,
|
|
153
|
+
createProgressTracker({
|
|
154
|
+
enabled: () => readKanboardSettings().reminders,
|
|
155
|
+
runnerOwned: () => (runner?.status().phase ?? "idle") !== "idle",
|
|
156
|
+
session: sessionId,
|
|
157
|
+
list: async () => {
|
|
158
|
+
const slug = projectSlug();
|
|
159
|
+
if (!cli || !slug) return [];
|
|
160
|
+
return asTaskList(await cli.run<unknown>(["list"], { extraEnv: { UNIPI_KANBOARD_PROJECT: slug } })).tasks;
|
|
161
|
+
},
|
|
162
|
+
cliPrefix: () => {
|
|
163
|
+
const slug = projectSlug();
|
|
164
|
+
return cli && slug ? `${cli.binary.path} --actor agent --project ${slug}` : null;
|
|
165
|
+
},
|
|
166
|
+
debug,
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
|
|
143
170
|
registerCommandRunner(ACTION_OPEN, async (ctx) => {
|
|
144
171
|
const context = ctx as ExtensionContext | undefined;
|
|
145
172
|
if (!context?.ui) return;
|
|
@@ -211,9 +238,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
211
238
|
});
|
|
212
239
|
|
|
213
240
|
pi.on("agent_settled", async (_event, ctx) => {
|
|
214
|
-
|
|
215
|
-
drainPending
|
|
216
|
-
|
|
241
|
+
const reminder = reminders.takePending();
|
|
242
|
+
if (drainPending) {
|
|
243
|
+
drainPending = false;
|
|
244
|
+
await drainQueueAfterDo(buildDeps(), ctx as unknown as ExtensionContext);
|
|
245
|
+
}
|
|
246
|
+
// A drained queue hands the session to the runner: the reminder is moot.
|
|
247
|
+
if (reminder && (runner?.status().phase ?? "idle") === "idle") sendReminder(pi, reminder);
|
|
217
248
|
});
|
|
218
249
|
|
|
219
250
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/kanboard",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Kanboard v3 — deferred-work board: CLI/daemon bridge, task runner and skill",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
34
|
+
"@pi-unipi/core": "3.0.0-alpha.12"
|
|
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.
|
|
52
|
-
"@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.
|
|
53
|
-
"@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.
|
|
54
|
-
"@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.
|
|
55
|
-
"@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.
|
|
51
|
+
"@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.12",
|
|
52
|
+
"@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.12",
|
|
53
|
+
"@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.12",
|
|
54
|
+
"@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.12",
|
|
55
|
+
"@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.12"
|
|
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
|
|
@@ -28,6 +28,8 @@ be on `PATH`):
|
|
|
28
28
|
<binary> --actor agent --project <slug> edit <ID> --title|--body|--labels … # only tasks you created, while in backlog/todo
|
|
29
29
|
<binary> --actor agent --project <slug> edit <ID> --strategy none|goal|ralph|swarm|graph|auto # how the runner works it (auto/unset = jev decides)
|
|
30
30
|
<binary> --actor agent --project <slug> edit <ID> --plan yes|no|auto # plan+approve first (auto/unset = jev decides)
|
|
31
|
+
<binary> --actor agent --project <slug> start <ID> # todo → in progress, claimed for your session (free)
|
|
32
|
+
<binary> --actor agent --project <slug> finish <ID> --comment "<summary>" # in progress → in review, only a task you started (free)
|
|
31
33
|
<binary> --actor agent --project <slug> move <ID> blocked --comment "<what you need>"
|
|
32
34
|
<binary> --actor agent --project <slug> link <ID> --after <DEP>
|
|
33
35
|
<binary> --actor agent --project <slug> unlink <ID> --after <DEP>
|
|
@@ -50,9 +52,9 @@ and `rotate-token` are user-only — the agent is refused.
|
|
|
50
52
|
| Move | Who |
|
|
51
53
|
|---|---|
|
|
52
54
|
| backlog ↔ todo | user, agent |
|
|
53
|
-
| todo → in progress |
|
|
55
|
+
| todo → in progress | the runner (`claim-next`), or the agent with `start <ID>` (claims it for its session) |
|
|
54
56
|
| edit a task | agent — only tasks it created, and only in backlog/todo |
|
|
55
|
-
| in progress → in review |
|
|
57
|
+
| in progress → in review | the runner (when a runner task's turn ends), or the agent with `finish <ID> --comment` — only a task its own session `start`ed |
|
|
56
58
|
| in progress → blocked | agent, system — **comment required** (what you need) |
|
|
57
59
|
| blocked → todo | user only — comment required (the answer) |
|
|
58
60
|
| in review → done | user only |
|
|
@@ -70,8 +72,15 @@ lists them — read the files there directly if you need one.
|
|
|
70
72
|
|
|
71
73
|
1. **Never pass `--actor user`.** That is an honour system: pretending to be the
|
|
72
74
|
user to cancel a task or mark it done breaks the board's whole contract.
|
|
73
|
-
2. **
|
|
74
|
-
|
|
75
|
+
2. **Working a task by hand** (the user says "do UNI-5"): **`start` a task
|
|
76
|
+
before working on it, `finish` it with a summary when done** —
|
|
77
|
+
`start <ID>` before your first edit, `finish <ID> --comment "<what you did>"`
|
|
78
|
+
before your turn ends (or `move <ID> blocked --comment "<what you need>"` if
|
|
79
|
+
you cannot). Both are free and need no `/unipi:kanboard-do`. In Review means
|
|
80
|
+
"the agent did the work, a human reviews" — never leave a task you worked in
|
|
81
|
+
Todo or In Progress. You may have several tasks started. **Never move a task
|
|
82
|
+
to `done`**, and never `finish` a task the runner gave you: the runner writes
|
|
83
|
+
in_review for its own tasks when your turn ends (`finish` refuses them).
|
|
75
84
|
3. **Never cancel.** If a task should be dropped, block it with
|
|
76
85
|
`move <ID> blocked --comment "suggest cancel: <why>"` and let the user decide.
|
|
77
86
|
4. **Follow the blocking rule in your task prompt**: by default work
|
|
@@ -85,9 +94,10 @@ lists them — read the files there directly if you need one.
|
|
|
85
94
|
why. You may
|
|
86
95
|
block only the task your own session is running (`move <ID> blocked` checks
|
|
87
96
|
`--session`/`UNIPI_KANBOARD_SESSION` against the claim).
|
|
88
|
-
6. **To have tasks worked
|
|
89
|
-
`queue <IDs>` (Todo tasks, up to the queue limit — setting
|
|
90
|
-
|
|
97
|
+
6. **To have tasks worked by the runner after a `/unipi:kanboard-do` turn, queue
|
|
98
|
+
them** with `queue <IDs>` (Todo tasks, up to the queue limit — setting
|
|
99
|
+
`queueMax`, default 10) — the runner starts them one by one after the turn
|
|
100
|
+
ends. Never `claim-next` yourself, and don't `start` a task you queued.
|
|
91
101
|
7. Use `note <ID> "<text>"` for progress worth remembering (decisions, what you
|
|
92
102
|
verified, what you left undone) — it is the activity log the next reader sees.
|
|
93
103
|
8. Dependencies form a DAG: a task is ready only when every dep reached the chain
|
|
@@ -98,8 +108,9 @@ lists them — read the files there directly if you need one.
|
|
|
98
108
|
## Terminal-only execution
|
|
99
109
|
|
|
100
110
|
The web UI can create, edit, reorder, link and move tasks, but it **never runs a
|
|
101
|
-
task** — there is no run button. Work starts only from a terminal
|
|
102
|
-
`/unipi:kanboard-autowork start
|
|
111
|
+
task** — there is no run button. Work starts only from a terminal: the runner
|
|
112
|
+
(`/unipi:kanboard-autowork start`, or the queue after a `/unipi:kanboard-do`), or
|
|
113
|
+
an agent that `start`s a task the user asked it to do. (The Done column's "Summarize & archive" does call the
|
|
103
114
|
agent command set in the board's Settings, but only to write a summary.)
|
|
104
115
|
|
|
105
116
|
## Attachments
|
|
@@ -42,7 +42,7 @@ Priority -p: 1 none · 2 low · 3 medium · 4 high · 5 urgent`;
|
|
|
42
42
|
|
|
43
43
|
export function doText(slug: string, cli: string, request: string, queueMax = 10, credits = 0): string {
|
|
44
44
|
const limit = queueMax === 0 ? "Todo tasks" : `Todo tasks, at most ${queueMax}`;
|
|
45
|
-
return `[kanboard] For this request you may use the kanboard skill on project ${slug} (CLI: \`${cli} --actor agent --project ${slug} …\`). You have ${credits} write credit${credits === 1 ? "" : "s"} remaining this session — each board write (add, move, edit, note, link, order, queue) costs 1, reads are free; /unipi:kanboard-do tops the credits back up. You can add tasks, move them between backlog and todo, link, order, note, and edit tasks you created. To have tasks worked, queue them in order with \`queue <IDs>\` (${limit}); the runner starts them one by one after this turn
|
|
45
|
+
return `[kanboard] For this request you may use the kanboard skill on project ${slug} (CLI: \`${cli} --actor agent --project ${slug} …\`). You have ${credits} write credit${credits === 1 ? "" : "s"} remaining this session — each board write (add, move, edit, note, link, order, queue) costs 1, reads are free; /unipi:kanboard-do tops the credits back up. You can add tasks, move them between backlog and todo, link, order, note, and edit tasks you created. To have tasks worked by the runner, queue them in order with \`queue <IDs>\` (${limit}); the runner starts them one by one after this turn. If you work a task yourself in this turn instead, \`start <ID>\` it before working on it and \`finish <ID> --comment "<summary>"\` it when done (both free) — never leave a task you worked in Todo or In Progress. Read a task with \`show <ID>\` before editing, linking or queueing it — \`list\` only shows titles and a one-line excerpt. To choose how a task is worked, label it with \`edit <ID> --strategy none|goal|ralph|swarm|graph\` and \`--plan yes|no\`; leave it unset to let the runner decide. If the request is unclear, ask me instead of guessing.
|
|
46
46
|
|
|
47
47
|
Request: ${request}`;
|
|
48
48
|
}
|
|
@@ -19,6 +19,13 @@ export const ADD_CAP_REASON = addCapReason(ADD_CAP);
|
|
|
19
19
|
/** Subcommands that never write to the board. */
|
|
20
20
|
const READONLY = new Set(["list", "show", "attachments", "next", "chain", "search", "status"]);
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Writes that cost nothing and need no -do window: `start`/`finish` only touch
|
|
24
|
+
* tasks the session claims itself (the binary enforces ownership), and the
|
|
25
|
+
* board should always show what is being worked.
|
|
26
|
+
*/
|
|
27
|
+
const FREE_WRITES = new Set(["start", "finish"]);
|
|
28
|
+
|
|
22
29
|
/** Global flags that take a value; `--json` is the only valueless one. */
|
|
23
30
|
const GLOBAL_VALUE_FLAGS = new Set(["--actor", "--project", "--gate", "--session"]);
|
|
24
31
|
|
|
@@ -60,6 +67,11 @@ export function kanboardInvocations(command: string): KanboardInvocation[] {
|
|
|
60
67
|
return out;
|
|
61
68
|
}
|
|
62
69
|
|
|
70
|
+
/** A write that is free and allowed without a -do window (`start`, `finish`). */
|
|
71
|
+
export function isFreeWrite(invocation: KanboardInvocation): boolean {
|
|
72
|
+
return FREE_WRITES.has(invocation.sub);
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
/** Read-only means: no writes, and the board does not change. */
|
|
64
76
|
export function isReadonly(invocation: KanboardInvocation): boolean {
|
|
65
77
|
if (READONLY.has(invocation.sub)) return true;
|
|
@@ -96,7 +108,7 @@ export interface WriteGuard {
|
|
|
96
108
|
|
|
97
109
|
/**
|
|
98
110
|
* Writes cost session credits (one per write subcommand in the command line);
|
|
99
|
-
* reads are free and never blocked. A runner task keeps unlimited access
|
|
111
|
+
* reads and `start`/`finish` are free and never blocked. A runner task keeps unlimited access
|
|
100
112
|
* (still add-capped). Credits persist across turns and follow-up questions
|
|
101
113
|
* until spent; /unipi:kanboard-do tops up to N without stacking past N.
|
|
102
114
|
*/
|
|
@@ -149,7 +161,7 @@ export function createWriteGuard(
|
|
|
149
161
|
lastTask = task;
|
|
150
162
|
}
|
|
151
163
|
for (const invocation of invocations) {
|
|
152
|
-
if (isReadonly(invocation)) continue;
|
|
164
|
+
if (isReadonly(invocation) || isFreeWrite(invocation)) continue;
|
|
153
165
|
if (task !== null) {
|
|
154
166
|
const cap = countAdd(invocation);
|
|
155
167
|
if (cap) return cap;
|