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