baldart 3.14.0 → 3.15.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 (26) hide show
  1. package/CHANGELOG.md +70 -15
  2. package/VERSION +1 -1
  3. package/framework/.claude/agents/api-perf-cost-auditor.md +47 -10
  4. package/framework/.claude/agents/coder.md +61 -10
  5. package/framework/.claude/agents/prd-card-writer.md +29 -19
  6. package/framework/.claude/agents/security-reviewer.md +1 -1
  7. package/framework/.claude/skills/bug/references/logging-patterns.md +45 -8
  8. package/framework/.claude/skills/new/SKILL.md +180 -86
  9. package/framework/.claude/skills/prd/SKILL.md +30 -2
  10. package/framework/.claude/skills/prd/assets/card-template.yml +43 -26
  11. package/framework/.claude/skills/prd/assets/epic-template.yml +3 -2
  12. package/framework/.claude/skills/prd/assets/prd-template.md +90 -14
  13. package/framework/.claude/skills/prd/assets/state-template.md +18 -0
  14. package/framework/.claude/skills/prd/references/api-perf-gate.md +102 -52
  15. package/framework/.claude/skills/prd/references/audit-phase.md +13 -13
  16. package/framework/.claude/skills/prd/references/discovery-phase.md +214 -28
  17. package/framework/.claude/skills/prd/references/prd-writing-phase.md +65 -23
  18. package/framework/.claude/skills/prd/references/research-phase.md +22 -4
  19. package/framework/.claude/skills/prd/references/ui-design-phase.md +115 -3
  20. package/framework/.claude/skills/prd/references/validation-phase.md +2 -2
  21. package/framework/docs/PROJECT-CONFIGURATION.md +41 -1
  22. package/framework/templates/baldart.config.template.yml +25 -0
  23. package/package.json +1 -1
  24. package/src/commands/configure.js +72 -0
  25. package/src/commands/update.js +13 -1
  26. package/src/utils/git.js +6 -1
@@ -108,7 +108,7 @@ Main repo: [/absolute/path/to/main/repo]
108
108
 
109
109
  1c. **Field Registry Validation (pre-flight gate)** — for each card with a `data_fields` block, run the project's field-validation tool if available (path listed in `.baldart/overlays/new.md`; typically `python3 tools/validate-card-fields.py <card-yaml-path>`).
110
110
  - If exit 1: display the field errors in `## Issues & Flags` and HALT — ask the user to fix the card before proceeding. Do not start implementation until the card passes validation.
111
- - If the card has DB-index signals (e.g. `firestore_indexes`, `data.collections`) but NO `data_fields` block: log WARNING in `## Issues & Flags` — "Card `<ID>` touches storage but has no `data_fields` block. Field names are unvalidated."
111
+ - If the card has DB-index signals (`db_indexes` — or legacy `firestore_indexes` — or `data.collections`/`data.tables`) but NO `data_fields` block: log WARNING in `## Issues & Flags` — "Card `<ID>` touches the persistence layer but has no `data_fields` block. Field/column names are unvalidated."
112
112
  - Cards with no `data_fields` and no storage signals: skip silently.
113
113
  - If the project does not ship a field-validation tool: skip this step.
114
114
  2. Check `${paths.references_dir}/project-status.md` for current state (skip when absent).
@@ -173,8 +173,9 @@ Main repo: [/absolute/path/to/main/repo]
173
173
  requirements assume stays unchanged? Flag missing depends_on.
174
174
  3. EXECUTION ORDER RISKS: Given the parallel_group assignments, will parallel
175
175
  execution cause merge conflicts or type errors?
176
- 4. SHARED STATE MUTATIONS: Do multiple cards write to the same Firestore
177
- collection/document in ways that could conflict at runtime?
176
+ 4. SHARED STATE MUTATIONS: Do multiple cards write to the same persistence
177
+ {entity} ({collection|table|item} per `stack.database`) in ways that could
178
+ conflict at runtime?
178
179
 
179
180
  For each finding return:
180
181
  - **Cards involved**: CARD-A + CARD-B
@@ -218,7 +219,7 @@ Before Phase 3.5, determine the QA profile for each card by reading its YAML met
218
219
  | **SKIP** | Card type is `docs`, `chore`, or `config` — OR all changed paths are `.md`/`.yml` (non-API)/CSS with zero logic files — OR title contains only cosmetic keywords (typo, rename, copy, wording, style) with no code areas |
219
220
  | **LIGHT** | Card type is `bugfix` OR `refactor` — AND ≤3 files likely touched — AND no HIGH-risk keywords in paths/areas/title. **NEVER applies to `feature` or `enhancement` cards.** |
220
221
  | **BALANCED** | Default for ALL `feature` / `enhancement` cards not matching DEEP rules — OR `bugfix`/`refactor` with >3 files or HIGH-risk keywords |
221
- | **DEEP** | ANY of: areas includes both `api` + `data` — OR paths/title contain `auth`, `payment`, `permission`, `schema`, `migration`, `cron`, `webhook`, `transaction` — OR >15 files likely touched — OR acceptance criteria count > 5 — OR Firestore indexes changed — OR API contract changed — OR `data_fields` block has ≥3 entries with `status: new` or `status: modified` |
222
+ | **DEEP** | ANY of: areas includes both `api` + `data` — OR paths/title contain `auth`, `payment`, `permission`, `schema`, `migration`, `cron`, `webhook`, `transaction` — OR >15 files likely touched — OR acceptance criteria count > 5 — OR DB indexes changed (`db_indexes` block present, or legacy `firestore_indexes`) — OR API contract changed — OR `data_fields` block has ≥3 entries with `status: new` or `status: modified` |
222
223
 
223
224
  **Critical**: `feature` and `enhancement` cards are ALWAYS BALANCED minimum — never LIGHT. The `files_likely_touched` field in YAML underestimates actual scope; ignore it for profile decisions on feature cards. When in doubt between BALANCED and DEEP, use DEEP.
224
225
 
@@ -306,29 +307,46 @@ For each card, execute these phases in order:
306
307
  - Do NOT add unrequested features or extra error handling beyond what's specified
307
308
  - Do NOT modify test files unless the card explicitly requires it
308
309
 
309
- ### Firestore Composite Indexes (if card has `firestore_indexes` field)
310
- This card requires the following composite indexes in `firestore.indexes.json`.
311
- You MUST add these in the SAME commit as the query code. Missing indexes cause
312
- runtime FAILED_PRECONDITION errors (500 in production).
313
-
314
- [paste firestore_indexes entries from card YAML, formatted as:]
315
- | Collection | Fields | Query Location | PRD Ref |
316
- |-----------|--------|----------------|---------|
317
- | [collection] | [field1 ASC, field2 DESC] | [file path] | [IDX-N] |
318
-
319
- For each index, add the corresponding entry to `firestore.indexes.json` under
320
- `indexes[]` with this format:
321
- ```json
322
- {
323
- "collectionGroup": "<collection>",
324
- "queryScope": "COLLECTION",
325
- "fields": [
326
- { "fieldPath": "<field1>", "order": "ASCENDING" },
327
- { "fieldPath": "<field2>", "order": "DESCENDING" }
328
- ]
329
- }
330
- ```
331
- Include `firestore.indexes.json` in your staged files.
310
+ ### Database Indexes (if card has `db_indexes` — or legacy `firestore_indexes` field)
311
+ This card requires the following indexes shipped in the SAME commit as the query
312
+ code. Missing indexes degrade performance or break production (variant per
313
+ `stack.database` see `framework/.claude/agents/coder.md § Database Index Invariant`).
314
+
315
+ [paste db_indexes entries from card YAML, formatted as:]
316
+ | Entity | Dialect | Fields | Kind | Query Location | PRD Ref |
317
+ |--------|---------|--------|------|----------------|---------|
318
+ | [entity] | [stack.database] | [field1 ASC, field2 DESC] | [composite/covering/GIN/GSI] | [file path] | [IDX-N] |
319
+
320
+ **Where to ship the index pick the artifact matching `stack.database`:**
321
+
322
+ - `firestore` → append to `firestore.indexes.json` under `indexes[]`:
323
+ ```json
324
+ {
325
+ "collectionGroup": "<entity>",
326
+ "queryScope": "COLLECTION",
327
+ "fields": [
328
+ { "fieldPath": "<field1>", "order": "ASCENDING" },
329
+ { "fieldPath": "<field2>", "order": "DESCENDING" }
330
+ ]
331
+ }
332
+ ```
333
+ Stage `firestore.indexes.json` together with the query code.
334
+ - `postgres` / `supabase` / `mysql` / `sqlite` → add a migration file under the
335
+ project's migrations dir (`migrations/`, `db/migrate/`, `supabase/migrations/`,
336
+ `prisma/migrations/` per project convention) with `CREATE INDEX ...` or the
337
+ Prisma `@@index([...])` directive. For Supabase, RLS policies live in the same
338
+ migration when relevant.
339
+ - `mongodb` → add `db.<entity>.createIndex(...)` to the project's index-bootstrap
340
+ script (path declared in `.baldart/overlays/new.md § Schema Bootstrap`), or run
341
+ it as part of the migration command.
342
+ - `dynamodb` → update the table definition in the project's IaC (CDK / Terraform /
343
+ SAM / SST) with the matching GSI/LSI.
344
+ - Stack `none` or unset → if you still see `db_indexes` on the card, ask the user
345
+ to confirm the persistence target before staging anything.
346
+
347
+ Stage the index artifact alongside the query code in the SAME commit. Verification
348
+ (post-deploy index propagation) is handled in the Production Readiness Checklist
349
+ section below, branched by `stack.deployment`.
332
350
 
333
351
  ### Expected Output Locations
334
352
  [pre-fill from codebase-architect: for each requirement, the file:line where the change should go]
@@ -506,11 +524,23 @@ Before triggering any review, you MUST verify that the coder agent implemented *
506
524
  AND read (getter/reader path) in the changed files.
507
525
  - For each `status: modified` field: verify old-name references are removed and
508
526
  new-name references exist.
509
- - **Firestore compound query** → verify: if the card has a `firestore_indexes` field,
510
- check that EVERY listed index exists in `firestore.indexes.json` (match collection +
511
- fields + order). Also grep the query code to confirm `where()` + `orderBy()` field
512
- names match the index definition exactly. Missing or mismatched index = CRITICAL gap
513
- (causes runtime 500 FAILED_PRECONDITION).
527
+ - **DB compound query** → verify: if the card has a `db_indexes` (or legacy
528
+ `firestore_indexes`) field, check that EVERY listed index has been shipped to
529
+ the artifact matching `stack.database`:
530
+ - `firestore` entries exist in `firestore.indexes.json` (match collection +
531
+ fields + order); also grep the query code to confirm `where()` + `orderBy()`
532
+ field names match the index definition exactly. Missing index = CRITICAL
533
+ (runtime 500 FAILED_PRECONDITION).
534
+ - `postgres`/`supabase`/`mysql`/`sqlite` → a migration file exists declaring
535
+ the index (or `prisma/schema.prisma` `@@index([...])`); grep the query to
536
+ confirm the column names match. Missing migration = CRITICAL (silent
537
+ Seq Scan in production on hot path).
538
+ - `mongodb` → `createIndex` call exists in the bootstrap script (or migration);
539
+ compound field order in the call matches equality → range → sort in the query.
540
+ Missing = HIGH (no immediate error, but slow aggregation under load).
541
+ - `dynamodb` → the GSI/LSI is declared in the IaC table definition AND the
542
+ query uses the GSI name via `IndexName`. Missing = CRITICAL (throttle on
543
+ hot partition).
514
544
 
515
545
  If the completion report has `items_skipped` that is not "none", immediately flag those
516
546
  items as Missing regardless of the agent's justification.
@@ -695,7 +725,7 @@ If all met, ask the user: `Vuoi testarlo con Playwright E2E? (si/no)`
695
725
  fields, then submit the login form. No manual intervention needed.
696
726
 
697
727
  ## Test Data Prerequisites
698
- [paste test_data_prerequisites — data that must exist in Firestore]
728
+ [paste test_data_prerequisites — data that must exist in the persistence layer before the test runs]
699
729
 
700
730
  ## Guidelines
701
731
  - Use page.getByRole(), page.getByText(), page.getByTestId() for selectors
@@ -752,8 +782,8 @@ Non-blocking — findings are logged but do NOT block commit.
752
782
  ### Invariant checklist (Linking Protocol — docs/guides/linking-protocol-rollout-v1.md):
753
783
  - [ ] New route.ts added? → ${paths.references_dir}/api/<module>.md + api/index.md count
754
784
  - [ ] New page.tsx added? → ${paths.references_dir}/ui/<domain>.md + ui/index.md Route Summary
755
- - [ ] New Firestore collection? → ${paths.references_dir}/data-model.md + collections/<domain>.md
756
- - [ ] Compound Firestore query (where+orderBy on different fields)? → firestore.indexes.json must include the composite index and be staged
785
+ - [ ] New persistence-layer {entity} ({collection|table|item} per `stack.database`)? → ${paths.references_dir}/data-model.md + the entity's reference doc per project convention (`collections/<domain>.md`, `tables/<domain>.md`, etc.)
786
+ - [ ] Compound query needing a multi-attribute index? → the matching index artifact MUST be staged in the same commit, per `stack.database`: `firestore.indexes.json` (firestore), migration file or Prisma `@@index` (SQL), `createIndex` script (mongo), GSI/LSI in IaC (dynamodb)
757
787
  - [ ] Backlog card set to DONE? → ${paths.references_dir}/ssot-registry.md entry
758
788
  - [ ] New external dependency? → agents/architecture.md External Dependencies list
759
789
  - [ ] Card has `documentation_impact` field? → verify each listed doc is updated
@@ -1260,43 +1290,57 @@ After Phase 6 completes (or after the final summary report if Phase 6 is deferre
1260
1290
 
1261
1291
  ### How to detect items
1262
1292
 
1263
- Scan ALL files changed across the batch (use the tracker's completed cards + `git diff` against the base branch) and check for:
1264
-
1265
- | Category | Detection signal | Action to report |
1266
- |----------|-----------------|------------------|
1267
- | **Firestore indexes** | New/modified `.firestore.indexes.json`, or code using new compound queries with `orderBy`/`where` on multiple fields | `firebase deploy --only firestore:indexes` |
1268
- | **Firestore security rules** | New/modified `firestore.rules` | `firebase deploy --only firestore:rules` |
1269
- | **Storage security rules** | New/modified `storage.rules` | `firebase deploy --only storage:rules` |
1270
- | **Environment variables** | New `process.env.*` references not present in the base branch, new entries in `.env.example` or `.env.local` | 1. Add to Vercel project settings (list each var name + environments) 2. Update `${paths.references_dir}/env-vars.md` Change Log |
1271
- | **Firebase Remote Config** | New `remoteConfig` keys in code | Add keys in Firebase Console > Remote Config |
1272
- | **Firebase Auth providers** | New auth provider configuration | Enable provider in Firebase Console > Authentication |
1273
- | **Scheduled functions / cron** | New or modified cron/scheduled Cloud Functions | Deploy functions: `firebase deploy --only functions` |
1274
- | **Database migrations** | New collections, field renames, data backfills referenced in code or ADRs | Run migration script (specify which) |
1275
- | **New API endpoints** | New route files under `src/app/api/` | Verify CORS/auth config; update API docs if public |
1276
- | **Third-party services** | New API keys, webhook URLs, or external service integrations | Configure in provider dashboard + add secrets to Vercel |
1277
- | **DNS / domain changes** | Hosting or redirect config changes | Update DNS records or Vercel domain settings |
1278
- | **Package upgrades with breaking changes** | Major version bumps in `package.json` | Verify compatibility; check migration guides |
1293
+ Scan ALL files changed across the batch (use the tracker's completed cards + `git diff` against the base branch) and check for the items below.
1294
+
1295
+ **The "Action to report" column shows the command for the deployment target
1296
+ matching `stack.deployment` in `baldart.config.yml`.** When `stack.deployment`
1297
+ is empty, infer from `stack.database` + presence of config files
1298
+ (`vercel.json`, `firebase.json`, `wrangler.toml`, `fly.toml`) and fall back to
1299
+ asking the user.
1300
+
1301
+ | Category | Detection signal | Action to report (per `stack.deployment`) |
1302
+ |----------|-----------------|-------------------------------------------|
1303
+ | **Database indexes** | New/modified index config file (`firestore.indexes.json`, SQL migration with `CREATE INDEX`, `prisma migrate` artifact, `db.createIndex` call, CDK/Terraform GSI) | firebase: `firebase deploy --only firestore:indexes`; vercel+postgres: run migrations during deploy; aws+dynamodb: apply CDK/Terraform; generic: run the project's migration command |
1304
+ | **Persistence-layer access rules** | New/modified `firestore.rules`, Supabase RLS migration, Mongo validator, DynamoDB IAM policy | firebase: `firebase deploy --only firestore:rules`; supabase: `supabase db push`; aws+dynamodb: apply IAM via CDK/Terraform |
1305
+ | **Storage access rules** | New/modified `storage.rules` or equivalent bucket policy | firebase: `firebase deploy --only storage:rules`; aws: apply S3 bucket policy; gcp: apply GCS IAM |
1306
+ | **Environment variables** | New `process.env.*` references not in the base branch, new entries in `.env.example` or `.env.local` | 1. Add to the deployment platform (Vercel/Firebase/Cloudflare/AWS Param Store) — list each var + target environments 2. Update `${paths.references_dir}/env-vars.md` Change Log |
1307
+ | **Feature-flag / remote config** | New flag keys in code, new `remoteConfig` calls, growthbook/launchdarkly keys | Add keys in the project's flag system (Firebase Remote Config / Growthbook / LaunchDarkly / Unleash) |
1308
+ | **Auth provider configuration** | New auth provider initialization or scope change | Configure in the auth provider console matching `stack.auth_provider` (Firebase Console / Supabase dashboard / Clerk dashboard / Auth0 / Cognito) |
1309
+ | **Scheduled functions / cron** | New or modified cron/scheduled jobs | firebase: `firebase deploy --only functions`; vercel: deploy includes cron from `vercel.json`; aws: deploy EventBridge rule + Lambda |
1310
+ | **Database migrations** | New {entities}, field renames, data backfills referenced in code or ADRs | Run the project's migration command — varies by stack (firebase admin script / `supabase db push` / `prisma migrate deploy` / Mongo migration tool / SQL migrator) |
1311
+ | **New API endpoints** | New route files (`src/app/api/` Next.js, `app/routes/api.*` Remix, `src/routes/api/+server.ts` SvelteKit, etc.) | Verify CORS/auth config; update API docs if public |
1312
+ | **Third-party services** | New API keys, webhook URLs, or external service integrations | Configure in provider dashboard + add secrets to the deployment platform |
1313
+ | **DNS / domain changes** | Hosting or redirect config changes | Update DNS records on registrar; update domain settings on the deployment platform |
1314
+ | **Package upgrades with breaking changes** | Major version bumps in `package.json` / `pyproject.toml` / `Gemfile` | Verify compatibility; check migration guides |
1279
1315
 
1280
1316
  ### Output format
1281
1317
 
1282
- Present the checklist as a clearly formatted section in the final report:
1318
+ Present the checklist as a clearly formatted section in the final report.
1319
+ The example below assumes `stack.deployment: firebase` + `stack.database: firestore`;
1320
+ adapt commands and tags to the project's resolved stack.
1283
1321
 
1284
1322
  ```
1285
1323
  ## Production Readiness Checklist
1286
1324
 
1287
1325
  ### Required before deploy
1288
- 1. **[Firebase Indexes]** Deploy Firestore composite indexes
1326
+ 1. **[DB Indexes — firestore]** Deploy composite indexes
1289
1327
  - Command: `firebase deploy --only firestore:indexes`
1290
- - Reason: New compound query on `redemptions` (storeId + tableNumber + createdAt)
1328
+ - Reason: New compound query on `<entity>` (`<field1>` + `<field2>` + `<field3>`)
1291
1329
 
1292
- 2. **[Environment Variable]** Add `REDIS_URL` to Vercel
1293
- - Go to: Vercel > Project Settings > Environment Variables
1330
+ 2. **[Environment Variable]** Add `<VAR_NAME>` to the deployment platform
1331
+ - Go to: <Vercel/Firebase/Cloudflare/AWS> > Project Settings > Environment Variables
1294
1332
  - Required for: Production, Preview
1295
- - Value: (obtain from Upstash dashboard)
1333
+ - Value: (obtain from <provider> dashboard)
1296
1334
 
1297
- 3. **[Firestore Rules]** Deploy updated security rules
1335
+ 3. **[DB Access Rules — firestore]** Deploy updated security rules
1298
1336
  - Command: `firebase deploy --only firestore:rules`
1299
- - Reason: New collection `promoRedemptions` access rules added
1337
+ - Reason: New {entity} `<name>` access rules added
1338
+
1339
+ # Equivalent commands for other stacks:
1340
+ # stack.database: supabase → `supabase db push` (RLS migration)
1341
+ # stack.database: postgres → `prisma migrate deploy` (or project migration tool)
1342
+ # stack.database: mongodb → run the index/validator bootstrap script
1343
+ # stack.database: dynamodb → `cdk deploy` / `terraform apply` for the table+GSI
1300
1344
 
1301
1345
  ### No action needed
1302
1346
  - No new scheduled functions
@@ -1304,8 +1348,8 @@ Present the checklist as a clearly formatted section in the final report:
1304
1348
  - No DNS changes
1305
1349
 
1306
1350
  ### Notes
1307
- - Firebase index deployment can take 5-10 minutes; deploy BEFORE releasing the code
1308
- - Environment variables must be set BEFORE the Vercel deployment triggers
1351
+ - DB index propagation can take time (firestore 5-10 min, postgres CONCURRENTLY minutes-to-hours on large tables, dynamodb GSI minutes); deploy BEFORE releasing the code
1352
+ - Environment variables must be set on the deployment platform BEFORE the deploy triggers
1309
1353
  ```
1310
1354
 
1311
1355
  ### Auto-execution of agent-doable tasks
@@ -1313,22 +1357,24 @@ Present the checklist as a clearly formatted section in the final report:
1313
1357
  Before presenting the checklist, **auto-execute** all items that can be performed by the agent
1314
1358
  without manual intervention. Do NOT ask the user for approval — just run them.
1315
1359
 
1316
- **Auto-executable items** (run via Bash tool, no confirmation needed):
1360
+ **Auto-executable items** (run via Bash tool, no confirmation needed). Pick the
1361
+ command matching `stack.deployment` + `stack.database`. If the inferred command
1362
+ is wrong for the project, ask the user — never auto-execute a guess.
1317
1363
 
1318
- | Category | Command | Auto-execute? |
1319
- |----------|---------|--------------|
1320
- | Firestore indexes | `firebase deploy --only firestore:indexes --project <your-firebase-project>` | YES |
1321
- | Firestore security rules | `firebase deploy --only firestore:rules --project <your-firebase-project>` | YES |
1322
- | Storage security rules | `firebase deploy --only storage:rules --project <your-firebase-project>` | YES |
1323
- | Scheduled functions | `firebase deploy --only functions --project <your-firebase-project>` | YES |
1364
+ | Category | Command per `stack.deployment` | Auto-execute? |
1365
+ |----------|-------------------------------|--------------|
1366
+ | Database indexes | firebase → `firebase deploy --only firestore:indexes --project <id>`; supabase → `supabase db push`; vercel+postgres → `prisma migrate deploy` (or project-specific) | YES (when stack-matched) |
1367
+ | Persistence access rules | firebase → `firebase deploy --only firestore:rules --project <id>`; supabase → `supabase db push` (RLS migration); aws → CDK / Terraform apply | YES (when stack-matched) |
1368
+ | Storage access rules | firebase → `firebase deploy --only storage:rules --project <id>`; aws → S3 bucket policy apply via IaC | YES (when stack-matched) |
1369
+ | Scheduled functions | firebase → `firebase deploy --only functions --project <id>`; vercel → deploy step already includes cron from `vercel.json`; aws → CDK / Terraform apply | YES (when stack-matched) |
1324
1370
 
1325
1371
  **Manual-only items** (report to user, do NOT auto-execute):
1326
1372
 
1327
1373
  | Category | Why manual |
1328
1374
  |----------|-----------|
1329
- | Environment variables | Requires Vercel dashboard access or secret values |
1330
- | Firebase Remote Config | Requires Firebase Console UI |
1331
- | Firebase Auth providers | Requires Firebase Console UI |
1375
+ | Environment variables | Requires deployment-platform dashboard access or secret values |
1376
+ | Feature-flag / remote config | Requires flag-system console (Firebase Remote Config / GrowthBook / LaunchDarkly / Unleash) |
1377
+ | Auth provider configuration | Requires console UI of the provider matching `stack.auth_provider` |
1332
1378
  | Database migrations / backfills | Risk of data loss — needs human judgment |
1333
1379
  | Third-party service config | Requires external dashboards and secrets |
1334
1380
  | DNS / domain changes | Risk of downtime — needs human judgment |
@@ -1339,20 +1385,33 @@ without manual intervention. Do NOT ask the user for approval — just run them.
1339
1385
  2. Log the result (success/failure) in the tracker under `## Production Readiness`.
1340
1386
  3. In the final checklist output, mark auto-executed items with their result:
1341
1387
  ```
1342
- 1. **[Firebase Indexes]** Deploy Firestore composite indexes
1343
- - Command: `firebase deploy --only firestore:indexes --project <your-firebase-project>`
1388
+ 1. **[DB Indexes — <stack.database>]** Deploy indexes
1389
+ - Command: <stack-matched command from the Auto-executable table>
1344
1390
  - Result: DEPLOYED (took 45s) | FAILED (error: ...)
1345
1391
  ```
1346
1392
  4. If an auto-execution FAILS: log the error, mark it as `MANUAL FALLBACK NEEDED`,
1347
1393
  and include it in the "Required before deploy" section for the user to handle.
1348
1394
 
1349
- ### Firestore Index Verification (MUST — after deploy)
1395
+ ### DB Index Verification (MUST — after deploy)
1396
+
1397
+ After the deploy command succeeds, verify the indexes are actually live before
1398
+ reporting success. The deploy command typically returns before index propagation
1399
+ completes (Firestore: 5–10 minutes; Postgres `CREATE INDEX CONCURRENTLY` on a
1400
+ large table: minutes to hours; DynamoDB GSI: minutes; Mongo background index:
1401
+ minutes to hours).
1402
+
1403
+ **Skip this section entirely when:**
1404
+ - the card has no `db_indexes` / `firestore_indexes` block, OR
1405
+ - `stack.database` is unset / `none`, OR
1406
+ - the card's index artifact is a SQL migration on a small table (the migration
1407
+ itself is synchronous and self-verifying — the deploy step already failed if
1408
+ the index didn't build).
1350
1409
 
1351
- After `firebase deploy --only firestore:indexes` succeeds, you MUST verify that all indexes
1352
- are actually `READY` before reporting success. The deploy command returns immediately, but
1353
- indexes can take 5-10 minutes to build.
1410
+ **Verification procedure pick the variant matching `stack.database`:**
1354
1411
 
1355
- **Verification procedure:**
1412
+ #### Variant — Firestore (`stack.database: firestore`)
1413
+
1414
+ After `firebase deploy --only firestore:indexes` succeeds:
1356
1415
 
1357
1416
  1. **Extract expected collection groups** from the local `firestore.indexes.json`:
1358
1417
  ```bash
@@ -1373,7 +1432,6 @@ indexes can take 5-10 minutes to build.
1373
1432
  done | python3 -c "
1374
1433
  import sys, json, re
1375
1434
  raw = sys.stdin.read()
1376
- # Parse multiple JSON responses concatenated
1377
1435
  creating = []
1378
1436
  for match in re.finditer(r'\{[^{}]*\"indexes\"[^}]*\}', raw, re.DOTALL):
1379
1437
  try:
@@ -1394,19 +1452,55 @@ indexes can take 5-10 minutes to build.
1394
1452
  ```
1395
1453
 
1396
1454
  3. **Poll if NOT_READY** — re-check every 30 seconds, up to 10 retries (5 minutes max).
1397
- After each retry, print a status update: `Index verification attempt N/10 — still N indexes building...`
1398
1455
 
1399
1456
  4. **Final status**:
1400
- - If all indexes are `READY`: mark as `VERIFIED READY` in the checklist
1401
- - If indexes are still `CREATING` after 10 retries: mark as `DEPLOYED BUT BUILDING — indexes may take a few more minutes` (this is a warning, not a failure)
1402
- - If any index is `NEEDS_REPAIR` or `ERROR`: mark as `INDEX ERROR — manual intervention required` and include the index details
1457
+ - All `READY` `VERIFIED READY`.
1458
+ - Still `CREATING` after 10 retries `DEPLOYED BUT BUILDING` (warning).
1459
+ - Any `NEEDS_REPAIR` / `ERROR` `INDEX ERROR — manual intervention required`.
1460
+
1461
+ #### Variant — Postgres / Supabase (`stack.database` ∈ {postgres, supabase})
1462
+
1463
+ After the migration / `supabase db push` succeeds:
1464
+
1465
+ ```bash
1466
+ # For each index named in the migration:
1467
+ psql "$DATABASE_URL" -c "SELECT indexname, indexdef FROM pg_indexes WHERE indexname = '<index_name>';"
1468
+ # If the migration used CREATE INDEX CONCURRENTLY on a large table, also check:
1469
+ psql "$DATABASE_URL" -c "SELECT pid, phase, blocks_total, blocks_done FROM pg_stat_progress_create_index;"
1470
+ ```
1471
+
1472
+ If `pg_stat_progress_create_index` returns rows → index still building, poll every
1473
+ 30s. If `pg_indexes` returns 0 rows for an expected name → CRITICAL (migration
1474
+ silently skipped or rolled back).
1475
+
1476
+ #### Variant — MongoDB (`stack.database: mongodb`)
1477
+
1478
+ After the bootstrap script / migration runs:
1479
+
1480
+ ```bash
1481
+ mongosh "$MONGO_URL" --eval "db.<entity>.getIndexes()"
1482
+ ```
1483
+
1484
+ Confirm every expected `name`/`key` is present. For background-built indexes, watch
1485
+ `db.currentOp({'$or':[{op:'command','command.createIndexes':{$exists:true}}]})` until empty.
1486
+
1487
+ #### Variant — DynamoDB (`stack.database: dynamodb`)
1488
+
1489
+ After `cdk deploy` / `terraform apply`:
1490
+
1491
+ ```bash
1492
+ aws dynamodb describe-table --table-name <table> \
1493
+ --query 'Table.GlobalSecondaryIndexes[].{Name:IndexName,Status:IndexStatus}'
1494
+ ```
1495
+
1496
+ All GSIs must show `ACTIVE`. `CREATING` → poll; `DELETING` / `UPDATING` → manual review.
1403
1497
 
1404
1498
  **Checklist output format with verification:**
1405
1499
  ```
1406
- 1. **[Firebase Indexes]** Deploy Firestore composite indexes
1407
- - Command: `firebase deploy --only firestore:indexes --project <your-firebase-project>`
1500
+ 1. **[DB Indexes — <stack.database>]** Deploy indexes
1501
+ - Command: <stack-matched command>
1408
1502
  - Deploy: SUCCESS (took 45s)
1409
- - Verification: ALL INDEXES READY (155/155) | BUILDING (3 still creating after 5min) | ERROR (details)
1503
+ - Verification: ALL READY (5/5) | BUILDING (2 still creating after 5min) | ERROR (details)
1410
1504
  ```
1411
1505
 
1412
1506
  ### Rules
@@ -28,6 +28,7 @@ message. You ask questions, wait for answers, and iterate.
28
28
  |------|-------|-----------|
29
29
  | 0 | Context Recovery | [discovery-phase.md](references/discovery-phase.md) |
30
30
  | 1 | Kickoff | [discovery-phase.md](references/discovery-phase.md) |
31
+ | 1.6 | Mockup Intake | [discovery-phase.md](references/discovery-phase.md) |
31
32
  | 2 | Discovery Question Loop | [discovery-phase.md](references/discovery-phase.md) |
32
33
  | 2→CR | Change Request (auto/manual) | [prd-add-phase.md](references/prd-add-phase.md) |
33
34
  | 2.5 | Research (opzionale) | [research-phase.md](references/research-phase.md) |
@@ -88,6 +89,17 @@ message. You ask questions, wait for answers, and iterate.
88
89
  **Canonical examples**: `FEAT-0875-00..08` (Survey Analytics Redesign),
89
90
  `FEAT-0876-00..11` (Menu TIPS). See `assets/epic-template.yml` for the epic
90
91
  structure and `assets/card-template.yml` for child structure.
92
+ 16. **Mockup Intake (MANDATORY).** Subito dopo Kickoff (Step 1) e prima di entrare in
93
+ Discovery (Step 2), esegui Step 1.6 — chiedi all'utente se ha mockup a disposizione.
94
+ Se **sì**: chiedi formato (immagini in chat / path locali), **STOP**, attendi. Sull'arrivo:
95
+ copia i path locali in `${paths.prd_dir}/<slug>/mockups/`, analizza in dettaglio (vedi
96
+ [discovery-phase.md](references/discovery-phase.md) § "Mockup analysis schema"), popola
97
+ `## UI Design` nello state, poi entra in Discovery. Se **no**: marca
98
+ `mockups.status: none` e procedi col flow standard. Il decision tree di Step 3 (UI Design)
99
+ consuma `mockups.status` + `screens_in_scope[]` per scegliere ramo Full / Hybrid / Skip
100
+ senza ulteriore intervento. Le ambiguità rilevate dall'analisi mockup
101
+ (`mockup_analysis.screens[].gaps[]`) DEVONO diventare domande mirate in Discovery o
102
+ essere esplicitamente waivate.
91
103
 
92
104
  ---
93
105
 
@@ -122,6 +134,7 @@ At the END of every message (after all text, before stopping), display:
122
134
  | # | Fase | Stato |
123
135
  |---|------|-------|
124
136
  | 1 | Discovery & comprensione | ⬜/🔄/✅ |
137
+ | 1.6 | Mockup intake | ⬜/🔄/✅/⏭️ |
125
138
  | 1.5 | Ricerca best practice | ⬜/🔄/✅/⏭️ |
126
139
  | 2 | Design UI & approvazione | ⬜/🔄/✅/⏭️ |
127
140
  | 3 | Conferma specifiche | ⬜/🔄/✅ |
@@ -129,7 +142,9 @@ At the END of every message (after all text, before stopping), display:
129
142
  | 5 | Validazione e commit | ⬜/🔄/✅ |
130
143
 
131
144
  Comprensione: X% (N/M dimensioni coperte) — ISA: N punti identificati
145
+ Mockup: ⬜ non chiesto / 🔄 in attesa / ✅ N mockup / ⏭️ nessuno
132
146
  Ricerca: ⬜ non valutata / 🔍 in corso (background) / ✅ completata / ⏭️ non necessaria
147
+ Step 3 mode: full / hybrid / skipped (impostato dopo Step 1.6 e refinementato a Step 3)
133
148
  Prossimo passo: <what happens next>
134
149
  ```
135
150
 
@@ -183,6 +198,16 @@ Dimensions 1-8 can be resolved by: context-primer context (auto), targeted codeb
183
198
  Dimension 9 uses automated codebase scan + user validation (see discovery-phase.md).
184
199
  Dimension 10 uses a built-in evaluation tree (see discovery-phase.md).
185
200
 
201
+ **Mockup-driven pre-population (when Step 1.6 produced `mockups.status: provided`):**
202
+ - Dimension 5 (UI impact) is largely pre-resolved from `mockup_analysis.screens[]`
203
+ — log as covered with source `mockup-analysis`. Only ask UI questions for
204
+ ambiguities in `mockup_analysis.screens[].gaps[]` or for screens NOT in the mockups.
205
+ - Dimension 2 (User journey) is partially pre-resolved from `mockup_analysis.user_flow`
206
+ — ask only for the connective steps that aren't visible from the mockup sequence
207
+ (entry point, exit, error branches).
208
+ - All other dimensions follow the normal flow — mockups do not pre-resolve data
209
+ model, API contract, permissions, edge cases, rollout, ISA, or test strategy.
210
+
186
211
  ---
187
212
 
188
213
  ## COMPLETED PROGRESS BAR (for final message)
@@ -194,6 +219,7 @@ Dimension 10 uses a built-in evaluation tree (see discovery-phase.md).
194
219
  | # | Fase | Stato |
195
220
  |---|------|-------|
196
221
  | 1 | Discovery & comprensione | ✅ |
222
+ | 1.6 | Mockup intake | ✅/⏭️ |
197
223
  | 1.5 | Ricerca best practice | ✅/⏭️ |
198
224
  | 2 | Design UI & approvazione | ✅/⏭️ |
199
225
  | 3 | Conferma specifiche | ✅ |
@@ -201,7 +227,9 @@ Dimension 10 uses a built-in evaluation tree (see discovery-phase.md).
201
227
  | 5 | Validazione e commit | ✅ |
202
228
 
203
229
  Comprensione: 100%
230
+ Mockup: ✅ N mockup analizzati / ⏭️ nessuno fornito
204
231
  Ricerca: ✅ completata / ⏭️ non necessaria
232
+ Step 3 mode: full / hybrid / skipped
205
233
  **Pronto per l'implementazione.**
206
234
  ```
207
235
 
@@ -218,13 +246,13 @@ After cards are created and committed, log this PRD run to `docs/metrics/skill-r
218
246
  - `ac_coverage_ratio`: total acceptance_criteria count / total user_stories count across all cards
219
247
  - `isa_count`: number of ISA items identified (from the progress bar "ISA: N punti")
220
248
  - `has_test_plan_pct`: % of cards that have a `test_plan` field (even if `e2e_required: false`)
221
- - `has_firestore_indexes_pct`: % of cards that have a `firestore_indexes` field
249
+ - `has_db_indexes_pct`: % of cards that have a `db_indexes` field (covers any persistence layer; legacy `firestore_indexes` cards count too)
222
250
  - `discovery_iterations`: approximate number of Q&A rounds with the user (count AskUserQuestion calls in this session, default 1 if unknown)
223
251
 
224
252
  2. Write ONE JSON line (append) to `docs/metrics/skill-runs.jsonl`:
225
253
 
226
254
  ```json
227
- {"ts":"<ISO-8601-UTC>","skill":"prd","run_id":"prd-<slug>","prd_slug":"<slug>","cards_created":0,"ac_coverage_ratio":0.0,"isa_count":0,"has_test_plan_pct":0.0,"has_firestore_indexes_pct":0.0,"discovery_iterations":1,"prd_path":"${paths.prd_dir}/<slug>/PRD.md"}
255
+ {"ts":"<ISO-8601-UTC>","skill":"prd","run_id":"prd-<slug>","prd_slug":"<slug>","cards_created":0,"ac_coverage_ratio":0.0,"isa_count":0,"has_test_plan_pct":0.0,"has_db_indexes_pct":0.0,"discovery_iterations":1,"prd_path":"${paths.prd_dir}/<slug>/PRD.md"}
228
256
  ```
229
257
 
230
258
  **This step is NON-BLOCKING** — if it fails, do not abort. Log "Metrics Log: SKIPPED" in the progress bar.
@@ -31,7 +31,10 @@ business_rationale: |
31
31
  scope:
32
32
  summary: |
33
33
  {{What this card delivers in 2-3 lines.}}
34
- users: [{{CUSTOMER|MERCHANT|SUPER_ADMIN}}]
34
+ # Drawn from identity.audience_segments[] in baldart.config.yml.
35
+ # Use the project's own persona labels (e.g. ["customer","merchant"] or
36
+ # ["admin","editor","viewer"] or ["tenant","support","ops"]).
37
+ users: [{{persona1, persona2}}]
35
38
  value: {{Business value in one line.}}
36
39
 
37
40
  # --- Scope Boundaries (OPTIONAL — include when card is part of a multi-card epic) ---
@@ -122,13 +125,16 @@ test_plan:
122
125
  maps_to: "US-{{N}} / AC-{{N}}"
123
126
  priority: {{HIGH|MEDIUM}}
124
127
  test_credentials:
125
- persona: {{CUSTOMER|MERCHANT|SUPER_ADMIN}}
126
- auth_method: "{{OTP|password}}"
127
- credentials: "{{phone: 3486417303 | username/password}}"
128
- store: "{{store name if merchant}}"
129
- notes: "{{e.g., OTP inserito manualmente dall'utente}}"
128
+ # Persona names come from identity.audience_segments[] in baldart.config.yml.
129
+ # Credential REFERENCES (not real secrets) live in .baldart/overlays/prd.md
130
+ # § Test Credentials. Never paste secrets in committed YAML.
131
+ persona: "{{from identity.audience_segments[]}}"
132
+ auth_method: "{{OTP | password | magic-link | api-token}}"
133
+ credentials_ref: "{{secret-manager://path | .env.test:VAR_NAME | overlay-reference}}"
134
+ context: "{{tenant / workspace / store / org — if applicable}}"
135
+ notes: "{{e.g., OTP entered manually during test}}"
130
136
  test_data_prerequisites:
131
- - "{{any Firestore data needed before tests}}"
137
+ - "{{any data that must exist in the persistence layer before tests run}}"
132
138
 
133
139
  integration_points:
134
140
  - id: ISA-{{N}}
@@ -169,15 +175,17 @@ reuse_analysis:
169
175
  # --- Data Sources (MANDATORY — compile for EVERY card; use [] only for pure docs/config cards) ---
170
176
  # High-level overview of every data source or destination touched by this card.
171
177
  # Rules:
172
- # type: firestore collection name in `path`; field-level detail goes in data_fields below.
178
+ # type: db {entity} name in `path` (collection/table/index per stack.database); field-level detail in data_fields below.
173
179
  # type: file → repo-relative path, operations (READ|WRITE|APPEND|CREATE|DELETE), format.
174
180
  # type: api → URL or endpoint pattern; READ=GET, WRITE=POST/PUT/PATCH, DELETE=DELETE.
175
181
  # type: env → env var name; operations always [READ].
176
182
  # [] → explicit empty list for cards that read/write NO data (docs, config stubs).
177
183
  # NEVER omit this field silently — an empty [] signals the writer verified there are no sources.
184
+ # Legacy "firestore" type is still accepted; prefer "db" + db_dialect.
178
185
  data_sources:
179
- - type: "{{firestore|file|api|env}}"
180
- path: "{{collection name | repo-relative file path | API endpoint | env var name}}"
186
+ - type: "{{db|file|api|env}}"
187
+ db_dialect: "{{firestore|postgres|supabase|mysql|mongodb|dynamodb|sqlite}}" # only when type: db
188
+ path: "{{entity name | repo-relative file path | API endpoint | env var name}}"
181
189
  operations: [{{READ|WRITE|APPEND|CREATE|DELETE}}]
182
190
  # format: "{{JSONL|YAML|JSON|markdown|binary}}" # include for file type only
183
191
  # note: "{{optional: data shape, why this source}}"
@@ -194,32 +202,41 @@ env_vars:
194
202
  feature_card: "{{nome feature / ID card, es. SPU / ADR-2026-04-24}}"
195
203
  note: "{{a cosa serve}}"
196
204
 
197
- # --- Data Fields (MANDATORY for cards that read/write Firestore — omit for UI/docs/config only) ---
205
+ # --- Data Fields (MANDATORY for cards that read/write the persistence layer — omit for UI/docs/config only) ---
198
206
  # Structured field-name registry for mechanical validation (pre-commit hook + Quality Audit).
199
- # Field Grounding Rule: EVERY field here MUST be verified via Grep on field-registry.json
200
- # BEFORE ts_verified is set to true. See prd-card-writer.md Field Grounding Rule.
201
- # Fields id, createdAt, updatedAt are universal — do NOT include them here.
207
+ # Field Grounding Rule: EVERY field here MUST be verified via Grep on the schema registry
208
+ # (path resolved per .baldart/overlays/prd.md § Schema Registry — common defaults:
209
+ # ${paths.references_dir}/field-registry.json for Firestore-style projects,
210
+ # ${paths.references_dir}/schema.md for SQL, prisma/schema.prisma for Prisma).
211
+ # Fields id, createdAt, updatedAt (or their snake_case equivalents) are universal — do NOT include here.
202
212
  data_fields:
203
- - collection: "{{collectionName}}" # exact key in ${paths.references_dir}/field-registry.json
204
- field: "{{fieldName}}" # exact field name (verified via Grep)
205
- type: "{{TypeScript type}}" # e.g. "string", "OccasionType", "boolean"
213
+ - entity: "{{collection or table name}}" # exact key in the project schema registry
214
+ field: "{{fieldName or column_name}}" # exact identifier (verified via Grep)
215
+ type: "{{language-native type}}" # e.g. "string", "OccasionType", "boolean", "varchar(64)", "JSONB"
206
216
  status: "{{existing|new|modified|deprecated_removed}}"
207
217
  ts_verified: {{true|false}} # true = Grep confirmed field in registry
208
- source: "{{src/types/booking.ts}}" # TypeScript file where interface is defined
218
+ source: "{{src/types/booking.ts | prisma/schema.prisma:42 | migrations/2024_..._create.sql}}"
209
219
  # schema_ref: "PRD.md#schema-verification" # ONLY for status: new fields
210
220
 
211
- firestore_indexes:
212
- - collection: "{{collection name}}"
221
+ db_indexes:
222
+ - entity: "{{collection or table name}}"
223
+ dialect: "{{firestore|postgres|supabase|mysql|mongodb|dynamodb|sqlite}}"
213
224
  fields:
214
- - field: "{{field1}}"
215
- order: "{{ASC|DESC}}"
216
- - field: "{{field2}}"
225
+ - field: "{{field1 or column1}}"
226
+ order: "{{ASC|DESC}}" # firestore/sql; for mongo use {field1: 1|-1}
227
+ - field: "{{field2 or column2}}"
217
228
  order: "{{ASC|DESC}}"
229
+ kind: "{{composite|covering|partial|GIN|GSI|LSI|unique|fulltext}}" # pick what matches dialect
218
230
  query_location: "{{file path where the query lives}}"
219
231
  prd_ref: "IDX-{{N}}"
220
- # Omit this section entirely if the card has no compound Firestore queries.
221
- # If present, the coder MUST add these indexes to firestore.indexes.json
222
- # in the same commit as the query code.
232
+ # Omit this section entirely if the card has no compound queries / multi-column indexes.
233
+ # If present, the coder MUST ship the index in the same commit as the query —
234
+ # firestore.indexes.json (Firestore), migration file (SQL), createIndex call (Mongo),
235
+ # CDK/Terraform table definition (DynamoDB).
236
+
237
+ # Legacy field name kept for backwards-compat with pre-3.15.0 cards. The validator
238
+ # accepts either name; the writer should prefer db_indexes for new cards.
239
+ firestore_indexes: [] # DEPRECATED in v3.15.0 — use db_indexes instead
223
240
 
224
241
  documentation_impact:
225
242
  - "{{doc path}} — {{what to update}}"
@@ -11,7 +11,7 @@
11
11
  # The epic is a TRACKER, not implementation work:
12
12
  # - NO files_likely_touched pointing to code (only docs allowed)
13
13
  # - NO validation_commands, existing_patterns, anti_patterns
14
- # - NO data_fields, firestore_indexes
14
+ # - NO data_fields, db_indexes (firestore_indexes legacy too)
15
15
  # - NO test_plan with scenarios (test scenarios live on children)
16
16
  # - data_sources: [] (always empty)
17
17
  #
@@ -65,7 +65,8 @@ scope:
65
65
  summary: |
66
66
  Coordinamento delle {{N}} sub-card che implementano l'epic:
67
67
  {{breve descrizione di ogni sub-card in 1 riga ciascuna}}
68
- users: [{{CUSTOMER|MERCHANT|SUPER_ADMIN}}]
68
+ # Drawn from identity.audience_segments[] in baldart.config.yml.
69
+ users: [{{persona1, persona2}}]
69
70
  value: "{{one-line business value}}"
70
71
 
71
72
  scope_boundaries: