kaizen-agent 1.33.0 → 1.33.1
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 +33 -3
- package/cli/sources.test.ts +3 -0
- package/cli/sources.ts +13 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,11 +2,41 @@
|
|
|
2
2
|
<img src="https://raw.githubusercontent.com/hfadhlullah/kaizen/main/assets/banner.png" alt="kaizen" width="760">
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
|
-
<p align="center"><b>
|
|
5
|
+
<p align="center"><b>One tool to build and maintain your product with AI agents.</b><br>Requests in, a plan you approve, the work, an independent review, done.</p>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<p align="center"><img src="assets/hero.gif" alt="Animated walkthrough of the real kaizen board with sample data. 1: a request gathered from a support sheet waits in the Icebox and is promoted. 2: it is an idea on the board, and Run opens Claude Code. 3: the agent works in the card's own terminal and writes a plan. 4: the plan panel shows what done and wrong mean, and it is approved. 5: it builds, then a reviewer that never saw the work reports a high finding, a double charge. 6: only that finding is ticked and fixed. 7: the reviewer re-checks it. 8: the run lands in Done, with the low finding left in the backlog." width="760"></p>
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## The problem
|
|
10
|
+
|
|
11
|
+
You ask an AI coding agent to retry a payment webhook when the bank times out. It starts editing at once, then says *"Done, tests pass."* The tests do pass. They were written by the same agent, from the same assumption: that a timeout means the charge failed. Sometimes the bank said yes and the reply got lost. Now a retry charges the customer twice, and nothing in the agent's report would make you look.
|
|
12
|
+
|
|
13
|
+
None of this is a lack of intelligence. It is a missing workflow:
|
|
14
|
+
|
|
15
|
+
| What goes wrong | What kaizen does |
|
|
16
|
+
| :--- | :--- |
|
|
17
|
+
| The agent decides what "done" means on its own, and you find out from the diff | It writes a plan first, including what *wrong* would look like, and waits for your approve or change |
|
|
18
|
+
| The author grades its own work, so its blind spot is in the code *and* in the check | A second agent that never saw the work reviews it, from the request, the plan and the diff only |
|
|
19
|
+
| Findings get fixed in an endless loop, or silently dropped | Serious findings are fixed and re-checked, at most twice; the rest come to you, and what is left goes to a backlog |
|
|
20
|
+
| Requests live in sheets, docs and social posts; the plan in one chat, the review in another, the commit somewhere else | One board, from an icebox that gathers those requests to an idea, a plan, the build, the review, the fix loop and the commit, every step on file |
|
|
21
|
+
|
|
22
|
+
Many assistants now ask for approval before they act, and some run a checker on their own draft. The difference here is *who* checks: a reviewer that shares the author's context shares its blind spots. Kaizen's reviewer starts cold, on purpose.
|
|
23
|
+
|
|
24
|
+
Every stage is a file in `.kaizen/runs/<id>/`, so a run can be resumed later, by another session or another tool (Claude Code, Codex, Antigravity), and read back when someone asks why the code is the way it is.
|
|
25
|
+
|
|
26
|
+
## Who it is for
|
|
27
|
+
|
|
28
|
+
**Good fit if you:**
|
|
29
|
+
|
|
30
|
+
- Build and maintain a product, and want one place for it: requests gathered from where they live, then plan, build, review and commit, without switching tools.
|
|
31
|
+
- Already use an AI coding agent, and have caught it confidently wrong more than once.
|
|
32
|
+
- Change things where a mistake is expensive: money, data, migrations, anything a customer sees.
|
|
33
|
+
- Want to see and steer the plan before code is written, not reverse-engineer it from a diff.
|
|
34
|
+
|
|
35
|
+
**Not for you if:**
|
|
36
|
+
|
|
37
|
+
- Your changes are typos and one-liners. A run costs several times one prompt; kaizen takes a short path for small work, but it is not free.
|
|
38
|
+
- You want the agent to ship without you. Kaizen is built to stop and ask.
|
|
39
|
+
- You do not use an AI coding agent. Kaizen runs inside one; it is not one.
|
|
10
40
|
|
|
11
41
|
## Install
|
|
12
42
|
|
package/cli/sources.test.ts
CHANGED
|
@@ -101,6 +101,9 @@ test("a sheet row whose status is Done or Finish is skipped, not marked seen, an
|
|
|
101
101
|
expect(split("sheet", "no\tdetail\tnotes\n1\tDark mode\tDone\n2\tExport\tfinish\n").map((i) => i.text)).toEqual(["Dark mode", "Export"]);
|
|
102
102
|
// The whole cell names the column, not a word inside it.
|
|
103
103
|
expect(split("sheet", "detail\tstatus notes\nDark mode\tDone\n")).toEqual([{ text: "Dark mode", notes: "Done" }]);
|
|
104
|
+
// A named column of page names loses to the column holding the requests.
|
|
105
|
+
expect(split("sheet", "NO\tPAGE\tDETAIL\tSTATUS\tNOTES\n1\tDash\tList\tDone\tAdd a chart to the list\n2\tPlan\tTimeline\t\tDropdown closes before an item can be picked\n3\tPlan\t\t\tRename the statuses to proposal and tender\n").map((i) => i.text))
|
|
106
|
+
.toEqual(["Dropdown closes before an item can be picked", "Rename the statuses to proposal and tender"]);
|
|
104
107
|
|
|
105
108
|
addSource(state, SHEET);
|
|
106
109
|
expect(await gatherSource(state, SHEET, text(sheet17(statuses)), pub)).toMatchObject({ ok: true, added: 5, note: "5 new, 4 done skipped" });
|
package/cli/sources.ts
CHANGED
|
@@ -385,14 +385,19 @@ export function sift(kind: Kind, body: string): { items: Item[]; done: number }
|
|
|
385
385
|
const head = filled.slice(0, 5).find((row) => !/^\d{1,3}[.)]?$/.test(row.find(Boolean) ?? "") && (named(row, HEADER) >= 0 || named(row, STATUS) >= 0));
|
|
386
386
|
const data = head ? filled.slice(filled.indexOf(head) + 1) : filled;
|
|
387
387
|
const status = head ? named(head, STATUS) : -1;
|
|
388
|
-
|
|
389
|
-
//
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
388
|
+
// One column for the whole sheet, the one holding the most text that reads like a
|
|
389
|
+
// request. Never a cell per row, which takes `Open` or a name.
|
|
390
|
+
// Finished rows do not vote: their replies outweigh the requests still open.
|
|
391
|
+
const open = data.filter((row) => status < 0 || !DONE.test(row[status] ?? ""));
|
|
392
|
+
const text = (i: number) => i === status ? 0 : open.reduce((sum, row) => sum + (wordy(row[i] ?? "") ? row[i]!.length : 0), 0);
|
|
393
|
+
let wordiest = -1;
|
|
394
|
+
for (let i = 0, most = 0; i < Math.max(0, ...data.map((row) => row.length)); i++) if (text(i) > most) { most = text(i); wordiest = i; }
|
|
395
|
+
// A named column loses to one holding far more text: `DETAIL` naming the page while
|
|
396
|
+
// `NOTES` holds the request.
|
|
397
|
+
let known = head ? named(head, HEADER) : -1;
|
|
398
|
+
// ponytail: a named column with no wordy text at all keeps it (one-cell title rows, pinned by test).
|
|
399
|
+
if (known >= 0 && wordiest >= 0 && text(known) > 0 && text(wordiest) > 3 * text(known)) known = -1;
|
|
400
|
+
const col = known >= 0 ? known : wordiest;
|
|
396
401
|
let done = 0;
|
|
397
402
|
const items = data.flatMap((row) => {
|
|
398
403
|
const text = row[col] ?? "";
|
package/package.json
CHANGED