baldart 4.21.0 → 4.22.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 +24 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/doc-reviewer.md +15 -0
- package/framework/.claude/skills/prd/SKILL.md +16 -0
- package/framework/.claude/skills/prd/assets/state-template.md +9 -0
- package/framework/.claude/skills/prd/references/discovery-phase.md +25 -6
- package/framework/.claude/skills/prd/references/prd-writing-phase.md +5 -3
- package/framework/.claude/skills/prd/references/validation-phase.md +74 -0
- package/framework/routines/doc-review.routine.yml +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ 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.0] - 2026-06-09
|
|
9
|
+
|
|
10
|
+
**`/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).
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`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.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **`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.
|
|
19
|
+
- **`framework/.claude/skills/prd/assets/state-template.md`** — new structured `## Obsidian Spec Note` section (`wikilink:` / `path:` / `status:`).
|
|
20
|
+
- **`framework/.claude/skills/prd/SKILL.md`** — new **HARD RULE 19** (Obsidian back-reference) + Step 7.6 row in the flow table.
|
|
21
|
+
- **`framework/.claude/skills/prd/references/prd-writing-phase.md`** — Canonical Sources row now reads the structured `wikilink:` field and cross-links Step 7.6.
|
|
22
|
+
|
|
23
|
+
## [4.21.1] - 2026-06-09
|
|
24
|
+
|
|
25
|
+
**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).
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **`framework/routines/doc-review.routine.yml`** — new step 3b: when `features.has_api_docs: true`, reconcile the canonical `errors.md` (stable error codes added/renamed/removed → apply or flag `DOC_GAP`) and `schemas.md` (Zod/TS shape changes → update or flag `SCHEMA_DRIFT`) against the last-24h commits. Skips silently when the paths are unset.
|
|
30
|
+
- **`framework/.claude/agents/doc-reviewer.md`** — new "Canonical API registries — reconciliation (nightly-owned)" section: the agent now explicitly OWNS the code→doc direction for the two registries (the `doc-writing-for-rag` skill owns the doc-authoring direction). Ties together the existing `SCHEMA_DRIFT` + error-code checks.
|
|
31
|
+
|
|
8
32
|
## [4.21.0] - 2026-06-09
|
|
9
33
|
|
|
10
34
|
**Code knowledge graph layer (Graphify) + Karpathy wiki rebind + nightly doc-alignment command.** Introduce [Graphify](https://github.com/safishamsi/graphify) as the new retrieval engine replacing the removed RAG (v4.20.0): a single language-agnostic tool (tree-sitter, 28 langs, local/offline, native Leiden communities; pip `graphifyy`, CLI `graphify` + `graphify-mcp`). Opt-in, runtime-detected, silent fallback to LSP→Grep→Git. **MINOR** (additive; new agent + 2 skills + 1 routine + 1 protocol module; new config key `features.has_code_graph` + `graph.*` propagated end-to-end per the schema-change rule).
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.22.0
|
|
@@ -409,6 +409,21 @@ Beyond route existence, also check schema diffs:
|
|
|
409
409
|
- For new fields in a documented payload: NEEDS_UPDATE.
|
|
410
410
|
- For removed fields still in doc: ORPHAN_FIELD.
|
|
411
411
|
|
|
412
|
+
## Canonical API registries — reconciliation (nightly-owned)
|
|
413
|
+
|
|
414
|
+
When `features.has_api_docs: true`, you OWN keeping the two canonical registries in
|
|
415
|
+
sync with code on the nightly `doc-review` run (and on any API-doc rewrite):
|
|
416
|
+
- **`${paths.api_errors}`** (errors.md) — the single registry of stable error codes.
|
|
417
|
+
A code added / renamed / removed in the code → apply it to the right domain
|
|
418
|
+
section (trivial fix) or flag `DOC_GAP`. Endpoint docs link to the **domain
|
|
419
|
+
anchor**; they must never duplicate the table.
|
|
420
|
+
- **`${paths.api_schemas}`** (schemas.md) — the documented projection of the
|
|
421
|
+
Zod/TS shapes (Zod-in-code stays the SSOT). A shape change → update the table or
|
|
422
|
+
flag `SCHEMA_DRIFT`.
|
|
423
|
+
Skip silently when either path is unset. This is the code→doc direction that keeps
|
|
424
|
+
the registries authoritative; the `doc-writing-for-rag` skill handles the
|
|
425
|
+
doc-authoring (APPEND, no duplication) direction.
|
|
426
|
+
|
|
412
427
|
## Endpoint Count Reconciliation
|
|
413
428
|
|
|
414
429
|
Applies **when the project uses file-system route handlers** (e.g. Next.js App Router `route.ts`). Adapt the commands to the project's actual API layout — the paths below are the common Next.js convention, not a hardcoded assumption. The convention: SSOT count in `api/index.md` = sum of HTTP method exports (a handler exporting GET + POST counts as 2 endpoints).
|
|
@@ -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
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
|
|
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
|
|
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.
|
|
@@ -19,6 +19,14 @@ prompt: |
|
|
|
19
19
|
references. Flag drift as `DOC_DRIFT`.
|
|
20
20
|
3. For each source file change that landed without a corresponding doc
|
|
21
21
|
update, flag `DOC_GAP`.
|
|
22
|
+
3b. If `features.has_api_docs: true`, reconcile the CANONICAL registries
|
|
23
|
+
against the day's code changes:
|
|
24
|
+
- `${paths.api_errors}` (errors.md): a stable error code added / renamed /
|
|
25
|
+
removed in the code → apply it to the registry (trivial) or flag
|
|
26
|
+
`DOC_GAP`. Endpoint docs must link to the domain anchor, never duplicate.
|
|
27
|
+
- `${paths.api_schemas}` (schemas.md): a route's Zod/TS request/response
|
|
28
|
+
shape changed → update the matching table or flag `SCHEMA_DRIFT`.
|
|
29
|
+
Skip silently when either path is unset.
|
|
22
30
|
4. If the project ships a design-system SSOT, run the standard DS drift
|
|
23
31
|
checks (INDEX coverage, per-component accuracy, animations
|
|
24
32
|
reconciliation, tokens reconciliation).
|