baldart 4.68.0 → 4.68.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 +23 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/doc-reviewer.md +27 -1
- package/framework/.claude/skills/design-system-init/SKILL.md +36 -7
- package/framework/agents/design-system-protocol.md +2 -1
- package/framework/agents/workflows.md +32 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ 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.68.2] - 2026-06-24
|
|
9
|
+
|
|
10
|
+
**A change's OWN documentation now closes before merge — no more "post-merge, non-blocking" doc follow-ups for what the change itself touched.** Observed on a real `mayo` FEAT-0055 run that merged with two deferred doc items: a full-sync of the `/products` screen doc (the exact route it changed, beyond a stub) and a `must_rule` clarification on `PageLayout.md` (the component it modified). Both are *own-docs* — documenting what you just shipped — yet `/new` permitted deferring them (the DS Decision Matrix routed "needs judgement" to a follow-up, and Phase 6b force-marks cards DONE regardless). Leaving the doc of the thing you just changed stale at merge is the drift entry door the Post-Intervention philosophy exists to close.
|
|
11
|
+
|
|
12
|
+
**PATCH** — tightens the deferral classification of an existing gate; no new config key, no new agent/skill. Deliberately NOT a blanket "all docs block merge" (that regresses the follow-up mechanism by coupling ready code to genuinely-separate design decisions) — only *own-docs* block; adjacent/cross-cutting docs still defer to a tracked follow-up.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **New SSOT § "Documentation Closure"** in `agents/workflows.md` (twin of the AC Scope Closure Discipline, STRICTER) — a change's OWN docs must be SYNCED in the same PR before merge, no follow-up escape, a stub is not synced. "Own-docs" is **deterministic** (not the agent's discretion to relabel as adjacent): (1) the spec of any modified primitive, (2) the screen/route doc for a touched route, (3) the card's declared `documentation_impact`/`canonical_docs`. Anything outside those three is adjacent and still deferrable.
|
|
17
|
+
- **`design-system-protocol.md` Decision Matrix tightened** — a spec update that DOCUMENTS the behaviour THIS change introduced (a new/changed `must_rule`/prop/variant/slot/a11y hook) is **inline-BLOCKING, not deferrable**; only a genuinely SEPARATE design decision (a new variant's full semantics, breaking-change migration design, an unresolved a11y trade-off) remains the deferrable case.
|
|
18
|
+
- **`doc-reviewer` Own-Documentation Closure gate** — own-doc obligations are `synced` or a **BLOCKER** (`DOC_OWN_STUB` for a stub-only own-route doc, `DS_COMPONENT_STALE` for a modified-primitive spec), emitted as `BLOCKER` (never a `LOW`/`MED` note, never a silent "deferred"). Flows through the existing pre-merge severity gate (an unresolved BLOCKER blocks the merge — `final-review.md`) and the `doc` domain-override (never inline-bypassed). Shared agent + shared `new-final-review.js` → enforced in BOTH `/new` and `new2` with no separate wiring.
|
|
19
|
+
|
|
20
|
+
## [4.68.1] - 2026-06-24
|
|
21
|
+
|
|
22
|
+
**`/design-system-init` now actually ACTIVATES the closed-set gate it just populated — found on the first real `mayo` upgrade run.** The v4.68.0 upgrade correctly derived + confirmed the closed-set data (the two-header `page-header` family + a `range-slider` pair landed in the component HEADs with `canonical_for`/`selection_closed: true`), but `baldart ds-gate` stayed `no-policy` and never enforced. Root cause: step 6's serializer bundle merged "deterministic (step 3) + agentic (step 4)" but NOT the step-4b/4c selection-policy fields, so `emitSelectionPolicy` ran over components without `canonical_for` and generated an EMPTY `INDEX.md § "Selection Policy"` block (the HEADs got the fields via a side path; the gate reads the INDEX block). Data present, gate dormant.
|
|
23
|
+
|
|
24
|
+
**PATCH** — corrects the bootstrap write/verify flow; no schema/API change.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **Selection-policy fields flow into the `--index` bundle** (`design-system-init/SKILL.md` step 6 + workflow step 5) — the serializer bundle MUST carry `canonical_for`/`use_when`/`selection_closed` for ALL components so `emitSelectionPolicy` generates the populated `INDEX.md § "Selection Policy"` block. Building the bundle from `extract-manifest` only / pre-4c agentic JSON leaves the block empty.
|
|
29
|
+
- **New BLOCKING verification step 6b/5b** — when any closure was confirmed, the skill now asserts `INDEX.md` contains `## Selection Policy` AND `baldart ds-gate` no longer reports `no-policy` (the gate reads the COMMITTED baseline, so the INDEX block must be committed) before declaring the closed-set bootstrapped. Closes the "data in HEADs but gate dormant" gap that would otherwise ship silently.
|
|
30
|
+
|
|
8
31
|
## [4.68.0] - 2026-06-24
|
|
9
32
|
|
|
10
33
|
**Closed-Set Selection Policy — the third semantic layer that makes the "third header" structurally impossible.** Found on real `mayo` PRDs: every PRD ignored the two existing canonical headers (`SectionHeader` depth-0, `DrilldownHeader` depth-1+) and wrote new ones, requiring an expensive consolidation epic (`FEAT-0045` + an ADR) and leaving `Header.tsx` deprecated-but-live in 3 call-sites. Root cause (confirmed by a BALDART trace + 40-source 2026 research): the registry has a token layer and a component layer, but **no layer asserts the *boundary* of a category** — so adding a third header violated no rule, only an undiscovered convention. The registry-first cascade was advisory at generation-time + reactive at review-time; nothing prevented the duplicate at build-time. The 2026 market confirms the gap: no vendor (Figma Code Connect, Storybook MCP, shadcn) hard-gates the reuse decision, and no deterministic tool detects a semantically-equivalent rewrite — but BALDART already ships the machine-readable manifest signature, so it is "one manifest-signature-diff away".
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.68.
|
|
1
|
+
4.68.2
|
|
@@ -246,7 +246,33 @@ Run this before any general audit:
|
|
|
246
246
|
7. Write missing docs directly. Prefer extending existing reference docs over creating new files unless the feature is large enough to justify a standalone document. For type-specific checklists, read `.claude/skills/doc-reviewer-support/references/doc-checklists.md` **if it exists**; otherwise apply the doc-type rules and invariant table above and the `doc-writing-for-rag` skill's templates.
|
|
247
247
|
8. Update indexes when new docs are added.
|
|
248
248
|
9. Assess Obsidian/wiki sync need (section H) — **OPTIONAL, only when `features.has_wiki_overlay: true` in `baldart.config.yml`**. If the flag is absent or false, skip section H with a one-line "no wiki overlay" note. When the flag is true, read `.claude/skills/doc-reviewer-support/references/obsidian-integration.md` for trigger conditions **if it exists**; otherwise assess on first principles (new cross-cutting concept, renamed canonical, deprecated doc) and note the need without dispatching any sync agent here.
|
|
249
|
-
10. Report what was checked, added, fixed, and deferred.
|
|
249
|
+
10. Report what was checked, added, fixed, and deferred — but see the Own-Documentation Closure gate below: an own-doc may NOT appear in the "deferred" bucket.
|
|
250
|
+
|
|
251
|
+
### Own-Documentation Closure (BLOCKING — own-docs close in this PR, no defer)
|
|
252
|
+
|
|
253
|
+
Per `agents/workflows.md § Documentation Closure`, the documentation of **what
|
|
254
|
+
this change itself touched** must be SYNCED in this diff before merge — it is NOT
|
|
255
|
+
deferrable to a follow-up, and a STUB is not synced. Build the own-doc obligation
|
|
256
|
+
list deterministically from the diff + card (do not relabel an own-doc as
|
|
257
|
+
"adjacent" to defer it):
|
|
258
|
+
|
|
259
|
+
1. **Modified-primitive spec** — every component whose source changed → its
|
|
260
|
+
`components/<Name>.md` reflects the shipped behaviour (the `must_rules` / props /
|
|
261
|
+
slots the change introduced). A stale/stub spec is `DS_COMPONENT_STALE`.
|
|
262
|
+
2. **Touched route/screen doc** — the diff changed a route/page → the screen/route
|
|
263
|
+
doc for THAT route is synced (not just stubbed). A stub-only doc for a route you
|
|
264
|
+
changed is `DOC_OWN_STUB` (the screens/README "stub but full-sync deferred"
|
|
265
|
+
pattern — not allowed for an own-route).
|
|
266
|
+
3. **Declared `documentation_impact` / `canonical_docs`** — every doc the card named
|
|
267
|
+
as in-scope is synced.
|
|
268
|
+
|
|
269
|
+
Each obligation is `synced` or it is a **BLOCKER** finding (`DOC_OWN_STUB` /
|
|
270
|
+
`DS_COMPONENT_STALE`) — emit it as `BLOCKER` in section F/G, never as a `LOW`/`MED`
|
|
271
|
+
note and never silently in a "deferred" list. In WRITE mode you fix it yourself
|
|
272
|
+
(you are fully responsible for feature docs — `## Constraints`); you do NOT defer
|
|
273
|
+
an own-doc to another agent or a later card. Only **adjacent** docs (a broader
|
|
274
|
+
rewrite, a genuinely separate design decision, areas the change only grazed) may be
|
|
275
|
+
reported as a tracked follow-up.
|
|
250
276
|
|
|
251
277
|
## Audit Process (general documentation review)
|
|
252
278
|
1. **Map**: Build tree of all docs with purpose annotations.
|
|
@@ -158,8 +158,17 @@ precedence caveats: `framework/agents/effort-protocol.md`.
|
|
|
158
158
|
Reconciliation gate: auto where confident, ask where it is the user's call.
|
|
159
159
|
5. **Bootstrap the DTCG token SSOT.** See § Token SSOT bootstrap below.
|
|
160
160
|
6. **Write the files — DETERMINISTICALLY (the HEAD is NEVER model-authored).**
|
|
161
|
-
Merge the deterministic JSON (step 3) with the agentic JSON (step 4)
|
|
162
|
-
|
|
161
|
+
Merge the deterministic JSON (step 3) with the agentic JSON (step 4) **and the
|
|
162
|
+
selection-policy fields from steps 4b/4c** (`canonical_for` / `use_when` /
|
|
163
|
+
`selection_closed`) per component into a bundle and run the serializer. The
|
|
164
|
+
bundle MUST carry the selection-policy fields — they are what
|
|
165
|
+
`emitSelectionPolicy` reads to GENERATE the `INDEX.md § "Selection Policy"`
|
|
166
|
+
block. Omitting them (e.g. building the bundle from `extract-manifest` only, or
|
|
167
|
+
from the pre-4c agentic JSON) writes the closed-set fields to the HEADs via a
|
|
168
|
+
side path but leaves the INDEX block EMPTY, so `baldart ds-gate` stays
|
|
169
|
+
`no-policy` and the gate never activates. On UPGRADE, the `--index` bundle MUST
|
|
170
|
+
include ALL components (not only the changed ones) so the regenerated router +
|
|
171
|
+
policy block are complete. Run the serializer:
|
|
163
172
|
```
|
|
164
173
|
node .framework/framework/.claude/skills/design-system-init/scripts/serialize-spec.mjs \
|
|
165
174
|
--bundle <bundle.json> --out-dir ${paths.design_system}/components \
|
|
@@ -186,6 +195,18 @@ precedence caveats: `framework/agents/effort-protocol.md`.
|
|
|
186
195
|
- `tokens-reference.md` — **generated** human view of `.tokens.json` (or pure
|
|
187
196
|
narrative). Not a third source of values.
|
|
188
197
|
- `patterns/.gitkeep` — empty dir for future pattern docs.
|
|
198
|
+
6b. **VERIFY the Selection Policy activated (BLOCKING when any closure was confirmed).**
|
|
199
|
+
If step 4c confirmed any `selection_closed: true`, then after the write:
|
|
200
|
+
- `grep -q '## Selection Policy' ${paths.design_system}/INDEX.md` MUST succeed —
|
|
201
|
+
the generated block lists the closed families. If it is ABSENT, the bundle
|
|
202
|
+
dropped the selection-policy fields (step 6): rebuild the `--index` bundle
|
|
203
|
+
INCLUDING `canonical_for`/`selection_closed` for ALL components and re-run.
|
|
204
|
+
- `npx baldart ds-gate --json` MUST NOT report `"reason":"no-policy"`. If it
|
|
205
|
+
still does, the committed INDEX lacks the block — the gate reads the COMMITTED
|
|
206
|
+
baseline, so the INDEX (with the policy block) must be committed for the gate
|
|
207
|
+
to enforce. Surface this in the next-steps so the user commits it.
|
|
208
|
+
Do NOT declare the closed-set bootstrapped until both pass — otherwise the data
|
|
209
|
+
is in the HEADs but the gate is dormant (the exact gap this check closes).
|
|
189
210
|
7. **Update config.** Set `features.has_design_system: true`,
|
|
190
211
|
`paths.design_system: <target>`, and (when tokens bootstrapped)
|
|
191
212
|
`paths.design_tokens` + `design_tokens.outputs`. Use the same YAML write path
|
|
@@ -225,11 +246,19 @@ precedence caveats: `framework/agents/effort-protocol.md`.
|
|
|
225
246
|
4. **Token SSOT bootstrap** — § Token SSOT bootstrap (derive `.tokens.json`,
|
|
226
247
|
set outputs, `baldart tokens build`, round-trip verify).
|
|
227
248
|
|
|
228
|
-
5. **Write files DETERMINISTICALLY** — merge deterministic+agentic
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
249
|
+
5. **Write files DETERMINISTICALLY** — merge deterministic+agentic+selection-policy
|
|
250
|
+
field data per component (the bundle MUST carry `canonical_for`/`use_when`/
|
|
251
|
+
`selection_closed` so the serializer GENERATES the `INDEX.md § Selection Policy`
|
|
252
|
+
block) and run `scripts/serialize-spec.mjs --index` over ALL components (emits
|
|
253
|
+
valid-YAML HEADs + thin INDEX router + policy block, self-validates, fails
|
|
254
|
+
closed). Never hand-write the HEAD. Then the generated tokens-reference +
|
|
255
|
+
`patterns/.gitkeep`. UPGRADE salvages agentic values from existing (even
|
|
256
|
+
malformed) HEADs before re-serializing.
|
|
257
|
+
|
|
258
|
+
5b. **Verify the Selection Policy activated** (§ What This Skill Does step 6b) —
|
|
259
|
+
when any closure was confirmed: `INDEX.md` MUST contain `## Selection Policy`
|
|
260
|
+
AND `baldart ds-gate` MUST NOT report `no-policy` (commit the INDEX — the gate
|
|
261
|
+
reads the committed baseline). Don't declare done until both pass.
|
|
233
262
|
|
|
234
263
|
6. **Persist config** — `features.has_design_system: true`, `paths.design_system`,
|
|
235
264
|
and (if tokens bootstrapped) `paths.design_tokens` + `design_tokens.outputs`.
|
|
@@ -600,7 +600,8 @@ For each item in the diff that touched a visual surface, run these 4 checks:
|
|
|
600
600
|
| Situation | Action |
|
|
601
601
|
|---|---|
|
|
602
602
|
| Spec / token update is trivial (variant added, prop renamed, token value tweaked) | Apply inline — same commit as the code change |
|
|
603
|
-
| Spec
|
|
603
|
+
| Spec update DOCUMENTS the behaviour THIS change introduced (a new/changed `must_rule`, prop, variant, slot, a11y hook the diff added) | **Apply inline — BLOCKING, not deferrable.** This is an *own-doc* (`agents/workflows.md § Documentation Closure`): documenting what you just shipped is part of the change, never a follow-up. A stub is not synced. |
|
|
604
|
+
| Spec / token update requires a genuinely SEPARATE design decision (a new variant's full semantics needing its own design pass, a breaking change needing migration design, an unresolved accessibility trade-off) — beyond documenting this change | Open a follow-up card; **document the gap explicitly** in the change description; flag for `code-reviewer`. This is the ONLY deferrable case. |
|
|
604
605
|
| Reused undocumented primitive that is broadly useful | Add INDEX entry inline; if a full spec needs design work, scaffold a stub spec marked `status: needs-review` |
|
|
605
606
|
| Reused undocumented primitive that is surface-specific | Add INDEX entry with `scope: local` and a 2-line note explaining why no full spec is needed |
|
|
606
607
|
| Introduced a primitive that **duplicates** an existing registry entry | **Stop**. This is the failure mode the cascade exists to prevent. Revert and reuse the existing primitive, or escalate to refactor the existing primitive if the new requirement is legitimately broader |
|
|
@@ -61,6 +61,38 @@ When a card's `acceptance_criteria` cannot be fully implemented as written, the
|
|
|
61
61
|
|
|
62
62
|
Any deferral travels through an explicit `AskUserQuestion` with the AC text quoted verbatim, one question per AC. For orchestrator skills (`/new`, `/prd`) this discipline is enforced in the per-card AC-closure gate before commit. Auto Mode's "bias toward proceeding" applies to routine decisions, NOT to scope reduction — silent deferral of a numbered AC is a violation even in Auto Mode.
|
|
63
63
|
|
|
64
|
+
### Documentation Closure (own-docs close before merge — no defer)
|
|
65
|
+
|
|
66
|
+
The same discipline applies to the **documentation of what the change itself
|
|
67
|
+
touched** — and is STRICTER than ACs: a change's OWN docs must be reconciled
|
|
68
|
+
**in the same PR, before merge**. They may NOT be deferred to a post-merge
|
|
69
|
+
follow-up, and a STUB is not "synced". Leaving the doc of the thing you just
|
|
70
|
+
changed stale at merge is the drift entry door the Post-Intervention philosophy
|
|
71
|
+
exists to close ("reconcile at source, not next Monday").
|
|
72
|
+
|
|
73
|
+
**"Own docs" is deterministic** (derivable from the diff + card — not the agent's
|
|
74
|
+
discretion to relabel as "adjacent"):
|
|
75
|
+
|
|
76
|
+
1. **Modified-primitive spec** — any component whose source changed in the diff →
|
|
77
|
+
its `${paths.design_system}/components/<Name>.md` (incl. the `must_rules` /
|
|
78
|
+
behaviour the change introduced). This is `DS_COMPONENT_STALE` and is already
|
|
79
|
+
blocking; it is **not** deferrable as "needs design judgement" when it merely
|
|
80
|
+
documents what this change did (see `agents/design-system-protocol.md`
|
|
81
|
+
Decision Matrix).
|
|
82
|
+
2. **Touched route/screen doc** — if the diff changes a route/page, the screen/route
|
|
83
|
+
doc for THAT route (`${paths.references_dir}/ui/…` / `docs/design/screens/…`).
|
|
84
|
+
3. **Declared `documentation_impact` / `canonical_docs`** — the docs the card itself
|
|
85
|
+
named as in-scope.
|
|
86
|
+
|
|
87
|
+
Each own-doc obligation is `synced` (the doc reflects the shipped change, in this
|
|
88
|
+
diff) or it BLOCKS the merge. There is no `deferred` state for an own-doc and no
|
|
89
|
+
follow-up-card escape — the only resolutions are *sync it now* or an explicit
|
|
90
|
+
`[USER-APPROVED DEFERRAL]` recorded via `AskUserQuestion` (interactive) / surfaced
|
|
91
|
+
as a blocker (autonomous). **Adjacent / cross-cutting docs** — a broader rewrite, a
|
|
92
|
+
genuinely separate design decision, docs for areas the change only grazed — are
|
|
93
|
+
NOT own-docs: those legitimately defer to a tracked follow-up card. The boundary is
|
|
94
|
+
the three deterministic categories above; anything outside them is adjacent.
|
|
95
|
+
|
|
64
96
|
### Coder authority (no defer)
|
|
65
97
|
|
|
66
98
|
Coder agents report `done | failed` at card level. Per-requirement signals (`done | not_implemented`) are inputs to the orchestrator's AC-Closure Gate, never terminal verdicts. Coders have NO authority to declare an AC `deferred`, `out of scope`, `covered by X`, `partial`, `blocked`, or any equivalent. Only the user, via the gate's `AskUserQuestion`, can approve a deferral. Inventing constraints — `time budget`, `context budget`, `context pressure as override`, or any phrase not enumerated in a phase's documented Gate table — to skip phases or defer ACs is a protocol violation. The same rule applies to orchestrator agents (sequential and team-mode L0/L1/L2/L3): they relay coder signals into the gate; they do not aggregate, summarize, or pre-filter deferrals.
|