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
@@ -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,12 +219,44 @@ 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
 
225
226
  ---
226
227
 
228
+ ## Agent Routing (Phase 2 dispatcher)
229
+
230
+ Phase 2 reads the card's `owner_agent` field and dispatches to the matching
231
+ specialist. The enum is defined by the PRD card writer
232
+ (`framework/.claude/agents/prd.md:538` + `prd-card-writer.md § Agent
233
+ Specialization Rules`) and validated by the PRD validation phase
234
+ (`framework/.claude/skills/prd/references/validation-phase.md` Step 6 → 0).
235
+
236
+ | `owner_agent` | Dispatcher action in Phase 2 step 7 | Briefing variant |
237
+ |---|---|---|
238
+ | `coder` | Spawn `coder` | Standard coder briefing (default body below) |
239
+ | `ui-expert` | Spawn `ui-expert` | UI briefing — adds BLOCKING registry-first cascade + Post-Intervention Coherence Check (see step 7 § UI branch) |
240
+ | `plan` | Fallback to `coder` + WARN | Standard coder briefing + log `"[ROUTER] plan-only briefing not yet implemented — using coder"` |
241
+ | `visual-designer` | Fallback to `coder` + WARN | Standard coder briefing + same WARN format |
242
+ | `motion-expert` | Fallback to `coder` + WARN | Standard coder briefing + same WARN format |
243
+ | missing / `claude` / unknown | Fallback to `coder` + WARN | Standard coder briefing; for unknown value also log the literal value |
244
+
245
+ The three `plan` / `visual-designer` / `motion-expert` stubs exist so the
246
+ router never blocks a card; specialized briefings are tracked as a follow-up.
247
+
248
+ If you change which values are valid here, also update:
249
+
250
+ - `framework/.claude/agents/prd.md:538` (the canonical enum comment),
251
+ - `framework/.claude/skills/prd/assets/card-template.yml` (the placeholder),
252
+ - `framework/.claude/agents/prd-card-writer.md § Agent Specialization Rules`,
253
+ - `framework/.claude/skills/prd/references/validation-phase.md` Step 6 → 0a,
254
+ - `framework/.claude/agents/REGISTRY.md` decision-tree.
255
+
256
+ Keep them in lockstep — drift between any two layers silently mis-routes cards.
257
+
258
+ ---
259
+
227
260
  ## Per-card pipeline
228
261
 
229
262
  For each card, execute these phases in order:
@@ -261,7 +294,28 @@ For each card, execute these phases in order:
261
294
 
262
295
  ### Phase 2 — Implement (self-healing, up to 3 retries)
263
296
  6. **Update tracker**: phase = "2-implement".
264
- 7. Spawn the **coder** agent (or appropriate specialist from `.claude/agents/REGISTRY.md`) using this **standardized mission briefing** fill in each section from the card YAML, tracker, and codebase-architect findings:
297
+ 6b. **Agent dispatch (router)** read `owner_agent` from the card YAML and resolve the spawn target per the table in § Agent Routing above:
298
+
299
+ ```
300
+ Let raw = card.owner_agent (string, may be missing).
301
+ Switch on raw:
302
+ - "coder" → spawn = "coder", briefing = "coder"
303
+ - "ui-expert" → spawn = "ui-expert", briefing = "ui-expert"
304
+ - "plan" → spawn = "coder", briefing = "coder"
305
+ + log: "[ROUTER] plan-only briefing not yet implemented — using coder"
306
+ - "visual-designer" → spawn = "coder", briefing = "coder"
307
+ + log: "[ROUTER] visual-designer briefing not yet implemented — using coder"
308
+ - "motion-expert" → spawn = "coder", briefing = "coder"
309
+ + log: "[ROUTER] motion-expert briefing not yet implemented — using coder"
310
+ - "" | missing | "claude"
311
+ → spawn = "coder", briefing = "coder"
312
+ + log: "[ROUTER] card <ID> has no valid owner_agent (got '<raw>'); defaulting to coder"
313
+ - anything else → HALT. Log: "[ROUTER] card <ID> has unknown owner_agent '<raw>' — not in {coder, ui-expert, plan, visual-designer, motion-expert}. Ask the user how to proceed."
314
+ ```
315
+
316
+ Log the resolved `spawn` and `briefing` in the tracker (1 line: `"router: owner_agent=<raw> → spawn=<agent>, briefing=<variant>"`). This is the audit trail for which specialist actually handled the card.
317
+
318
+ 7. Spawn the **resolved agent** (from step 6b) using this **standardized mission briefing** — fill in each section from the card YAML, tracker, and codebase-architect findings. When `briefing = "ui-expert"`, ALSO include the additional UI sections marked **[UI-ONLY]** below:
265
319
 
266
320
  ```
267
321
  ## MISSION BRIEFING — <CARD-ID>
@@ -293,6 +347,70 @@ For each card, execute these phases in order:
293
347
  Read the design.html file and use it as the visual reference for your implementation.
294
348
  The design was approved by the user — your implementation MUST match it.
295
349
 
350
+ ### [UI-ONLY] Registry-first BLOCKING pre-work (include ONLY when briefing = "ui-expert")
351
+ You are spawned as `ui-expert`. Before writing any UI code, you MUST complete
352
+ the registry-first cascade defined in
353
+ `framework/.claude/agents/ui-expert.md` § "Authoritative Style Reference —
354
+ Registry-First Protocol" (the SSOT lives in
355
+ `framework/agents/design-system-protocol.md`). Reproduce its 5 steps
356
+ verbatim, do NOT paraphrase or skip:
357
+
358
+ 1. Read `${paths.design_system}/INDEX.md` (component index + Canonical
359
+ Authority Matrix).
360
+ 2. Read `${paths.ui_guidelines}` (visual language, typography,
361
+ accessibility, brand voice).
362
+ 3. Read `${paths.design_system}/tokens-reference.md` (token contract —
363
+ SSOT for every color / spacing / shadow / radius / motion value).
364
+ 4. For EACH primitive in scope on this card, read
365
+ `${paths.design_system}/components/<Name>.md`. "In scope" = any
366
+ component named in the mockup, the requirements, or `files_likely_touched`.
367
+ 5. For EACH pattern in scope, read the relevant
368
+ `${paths.design_system}/patterns/<topic>.md`.
369
+
370
+ State, in your first response, which Authority Matrix rows govern this
371
+ card, which component specs you read (step 4), and which patterns you
372
+ read (step 5). Skipping this declaration = the orchestrator will reject
373
+ the implementation and re-spawn.
374
+
375
+ The `features.has_design_system: true` flag in `baldart.config.yml` is
376
+ the precondition for the full cascade. When `features.has_design_system:
377
+ false`, only step 2 applies — log the gap, recommend `/design-system-init`
378
+ if drift is visible, and proceed with coder-level diligence (no cascade
379
+ enforced).
380
+
381
+ ### [UI-ONLY] Implementation-only constraint (include ONLY when briefing = "ui-expert")
382
+ This `/new` invocation gives you the role of IMPLEMENTER, not designer:
383
+
384
+ - DO NOT redesign the mockup. The mockup at `links.design` is the
385
+ user-approved visual contract for this card.
386
+ - DO NOT silently adapt a mockup detail that conflicts with the registry
387
+ (e.g. a custom shadow not in `tokens-reference.md`, a font size off the
388
+ type scale, a color outside the palette). If you find such a conflict:
389
+ STOP, log it in the tracker as `[DS-DRIFT] mockup-vs-registry`, and ask
390
+ the user which side to honor.
391
+ - DO NOT extend scope into business logic, API calls, state management, or
392
+ validation rules. Those belong to a sibling `coder` card (see
393
+ `backlog-phase.md § Rule B`). If a requirement appears to need logic,
394
+ STOP and ask — do not implement it.
395
+
396
+ ### [UI-ONLY] Post-Intervention Coherence Check (include ONLY when briefing = "ui-expert")
397
+ Before declaring the card done, you MUST reconcile the three design-system
398
+ sources in the SAME commit as your UI change, per
399
+ `framework/agents/design-system-protocol.md § Post-Intervention Coherence Check`:
400
+
401
+ - `${paths.design_system}/INDEX.md` — add / update entries for any primitive
402
+ introduced or modified. Drift code: `DS_INDEX_DRIFT`.
403
+ - `${paths.design_system}/components/<Name>.md` — ship the per-component
404
+ spec for any new primitive; update the spec when a primitive's API or
405
+ visual changes. Drift code: `DS_COMPONENT_STALE`.
406
+ - `${paths.design_system}/tokens-reference.md` — add / update token entries
407
+ when introducing new semantic tokens. Drift code: `DS_TOKENS_DRIFT`.
408
+
409
+ The four conditions defined in `design-system-protocol.md` are the SSOT —
410
+ reproduce them in your completion report under a `design_system_coherence:`
411
+ block listing which conditions applied and which artifacts you updated.
412
+ Omitting the block = the orchestrator treats the card as not done.
413
+
296
414
  ### File Permissions (ENFORCED — no exceptions)
297
415
  MAY EDIT — your files for this card:
298
416
  [list from ownership map for this card]
@@ -306,29 +424,46 @@ For each card, execute these phases in order:
306
424
  - Do NOT add unrequested features or extra error handling beyond what's specified
307
425
  - Do NOT modify test files unless the card explicitly requires it
308
426
 
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.
427
+ ### Database Indexes (if card has `db_indexes` — or legacy `firestore_indexes` field)
428
+ This card requires the following indexes shipped in the SAME commit as the query
429
+ code. Missing indexes degrade performance or break production (variant per
430
+ `stack.database` see `framework/.claude/agents/coder.md § Database Index Invariant`).
431
+
432
+ [paste db_indexes entries from card YAML, formatted as:]
433
+ | Entity | Dialect | Fields | Kind | Query Location | PRD Ref |
434
+ |--------|---------|--------|------|----------------|---------|
435
+ | [entity] | [stack.database] | [field1 ASC, field2 DESC] | [composite/covering/GIN/GSI] | [file path] | [IDX-N] |
436
+
437
+ **Where to ship the index pick the artifact matching `stack.database`:**
438
+
439
+ - `firestore` → append to `firestore.indexes.json` under `indexes[]`:
440
+ ```json
441
+ {
442
+ "collectionGroup": "<entity>",
443
+ "queryScope": "COLLECTION",
444
+ "fields": [
445
+ { "fieldPath": "<field1>", "order": "ASCENDING" },
446
+ { "fieldPath": "<field2>", "order": "DESCENDING" }
447
+ ]
448
+ }
449
+ ```
450
+ Stage `firestore.indexes.json` together with the query code.
451
+ - `postgres` / `supabase` / `mysql` / `sqlite` → add a migration file under the
452
+ project's migrations dir (`migrations/`, `db/migrate/`, `supabase/migrations/`,
453
+ `prisma/migrations/` per project convention) with `CREATE INDEX ...` or the
454
+ Prisma `@@index([...])` directive. For Supabase, RLS policies live in the same
455
+ migration when relevant.
456
+ - `mongodb` → add `db.<entity>.createIndex(...)` to the project's index-bootstrap
457
+ script (path declared in `.baldart/overlays/new.md § Schema Bootstrap`), or run
458
+ it as part of the migration command.
459
+ - `dynamodb` → update the table definition in the project's IaC (CDK / Terraform /
460
+ SAM / SST) with the matching GSI/LSI.
461
+ - Stack `none` or unset → if you still see `db_indexes` on the card, ask the user
462
+ to confirm the persistence target before staging anything.
463
+
464
+ Stage the index artifact alongside the query code in the SAME commit. Verification
465
+ (post-deploy index propagation) is handled in the Production Readiness Checklist
466
+ section below, branched by `stack.deployment`.
332
467
 
333
468
  ### Expected Output Locations
334
469
  [pre-fill from codebase-architect: for each requirement, the file:line where the change should go]
@@ -506,15 +641,48 @@ Before triggering any review, you MUST verify that the coder agent implemented *
506
641
  AND read (getter/reader path) in the changed files.
507
642
  - For each `status: modified` field: verify old-name references are removed and
508
643
  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).
644
+ - **DB compound query** → verify: if the card has a `db_indexes` (or legacy
645
+ `firestore_indexes`) field, check that EVERY listed index has been shipped to
646
+ the artifact matching `stack.database`:
647
+ - `firestore` entries exist in `firestore.indexes.json` (match collection +
648
+ fields + order); also grep the query code to confirm `where()` + `orderBy()`
649
+ field names match the index definition exactly. Missing index = CRITICAL
650
+ (runtime 500 FAILED_PRECONDITION).
651
+ - `postgres`/`supabase`/`mysql`/`sqlite` → a migration file exists declaring
652
+ the index (or `prisma/schema.prisma` `@@index([...])`); grep the query to
653
+ confirm the column names match. Missing migration = CRITICAL (silent
654
+ Seq Scan in production on hot path).
655
+ - `mongodb` → `createIndex` call exists in the bootstrap script (or migration);
656
+ compound field order in the call matches equality → range → sort in the query.
657
+ Missing = HIGH (no immediate error, but slow aggregation under load).
658
+ - `dynamodb` → the GSI/LSI is declared in the IaC table definition AND the
659
+ query uses the GSI name via `IndexName`. Missing = CRITICAL (throttle on
660
+ hot partition).
514
661
 
515
662
  If the completion report has `items_skipped` that is not "none", immediately flag those
516
663
  items as Missing regardless of the agent's justification.
517
664
 
665
+ - **[UI-ONLY] Design-system conformance** → run ONLY when `briefing = "ui-expert"` from step 6b
666
+ AND `features.has_design_system: true` in `baldart.config.yml`:
667
+ - Grep the changed files for hardcoded design values that bypass the registry:
668
+ hex colors (`#[0-9a-fA-F]{3,8}`), `rgb(`/`rgba(`, `box-shadow:` with inline
669
+ offsets/blurs, `border-radius:` with px/rem literals, `font-size:` with raw
670
+ px/rem (outside the type scale), `padding`/`margin` with raw px (outside the
671
+ spacing scale). Each hit on a NEW or MODIFIED line = Partial — the value
672
+ should come from a token, not a literal.
673
+ - Verify the completion report includes the `design_system_coherence:` block
674
+ required by the UI-ONLY briefing. Missing block = Missing (orchestrator
675
+ cannot confirm Post-Intervention Coherence Check ran).
676
+ - For each new primitive declared by the report (or detected via Grep for new
677
+ components in `${paths.components_primitives}`), verify the matching
678
+ `${paths.design_system}/components/<Name>.md` spec was created in the same
679
+ commit. Missing spec = Partial — fix by re-spawning `ui-expert` with the
680
+ narrow instruction "ship the component spec for <Name> per
681
+ design-system-protocol.md".
682
+ - For each token change declared by the report, verify the entry exists in
683
+ `${paths.design_system}/tokens-reference.md`. Missing entry = Partial.
684
+ - If `features.has_design_system: false`, log "DS conformance skipped — flag is false" and continue.
685
+
518
686
  5. Classify each item:
519
687
  - **Done** — code exists AND satisfies the FULL scope of the requirement (not just partial).
520
688
  - **Partial** — some code exists but the criterion is not fully satisfied (e.g., UI renders but no error state, endpoint exists but wrong response shape).
@@ -695,7 +863,7 @@ If all met, ask the user: `Vuoi testarlo con Playwright E2E? (si/no)`
695
863
  fields, then submit the login form. No manual intervention needed.
696
864
 
697
865
  ## Test Data Prerequisites
698
- [paste test_data_prerequisites — data that must exist in Firestore]
866
+ [paste test_data_prerequisites — data that must exist in the persistence layer before the test runs]
699
867
 
700
868
  ## Guidelines
701
869
  - Use page.getByRole(), page.getByText(), page.getByTestId() for selectors
@@ -752,8 +920,8 @@ Non-blocking — findings are logged but do NOT block commit.
752
920
  ### Invariant checklist (Linking Protocol — docs/guides/linking-protocol-rollout-v1.md):
753
921
  - [ ] New route.ts added? → ${paths.references_dir}/api/<module>.md + api/index.md count
754
922
  - [ ] 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
923
+ - [ ] 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.)
924
+ - [ ] 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
925
  - [ ] Backlog card set to DONE? → ${paths.references_dir}/ssot-registry.md entry
758
926
  - [ ] New external dependency? → agents/architecture.md External Dependencies list
759
927
  - [ ] Card has `documentation_impact` field? → verify each listed doc is updated
@@ -1260,43 +1428,57 @@ After Phase 6 completes (or after the final summary report if Phase 6 is deferre
1260
1428
 
1261
1429
  ### How to detect items
1262
1430
 
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 |
1431
+ 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.
1432
+
1433
+ **The "Action to report" column shows the command for the deployment target
1434
+ matching `stack.deployment` in `baldart.config.yml`.** When `stack.deployment`
1435
+ is empty, infer from `stack.database` + presence of config files
1436
+ (`vercel.json`, `firebase.json`, `wrangler.toml`, `fly.toml`) and fall back to
1437
+ asking the user.
1438
+
1439
+ | Category | Detection signal | Action to report (per `stack.deployment`) |
1440
+ |----------|-----------------|-------------------------------------------|
1441
+ | **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 |
1442
+ | **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 |
1443
+ | **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 |
1444
+ | **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 |
1445
+ | **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) |
1446
+ | **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) |
1447
+ | **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 |
1448
+ | **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) |
1449
+ | **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 |
1450
+ | **Third-party services** | New API keys, webhook URLs, or external service integrations | Configure in provider dashboard + add secrets to the deployment platform |
1451
+ | **DNS / domain changes** | Hosting or redirect config changes | Update DNS records on registrar; update domain settings on the deployment platform |
1452
+ | **Package upgrades with breaking changes** | Major version bumps in `package.json` / `pyproject.toml` / `Gemfile` | Verify compatibility; check migration guides |
1279
1453
 
1280
1454
  ### Output format
1281
1455
 
1282
- Present the checklist as a clearly formatted section in the final report:
1456
+ Present the checklist as a clearly formatted section in the final report.
1457
+ The example below assumes `stack.deployment: firebase` + `stack.database: firestore`;
1458
+ adapt commands and tags to the project's resolved stack.
1283
1459
 
1284
1460
  ```
1285
1461
  ## Production Readiness Checklist
1286
1462
 
1287
1463
  ### Required before deploy
1288
- 1. **[Firebase Indexes]** Deploy Firestore composite indexes
1464
+ 1. **[DB Indexes — firestore]** Deploy composite indexes
1289
1465
  - Command: `firebase deploy --only firestore:indexes`
1290
- - Reason: New compound query on `redemptions` (storeId + tableNumber + createdAt)
1466
+ - Reason: New compound query on `<entity>` (`<field1>` + `<field2>` + `<field3>`)
1291
1467
 
1292
- 2. **[Environment Variable]** Add `REDIS_URL` to Vercel
1293
- - Go to: Vercel > Project Settings > Environment Variables
1468
+ 2. **[Environment Variable]** Add `<VAR_NAME>` to the deployment platform
1469
+ - Go to: <Vercel/Firebase/Cloudflare/AWS> > Project Settings > Environment Variables
1294
1470
  - Required for: Production, Preview
1295
- - Value: (obtain from Upstash dashboard)
1471
+ - Value: (obtain from <provider> dashboard)
1296
1472
 
1297
- 3. **[Firestore Rules]** Deploy updated security rules
1473
+ 3. **[DB Access Rules — firestore]** Deploy updated security rules
1298
1474
  - Command: `firebase deploy --only firestore:rules`
1299
- - Reason: New collection `promoRedemptions` access rules added
1475
+ - Reason: New {entity} `<name>` access rules added
1476
+
1477
+ # Equivalent commands for other stacks:
1478
+ # stack.database: supabase → `supabase db push` (RLS migration)
1479
+ # stack.database: postgres → `prisma migrate deploy` (or project migration tool)
1480
+ # stack.database: mongodb → run the index/validator bootstrap script
1481
+ # stack.database: dynamodb → `cdk deploy` / `terraform apply` for the table+GSI
1300
1482
 
1301
1483
  ### No action needed
1302
1484
  - No new scheduled functions
@@ -1304,8 +1486,8 @@ Present the checklist as a clearly formatted section in the final report:
1304
1486
  - No DNS changes
1305
1487
 
1306
1488
  ### 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
1489
+ - 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
1490
+ - Environment variables must be set on the deployment platform BEFORE the deploy triggers
1309
1491
  ```
1310
1492
 
1311
1493
  ### Auto-execution of agent-doable tasks
@@ -1313,22 +1495,24 @@ Present the checklist as a clearly formatted section in the final report:
1313
1495
  Before presenting the checklist, **auto-execute** all items that can be performed by the agent
1314
1496
  without manual intervention. Do NOT ask the user for approval — just run them.
1315
1497
 
1316
- **Auto-executable items** (run via Bash tool, no confirmation needed):
1498
+ **Auto-executable items** (run via Bash tool, no confirmation needed). Pick the
1499
+ command matching `stack.deployment` + `stack.database`. If the inferred command
1500
+ is wrong for the project, ask the user — never auto-execute a guess.
1317
1501
 
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 |
1502
+ | Category | Command per `stack.deployment` | Auto-execute? |
1503
+ |----------|-------------------------------|--------------|
1504
+ | 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) |
1505
+ | 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) |
1506
+ | Storage access rules | firebase → `firebase deploy --only storage:rules --project <id>`; aws → S3 bucket policy apply via IaC | YES (when stack-matched) |
1507
+ | 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
1508
 
1325
1509
  **Manual-only items** (report to user, do NOT auto-execute):
1326
1510
 
1327
1511
  | Category | Why manual |
1328
1512
  |----------|-----------|
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 |
1513
+ | Environment variables | Requires deployment-platform dashboard access or secret values |
1514
+ | Feature-flag / remote config | Requires flag-system console (Firebase Remote Config / GrowthBook / LaunchDarkly / Unleash) |
1515
+ | Auth provider configuration | Requires console UI of the provider matching `stack.auth_provider` |
1332
1516
  | Database migrations / backfills | Risk of data loss — needs human judgment |
1333
1517
  | Third-party service config | Requires external dashboards and secrets |
1334
1518
  | DNS / domain changes | Risk of downtime — needs human judgment |
@@ -1339,20 +1523,33 @@ without manual intervention. Do NOT ask the user for approval — just run them.
1339
1523
  2. Log the result (success/failure) in the tracker under `## Production Readiness`.
1340
1524
  3. In the final checklist output, mark auto-executed items with their result:
1341
1525
  ```
1342
- 1. **[Firebase Indexes]** Deploy Firestore composite indexes
1343
- - Command: `firebase deploy --only firestore:indexes --project <your-firebase-project>`
1526
+ 1. **[DB Indexes — <stack.database>]** Deploy indexes
1527
+ - Command: <stack-matched command from the Auto-executable table>
1344
1528
  - Result: DEPLOYED (took 45s) | FAILED (error: ...)
1345
1529
  ```
1346
1530
  4. If an auto-execution FAILS: log the error, mark it as `MANUAL FALLBACK NEEDED`,
1347
1531
  and include it in the "Required before deploy" section for the user to handle.
1348
1532
 
1349
- ### Firestore Index Verification (MUST — after deploy)
1533
+ ### DB Index Verification (MUST — after deploy)
1350
1534
 
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.
1535
+ After the deploy command succeeds, verify the indexes are actually live before
1536
+ reporting success. The deploy command typically returns before index propagation
1537
+ completes (Firestore: 510 minutes; Postgres `CREATE INDEX CONCURRENTLY` on a
1538
+ large table: minutes to hours; DynamoDB GSI: minutes; Mongo background index:
1539
+ minutes to hours).
1354
1540
 
1355
- **Verification procedure:**
1541
+ **Skip this section entirely when:**
1542
+ - the card has no `db_indexes` / `firestore_indexes` block, OR
1543
+ - `stack.database` is unset / `none`, OR
1544
+ - the card's index artifact is a SQL migration on a small table (the migration
1545
+ itself is synchronous and self-verifying — the deploy step already failed if
1546
+ the index didn't build).
1547
+
1548
+ **Verification procedure — pick the variant matching `stack.database`:**
1549
+
1550
+ #### Variant — Firestore (`stack.database: firestore`)
1551
+
1552
+ After `firebase deploy --only firestore:indexes` succeeds:
1356
1553
 
1357
1554
  1. **Extract expected collection groups** from the local `firestore.indexes.json`:
1358
1555
  ```bash
@@ -1373,7 +1570,6 @@ indexes can take 5-10 minutes to build.
1373
1570
  done | python3 -c "
1374
1571
  import sys, json, re
1375
1572
  raw = sys.stdin.read()
1376
- # Parse multiple JSON responses concatenated
1377
1573
  creating = []
1378
1574
  for match in re.finditer(r'\{[^{}]*\"indexes\"[^}]*\}', raw, re.DOTALL):
1379
1575
  try:
@@ -1394,19 +1590,55 @@ indexes can take 5-10 minutes to build.
1394
1590
  ```
1395
1591
 
1396
1592
  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
1593
 
1399
1594
  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
1595
+ - All `READY` `VERIFIED READY`.
1596
+ - Still `CREATING` after 10 retries `DEPLOYED BUT BUILDING` (warning).
1597
+ - Any `NEEDS_REPAIR` / `ERROR` `INDEX ERROR — manual intervention required`.
1598
+
1599
+ #### Variant — Postgres / Supabase (`stack.database` ∈ {postgres, supabase})
1600
+
1601
+ After the migration / `supabase db push` succeeds:
1602
+
1603
+ ```bash
1604
+ # For each index named in the migration:
1605
+ psql "$DATABASE_URL" -c "SELECT indexname, indexdef FROM pg_indexes WHERE indexname = '<index_name>';"
1606
+ # If the migration used CREATE INDEX CONCURRENTLY on a large table, also check:
1607
+ psql "$DATABASE_URL" -c "SELECT pid, phase, blocks_total, blocks_done FROM pg_stat_progress_create_index;"
1608
+ ```
1609
+
1610
+ If `pg_stat_progress_create_index` returns rows → index still building, poll every
1611
+ 30s. If `pg_indexes` returns 0 rows for an expected name → CRITICAL (migration
1612
+ silently skipped or rolled back).
1613
+
1614
+ #### Variant — MongoDB (`stack.database: mongodb`)
1615
+
1616
+ After the bootstrap script / migration runs:
1617
+
1618
+ ```bash
1619
+ mongosh "$MONGO_URL" --eval "db.<entity>.getIndexes()"
1620
+ ```
1621
+
1622
+ Confirm every expected `name`/`key` is present. For background-built indexes, watch
1623
+ `db.currentOp({'$or':[{op:'command','command.createIndexes':{$exists:true}}]})` until empty.
1624
+
1625
+ #### Variant — DynamoDB (`stack.database: dynamodb`)
1626
+
1627
+ After `cdk deploy` / `terraform apply`:
1628
+
1629
+ ```bash
1630
+ aws dynamodb describe-table --table-name <table> \
1631
+ --query 'Table.GlobalSecondaryIndexes[].{Name:IndexName,Status:IndexStatus}'
1632
+ ```
1633
+
1634
+ All GSIs must show `ACTIVE`. `CREATING` → poll; `DELETING` / `UPDATING` → manual review.
1403
1635
 
1404
1636
  **Checklist output format with verification:**
1405
1637
  ```
1406
- 1. **[Firebase Indexes]** Deploy Firestore composite indexes
1407
- - Command: `firebase deploy --only firestore:indexes --project <your-firebase-project>`
1638
+ 1. **[DB Indexes — <stack.database>]** Deploy indexes
1639
+ - Command: <stack-matched command>
1408
1640
  - Deploy: SUCCESS (took 45s)
1409
- - Verification: ALL INDEXES READY (155/155) | BUILDING (3 still creating after 5min) | ERROR (details)
1641
+ - Verification: ALL READY (5/5) | BUILDING (2 still creating after 5min) | ERROR (details)
1410
1642
  ```
1411
1643
 
1412
1644
  ### Rules