kaizen-agent 1.3.1 → 1.3.3

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
@@ -15,8 +15,9 @@
15
15
  ---
16
16
 
17
17
  ```bash
18
- # 1. Install Bun (prerequisite)
18
+ # 1. Install Bun (prerequisite) — macOS, Linux, WSL
19
19
  curl -fsSL https://bun.sh/install | bash
20
+ # Windows PowerShell: powershell -c "irm bun.sh/install.ps1 | iex"
20
21
 
21
22
  # 2. Install Kaizen
22
23
  bunx kaizen-agent
@@ -284,28 +285,58 @@ leave. Hold **Shift** and drag to select text anyway.
284
285
 
285
286
  ## Install
286
287
 
287
- ### Prerequisites: Bun
288
+ Kaizen's installer and interactive dashboard require [Bun](https://bun.sh) — it is
289
+ the only prerequisite. Pick your platform:
288
290
 
289
- Kaizen's installer and interactive dashboard require [Bun](https://bun.sh). If you don't have Bun installed yet:
291
+ <details open>
292
+ <summary><b>Windows</b></summary>
293
+
294
+ In PowerShell:
295
+
296
+ ```powershell
297
+ # 1. Install Bun
298
+ powershell -c "irm bun.sh/install.ps1 | iex"
299
+
300
+ # 2. Reopen PowerShell so bun is on your PATH, then:
301
+ bunx kaizen-agent
302
+ ```
303
+
304
+ Git is not required. Where it is missing, kaizen copies itself into `%USERPROFILE%\kaizen`
305
+ instead of cloning, and `bunx kaizen-agent` is also how you update. Links are made as
306
+ directory junctions and file copies, so no administrator rights or Developer Mode are
307
+ needed. WSL users can follow the Linux instructions instead.
308
+
309
+ </details>
310
+
311
+ <details>
312
+ <summary><b>macOS</b></summary>
290
313
 
291
314
  ```bash
292
- # macOS, Linux, WSL
315
+ # 1. Install Bun
293
316
  curl -fsSL https://bun.sh/install | bash
317
+ # or: brew install oven-sh/bun/bun
294
318
 
295
- # or via Homebrew
296
- brew install oven-sh/bun/bun
297
-
298
- # or via npm
299
- npm install -g bun
319
+ # 2. Install Kaizen
320
+ bunx kaizen-agent
300
321
  ```
301
322
 
302
- ### Install Kaizen
323
+ </details>
324
+
325
+ <details>
326
+ <summary><b>Linux</b></summary>
303
327
 
304
328
  ```bash
329
+ # 1. Install Bun
330
+ curl -fsSL https://bun.sh/install | bash
331
+ # or: npm install -g bun
332
+
333
+ # 2. Install Kaizen
305
334
  bunx kaizen-agent
306
335
  ```
307
336
 
308
- 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.
337
+ </details>
338
+
339
+ The installer 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.
309
340
 
310
341
  Run from inside a project it asks whether to install globally or for that project
311
342
  alone; anywhere else — your home directory, a plain folder, a script — it installs
package/cli/dashboard.ts CHANGED
@@ -140,8 +140,12 @@ function readMouse(rest: string): { ev: MouseEv; len: number } | null {
140
140
  const WHEEL_UP = 64, WHEEL_DOWN = 65;
141
141
  const isClick = (e: MouseEv) => e.press && e.button === 0;
142
142
 
143
+ // Re-sent even when this module thinks it is already armed: settings runs as an
144
+ // action, tracks arming with its own flag, and turns reporting off in the terminal
145
+ // on the way out. Enabling twice costs nothing; trusting the stale flag costs the
146
+ // mouse for the rest of the session.
143
147
  function mouseOn() {
144
- if (!mouseWanted || mouseArmed) return;
148
+ if (!mouseWanted) return;
145
149
  process.stdout.write("\x1b[?1000h\x1b[?1006h");
146
150
  mouseArmed = true;
147
151
  }
@@ -208,7 +212,9 @@ export async function dashboard(
208
212
  { key: "backlog", label: "Backlog", hint: "what runs noticed and did not do" },
209
213
  ] : []),
210
214
  { key: "settings", label: "Settings", hint: "modes, approvals, who builds" },
211
- ...(state && !existsSync(join(state, "spec.md"))
215
+ // ~/.kaizen is the global state, not a project: there is nothing to set up
216
+ // there, and it never holds the spec files a project copy does.
217
+ ...(state && state !== join(home, ".kaizen") && !existsSync(join(state, "spec.md"))
212
218
  ? [{ key: "init", label: "Set up this project", hint: "write .kaizen/ here" }] : []),
213
219
  ...(!state ? [{ key: "init", label: "Set up this project", hint: "write .kaizen/ here" }] : []),
214
220
  { key: "upgrade", label: "Upgrade", hint: "pull, relink, clear the installer cache" },
package/cli/install.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  } from "node:fs";
7
7
  import { join, dirname, basename } from "node:path";
8
8
  import { homedir, tmpdir } from "node:os";
9
- import { applyPreset, PRESETS, type PresetName } from "./settings.ts";
9
+ import { applyPreset, detectPreset, PRESETS, type PresetName } from "./settings.ts";
10
10
 
11
11
  const home = homedir();
12
12
  const REPO_URL = "https://github.com/hfadhlullah/kaizen.git";
@@ -271,9 +271,11 @@ const root = await chooseRoot();
271
271
  const presetChoice = await choosePreset();
272
272
  const targets = found(root);
273
273
 
274
- async function choosePreset(): Promise<PresetName> {
274
+ // null means "leave the config alone": an upgrade or a --yes run never asked, and
275
+ // answering "medium" for the user overwrote whatever preset they had chosen.
276
+ async function choosePreset(): Promise<PresetName | null> {
275
277
  if (presetArg) return presetArg;
276
- if (!interactive) return "medium";
278
+ if (!interactive) return null;
277
279
 
278
280
  return select("Choose workflow preset", [
279
281
  {
@@ -473,10 +475,16 @@ const globalConfig = join(globalKaizen, "config.yml");
473
475
  mkdirSync(globalKaizen, { recursive: true });
474
476
  const defPath = join(repo, "skills/kaizen/config.default.yml");
475
477
  const def = readFileSync(defPath, "utf8");
476
- const base = existsSync(globalConfig) ? readFileSync(globalConfig, "utf8") : def;
477
- const conf = applyPreset(base, presetChoice, def);
478
- writeFileSync(globalConfig, conf);
479
- step(`configured ${c.bold(presetChoice)} preset in ${tilde(globalConfig)}`);
478
+ const existing = existsSync(globalConfig) ? readFileSync(globalConfig, "utf8") : null;
479
+ if (presetChoice) {
480
+ writeFileSync(globalConfig, applyPreset(existing ?? def, presetChoice, def));
481
+ step(`configured ${c.bold(presetChoice)} preset in ${tilde(globalConfig)}`);
482
+ } else if (!existing) {
483
+ writeFileSync(globalConfig, def);
484
+ step(`wrote ${tilde(globalConfig)}`);
485
+ } else {
486
+ step(`kept your settings in ${tilde(globalConfig)} ${c.dim(`(${detectPreset(existing, def)})`)}`);
487
+ }
480
488
  }
481
489
 
482
490
  // A .kaizen/ in a parent already owns this folder's state, and setting up a child
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kaizen-agent",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "Staged workflow for AI agents — code, writing, research, operations: plan, human approval, build, independent review, bounded fix loop.",
5
5
  "type": "module",
6
6
  "bin": {