baldart 4.83.0 → 4.84.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 +20 -0
- package/VERSION +1 -1
- package/framework/.claude/skills/ds-handoff/CHANGELOG.md +20 -0
- package/framework/.claude/skills/ds-handoff/SKILL.md +22 -6
- package/framework/.claude/skills/ds-handoff/assets/claude-design-handoff-prompt.template.md +23 -2
- package/framework/.claude/skills/ds-handoff/references/decision-pass.md +94 -0
- package/framework/.claude/skills/ds-handoff/references/field-extraction.md +21 -1
- package/framework/.claude/skills/prd/references/ui-design-phase.md +9 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ 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.84.0] - 2026-07-01
|
|
9
|
+
|
|
10
|
+
**`/ds-handoff` decision & preference pass — anticipa le domande di Claude Design invece di rimandargliele.** Il prompt field-level di `ds-handoff` copriva un solo asse (correttezza dei *campi* via field-extraction + coverage gate) e lasciava scoperto il **secondo asse — le decisioni di design aperte + le preferenze di consegna** — che è esattamente ciò su cui Claude Design rimanda le domande all'utente (nel caso reale "Hub fornitore", 6 domande su 6 erano su questo asse, zero sui campi). Una era **auto-inflitta** (il PRD diceva *"da proporre"* e la skill l'ha inoltrata testualmente), un'altra su un fatto **già in mano alla skill** (enum categoria con `color`) mai tradotto in istruzione.
|
|
11
|
+
|
|
12
|
+
Il fix è **combinato**: (1) un nuovo **Step 5.5 — Decision & preference pass** (`references/decision-pass.md`) che risolve PRIMA di emettere le scelte aperte / formato consegna / scope stati / canvas / varianti — **triggered, non always-on** (stessa filosofia del BLOCK del coverage gate: parte solo se c'è un irrisolto, UNA `AskUserQuestion` consolidata, no-op quando nulla è aperto; per le decisioni aperte offre "decido io" vs "fai proporre N opzioni a Claude Design"); (2) **arricchimento** che pre-compila i fatti rilevabili — nuova **§ 0 "Direttive di consegna & decisioni"** nel template + regola **enum presentazionale** in `field-extraction.md` (metadata `color`/`icon`/`badge`/`label` → render hint automatico, non una domanda). Attivo standalone **e** delegato da `/prd` (Branch B ora inoltra le preferenze già risolte in Discovery → la skill riconcilia e chiede solo il residuo). **DEGRADE** su Codex/no-TTY: bake dei default DICHIARATI in § 0, mai abort.
|
|
13
|
+
|
|
14
|
+
Resta un *thin orchestrator*, **nessun dual-SSOT** (delivery/placement/varianti non sono in `design-system-protocol.md`). **MINOR** — capability additiva su una skill esistente. **Nessuna nuova chiave `baldart.config.yml`** (rides on `features.has_design_system`) → la schema-change propagation rule NON si applica. Skill versionata `1.0.0 → 1.1.0` (bump `version` + entry nel `CHANGELOG.md` per-skill, stesso edit).
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **`framework/.claude/skills/ds-handoff/references/decision-pass.md`** — il pre-emit Step 5.5: trigger inventory, `AskUserQuestion` consolidata, DEGRADE bake-defaults, riconciliazione in modalità delegata, false-positive guards.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **`framework/.claude/skills/ds-handoff/SKILL.md`** — nuovo Step 5.5 nel workflow, Step 6 popola anche § 0, Invocation + Inline fallbacks aggiornati; `version: 1.0.0 → 1.1.0`.
|
|
23
|
+
- **`framework/.claude/skills/ds-handoff/assets/claude-design-handoff-prompt.template.md`** — nuova § 0 "Direttive di consegna & decisioni"; § 7 rimanda a § 0 per il formato export.
|
|
24
|
+
- **`framework/.claude/skills/ds-handoff/references/field-extraction.md`** — regola enum presentazionale (render hint automatico) nel mapping + sezione dedicata.
|
|
25
|
+
- **`framework/.claude/skills/prd/references/ui-design-phase.md`** — Branch B inoltra a `/ds-handoff` le preferenze di consegna/decisione già emerse in Discovery.
|
|
26
|
+
- **`framework/.claude/skills/ds-handoff/CHANGELOG.md`** — entry `1.1.0`.
|
|
27
|
+
|
|
8
28
|
## [4.83.0] - 2026-07-01
|
|
9
29
|
|
|
10
30
|
**Versioned root-file primitives — BALDART now generates `AGENTS.md` + `CLAUDE.md` from SOTA skeletons.** Previously `AGENTS.md` was a bulk symlink into the framework payload (not customizable without losing auto-update) and `CLAUDE.md` was not shipped at all. Now both are **generated real files**, produced on every install/update from **versioned skeletons** under `framework/templates/primitives/`.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.84.0
|
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 1.1.0 — 2026-07-01
|
|
6
|
+
|
|
7
|
+
- **Decision & preference pass (Step 5.5)** — nuovo `references/decision-pass.md`.
|
|
8
|
+
Chiude l'asse *decisioni* (accanto all'asse *campi* del coverage gate): risolve
|
|
9
|
+
PRIMA di emettere le scelte di design aperte + preferenze di consegna che Claude
|
|
10
|
+
Design altrimenti rimanda all'utente come domande (token `da proporre`, formato
|
|
11
|
+
consegna, scope stati, canvas/placement, appetito varianti). Triggered-not-always-on,
|
|
12
|
+
UNA `AskUserQuestion` consolidata, no-op quando nulla è aperto; per le decisioni
|
|
13
|
+
aperte offre "decido io" vs "fai proporre N opzioni a Claude Design".
|
|
14
|
+
- **Template § 0 "Direttive di consegna & decisioni"** — nuova sezione che porta le
|
|
15
|
+
risposte del pass (placement, formato, stati da consegnare, decisioni aperte,
|
|
16
|
+
varianti) come direttive esplicite; § 7 ora rimanda a § 0 per il formato export.
|
|
17
|
+
- **Enum presentazionale** — `references/field-extraction.md` rileva metadata di
|
|
18
|
+
display (`color`/`icon`/`badge`/`label`) sulle opzioni enum ed emette un render
|
|
19
|
+
hint automatico (es. Categoria con colore → pallino colore per opzione), evitando
|
|
20
|
+
la domanda "come lo rendo?". Non è un `da definire` né una domanda.
|
|
21
|
+
- **DEGRADE** (Codex / no-TTY): il pass fa bake dei default e li DICHIARA in § 0,
|
|
22
|
+
mai abort. **Delegated mode**: riconcilia con le preferenze già risolte da `/prd`
|
|
23
|
+
(Branch B in `ui-design-phase.md` ora le inoltra), chiede solo il residuo.
|
|
24
|
+
|
|
5
25
|
## 1.0.0 — 2026-07-01
|
|
6
26
|
|
|
7
27
|
- Baseline: versioning per-skill introdotto al framework v4.82.0.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ds-handoff
|
|
3
3
|
effort: medium
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
description: >
|
|
6
6
|
Produce a FIELD-LEVEL, 1:1, interaction-complete handoff brief for Claude Design
|
|
7
7
|
— every screen's real fields (label, control type, required, validation, default,
|
|
@@ -67,7 +67,9 @@ user input. Level→behavior mapping, parsing contract, and precedence caveats:
|
|
|
67
67
|
`/ds-handoff <screens-or-feature>` (standalone) · `/ds-handoff` (ask). When called
|
|
68
68
|
by `/prd` Step 3.0 Branch B, the caller passes the resolved context (state-file
|
|
69
69
|
path + feature title/objective/user_flow/personas/screens_in_scope/mockup_analysis
|
|
70
|
-
+ brand + DS flag
|
|
70
|
+
+ brand + DS flag + any delivery/decision preferences already resolved in Discovery)
|
|
71
|
+
— skip the standalone screen-resolution prompt (Step 1's ask), and reconcile the
|
|
72
|
+
Step 5.5 decision pass against those preferences (ask only the residual).
|
|
71
73
|
|
|
72
74
|
## Pre-flight
|
|
73
75
|
|
|
@@ -120,10 +122,23 @@ Each step is a delegation. Read the cited SSOT; do not paraphrase it.
|
|
|
120
122
|
user-confirmation (present best-effort, ask the user to fill `da definire`);
|
|
121
123
|
never hard-abort.
|
|
122
124
|
|
|
125
|
+
This gate closes the **field** axis. The **decision** axis is Step 5.5.
|
|
126
|
+
|
|
127
|
+
5.5. **Decision & preference pass.** DELEGATE —
|
|
128
|
+
[references/decision-pass.md](references/decision-pass.md). Resolve the open
|
|
129
|
+
design choices + delivery/placement preferences that Claude Design would
|
|
130
|
+
otherwise bounce back as questions (the `da proporre` tokens, delivery format,
|
|
131
|
+
state scope, canvas, variation appetite). **Triggered, not always-on** — fires
|
|
132
|
+
only when an item is unresolved; ONE consolidated `AskUserQuestion`; a no-op when
|
|
133
|
+
nothing is open. **DEGRADE** (Codex / no-TTY): bake defaults and DECLARE them in
|
|
134
|
+
§ 0, never abort. **Delegated mode:** skip whatever `/prd` already resolved. The
|
|
135
|
+
answers populate the template's § 0.
|
|
136
|
+
|
|
123
137
|
6. **Fill the mandatory template.** Populate
|
|
124
138
|
[assets/claude-design-handoff-prompt.template.md](assets/claude-design-handoff-prompt.template.md)
|
|
125
|
-
with the
|
|
126
|
-
|
|
139
|
+
with the § 0 delivery/decision directives (from Step 5.5), the reconciled
|
|
140
|
+
per-screen specs + the top-level sections (brand / design system / stack / cosa
|
|
141
|
+
restituirmi). § 5's numeric constraints are the
|
|
127
142
|
`{{tokens.*}}` placeholders that **cite** `design-system-protocol.md` § Reference
|
|
128
143
|
Tables — copy values verbatim from the protocol, never invent numbers. Strip
|
|
129
144
|
empty conditionals.
|
|
@@ -152,8 +167,9 @@ Each step is a delegation. Read the cited SSOT; do not paraphrase it.
|
|
|
152
167
|
|
|
153
168
|
- **No `Workflow` tool needed** — this skill is prose-orchestrated.
|
|
154
169
|
- **Codex (no subagents):** Step 3's `codebase-architect` degrades to inline Grep
|
|
155
|
-
(per `references/field-extraction.md`); the gate degrades BLOCK →
|
|
156
|
-
|
|
170
|
+
(per `references/field-extraction.md`); the Step 5 gate degrades BLOCK →
|
|
171
|
+
user-confirmation; the Step 5.5 decision pass degrades to **bake-defaults**
|
|
172
|
+
declared in § 0 (per `references/decision-pass.md`). Runs end-to-end.
|
|
157
173
|
- **No LSP / no code-graph:** silent fallback down the retrieval order. Surface a
|
|
158
174
|
broken layer via `baldart doctor`, never abort here.
|
|
159
175
|
- **No formal schema in the stack:** the DEGRADE branch — best-effort inventory +
|
|
@@ -22,6 +22,23 @@
|
|
|
22
22
|
|
|
23
23
|
# Feature: {{feature_title}}
|
|
24
24
|
|
|
25
|
+
## 0. Direttive di consegna & decisioni
|
|
26
|
+
|
|
27
|
+
> Queste sono decisioni **già prese** (o esplicitamente delegate a te). Non
|
|
28
|
+
> richiedermele: seguile, oppure — dove indicato "proponi N opzioni" — proponi le
|
|
29
|
+
> alternative con i loro trade-off invece di sceglierne una a caso.
|
|
30
|
+
|
|
31
|
+
- **Dove collocarlo**: {{delivery.target_canvas}} <!-- es. "Nuovo canvas «Hub fornitore desktop/tablet», NON dentro il master-detail Fornitori esistente" -->
|
|
32
|
+
- **Formato di consegna**: {{delivery.output_delivery}} <!-- "1 artboard per stato (PNG ≥2x)" | "prototipo interattivo navigabile" | "entrambi" -->
|
|
33
|
+
- **Stati da consegnare**: {{delivery.states_to_deliver}} <!-- lista esplicita — consegna ESATTAMENTE questi, non chiedermi di deselezionare -->
|
|
34
|
+
{{#if delivery.open_decisions}}
|
|
35
|
+
- **Decisioni di design aperte**:
|
|
36
|
+
{{#each delivery.open_decisions}}
|
|
37
|
+
- **{{this.topic}}**: {{this.directive}} <!-- valore deciso, OPPURE "proponi {{this.n}} opzioni con trade-off" -->
|
|
38
|
+
{{/each}}
|
|
39
|
+
{{/if}}
|
|
40
|
+
- **Varianti**: {{delivery.variations}} <!-- "nessuna oltre le decisioni sopra" | assi richiesti (es. layout griglia, densità gruppi, posizione action bar) -->
|
|
41
|
+
|
|
25
42
|
## 1. Obiettivo
|
|
26
43
|
|
|
27
44
|
{{feature_objective_one_sentence}}
|
|
@@ -172,9 +189,13 @@
|
|
|
172
189
|
|
|
173
190
|
## 7. Cosa restituirmi
|
|
174
191
|
|
|
175
|
-
Per ogni schermata elencata in § 3
|
|
192
|
+
Per ogni schermata elencata in § 3, nel **formato di consegna deciso in § 0**
|
|
193
|
+
({{delivery.output_delivery}}):
|
|
176
194
|
|
|
177
|
-
1. **
|
|
195
|
+
1. **Export** ad alta risoluzione (≥ 2x) di OGNI stato in **§ 0 → Stati da
|
|
196
|
+
consegnare** (es. `dettaglio-fornitore__loading.png`,
|
|
197
|
+
`dettaglio-fornitore__populated.png`). Se § 0 chiede un prototipo interattivo,
|
|
198
|
+
consegna gli stati come schermi navigabili invece che come PNG separati.
|
|
178
199
|
2. {{output_format_preference_block}} <!-- "Codice HTML/CSS in un file unico" | "Codice React (.tsx) con import Tailwind" | "Link Figma alla frame" -->
|
|
179
200
|
3. **Mappa di tracciabilità campo→funzione** — per OGNI campo della field inventory,
|
|
180
201
|
conferma che sia presente e col controllo/mode indicati. Se un campo di § 3 manca
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Decision & preference pass — resolve the open choices BEFORE emitting
|
|
2
|
+
|
|
3
|
+
`ds-handoff` Step 5.5. Runs **after** the coverage gate (Step 5, which verifies the
|
|
4
|
+
*fields*) and **before** filling the template (Step 6). Where the coverage gate
|
|
5
|
+
closes the *data-correctness* axis, this pass closes the **decision axis**: the open
|
|
6
|
+
design choices, delivery preferences and workspace directives that — if left
|
|
7
|
+
implicit — Claude Design bounces back to the user as questions.
|
|
8
|
+
|
|
9
|
+
The failure this prevents: a prompt that says *"pattern editing per-sede, da
|
|
10
|
+
proporre"* forces Claude Design to STOP and ask which pattern; a prompt that lists
|
|
11
|
+
states but never says "deliver exactly these" invites a "deselect what you don't
|
|
12
|
+
need" round-trip; an enum with a colour but no render directive gets a "how do I
|
|
13
|
+
show the colour?" question. Every one of those is a decision BALDART can make (or
|
|
14
|
+
frame) up front.
|
|
15
|
+
|
|
16
|
+
**Same discipline as the coverage gate:** decision-**triggered**, not always-on —
|
|
17
|
+
it fires ONLY when there is an unresolved item; ONE consolidated `AskUserQuestion`;
|
|
18
|
+
never assume a default silently. If nothing is unresolved, this step is a **no-op**
|
|
19
|
+
and you proceed straight to Step 6.
|
|
20
|
+
|
|
21
|
+
## Trigger inventory — what makes the pass necessary
|
|
22
|
+
|
|
23
|
+
Scan the reconciled per-screen specs (Step 4 output: regions, actions, states,
|
|
24
|
+
list behaviour) plus the delegated/standalone context. An item is "unresolved" when:
|
|
25
|
+
|
|
26
|
+
| Item | Unresolved when… | Detection |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| **Open design decision** | an affordance/layout/pattern is explicitly left open | literal token `da proporre` / `da decidere` / `(… inline/pannello/rotta, da proporre)` / `TBD` / `?` in a region/action/state cell |
|
|
29
|
+
| **Delivery format** | not stated in context | no `output_delivery` in the delegated context / standalone args |
|
|
30
|
+
| **State scope** | states enumerated but not confirmed as the deliverable set | states present but no explicit "deliver these" directive |
|
|
31
|
+
| **Placement / canvas** | the Claude Design workspace target is unknown | no `target_canvas` in context |
|
|
32
|
+
| **Variation appetite** | the user's want for alternatives beyond the open decisions is unknown | not stated in context |
|
|
33
|
+
|
|
34
|
+
If EVERY row is already resolved (all decided in the source / passed by `/prd`),
|
|
35
|
+
**do not ask** — skip to Step 6.
|
|
36
|
+
|
|
37
|
+
## The consolidated AskUserQuestion (interactive, human present)
|
|
38
|
+
|
|
39
|
+
Raise **exactly ONE** `AskUserQuestion` covering only the unresolved rows. Suggested
|
|
40
|
+
questions (drop any that is already resolved; `multiSelect` where noted):
|
|
41
|
+
|
|
42
|
+
1. **Per each open design decision** — offer two shapes of resolution:
|
|
43
|
+
- *"Decido io"* → the user picks the concrete option (list the plausible ones:
|
|
44
|
+
e.g. inline / side-panel / dedicated route). The chosen value goes into §0 as a
|
|
45
|
+
firm directive.
|
|
46
|
+
- *"Fai proporre a Claude Design"* → frame it in the prompt as *"proponi N opzioni
|
|
47
|
+
per X con trade-off"*. This is legitimate — Claude Design is a design tool and
|
|
48
|
+
proposing is its job; the point is to make the ASK **intentional** in the prompt
|
|
49
|
+
instead of an accidental blocker.
|
|
50
|
+
2. **Formato di consegna** — `artboard-per-stato (PNG ≥2x)` (default) | `prototipo
|
|
51
|
+
interattivo navigabile` | both.
|
|
52
|
+
3. **Stati da consegnare** (`multiSelect`) — pre-checked with the full detected list;
|
|
53
|
+
the user unchecks any out of scope. The confirmed set becomes `states_to_deliver`.
|
|
54
|
+
4. **Placement / canvas** — `nuovo canvas dedicato «<feature>»` (default) | `dentro
|
|
55
|
+
un canvas esistente` (ask which).
|
|
56
|
+
5. **Varianti oltre le decisioni aperte** — `nessuna` (default) | pick axes (grid
|
|
57
|
+
layout, densità gruppi, posizione action bar, …).
|
|
58
|
+
|
|
59
|
+
Only after the user answers do you populate §0 and proceed to Step 6. Consistent with
|
|
60
|
+
always-ask-never-assume and "no silent deferral".
|
|
61
|
+
|
|
62
|
+
## DEGRADE (graceful — Codex / no-TTY / unattended)
|
|
63
|
+
|
|
64
|
+
When no interactive prompt is possible (Codex without subagents, no-TTY, an
|
|
65
|
+
autonomous run), do **not** hard-abort and do **not** ask. Instead **bake the
|
|
66
|
+
defaults** and **declare them explicitly** in §0 so the choice is visible, not
|
|
67
|
+
silent:
|
|
68
|
+
|
|
69
|
+
- Open decisions → framed as *"proponi 2 opzioni per X"* (let CD propose, since we
|
|
70
|
+
can't ask the user).
|
|
71
|
+
- Delivery → `artboard-per-stato (PNG ≥2x)`.
|
|
72
|
+
- States → deliver the full detected list.
|
|
73
|
+
- Placement → `nuovo canvas dedicato`.
|
|
74
|
+
- Variations → `nessuna`.
|
|
75
|
+
|
|
76
|
+
The prompt still ships, with an honest §0 the user can review — never an abort.
|
|
77
|
+
|
|
78
|
+
## Delegated-mode reconciliation (called from /prd)
|
|
79
|
+
|
|
80
|
+
When invoked from `/prd` Step 3.0 Branch B, the caller may already have resolved some
|
|
81
|
+
of these during Discovery (a delivery preference, a placement, an explicit design
|
|
82
|
+
decision). The passed context is authoritative: **skip every already-resolved row**
|
|
83
|
+
and ask only the residual. Never re-ask what `/prd` already knows. If the context
|
|
84
|
+
resolves everything, the pass is a no-op even in delegated mode.
|
|
85
|
+
|
|
86
|
+
## False-positive guards (do NOT treat as an open decision)
|
|
87
|
+
|
|
88
|
+
- **Descriptive prose that isn't a bivio** — a region note like "header con nome e
|
|
89
|
+
stato" is a spec, not a choice. Only a literal open-choice token (see the trigger
|
|
90
|
+
table) counts.
|
|
91
|
+
- **Fields** — those are the coverage gate's job (Step 5), not this pass. A `da
|
|
92
|
+
definire` cell is a *data* gap, not a *decision*; do not surface it here.
|
|
93
|
+
- **Already-decided affordances** — an action with a concrete effect/destination is
|
|
94
|
+
resolved; don't ask about it.
|
|
@@ -44,7 +44,7 @@ Anything you cannot ground in code is the **literal `da definire`** — never a
|
|
|
44
44
|
| **Required** | `sì` unless `.optional()` / `.nullish()` / `?` / `.partial()`. | `da definire` |
|
|
45
45
|
| **Validazione/Vincoli** | `.min()`/`.max()`/`.length()`/`.regex()`/`.email()`/`.url()`/`.int()`/`.positive()`/refinements. | `—` if none |
|
|
46
46
|
| **Default** | `.default(x)` / a form `defaultValues` entry. | `—` if none |
|
|
47
|
-
| **Opzioni / sorgente enum** | `z.enum([...])` / `z.nativeEnum` literals verbatim; a `z.string()` whose options come from a runtime query → `"query runtime — da definire"`. | `—` / `da definire` |
|
|
47
|
+
| **Opzioni / sorgente enum** | `z.enum([...])` / `z.nativeEnum` literals verbatim; a `z.string()` whose options come from a runtime query → `"query runtime — da definire"`. When the option source carries **presentational metadata**, add the render hint (see below). | `—` / `da definire` |
|
|
48
48
|
| **Helper text** | JSDoc on the field; the i18n `context` for the key; an existing form description. | `da definire` |
|
|
49
49
|
| **Mode** | `editable` by default; `readonly` for server-set / computed fields (see below). | `editable` |
|
|
50
50
|
| **Card/gruppo** | From `mockup_analysis.screens[].layout` when present, else the reconciliation decision (Step 4). | `da definire` |
|
|
@@ -57,6 +57,7 @@ component binding, a form control already in code) over the heuristic when prese
|
|
|
57
57
|
| Schema / type shape | Control |
|
|
58
58
|
|---|---|
|
|
59
59
|
| `z.enum([...])` / `z.nativeEnum` / union of string literals | `select` (or `radio` for ≤ 3 options / `segmented` per project convention) |
|
|
60
|
+
| enum whose option source carries **presentational metadata** (`color` / `icon` / `badge` / `label`) — a lookup table, a `const` map, a DB category with a colour | `select` **+ a render hint** (see "Presentational enums" below) |
|
|
60
61
|
| `z.boolean()` | `toggle` (or `checkbox`) |
|
|
61
62
|
| `z.string()` short (no/small `.max`) | `text input` |
|
|
62
63
|
| `z.string()` long (`.max` ≥ ~200, or named `notes`/`description`/`body`) | `textarea` |
|
|
@@ -69,6 +70,25 @@ component binding, a form control already in code) over the heuristic when prese
|
|
|
69
70
|
| `z.array(z.string())` from a known set | `multi-select` |
|
|
70
71
|
| `z.object(...)` nested | a sub-group / sub-card |
|
|
71
72
|
|
|
73
|
+
## Presentational enums (pre-empt the "how do I render it?" question)
|
|
74
|
+
|
|
75
|
+
When an enum's options are not bare strings but carry **display metadata** — a
|
|
76
|
+
category with a `color`, a status with an `icon`, an option with a human `label`
|
|
77
|
+
distinct from its value — capturing the values alone leaves Claude Design to guess
|
|
78
|
+
*how* to render them, which becomes a round-trip question. Instead, **detect the
|
|
79
|
+
extra fields and emit a render hint** in the Opzioni cell, so the directive is
|
|
80
|
+
explicit:
|
|
81
|
+
|
|
82
|
+
- Colour per option → `"<EnumName> (name + color) → pallino/badge colore per opzione; colore = .color"`.
|
|
83
|
+
- Icon per option → `"<EnumName> (name + icon) → icona per opzione; icona = .icon"`.
|
|
84
|
+
- Human label ≠ value → give both: `"value → «Label»"` per option.
|
|
85
|
+
|
|
86
|
+
Ground the metadata the same way as the enum itself (the lookup table / `const` map
|
|
87
|
+
/ schema). If the option list is a runtime query, still note the presentational field
|
|
88
|
+
if the row shape exposes it (`"query runtime — ogni riga ha { name, color }"`). This
|
|
89
|
+
is a documented hint the extraction step fills automatically — it is **not** a `da
|
|
90
|
+
definire` and it is **not** a user question.
|
|
91
|
+
|
|
72
92
|
## Readonly detection
|
|
73
93
|
|
|
74
94
|
Mark a field **readonly** (static text, no editable control) when it is not
|
|
@@ -46,10 +46,15 @@ delegate-or-else-inline contract as `/prd` → `/ds-new`.)
|
|
|
46
46
|
per-screen routing table");
|
|
47
47
|
- `mockup_analysis` from `## UI Design` if present (the skill reads its
|
|
48
48
|
`layout / component_props / states / responsive` as input);
|
|
49
|
-
- the `features.has_design_system` flag (the skill omits § 5 when `false`)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
- the `features.has_design_system` flag (the skill omits § 5 when `false`);
|
|
50
|
+
- **any delivery/decision preferences already surfaced in Discovery** (output
|
|
51
|
+
format, target canvas, a design decision the user already made) — `/ds-handoff`
|
|
52
|
+
runs a **decision pass** (its Step 5.5) before emitting, and reconciles against
|
|
53
|
+
what you pass so it asks only the residual, never re-asking the known.
|
|
54
|
+
|
|
55
|
+
`/ds-handoff` runs field extraction + the coverage gate + the decision pass + the
|
|
56
|
+
mandatory template and returns the **rendered prompt** plus the
|
|
57
|
+
**`field-inventory.md` path**.
|
|
53
58
|
|
|
54
59
|
**Graceful fallback** — if `/ds-handoff` is unavailable (Codex without it linked,
|
|
55
60
|
or an older install): render a **coarse** brief inline from `screens_in_scope[]`
|