ai4kanban 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -34
- package/bin/ai4kanban.mjs +59 -7
- package/dist/kanban.mjs +16714 -7574
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -65,17 +65,12 @@ akb skill install # add it, or bring an older copy up to date
|
|
|
65
65
|
That writes one file into `.claude/skills/kanban/` (Claude Code) and
|
|
66
66
|
`.agents/skills/kanban/` (Codex): `SKILL.md`, a short note telling a coding agent the board
|
|
67
67
|
is here and that `akb` owns it. The board app does the same thing from a button:
|
|
68
|
-
**Configuration →
|
|
68
|
+
**Configuration → General**.
|
|
69
69
|
|
|
70
70
|
Nothing else is copied in. The flows ship inside the command (`akb guide`), so a newer
|
|
71
|
-
command is newer flows in every project at once
|
|
72
|
-
it
|
|
73
|
-
|
|
74
|
-
An agent that finds no `akb` on the PATH doesn't stop: the note's first section says what to
|
|
75
|
-
run instead — the copy in this project where there is one, and otherwise `npx --yes
|
|
76
|
-
ai4kanban@<the version that wrote the note>`, pinned so the rules match the board. A run
|
|
77
|
-
started from the app or the CLI is told the same thing in its own words, and `akb skill`
|
|
78
|
-
says it to you at the moment the note lands.
|
|
71
|
+
command is newer flows in every project at once, and a project's git history never carries
|
|
72
|
+
350 kB of it. An agent that finds no `akb` on the PATH doesn't stop: the note names what to
|
|
73
|
+
run instead, pinned to the version that wrote it so the rules match the board.
|
|
79
74
|
|
|
80
75
|
## Update
|
|
81
76
|
|
|
@@ -86,15 +81,11 @@ npm install -g ai4kanban@latest # a newer command
|
|
|
86
81
|
akb update # a repaired board, from the project root
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
`akb update` refreshes a skill folder that is already there — it never adds one
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
It can't do the first line to itself — replacing the file that is running is how you get
|
|
96
|
-
half a command — so it checks npm and names that line when it is behind, rather than
|
|
97
|
-
reporting success a release late.
|
|
84
|
+
`akb update` refreshes a skill folder that is already there — it never adds one — adds
|
|
85
|
+
whatever an older release never wrote to the board, clears out what it no longer writes, and
|
|
86
|
+
prints which version you moved from and to with a link to everything that changed in between.
|
|
87
|
+
Your cards, config, and memory are never touched. It can't do the first line to itself, so it
|
|
88
|
+
checks npm and names that line when it is behind.
|
|
98
89
|
|
|
99
90
|
## Put an agent to work
|
|
100
91
|
|
|
@@ -103,7 +94,8 @@ card can be built from a terminal, over ssh, or from a script, without a chat se
|
|
|
103
94
|
without a browser.
|
|
104
95
|
|
|
105
96
|
```bash
|
|
106
|
-
akb implement 12 # build the card
|
|
97
|
+
akb implement 12 # build the card, then review what was built
|
|
98
|
+
akb review 12 # judge the delivery in flight on it again
|
|
107
99
|
akb refine 12 # sharpen it until it is ready to build
|
|
108
100
|
akb create "add dark mode" # write the card(s) for it
|
|
109
101
|
akb propose # write the next tasks
|
|
@@ -118,11 +110,10 @@ point at, and the command that closes the job.
|
|
|
118
110
|
akb implement 12 --print # the steps, for whoever is asking
|
|
119
111
|
```
|
|
120
112
|
|
|
121
|
-
That is the mode for an agent already in a session: it does the job
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
started always gets the printed flow, so a run can't spawn a copy of itself.
|
|
113
|
+
That is the mode for an agent already in a session: it does the job where it is, rather than
|
|
114
|
+
paying for a second agent to do it. Start a run when you want the work to happen on its own.
|
|
115
|
+
An agent working inside a run always gets the printed flow, so a run can't spawn a copy of
|
|
116
|
+
itself. `akb help runs` carries the whole rule.
|
|
126
117
|
|
|
127
118
|
The run keeps working after the command returns. Watch it, or stop it, from anywhere —
|
|
128
119
|
including from the board app, which drives its buttons through these same commands:
|
|
@@ -134,7 +125,7 @@ akb stop 3f2a1b04 # end one
|
|
|
134
125
|
akb resume 3f2a1b04 # continue one that failed
|
|
135
126
|
```
|
|
136
127
|
|
|
137
|
-
Which agent runs them — Claude Code, Codex, Cursor, OpenCode
|
|
128
|
+
Which agent runs them — Claude Code, Codex, Cursor, OpenCode, DeepSeek Harness or ZCode — and
|
|
138
129
|
what it is set to:
|
|
139
130
|
|
|
140
131
|
```bash
|
|
@@ -153,6 +144,35 @@ An API key is the one thing to leave to the user. Hand them the line rather than
|
|
|
153
144
|
for them: a key an agent types lands in its transcript and in the shell history, and a
|
|
154
145
|
saved key is never read back.
|
|
155
146
|
|
|
147
|
+
## Talk to it about the board
|
|
148
|
+
|
|
149
|
+
Sometimes the answer is a conversation, not a job. `akb chat` opens one about the whole
|
|
150
|
+
board; `akb chat <id>` opens one about that card. It answers, and it does the board work
|
|
151
|
+
you settle on in it.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
akb chat "what should I build next, and why?"
|
|
155
|
+
akb chat 12 "what is still unclear about this card?"
|
|
156
|
+
akb chat 12 "put this in v1 and drop the last todo" # it makes the change
|
|
157
|
+
akb chat "start a build on 12" # it starts the run
|
|
158
|
+
akb chat 12 # the conversation so far
|
|
159
|
+
akb chat 12 --clear # forget it and start fresh
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Chat is the kanban skill in a persistent agent session — the first prompt is only the skill
|
|
163
|
+
invocation and your message, and the skill reads the current board itself. It prints the
|
|
164
|
+
board-specific flow and does the work in the conversation by default; ask for a background run
|
|
165
|
+
when you want another agent to take it independently.
|
|
166
|
+
|
|
167
|
+
Every message is its own command, so a conversation is picked up from any terminal and
|
|
168
|
+
survives closing one. The board's conversation and each card's are separate, both under
|
|
169
|
+
`docs/kanban/.chats/`, on your machine and out of git.
|
|
170
|
+
|
|
171
|
+
A chat is not a run: it never shows in `akb runs` and never holds a card. A change to a card a
|
|
172
|
+
run is already working on is refused, and the refusal names the card and what that run is
|
|
173
|
+
doing. Only an agent whose command can take a second message into its own session can hold a
|
|
174
|
+
conversation; on any other, chat says so and names the agents that can.
|
|
175
|
+
|
|
156
176
|
## The manual
|
|
157
177
|
|
|
158
178
|
`akb help runs` is what a coding agent reads: every command it may call — the card work,
|
|
@@ -164,19 +184,16 @@ The flows are `akb guide`:
|
|
|
164
184
|
```bash
|
|
165
185
|
akb guide # every flow, one line each
|
|
166
186
|
akb guide board # how the board works: card format, layout, memory
|
|
167
|
-
akb guide
|
|
187
|
+
akb guide qa-loop # settle one card's planning gaps
|
|
168
188
|
akb guide plan-release # fill a release from its goal
|
|
169
189
|
```
|
|
170
190
|
|
|
171
|
-
A printed flow already carries the ones its action needs, in full, so this is for the
|
|
172
|
-
rest.
|
|
191
|
+
A printed flow already carries the ones its action needs, in full, so this is for the rest.
|
|
173
192
|
|
|
174
|
-
A run that writes or changes a card is followed by `akb refine` on that card,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
its way. Each one is an ordinary run: it shows in `akb runs`, has its own log, and
|
|
179
|
-
`akb stop` ends it.
|
|
193
|
+
A run that writes or changes a card is followed by `akb refine` on that card, as a run of its
|
|
194
|
+
own — so `akb create`, `akb revise`, `akb resolve`, `akb propose` and `akb plan-release` all
|
|
195
|
+
come back with their cards refined. Archiving or rejecting a card does the same for every card
|
|
196
|
+
it was blocking that now has nothing left in its way.
|
|
180
197
|
|
|
181
198
|
## What it won't do
|
|
182
199
|
|
package/bin/ai4kanban.mjs
CHANGED
|
@@ -68,12 +68,23 @@ const PROGRAM = (() => {
|
|
|
68
68
|
if (/[\\/](_npx|dlx)[\\/]/.test(entry)) return `npx --yes ${NAME}@${VERSION}`
|
|
69
69
|
const base = path.basename(entry).toLowerCase().replace(/\.(cmd|ps1|exe)$/, '')
|
|
70
70
|
if (base === 'akb' || base === NAME) return 'akb'
|
|
71
|
-
|
|
72
|
-
// `node cli/bin/ai4kanban.mjs`, which reads inside a sentence; an absolute path doesn't.
|
|
73
|
-
const near = path.relative(process.cwd(), entry)
|
|
74
|
-
return `node ${near && !near.startsWith('..') ? near : entry}`
|
|
71
|
+
return `node ${nearPath(entry)}`
|
|
75
72
|
})()
|
|
76
73
|
|
|
74
|
+
// How a path is spelled in something a person is meant to paste back.
|
|
75
|
+
//
|
|
76
|
+
// Relative when it is a short hop down from where the command was typed — a checkout says
|
|
77
|
+
// `node cli/bin/ai4kanban.mjs`, which reads inside a sentence and is what the project's own
|
|
78
|
+
// notes spell. Absolute otherwise, and absolute is the safe answer: run from `/`, a
|
|
79
|
+
// relative path is the whole absolute one with its leading slash quietly removed
|
|
80
|
+
// (`node Users/me/…/ai4kanban.mjs`), which runs from that one folder and nowhere else and
|
|
81
|
+
// reads to everyone else like a typo.
|
|
82
|
+
function nearPath(file) {
|
|
83
|
+
const near = path.relative(process.cwd(), file)
|
|
84
|
+
const shortHop = near && !near.startsWith('..') && !path.isAbsolute(near) && near.split(/[\\/]/).length <= 3
|
|
85
|
+
return shortHop ? near : file
|
|
86
|
+
}
|
|
87
|
+
|
|
77
88
|
// One line, when this copy isn't `akb`, for the text that spells it `akb` throughout — the
|
|
78
89
|
// help, and the flows a `--print` hands over. Cheaper than rewriting either, and it holds
|
|
79
90
|
// for the lines inside them that this command never wrote.
|
|
@@ -177,6 +188,13 @@ async function placeSkill(root, mode) {
|
|
|
177
188
|
const result = installSkill(root, mode === 'update' ? 'present' : undefined, PROGRAM)
|
|
178
189
|
for (const w of result.wrote) did.push(`${w.refreshed ? 'refreshed' : 'wrote'} ${w.path}/ — ${w.files} (${w.agent})`)
|
|
179
190
|
for (const s of result.skipped) notes.push(`${s.path} — ${s.why}`)
|
|
191
|
+
// The commit guard (#324), which goes in wherever the skill does. The FIRST write says
|
|
192
|
+
// so, so a user who ran `akb update` for something else learns it is there before a
|
|
193
|
+
// commit refuses; a rewrite of the board's own copy is silent, the way a refresh is.
|
|
194
|
+
if (result.hook?.wrote && !result.hook.wrote.refreshed) {
|
|
195
|
+
did.push(`wrote ${result.hook.wrote.path} — refuses a commit on the branch a delivery is landing on (\`--no-verify\` gets past it)`)
|
|
196
|
+
}
|
|
197
|
+
if (result.hook?.note) notes.push(result.hook.note)
|
|
180
198
|
// A project that has one agent's folder but not the other's. Update never writes a folder
|
|
181
199
|
// that isn't there — a plugin install keeps the skill in a read-only cache, and a board
|
|
182
200
|
// installed today has no folder at all until someone asks for one. Say the line that adds
|
|
@@ -359,6 +377,7 @@ async function cmdSkill(root, mode) {
|
|
|
359
377
|
say(`ai4kanban ${VERSION} — the coding agent skill in ${root}`)
|
|
360
378
|
say('')
|
|
361
379
|
for (const folder of state.folders) say(` ${folder.path}/ — ${sayFolder(folder)} (${folder.agent})`)
|
|
380
|
+
await sayHookState(root)
|
|
362
381
|
say('')
|
|
363
382
|
if (!state.installed) say(`Not installed. \`${PROGRAM} skill install\` writes it, and so does the board UI's button.`)
|
|
364
383
|
else if (state.outdated) say(`Older than this command. \`${PROGRAM} skill install\` brings it up to date.`)
|
|
@@ -400,6 +419,16 @@ async function sayPathState() {
|
|
|
400
419
|
say(` ${GET_LINE}`)
|
|
401
420
|
}
|
|
402
421
|
|
|
422
|
+
// Where the commit guard stands (#324), said next to the folders an agent reads. A project
|
|
423
|
+
// that is not a git repository has no hook to have, and gets no line about one.
|
|
424
|
+
async function sayHookState(root) {
|
|
425
|
+
const { readCommitHook, sayCommitHook } = await rules()
|
|
426
|
+
if (typeof readCommitHook !== 'function' || typeof sayCommitHook !== 'function') return
|
|
427
|
+
const hook = readCommitHook(root)
|
|
428
|
+
if (hook.state === 'no-git') return
|
|
429
|
+
say(` ${hook.path} — ${sayCommitHook(hook.state)}`)
|
|
430
|
+
}
|
|
431
|
+
|
|
403
432
|
function sayFolder(folder) {
|
|
404
433
|
if (folder.state === 'absent') return 'not installed'
|
|
405
434
|
if (folder.state === 'linked') return 'a symlink into a source checkout — never written over'
|
|
@@ -523,7 +552,8 @@ ${INTRO}
|
|
|
523
552
|
akb install [--tracks a,b,c] scaffold docs/kanban/ — the board, and nothing else
|
|
524
553
|
akb skill whether a coding agent can drive this board
|
|
525
554
|
akb skill install add the skill: SKILL.md into .claude/skills/kanban/
|
|
526
|
-
and .agents/skills/kanban
|
|
555
|
+
and .agents/skills/kanban/, plus the commit guard in
|
|
556
|
+
.git/hooks/pre-commit
|
|
527
557
|
akb skill refresh rewrite a skill that is already here, and write none
|
|
528
558
|
that isn't — how the note learns a new spelling of the
|
|
529
559
|
command
|
|
@@ -557,8 +587,8 @@ Put an agent to work on the board:
|
|
|
557
587
|
akb agent which agent runs them, and how it is set up
|
|
558
588
|
|
|
559
589
|
A run keeps working after the command returns. Add \`--print\` to any of the first four and
|
|
560
|
-
nothing starts: it prints what to do instead, filled in for this board — which is how
|
|
561
|
-
agent already
|
|
590
|
+
nothing starts: it prints what to do instead, filled in for this board — which is how the
|
|
591
|
+
agent you are already talking to does the job itself rather than starting a run of its own.
|
|
562
592
|
|
|
563
593
|
\`akb help runs\` is the whole of it — every command a coding agent may call, and when.
|
|
564
594
|
\`akb agent\` is where you pick the agent, its model and its key.
|
|
@@ -615,6 +645,10 @@ async function cmdBoard(args) {
|
|
|
615
645
|
// command line is the command's own.
|
|
616
646
|
const RUN_COMMANDS = new Set([
|
|
617
647
|
'implement',
|
|
648
|
+
// The two runs a delivery makes after its build (#302). The board starts each itself;
|
|
649
|
+
// typed by hand they put a stopped delivery back in motion.
|
|
650
|
+
'review',
|
|
651
|
+
'correct',
|
|
618
652
|
'run',
|
|
619
653
|
'refine',
|
|
620
654
|
'resolve',
|
|
@@ -622,6 +656,9 @@ const RUN_COMMANDS = new Set([
|
|
|
622
656
|
'create',
|
|
623
657
|
'propose',
|
|
624
658
|
'plan-release',
|
|
659
|
+
// Write a closed version's changelog into its summary file (#232) — the run the board
|
|
660
|
+
// UI's close starts, and the one a terminal close names.
|
|
661
|
+
'changelog',
|
|
625
662
|
// Finish setting the board up (#173) — the steps that read the repo and think, as one
|
|
626
663
|
// run. It is a run like the rest: the board UI's button starts exactly this.
|
|
627
664
|
'setup',
|
|
@@ -630,10 +667,25 @@ const RUN_COMMANDS = new Set([
|
|
|
630
667
|
// Put a spec agent on a card — a named agent that fills one part of its spec (#187).
|
|
631
668
|
'spec',
|
|
632
669
|
'runs',
|
|
670
|
+
// Talking to the agent about the board, or about one card (#240). Not a run: it holds a
|
|
671
|
+
// conversation here, in this process, and starts nothing.
|
|
672
|
+
'chat',
|
|
633
673
|
'log',
|
|
634
674
|
'stop',
|
|
635
675
|
'resume',
|
|
676
|
+
// End the DELIVERY in flight on a card and hand the card back (#301). `stop` ends one
|
|
677
|
+
// run of it; this ends the job.
|
|
678
|
+
'cancel',
|
|
679
|
+
// Throw a delivery's worktree and branch away (#303). Cancel leaves them where they are;
|
|
680
|
+
// this is the only thing that removes one.
|
|
681
|
+
'discard',
|
|
682
|
+
// Sign off the tree a delivery would land (#308), on a board that requires it. It ends
|
|
683
|
+
// nothing and starts nothing — it lets a delivery already waiting carry on.
|
|
684
|
+
'approve',
|
|
636
685
|
'agent',
|
|
686
|
+
// Which account this MACHINE is signed in to Cloud as (#326). Like `guide`, it needs no
|
|
687
|
+
// board: the sign-in belongs to the machine, not to any one project.
|
|
688
|
+
'cloud',
|
|
637
689
|
// The board's flows, shipped with this command rather than copied into each project.
|
|
638
690
|
'guide',
|
|
639
691
|
// What a started run's watcher is spawned as. Never typed by a person.
|