baldart 3.14.1 → 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 (25) hide show
  1. package/CHANGELOG.md +46 -0
  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
package/CHANGELOG.md CHANGED
@@ -5,6 +5,52 @@ All notable changes to BALDART will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.15.0] - 2026-05-23
9
+
10
+ Two changes ship together. **(1) PRD becomes mockup-aware** — formal intake of existing mockups between Kickoff and Discovery, with a per-screen decision tree in Step 3 that skips generation for screens already covered. **(2) Framework becomes stack-aware** — four new `stack.*` cardinal scalars (`database`, `auth_provider`, `framework`, `deployment`) drive vocabulary, gate sections, anti-pattern checklists, and deploy commands across `/prd`, `coder`, `api-perf-cost-auditor`, `/new`, `code-reviewer`, `security-reviewer`, `bug`. Project-identity assumptions previously hard-coded (mayo personas, real test credentials, Italian merchant business names) are removed from the framework and now resolved from `identity.audience_segments[]` + `.baldart/overlays/prd.md`. Sanitization sweep removed all PII (phone numbers, real usernames, real passwords, real store names) from the published payload.
11
+
12
+ ### Added — Mockup-aware PRD
13
+
14
+ - **Step 1.6 — Mockup Intake** in [framework/.claude/skills/prd/references/discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md). New mandatory step between Kickoff (Step 1) and Discovery (Step 2). Asks the user "Hai dei mockup a disposizione?" — if yes, asks for format (chat images / local paths / mixed), STOPs, and on receipt: copies local files into `${paths.prd_dir}/<slug>/mockups/` (with collision-safe rename), analyzes every mockup against the **Mockup analysis schema** (screens, user_flow, components, states_visible, copy_excerpts, gaps, design_system_alignment with violations when `features.has_design_system: true`), and populates `## UI Design` in the state file before entering Discovery. If "no", marks `mockups.status: none` and proceeds with the standard flow — fully backwards-compatible for projects without mockups.
15
+ - **Step 3 decision tree (Full / Hybrid / Skip)** in [framework/.claude/skills/prd/references/ui-design-phase.md](framework/.claude/skills/prd/references/ui-design-phase.md). Replaces the legacy "skip if UI N/A" precondition. The tree reads `mockups.status` + `screens_in_scope[]` from the state file and routes per-screen: covered-by-mockups screens skip 3a (options) and 3b (generation) — only Component Registry Lookup, approval gate (3c), and inventory (3d) run; uncovered screens invoke the `ui-design` subskill scoped to that single screen, passing the existing mockups as "design language anchor" so the new screen stays consistent. Includes a canonical 5-screen example (3 covered + 2 new) showing exactly which subskill invocations happen and how the final inventory merges.
16
+ - **"Design Reference & Mockup Inventory" section in the PRD template** ([framework/.claude/skills/prd/assets/prd-template.md](framework/.claude/skills/prd/assets/prd-template.md)). New section inserted between Documentation Impact and Section 1 (Problem Statement). Tracks `mockups.status`, `step_3_mode`, the screen inventory table (mapping each screen to its user story + mockup path + origin), the component-mapping table when a design system is in play (reused + new components + token violations), and the source-files traceability list (original user paths → canonical `mockups/` paths, or `chat://image-N` for inline images).
17
+ - **Mockup-aware fields in the state template** ([framework/.claude/skills/prd/assets/state-template.md](framework/.claude/skills/prd/assets/state-template.md)). Extends `## UI Design` with `mockups.{status,format,original_paths,canonical_paths}`, `mockup_analysis.{screens,user_flow,design_system_alignment}`, `step_3_mode`, `design.html_path`, `screens_in_scope`, `ui_inventory`. Single source of truth for everything Step 1.6 produces and Step 3 + PRD Writing consume.
18
+ - **PRD writing acknowledges mockup canonicality** in [framework/.claude/skills/prd/references/prd-writing-phase.md](framework/.claude/skills/prd/references/prd-writing-phase.md). The canonical sources resolution step now adds the `mockups/` directory as a canonical visual reference when `mockups.status` ∈ {`provided`, `partial`}, and the PRD sections checklist includes a new "Design Reference & Mockup Inventory" entry plus revised UI Specifications guidance to avoid duplication.
19
+ - **Hard Rule 16 (Mockup Intake) + Step 1.6 in the flow overview + progress-bar row** in [framework/.claude/skills/prd/SKILL.md](framework/.claude/skills/prd/SKILL.md). Codifies the new step as MANDATORY in the hard-rules section, adds the row `1.6 Mockup intake` to both the in-progress and completed progress-bar templates (with the `Mockup` and `Step 3 mode` summary lines), and adds a "Mockup-driven pre-population" note to the Quick Reference Comprehension Dimensions explaining how dimension 5 (UI impact) and partially dimension 2 (User journey) are pre-resolved from `mockup_analysis` when mockups are provided.
20
+ - **New-Screen Check during Discovery** in [framework/.claude/skills/prd/references/discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md). When a user answer reveals a UI screen NOT in `mockup_analysis.screens[]`, the skill no longer treats it as a generic scope expansion (which would offer `/prd-add`). Instead it appends the screen to `screens_in_scope[]` with `covered_by_mockups: false` and logs inline that Step 3 will generate that single screen in Hybrid mode. The Scope Expansion Check still applies for non-UI entities (new endpoints, roles, collections).
21
+
22
+ ### Added — Stack-aware framework
23
+
24
+ - **Four new `stack.*` scalar keys** in [framework/templates/baldart.config.template.yml](framework/templates/baldart.config.template.yml): `stack.database` (enum: firestore/supabase/postgres/mysql/mongodb/dynamodb/sqlite/none), `stack.auth_provider` (firebase-auth/supabase-auth/clerk/auth0/cognito/nextauth/lucia/custom/none), `stack.framework` (nextjs/remix/sveltekit/astro/nuxt/rails/django/fastapi/express/none), `stack.deployment` (vercel/firebase/aws/gcp/cloudflare/render/fly/self-hosted/none). Empty string preserves the always-ask contract — skills prompt the user when a needed scalar is unset and suggest `npx baldart configure`.
25
+ - **`baldart configure` autodetection + prompts for the 4 stack scalars** in [src/commands/configure.js](src/commands/configure.js). Autodetection probes `package.json` deps (`firebase`/`@supabase/*`/`pg`/`mongoose`/`@clerk/*`/`@auth0/*`/`next-auth`/`lucia`/`@aws-sdk/client-cognito-identity-provider`/`next`/`@remix-run/*`/`@sveltejs/kit`/`astro`/`nuxt`/`express`), file presence (`vercel.json`/`firebase.json`/`wrangler.toml`/`fly.toml`/`render.yaml`/`Gemfile`/`manage.py`/`requirements.txt`), and content patterns (Django/FastAPI in requirements, rails gem in Gemfile). Detected values pre-fill the interactive prompt. AUTODETECTED box surfaces all 4 values to the user.
26
+ - **`baldart update` schema-drift detector covers scalar `stack.*` keys** in [src/commands/update.js](src/commands/update.js). Extends the existing detector (which already flagged missing `features.*`, `paths.*`, `git.*` keys after an update) to enumerate `tpl.stack[*]` and report only the string-typed top-level scalars as `stack.<key>`. Sub-object keys (`charting`/`animation`/`testing`/`monorepo`/`design_system_signals`) are intentionally ignored — their drift is handled by their dedicated configure prompts. On missing scalars, the detector auto-offers `baldart configure`.
27
+ - **Database vocabulary branching in PRD writing** in [framework/.claude/skills/prd/references/prd-writing-phase.md](framework/.claude/skills/prd/references/prd-writing-phase.md). The Schema Verification Gate header now reads "MANDATORY if feature touches the persistence layer" instead of "if feature touches Firestore"; vocabulary adapts ({entity} = collection|table, {field} = field|column); the schema-registry path resolves via overlay → `stack.database` convention (Firestore `field-registry.json`, SQL `prisma/schema.prisma` or migrations dir, Mongo collection markdown). The PRD-template's Section 5 "Data Model" now ships **5 variants** (Firestore Composite, Relational B-tree+RLS, MongoDB compound, DynamoDB GSI/LSI, None) — the writer keeps only the variant matching `stack.database`.
28
+ - **api-perf-gate refactored as universal-core + stack addenda** in [framework/.claude/skills/prd/references/api-perf-gate.md](framework/.claude/skills/prd/references/api-perf-gate.md). Gate 5 (keyword scan): universal keywords + "Stack-specific keyword addenda" table activated only by the matching `stack.database`. Gates 1–3: universal checklist + "Stack-specific addenda" per `stack.database` (firestore listener/index/ID-hotspot rules, postgres/supabase RLS+EXPLAIN+JSONB rules, mongo compound-field-order+embed rules, dynamodb GSI+hot-partition rules) and per `stack.framework` (nextjs Route Handler `revalidate`/`use cache`, remix `headers`+`shouldRevalidate`, sveltekit runtime declaration, astro `prerender`). Reference Data section split into "Database pricing & cost-model snapshots" (4 stacks), "Runtime limits by `stack.deployment`" (Vercel/Cloudflare/AWS/Firebase table), "Framework caching primitives by `stack.framework`" (4 frameworks). User cites only the variant matching their config.
29
+ - **coder.md Database Index Invariant** in [framework/.claude/agents/coder.md](framework/.claude/agents/coder.md). Renamed from "Firestore Index Invariant"; ships per-stack instructions (Firestore composite + `firestore.indexes.json`, Postgres/Supabase `EXPLAIN` + migration with covering/GIN/RLS, MongoDB `createIndex` with equality→range→sort field order, DynamoDB GSI/LSI in CDK/Terraform, None/unset → skip with warning).
30
+ - **prd-card-writer Field Grounding Rule per-stack registry resolution** in [framework/.claude/agents/prd-card-writer.md](framework/.claude/agents/prd-card-writer.md). The Grep target for field verification is no longer hard-coded to `docs/references/field-registry.json` — it resolves via `.baldart/overlays/prd.md § Schema Registry` first, then by convention matching `stack.database` (Firestore field-registry, Prisma schema, SQL migrations, Mongo collection docs, DynamoDB table definition). Universal identifiers (`id`/`uuid`/PK, `createdAt`/`created_at`, `updatedAt`/`updated_at`) are exempt regardless of stack.
31
+ - **api-perf-cost-auditor reads stack scalars at session start** in [framework/.claude/agents/api-perf-cost-auditor.md](framework/.claude/agents/api-perf-cost-auditor.md). The agent's "Project Context" section is no longer hard-coded to "Next.js 16 + Firestore + Vercel Fluid Compute" — it now lists universal hard rules + addenda tables for `stack.framework`, `stack.database`, `stack.deployment`, and cites the resolved values in every audit header so the user knows which variant applied. Perf budgets move out of the agent into `${paths.references_dir}/perf-budgets.md` (consumer-owned); absence is flagged as a `BUDGETS_GAP` warning instead of using framework-baked numbers.
32
+ - **security-reviewer multi-stack access-rule coverage** in [framework/.claude/agents/security-reviewer.md](framework/.claude/agents/security-reviewer.md). Rule 6 (cloud/infra risks) lists the access-rule variant per `stack.database`: Firebase security rules, Supabase RLS policies, MongoDB validators + collection access, DynamoDB IAM policies, Postgres GRANT/REVOKE + RLS.
33
+ - **`/new` Production Readiness Checklist becomes stack-aware** in [framework/.claude/skills/new/SKILL.md](framework/.claude/skills/new/SKILL.md). Detection table and auto-executable commands branch on `stack.deployment` + `stack.database`. Firebase commands are no longer the default — they're one branch among many (vercel deploy, supabase db push, CDK/Terraform apply, firebase deploy). When `stack.deployment` is empty, the skill infers from config-file presence and falls back to asking the user — never auto-executes a guess.
34
+ - **`/new` end-to-end flow generalized for non-Firestore stacks** in [framework/.claude/skills/new/SKILL.md](framework/.claude/skills/new/SKILL.md). Five additional spots got the same treatment so a Supabase / Postgres / Mongo / DynamoDB project doesn't see Firestore-only instructions: pre-flight `data_fields` warning triggers on `db_indexes` (any dialect) and reads "touches the persistence layer" instead of "touches Firestore"; Codex parallel-conflict analyzer asks about same-{entity} writes in the project's vocabulary; DEEP-review trigger keys off `db_indexes` (legacy `firestore_indexes` still recognized); the Coder Briefing's index section ships per-`stack.database` instructions (Firestore JSON snippet, SQL migration / Prisma `@@index`, Mongo `createIndex`, DynamoDB GSI/LSI in IaC) and explicitly tells the agent which artifact to stage; post-implementation verification of compound queries branches into 4 dialects with their own missing-index severity; Docs Routing Reminder uses `{entity}` vocabulary and points at the stack-matched index artifact; and the post-deploy "DB Index Verification" section (previously Firestore-only with curl to the Firestore REST API) now opens with a Skip rule and 4 dialect variants (Firestore REST API, Postgres `pg_indexes` + `pg_stat_progress_create_index`, Mongo `getIndexes` + `currentOp`, DynamoDB `describe-table` GSI status). The Firestore variant retains its full procedure verbatim — no regression for Firestore consumers.
35
+ - **bug/logging-patterns.md framework-agnostic** in [framework/.claude/skills/bug/references/logging-patterns.md](framework/.claude/skills/bug/references/logging-patterns.md). The Next.js 16 logging section is now one of four (Next.js, Remix, SvelteKit, Astro/Nuxt) plus a generic `pino`/`winston` fallback. DB-tracing env var examples document the per-stack equivalent (`DEBUG_FIRESTORE=true`, `SUPABASE_DEBUG=true`, `DEBUG=knex:query`, `DEBUG=mongoose:*`).
36
+ - **Persona references generalized to `identity.audience_segments[]`** in [framework/.claude/skills/prd/references/discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md), [framework/.claude/skills/prd/references/prd-writing-phase.md](framework/.claude/skills/prd/references/prd-writing-phase.md), [framework/.claude/skills/prd/references/audit-phase.md](framework/.claude/skills/prd/references/audit-phase.md), [framework/.claude/skills/prd/assets/card-template.yml](framework/.claude/skills/prd/assets/card-template.yml), [framework/.claude/skills/prd/assets/epic-template.yml](framework/.claude/skills/prd/assets/epic-template.yml), [framework/.claude/skills/prd/assets/prd-template.md](framework/.claude/skills/prd/assets/prd-template.md). Hard-coded persona literals (`CUSTOMER`/`MERCHANT`/`MERCHANT_STAFF`/`SUPER_ADMIN`) are gone from the framework — replaced by `{{from identity.audience_segments[]}}` placeholders and explicit instructions to loop over the project-declared segments. AC grouping in PRD writing now reads "one group per persona drawn from `identity.audience_segments[]`, plus cross-cutting groups".
37
+ - **`db_indexes` field replaces `firestore_indexes` in card YAML** in [framework/.claude/skills/prd/assets/card-template.yml](framework/.claude/skills/prd/assets/card-template.yml). The card template renames the section; entries gain a `dialect` field matching `stack.database` and a `kind` field (composite/covering/partial/GIN/GSI/LSI/unique/fulltext). The legacy `firestore_indexes` name remains accepted as an alias so v3.14.x cards keep working — the validator in [framework/.claude/skills/prd/references/validation-phase.md](framework/.claude/skills/prd/references/validation-phase.md) recognizes both. Metric `has_firestore_indexes_pct` in [framework/.claude/skills/prd/SKILL.md](framework/.claude/skills/prd/SKILL.md) renamed to `has_db_indexes_pct`.
38
+ - **PROJECT-CONFIGURATION.md § 4.4 documents the 4 new scalars** in [framework/docs/PROJECT-CONFIGURATION.md](framework/docs/PROJECT-CONFIGURATION.md). New "Stack-cardinal scalars" subsection enumerates the 8 skills/agents that branch on them, the always-ask contract on empty values, and the schema-drift detector behavior.
39
+
40
+ ### Removed — PII sanitization
41
+
42
+ - **Test credentials (phone, username, password, store name) removed from the published payload.** [framework/.claude/skills/prd/references/discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md), [framework/.claude/skills/prd/assets/prd-template.md](framework/.claude/skills/prd/assets/prd-template.md), [framework/.claude/skills/prd/assets/card-template.yml](framework/.claude/skills/prd/assets/card-template.yml) no longer ship any real credential as "example". The discovery Test Strategy step now (a) consults `.baldart/overlays/prd.md § Test Credentials` first, (b) asks the user one structured question per persona if the overlay is silent, (c) stores a credential REFERENCE (secret-manager path, `.env.test:VAR_NAME`) in the state file instead of the literal secret, and (d) explicitly forbids the framework from carrying real PII.
43
+
44
+ ### Notes
45
+
46
+ - **One CLI change — `baldart configure`.** v3.15.0 adds autodetection + prompts for the 4 `stack.*` scalars and extends the `baldart update` schema-drift detector to flag missing scalar `stack.*` keys. Consumers upgrading from v3.14.x get the new prompts on the next `baldart configure` invocation; the detector triggers automatically on the next `baldart update`.
47
+ - **The schema-change propagation rule applied end-to-end** for the 4 new scalars: template ✓, configure prompt ✓, update detector ✓, doctor not extended (the always-ask contract in skills already covers the empty case), CHANGELOG ✓.
48
+ - **Backwards-compatibility for v3.14.x cards.** Cards with the legacy `firestore_indexes` field still validate (the writer-side renamed it to `db_indexes`, but the validator and downstream agents accept both names). Cards with `type: firestore` in `data_sources` are equivalent to `type: db, db_dialect: firestore`.
49
+ - **Active PRD sessions started under v3.14.x** do not have `## UI Design` populated with the mockup fields; the skill treats `pending`/missing as `mockups.status: none` and falls into the Full Step-3 branch (legacy behavior). New sessions on v3.15.0+ pick up Step 1.6 automatically.
50
+ - **Step 3 Hybrid mode preserves the design-system cascade.** When `features.has_design_system: true`, the BLOCKING reads of `${paths.design_system}/INDEX.md` + `tokens-reference.md` run BOTH in Step 1.6 (during mockup analysis, to flag violations early) AND in Step 3 (during per-screen Component Registry Lookup, to validate covered + new screens uniformly). Violations bubble up to the unified 3c approval gate.
51
+ - **Sanitization is final, not a heuristic.** Grep across `framework/` for `3486417303`, `antonio.baldassarre2336`, `bRkS2bzqyesK`, `Bar Roma` returns zero hits after this release. Consumers who already had `.baldart/overlays/prd.md` with their real credentials are unaffected — the overlay never leaves the consumer repo.
52
+ - **Verification is manual** (no test suite — `npm test` is no-op stub). Scenarios to dogfood after install: (1) `npx baldart update` on a v3.14.x consumer → schema-drift detector flags 4 new `stack.*` keys → `baldart configure` autodetection pre-fills them; (2) `/prd` on a Supabase project (`stack.database: supabase`) → Schema Verification Gate uses Variant B (Relational), api-perf-gate adds postgres+supabase addenda, audit-phase enforces RLS; (3) `/prd` on a Firestore project (`stack.database: firestore`) → behavior identical to v3.14.x (no regression); (4) `/prd` with mockups → mockup intake + Hybrid Step 3; (5) `/new` on a Cloudflare deployment (`stack.deployment: cloudflare`) → no `firebase deploy` commands proposed.
53
+
8
54
  ## [3.14.1] - 2026-05-23
9
55
 
10
56
  Hotfix for the `.framework/` gitignore self-heal shipped in v3.14.0. The detector misread `git check-ignore -v` output: when `check-ignore` matched a negation pattern (`!.framework`), it still reported the match, and `checkFrameworkIgnored` flagged the path as ignored. The result: every consumer who hit the self-heal on first run got `.framework/ is STILL ignored after auto-heal` and `process.exit(1)` — the heal *had* actually worked (the negation was in place), but the verifier didn't recognize its own fix. Reported during the v3.13.0 → v3.14.0 update in a downstream consumer.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.14.1
1
+ 3.15.0
@@ -39,16 +39,53 @@ To prevent context bloat:
39
39
  - Max **5 search_docs MCP calls**.
40
40
  - Never read files outside `git diff --name-only` (or scope passed by orchestrator) unless tracing a callgraph that proves a regression.
41
41
 
42
- ## Project Context (Next.js 16 + Firestore + Vercel Fluid Compute)
43
-
44
- - Default runtime: Fluid Compute (Node.js 24 LTS). Edge runtime is **not** the recommended default.
45
- - Vercel Functions billing: Active CPU + provisioned memory + invocations. **Not** wall-clock GB-s.
46
- - Firestore is the dominant cost driver. Hard rules from AGENTS.md NFR Performance:
47
- - Every `where()` MUST include `.limit()`.
48
- - Pagination MUST be cursor-based (`startAfter()`), never offset-based.
49
- - No `getDoc()` in loops batch with `getAll()` / `getDocs()`.
50
- - Composite queries require updated `firestore.indexes.json` in same commit.
51
- - Project performance budgets: API route p99 < 2s (lightweight < 500ms), ≤ 50 Firestore reads / route, bundle ≤ 250KB gzipped.
42
+ ## Project Context (read from `baldart.config.yml`)
43
+
44
+ Read `stack.framework`, `stack.database`, `stack.deployment` at the start of
45
+ every audit. The rules below adapt automatically; cite the resolved values in
46
+ your findings header so the user knows which variant you applied.
47
+
48
+ **Universal hard rules** (apply to any stack):
49
+ - Every list query MUST include a `limit` (or equivalent pagination size).
50
+ - Pagination MUST be cursor/keyset-based, never offset-based on hot paths.
51
+ - No N+1 reads in loops batch / join / `$lookup` / `getAll` per stack.
52
+ - Multi-attribute queries require their matching index shipped in the same commit
53
+ as the query (see Database Index Invariant in coder.md per `stack.database`).
54
+
55
+ **Stack-specific addenda** (apply only when matching):
56
+
57
+ - `stack.framework: nextjs` → Default runtime Fluid Compute (Node.js 24 LTS).
58
+ Edge runtime is not the recommended default. GET Route Handlers are dynamic
59
+ by default since v15 — opt in to caching via `revalidate` / `'use cache'`.
60
+ - `stack.framework: remix` → Set `headers` for Cache-Control explicitly.
61
+ Rely on CDN-level caching.
62
+ - `stack.framework: sveltekit` → Choose Edge vs Node runtime per route;
63
+ declare `prerender` for static pages.
64
+
65
+ - `stack.database: firestore` → Hard rules from AGENTS.md NFR Performance:
66
+ every `where()` includes `.limit()`; pagination uses `startAfter()`; no
67
+ `getDoc()` in loops; composite queries update `firestore.indexes.json` in
68
+ the same commit.
69
+ - `stack.database: postgres | supabase | mysql | sqlite` → `EXPLAIN` every
70
+ new query on a >10k-row table; surface Seq Scan as a HIGH finding.
71
+ Supabase: every new table needs RLS aligned with the auth contract (CRITICAL).
72
+ - `stack.database: mongodb` → Compound index field order: equality → range →
73
+ sort. Aggregations on hot paths must use indexes (no `$match` after
74
+ `$project` that strips the indexed field).
75
+ - `stack.database: dynamodb` → Every non-PK access pattern has a GSI / LSI.
76
+ Reject `FilterExpression` on hot paths.
77
+
78
+ - `stack.deployment: vercel` → Active CPU + provisioned memory + invocations
79
+ billing (not wall-clock GB-s). Payload limit 4.5 MB. Max duration 300s
80
+ Hobby / 800s Pro.
81
+ - `stack.deployment: cloudflare` → 30s CPU per request; 100 MB payload.
82
+ - `stack.deployment: aws` → Lambda 6 MB sync / 256 KB async, max 900s.
83
+ - `stack.deployment: firebase` → 32 MB payload, max 540s (gen 2).
84
+
85
+ **Project performance budgets** are NOT hard-coded here. They live in
86
+ `${paths.references_dir}/perf-budgets.md` (consumer-owned). If that file does
87
+ not exist, derive ad-hoc defaults from the stack snapshot above and flag the
88
+ absence in your audit summary as a `BUDGETS_GAP` warning.
52
89
 
53
90
  ## Scope Boundary (MUST — read first)
54
91
 
@@ -161,16 +161,67 @@ This rule is enforced by:
161
161
  - `.claude/skills/new/SKILL.md § Phase 3.7 trigger #6` (mutation-after-helper
162
162
  call invokes per-card `/codexreview` before commit).
163
163
 
164
- ## Firestore Index Invariant (MUST)
165
-
166
- When writing or modifying Firestore queries that use `where()` + `orderBy()` on different fields, or multiple `where()` on different fields:
167
-
168
- 1. **Check `firestore.indexes.json`** does a composite index exist for this exact query pattern (collection, fields, order)?
169
- 2. **If missing**: add the index to `firestore.indexes.json` and stage it with your commit. Use the existing entries as format reference.
170
- 3. **For dynamic queries** (`let query = ...; if (x) query = query.where(...)`) — add a JSDoc comment above the function: `/** @requires-index: collectionGroup(field1 ASC, field2 DESC) */`
171
- 4. **Remember**: all-equality queries (only `==` filters, no `orderBy` on a different field) do NOT need composite indexes. Only compound queries mixing equality + inequality/range + orderBy on different fields need them.
172
-
173
- Missing indexes cause **500 errors in production** (Firestore FAILED_PRECONDITION, error code 9) that are invisible until runtime.
164
+ ## Database Index Invariant (MUST)
165
+
166
+ When writing or modifying queries that combine filters and orderings on
167
+ different attributes, ensure the matching index exists and ships in the same
168
+ commit as the query. Apply the variant matching `stack.database` from
169
+ `baldart.config.yml`:
170
+
171
+ **Variant Firestore (`stack.database: firestore`)**
172
+
173
+ Where `where()` + `orderBy()` on different fields, or multiple `where()` on
174
+ different fields:
175
+
176
+ 1. Check `firestore.indexes.json` for a composite index matching the exact
177
+ pattern (collection, fields, order).
178
+ 2. If missing: add it and stage with your commit.
179
+ 3. For dynamic queries (`let query = ...; if (x) query = query.where(...)`)
180
+ add a JSDoc: `/** @requires-index: collectionGroup(field1 ASC, field2 DESC) */`
181
+ 4. All-equality queries (only `==` filters, no `orderBy` on a different
182
+ field) do NOT need composite indexes.
183
+
184
+ Missing indexes cause **500 errors in production** (`FAILED_PRECONDITION`,
185
+ error code 9) invisible until runtime.
186
+
187
+ **Variant — Relational (`stack.database` ∈ {postgres, supabase, mysql, sqlite})**
188
+
189
+ When the query uses `WHERE col_a = ? AND col_b > ? ORDER BY col_c`, or any
190
+ JOIN/sort/filter combination that can produce a sequential scan on a hot
191
+ table:
192
+
193
+ 1. Run `EXPLAIN` (or `EXPLAIN ANALYZE` in dev) on the new query. Verify the
194
+ planner picks an Index Scan or Index Only Scan, not Seq Scan, on tables
195
+ with >10k rows.
196
+ 2. If a Seq Scan appears: add a composite or covering index in a new migration
197
+ (`migrations/<ts>_add_<entity>_<purpose>_idx.sql`, or
198
+ `prisma migrate dev` / `supabase migration new` per project conventions).
199
+ 3. Stage the migration with the same commit as the query change.
200
+ 4. For JSONB queries: ensure a GIN index exists on the JSONB column when
201
+ the query filters on it.
202
+ 5. For Supabase: every new table also requires an RLS policy aligned with the
203
+ PRD permissions section.
204
+
205
+ **Variant — MongoDB (`stack.database: mongodb`)**
206
+
207
+ 1. Check the collection's indexes via `db.<collection>.getIndexes()` (or the
208
+ schema file the project uses as registry).
209
+ 2. For compound queries, ensure the index field order follows
210
+ equality → range → sort.
211
+ 3. Add the index in code (`createIndex`) or migration, in the same commit.
212
+
213
+ **Variant — DynamoDB (`stack.database: dynamodb`)**
214
+
215
+ 1. Every non-PK access pattern needs either a GSI or LSI declared in the
216
+ table definition (CDK / Terraform / SAM template).
217
+ 2. Update the table definition in the same commit as the new query.
218
+ 3. Avoid `FilterExpression` on hot paths — pick a GSI instead.
219
+
220
+ **Variant — None / unset**
221
+
222
+ If `stack.database` is empty or `"none"`, skip this section. If you encounter
223
+ persistence code while `stack.database` is empty, surface a warning suggesting
224
+ `npx baldart configure`.
174
225
 
175
226
  ## Incremental Verification (MUST)
176
227
 
@@ -15,7 +15,15 @@ You are **PRD Card Writer** — a specialist agent that converts an approved PRD
15
15
  1. **Read the PRD `## Schema Verification` section** (generated during Step 4 of the PRD skill).
16
16
  Every field you write MUST appear in that table with status `✅ existing` or `🆕 new`.
17
17
 
18
- 2. **For each `✅ existing` field**: call `Grep("fieldName", "docs/references/field-registry.json")`.
18
+ 2. **For each `✅ existing` field**: call `Grep("fieldName", <schema-registry-path>)`.
19
+ The registry path is resolved per the project:
20
+ - `.baldart/overlays/prd.md § Schema Registry` defines it explicitly when present;
21
+ - otherwise the convention follows `stack.database`:
22
+ - firestore → `${paths.references_dir}/field-registry.json`
23
+ - postgres/supabase/mysql/sqlite → `prisma/schema.prisma` OR `${paths.references_dir}/schema.md` OR the latest migration under the project's migrations dir;
24
+ - mongodb → `${paths.references_dir}/collections/<name>.md` or a JSON schema file in the validator dir;
25
+ - dynamodb → the CDK / Terraform table definition file.
26
+ Then:
19
27
  - ≥1 match → set `ts_verified: true` in the card's `data_fields` entry.
20
28
  - 0 matches → HALT. Do NOT use this field. Ask: "Field not found in registry — is it new or a typo?"
21
29
 
@@ -23,9 +31,9 @@ You are **PRD Card Writer** — a specialist agent that converts an approved PRD
23
31
 
24
32
  4. **NEVER invent a field name** not in the Schema Verification snapshot, even if it "sounds right".
25
33
 
26
- 5. **Exempt from verification** (do not include in `data_fields`): `id`, `createdAt`, `updatedAt`.
34
+ 5. **Exempt from verification** (do not include in `data_fields`): the project's universal identifiers — `id`/`uuid`/PK, `createdAt`/`created_at`, `updatedAt`/`updated_at`.
27
35
 
28
- 6. **Populate `data_fields`** for every card that reads/writes Firestore documents (see Required Fields).
36
+ 6. **Populate `data_fields`** for every card that reads/writes the persistence layer (see Required Fields).
29
37
 
30
38
  ## Mission
31
39
 
@@ -127,7 +135,7 @@ applies even when N=1.
127
135
  4. **Reusing the FEAT-XXXX integer**. Each epic reserves the full integer space.
128
136
  5. **Epic with implementation fields**. The epic NEVER has `files_likely_touched`
129
137
  pointing to code (only docs), `validation_commands`, `existing_patterns`,
130
- `data_fields`, `data_sources` beyond `[]`, or `firestore_indexes`.
138
+ `data_fields`, `data_sources` beyond `[]`, or `db_indexes` (legacy `firestore_indexes` alias also forbidden on epics).
131
139
 
132
140
  ### Why MANDATORY
133
141
 
@@ -188,31 +196,33 @@ Every card MUST include ALL fields from the template:
188
196
  - `data_sources` — MANDATORY for EVERY card (never omit, even if empty):
189
197
  - High-level inventory of every data source or destination the card touches.
190
198
  - One entry per distinct source. Supported types:
191
- - `firestore`: collection name in `path`; field-level detail lives in `data_fields` (below).
199
+ - `db`: {entity} name in `path` (collection/table/index per `stack.database`); set `db_dialect` to the matching value. Field-level detail lives in `data_fields` (below).
192
200
  - `file`: repo-relative path, `operations` (READ|WRITE|APPEND|CREATE|DELETE), `format` (JSONL|YAML|JSON|markdown|binary).
193
201
  - `api`: URL or endpoint pattern; READ = GET, WRITE = POST/PUT/PATCH/DELETE.
194
202
  - `env`: env var name; `operations: [READ]`.
203
+ - **Legacy:** `firestore` is still accepted (treated as `db` with `db_dialect: firestore`).
195
204
  - For **pure docs/config/scaffolding cards** that read and write no data: set `data_sources: []` (explicit empty list — confirms the writer verified there are no sources; never silently omit the field).
196
- - For **Firestore cards**: include `type: firestore` entries here AND populate `data_fields` below. The two fields serve different purposes: `data_sources` is the traceable overview; `data_fields` is the field-level grounding for mechanical validation.
197
- - For **file-based tooling cards** (scripts, CLIs, hooks): list each file or directory the card reads from or writes to. This is the primary documentation for non-Firestore data flows.
198
- - `data_fields` — MANDATORY if card reads/writes any Firestore document:
199
- - For each field the card touches (excluding `id`, `createdAt`, `updatedAt`):
200
- - `collection`: exact collection name (must match key in `field-registry.json`)
201
- - `field`: exact field name (verified via Grep per Field Grounding Rule above)
202
- - `type`: TypeScript type string from the interface
205
+ - For **persistence-touching cards**: include `type: db` entries here AND populate `data_fields` below. The two fields serve different purposes: `data_sources` is the traceable overview; `data_fields` is the field-level grounding for mechanical validation.
206
+ - For **file-based tooling cards** (scripts, CLIs, hooks): list each file or directory the card reads from or writes to. This is the primary documentation for non-DB data flows.
207
+ - `data_fields` — MANDATORY if card reads/writes the persistence layer:
208
+ - For each field the card touches (excluding universal identifiers — `id`/`uuid`/PK, `createdAt`/`created_at`, `updatedAt`/`updated_at`):
209
+ - `entity`: exact collection or table name (must match key in the schema registry resolved per Field Grounding Rule step 2)
210
+ - `field`: exact identifier (verified via Grep per Field Grounding Rule above)
211
+ - `type`: language-native type from the schema (TypeScript interface / Prisma model / SQL column / Mongo validator)
203
212
  - `status`: `existing` | `new` | `modified` | `deprecated_removed`
204
213
  - `ts_verified`: `true` (after Grep confirms field in registry) or `false` (new fields only)
205
- - `source`: TypeScript file path where interface is defined (e.g. `src/types/booking.ts`)
214
+ - `source`: schema file path (e.g. `src/types/booking.ts`, `prisma/schema.prisma:42`, `migrations/2024_...sql`)
206
215
  - `schema_ref`: PRD section link — ONLY for `status: new` fields
207
216
  - Omit this block entirely for UI-only, docs-only, or config-only cards.
208
- - `firestore_indexes` — propagated from PRD Section 5 `### Firestore Composite Indexes` table:
209
- - For each card that introduces or modifies a Firestore query with compound fields
210
- (`where()` + `orderBy()` on different fields, or multiple `where()` on different fields),
217
+ - `db_indexes` — propagated from PRD Section 5 `### Database Indexes & Query Optimization` table:
218
+ - For each card that introduces or modifies a query needing a multi-attribute index
219
+ (Firestore composite, SQL B-tree/covering, Mongo compound, DynamoDB GSI/LSI),
211
220
  include the matching `IDX-N` entries from the PRD index table.
212
- - Each entry: `collection`, `fields` (with order ASC/DESC), `query_location`, `prd_ref`.
221
+ - Each entry: `entity`, `dialect` (matches `stack.database`), `fields`, `kind`, `query_location`, `prd_ref`.
213
222
  - If the PRD has no index table or this card has no compound queries: omit the field entirely.
214
- - **CRITICAL**: missing indexes cause runtime FAILED_PRECONDITION (500 in production).
215
- The coder MUST add these to `firestore.indexes.json` in the same commit as the query code.
223
+ - **CRITICAL**: missing indexes degrade performance or break production (Firestore: FAILED_PRECONDITION 500; SQL: sequential scan on hot path; DynamoDB: throttle on hot partition).
224
+ The coder MUST ship the index in the same commit as the query — per `stack.database` (firestore.indexes.json, migration file, createIndex call, table definition).
225
+ - Legacy field name `firestore_indexes` is still accepted for pre-3.15.0 cards.
216
226
  - `documentation_impact` — list of docs to update when card is DONE:
217
227
  - New `route.ts` -> `docs/references/api/<module>.md` + `api/index.md`
218
228
  - New collection -> `docs/references/data-model.md` + `collections/<domain>.md`
@@ -43,7 +43,7 @@ Before reviewing:
43
43
  3. **Flag security anti-patterns**: unsafe libraries, insecure framework usage, dangerous data flows.
44
44
  4. **Review comprehensively**: authentication, authorization, session handling, secrets management, cryptography, input validation, output encoding, deserialization, file handling, logging, error handling.
45
45
  5. **Assess attack vectors**: SSRF, XSS, CSRF, SQL/NoSQL injection, command injection, path traversal, RCE, IDOR, broken access control, race conditions, insecure randomness, data leakage.
46
- 6. **Evaluate cloud/infra risks**: IAM over-permissioning, public exposure, insecure storage, CI/CD secret leakage, supply chain risks, Firebase security rules.
46
+ 6. **Evaluate cloud/infra risks**: IAM over-permissioning, public exposure, insecure storage, CI/CD secret leakage, supply chain risks, persistence-layer access rules (variant per `stack.database`: Firebase security rules, Supabase RLS policies, MongoDB validators + role-based collection access, DynamoDB IAM policies, Postgres GRANT/REVOKE + RLS).
47
47
  7. **Assess privacy/data protection**: PII exposure, credential leakage, tokens in logs, internal ID exposure.
48
48
  8. **Evaluate dependencies**: third-party integration risks visible in code or manifests.
49
49
  9. **Propose remediations**: concrete, minimal, production-ready fixes.
@@ -1,8 +1,13 @@
1
1
  # Logging Patterns & Debug Environment Reference
2
2
 
3
- ## Next.js 16 Built-In Logging (next.config.ts)
3
+ > Pick the section matching `stack.framework` from `baldart.config.yml`. The
4
+ > first section (Next.js) is the most common; sections for other frameworks
5
+ > follow the same intent: maximize signal during a debug session, with a way
6
+ > to turn it off cleanly when done.
4
7
 
5
- Add these to `next.config.ts` during debug sessions:
8
+ ## Next.js 16 Built-In Logging (`stack.framework: nextjs`)
9
+
10
+ Add to `next.config.ts` during debug sessions:
6
11
 
7
12
  ```typescript
8
13
  logging: {
@@ -17,17 +22,49 @@ logging: {
17
22
 
18
23
  `browserToTerminal` (v16.2+) is the most powerful: it streams client-side `console.*` to the dev server terminal with file:line:col source location. No code changes needed.
19
24
 
25
+ ## Remix Built-In Logging (`stack.framework: remix`)
26
+
27
+ - Enable `loader` / `action` timing via `DEBUG=remix:*` env.
28
+ - For request logging, instrument `entry.server.ts` with a `handleRequest`
29
+ wrapper that logs method/path/duration.
30
+ - Browser console forwarding: not built-in; use a small client-side logger
31
+ posting to `/__debug` route handler during the session.
32
+
33
+ ## SvelteKit (`stack.framework: sveltekit`)
34
+
35
+ - Enable verbose `vite` logging via `vite --debug` for build-time issues.
36
+ - `handle` hook in `hooks.server.ts` is the natural choke point: log
37
+ method/path/duration there during a session.
38
+
39
+ ## Astro / Nuxt / Other
40
+
41
+ - Use the framework's request hook (Astro middleware, Nuxt `defineEventHandler`
42
+ wrapper) to log structured request/response data.
43
+ - Stick to plain `console.log` with a unique prefix that's easy to grep and
44
+ remove (e.g. `[BUG-1234]`).
45
+
46
+ ## Generic fallback (any framework)
47
+
48
+ When the framework has no built-in equivalent, add `pino` or `winston` to the
49
+ project and emit JSON logs at every interesting choke point (request entry,
50
+ DB call, external API call). Remove on session close.
51
+
20
52
  ## Environment Variables for Debug Sessions
21
53
 
22
54
  Set in `.env.local` during investigation, remove after:
23
55
 
24
56
  ```bash
25
- DEBUG_MODULES=reservations.patch,booking.schedule # server-side module filter
26
- DEBUG_FIRESTORE=true # Firestore op tracing
27
- DEBUG_NETWORK=true # request/response logging
28
- DEBUG_PROXY=true # proxy/middleware logging
29
- NEXT_PUBLIC_DEBUG_COMPONENTS=booking.form,planner # client component logs (rebuild required)
30
- NEXT_OTEL_VERBOSE=1 # verbose OpenTelemetry spans
57
+ # Examples pick the ones matching this project's stack:
58
+ DEBUG_MODULES=<module>.<verb> # server-side module filter (project-specific)
59
+ DEBUG_DB=true # generic DB op tracing — name varies by stack:
60
+ # firestore → DEBUG_FIRESTORE=true
61
+ # supabase → SUPABASE_DEBUG=true
62
+ # postgres → DEBUG=knex:query (or your ORM's flag)
63
+ # mongo → DEBUG=mongoose:* (if using mongoose)
64
+ DEBUG_NETWORK=true # request/response logging
65
+ DEBUG_PROXY=true # proxy/middleware logging
66
+ NEXT_PUBLIC_DEBUG_COMPONENTS=<module> # Next.js only — client component logs (rebuild required)
67
+ NEXT_OTEL_VERBOSE=1 # Next.js only — verbose OpenTelemetry spans
31
68
  NEXT_TURBOPACK_TRACING=1 # Turbopack bundler trace → .next/dev/trace-turbopack
32
69
  ```
33
70