baldart 4.95.0 → 4.97.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/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ 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
+ ## [4.97.0] - 2026-07-02
9
+
10
+ **Change Tiers — a real Light lane, so ordinary edits stop triggering the heavy machinery.** The root primitives forced plan mode on *any* non-trivial task, a `plan-auditor` + `doc-reviewer` review gate on *every* non-trivial plan, mandatory delegation to a domain agent, and (amplified by project overlays) a worktree + backlog card whenever more than a few files were touched — so even a small direct edit spun up the full orchestration. Root cause: there were only two tiers (Trivial vs everything-else-is-Heavy); no genuine middle lane.
11
+
12
+ - **New `## Change Tiers` section in the `AGENTS.md` primitive** (cross-tool SSOT, read by Claude + Codex) defines **Trivial / Light / Heavy**, and the *tier* — not raw file count — decides whether the heavy machinery fires. Default is **Light; when in doubt → Light**.
13
+ - **Light** (the new default for most work): any change that hits **no Heavy trigger**, even multi-file within one coherent area → implemented **directly on the current branch**, no plan mode, no plan-review, no worktree, no card.
14
+ - **Heavy** (aggressive calibration): escalate ONLY for a new DB schema/migration, a new external dependency, a new API contract/route or domain entity, a wide/cross-module refactor, or work parallel to other sessions on shared files → full machinery.
15
+ - The plan-review MUST, the delegation MUST, and the Git Workflow worktree rule in `AGENTS.md` are now scoped to **Heavy**; the `CLAUDE.md` primitive Plan Mode section likewise fires only for Heavy (Light/Trivial skip plan mode + review + mandatory delegation). Primitives bumped: `AGENTS.md` 1.5.0 → **1.6.0**, `CLAUDE.md` 1.2.0 → **1.3.0**.
16
+
17
+ **MINOR** — behavior/posture change to shipped primitives, no install-layout change. **Codex parity: portable** — pure prose in the shared `AGENTS.md` skeleton; Codex reads the same tiers to decide agent-spawn / worktree / card. **Not a `baldart.config.yml` key** → the schema-change propagation rule does NOT apply. Consumers pick it up on `baldart update` (regenerated root primitives); project overlays may add project-specific Heavy triggers.
18
+
19
+ ## [4.96.0] - 2026-07-02
20
+
21
+ **Protected branch decoupled from the integration trunk — `git.protected_branch`.** The root `AGENTS.md` primitive expressed the "NEVER push directly to X" MUST via `{{ git.trunk_branch }}`, conflating two distinct roles that in a two-branch gitflow are different branches: the *integration trunk* (worktree base + feature PR target in `/prd` + `/new`) and the *protected branch* (production/release line that must not receive direct pushes). A consumer with `trunk_branch: develop` therefore had its agents (Claude + Codex) refuse a direct `develop` push — even though `develop` was the integration branch they push to and `main` was the truly-protected line. `trunk_branch` could not simply be flipped to `main` because it also drives worktree creation (`update.js`), which must branch from `develop`.
22
+
23
+ - **New optional config key `git.protected_branch`** — the branch the "never push directly" rule protects. **Defaults to `git.trunk_branch`** when omitted, so single-trunk repos are byte-unchanged; a two-branch gitflow sets it explicitly (e.g. `protected_branch: main` while `trunk_branch: develop` stays the worktree base + PR target).
24
+ - **Primitive `AGENTS.md` skeleton → 1.5.0**: the push MUST now resolves `{{ git.protected_branch }}` and explicitly permits direct pushes to other branches (including the integration trunk when it differs) when the owner authorizes it.
25
+ - **Slot resolution** (`src/utils/root-primitives.js`): `git.protected_branch` resolves to `git.protected_branch || git.trunk_branch || 'main'`.
26
+ - **Schema-change propagation** (per the rule): template (`baldart.config.template.yml` — new commented key under `git:`), `configure` (new `detectProtectedBranch` probe + serialized `git.protected_branch` + `_probes`), `update` detector (already diffs all `git.*` keys → surfaces `git.protected_branch`; added a dedicated advisory), CHANGELOG. No doctor diagnostic needed (the update advisory + configure autodetect cover it).
27
+
28
+ **MINOR** — new optional config key, back-compat default, no install-layout change. **Codex parity: portable** — pure slot resolution in the shared `AGENTS.md` skeleton (transpiled to `.codex/agents/*` unchanged; the generated `AGENTS.md` is the cross-tool SSOT read by both runtimes).
29
+
8
30
  ## [4.95.0] - 2026-07-02
9
31
 
10
32
  **`/prd` — applier economico + EARS+verify (i due interventi strutturali dal forensics della deep analysis).**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 4.95.0
1
+ 4.97.0
@@ -44,6 +44,7 @@ key was introduced:
44
44
  | Commands table | `toolchain.commands.*` → `package.json` scripts (rows with no source are omitted) |
45
45
  | Repo map | non-empty `paths.*` + a derived source root |
46
46
  | `git.trunk_branch` | `git.trunk_branch` |
47
+ | `git.protected_branch` | `git.protected_branch` → `git.trunk_branch` (default) — the "never push directly" branch; differs from the trunk only in a two-branch gitflow |
47
48
  | feature gates | `features.has_backlog` / `has_adrs` / `has_i18n` / `has_design_system` |
48
49
 
49
50
  ## Overlay
@@ -416,6 +416,15 @@ git:
416
416
  # (falling back to asking the user). Default kept as "develop" for back-compat.
417
417
  trunk_branch: develop
418
418
 
419
+ # Protected branch — the branch that MUST NOT receive direct pushes (the
420
+ # production/release line). Skills resolve this key for the "never push
421
+ # directly to X" rule. DEFAULTS to `trunk_branch` when omitted, so single-trunk
422
+ # repos need not set it. Set it explicitly ONLY for a two-branch gitflow where
423
+ # the protected line differs from the integration trunk — e.g.
424
+ # `protected_branch: main` while `trunk_branch: develop` (features integrate
425
+ # into develop; main is reached only via a release/hotfix PR).
426
+ protected_branch: develop
427
+
419
428
  # How `/mw` lands the feature branch onto the trunk:
420
429
  #
421
430
  # pr (default) — push feature branch, open a PR via `gh pr create`,
@@ -4,6 +4,34 @@ Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://sem
4
4
  Questo è il changelog INTERNO dello skeleton spedito (`primitive_version`), separato dal
5
5
  file `AGENTS.md` generato nel consumer e indipendente dal `VERSION` del framework.
6
6
 
7
+ ## 1.6.0 — 2026-07-02
8
+
9
+ - **Change Tiers — a real Light lane between Trivial and Heavy**: new `## Change Tiers`
10
+ section defines Trivial / Light / Heavy, and the tier (NOT raw file count) now decides
11
+ whether the heavy machinery fires. The plan-review MUST is scoped to **Heavy** plans (was
12
+ "any non-trivial plan → `plan-auditor` + `doc-reviewer`"); the delegation MUST is scoped to
13
+ **Heavy** implementation (Light changes MAY be implemented directly inline); the Git
14
+ Workflow worktree rule fires for **Heavy** work on a new branch (Light goes on the current
15
+ branch). Heavy triggers (aggressive calibration): new DB schema/migration, new external
16
+ dependency, new API contract/route or domain entity, wide/cross-module refactor, or work
17
+ parallel to other sessions on shared files. Default is **Light; when in doubt → Light**.
18
+ Removes the "everything is non-trivial → plan mode + review + delegate + worktree + card"
19
+ friction on ordinary edits. Cross-tool: pure prose in the shared skeleton — portable
20
+ (Claude + Codex; Codex reads the same tiers to decide agent-spawn / worktree / card).
21
+
22
+ ## 1.5.0 — 2026-07-02
23
+
24
+ - **Protected branch decoupled from the integration trunk**: the "NEVER push directly"
25
+ MUST now resolves the new `{{ git.protected_branch }}` slot instead of
26
+ `{{ git.trunk_branch }}`, and explicitly permits direct pushes to other branches
27
+ (including the integration trunk when it differs) when the owner authorizes it.
28
+ `git.protected_branch` defaults to `git.trunk_branch`, so single-trunk repos are
29
+ byte-unchanged; a two-branch gitflow sets it (e.g. `protected_branch: main` while
30
+ `trunk_branch: develop` stays the worktree base + PR target). Fixes the case where a
31
+ consumer with `trunk_branch: develop` had its agents refuse a direct `develop` push
32
+ even though `develop` was the integration branch and `main` was the protected line.
33
+ Cross-tool: pure slot resolution in the shared skeleton — portable (Claude + Codex).
34
+
7
35
  ## 1.4.0 — 2026-07-02
8
36
 
9
37
  - **Analysis-profile vocabulary on the understand-before-implement MUST**: the
@@ -1,4 +1,4 @@
1
- <!-- baldart-primitive: name=AGENTS primitive_version=1.4.0
1
+ <!-- baldart-primitive: name=AGENTS primitive_version=1.6.0
2
2
  This is the SHIPPED SKELETON. The writer (src/utils/root-primitives.js) strips
3
3
  this banner, resolves every {{ slot }} / {{> partial }} / {{#flag}} from
4
4
  baldart.config.yml (+ package.json/README), merges .baldart/overlays/AGENTS.md,
@@ -33,16 +33,19 @@ mechanics — this file remains the single source of truth for the protocol.
33
33
  diff). Contract + per-profile scoping: `agents/analysis-profiles.md`. Only if NEITHER
34
34
  invocation mechanism exists, degrade explicitly to inline retrieval
35
35
  (code-graph → LSP → Grep) and SAY SO.
36
- - MUST have any non-trivial plan reviewed BEFORE presenting it for approval — run
37
- `plan-auditor` + `doc-reviewer` (in parallel), incorporate their feedback, and note in the
38
- plan that the review gate was honored. Present the ALREADY-reviewed plan, never a raw one.
39
- (Claude Code enforces this inside plan mode, before `ExitPlanMode` — see `CLAUDE.md`.)
40
- - MUST delegate implementation to the domain agent — plan and delegate, do NOT write
41
- substantial code inline: **code / logic / tests → `coder`**; **UI (components, pages,
36
+ - MUST have any **Heavy** plan (see § Change Tiers) reviewed BEFORE presenting it for
37
+ approval — run `plan-auditor` + `doc-reviewer` (in parallel), incorporate their feedback,
38
+ and note in the plan that the review gate was honored. Present the ALREADY-reviewed plan,
39
+ never a raw one. (Claude Code enforces this inside plan mode, before `ExitPlanMode` — see
40
+ `CLAUDE.md`.) **Light** and **Trivial** changes need no plan and no review implement them
41
+ directly.
42
+ - MUST delegate **Heavy** implementation to the domain agent — plan and delegate, do NOT
43
+ write substantial code inline: **code / logic / tests → `coder`**; **UI (components, pages,
42
44
  styling, visual output) → `ui-expert`**. Same dual-tool invocation as `codebase-architect`
43
- (Claude Code: Task tool `subagent_type`; Codex: custom agent by name). Every other agent
44
- (code-reviewer, doc-reviewer, qa-sentinel, security-reviewer, …) routes via
45
- `.claude/agents/REGISTRY.md`.
45
+ (Claude Code: Task tool `subagent_type`; Codex: custom agent by name). For a **Light**
46
+ change the orchestrator MAY implement directly inline (or still delegate at its discretion
47
+ — e.g. for volume). Every other agent (code-reviewer, doc-reviewer, qa-sentinel,
48
+ security-reviewer, …) routes via `.claude/agents/REGISTRY.md`.
46
49
  - MUST NOT silently substitute a different agent when an invocation returns empty / times
47
50
  out / is denied — STOP, report verbatim, and wait. Never auto-route to a generic agent.
48
51
  - MUST NOT work on files another agent has claimed; parallel work only on independent areas.
@@ -55,7 +58,9 @@ mechanics — this file remains the single source of truth for the protocol.
55
58
  - MUST use commit format `{{ git.commit_format }}`; small, traceable commits.
56
59
  - MUST NOT commit with failing lint/type checks. Full build only before opening a PR.
57
60
  - MUST pre-sync (`git fetch`, clean status, confirm branch, `--ff-only`) and NEVER push
58
- directly to `{{ git.trunk_branch }}` — all changes reach it via PR.
61
+ directly to `{{ git.protected_branch }}` — the protected branch reaches its state only
62
+ via PR. Other branches (including the integration branch `{{ git.trunk_branch }}` when it
63
+ differs) MAY be pushed to directly when the owner authorizes it.
59
64
  - MUST get owner approval before force-push/reset or deleting an UNMERGED branch (create a
60
65
  `backup/<YYYYMMDD>-<reason>` tag first). Deleting an already-merged branch is routine.
61
66
  - MUST NOT hardcode secrets / tokens / API keys (env vars only), expose internal stack
@@ -89,14 +94,34 @@ mechanics — this file remains the single source of truth for the protocol.
89
94
  entries older than 7 days to `work-history.md`.
90
95
  {{/has_project_status}}
91
96
 
97
+ ## Change Tiers
98
+
99
+ Every change is one of three tiers. The tier — NOT raw file count — decides whether the heavy
100
+ machinery (plan mode, plan review, delegation, worktree, backlog card) applies. **When in
101
+ doubt, treat it as Light** and escalate only when a Heavy trigger is actually present.
102
+
103
+ - **Trivial** — a one-liner, typo, or obvious bug with a clear fix. Just do it.
104
+ - **Light** — the default for most work. Any change that does **not** hit a Heavy trigger,
105
+ even if it spans several files within one coherent area. → Implement **directly on the
106
+ current branch**: no plan mode, no plan-review gate, no worktree, no backlog card. The
107
+ orchestrator may edit inline or delegate for volume. Docs stay in sync and the pre-commit
108
+ gates still run.
109
+ - **Heavy** — escalate ONLY when the change: introduces a new DB schema / migration; adds a
110
+ new external dependency; adds a new API contract / route or a new domain entity; is a wide
111
+ or cross-module refactor; or runs in parallel with other agents/sessions on shared files.
112
+ → Full machinery: plan mode → reviewed plan (`plan-auditor` + `doc-reviewer`) → delegation
113
+ to the domain agent → a git **worktree** (`/nw`) → a backlog card (when the backlog feature
114
+ is on). Project overlays may add project-specific Heavy triggers.
115
+
92
116
  ## Git Workflow
93
117
 
94
118
  Branch naming: `{{ git.feature_prefix }}/<CARD-ID>-slug` (local), `codex/…` or `claude/…`
95
119
  (cloud agents), `hotfix/<ID>-slug` (production fixes). Branches are created by the
96
120
  orchestrator (`/nw`, `/new`) or the user — **never by the `coder` agent** (it implements on
97
- the branch it was spawned on). For a NEW branch, prefer a git **worktree** (`/nw`): the
98
- orchestrator MUST NOT run `git switch` / `checkout -b` / `branch` on the shared main
99
- checkout (other sessions share it). Stage explicit filenames only; never bundle unrelated changes.
121
+ the branch it was spawned on). **Light** changes go directly on the current branch. **Heavy**
122
+ work on a NEW branch uses a git **worktree** (`/nw`) the orchestrator MUST NOT run
123
+ `git switch` / `checkout -b` / `branch` on the shared main checkout (other sessions share it).
124
+ Stage explicit filenames only; never bundle unrelated changes.
100
125
 
101
126
  ## Workflow Gates
102
127
 
@@ -4,6 +4,13 @@ Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://sem
4
4
  Changelog INTERNO dello stub spedito (`primitive_version`), separato dal `CLAUDE.md`
5
5
  generato nel consumer e indipendente dal `VERSION` del framework.
6
6
 
7
+ ## 1.3.0 — 2026-07-02
8
+
9
+ - Plan Mode scoped to **Heavy** changes (see `AGENTS.md` § Change Tiers): Light and Trivial
10
+ changes now explicitly skip plan mode, the plan-review gate, and mandatory delegation —
11
+ implemented directly. "When in doubt → Light." Removes the plan-mode-for-any-non-trivial-
12
+ task friction on ordinary edits. Mirrors the AGENTS.md primitive 1.6.0 Change Tiers.
13
+
7
14
  ## 1.2.0 — 2026-07-02
8
15
 
9
16
  - Plan Mode: the `codebase-architect` pre-plan invocation now passes the matching
@@ -1,4 +1,4 @@
1
- <!-- baldart-primitive: name=CLAUDE primitive_version=1.2.0
1
+ <!-- baldart-primitive: name=CLAUDE primitive_version=1.3.0
2
2
  SHIPPED SKELETON. The writer strips this banner, resolves {{ slot }}/{{#flag}} from
3
3
  baldart.config.yml, merges .baldart/overlays/CLAUDE.md, stamps a baldart-generated
4
4
  marker, and writes the result to the repo root.
@@ -14,8 +14,11 @@ SSOT, not restated here. Below are the **Claude-native mechanics only**.
14
14
 
15
15
  ## Plan Mode (Claude-native)
16
16
 
17
- - Enter plan mode (`EnterPlanMode`) for any non-trivial task before writing code.
18
- Trivial = single-line fix / typo / obvious bug.
17
+ Plan mode is for **Heavy** changes only (see `AGENTS.md` § Change Tiers). **Light** and
18
+ **Trivial** changes skip plan mode, the plan-review gate, and mandatory delegation implement
19
+ them directly. When in doubt, treat it as Light. For a Heavy task:
20
+
21
+ - Enter plan mode (`EnterPlanMode`) before writing code.
19
22
  - Invoke `codebase-architect` before writing the plan — never plan blind. Pass the
20
23
  matching `PROFILE=<feature|bug|impact|discovery|ui|baseline>` token (the profile
21
24
  vocabulary and routing live in `AGENTS.md` § Non-negotiables and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "4.95.0",
3
+ "version": "4.97.0",
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"
@@ -102,6 +102,38 @@ function detectTrunkBranch(cwd = process.cwd()) {
102
102
  }
103
103
  }
104
104
 
105
+ /**
106
+ * Autodetect the protected branch (git.protected_branch) — the branch that MUST
107
+ * NOT receive direct pushes (production/release line). In a two-branch gitflow
108
+ * this differs from the integration `trunk_branch`: features integrate into the
109
+ * trunk (worktree base + PR target), while a separate protected branch is only
110
+ * reached via release/hotfix PRs.
111
+ * Heuristic: if trunk is NOT already `main`/`master` and such a branch exists,
112
+ * that's the protected line; otherwise the protected branch IS the trunk
113
+ * (single-trunk repo — the back-compat default, since protected_branch defaults
114
+ * to trunk_branch when absent).
115
+ */
116
+ function detectProtectedBranch(cwd = process.cwd(), trunk = 'develop') {
117
+ try {
118
+ const { execSync } = require('child_process');
119
+ const opts = { cwd, stdio: ['ignore', 'pipe', 'ignore'], timeout: 5000, encoding: 'utf8' };
120
+ const branches = (() => {
121
+ try { return execSync('git branch --format=%(refname:short)', opts).split('\n').map((s) => s.trim()); }
122
+ catch (_) { return []; }
123
+ })();
124
+ if (trunk !== 'main' && trunk !== 'master') {
125
+ for (const cand of ['main', 'master']) {
126
+ if (branches.includes(cand)) {
127
+ return { value: cand, reason: `two-branch gitflow: '${cand}' is the protected line (trunk is '${trunk}').` };
128
+ }
129
+ }
130
+ }
131
+ return { value: trunk, reason: `single-trunk repo — protected branch is the trunk ('${trunk}').` };
132
+ } catch (_) {
133
+ return { value: trunk, reason: `probe failed — protected branch defaults to trunk ('${trunk}').` };
134
+ }
135
+ }
136
+
105
137
  /**
106
138
  * Autodetect whether this project develops in parallel git worktrees
107
139
  * (`git worktree list` shows linked worktrees beyond the main one). Used to
@@ -371,6 +403,7 @@ function detect(cwd = process.cwd()) {
371
403
  : '';
372
404
 
373
405
  const trunkBranchProbe = detectTrunkBranch(cwd);
406
+ const protectedBranchProbe = detectProtectedBranch(cwd, trunkBranchProbe.value);
374
407
  const mergeStrategyProbe = detectMergeStrategy(cwd, trunkBranchProbe.value);
375
408
  // Default schema_deploy_from_trunk_only ON when parallel worktrees are in use
376
409
  // (the topology prone to migration-history desync). Otherwise keep the
@@ -532,6 +565,7 @@ function detect(cwd = process.cwd()) {
532
565
  // Set to plain strings — the structured probe details (`protected`,
533
566
  // `reason`) are kept on a sibling key so mergePreserving stays type-safe.
534
567
  trunk_branch: trunkBranchProbe.value,
568
+ protected_branch: protectedBranchProbe.value,
535
569
  merge_strategy: mergeStrategyProbe.value,
536
570
  },
537
571
  _probes: {
@@ -539,6 +573,7 @@ function detect(cwd = process.cwd()) {
539
573
  // interactivePrompts to surface the autodetection reasoning.
540
574
  merge_strategy: mergeStrategyProbe,
541
575
  trunk_branch: trunkBranchProbe,
576
+ protected_branch: protectedBranchProbe,
542
577
  },
543
578
  };
544
579
 
@@ -1551,6 +1551,12 @@ async function update(options = {}, unknownArgs = []) {
1551
1551
  + 'Until it is set, those skills autodetect the trunk (origin/HEAD → develop/main/master) '
1552
1552
  + 'and warn on each run; run `npx baldart configure` to persist it and make it deterministic.');
1553
1553
  }
1554
+ if (allMissing.includes('git.protected_branch')) {
1555
+ UI.warning('`git.protected_branch` is the branch the "never push directly" rule protects '
1556
+ + '(AGENTS.md). It DEFAULTS to `git.trunk_branch`, so single-trunk repos are unchanged; '
1557
+ + 'set it (e.g. `main`) only for a two-branch gitflow where the protected line differs from '
1558
+ + 'the integration trunk (e.g. trunk `develop`, protected `main`).');
1559
+ }
1554
1560
  }
1555
1561
  }
1556
1562
  } catch (_) {
@@ -159,6 +159,11 @@ function resolveSlots(cwd, cfg) {
159
159
  'stack.summary': stackSummary,
160
160
  'stack.node_suffix': nodeSuffix,
161
161
  'git.trunk_branch': git.trunk_branch || 'main',
162
+ // The branch that MUST NOT receive direct pushes (production/protected).
163
+ // Defaults to trunk_branch so single-trunk repos are unchanged; two-branch
164
+ // gitflows set it explicitly (e.g. protected_branch: main while
165
+ // trunk_branch: develop is the integration/PR target + worktree base).
166
+ 'git.protected_branch': git.protected_branch || git.trunk_branch || 'main',
162
167
  'git.feature_prefix': 'feat', // STATIC BALDART convention
163
168
  'git.commit_format': '[FEAT-XXXX] description', // STATIC default (override via overlay)
164
169
  'i18n.registry': paths.i18n_registry || 'the i18n registry',