baldart 4.21.1 → 4.22.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/CHANGELOG.md CHANGED
@@ -5,6 +5,31 @@ 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.22.1] - 2026-06-09
9
+
10
+ **Epic-parent closure at end of `/new` + `/new2`.** When the last child of an epic is implemented, the epic/parent card now gets marked `DONE` automatically instead of being left stuck at `TODO`. The Phase 6b post-merge reconciliation gate only ever touched the **batch cards** (the children); the epic/parent card (`group.is_epic: true`) is excluded from the batch by the epic guard, so it never got reconciled — final-review only *reported* "all children done" without writing the epic's own status. **PATCH** (strengthens the existing Phase 6b reconciliation gate; no new agent/skill/command/config key — `/new2` inherits it because its merge agent follows `merge-cleanup.md` as SSOT).
11
+
12
+ ### Changed
13
+
14
+ - **`framework/.claude/skills/new/references/merge-cleanup.md`** — Phase 6b gains **step 5e (Epic-parent closure)**: for each distinct `group.parent` of the batch (plus any epic card in the batch itself), if **every** child is `DONE` (checked across the whole backlog, not just the batch subset), force-update the epic card to `status: DONE` + `completed_date` + note, folded into the same reconciliation commit. Leaves the epic untouched if any child is still open. The step-6 tracker block now records `Epics closed: …`.
15
+ - **`framework/.claude/skills/new/references/final-review.md`** — the "all cards in the epic are DONE" Next-Steps message now states the epic card itself is marked `DONE` (by Phase 6b step 5e), with a note that a still-`TODO` epic under all-DONE children is a Phase 6b failure to flag.
16
+ - **`framework/.claude/workflows/new2.js`** — the merge agent's deterministic policies gain an explicit **EPIC CLOSURE** rule (all-children-DONE gate, distinct from the F-029 forced-DONE prohibition since the epic is a tracker), `MERGE_SCHEMA` gains `epicsClosed[]`, and a new `epic-closure` ledger entry records which epics were closed.
17
+
18
+ ## [4.22.0] - 2026-06-09
19
+
20
+ **`/prd` Obsidian back-reference.** When a PRD is kicked off from an Obsidian note (the documental starting point), the same note now receives, at the end of the run, an idempotent snippet indexing how the feature was developed and where it landed — PRD path, epic + card IDs, branch, merge commit/PR, and the PRD's Canonical Sources — so the user can later query the note ("come è stata sviluppata la feature X, dov'è finita"). **MINOR** (additive capability on the `prd` skill; no new `baldart.config.yml` key — the note path is runtime-detected and state-persisted, so the schema-change propagation rule does not apply).
21
+
22
+ ### Added
23
+
24
+ - **`framework/.claude/skills/prd/references/validation-phase.md`** — new **Step 7.6 — Obsidian back-reference** (runs after the merge, when the canonical paths/IDs/SHA are final). Writes a marker-delimited section (`<!-- BALDART:prd:<slug> START/END -->`) holding a fenced `yaml` payload + human-readable links back into the spec note. **Idempotent** (re-runs / `/prd-add` replace the block in place), **non-blocking** (no note, unresolved vault path, or unwritable file → skip with a log line). The note lives in the user's vault, outside the worktree and outside git — a plain filesystem write, never staged.
25
+
26
+ ### Changed
27
+
28
+ - **`framework/.claude/skills/prd/references/discovery-phase.md`** — Step 1 point 2 Obsidian detection broadened beyond `[[wikilink]]` to also accept `obsidian://open?…` URIs and pasted `.md` paths, and now resolves + persists the note's **absolute `path:`** (vault root from `paths.obsidian_vault` / memory / one-time ask) so Step 7.6 can write back without re-deriving.
29
+ - **`framework/.claude/skills/prd/assets/state-template.md`** — new structured `## Obsidian Spec Note` section (`wikilink:` / `path:` / `status:`).
30
+ - **`framework/.claude/skills/prd/SKILL.md`** — new **HARD RULE 19** (Obsidian back-reference) + Step 7.6 row in the flow table.
31
+ - **`framework/.claude/skills/prd/references/prd-writing-phase.md`** — Canonical Sources row now reads the structured `wikilink:` field and cross-links Step 7.6.
32
+
8
33
  ## [4.21.1] - 2026-06-09
9
34
 
10
35
  **Nightly reconciliation of the canonical API registries (errors.md / schemas.md).** Makes the nightly `doc-review` run explicitly keep `${paths.api_errors}` and `${paths.api_schemas}` in sync with the day's code changes, instead of relying on the generic doc↔code drift step. **PATCH** (strengthens existing routine/agent behaviour; no new agent/skill/command/config key).
package/VERSION CHANGED
@@ -1 +1 @@
1
- 4.21.1
1
+ 4.22.1
@@ -303,10 +303,16 @@ deterministic script outside this orchestrator's context window.
303
303
  ```
304
304
  ## Prossimi Passi
305
305
 
306
- Tutte le card dell'epic **FEAT-XXXX** sono state completate.
306
+ Tutte le card dell'epic **FEAT-XXXX** sono state completate, e la card epic stessa è
307
+ stata marcata `DONE` (chiusura automatica in Phase 6b, step 5e).
307
308
  Pronto per il deploy: `/deploy` o `git push origin <trunk branch>` (il `git.trunk_branch` configurato)
308
309
  ```
309
310
 
311
+ > Nota: la chiusura della card epic è eseguita dal gate Phase 6b (epic-parent closure),
312
+ > non da questo step di reporting — qui la si riporta soltanto. Se l'epic risultasse
313
+ > ancora `TODO`/`IN_PROGRESS` mentre tutti i figli sono `DONE`, è un fallimento di
314
+ > Phase 6b step 5e da segnalare in `## Issues & Flags`.
315
+
310
316
  5. **Proceed to Phase 7** (production readiness checklist).
311
317
 
312
318
  ---
@@ -74,12 +74,39 @@ The most common failure mode is leaving cards IN_PROGRESS after merge. This crea
74
74
  - If doc-freshness requires ssot-registry.md → update its `last_verified_from_code` date, stage it, and retry.
75
75
  - If COMMIT_LOCK → re-run step 5a and retry.
76
76
  - Do NOT retry more than 2 times. Log the failure and move on.
77
+ 5e. **Epic-parent closure (MANDATORY — the epic card is NOT in the batch)**: the batch
78
+ implements children; the epic/parent card (`group.is_epic: true`, id usually ending
79
+ `-00` / filename `*-epic.yml` / `review_profile: skip`) is never implemented and is
80
+ excluded from the per-card loop in step 2 — so it stays at its old status (almost
81
+ always `TODO`) even when its **last** child just went DONE. Close it here, deterministically:
82
+
83
+ For each **distinct parent epic** referenced by the batch — the set of `group.parent`
84
+ values across the batch cards, PLUS any card in the batch that is itself an epic
85
+ (`group.is_epic: true`) — do:
86
+ a. Read the epic parent card `${paths.backlog_dir}/<EPIC-ID>.yml`. If `status: DONE`
87
+ already → skip (idempotent).
88
+ b. Check that **every** child is DONE (not just the batch's subset — children
89
+ implemented in earlier sessions count too):
90
+ ```bash
91
+ # Lists children of <EPIC-ID> that are NOT yet DONE. Empty output ⇒ all DONE.
92
+ grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml | xargs grep -L "status: DONE"
93
+ ```
94
+ c. **Only if** that command prints nothing (all children DONE) → force-update the epic
95
+ parent: set `status: DONE`, add `completed_date: <today>`, add note
96
+ `"Marked DONE by epic-closure gate (Phase 6b) — all children DONE"`. Stage it and
97
+ **fold into the SAME reconciliation commit** as step 5 (or, if step 5 didn't run
98
+ because all children were already DONE, make a dedicated
99
+ `[BATCH] Close epic <EPIC-ID> — all children DONE` commit, honoring the same
100
+ COMMIT_LOCK / doc-freshness precautions as step 5a–5d).
101
+ d. **If any child is still open** → leave the epic untouched: it is genuinely still in
102
+ progress, and step-4b's "Card rimanenti nell'epic" table already reports the gap.
77
103
  6. **Update tracker** with reconciliation results:
78
104
  ```
79
105
  ## Phase 6b — Status Reconciliation
80
106
  Cards checked: N
81
107
  Already DONE: M
82
108
  Force-updated to DONE: K [list card IDs]
109
+ Epics closed: J [list epic IDs] (or "none — children still open" / "n/a — no epic in batch")
83
110
  Reconciliation commit: <hash> (or "not needed")
84
111
  ```
85
112
  7. **HALT condition**: if a card cannot be updated (e.g., file read error, YAML parse error), log it in `## Issues & Flags` and continue with the remaining cards. Report the failure in the final summary.
@@ -49,6 +49,7 @@ message. You ask questions, wait for answers, and iterate.
49
49
  | 5 | Backlog Cards | [backlog-phase.md](references/backlog-phase.md) |
50
50
  | 6 | Quality Audit | [validation-phase.md](references/validation-phase.md) |
51
51
  | 7 | Resolution, Commit & Merge | [validation-phase.md](references/validation-phase.md) |
52
+ | 7.6 | Obsidian back-reference (only if a spec note was given) | [validation-phase.md](references/validation-phase.md) |
52
53
 
53
54
  **Before starting each phase, read the corresponding reference file.**
54
55
 
@@ -233,6 +234,21 @@ message. You ask questions, wait for answers, and iterate.
233
234
  transcripts for REAL per-role token + wall-clock cost. The token itself is NOT part
234
235
  of the feature description — strip it before recording the user's verbatim feature
235
236
  text in `## Feature Description`.
237
+ 19. **Obsidian back-reference (MANDATORY when a spec note was given).** If the user
238
+ kicked off the PRD from an Obsidian note (any of: `[[Note]]` wikilink,
239
+ `obsidian://open?…` URI, or a pasted `.md` path), Step 1 detection persists it in
240
+ the state file `## Obsidian Spec Note` (`wikilink:` + absolute `path:` + `status:`).
241
+ At the END of the run — **after** the merge (validation-phase Step 7, item 9) so the
242
+ paths/IDs/SHA are final — Step 7.6 writes an **idempotent** snippet back into that
243
+ note: a marker-delimited section (`<!-- BALDART:prd:<slug> START/END -->`) holding a
244
+ fenced `yaml` block with the feature slug, PRD path, epic + card IDs, branch, merge
245
+ commit/PR, and the PRD's Canonical Sources as `resources:`. This makes the original
246
+ note the durable index the user can later query ("come è stata sviluppata la feature
247
+ X, dov'è finita"). The note lives in the user's **vault, outside the worktree and
248
+ outside git** — it is a plain filesystem write, never staged/committed. The step is
249
+ **NON-BLOCKING**: no spec note, unresolved vault path, or an unwritable note all skip
250
+ it with a log line, never aborting the PRD. See discovery-phase.md Step 1 point 2 and
251
+ validation-phase.md Step 7.6.
236
252
 
237
253
  ---
238
254
 
@@ -12,6 +12,15 @@ stats_enabled: {{true if invoked with -stats/--stats, else false}}
12
12
  - created_at: {{ISO-8601 UTC}}
13
13
  - merge_commit: (pending — populated by validation-phase Step 7 after mw-docs)
14
14
 
15
+ ## Obsidian Spec Note
16
+
17
+ <!-- Populated by discovery-phase.md Step 1 point 2 ONLY when the user passed an
18
+ Obsidian note as the documental starting point. When no note was given, leave
19
+ status: none and the Step 7.6 back-reference is skipped. -->
20
+ wikilink: none # [[Note Name]] form — feeds PRD Canonical Sources row
21
+ path: none # absolute fs path of the note — target of the Step 7.6 writeback
22
+ status: none # none | detected | back-reference-written
23
+
15
24
  ## Feature Description
16
25
  {{user's description verbatim}}
17
26
 
@@ -59,12 +59,31 @@ this is a fresh session (no existing state file).
59
59
 
60
60
  1. Derive `<slug>`: kebab-case, lowercase, max 40 chars, no special chars.
61
61
  Example: "Nutritional info on menu" -> `menu-nutritional-info`
62
- 2. **Obsidian spec detection:** scan the user's message for Obsidian note references:
63
- - Wikilink pattern: `[[Note Name]]` or `[[Note Name|Alias]]`
64
- - If found: extract the note name and save it in the state file under
65
- `## Obsidian Spec Note: [[Note Name]]`. This will be added to Canonical Sources in the PRD.
66
- - Read the note content from the vault path in memory (`reference_obsidian_vault.md`)
67
- to pre-populate discovery dimensions where possible treat it as a user-provided spec.
62
+ 2. **Obsidian spec detection (and back-reference setup):** scan the user's message
63
+ for a reference to an Obsidian note used as the documental starting point. Accept
64
+ any of these forms:
65
+ - Wikilink: `[[Note Name]]` or `[[Note Name|Alias]]`.
66
+ - `obsidian://open?vault=<Vault>&file=<rel/path/Note>` URI (URL-decode `file`).
67
+ - A filesystem path to a `.md` file the user pastes ("la nota è in `…/Vault/…/Note.md`").
68
+
69
+ If found, populate the `## Obsidian Spec Note` section of the state file with:
70
+ - `wikilink:` — the `[[Note Name]]` form (for the PRD Canonical Sources row, see
71
+ prd-writing-phase.md Step 4 point 2).
72
+ - `path:` — the **absolute** filesystem path of the note. Resolve it now so the
73
+ end-of-run back-reference (validation-phase Step 7.6) can write to it without
74
+ re-deriving:
75
+ - URI/full path given → use it directly (URL-decode + join `vault`+`file`).
76
+ - Only a bare wikilink given → you need the vault root to resolve it. Use the
77
+ vault path recorded in memory (`reference_obsidian_vault.md`) if present; else
78
+ **ASK the user once** for the vault root (or the note's full path) and persist
79
+ their answer in this state section. Do NOT assume a default. If the user
80
+ declines, set `path: none` — detection still works for pre-population, but the
81
+ Step 7.6 writeback is skipped (logged, never fatal).
82
+ - `status: detected`.
83
+
84
+ Then read the note content (from `path:`) to pre-populate discovery dimensions
85
+ where possible — treat it as a user-provided spec. This same note becomes the
86
+ target of the back-reference snippet at the end of the run (HARD RULE 19).
68
87
  3. **Create the docs worktree (MANDATORY — HARD RULE 17)** — invoke the
69
88
  `worktree-manager` skill in programmatic docs mode BEFORE any file write:
70
89
 
@@ -7,10 +7,12 @@ Mark task 3 as `in_progress`.
7
7
  ## Write PRD
8
8
 
9
9
  1. Create directory `${paths.prd_dir}/<slug>/` if it doesn't exist.
10
- 2. **Obsidian spec note (if present):** if the state file contains `## Obsidian Spec Note`,
11
- add a row to the Canonical Sources table in the PRD:
10
+ 2. **Obsidian spec note (if present):** if the state file `## Obsidian Spec Note`
11
+ section has `status: detected`, add a row to the Canonical Sources table in the PRD
12
+ using its `wikilink:` value:
12
13
  `| Obsidian spec | [[Note Name]] |`
13
- This preserves traceability from the user's original spec note to the final PRD.
14
+ This preserves traceability from the user's original spec note to the final PRD, and
15
+ the same note receives the end-of-run back-reference snippet (validation-phase Step 7.6).
14
16
  3. **Resolve canonical sources** before writing:
15
17
  - Read `${paths.references_dir}/ssot-registry.md` to identify the macro feature and any
16
18
  existing canonical docs.
@@ -247,6 +247,79 @@ markers it can emit, then act:
247
247
  empty, no `[SYNC-NEEDS-DECISION]` marker is left unhandled, and the merged remote
248
248
  branch is gone (or its deletion is explicitly user-deferred).
249
249
 
250
+ ### Step 7.6 — Obsidian back-reference (NON-BLOCKING — runs only when a spec note was given)
251
+
252
+ **Why this exists.** When the user kicked off the PRD from an Obsidian note (state
253
+ file `## Obsidian Spec Note / status: detected`, see HARD RULE 19), they want that
254
+ same note to become the durable index of *how the feature was developed and where it
255
+ landed* — so they can later ask "come è stata sviluppata la feature X?" and get the
256
+ PRD, cards, and merge from the note itself. This step writes a single, idempotent,
257
+ machine-and-human readable snippet back into the note.
258
+
259
+ **Runs AFTER the merge (Step 7 item 9) succeeds** — only then are the canonical paths,
260
+ card IDs, branch, PR/SHA final. The note lives in the user's **vault, OUTSIDE the
261
+ worktree and outside git** — so this is a plain filesystem write to the absolute
262
+ `path:`, NOT a worktree-relative path and NOT a git-tracked artefact (do not stage it).
263
+
264
+ **Skip conditions (each logged, never fatal):**
265
+ - `## Obsidian Spec Note / status` is `none` (no note was given) → skip silently.
266
+ - `path:` is `none` or empty (vault root never resolved at Step 1) → skip with a note.
267
+ - The file at `path:` does not exist or is not writable → skip with a one-line warning.
268
+
269
+ **Procedure:**
270
+
271
+ 1. Read the current content of the note at `path:`.
272
+ 2. Build the snippet, delimited by HTML-comment markers keyed on the slug so the step
273
+ is **idempotent** — a re-run (or a later `/prd-add`) REPLACES the block between the
274
+ markers in place instead of appending a duplicate. If the markers are absent, append
275
+ the block at the end of the note (preceded by one blank line).
276
+
277
+ ```markdown
278
+ <!-- BALDART:prd:<slug> START -->
279
+ ## 🛠 Sviluppo BALDART — <slug>
280
+
281
+ ```yaml
282
+ feature: <slug>
283
+ prd: ${paths.prd_dir}/<slug>/PRD.md
284
+ epic: FEAT-XXXX-00-<slug>-epic
285
+ cards:
286
+ - FEAT-XXXX-01-<sub-slug>
287
+ - FEAT-XXXX-02-<sub-slug>
288
+ resources: # other Canonical Sources from the PRD (mockups, ADRs, ref docs, research)
289
+ - ${paths.prd_dir}/<slug>/design.html # omit if no design
290
+ - <ssot-registry entry / ADR path / research link>
291
+ branch: prd/<slug>
292
+ merge_commit: <SHA from state ## Validation>
293
+ pr: <PR number, or n/a for local-push>
294
+ trunk_branch: <git.trunk_branch>
295
+ date: <ISO-8601 UTC>
296
+ status: planned # planned | in-progress | done
297
+ ```
298
+
299
+ - **PRD:** [`${paths.prd_dir}/<slug>/PRD.md`](...)
300
+ - **Cards:** FEAT-XXXX-00 (epic) · FEAT-XXXX-01 · FEAT-XXXX-02 …
301
+ - **Merge:** `<SHA>` su `<git.trunk_branch>`<!-- · PR #N -->
302
+
303
+ _Generato da `/prd` il <date>. Aggiorna `status:` a `done` quando la feature è in produzione._
304
+ <!-- BALDART:prd:<slug> END -->
305
+ ```
306
+
307
+ Fill the `yaml` block from the final state: `<slug>`, the real epic + child card
308
+ IDs created in Step 5, the merge SHA written under `## Validation` (Step 7 item 8),
309
+ the PR number from the `mw-docs` return (or `n/a`), and the Canonical Sources list
310
+ the PRD already assembled (prd-writing-phase.md Step 4 point 3) for `resources:`.
311
+ The inner ```` ```yaml ```` block is fenced, NOT real top-of-file frontmatter — it
312
+ is the queryable payload Claude reads back when asked about the feature later.
313
+
314
+ 3. Write the updated note back to `path:`.
315
+ 4. Set `## Obsidian Spec Note / status: back-reference-written` in the state file.
316
+ (The state file is already committed; this is a local marker for a possible resume —
317
+ do NOT re-commit just for this field.)
318
+
319
+ **This step is NON-BLOCKING** — any failure (note moved, vault unmounted, permission
320
+ denied) logs "Obsidian back-reference: SKIPPED (<reason>)" and the run completes. The
321
+ PRD merge has already happened; the back-reference is a convenience index, never a gate.
322
+
250
323
  ### Final output
251
324
 
252
325
  Print final summary:
@@ -257,6 +330,7 @@ Print final summary:
257
330
  - Branch & merge strategy used
258
331
  - PR number (if `strategy = pr`) or merge SHA (if `local-push`)
259
332
  - Confirmation that the worktree was cleaned up AND the remote branch was deleted
333
+ - Obsidian back-reference: the note path the snippet was written to (only when Step 7.6 ran; omit otherwise)
260
334
 
261
335
  **HARD RULE — no passive deferral.** The final summary MUST NOT contain a
262
336
  "your manual actions / non-blocking notes / you can do it yourself" section.
@@ -163,6 +163,7 @@ const MERGE_SCHEMA = {
163
163
  mergeTs: { type: 'string' },
164
164
  reconciliation: { type: 'string' },
165
165
  forcedDone: { type: 'array', items: { type: 'string' }, description: 'MUST be empty — false-DONE is forbidden (F-029)' },
166
+ epicsClosed: { type: 'array', items: { type: 'string' }, description: 'Epic/parent cards marked DONE by Phase 6b step 5e (all children DONE) — NOT a forcedDone violation' },
166
167
  uncommittedLeft: { type: 'boolean', description: 'true if dirty code was left (NOT committed) + reported (F-030)' },
167
168
  note: { type: 'string' },
168
169
  },
@@ -634,6 +635,7 @@ if (!committed.length) {
634
635
  `• G24 → auto-merge via merge_strategy.\n` +
635
636
  `• F-030 HARD RULE: NEVER \`git add\`/commit code that did not pass the per-card gates. If the worktree is dirty with uncommitted code → DO NOT commit it; leave it, set uncommittedLeft:true, and report. NO "safety commit". Security/migration code is NEVER swept in.\n` +
636
637
  `• F-029 HARD RULE: Phase 6b reconciliation marks a card DONE ONLY if it has a real commit in ${TRUNK}..HEAD AND its gates are green. NEVER force a non-implemented card to DONE. Return forcedDone:[] (must be empty).\n` +
638
+ `• EPIC CLOSURE (Phase 6b step 5e): the epic/parent card (group.is_epic:true) is NOT in the batch and stays TODO unless closed here. For each distinct group.parent of the batch cards (and any epic card in the batch itself): if EVERY child of that epic — \`grep -l "parent: <EPIC-ID>" backlog/*.yml | xargs grep -L "status: DONE"\` prints nothing — set the epic card status:DONE + completed_date + note "epic-closure gate — all children DONE" and fold into the reconciliation commit. If any child is still open → leave the epic untouched. This is NOT a forcedDone violation (the epic is a tracker, gated on all-children-DONE, not on its own commit). Return epicsClosed:[<EPIC-IDs marked DONE>].\n` +
637
639
  `• G19 sync-deferred → HEAD==${TRUNK} ff-pull, else leave+report. G20 → leave+report. G21 post-batch dirty → partition-ignore framework artifacts; leave the rest + report (do NOT commit). G22 divergence → behind: ff-pull; ahead/both: leave+report; NEVER reset --hard/force-push. G23 stash restore conflict → leave intact + report.\n\n` +
638
640
  `Return: { merged, mergeCommit, mergeTs, reconciliation, forcedDone:[], uncommittedLeft, note }`,
639
641
  { label: 'merge', phase: 'Merge', agentType: 'general-purpose', schema: MERGE_SCHEMA }
@@ -641,6 +643,7 @@ if (!committed.length) {
641
643
  } catch (e) { if (e && e.transientExhausted) noteDegraded('outage'); mergeResult = null }
642
644
  if (mergeResult && (mergeResult.forcedDone || []).length) { noteDegraded('false_done'); ledger(firstCard, 'F029-guard', 'VIOLATION', `forcedDone: ${mergeResult.forcedDone.join(' ')}`) }
643
645
  if (mergeResult && mergeResult.uncommittedLeft) ledger(firstCard, 'F030-guard', 'LEFT-UNCOMMITTED', 'dirty code left (not swept) + reported')
646
+ if (mergeResult && (mergeResult.epicsClosed || []).length) ledger(firstCard, 'epic-closure', 'CLOSED', `epics marked DONE (all children DONE): ${mergeResult.epicsClosed.join(' ')}`)
644
647
  ledger(firstCard, 'G24-merge', (mergeResult && mergeResult.merged) ? 'MERGED' : 'INCOMPLETE', (mergeResult && (mergeResult.mergeCommit || mergeResult.note)) || '')
645
648
  if (mergeResult && mergeResult.reconciliation) ledger(firstCard, 'G19-23-reconcile', 'AUTO', mergeResult.reconciliation)
646
649
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "4.21.1",
3
+ "version": "4.22.1",
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"