kaizen-agent 0.7.4 → 1.1.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 +29 -2
- package/cli/dashboard.ts +152 -7
- package/cli/settings.ts +1 -0
- package/package.json +1 -1
- package/skills/kaizen/SKILL.md +1 -0
- package/skills/kaizen/config.default.yml +6 -0
- package/skills/kaizen/spec-build.md +9 -0
- package/skills/kaizen/spec-plan.md +20 -4
- package/skills/kaizen/spec-review.md +15 -0
- package/skills/kaizen-help/SKILL.md +1 -0
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<p align="center"><i>Your AI agent shows you the plan before it does the work,<br>and a second agent checks what it did.</i></p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
+
<a href="https://github.com/hfadhlullah/kaizen/stargazers"><img alt="stars" src="https://img.shields.io/github/stars/hfadhlullah/kaizen?style=social"></a>
|
|
8
9
|
<a href="https://www.npmjs.com/package/kaizen-agent"><img alt="npm" src="https://img.shields.io/npm/v/kaizen-agent?color=2d50a5&label=npm"></a>
|
|
9
10
|
<a href="https://github.com/hfadhlullah/kaizen/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/npm/l/kaizen-agent?color=2d50a5"></a>
|
|
10
11
|
<img alt="dependencies" src="https://img.shields.io/badge/dependencies-0-2d50a5">
|
|
@@ -13,6 +14,16 @@
|
|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
17
|
+
```bash
|
|
18
|
+
# 1. Install Bun (prerequisite)
|
|
19
|
+
curl -fsSL https://bun.sh/install | bash
|
|
20
|
+
|
|
21
|
+
# 2. Install Kaizen
|
|
22
|
+
bunx kaizen-agent
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
16
27
|
## The problem
|
|
17
28
|
|
|
18
29
|
You ask an AI to do something real — write the launch email, draft the policy,
|
|
@@ -217,12 +228,28 @@ kaizen Done, and reviewed. Two things found:
|
|
|
217
228
|
|
|
218
229
|
## Install
|
|
219
230
|
|
|
231
|
+
### Prerequisites: Bun
|
|
232
|
+
|
|
233
|
+
Kaizen's installer and interactive dashboard require [Bun](https://bun.sh). If you don't have Bun installed yet:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# macOS, Linux, WSL
|
|
237
|
+
curl -fsSL https://bun.sh/install | bash
|
|
238
|
+
|
|
239
|
+
# or via Homebrew
|
|
240
|
+
brew install oven-sh/bun/bun
|
|
241
|
+
|
|
242
|
+
# or via npm
|
|
243
|
+
npm install -g bun
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Install Kaizen
|
|
247
|
+
|
|
220
248
|
```bash
|
|
221
249
|
bunx kaizen-agent
|
|
222
250
|
```
|
|
223
251
|
|
|
224
|
-
It walks you through where to install, then tells you what to type next.
|
|
225
|
-
`npx` too. Restart your editor afterwards.
|
|
252
|
+
It walks you through where to install, prompts for your workflow preset (`medium`, `low`, or `ultra`), then tells you what to type next. Restart your editor afterwards.
|
|
226
253
|
|
|
227
254
|
Run from inside a project it asks whether to install globally or for that project
|
|
228
255
|
alone; anywhere else — your home directory, a plain folder, a script — it installs
|
package/cli/dashboard.ts
CHANGED
|
@@ -41,6 +41,80 @@ const WORDMARK = [
|
|
|
41
41
|
"█ █ █ █ █ █▄▄ █▄▄ █ █",
|
|
42
42
|
];
|
|
43
43
|
|
|
44
|
+
const KNOWN_AGENTS = [
|
|
45
|
+
{ name: "Claude Code", dir: ".claude", cmd: "claude" },
|
|
46
|
+
{ name: "Antigravity", dir: ".agents", cmd: "agy" },
|
|
47
|
+
{ name: "Codex", dir: ".codex", cmd: "codex" },
|
|
48
|
+
{ name: "OpenCode", dir: ".opencode", cmd: "opencode" },
|
|
49
|
+
{ name: "Gemini CLI", dir: ".gemini", cmd: "gemini" },
|
|
50
|
+
{ name: "Cursor", dir: ".cursor", cmd: "cursor" },
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
function detectDefaultAgent(projectDir: string): { name: string; cmd: string } {
|
|
54
|
+
const cfgFile = existsSync(join(projectDir, ".kaizen", "config.yml"))
|
|
55
|
+
? join(projectDir, ".kaizen", "config.yml")
|
|
56
|
+
: join(home, ".kaizen", "config.yml");
|
|
57
|
+
if (existsSync(cfgFile)) {
|
|
58
|
+
const text = readFileSync(cfgFile, "utf8");
|
|
59
|
+
const m = /^\s*agent:\s*\n\s*default:\s*(\S+)/m.exec(text) || /^\s*agent\.default:\s*(\S+)/m.exec(text);
|
|
60
|
+
if (m && m[1] && m[1] !== "auto") {
|
|
61
|
+
const found = KNOWN_AGENTS.find((a) => a.cmd === m[1] || a.name.toLowerCase() === m[1].toLowerCase());
|
|
62
|
+
if (found && Bun.which(found.cmd)) return found;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const a of KNOWN_AGENTS) {
|
|
67
|
+
if (existsSync(join(projectDir, a.dir)) && Bun.which(a.cmd)) return a;
|
|
68
|
+
}
|
|
69
|
+
if (Bun.which("claude")) return { name: "Claude Code", cmd: "claude" };
|
|
70
|
+
for (const a of KNOWN_AGENTS) {
|
|
71
|
+
if (Bun.which(a.cmd)) return a;
|
|
72
|
+
}
|
|
73
|
+
return { name: "Claude Code", cmd: "claude" };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function findTerminal(cwd: string, fullCmd: string[]): { cmd: string[]; detached: boolean } | null {
|
|
77
|
+
const hasDisplay = Boolean(process.env.WAYLAND_DISPLAY || process.env.DISPLAY);
|
|
78
|
+
const inTmux = Boolean(process.env.TMUX);
|
|
79
|
+
|
|
80
|
+
if (process.env.TERMINAL && Bun.which(process.env.TERMINAL)) {
|
|
81
|
+
const term = process.env.TERMINAL;
|
|
82
|
+
if (term.includes("kitty")) return { cmd: [term, "--directory", cwd, ...fullCmd], detached: true };
|
|
83
|
+
if (term.includes("alacritty")) return { cmd: [term, "--working-directory", cwd, "-e", ...fullCmd], detached: true };
|
|
84
|
+
if (term.includes("ghostty")) return { cmd: [term, `--working-directory=${cwd}`, "-e", ...fullCmd], detached: true };
|
|
85
|
+
if (term.includes("foot")) return { cmd: [term, "-D", cwd, ...fullCmd], detached: true };
|
|
86
|
+
return { cmd: [term, "-e", ...fullCmd], detached: true };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (hasDisplay && Bun.which("xdg-terminal-exec")) {
|
|
90
|
+
return { cmd: ["xdg-terminal-exec", `--dir=${cwd}`, "--", ...fullCmd], detached: true };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (hasDisplay) {
|
|
94
|
+
if (Bun.which("kitty")) return { cmd: ["kitty", "--directory", cwd, ...fullCmd], detached: true };
|
|
95
|
+
if (Bun.which("ghostty")) return { cmd: ["ghostty", `--working-directory=${cwd}`, "-e", ...fullCmd], detached: true };
|
|
96
|
+
if (Bun.which("alacritty")) return { cmd: ["alacritty", "--working-directory", cwd, "-e", ...fullCmd], detached: true };
|
|
97
|
+
if (Bun.which("foot")) return { cmd: ["foot", "-D", cwd, ...fullCmd], detached: true };
|
|
98
|
+
if (Bun.which("wezterm")) return { cmd: ["wezterm", "start", "--cwd", cwd, "--", ...fullCmd], detached: true };
|
|
99
|
+
if (Bun.which("gnome-terminal")) return { cmd: ["gnome-terminal", `--working-directory=${cwd}`, "--", ...fullCmd], detached: true };
|
|
100
|
+
if (Bun.which("xfce4-terminal")) return { cmd: ["xfce4-terminal", `--default-working-directory=${cwd}`, "-x", ...fullCmd], detached: true };
|
|
101
|
+
if (Bun.which("konsole")) return { cmd: ["konsole", "--workdir", cwd, "-e", ...fullCmd], detached: true };
|
|
102
|
+
if (Bun.which("xterm")) return { cmd: ["xterm", "-e", `cd "${cwd}" && ${fullCmd.join(" ")}`], detached: true };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (inTmux && Bun.which("tmux")) {
|
|
106
|
+
const cmdStr = fullCmd.map((a) => (a.includes(" ") ? JSON.stringify(a) : a)).join(" ");
|
|
107
|
+
return { cmd: ["tmux", "new-window", "-c", cwd, cmdStr], detached: false };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (process.platform === "darwin") {
|
|
111
|
+
const cmdStr = fullCmd.map((a) => (a.includes(" ") ? `\\"${a}\\"` : a)).join(" ");
|
|
112
|
+
const script = `tell application "Terminal" to do script "cd \\"${cwd}\\" && ${cmdStr}"\ntell application "Terminal" to activate`;
|
|
113
|
+
return { cmd: ["osascript", "-e", script], detached: true };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
44
118
|
|
|
45
119
|
export async function dashboard(
|
|
46
120
|
repo: string,
|
|
@@ -101,16 +175,19 @@ export async function dashboard(
|
|
|
101
175
|
|
|
102
176
|
// An action that has something to say says it here, on its own screen, rather
|
|
103
177
|
// than printing to a terminal the dashboard is about to paint over.
|
|
104
|
-
async function report(lines: string[]) {
|
|
178
|
+
async function report(lines: string[], footer = "any key to go back"): Promise<string> {
|
|
105
179
|
stdout.write("\x1b[?1049h\x1b[?25l\x1b[H\x1b[2J");
|
|
106
180
|
stdout.write("\n");
|
|
107
181
|
for (const line of lines) stdout.write(` ${line}\n`);
|
|
108
|
-
stdout.write(`\n ${c.dim(
|
|
182
|
+
stdout.write(`\n ${c.dim(footer)}\n`);
|
|
109
183
|
stdin.setRawMode(true);
|
|
110
184
|
stdin.resume();
|
|
185
|
+
let key = "";
|
|
111
186
|
await new Promise<void>((resolve) => {
|
|
112
187
|
const once = (chunk: Buffer) => {
|
|
113
|
-
|
|
188
|
+
const s = chunk.toString();
|
|
189
|
+
if (s.includes("\x03")) process.exit(130);
|
|
190
|
+
key = s;
|
|
114
191
|
stdin.off("data", once);
|
|
115
192
|
resolve();
|
|
116
193
|
};
|
|
@@ -119,6 +196,7 @@ export async function dashboard(
|
|
|
119
196
|
stdin.setRawMode(false);
|
|
120
197
|
stdin.pause();
|
|
121
198
|
stdout.write("\x1b[?25h\x1b[?1049l");
|
|
199
|
+
return key;
|
|
122
200
|
}
|
|
123
201
|
|
|
124
202
|
// ---------------------------------------------------------------- views
|
|
@@ -338,17 +416,84 @@ export async function dashboard(
|
|
|
338
416
|
}
|
|
339
417
|
}
|
|
340
418
|
for (;;) {
|
|
341
|
-
const { index } = await pick(
|
|
342
|
-
|
|
419
|
+
const { index, key } = await pick(
|
|
420
|
+
from ? `Backlog — ${label(from)}` : "Backlog — open items",
|
|
421
|
+
rows,
|
|
422
|
+
"enter read · r run in agent · backspace back",
|
|
423
|
+
(n) => full[n] === null,
|
|
424
|
+
"rR",
|
|
425
|
+
);
|
|
343
426
|
if (index === null) return;
|
|
344
427
|
// Rows are cut to the window, so reading one means opening it.
|
|
345
428
|
const it = full[index];
|
|
346
429
|
if (!it) continue;
|
|
347
|
-
|
|
430
|
+
if (key === "r" || key === "R") {
|
|
431
|
+
await startBacklogItem(it, from ?? state!);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const k = await report([
|
|
348
435
|
c.bold(it.where ?? "Backlog item"),
|
|
349
436
|
it.severity ? c.dim(` ${it.severity}`) : "",
|
|
350
437
|
"",
|
|
351
438
|
...wrap(it.raw.replace(/`/g, ""), 2),
|
|
439
|
+
], "r run in agent · any other key to go back");
|
|
440
|
+
if (k === "r" || k === "R") {
|
|
441
|
+
await startBacklogItem(it, from ?? state!);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async function startBacklogItem(it: Item, from: string) {
|
|
447
|
+
const projectDir = from === join(home, ".kaizen")
|
|
448
|
+
? process.cwd()
|
|
449
|
+
: (from.endsWith(".kaizen") ? dirname(from) : from);
|
|
450
|
+
const agent = detectDefaultAgent(projectDir);
|
|
451
|
+
const agentBin = Bun.which(agent.cmd) ?? agent.cmd;
|
|
452
|
+
const prompt = it.where ? `/kaizen ${it.text} (${it.where})` : `/kaizen ${it.text}`;
|
|
453
|
+
const fullCmd = [agentBin, prompt];
|
|
454
|
+
|
|
455
|
+
const term = findTerminal(projectDir, fullCmd);
|
|
456
|
+
if (!term) {
|
|
457
|
+
await report([
|
|
458
|
+
c.bold("Could not open terminal"),
|
|
459
|
+
"",
|
|
460
|
+
c.dim("No supported terminal emulator found (xdg-terminal-exec, kitty, ghostty, alacritty, tmux)."),
|
|
461
|
+
"",
|
|
462
|
+
"Run manually:",
|
|
463
|
+
` ${c.cyan(`cd "${projectDir}" && ${agent.cmd} "${prompt}"`)}`,
|
|
464
|
+
]);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
const proc = Bun.spawn(term.cmd, {
|
|
470
|
+
cwd: projectDir,
|
|
471
|
+
stdin: "ignore",
|
|
472
|
+
stdout: "ignore",
|
|
473
|
+
stderr: "ignore",
|
|
474
|
+
detached: term.detached,
|
|
475
|
+
});
|
|
476
|
+
if (term.detached) proc.unref();
|
|
477
|
+
|
|
478
|
+
await report([
|
|
479
|
+
c.bold("Started in new terminal"),
|
|
480
|
+
"",
|
|
481
|
+
` ${c.cyan("Agent")} ${agent.name} (${c.bold(agent.cmd)})`,
|
|
482
|
+
` ${c.cyan("Project")} ${tilde(projectDir)}`,
|
|
483
|
+
` ${c.cyan("Task")} ${it.text}`,
|
|
484
|
+
...(it.where ? [` ${c.cyan("File")} ${it.where}`] : []),
|
|
485
|
+
...(it.severity ? [` ${c.cyan("Severity")} ${it.severity}`] : []),
|
|
486
|
+
"",
|
|
487
|
+
c.dim(`Opened in new window running: ${agent.cmd} "${prompt}"`),
|
|
488
|
+
]);
|
|
489
|
+
} catch (err: any) {
|
|
490
|
+
await report([
|
|
491
|
+
c.bold("Failed to spawn terminal"),
|
|
492
|
+
"",
|
|
493
|
+
c.dim(err?.message ?? String(err)),
|
|
494
|
+
"",
|
|
495
|
+
"Run manually:",
|
|
496
|
+
` ${c.cyan(`cd "${projectDir}" && ${agent.cmd} "${prompt}"`)}`,
|
|
352
497
|
]);
|
|
353
498
|
}
|
|
354
499
|
}
|
|
@@ -482,7 +627,7 @@ export async function dashboard(
|
|
|
482
627
|
? ` ${c.cyan("›")} ${c.bold(a.label.padEnd(20))}${c.dim(a.hint)}\n`
|
|
483
628
|
: ` ${c.dim(a.label)}\n`);
|
|
484
629
|
}
|
|
485
|
-
stdout.write(`\n ${c.dim("↑↓ move · enter choose · q
|
|
630
|
+
stdout.write(`\n ${c.dim("↑↓ move · enter choose · q quit")} ${c.dim("⭐ github.com/hfadhlullah/kaizen")}\n`);
|
|
486
631
|
};
|
|
487
632
|
|
|
488
633
|
stdout.write("\x1b[?1049h\x1b[?25l");
|
package/cli/settings.ts
CHANGED
|
@@ -109,6 +109,7 @@ const SETTINGS: Setting[] = [
|
|
|
109
109
|
{ key: "state.keep_runs", values: ["5", "10", "20", "50"], help: "Completed runs kept before the oldest is pruned" },
|
|
110
110
|
{ key: "git.auto_commit", values: ["false", "true"], help: "Commit the work when a run finishes" },
|
|
111
111
|
{ key: "git.branch_before_implement", values: ["true", "false"], help: "Branch before building when on the default branch" },
|
|
112
|
+
{ key: "agent.default", values: ["auto", "claude", "codex", "agy", "opencode", "gemini"], help: "Default coding agent to launch from dashboard backlog" },
|
|
112
113
|
];
|
|
113
114
|
|
|
114
115
|
const c = {
|
package/package.json
CHANGED
package/skills/kaizen/SKILL.md
CHANGED
|
@@ -94,6 +94,7 @@ whichever the user picks.
|
|
|
94
94
|
| `review.write_memory` | `true`, `false` | Let the reviewer append lessons to `memory.md` |
|
|
95
95
|
| `git.auto_commit` | `true`, `false` | Commit the work when a run finishes |
|
|
96
96
|
| `git.branch_before_implement` | `true`, `false` | Branch before building when on the default branch |
|
|
97
|
+
| `agent.default` | `auto`, `claude`, `codex`, `agy`, `opencode`, `gemini` | Coding agent to launch from dashboard backlog |
|
|
97
98
|
|
|
98
99
|
Rules for writing the file:
|
|
99
100
|
|
|
@@ -128,3 +128,9 @@ git:
|
|
|
128
128
|
# Create a branch before the implement stage when on the default branch.
|
|
129
129
|
# Ignored when the project is not a git repository.
|
|
130
130
|
branch_before_implement: true
|
|
131
|
+
|
|
132
|
+
agent:
|
|
133
|
+
# Default coding agent to launch from dashboard backlog (auto | claude | codex | agy | opencode | gemini).
|
|
134
|
+
# auto picks Claude Code if installed, otherwise the first agent found on PATH.
|
|
135
|
+
default: auto
|
|
136
|
+
|
|
@@ -47,6 +47,15 @@ change works" into "nothing else broke". A check already failing before the chan
|
|
|
47
47
|
not this run's finding; a check that passed before and fails after is, and it stops
|
|
48
48
|
the stage.
|
|
49
49
|
|
|
50
|
+
**Keep the working transcript small.** Everything the builder reads stays in its
|
|
51
|
+
context and is re-read on every request that follows, so a full test-suite dump at the
|
|
52
|
+
start of the stage is paid for again at every step after it. Pipe long output through
|
|
53
|
+
a filter that keeps the decisive lines — the failure count, the failing test names, the
|
|
54
|
+
first error — and read the full output only when a check actually fails. The same holds
|
|
55
|
+
for reading material: open the manifest's paths at the ranges the plan names, not whole
|
|
56
|
+
files, and never re-read a file this stage already changed. `03-impl.md` records the
|
|
57
|
+
result, not the transcript.
|
|
58
|
+
|
|
50
59
|
**Read the plan's File manifest instead of searching.** The planner already located
|
|
51
60
|
every path this run touches. Search the material only for what the manifest does not
|
|
52
61
|
cover, and note in `03-impl.md` what was missing from it.
|
|
@@ -66,11 +66,27 @@ The planner reads code but writes none. Its plan must contain:
|
|
|
66
66
|
item; "every new query path has a covering test" is. A tier fixes the severity
|
|
67
67
|
before the reviewer has an opinion, which is what stops the same class of problem
|
|
68
68
|
being `high` in one run and `medium` in the next.
|
|
69
|
-
7. **
|
|
69
|
+
7. **Design direction, for any work with a visual surface** — a website, a landing
|
|
70
|
+
page, a UI, a deck, a printed piece. The direction is settled before the builder
|
|
71
|
+
starts, because it is the one decision that cannot be changed afterwards without
|
|
72
|
+
redoing the work: copy survives a re-skin, markup does not.
|
|
73
|
+
|
|
74
|
+
Look for it in the material first — a `design.md`, a design system, a brand or style
|
|
75
|
+
guide, an existing stylesheet with established tokens. Where one exists, the plan
|
|
76
|
+
names it and follows it, and asks nothing; the answer is already in the repository.
|
|
77
|
+
|
|
78
|
+
Where none exists, the direction is an *Open question* with 3-4 concrete options,
|
|
79
|
+
each named for what it signals rather than for its palette, so the user chooses a
|
|
80
|
+
positioning rather than a color. Bringing one direction and building it is the
|
|
81
|
+
failure this item exists to prevent: the planner has an opinion here as everywhere
|
|
82
|
+
else, but a visual direction chosen silently is a decision taken from the user, not
|
|
83
|
+
a proposal made to them.
|
|
84
|
+
|
|
85
|
+
8. **Risks** — what could break, what is irreversible, what needs a migration or a
|
|
70
86
|
backup taken first.
|
|
71
|
-
|
|
87
|
+
9. **Open questions** — assumptions that survived the interview. If this list is
|
|
72
88
|
non-empty, the approval must ask the user about it rather than defaulting.
|
|
73
|
-
|
|
89
|
+
10. **Out of scope suggestions** — worthwhile things noticed but not asked for, each
|
|
74
90
|
its own proposal. Never folded into a step.
|
|
75
91
|
|
|
76
92
|
The plan is a proposal, not a decision. It never edits files, runs migrations, or
|
|
@@ -80,7 +96,7 @@ installs packages.
|
|
|
80
96
|
fix loop reads it again per iteration, so a line written once is read five or six
|
|
81
97
|
times. Sections 3 to 6 — the material to reuse, the file manifest, the steps, the
|
|
82
98
|
verification — earn their length: they are what stop every later stage searching the
|
|
83
|
-
material again, and cutting them costs more than it saves. Sections 0, 1,
|
|
99
|
+
material again, and cutting them costs more than it saves. Sections 0, 1, 8 and 10 are
|
|
84
100
|
read once by a human at the approval and should be as short as they can be and still
|
|
85
101
|
be correct: a paragraph of framing, a paragraph of goal, the risks that are real, the
|
|
86
102
|
questions that are open. An alternative rejected gets a line saying what and why, not
|
|
@@ -48,6 +48,21 @@ operational work: missing prerequisites, absent rollback, steps that cannot be
|
|
|
48
48
|
executed as written. The plan's Verification section says what was promised; the
|
|
49
49
|
reviewer checks that promise was kept.
|
|
50
50
|
|
|
51
|
+
**Keep the working transcript small.** Everything the reviewer reads stays in its
|
|
52
|
+
context and is re-read on every request that follows, so the re-run suite dumped in
|
|
53
|
+
full at check 4 is paid for again at every check after it. Pipe long output through a
|
|
54
|
+
filter that keeps the decisive lines — the failure count, the failing test names, the
|
|
55
|
+
first error — and read the full output only where a check actually fails, which is the
|
|
56
|
+
only place the detail becomes a finding. The same holds for the work under review: open
|
|
57
|
+
the manifest's paths at the ranges the plan names, and read the diff rather than the
|
|
58
|
+
whole file wherever the finding would cite a changed line. `04-review.md` records the
|
|
59
|
+
findings, not the transcript.
|
|
60
|
+
|
|
61
|
+
This does not apply to check 3. Blast radius is the check whose whole point is what
|
|
62
|
+
the diff does not contain, so it reads as widely as it needs to — every caller, every
|
|
63
|
+
reader, whole files where that is what it takes. A cheaper blast-radius pass is not a
|
|
64
|
+
cheaper review, it is the check not happening.
|
|
65
|
+
|
|
51
66
|
Each finding is one line, numbered from 1 within the review:
|
|
52
67
|
`<n>. <where>: <severity>: <problem>. <fix>. [G-nn]` Where is a `path:line` for code,
|
|
53
68
|
and a section, page, or step reference otherwise. Severity is one of `critical`,
|
|
@@ -94,6 +94,7 @@ Each iteration is written to `runs/<id>/05-iterations/`.
|
|
|
94
94
|
| `state.keep_runs` | `20` | Completed runs kept before pruning oldest (rescues open backlog first) |
|
|
95
95
|
| `git.auto_commit` | `false` | Never commit/push/PR unless the user explicitly asks |
|
|
96
96
|
| `git.branch_before_implement` | `true` | Branch before implement stage when on the default branch |
|
|
97
|
+
| `agent.default` | `auto` | Coding agent to launch from dashboard backlog |
|
|
97
98
|
|
|
98
99
|
`.kaizen/config.yml` overrides only the keys it sets; everything else falls back to
|
|
99
100
|
this skill's `config.default.yml`.
|