@pi-unipi/kanboard 3.0.0-alpha.21 → 3.0.0-alpha.23

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 (3) hide show
  1. package/README.md +98 -182
  2. package/package.json +7 -7
  3. package/src/settings.ts +36 -30
package/README.md CHANGED
@@ -1,214 +1,130 @@
1
- # @pi-unipi/kanboard
1
+ # Kanboard
2
2
 
3
- The pi half of **kanboard v3**: a per-project board for deferred work. The
4
- storage, transition rules and web UI live in the Rust binary
5
- ([`crates/kanboard`](../../crates/kanboard) — one writer for every change); this
6
- package is the terminal-side bridge: commands, the `-do` budget, the turn
7
- arbiter's kanboard monitor, hub settings and the `kanboard` skill.
8
- **There is no runner** — the session works board tasks itself; the runner,
9
- queue and strategy labels were removed (see
10
- [`docs/plans/2026-09-30-01a0f095.md`](../../docs/plans/2026-09-30-01a0f095.md)).
3
+ Keep a per-project board of work for later, and let the agent work the tasks when you allow it.
11
4
 
12
- Spec: [`docs/specs/2026-09-24-kanboard-v3-design.md`](../../docs/specs/2026-09-24-kanboard-v3-design.md)
13
- (superseded for the runner/queue/strategy parts).
5
+ `@pi-unipi/kanboard` · part of [UniPi](../../README.md)
14
6
 
15
- ## Commands
7
+ ![Kanboard dashboard: tasks that need you, the next ready task and project health](../../docs/assets/screenshots/kanboard-dashboard.png)
16
8
 
17
- `/unipi:kanboard [open|close|onboard|status|doctor]` — bare lists everything
18
- (display-only, never enters the LLM context):
9
+ ![Kanboard board: lanes from Backlog to Done with task cards](../../docs/assets/screenshots/kanboard-board.png)
19
10
 
20
- | Sub | What it does |
21
- |---|---|
22
- | `open [--host H] [--port N]` | Ensure the daemon (reuse a healthy one, else spawn `serve` detached) and print `http://127.0.0.1:<port>/p/<slug>`. The browser opens only when `openBrowser` is on. |
23
- | `onboard` | `project add` for this workspace and remembers the slug. Idempotent. |
24
- | `close` | Shut down the board daemon — the web UI goes offline until the next `open`. Running tasks are unaffected. |
25
- | `status` | Daemon pid/port, project counts and active claims (session/pid/host/staleness). |
26
- | `doctor` | ✓/✗ setup check (binary, daemon health, project, summary agent, bind, claims) as a display-only message. |
11
+ ## What it does
27
12
 
28
- The other three commands are separate slash commands:
13
+ - Keeps tasks in lanes: Backlog, Todo, In Progress, In Review, Blocked, Done, Cancelled and Archived.
14
+ - Opens a web board for each project. The board updates when the agent or the CLI changes a task.
15
+ - Lets you add a task from the prompt with no agent turn.
16
+ - Lets the agent work tasks only within a budget that you give it, or in autowork.
17
+ - Asks the agent to continue a task that it started and did not finish.
18
+ - Stores tasks as markdown files. The Rust binary `unipi-kanboard` writes all changes. Refer to [the crate README](../../crates/kanboard/README.md).
29
19
 
30
- | Command | What it does |
31
- |---|---|
32
- | `/unipi:kanboard-add [-p 1-5] [--after ID] [--status backlog\|todo] <title>` | Capture a task — no agent turn. Lines below the title are the body; existing file paths pasted there are attached. `-p` maps 1 none · 2 low · 3 medium · 4 high · 5 urgent. |
33
- | `/unipi:kanboard-do <request>` | Reveal the skill and hand the request to the agent with a **budget**: `doTasks` task slots (each `start` uses one) and `doWrites` board writes (add, edit, link, order, move backlog↔todo, note on tasks you don't hold). Always free: reads, and `finish`, `move <ID> blocked --comment` and `note` on tasks this session started. Budgets persist across turns until spent; `-do` tops up without stacking, `off` revokes. Children never write. |
34
- | `/unipi:kanboard-autowork start\|stop` | `start` turns autowork on: the session works every ready task one at a time, in any mode it chooses, with no budget limits. `stop` turns the offers off (never aborts the current turn). |
35
-
36
- The old `add`/`work`/`stop` subcommands and bare-text capture now just point at
37
- these commands.
38
-
39
- ## Continuation: the turn arbiter's monitor
40
-
41
- There is no runner loop. When a run settles, `src/monitor.ts` — a nudge
42
- provider on core's turn arbiter (`agent_before_settle`) — proposes at most one
43
- continuation:
44
-
45
- - **Claims (priority 50):** a task this session started is still In Progress →
46
- `↻ UNI-30 still In Progress — continue, or finish/block it (n/5)`.
47
- - **Autowork-next (priority 40):** autowork on, no open claims, a ready task
48
- exists → `↻ next ready: UNI-33 <title> …`; nothing ready → an
49
- `autowork done` notice, then autowork turns itself off.
50
-
51
- The monitor defers to a **long-horizon owner** (priority 100), to **pending
52
- events** and to **wait sources** (a running bg wake, a busy sidekick, a
53
- background subagent). It **disarms** on an aborted/errored run (Esc never gets
54
- talked over) and when a goal stops paused/budget with claims open (notice
55
- only). Runaway guards: 2 nudged runs with zero tool calls → `⚠ stalled`, a
56
- hard cap of 5 nudges per task, a question heuristic (the agent asked the user
57
- something → notice, no nudge), and in autowork the same stall rule plus a
58
- 3-offers-per-task cap. After an Esc, a later prompt that names a claimed id
59
- re-arms the monitor.
60
-
61
- **Children are read-only.** Sidekicks and subagents may read the board; every
62
- write is refused with "board writes are the lead's job — report this to the
63
- lead". Reminders are silent there too.
64
-
65
- **Session identity & lifecycle.** On every lead `session_start` the session id
66
- becomes `UNIPI_KANBOARD_SESSION = pi-<pi session id>` (stable across `-c`/`-r`)
67
- and `UNIPI_KANBOARD_PID` the process pid. At startup stale claims whose pid died
68
- are reaped (`session lost: …`), and tasks released that way get a one-time
69
- notice ("UNI-30 was released when the last run ended — ask me to re-start it").
70
- On `session_shutdown` this session's open claims are released to Todo with
71
- `released: session ended mid-task (<session>)` (actor system — the agent actor
72
- cannot release).
73
-
74
- ## Settings (hub section "Kanboard")
75
-
76
- | Setting | Default | Notes |
77
- |---|---|---|
78
- | `chainGate` | `in_review` | `done` waits for a finished dependency |
79
- | `idleMin` | `10` | Passed to `serve --idle-min` |
80
- | `port` | `0` | Passed to `serve --port` (0 = OS-assigned) |
81
- | `archiveAfterDays` | `0` | > 0 → `archive-sweep --after-days N` on session start (fire and forget) |
82
- | `openBrowser` | `false` | Open the board in a browser on `open` |
83
- | `requireAuth` | `false` | Also require the access token on 127.0.0.1 (remote always does) |
84
- | `keepToken` | `false` | Reuse `<home>/token` across daemon restarts |
85
- | `maxSessions` | `2` | Distinct sessions holding in-progress tasks per project (`UNIPI_KANBOARD_MAX_SESSIONS`) |
86
- | `turnAddLimit` | `20` | `add` calls allowed per turn (0 = unlimited) — the runaway guard, applies in autowork too |
87
- | `reminders` | `true` | R1: steer on the first file-changing call while a mentioned task is still Todo (text only, never blocks; silent in child sessions) |
88
- | `doTasks` | `5` | Task slots a `/unipi:kanboard-do` grants (each `start` costs one) |
89
- | `doWrites` | `10` | Board writes a `/unipi:kanboard-do` grants; a stored `doCredits` migrates into this |
90
- | *actions* | | `Open board…`, `Stop daemon`, `Summary agent command…`, `Rotate access token` |
91
-
92
- `Summary agent command…` writes through `settings set agent-command` and
93
- `Rotate access token` runs `rotate-token` — both are **user-only** (actor=agent
94
- is refused), as are `settings set` calls generally. `settings show` is read-only.
95
-
96
- ## Binary resolution
97
-
98
- 1. `UNIPI_KANBOARD_BIN` (explicit path)
99
- 2. `@pi-unipi/kanboard-<platform>-<arch>/bin/unipi-kanboard[.exe]` (K4 ships these)
100
- 3. the dev build `<repo>/crates/kanboard/target/{release,debug}/unipi-kanboard`
101
-
102
- Nothing found → every command reports
103
- `kanboard binary unavailable for <platform>-<arch>` and does nothing else.
104
-
105
- **Agent bash env:** pi has no extension-level mechanism to add env vars to the
106
- `bash` tool (only replacing bash via `registerTool` + `BashToolOptions`, which
107
- would change tool schemas mid-session and break the prefix cache — spec principle
108
- 4 forbids that). So the task prompt and the skill pass `--actor agent --project
109
- <slug>` explicitly and call the binary by absolute path.
110
-
111
- ## Skill
112
-
113
- `skills/kanboard/SKILL.md` describes the CLI, the lanes, who may move what, and
114
- the rules agents must follow. It is a normal pi skill (jev skill-judging can
115
- reveal it on intent), and `/unipi:kanboard-do` force-reveals it by emitting
116
- `unipi:skills:reveal`, which utility turns into the usual append-only reveal
117
- message — the system prompt is never touched.
118
-
119
- ## Platforms and packaging
120
-
121
- | Platform | npm package | Rust target | Notes |
122
- |---|---|---|---|
123
- | Linux x64 | `@pi-unipi/kanboard-linux-x64` | `x86_64-unknown-linux-musl` | static-pie, 3.9 MB |
124
- | Linux arm64 | `@pi-unipi/kanboard-linux-arm64` | `aarch64-unknown-linux-musl` | static |
125
- | macOS arm64 | `@pi-unipi/kanboard-darwin-arm64` | `aarch64-apple-darwin` | |
126
- | macOS x64 | `@pi-unipi/kanboard-darwin-x64` | `x86_64-apple-darwin` | cross-built from macos-14 |
127
- | Windows x64 | `@pi-unipi/kanboard-win32-x64` | `x86_64-pc-windows-msvc` | |
128
-
129
- They are **optional dependencies** of this package (`os`/`cpu` gated), so `npm install`
130
- pulls exactly one. `.github/workflows/kanboard-binaries.yml` builds them (tests +
131
- clippy on native targets, release build per target, artifact per platform) and, on
132
- a `v*` tag, attaches the binaries to the GitHub release. Publishing to npm:
20
+ ## Quick start
21
+
22
+ UniPi installs this package:
133
23
 
134
24
  ```bash
135
- npm run publish:kanboard -- --dry-run # what would ship
136
- npm run publish:kanboard # publishes, or skips loudly
25
+ pi install npm:@pi-unipi/unipi
137
26
  ```
138
27
 
139
- The script **skips any platform package whose `bin/` is empty** (and exits 2), so
140
- an empty platform package can never be published. CI publishes only when an
141
- `NPM_TOKEN` secret exists — this repository has none, so the release job attaches
142
- artifacts and says so.
143
-
144
- Local packaging proof (no registry, no network):
28
+ To install this package alone:
145
29
 
146
30
  ```bash
147
- node scripts/test-kanboard-packaging.mjs
148
- # packs packages/kanboard + the linux-x64 platform package, installs both into a
149
- # temp node_modules, resolves the binary through src/bin.ts and runs --version
31
+ pi install npm:@pi-unipi/kanboard
150
32
  ```
151
33
 
152
- ## Remote access
34
+ npm installs the binary for your platform as an optional package: Linux x64 and arm64, macOS x64 and arm64, and Windows x64.
153
35
 
154
- The daemon binds `127.0.0.1` by default — local only, no token. For access from
155
- another machine either **tunnel** it (nothing to configure):
36
+ 1. Run `/unipi:kanboard onboard` to register the project.
37
+ 2. Run `/unipi:kanboard-add Fix the flaky login test` to add a task.
38
+ 3. Run `/unipi:kanboard open` and open the link that it prints.
39
+ 4. Run `/unipi:kanboard-do work the login tasks` to let the agent work them.
156
40
 
157
- ```bash
158
- ssh -N -L 37473:127.0.0.1:37473 <hostname> # then open http://127.0.0.1:37473
159
- ```
41
+ ## Commands
160
42
 
161
- …or bind a reachable interface, which turns on the **token gate**:
43
+ | Command | What it does |
44
+ |---|---|
45
+ | `/unipi:kanboard` | Lists the commands. |
46
+ | `/unipi:kanboard open [--host H] [--port N]` | Starts the board daemon if it does not run, and prints the board link. |
47
+ | `/unipi:kanboard close` | Stops the board daemon. Tasks in progress do not change. |
48
+ | `/unipi:kanboard onboard` | Registers this project. You can run it again with no effect. |
49
+ | `/unipi:kanboard status` | Shows the daemon and the active claims. |
50
+ | `/unipi:kanboard show [--all]` | Shows the board in the chat. |
51
+ | `/unipi:kanboard doctor` | Examines the setup: binary, daemon, project and bind address. |
52
+ | `/unipi:kanboard-add [-p 1-5] [--after ID] [--status backlog\|todo] <title>` | Adds a task. Lines below the title become the description. A file path in the description becomes an attachment. |
53
+ | `/unipi:kanboard-do <request>` | Gives the request to the agent with a task budget. `off` removes the budget. |
54
+ | `/unipi:kanboard-autowork start\|stop` | `start` lets the agent work all ready tasks, one at a time. `stop` stops the offers of new tasks. |
162
55
 
163
- ```bash
164
- /unipi:kanboard open --host 0.0.0.0 --port 37473 # every interface
165
- /unipi:kanboard open --host tailscale # the tailnet IPv4
166
- ```
56
+ Priority `-p`: 1 none, 2 low, 3 medium, 4 high, 5 urgent.
167
57
 
168
- `--host` and `--port` override the `host`/`port` settings for that invocation
169
- only. `tailscale` resolves through `tailscale ip -4` (clear error when tailscale
170
- is not installed). For a wildcard bind the printed URLs cover the machine
171
- hostname, every non-internal IPv4 and the tailnet address, and a warning says
172
- `board is reachable from the network; anyone with the link can edit it`.
58
+ The output of these commands shows in the chat. It does not go into the model context.
173
59
 
174
- **Token model.** Any non-loopback bind generates a 32-byte token (base64url) and
175
- writes it to `daemon.json` alongside `host`. Every request must carry it:
60
+ ## Task budget
176
61
 
177
- - `?t=<token>` — sets an `HttpOnly; SameSite=Strict` cookie and 303-redirects to
178
- the same URL without the parameter (so the token leaves the address bar),
179
- - the `kb_token` cookie, or
180
- - `Authorization: Bearer <token>`.
62
+ `/unipi:kanboard-do` gives the agent two budgets:
181
63
 
182
- Missing or wrong tokens answer `401` with a page saying to open the link printed
183
- by `/unipi:kanboard open`. `/api/health` stays reachable but returns only
184
- `{ok, version}` (no pid) off-loopback, and POSTs are refused when their `Origin`
185
- does not match the request `Host` (drive-by CSRF), in both modes. Loopback binds
186
- keep no token at all.
64
+ - **Task slots** (`doTasks`, default 5). Each `start` uses one slot.
65
+ - **Board writes** (`doWrites`, default 10). `add`, `edit`, `link`, `order`, a move between Backlog and Todo, and a `note` on a task of another session each use one write.
187
66
 
188
- Changing the binding needs a restart: if a daemon already runs with a different
189
- host/port, `serve` reports `bindingChanged` and `/unipi:kanboard open` stops the
190
- old one and starts the new one (`restarted kanboard on 0.0.0.0:37473`). The
191
- daemon runs no jobs, so nothing is lost.
67
+ Some operations are always free: reads, and `finish`, `move <ID> blocked`, `note` and `attach` on tasks that this session started. The budget stays until the agent uses it. A new `-do` fills the budget again. It does not add to the old budget.
192
68
 
193
- ## Storage
69
+ In autowork, the agent has no budget. It can use any mode, for example goal or ralph.
194
70
 
195
- `~/.unipi/kanboard/` (`UNIPI_KANBOARD_HOME` overrides it): `daemon.json` +
196
- `daemon.lock` for the daemon, and `projects/<slug>/{project.json,board.lock,tasks/*.md,queues/<session>.json}`.
197
- The extension never edits those files — the binary owns them.
71
+ Subagents and sidekicks can read the board, but cannot write to it. The guard tells them to report to the lead.
198
72
 
199
- ## Troubleshooting
73
+ ## Settings
200
74
 
201
- | Symptom | Fix |
202
- |---|---|
203
- | `kanboard binary unavailable for <platform>-<arch>` | No `UNIPI_KANBOARD_BIN`, no platform package and no dev build. Build `crates/kanboard` (`cargo build --release`) or set `UNIPI_KANBOARD_BIN`. |
204
- | The board says *"N task file(s) need repair"* | A file was edited by hand. One bad file no longer blocks the board (it is skipped and reported); run `unipi-kanboard validate --fix`, then `validate`. |
205
- | `UNI-5 is unreadable: … (line N)` | That task's own file is broken — repair it before moving/noting it. |
206
- | The daemon looks stale | `unipi-kanboard status` (pid + liveness), then `/unipi:kanboard close`, `unipi-kanboard stop` (SIGTERM, ≤3s) or the hub's **Stop daemon** action. |
207
- | Nothing is ready | `unipi-kanboard list --ready --json` shows `waitingFor`; a cancelled dependency blocks forever — `link`/`unlink` to re-plan. |
208
- | A board call prompts for permission | Fixed in auto mode: `unipi-kanboard … --actor agent` is allow-listed by the permission gate (ask mode still asks). |
75
+ Open `/unipi:settings` → **Kanboard**. The file is `~/.unipi/config/kanboard/config.json`.
209
76
 
210
- ## Tests
77
+ | Key | Default | What it does |
78
+ |---|---|---|
79
+ | `chainGate` | `in_review` | Status that a dependency must reach before the next task is ready: `in_review` or `done`. The web board uses it. |
80
+ | `idleMin` | `10` | Minutes with no board open before the daemon stops. |
81
+ | `host` | `127.0.0.1` | Bind address. Any other address needs an access token. |
82
+ | `port` | `0` | Daemon port. `0` lets the OS select a port. |
83
+ | `archiveAfterDays` | `0` | Archives done and cancelled tasks after this many days. `0` turns it off. |
84
+ | `retentionDays` | `90` | Moves archived and cancelled tasks to cold storage after this many days. |
85
+ | `openBrowser` | `false` | Opens the board in a browser on `open`. |
86
+ | `requireAuth` | `false` | Asks for the token on `127.0.0.1` too. |
87
+ | `keepToken` | `false` | Uses the same token after a daemon restart. |
88
+ | `maxSessions` | `2` | Number of sessions that can hold In Progress tasks in one project. |
89
+ | `turnAddLimit` | `20` | `add` calls in one turn. `0` means no limit. |
90
+ | `reminders` | `true` | Reminds the agent to `start` a Todo task before it edits files. |
91
+ | `doTasks` | `5` | Task slots that one `-do` gives. |
92
+ | `doWrites` | `10` | Board writes that one `-do` gives. |
93
+
94
+ At session start, Kanboard runs `archive-sweep` when `archiveAfterDays` or `retentionDays` is more than 0.
95
+
96
+ ## How it works
97
+
98
+ Kanboard has no task runner. The agent works each task in your session. When a run ends, a monitor on the [turn arbiter](../../docs/architecture/turn-arbiter.md) can add one message to continue:
99
+
100
+ - **Claims** (priority 50). A task that this session started is still In Progress. The monitor asks the agent to continue, finish or block it.
101
+ - **Next task** (priority 40). Autowork is on and a ready task exists. The monitor offers it. When no task is ready, autowork stops.
102
+
103
+ The monitor waits for a [long-horizon](../../docs/architecture/long-horizon.md) owner (priority 100) and for pending events. It stops after you press `Esc` or a run fails. It also stops after 2 runs with no tool calls, after 5 messages for one task, or after 3 offers of one task in autowork.
104
+
105
+ At session start, Kanboard releases claims of dead processes. At session end, it moves the open claims of this session back to Todo. The next start shows a notice about these tasks.
106
+
107
+ ## Remote access
108
+
109
+ The daemon listens on `127.0.0.1` by default and needs no token. To use the board from another machine, use an SSH tunnel:
211
110
 
212
111
  ```bash
213
- npm test -w packages/kanboard # bin resolution, commands, budget guard, monitor, settings
112
+ ssh -N -L 37473:127.0.0.1:37473 <hostname>
214
113
  ```
114
+
115
+ You can also bind another address, for example `/unipi:kanboard open --host 0.0.0.0 --port 37473` or `--host tailscale`. Then the daemon makes an access token, and the printed link contains it. Anyone with the link can edit the board.
116
+
117
+ ## Troubleshooting
118
+
119
+ | Problem | Fix |
120
+ |---|---|
121
+ | `kanboard binary unavailable for <platform>-<arch>` | Set `UNIPI_KANBOARD_BIN` to the binary path, or build `crates/kanboard` with `cargo build --release`. |
122
+ | The board says that some task files have errors | Run `unipi-kanboard validate --fix`, then `unipi-kanboard validate`. |
123
+ | The daemon does not respond | Run `/unipi:kanboard close`, then `/unipi:kanboard open`. |
124
+ | No task is ready | Run `unipi-kanboard list --ready --json` and read `waitingFor`. A cancelled dependency blocks a task. |
125
+
126
+ ## See also
127
+
128
+ - [Kanboard crate: CLI, daemon and JSON API](../../crates/kanboard/README.md)
129
+ - [Turn arbiter](../../docs/architecture/turn-arbiter.md)
130
+ - [Commands reference](../../docs/reference/commands.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/kanboard",
3
- "version": "3.0.0-alpha.21",
3
+ "version": "3.0.0-alpha.23",
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.21"
34
+ "@pi-unipi/core": "3.0.0-alpha.23"
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.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"
51
+ "@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.23",
52
+ "@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.23",
53
+ "@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.23",
54
+ "@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.23",
55
+ "@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.23"
56
56
  }
57
57
  }
package/src/settings.ts CHANGED
@@ -34,9 +34,6 @@ export interface KanboardSettings {
34
34
  doTasks: number;
35
35
  /** Board writes a /unipi:kanboard-do grants. */
36
36
  doWrites: number;
37
- /** Whether a blocked-by-confusion task may ask the user (ask) or must
38
- * assume-and-note (avoid, the default). */
39
- blocking: "avoid" | "ask";
40
37
  /** Progress reminders when the agent works board tasks by hand: `start`
41
38
  * before the first edit, `finish` (or block) before the turn ends. */
42
39
  reminders: boolean;
@@ -56,7 +53,6 @@ export const DEFAULT_SETTINGS: KanboardSettings = {
56
53
  turnAddLimit: 20,
57
54
  doTasks: 5,
58
55
  doWrites: 10,
59
- blocking: "avoid",
60
56
  reminders: true,
61
57
  };
62
58
 
@@ -74,54 +70,65 @@ export function registerKanboardSettings(): void {
74
70
  defaults: { ...DEFAULT_SETTINGS } as unknown as Record<string, unknown>,
75
71
  schema: [
76
72
  {
77
- title: "Kanboard",
78
- description: "The session's work board: daemon, -do budgets and skill",
73
+ title: "Agent",
74
+ description: "Task flow and budgets for sessions working the board",
79
75
  fields: [
80
76
  {
81
77
  key: "chainGate",
82
78
  type: "enum",
83
79
  label: "Chain gate",
80
+ description: "When a dependency counts as satisfied and the next task may start.",
84
81
  options: [
85
- { value: "in_review", label: "in_review (next task starts when this one is reviewed)" },
86
- { value: "done", label: "done (next task waits for a completed dependency)" },
82
+ { value: "in_review", label: "in review", description: "next task may start once this one is in review" },
83
+ { value: "done", label: "done", description: "next task waits for a completed dependency" },
87
84
  ],
88
- description: "When a dependency counts as satisfied for the next task",
89
85
  },
90
- { key: "idleMin", type: "number", label: "Daemon idle minutes", min: 1, description: "Shut the daemon down after this long with no board open" },
86
+ { key: "maxSessions", type: "number", label: "Max sessions", min: 1, description: "Distinct sessions that may hold in_progress tasks, per project." },
87
+ { key: "turnAddLimit", type: "number", label: "Adds per turn", min: 0, zeroLabel: "unlimited", description: "`add` calls one turn may make." },
88
+ { key: "reminders", type: "boolean", label: "Progress reminders", description: "Remind the agent to `start` a mentioned task before editing; text only, off in child sessions." },
89
+ { key: "doTasks", type: "number", label: "-do task slots", min: 0, zeroLabel: "off", description: "Task slots a /unipi:kanboard-do grants; each `start` uses one." },
90
+ { key: "doWrites", type: "number", label: "-do write budget", min: 0, zeroLabel: "off", description: "Board writes a /unipi:kanboard-do grants (add, edit, link, order, move, notes)." },
91
+ ],
92
+ },
93
+ {
94
+ title: "Housekeeping",
95
+ description: "What happens to finished and cancelled tasks",
96
+ fields: [
97
+ { key: "archiveAfterDays", type: "number", label: "Archive after", unit: "days", min: 0, zeroLabel: "off", description: "Auto-archive done/cancelled tasks on session start." },
98
+ { key: "retentionDays", type: "number", label: "Cold storage after", unit: "days", min: 0, zeroLabel: "off", description: "Move archived tasks to cold storage — readable files, gone from the board." },
99
+ ],
100
+ },
101
+ {
102
+ title: "Board server",
103
+ description: "Daemon binding, lifetime and access token",
104
+ advanced: true,
105
+ fields: [
91
106
  {
92
107
  key: "host",
93
108
  type: "string",
94
109
  label: "Bind address",
95
110
  emptyLabel: "127.0.0.1 (local only)",
96
111
  hint: "127.0.0.1 · 0.0.0.0 (LAN, token-gated) · tailscale (tailnet IP)",
97
- description: "Anything but a loopback address requires an access token",
112
+ description: "Address the board server binds; anything but a loopback requires the access token.",
98
113
  },
99
- { key: "port", type: "number", label: "Daemon port", min: 0, max: 65535, zeroLabel: "auto", description: "0 lets the OS pick a free port" },
100
- { key: "archiveAfterDays", type: "number", label: "Archive after (days)", min: 0, zeroLabel: "off", description: "Auto-archive done/cancelled tasks on session start" },
101
- { key: "retentionDays", type: "number", label: "Cold storage after (days)", min: 0, zeroLabel: "off", description: "Move archived/cancelled tasks to cold storage — files stay readable, the board drops them" },
102
- { key: "openBrowser", type: "boolean", label: "Open the browser", description: "Open the board in a browser when /unipi:kanboard opens it" },
114
+ { key: "port", type: "number", label: "Daemon port", min: 0, max: 65535, zeroLabel: "auto", description: "Port the board server listens on; 0 lets the OS pick a free one." },
115
+ { key: "idleMin", type: "number", label: "Daemon idle", unit: "min", min: 1, description: "Shut the daemon down after this long with no board open." },
116
+ { key: "openBrowser", type: "boolean", label: "Open browser", description: "Open the board in a browser when /unipi:kanboard opens it." },
103
117
  {
104
118
  key: "requireAuth",
105
119
  type: "boolean",
106
- label: "Require the access token on localhost too",
107
- description: "Remote binds always need the token; this adds it for 127.0.0.1. Applies on the next daemon start.",
120
+ label: "Token on localhost",
121
+ description: "Require the access token on 127.0.0.1 too; remote binds always need it. Next daemon start.",
108
122
  },
109
123
  {
110
124
  key: "keepToken",
111
125
  type: "boolean",
112
- label: "Keep the access token across restarts",
113
- description: "Reuse one token so board links stay valid; rotate it below.",
114
- },
115
- { key: "maxSessions", type: "number", label: "Sessions working at once (per project)", min: 1, description: "Distinct sessions holding in_progress tasks" },
116
- { key: "turnAddLimit", type: "number", label: "New tasks per turn", min: 0, zeroLabel: "unlimited", description: "`add` calls allowed per turn" },
117
- {
118
- key: "reminders",
119
- type: "boolean",
120
- label: "Progress reminders",
121
- description: "Remind the agent to `start` a mentioned Todo task before editing (text only, never blocks; off in child sessions)",
126
+ label: "Keep token",
127
+ description: "Reuse <home>/token across restarts so board links stay valid; rotate below.",
122
128
  },
123
- { key: "doTasks", type: "number", label: "-do task slots", min: 0, zeroLabel: "off", description: "Task slots a /unipi:kanboard-do grants; each `start` uses one" },
124
- { key: "doWrites", type: "number", label: "-do write budget", min: 0, zeroLabel: "off", description: "Board writes a /unipi:kanboard-do grants (add, edit, link, order, move, note on tasks you don't hold)" },
129
+ { key: "open", type: "action", label: "Open board…", description: "Start the daemon and open the board.", command: ACTION_OPEN },
130
+ { key: "stopDaemon", type: "action", label: "Stop daemon…", description: "Shut the board server down now.", command: ACTION_STOP_DAEMON },
131
+ { key: "rotateToken", type: "action", label: "Rotate access token…", description: "Issue a new token; old board links stop working.", command: ACTION_ROTATE_TOKEN },
125
132
  ],
126
133
  },
127
134
  ],
@@ -153,7 +160,6 @@ export function readKanboardSettings(cwd: string = process.cwd()): KanboardSetti
153
160
  typeof raw.doWrites === "number" && raw.doWrites >= 0 && storedDoWritesSet(cwd)
154
161
  ? raw.doWrites
155
162
  : (storedLegacyDoCredits(cwd) ?? DEFAULT_SETTINGS.doWrites),
156
- blocking: raw.blocking === "ask" ? "ask" : "avoid",
157
163
  reminders: raw.reminders !== false,
158
164
  };
159
165
  }