baldart 3.14.1 → 3.16.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.
Files changed (27) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/VERSION +1 -1
  3. package/framework/.claude/agents/REGISTRY.md +10 -0
  4. package/framework/.claude/agents/api-perf-cost-auditor.md +47 -10
  5. package/framework/.claude/agents/coder.md +61 -10
  6. package/framework/.claude/agents/prd-card-writer.md +92 -19
  7. package/framework/.claude/agents/security-reviewer.md +1 -1
  8. package/framework/.claude/skills/bug/references/logging-patterns.md +45 -8
  9. package/framework/.claude/skills/new/SKILL.md +319 -87
  10. package/framework/.claude/skills/prd/SKILL.md +30 -2
  11. package/framework/.claude/skills/prd/assets/card-template.yml +59 -27
  12. package/framework/.claude/skills/prd/assets/epic-template.yml +11 -3
  13. package/framework/.claude/skills/prd/assets/prd-template.md +90 -14
  14. package/framework/.claude/skills/prd/assets/state-template.md +18 -0
  15. package/framework/.claude/skills/prd/references/api-perf-gate.md +102 -52
  16. package/framework/.claude/skills/prd/references/audit-phase.md +13 -13
  17. package/framework/.claude/skills/prd/references/backlog-phase.md +81 -0
  18. package/framework/.claude/skills/prd/references/discovery-phase.md +214 -28
  19. package/framework/.claude/skills/prd/references/prd-writing-phase.md +65 -23
  20. package/framework/.claude/skills/prd/references/research-phase.md +22 -4
  21. package/framework/.claude/skills/prd/references/ui-design-phase.md +115 -3
  22. package/framework/.claude/skills/prd/references/validation-phase.md +22 -2
  23. package/framework/docs/PROJECT-CONFIGURATION.md +41 -1
  24. package/framework/templates/baldart.config.template.yml +25 -0
  25. package/package.json +1 -1
  26. package/src/commands/configure.js +72 -0
  27. package/src/commands/update.js +13 -1
@@ -72,8 +72,118 @@ la feature prima di scrivere qualsiasi documento.
72
72
 
73
73
  **Gate:** state file exists on disk AND all tasks created AND context loaded.
74
74
 
75
- **Immediately proceed to Step 2** — do NOT stop here. Show the kickoff message
76
- and continue to the discovery loop in the same turn.
75
+ **Immediately proceed to Step 1.6** — do NOT stop here. Show the kickoff message
76
+ and ask the mockup intake question in the same turn.
77
+
78
+ ## Step 1.6 — Mockup Intake (MANDATORY)
79
+
80
+ Runs between Kickoff (Step 1) and Discovery (Step 2). Cannot be skipped.
81
+
82
+ **Purpose:** detect whether the user already has mockups for this feature, archive
83
+ them as canonical artefacts, and feed the visual analysis into Discovery alongside
84
+ the codebase context from `/cont`. The Step 3 (UI Design) decision tree consumes the
85
+ result.
86
+
87
+ ### 1.6.1 — Ask
88
+
89
+ After the kickoff output (Step 1, point 7), append this question to the SAME message:
90
+
91
+ ```
92
+ ### Domanda — Mockup
93
+
94
+ Hai dei mockup a disposizione per questa feature?
95
+
96
+ - **Sì** → posso analizzarli prima di iniziare la discovery, così le domande
97
+ saranno calibrate su quello che è già definito visivamente.
98
+ - **No** → procediamo con la discovery standard; se serve, in Step 3 genero
99
+ io 3 opzioni di design.
100
+ ```
101
+
102
+ **STOP.** Display Progress Bar (row `1.6 Mockup intake: 🔄`) and wait for the user.
103
+
104
+ ### 1.6.2 — Answer = "No"
105
+
106
+ - Update state file `## UI Design`: `mockups.status: none`.
107
+ - Mark progress bar row `1.6 ✅ (no mockups)`.
108
+ - **Immediately proceed to Step 2** in the same turn. No further STOP.
109
+
110
+ ### 1.6.3 — Answer = "Sì"
111
+
112
+ Append this follow-up to the SAME message:
113
+
114
+ ```
115
+ Perfetto. In che forma me li passi?
116
+
117
+ - **Immagini in chat** — incollale direttamente nel prossimo messaggio.
118
+ - **Path locali** — incolla i percorsi (assoluti o relativi al repo) e li copio
119
+ in `${paths.prd_dir}/<slug>/mockups/`.
120
+ - **Misti** — entrambe le cose.
121
+ ```
122
+
123
+ - Update state file `## UI Design`: `mockups.status: requested`, `mockups.format: pending`.
124
+ - **STOP.** Wait for the user.
125
+
126
+ ### 1.6.4 — Mockup reception & archival
127
+
128
+ When the user replies with the mockups:
129
+
130
+ 1. **Detect format** and update `mockups.format` ∈ {`chat-images`, `local-paths`, `mixed`}.
131
+ 2. **For each local path provided:**
132
+ - Resolve to absolute path. If file does not exist: ask the user to confirm/correct
133
+ (do not silently skip).
134
+ - Ensure `${paths.prd_dir}/<slug>/mockups/` exists (create if missing).
135
+ - Copy the file into that directory, preserving filename. On collision (file with
136
+ same name already there): append numeric suffix (`<name>-2.png`).
137
+ - Record both paths in state: `mockups.original_paths[]` and `mockups.canonical_paths[]`.
138
+ 3. **For chat images:** record in state `mockups.original_paths[]` as `chat://image-N`
139
+ (the images remain in the conversation context window).
140
+ 4. Update `mockups.status: provided` (or `partial` only if the user explicitly says
141
+ "ho solo questi 2 ma servono anche altri").
142
+
143
+ ### 1.6.5 — Mockup analysis (MANDATORY before Discovery)
144
+
145
+ Analyze ALL provided mockups (visual analysis for chat images, Read for copied files
146
+ that are textual like HTML/SVG). Populate `## UI Design` in the state file using the
147
+ **Mockup analysis schema** (see appendix at the end of this file).
148
+
149
+ When `features.has_design_system: true`, BLOCKING reads of `${paths.design_system}/INDEX.md`
150
+ and `${paths.design_system}/tokens-reference.md` apply BEFORE running the alignment
151
+ check — same protocol as Step 3 (UI Design). Flag every hardcoded value (hex / shadow /
152
+ radius / spacing) that conflicts with a known token as a violation in
153
+ `mockup_analysis.design_system_alignment.violations[]`.
154
+
155
+ ### 1.6.6 — Output and handoff to Discovery
156
+
157
+ After analysis is complete, present to the user:
158
+
159
+ ```
160
+ Mockup acquisiti e analizzati: N schermate identificate.
161
+
162
+ Schermate: <list>
163
+ Flusso utente inferito: <one-line summary>
164
+ Componenti riconosciuti: N (X riusati dal registry, Y nuovi)
165
+ Stati visibili: <empty/loading/error/success per schermata se rilevanti>
166
+ Allineamento design system: <aligned | N violations to resolve in Step 3>
167
+ Gap da chiarire in discovery: <list of ambiguities, max 5>
168
+
169
+ Ora entro in **Discovery** — le domande saranno calibrate su quanto già definito
170
+ nei mockup. Le ambiguità rilevate diventeranno domande mirate.
171
+
172
+ <Progress Bar>
173
+ ```
174
+
175
+ - Mark progress bar row `1.6 ✅` (or `🔄` if `partial`).
176
+ - **Immediately proceed to Step 2** in the same turn.
177
+
178
+ ### Coordination with `/cont`
179
+
180
+ The `/cont` skill invoked in Step 1.5 runs synchronously and completes before the
181
+ kickoff output. The mockup intake question is asked in the same message; if the user
182
+ answers "Sì", the STOP gives the codebase context time to settle in conversation
183
+ history while we wait. When the mockups arrive, the visual analysis combines with the
184
+ already-loaded codebase context to inform Discovery dimension selection (especially
185
+ dimension 5 UI impact and partially dimension 2 User journey, both of which can be
186
+ pre-populated from `mockup_analysis`).
77
187
 
78
188
  ## Step 2 — Discovery Question Loop
79
189
 
@@ -171,6 +281,16 @@ section of the state file. Mark dimension as covered.
171
281
  the Change Request flow. After it completes, resume discovery from the
172
282
  next uncovered dimension.
173
283
  - If user says out-of-scope: note in Discovery Log and continue.
284
+ - **New-Screen Check** (only when `mockups.status` ∈ {`provided`, `partial`}):
285
+ When the user's answer reveals a UI screen NOT present in
286
+ `mockup_analysis.screens[]`, do NOT treat it as a scope expansion. Instead,
287
+ append the screen to `screens_in_scope[]` in the state file with
288
+ `covered_by_mockups: false`. Log inline:
289
+ `Ho rilevato una nuova schermata non presente nei mockup: **<name>**. La
290
+ genero in Step 3 (modalità ibrida) solo per quella schermata.`
291
+ Continue with the next dimension. This is a routine signal for Step 3, not
292
+ a scope expansion — the Scope Expansion Check above still applies for
293
+ non-UI entities (endpoints, roles, collections).
174
294
  - Update state file
175
295
  - Proceed to next uncovered dimension (back to action 1)
176
296
 
@@ -274,30 +394,41 @@ Instead, run the E2E Evaluation Decision Tree and present the result.
274
394
  **When E2E is REQUIRED or user accepts RECOMMENDED:**
275
395
 
276
396
  1. Identify test scenarios from user stories and acceptance criteria (2-5 scenarios max).
277
- 2. Determine test persona:
278
-
279
- **Consumer feature** (target users include CUSTOMER):
280
- - Auto-set credentials: `phone: 3486417303, auth: OTP (manual input by user during test)`
281
- - Inform user: `Credenziali test consumer: 3486417303 (OTP manuale durante il test).`
282
- - No question needed.
283
-
284
- **Merchant feature** (target users include MERCHANT or MERCHANT_STAFF):
285
- - ASK the user:
286
- ```
287
- ### Domanda Credenziali test merchant
288
-
289
- Questa feature richiede test E2E come merchant.
290
- Su quale merchant e store vuoi testare?
291
- Servono le credenziali di login (username/password).
292
-
293
- Esempio: antonio.baldassarre2336 / bRkS2bzqyesK su store "Bar Roma"
294
- ```
295
- - **STOP.** Wait for user response. Store credentials in state file under `## Test Plan`.
296
-
297
- **Super Admin feature** (target users include SUPER_ADMIN):
298
- - ASK the user for admin credentials (same pattern as merchant).
299
-
300
- **Mixed personas**: gather credentials for each persona that needs E2E.
397
+ 2. **Determine test personas** by intersecting:
398
+ - The user-stories' `As a <persona>` field, and
399
+ - `identity.audience_segments[]` from `baldart.config.yml` (single source of truth
400
+ for the project's personas NEVER hardcode persona names in the skill).
401
+
402
+ For each persona that needs E2E coverage, gather credentials using the following
403
+ resolution order:
404
+
405
+ **a. Consult `.baldart/overlays/prd.md`** (if present) for a `## Test Credentials`
406
+ section. If the overlay defines a default credential pattern for the persona
407
+ (e.g. `customer phone OTP`, `merchant → username/password`), use it and
408
+ log inline: `Credenziali test {{persona}}: caricate da overlay.`
409
+ Do NOT print the actual credential values inline — only confirm the source.
410
+
411
+ **b. Otherwise ASK the user**, ONE question per persona:
412
+ ```
413
+ ### Domanda Credenziali test {{persona}}
414
+
415
+ Questa feature richiede test E2E con la persona **{{persona}}**.
416
+ Fornisci le credenziali di test (o un riferimento all'ambiente di test):
417
+
418
+ - Metodo di auth: <es. password / OTP via SMS / magic link / API token>
419
+ - Identificativo: <es. username, email, phone>
420
+ - Secret: <password, OTP source, token meglio NON incollarlo in chat,
421
+ usa un riferimento al vault>
422
+ - Contesto (se rilevante): <es. tenant, workspace, store, organization>
423
+ ```
424
+ **STOP.** Wait for user response. Store the *minimum-necessary* credential
425
+ reference in the state file under `## Test Plan` — prefer a reference to a
426
+ secret manager / 1Password / `.env.test` path over the literal secret.
427
+
428
+ Suggerisci all'utente di consolidare la risposta in `.baldart/overlays/prd.md`
429
+ (sezione `## Test Credentials`) per evitare la stessa domanda ai PRD futuri.
430
+
431
+ **c. Mixed personas:** ripeti b. per ciascuna persona non risolta da a.
301
432
 
302
433
  3. After credentials are gathered, summarize the test plan:
303
434
  ```
@@ -305,8 +436,8 @@ Instead, run the E2E Evaluation Decision Tree and present the result.
305
436
 
306
437
  E2E: REQUIRED | RECOMMENDED (accettato)
307
438
  Scenari: N test scenarios
308
- Persona: [Consumer | Merchant | Super Admin | Mixed]
309
- Credenziali: [summary]
439
+ Personas coinvolte: <list from identity.audience_segments[] involved>
440
+ Sorgente credenziali: [overlay | user-provided | mixed]
310
441
 
311
442
  Scenari pianificati:
312
443
  1. [scenario description — maps to US-X / AC-X]
@@ -315,6 +446,11 @@ Instead, run the E2E Evaluation Decision Tree and present the result.
315
446
 
316
447
  4. Mark dimension as covered. Update state file `## Test Plan` section.
317
448
 
449
+ > **Security note:** the framework MUST NOT contain any real test credential
450
+ > (phone numbers, usernames, passwords, tokens). All credential examples in this
451
+ > file are intentionally generic. Project-specific defaults live in
452
+ > `.baldart/overlays/prd.md` (consumer-owned, not redistributed).
453
+
318
454
  ### Research Trigger (evaluated at ~75% comprehension)
319
455
 
320
456
  When 6+ non-test dimensions are covered, evaluate complexity signals from
@@ -357,3 +493,53 @@ Passo alla fase successiva: [UI Design / Scrittura PRD]
357
493
 
358
494
  <Progress Bar>
359
495
  ```
496
+
497
+ ---
498
+
499
+ ## Appendix — Mockup analysis schema
500
+
501
+ Used by Step 1.6.5. Populate the `## UI Design` section of the state file with this
502
+ structure. Be specific — vague analysis defeats the purpose of skipping Step 3.
503
+
504
+ ```yaml
505
+ mockups:
506
+ status: provided | partial | none | requested
507
+ format: chat-images | local-paths | mixed
508
+ original_paths:
509
+ - <user-provided path or chat://image-N>
510
+ canonical_paths:
511
+ - mockups/<file>.png # only for local-paths
512
+ mockup_analysis:
513
+ screens:
514
+ - name: <inferred name, e.g. "Lista ordini">
515
+ mockup_ref: <canonical_path or chat://image-N>
516
+ purpose: <one line — what this screen lets the user do>
517
+ components:
518
+ - <component name from ${paths.design_system}/INDEX.md if matched, else free-form>
519
+ states_visible: [empty, loading, error, success, default]
520
+ copy_excerpts:
521
+ - <verbatim text visible in the mockup, max ~10 strings per screen>
522
+ gaps:
523
+ - <ambiguity to clarify in Discovery, e.g. "filtro per data: range o singola?">
524
+ user_flow:
525
+ - <step 1, e.g. "Utente apre Lista ordini → tap su riga → Dettaglio ordine">
526
+ design_system_alignment:
527
+ status: aligned | violations | not-applicable
528
+ violations:
529
+ - mockup: <screen name>
530
+ kind: hardcoded-color | hardcoded-spacing | hardcoded-shadow | hardcoded-radius | custom-component
531
+ detail: <e.g. "background #FF6A00 — token equivalent: --color-brand-primary">
532
+ fix_in_step_3: <token name or component to swap in>
533
+ ```
534
+
535
+ **When NOT to fill a field:**
536
+ - Omit `design_system_alignment` entirely (do NOT write `not-applicable`) when
537
+ `features.has_design_system: false` — the field becomes irrelevant.
538
+ - Omit `copy_excerpts` for screens that have no readable text (icon-only).
539
+ - Omit `states_visible` for screens that show only the default state — do not
540
+ invent states the mockup doesn't show.
541
+
542
+ **Gap discipline:** every entry in `gaps[]` MUST become either a Discovery question
543
+ or an explicit non-question (recorded in Discovery Log as "skipped — outside
544
+ mockup scope"). Gaps that remain unresolved by the end of Discovery block PRD
545
+ writing in Step 4.
@@ -17,6 +17,11 @@ Mark task 3 as `in_progress`.
17
17
  - Read `docs/guides/linking-protocol-rollout-v1.md` for the Canonical Ownership Matrix.
18
18
  - Identify which existing PRDs, ADRs, reference docs, or backlog cards are canonical
19
19
  for this feature area.
20
+ - **Mockup-derived canonical sources** (when `mockups.status` ∈ {`provided`, `partial`}
21
+ in state file): treat `${paths.prd_dir}/<slug>/mockups/` as a canonical visual
22
+ reference. Add a row to the PRD Canonical Sources table:
23
+ `| Mockup originali | ${paths.prd_dir}/<slug>/mockups/ |`. If chat images were
24
+ analyzed without being copied to disk, add: `| Mockup chat | inline in PRD session — see Design Reference section |`.
20
25
  3. **Incorporate research findings** (if `## Research Findings` in state file is populated):
21
26
  - Reference best practices in data model, API, and architecture decisions.
22
27
  - Cite sources in PRD rationale sections.
@@ -24,42 +29,65 @@ Mark task 3 as `in_progress`.
24
29
  - If regulatory findings exist: add a dedicated "Compliance Requirements" section.
25
30
  - Include a "Research-Informed Decisions" subsection listing decisions influenced
26
31
  by research, with brief rationale and source reference.
27
- 3.5. **Schema Verification Gate (MANDATORY if feature touches Firestore)**
32
+ 3.5. **Schema Verification Gate (MANDATORY if feature touches the persistence layer)**
28
33
 
29
- If any of the following apply: new Firestore collection, modified fields, compound queries,
30
- or reading/writing existing documents run this gate before writing Section 3 (Data Model).
34
+ Read `stack.database` from `baldart.config.yml`. If empty AND the feature
35
+ description mentions data persistence, ASK the user which database is in
36
+ use and persist the answer to `baldart.config.yml` (offer `npx baldart
37
+ configure` if multiple keys are missing). Skip this gate when
38
+ `stack.database: none` or the feature is stateless.
39
+
40
+ The vocabulary in this gate adapts to `stack.database`:
41
+ - Firestore / MongoDB / DynamoDB → "collections" / "documents" / "fields"
42
+ - Postgres / Supabase / MySQL / SQLite → "tables" / "rows" / "columns"
43
+ The procedure below uses **{entity}** = collection|table and **{field}** =
44
+ field|column.
45
+
46
+ If any of the following apply: new {entity}, modified {field}s, compound
47
+ queries, or reading/writing existing rows/documents — run this gate before
48
+ writing Section 5 (Data Model).
31
49
 
32
50
  **Procedure:**
33
- 1. Identify every collection the feature uses or modifies.
34
- 2. For each collection: read `${paths.references_dir}/field-registry.json` find the collection key.
51
+ 1. Identify every {entity} the feature uses or modifies.
52
+ 2. For each {entity}: read the project schema registry. The path is
53
+ project-specific — common locations: `${paths.references_dir}/field-registry.json`
54
+ (Firestore-style projects), `${paths.references_dir}/schema.md` (SQL),
55
+ `${paths.references_dir}/collections/*.md` (per-collection markdown), or
56
+ the migrations dir for SQL projects (`migrations/`, `db/migrate/`,
57
+ `prisma/schema.prisma`, `supabase/migrations/`). Resolution order: check
58
+ `.baldart/overlays/prd.md § Schema Registry` first if defined; otherwise
59
+ pick the convention matching `stack.database`.
35
60
  3. Build a `## Schema Verification` section in the PRD (see template below).
36
- 4. Mark each field: `✅ existing` | `🆕 new` | `❌ NOT FOUND`.
37
- 5. **GATE**: if ANY field is `❌ NOT FOUND` and NOT marked as `🆕 new`:
61
+ 4. Mark each {field}: `✅ existing` | `🆕 new` | `❌ NOT FOUND`.
62
+ 5. **GATE**: if ANY {field} is `❌ NOT FOUND` and NOT marked as `🆕 new`:
38
63
  - STOP — do not advance to Section 5 (backlog cards).
39
- - Ask the user: "Is `fieldName` in collection `collectionName` a new field or a naming error?"
40
- - If new: add full schema definition in PRD Section 3 and mark `🆕`.
64
+ - Ask the user: "Is `{fieldName}` in {entity} `{entityName}` a new {field} or a naming error?"
65
+ - If new: add full schema definition in PRD Section 5 and mark `🆕`.
41
66
  - If error: correct the name.
42
67
 
43
68
  **Template `## Schema Verification`** (insert after PRD Acceptance Criteria section):
44
69
 
45
70
  ```markdown
46
71
  ## Schema Verification
47
- > Source: field-registry.jsonverificato il {YYYY-MM-DD}
48
- > Complessità stimata: HIGH | MEDIUM | LOW
72
+ > Source: {schema-registry-path}verified on {YYYY-MM-DD}
73
+ > Database: {stack.database}
74
+ > Complexity: HIGH | MEDIUM | LOW
49
75
 
50
- ### Collection: {collectionName}
76
+ ### {entity}: {entityName}
51
77
 
52
- | Field | Type | Status | Note |
53
- |-------|------|--------|------|
78
+ | {field} | Type | Status | Note |
79
+ |---------|------|--------|------|
54
80
  | `fieldName` | string | ✅ existing | — |
55
- | `newField` | string | 🆕 new | schema in Section 3 |
56
- | `~~oldField~~` | — | ❌ NOT FOUND | correggi nome |
81
+ | `newField` | string | 🆕 new | schema in Section 5 |
82
+ | `~~oldField~~` | — | ❌ NOT FOUND | rename mismatch |
57
83
 
58
- ### Blocchi aperti
59
- - (nessuno) — oppure lista deicon azione richiesta
84
+ ### Open issues
85
+ - (none) — or list ofwith required action
60
86
  ```
61
87
 
62
- **Nota**: `id`, `createdAt`, `updatedAt` sono universali — non richiedono verifica.
88
+ **Universal fields:** auto-PK/ID, `createdAt`/`created_at`,
89
+ `updatedAt`/`updated_at` are universal in their stack — do not require
90
+ verification.
63
91
 
64
92
  4. Write `docs/prd/<slug>/PRD.md` using the template from `assets/prd-template.md`.
65
93
 
@@ -72,13 +100,27 @@ Every PRD MUST include these sections (remove only when genuinely N/A):
72
100
  - Goals / non-goals
73
101
  - Personas
74
102
  - User stories
75
- - Data model (TypeScript interfaces, Firestore schema changes, validation rules, **Firestore Composite Indexes table** — MANDATORY if any compound query exists)
103
+ - Data model (type definitions matching the language stack, persistence-layer
104
+ schema changes, validation rules, **Database Indexes & Query Optimization
105
+ table** — MANDATORY if any compound query / multi-column index exists. Pick
106
+ the variant matching `stack.database`: Firestore Composite, Postgres B-tree,
107
+ MongoDB compound, DynamoDB GSI/LSI. See `assets/prd-template.md § 5`.)
76
108
  - API contract changes (endpoints, request/response, validation)
109
+ - **Design Reference & Mockup Inventory** (if UI impact ≠ N/A — populate from
110
+ `mockups.*`, `mockup_analysis.*`, `step_3_mode`, and `screens_in_scope[]` in
111
+ the state file. Include the screen inventory table, the component mapping
112
+ table when `features.has_design_system: true`, and the source-files
113
+ traceability list. When `mockups.status: none`, the section is still present
114
+ with the table empty and a note "Design generato in Step 3 — vedi design.html".)
77
115
  - UI specifications (if applicable — MUST derive from `## UI Element Inventory` in
78
- state file; include the full inventory table verbatim, reference `design.html` path,
79
- and map each UI element to the requirement it satisfies)
116
+ state file; include the full inventory table verbatim, reference `design.html` path
117
+ OR `mockups/` directory when `step_3_mode: skipped`, and map each UI element to
118
+ the requirement it satisfies. Do NOT duplicate the screen list from the Design
119
+ Reference section above — link to it.)
80
120
  - i18n specification (dictionary keys, locale files)
81
- - Acceptance criteria (grouped by area: Merchant, Customer, API, i18n)
121
+ - Acceptance criteria (grouped by area: one group per persona drawn from
122
+ `identity.audience_segments[]`, plus cross-cutting groups: API, i18n,
123
+ Observability if relevant)
82
124
  - Edge cases and failure modes (table format)
83
125
  - Out of scope
84
126
  - Dependencies (table with type and status)
@@ -42,9 +42,21 @@ Scan discovery answers and codebase-architect findings for these signals:
42
42
  Trigger as soon as confidence is HIGH (typically at ~75% comprehension).
43
43
 
44
44
  1. **Identify research topics** from the matching signals. Formulate 1-3
45
- specific research questions. Examples:
46
- - S1: "Best practices for implementing [pattern] in a Next.js/Firestore stack"
47
- - S2: "Regulatory requirements for [topic] in Italy/EU, implementation checklist"
45
+ specific research questions. Build the stack signature dynamically from
46
+ `baldart.config.yml`:
47
+
48
+ ```
49
+ stack_signature = "{{stack.framework}} + {{stack.database}} + {{stack.auth_provider}}"
50
+ # Examples it might resolve to:
51
+ # "nextjs + firestore + firebase-auth"
52
+ # "remix + supabase + supabase-auth"
53
+ # "sveltekit + postgres + lucia"
54
+ # If any segment is empty, omit it from the signature.
55
+ ```
56
+
57
+ Examples of research questions (substitute {stack_signature} at runtime):
58
+ - S1: "Best practices for implementing [pattern] on a {stack_signature} stack"
59
+ - S2: "Regulatory requirements for [topic] in {{identity.language country}}, implementation checklist"
48
60
  - S3: "Integration patterns for [service], comparison of approaches, gotchas"
49
61
  - S4: "UX best practices for [pattern], accessibility considerations, mobile"
50
62
  - S6: "Trade-offs of [approach A] vs [approach B] for [use case]"
@@ -58,13 +70,19 @@ Trigger as soon as confidence is HIGH (typically at ~75% comprehension).
58
70
  prompt: "Research the following topics for a PRD we're writing for feature
59
71
  '<slug>'. Context: <1-2 line feature summary>.
60
72
 
73
+ Project stack (from baldart.config.yml):
74
+ - framework: {{stack.framework or 'unspecified'}}
75
+ - database: {{stack.database or 'unspecified'}}
76
+ - auth_provider: {{stack.auth_provider or 'unspecified'}}
77
+ - deployment: {{stack.deployment or 'unspecified'}}
78
+
61
79
  Research questions:
62
80
  1. <question>
63
81
  2. <question>
64
82
 
65
83
  For each topic, provide:
66
84
  - Summary of best practices (with sources)
67
- - Recommended approach for our stack (Next.js 16, Firestore, Firebase Auth)
85
+ - Recommended approach for the project stack above
68
86
  - Key gotchas or anti-patterns to avoid
69
87
  - If applicable: regulatory checklist or compliance requirements
70
88
 
@@ -1,8 +1,18 @@
1
1
  # UI Design Phase (Step 3)
2
2
 
3
- Skip entirely if UI impact dimension is N/A. Proceed to PRD Writing Phase.
3
+ ## Precondition decision tree
4
4
 
5
- Mark task 2 as `in_progress`.
5
+ Read `mockups.status` and `screens_in_scope[]` from the state file `## UI Design`
6
+ section (populated by Step 1.6) plus the UI impact dimension from the discovery
7
+ checklist. Pick exactly one branch:
8
+
9
+ | Condition | Branch | Action |
10
+ |-----------|--------|--------|
11
+ | UI impact = N/A | **Skip totale** | Mark task 2 `completed` ("Skipped — no UI"). `step_3_mode: skipped`. Proceed to PRD Writing Phase. |
12
+ | `mockups.status: none` AND UI impact ≠ N/A | **Full** | Run the standard pipeline 3a → 3b → 3c → 3d as before. `step_3_mode: full`. |
13
+ | `mockups.status` ∈ {`provided`, `partial`} AND UI impact ≠ N/A | **Hybrid** | Per-screen routing (see § Hybrid mode below). `step_3_mode: hybrid` (or `skipped` if every screen is covered AND no `mockup_analysis.design_system_alignment.violations`). |
14
+
15
+ Mark task 2 as `in_progress` for the Full and Hybrid branches.
6
16
 
7
17
  ## Delegation to `ui-design` Skill
8
18
 
@@ -50,7 +60,7 @@ MISSING — no match found:
50
60
 
51
61
  This prevents designing new components when 450+ reusable ones already exist.
52
62
 
53
- ### Gates (same as before)
63
+ ### Gates (Full branch)
54
64
 
55
65
  - **After Step 3b:** all 3 polished options open in Safari AND screenshots shown inline.
56
66
  **STOP.** Wait for user to choose.
@@ -59,3 +69,105 @@ This prevents designing new components when 450+ reusable ones already exist.
59
69
  is populated in the state file with at least 3 elements.
60
70
 
61
71
  Mark task 2 as `completed`. Update state file status to `specs-confirmed`.
72
+
73
+ ---
74
+
75
+ ## Hybrid mode (Step 1.6 produced mockups)
76
+
77
+ Triggered when `mockups.status` ∈ {`provided`, `partial`}. The principle: the user
78
+ has already done the design work for some screens — don't redo it. Validate, align
79
+ to the design system, approve, and inventory. Generate ONLY the screens not covered.
80
+
81
+ ### Build the per-screen routing table
82
+
83
+ 1. Construct `screens_in_scope[]` by merging:
84
+ - User Stories from the state file (one row per US that implies a screen).
85
+ - ISA `NAVIGATION` and `DASHBOARD` touchpoints that imply landing screens.
86
+ - The `mockup_analysis.screens[]` list itself (in case the mockups include
87
+ screens the user stories didn't make explicit).
88
+ 2. For each entry, set `covered_by_mockups: true` iff the screen matches a
89
+ `mockup_analysis.screens[].name` (case-insensitive substring match is fine —
90
+ when ambiguous, ASK the user "questa schermata `<X>` corrisponde al mockup
91
+ `<Y>`?" and STOP).
92
+ 3. Persist `screens_in_scope[]` in the state file `## UI Design` section.
93
+
94
+ ### Per-screen execution
95
+
96
+ | `covered_by_mockups` | What runs | Notes |
97
+ |----------------------|-----------|-------|
98
+ | `true` | Component Registry Lookup (adapted) + 3c (approval gate) + 3d (save & inventory) | SKIP 3a (options) and 3b (generation). Use the provided mockup as the canonical reference. |
99
+ | `false` | Subskill `ui-design` 3a + 3b SCOPED TO THIS SCREEN, then 3c + 3d | Pass the screen name + relevant discovery answers + context-primer output. Mockups for OTHER screens already approved are passed as "existing design language to match" so the new screen looks consistent. |
100
+
101
+ ### Step 3 sub-flow in Hybrid mode
102
+
103
+ 1. **Component Registry Lookup (all screens, before any generation).**
104
+ For each screen — covered OR new — match `mockup_analysis.screens[].components[]`
105
+ (covered) or the inferred component list (new) against
106
+ `${paths.references_dir}/component-registry.md` and, when
107
+ `features.has_design_system: true`, against `${paths.design_system}/INDEX.md`.
108
+ - For covered screens: any component used in a mockup but NOT in the registry
109
+ becomes either (a) a REUSE recommendation if a close match exists, or (b) a
110
+ candidate new primitive — flag in `mockup_analysis.design_system_alignment`.
111
+ - For new screens: passed to `ui-design` as the REUSE list (prevents the
112
+ subskill from inventing new components).
113
+ 2. **Generation pass (new screens only).**
114
+ For each new screen, invoke `Skill(ui-design)` with payload:
115
+ ```
116
+ feature_slug: <slug>
117
+ scope: single-screen
118
+ screen_name: <X>
119
+ discovery_excerpt: <answers relevant to this screen>
120
+ reuse_components: <list from registry lookup>
121
+ design_language_anchor: mockups/<existing-mockup-1>.png, mockups/<existing-mockup-2>.png
122
+ ```
123
+ The subskill produces 3 options for that one screen (its standard 3b output).
124
+ Open in Safari, **STOP**, wait for user to choose.
125
+ 3. **Approval gate (all screens, 3c).**
126
+ Present in ONE message:
127
+ - Thumbnail + path for each `covered_by_mockups: true` screen.
128
+ - The user-chosen option for each `generated_in_step_3b: true` screen.
129
+ - All `design_system_alignment.violations[]` consolidated into a "Issues da
130
+ risolvere prima di Step 4" list with the proposed token/component swap.
131
+ Ask explicit confirmation ("confermo", "va bene", "ok"). **STOP.**
132
+ 4. **Save & Inventory (all screens, 3d).**
133
+ - For covered screens: copy `mockups/<file>.png` references into the unified
134
+ UI Element Inventory; no `design.html` regeneration needed unless the subskill
135
+ also ran. If at least one new screen was generated, the merged `design.html`
136
+ includes both the new mockups and embeds/links to the existing ones.
137
+ - For all-covered runs (`generated_in_step_3b: false` everywhere): set
138
+ `design.html_path: n/a (mockup-only)` in the state file; the PRD will link
139
+ directly to `${paths.prd_dir}/<slug>/mockups/`.
140
+ - Update `## UI Element Inventory` in the state file with at least one row per
141
+ covered screen + per generated screen.
142
+
143
+ ### Hybrid gates
144
+
145
+ - **After per-screen 3b (only if any new screen exists):** all 3 polished options
146
+ per new screen open in Safari AND screenshots shown inline. **STOP.** Wait for
147
+ user choice.
148
+ - **After 3c (approval):** explicit user approval AND every entry in
149
+ `design_system_alignment.violations[]` is either resolved (token/component
150
+ swapped in the inventory) or explicitly waived by the user (logged as such).
151
+ - **After 3d:** UI Element Inventory populated with at least one row per screen in
152
+ `screens_in_scope[]`. `design.html_path` set OR `mockup-only` flag recorded.
153
+
154
+ Mark task 2 as `completed`. Update state file status to `specs-confirmed`.
155
+
156
+ ### Canonical example
157
+
158
+ Feature with 5 screens (`Lista ordini`, `Dettaglio ordine`, `Filtri`, `Onboarding`,
159
+ `Stato pagamento`). Mockups provided for 3 of them.
160
+
161
+ ```
162
+ screens_in_scope:
163
+ - { name: "Lista ordini", covered_by_mockups: true, generated_in_step_3b: false }
164
+ - { name: "Dettaglio ordine", covered_by_mockups: true, generated_in_step_3b: false }
165
+ - { name: "Filtri", covered_by_mockups: true, generated_in_step_3b: false }
166
+ - { name: "Onboarding", covered_by_mockups: false, generated_in_step_3b: true }
167
+ - { name: "Stato pagamento", covered_by_mockups: false, generated_in_step_3b: true }
168
+ ```
169
+
170
+ Result: `ui-design` subskill runs TWICE (one invocation per new screen, each
171
+ producing 3 options). The 3 covered screens skip 3a/3b entirely. The final approval
172
+ gate presents all 5 screens together. `step_3_mode: hybrid`. The PRD links to
173
+ `mockups/` for the 3 covered + `design.html` for the 2 new.
@@ -6,6 +6,26 @@
6
6
 
7
7
  Mark task 5 as `in_progress`.
8
8
 
9
+ 0. **Agent Specialization Audit (runs FIRST — blocks if any failure)** — for each generated child card (epics are skipped):
10
+
11
+ a. **`owner_agent` enum check (BLOCKING)** — read the `owner_agent` field. It MUST equal one of:
12
+ ```
13
+ coder | ui-expert | plan | visual-designer | motion-expert
14
+ ```
15
+ Empty string, missing field, `claude`, or any other value = **BLOCKER**.
16
+ Message to the user: `"Card <ID> has owner_agent: '<value>' — must be one of {coder, ui-expert, plan, visual-designer, motion-expert}. Fix the card YAML before commit."`
17
+ Halt the audit. No subsequent checks run on a card that fails this gate.
18
+
19
+ b. **UI-only scope heuristic (WARN — soft gate, not blocking)** — for each card with `owner_agent: ui-expert`:
20
+ - Concatenate `scope.summary`, `requirements[]`, and `acceptance_criteria[]` into one lowercase string.
21
+ - Grep for logic-marker substrings: `api call`, `endpoint`, `route handler`, `state machine`, `validation logic`, `business rule`, `database`, `migration`, `prisma`, `firestore.collection`, `auth flow`, `token storage`, `webhook`, `cron`.
22
+ - For each marker hit, log a WARN line in the audit output:
23
+ `"[UI-SCOPE-WARN] Card <ID> (ui-expert) mentions '<marker>' — review whether logic belongs in a sibling coder card. See backlog-phase.md § Rule B."`
24
+ - The check is intentionally a soft gate: substrings like "API contract per il mock" or "consumes the auth state from `useAuth()`" are legitimate UI references. The WARN exists to prompt human review, not to block.
25
+ - Exception (no WARN): the marker appears INSIDE a quoted string that explicitly says "consume", "mock", "contract reference", or "exposed by sibling card" — those are UI cards reading an upstream contract, which is expected.
26
+
27
+ **Gate**: every card has `owner_agent` in the enum. WARN entries from check (b) are noted in the audit log; user may accept them after review.
28
+
9
29
  1. **Field Name Audit (runs BEFORE audit agents)** — for each generated card:
10
30
 
11
31
  a. Verify every `data_fields` entry has `ts_verified: true` OR `status: new` with `schema_ref`.
@@ -16,8 +36,8 @@ Mark task 5 as `in_progress`.
16
36
  definition (type, nullable, default, indexing notes).
17
37
  c. For cards with `estimated_complexity: LOW`:
18
38
  - Verify only that `data_fields` has `ts_verified: true` or `status: new`. No grep needed.
19
- d. If card has `firestore_indexes` but NO `data_fields`: log warning —
20
- "card touches Firestore (firestore_indexes present) but missing data_fields block."
39
+ d. If card has `db_indexes` (or legacy `firestore_indexes`) but NO `data_fields`: log warning —
40
+ "card touches the persistence layer (db_indexes present) but missing data_fields block."
21
41
 
22
42
  **Gate**: no field with `status: existing | modified` and `ts_verified: false` can proceed.
23
43