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 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 → Agent setup**.
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 and the command itself stays where npm put
72
- it, so a project's git history never carries 350 kB of 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, since not
90
- having it is an ordinary state now adds whatever an older release never wrote to the
91
- board, clears out what it no longer writes, and prints which version you moved from and to
92
- with a link to everything that changed in between. Your cards, config, and memory are never
93
- touched.
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 in the conversation
122
- it is already in, rather than paying for a second agent to do the job it is sitting there
123
- to do. Start a run when you want the work to happen on its own. `akb help runs` carries
124
- the whole rule, beside the commands it applies to. An agent working inside a run the board
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 or DeepSeek Harness — and
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 refine # one card, vague to ready
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, started as a
175
- run of its own once the first one ends — so `akb create "…"`, `akb revise`, `akb resolve`,
176
- `akb propose` and `akb plan-release` all come back with their cards refined. Archiving or
177
- rejecting a card does the same for every card it was blocking that now has nothing left in
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
- // Relative to where it was typed when that is shorter and still runs — a checkout says
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 an
561
- agent already in a session does the job itself rather than starting a second one.
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.