baldart 3.8.0 → 3.8.2

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/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ All notable changes to BALDART will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.8.2] - 2026-05-22
9
+
10
+ `baldart` (smart doctor) no longer double-confirms safe actions. Previously, running `baldart` with a remote-ahead state would ask *"Run: Pull N commit(s)?"* and then the `update` command would ask *"Proceed with update?"* immediately after — two prompts for the same intent.
11
+
12
+ ### Fixed
13
+
14
+ - **`src/commands/doctor.js` action runner** — every action now carries an `autoOk` flag. Safe & idempotent actions (`update`, `configure*`, `migrate`, `register-edit-gate`) run without the outer doctor confirmation (their own internal prompts take over). Actions that change external state or need explicit version classification (`add`, `push`) keep the outer confirmation so the user signals intent explicitly.
15
+
16
+ Result: `baldart` in a repo with "remote ahead" now goes straight into the update flow (with its own pre-flight stash + diff preview + proceed prompt), instead of double-asking.
17
+
18
+ ## [3.8.1] - 2026-05-22
19
+
20
+ Documentation: promote the "one command for everything" install path in the README and surface the global-install recommendation in CLAUDE.md.
21
+
22
+ ### Changed
23
+
24
+ - **`README.md` Quick Start** — restructured. Primary path is now `npm i -g baldart` once, then `baldart` (no args) in any project. Added a table that maps every repo state to the action `baldart` proposes (install / migrate / configure / update / push). The `npx baldart …` form remains documented as the no-global-install alternative.
25
+ - **`CLAUDE.md`** — added the recommended end-user install (`npm i -g baldart`) to the distribution note.
26
+
27
+ No behavioural changes; the smart-doctor entry point has worked this way since v3.2.0, this release just makes it discoverable.
28
+
8
29
  ## [3.8.0] - 2026-05-22
9
30
 
10
31
  `.claude/agents/` and `.claude/commands/` move from bulk symlink to **per-item merge** with an **overlay system** (compile-time merge of base + overlay). Closes the long-standing gap where specializing a framework agent forced you to either fork the whole file (and lose upstream updates) or contaminate `.framework/`.
package/README.md CHANGED
@@ -14,47 +14,68 @@ BALDART provides a portable system for:
14
14
 
15
15
  ## Quick Start
16
16
 
17
- ### Installation
17
+ ### One command for everything (recommended)
18
+
19
+ Install the CLI globally once:
18
20
 
19
21
  ```bash
20
- # In your project directory
21
- npx baldart add
22
+ npm i -g baldart
22
23
  ```
23
24
 
24
- > Available on npm as [`baldart`](https://www.npmjs.com/package/baldart). If you need to pin a specific version (or you're hitting an old cached npx tarball), use `npx baldart@3.6.1 <cmd>` (or any other version). The legacy form `npx -y github:antbald/BALDART <cmd>` still works for unreleased commits on `main`.
25
+ Then in any project directory just run:
25
26
 
26
- That's it! The `add` command handles everything automatically:
27
- - Downloads the framework via Git subtree into `.framework/`
28
- - Creates symlinks for auto-updateable files (AGENTS.md, agents/, .claude/agents/, .claude/commands/)
29
- - Copies customizable templates (hooks, UI guidelines, backlog cards)
30
- - Creates required directories (docs/, templates/, backlog/)
27
+ ```bash
28
+ baldart
29
+ ```
31
30
 
32
- No additional activation steps needed once installed, Claude Code will automatically pick up the agents, commands, and protocols.
31
+ That's it. `baldart` with no arguments runs the **smart doctor**: it auto-detects the repo state and proposes the next sensible action with a `Y/n` prompt. You don't need to remember `add` vs `update` vs `configure` vs `migrate` — it picks the right one.
33
32
 
34
- ### Usage
33
+ | Repo state | What `baldart` proposes |
34
+ |---|---|
35
+ | No `.framework/` | "Install BALDART framework" → runs `add` |
36
+ | Legacy bulk-symlink (pre-v3.8.0) | "Migrate legacy layout" → runs `migrate` |
37
+ | Missing `baldart.config.yml` | "Generate baldart.config.yml" → runs `configure` |
38
+ | New config keys in this framework version | "Refresh baldart.config.yml" → runs `configure` |
39
+ | `framework-edit-gate` hook not registered | "Register hook" |
40
+ | Remote framework is ahead | "Pull N commit(s) from upstream" → runs `update` |
41
+ | Local framework changes ready to share | "Push local improvements upstream" → runs `push` |
35
42
 
36
- ```bash
37
- # Smart entry point: diagnose install state and propose next action.
38
- # `npx baldart` with no arguments runs this; equivalent to `baldart doctor`.
39
- npx baldart
43
+ If several conditions hold, actions are presented in priority order (e.g. update before push).
40
44
 
41
- # Show version + install date + drift from remote
42
- npx baldart version
45
+ Upgrade the CLI later:
46
+ ```bash
47
+ npm i -g baldart@latest
48
+ ```
43
49
 
44
- # Check status (symlinks, config, overlay drift)
45
- npx baldart status
50
+ ### Without the global install
46
51
 
47
- # (Re)generate baldart.config.yml interactive prompts + autodetection
48
- npx baldart configure
52
+ If you don't want a global install, every command also works via `npx`:
49
53
 
50
- # Update framework
54
+ ```bash
55
+ npx baldart # same smart entry point
56
+ npx baldart add # explicit subcommands
51
57
  npx baldart update
52
-
53
- # Contribute improvements upstream (auto bump + CHANGELOG + tag)
58
+ npx baldart configure
54
59
  npx baldart push
60
+ npx baldart version
61
+ npx baldart status
55
62
  ```
56
63
 
57
- > **Tip**: During installation, BALDART offers to configure git aliases (`fw-version`, `fw-update`, `fw-push`) so you can skip the `npx baldart` prefix after the first install.
64
+ > The legacy `npx -y github:antbald/BALDART <cmd>` form still works if you need to install from an unreleased commit on `main`. For pinning a specific version: `npx baldart@3.8.0 <cmd>`.
65
+
66
+ ### What `add` (first install) does
67
+
68
+ - Downloads the framework via Git subtree into `.framework/`
69
+ - Creates symlinks for auto-updateable files (AGENTS.md, agents/)
70
+ - Per-item-merges framework agents/commands/skills into `.claude/` (real directories where your own files coexist)
71
+ - Detects Codex on the machine and mirrors skills into `.agents/skills/` if found
72
+ - Copies customizable templates (hooks, UI guidelines, backlog cards)
73
+ - Registers the `framework-edit-gate` hook in `.claude/settings.json`
74
+ - Runs `configure` interactively to populate `baldart.config.yml`
75
+
76
+ No additional activation steps needed — once installed, Claude Code (and Codex) automatically pick up the agents, commands, skills, and protocols.
77
+
78
+ > **Tip**: During installation, BALDART offers to configure git aliases (`fw-version`, `fw-update`, `fw-push`) — handy if you don't want the global install but find `npx baldart …` long.
58
79
 
59
80
  ## Features
60
81
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.8.0
1
+ 3.8.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "3.8.0",
3
+ "version": "3.8.2",
4
4
  "description": "Claude Agent Framework - Reusable framework for coordinating AI agents and humans in software projects",
5
5
  "bin": {
6
6
  "baldart": "./bin/baldart.js"
@@ -228,11 +228,19 @@ function planActions(state) {
228
228
  return actions;
229
229
  }
230
230
 
231
+ // `autoOk` policy:
232
+ // - true → safe & idempotent action that has its own internal prompts
233
+ // (update, configure, migrate, hook register). The outer doctor
234
+ // prompt would be a redundant double-confirmation, so we skip it.
235
+ // - false → state-changing action that warrants explicit intent at the
236
+ // doctor level (add = first install, push = writes to remote
237
+ // and triggers a version-classification dialog).
231
238
  if (!state.frameworkPresent) {
232
239
  actions.push({
233
240
  key: 'add',
234
241
  label: 'Install BALDART framework',
235
242
  why: 'No .framework/ directory found in this repo.',
243
+ autoOk: false,
236
244
  run: async () => {
237
245
  const add = require('./add');
238
246
  await add(REPO_DEFAULT, { branch: 'main' });
@@ -246,6 +254,7 @@ function planActions(state) {
246
254
  key: 'migrate',
247
255
  label: 'Migrate legacy v2.0.x layout',
248
256
  why: '.claude/skills/ is a bulk symlink — v2.0.x layout. v2.1.1+ uses per-item merge.',
257
+ autoOk: true,
249
258
  run: () => require('./migrate')(),
250
259
  });
251
260
  return actions;
@@ -256,6 +265,7 @@ function planActions(state) {
256
265
  key: 'configure-malformed',
257
266
  label: 'Rewrite baldart.config.yml (current file is malformed)',
258
267
  why: 'Existing baldart.config.yml is not valid YAML — re-running configure will rebuild it.',
268
+ autoOk: true,
259
269
  run: () => require('./configure')(),
260
270
  });
261
271
  return actions;
@@ -266,6 +276,7 @@ function planActions(state) {
266
276
  key: 'configure',
267
277
  label: 'Generate baldart.config.yml',
268
278
  why: 'Skills require a config to resolve project-specific paths/identity/stack. Without it they will prompt on every invocation.',
279
+ autoOk: true,
269
280
  run: () => require('./configure')(),
270
281
  });
271
282
  return actions;
@@ -276,6 +287,7 @@ function planActions(state) {
276
287
  key: 'configure-drift',
277
288
  label: `Refresh baldart.config.yml (${state.configSchemaMissing.length} new key(s) from framework template)`,
278
289
  why: 'Framework added config keys this consumer doesn\'t yet declare: ' + state.configSchemaMissing.join(', '),
290
+ autoOk: true,
279
291
  run: () => require('./configure')(),
280
292
  });
281
293
  // Drift is non-blocking — keep checking for other actions after.
@@ -286,6 +298,7 @@ function planActions(state) {
286
298
  key: 'register-edit-gate',
287
299
  label: 'Register framework-edit-gate hook (.claude/settings.json)',
288
300
  why: 'Prevents project-specific tokens (Neo-Brutalism, merchant, …) from being written to .framework/ accidentally. Standard in v3.3.0+; missing on installs predating that version.',
301
+ autoOk: true,
289
302
  run: async () => {
290
303
  const res = require('../utils/hooks').register();
291
304
  UI.success(`Hook registered: ${res.status} (${res.path})`);
@@ -301,6 +314,7 @@ function planActions(state) {
301
314
  key: 'update',
302
315
  label: `Pull ${state.remote.behind} commit(s) from upstream`,
303
316
  why: 'Remote framework is ahead of your local copy. Updating first keeps your contributions on a fresh base.',
317
+ autoOk: true, // update has its own internal "Proceed?" prompt + pre-flight stash
304
318
  run: () => require('./update')(),
305
319
  });
306
320
  }
@@ -312,6 +326,7 @@ function planActions(state) {
312
326
  why: state.workingTreeDirty
313
327
  ? `${state.workingTreeDirty} uncommitted file(s) in .framework/ — commit them through \`baldart push\`.`
314
328
  : `${state.commitsAhead} commit(s) on .framework/ not yet pushed.`,
329
+ autoOk: false, // push writes to remote and asks for version classification — keep explicit intent
315
330
  run: () => require('./push')(),
316
331
  });
317
332
  }
@@ -472,7 +487,16 @@ async function doctor(opts = {}) {
472
487
  for (const action of actions) {
473
488
  let proceed = auto;
474
489
  if (!auto) {
475
- proceed = await UI.confirm(`Run: ${action.label}?`, true);
490
+ // Safe & idempotent actions (`autoOk: true`) run without an outer
491
+ // confirmation — they have their own internal prompts. Actions that
492
+ // change external state or require explicit version classification
493
+ // (add, push) still ask here so the user signals intent.
494
+ if (action.autoOk) {
495
+ UI.info(`→ Running: ${action.label}`);
496
+ proceed = true;
497
+ } else {
498
+ proceed = await UI.confirm(`Run: ${action.label}?`, true);
499
+ }
476
500
  }
477
501
  if (!proceed) {
478
502
  UI.info(`Skipped: ${action.label}`);