@donotdev/cli 0.0.12 โ†’ 0.0.14

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 (85) hide show
  1. package/dependencies-matrix.json +32 -118
  2. package/dist/bin/commands/agent-setup.d.ts +6 -0
  3. package/dist/bin/commands/agent-setup.d.ts.map +1 -0
  4. package/dist/bin/commands/agent-setup.js +623 -0
  5. package/dist/bin/commands/agent-setup.js.map +1 -0
  6. package/dist/bin/commands/build.js +13 -12
  7. package/dist/bin/commands/bump.js +103 -35
  8. package/dist/bin/commands/cacheout.js +13 -12
  9. package/dist/bin/commands/create-app.js +53 -151
  10. package/dist/bin/commands/create-project.js +109 -167
  11. package/dist/bin/commands/deploy.js +7620 -30
  12. package/dist/bin/commands/dev.js +13 -12
  13. package/dist/bin/commands/emu.js +13 -12
  14. package/dist/bin/commands/firebase-setup.d.ts +6 -0
  15. package/dist/bin/commands/firebase-setup.d.ts.map +1 -0
  16. package/dist/bin/commands/firebase-setup.js +7 -0
  17. package/dist/bin/commands/firebase-setup.js.map +1 -0
  18. package/dist/bin/commands/format.js +13 -12
  19. package/dist/bin/commands/lint.js +13 -12
  20. package/dist/bin/commands/preview.js +13 -12
  21. package/dist/bin/commands/staging.d.ts +11 -0
  22. package/dist/bin/commands/staging.d.ts.map +1 -0
  23. package/dist/bin/commands/staging.js +12 -0
  24. package/dist/bin/commands/staging.js.map +1 -0
  25. package/dist/bin/commands/sync-secrets.js +13 -12
  26. package/dist/bin/commands/wai.js +7397 -11
  27. package/dist/bin/dndev.js +28 -3
  28. package/dist/bin/donotdev.js +28 -3
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +7760 -109
  32. package/dist/index.js.map +1 -1
  33. package/package.json +1 -1
  34. package/templates/app-demo/src/pages/DetailPage.tsx.example +1 -1
  35. package/templates/app-demo/src/pages/FullPage.tsx.example +3 -3
  36. package/templates/app-demo/src/pages/HomePage.tsx.example +1 -1
  37. package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +5 -5
  38. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +3 -3
  39. package/templates/app-next/.env.example +2 -0
  40. package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
  41. package/templates/app-vite/.env.example +2 -0
  42. package/templates/app-vite/src/pages/HomePage.tsx.example +163 -73
  43. package/templates/functions-firebase/build.mjs.example +26 -10
  44. package/templates/functions-firebase/functions-firebase/build.mjs.example +26 -10
  45. package/templates/functions-firebase/functions.config.js.example +11 -15
  46. package/templates/github-consumer/.github/workflows/ci.yml.example +36 -0
  47. package/templates/root-consumer/.claude/agents/architect.md.example +2 -2
  48. package/templates/root-consumer/.claude/agents/builder.md.example +2 -2
  49. package/templates/root-consumer/.claude/agents/coder.md.example +2 -2
  50. package/templates/root-consumer/.claude/agents/extractor.md.example +2 -3
  51. package/templates/root-consumer/.claude/agents/polisher.md.example +67 -291
  52. package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +4 -4
  53. package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
  54. package/templates/root-consumer/.claude/commands/build.md.example +3 -3
  55. package/templates/root-consumer/.claude/commands/design.md.example +1 -1
  56. package/templates/root-consumer/.claude/commands/polish.md.example +66 -82
  57. package/templates/root-consumer/.dndev/args.json.example +6 -0
  58. package/templates/root-consumer/.env.example +13 -13
  59. package/templates/root-consumer/.gemini/settings.json.example +9 -0
  60. package/templates/root-consumer/.gitignore.example +3 -1
  61. package/templates/root-consumer/AI.md.example +150 -0
  62. package/templates/root-consumer/CLAUDE.md.example +19 -104
  63. package/templates/root-consumer/README.md.example +81 -255
  64. package/templates/root-consumer/entities/Contact.ts.example +126 -0
  65. package/templates/root-consumer/entities/index.ts.example +6 -3
  66. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +59 -326
  67. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +2 -1
  68. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +144 -9
  69. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
  70. package/templates/root-consumer/guides/dndev/INDEX.md.example +10 -0
  71. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +13 -16
  72. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +263 -0
  73. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +1 -1
  74. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +168 -0
  75. package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +17 -19
  76. package/templates/root-consumer/guides/dndev/SETUP_TESTING.md.example +184 -0
  77. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +134 -69
  78. package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +66 -44
  79. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +18 -1
  80. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +1 -0
  81. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +2 -1
  82. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +2 -1
  83. package/templates/root-consumer/guides/wai-way/blueprints/4_configure.md.example +180 -108
  84. package/templates/root-consumer/guides/wai-way/context_map.json.example +8 -7
  85. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +4 -4
@@ -47,41 +47,39 @@ export const crud = createCrudFunctions(entities);
47
47
 
48
48
  ## Custom Functions
49
49
 
50
- **When writing custom functions, use `/server` imports:**
50
+ **Use `createFunction` โ€” handles config, validation, auth, rate limiting, metrics automatically:**
51
51
 
52
52
  ```typescript
53
- import { onCall } from 'firebase-functions/v2/https';
54
- import { FUNCTION_CONFIG } from '@donotdev/functions/firebase';
53
+ import * as v from 'valibot';
54
+ import { createFunction } from '@donotdev/functions/firebase';
55
55
  import { getFirebaseAdminFirestore } from '@donotdev/firebase/server';
56
- import { handleError } from '@donotdev/core/server';
57
56
 
58
- export const myFunction = onCall(FUNCTION_CONFIG, async (request) => {
57
+ const schema = v.object({ productId: v.string() });
58
+
59
+ export const getProductDetails = createFunction(schema, 'get_product_details', async (data, { uid }) => {
59
60
  const db = getFirebaseAdminFirestore();
60
- // Your logic here
61
- return { data: 'result' };
61
+ const doc = await db.collection('products').doc(data.productId).get();
62
+ return doc.data();
62
63
  });
63
64
  ```
64
65
 
66
+ **That's it.** Rate limiting, metrics, auth, schema validation โ€” all included by default. No config needed.
67
+
68
+ **Advanced:** Use `createBaseFunction` if you need custom config (memory, timeout, region override).
69
+
65
70
  ---
66
71
 
67
72
  ## Post-Deployment: Cloud Run IAM
68
73
 
69
- **After deploying, you may see `403 Forbidden` on CORS preflight. Fix:**
74
+ **`dndev deploy` handles this automatically.** It runs `gcloud run services update --no-invoker-iam-check` on all deployed functions after each deploy.
70
75
 
71
- ```bash
72
- # PowerShell
73
- gcloud run services update create-products --region=europe-west1 --no-invoker-iam-check --project=myproject
74
- ```
76
+ If you deploy manually with `firebase deploy` (not recommended), you'll see `403 Forbidden` on CORS preflight. Fix by using `dndev deploy` instead, or run manually:
75
77
 
76
- **For all CRUD functions:**
77
- ```powershell
78
- $services = @('create-products', 'get-products', 'list-products', 'update-products', 'delete-products');
79
- foreach ($service in $services) {
80
- gcloud run services update $service --region=europe-west1 --no-invoker-iam-check --project=myproject
81
- }
78
+ ```bash
79
+ gcloud run services update <function-name> --region=<region> --no-invoker-iam-check --project=<project-id>
82
80
  ```
83
81
 
84
- **Why?** Cloud Run blocks unauthenticated OPTIONS (CORS preflight) by default. Your function still validates Firebase Auth - this only allows the preflight to pass.
82
+ **Why?** Cloud Run blocks unauthenticated OPTIONS (CORS preflight) by default. Your function still validates Firebase Auth in code โ€” this only allows the preflight to pass.
85
83
 
86
84
  ---
87
85
 
@@ -0,0 +1,184 @@
1
+ # Testing Guide
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ bun add -D vitest @testing-library/react @testing-library/jest-dom jsdom
7
+ ```
8
+
9
+ ### vitest.config.ts
10
+
11
+ ```ts
12
+ import { defineConfig } from 'vitest/config';
13
+ import react from '@vitejs/plugin-react';
14
+
15
+ export default defineConfig({
16
+ plugins: [react()],
17
+ test: {
18
+ environment: 'jsdom',
19
+ setupFiles: ['./tests/setup.ts'],
20
+ globals: true,
21
+ include: ['tests/**/*.test.ts', 'tests/**/*.test.tsx'],
22
+ },
23
+ });
24
+ ```
25
+
26
+ ### tests/setup.ts
27
+
28
+ ```ts
29
+ import '@testing-library/jest-dom';
30
+ ```
31
+
32
+ ### package.json scripts
33
+
34
+ ```json
35
+ {
36
+ "scripts": {
37
+ "test": "vitest run",
38
+ "test:watch": "vitest"
39
+ }
40
+ }
41
+ ```
42
+
43
+ ---
44
+
45
+ ## What To Test
46
+
47
+ ### 1. Entity Tests
48
+
49
+ For each entity defined in `entities/`, test:
50
+
51
+ **CRUD operations:**
52
+ ```ts
53
+ // tests/entities/Task.test.ts
54
+ import { describe, it, expect } from 'vitest';
55
+ import { TaskEntity } from '../../entities';
56
+
57
+ describe('TaskEntity', () => {
58
+ it('has correct fields', () => {
59
+ const fields = TaskEntity.fields;
60
+ expect(fields).toHaveProperty('title');
61
+ expect(fields).toHaveProperty('status');
62
+ expect(fields.title.required).toBe(true);
63
+ });
64
+
65
+ it('has correct access rules', () => {
66
+ const access = TaskEntity.access;
67
+ expect(access.create).toContain('authenticated');
68
+ expect(access.read).toContain('owner');
69
+ expect(access.delete).toContain('admin');
70
+ });
71
+ });
72
+ ```
73
+
74
+ **What to verify per entity:**
75
+ - All required fields defined
76
+ - Field types match spec
77
+ - Access rules match spec (create/read/update/delete per role)
78
+ - State transitions valid (if entity has states)
79
+ - Default values set correctly
80
+
81
+ ### 2. Page Render Tests
82
+
83
+ For each page in `src/pages/`, test that it mounts:
84
+
85
+ ```tsx
86
+ // tests/pages/DashboardPage.test.tsx
87
+ import { describe, it, expect } from 'vitest';
88
+ import { render, screen } from '@testing-library/react';
89
+ import DashboardPage from '../../src/pages/DashboardPage';
90
+
91
+ describe('DashboardPage', () => {
92
+ it('renders without crashing', () => {
93
+ render(<DashboardPage />);
94
+ expect(document.body).toBeTruthy();
95
+ });
96
+
97
+ it('has correct PageMeta', () => {
98
+ expect(DashboardPage.meta).toBeDefined();
99
+ expect(DashboardPage.meta.title).toBeTruthy();
100
+ expect(DashboardPage.meta.auth).toBe(true);
101
+ });
102
+ });
103
+ ```
104
+
105
+ **What to verify per page:**
106
+ - Page renders without error
107
+ - PageMeta is defined (title, auth requirement, admin flag)
108
+ - Route protection matches spec (public/auth/admin)
109
+
110
+ ### 3. Access Control Tests
111
+
112
+ Derive from entity permissions in the spec:
113
+
114
+ ```ts
115
+ // tests/access/access-rules.test.ts
116
+ import { describe, it, expect } from 'vitest';
117
+ import { entities } from '../../entities';
118
+
119
+ describe('Access Control', () => {
120
+ it('admin entities require admin access', () => {
121
+ // Entities marked admin-only in spec
122
+ const adminEntities = ['AuditLog', 'SystemConfig'];
123
+ for (const name of adminEntities) {
124
+ const entity = entities[name];
125
+ expect(entity.access.create).toContain('admin');
126
+ }
127
+ });
128
+
129
+ it('user-owned entities have owner access', () => {
130
+ // Entities where users own their own data
131
+ const userEntities = ['Task', 'Profile'];
132
+ for (const name of userEntities) {
133
+ const entity = entities[name];
134
+ expect(entity.access.update).toContain('owner');
135
+ }
136
+ });
137
+ });
138
+ ```
139
+
140
+ ### 4. Firestore Rules Tests
141
+
142
+ If using Firebase, generate rules from entity access definitions:
143
+
144
+ ```
145
+ // firestore.rules โ€” generated from entities
146
+ rules_version = '2';
147
+ service cloud.firestore {
148
+ match /databases/{database}/documents {
149
+
150
+ // TaskEntity: create=authenticated, read=owner, update=owner, delete=admin
151
+ match /tasks/{taskId} {
152
+ allow create: if request.auth != null;
153
+ allow read, update: if request.auth != null && resource.data.userId == request.auth.uid;
154
+ allow delete: if request.auth.token.admin == true;
155
+ }
156
+ }
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Test Generation Checklist
163
+
164
+ The Polisher agent should generate tests for everything in the spec:
165
+
166
+ | Source | Test Type | File |
167
+ |--------|-----------|------|
168
+ | Each entity | Field validation + access rules | `tests/entities/[Entity].test.ts` |
169
+ | Each page | Render + PageMeta | `tests/pages/[Page].test.tsx` |
170
+ | Spec permissions | Access control matrix | `tests/access/access-rules.test.ts` |
171
+ | Spec auth | Auth provider config | `tests/auth/auth.test.ts` |
172
+ | Entity access | Firestore rules | `firestore.rules` |
173
+
174
+ ---
175
+
176
+ ## Running Tests
177
+
178
+ ```bash
179
+ bun test # Run all tests once
180
+ bun test:watch # Watch mode
181
+ bunx vitest --ui # Visual UI
182
+ ```
183
+
184
+ Tests should pass before calling `complete_phase({ files: [...test files...] })`.
@@ -15,13 +15,98 @@
15
15
 
16
16
  ---
17
17
 
18
+ ## The Intelligence Engine (MCP Server)
19
+
20
+ Your project is pre-configured with a **Knowledge Engine** (MCP Server) in `.mcp.json`.
21
+
22
+ 1. **Phase Tracking:** `start_phase(N)` returns the blueprint, agent persona, and files to read for each phase.
23
+ 2. **Type Intelligence:** `lookup_symbol("ComponentName")` returns actual TypeScript types โ€” never guess props.
24
+ 3. **Knowledge Retrieval:** `get_guide("CRUD")`, `get_guideline("styling")`, `search_framework("keyword")`.
25
+ 4. **Implementation Tracking:** `init_implementation()` creates a persistent checklist. `update_progress()` ticks items. `get_progress()` reads status. Survives across sessions.
26
+ 5. **Captain's Log:** Session history auto-recorded on `approve_phase()`. `get_project_history()` for metrics and post-mortem.
27
+ 6. **Lessons:** `record_lesson("gotcha", { tags: ["stripe", "billing"] })` saves tagged gotchas to `.dndev/LESSONS.md`. Filtered by phase + module on next `start_phase`.
28
+
29
+ The IDE (Cursor, Claude Code, etc.) handles file write approval natively. No MCP-level gating.
30
+
31
+ ---
32
+
33
+ ## Implementation Tracking (Multi-Session Progress)
34
+
35
+ For projects that span multiple AI sessions, `.dndev/implementation.md` tracks what's done and what's pending.
36
+
37
+ ### Setup (after Phase 0)
38
+
39
+ ```
40
+ # Auto-generate from spec
41
+ init_implementation({ from_spec: true })
42
+
43
+ # Or manual sections
44
+ init_implementation({ sections: [
45
+ { title: "Auth Module", items: ["Login page", "Registration", "Password reset"] },
46
+ { title: "Dashboard", items: ["Stats cards", "Activity feed", "Charts"] }
47
+ ] })
48
+ ```
49
+
50
+ ### During Work
51
+
52
+ ```
53
+ # Tick items as you complete them
54
+ update_progress({ item: "Login page", done: true })
55
+ update_progress({ item: "Stats cards", done: true, note: "Used Card component with level h3" })
56
+
57
+ # Check progress
58
+ get_progress() # full overview
59
+ get_progress({ section: "Auth Module" }) # filtered to section
60
+ ```
61
+
62
+ ### Cross-Session Continuity
63
+
64
+ When you start a new session:
65
+ 1. `start_phase(N)` automatically includes implementation progress
66
+ 2. The agent sees what's done and picks up where it left off
67
+ 3. No repeated work, no drift
68
+
69
+ ---
70
+
71
+ ## Captain's Log (Project History)
72
+
73
+ Every `approve_phase()` auto-records a session entry to `.dndev/captain-log.json`. No manual action needed.
74
+
75
+ ### What's Recorded Automatically
76
+
77
+ - Date + timestamps (started/completed)
78
+ - Phase number and name
79
+ - Module (if scoped)
80
+ - Files touched + symbols used
81
+ - Outcome summary (from `complete_phase({ summary: "..." })`)
82
+
83
+ ### Viewing History
84
+
85
+ ```
86
+ get_project_history()
87
+ ```
88
+
89
+ Returns computed metrics + timeline:
90
+ - Total sessions, phases completed
91
+ - Files and symbols totals
92
+ - Per-session timeline with outcomes
93
+
94
+ ### Post-Mortem
95
+
96
+ The raw JSON at `.dndev/captain-log.json` enables:
97
+ - Phase velocity analysis (how many sessions per phase)
98
+ - Issue tracking across the project lifecycle
99
+ - Team-level comparison across projects
100
+
101
+ ---
102
+
18
103
  ## The Flow
19
104
 
20
105
  ```
21
- BRAINSTORM โ†’ SPEC โ†’ SCAFFOLD โ†’ ENTITIES โ†’ COMPOSE โ†’ CONFIGURE
106
+ BRAINSTORM (โ†’ spec) โ†’ SCAFFOLD โ†’ ENTITIES โ†’ COMPOSE โ†’ CONFIGURE
22
107
  ```
23
108
 
24
- **Critical:** The spec is the OUTPUT of brainstorming, not the input. No code until spec is validated.
109
+ **Critical:** The spec is the OUTPUT of Phase 0 (BRAINSTORM), not a separate phase. No code until spec is validated.
25
110
 
26
111
  ---
27
112
 
@@ -267,94 +352,75 @@ Copy from `page_patterns.md`:
267
352
 
268
353
  ---
269
354
 
270
- ## Phase 4: CONFIGURE
355
+ ## Phase 4: CONFIGURE + TEST
271
356
 
272
- **Goal:** Finalize configuration and test.
357
+ **Goal:** Generate tests, firestore rules, CI/CD, and finalize config.
273
358
 
274
359
  **READ:**
360
+ - `guides/wai-way/spec_template.md` - The validated spec (your test plan)
361
+ - `entities/index.ts` - All entity definitions
275
362
  - `src/config/app.ts` - App configuration
276
- - `src/config/legal.ts` - Legal info
277
- - `.env` - Environment variables
363
+ - `guides/dndev/SETUP_TESTING.md` - Testing patterns
278
364
 
279
- ### Step 4.1: Update Configuration
365
+ ### Step 4.1: Generate Tests
280
366
 
281
- **app.ts:**
282
- - [ ] `APP_NAME` and `APP_SHORT_NAME`
283
- - [ ] Correct `preset`
284
- - [ ] Footer legal links
367
+ Call `get_guide("TESTING")` for patterns.
285
368
 
286
- **legal.ts:**
287
- - [ ] Company name and registration
288
- - [ ] Contact emails
289
- - [ ] Hosting provider
290
- - [ ] Jurisdiction
369
+ **Entity tests** โ€” one per entity in `tests/entities/[Entity].test.ts`:
370
+ - [ ] Required fields defined
371
+ - [ ] Field types match spec
372
+ - [ ] Access rules match spec (create/read/update/delete per role)
291
373
 
292
- **.env:**
293
- - [ ] `VITE_FIREBASE_*` values
294
- - [ ] `VITE_DONOTDEV_LICENSE_KEY`
295
- - [ ] Optional: `VITE_STRIPE_*`, `VITE_SENTRY_DSN`
374
+ **Page tests** โ€” one per page in `tests/pages/[Page].test.tsx`:
375
+ - [ ] Renders without error
376
+ - [ ] PageMeta defined (title, auth, admin)
377
+ - [ ] Route protection matches spec
296
378
 
297
- ### Step 4.2: Firebase Setup
379
+ **Access control tests** in `tests/access/access-rules.test.ts`:
380
+ - [ ] Admin entities require admin access
381
+ - [ ] User-owned entities have owner access
382
+ - [ ] No unauthenticated writes
298
383
 
299
- 1. Enable auth providers in Firebase Console
300
- 2. Create Firestore database
301
- 3. Deploy rules: `firebase deploy --only firestore:rules`
384
+ ### Step 4.2: Generate Firestore Rules
302
385
 
303
- ### Step 4.3: Test
386
+ Create `firestore.rules` from entity access definitions:
387
+ - `owner` โ†’ `resource.data.userId == request.auth.uid`
388
+ - `admin` โ†’ `request.auth.token.admin == true`
389
+ - `authenticated` โ†’ `request.auth != null`
304
390
 
305
- ```bash
306
- dndev emu start
307
- bun dev
308
- ```
391
+ ### Step 4.3: Generate CI/CD
309
392
 
310
- **Test checklist:**
311
- - [ ] Can create/login user
312
- - [ ] Public pages work without auth
313
- - [ ] Protected pages redirect to login
314
- - [ ] Admin pages require admin role
315
- - [ ] CRUD operations work
316
- - [ ] Data persists
393
+ Create `.github/workflows/ci.yml`:
394
+ - Quality job: `bun install` โ†’ `bun run type-check` โ†’ `bun test`
395
+ - Deploy job: `bun run build` โ†’ Firebase deploy (on main push)
317
396
 
318
- ### Step 4.4: Mobile Check
397
+ ### Step 4.4: Update Configuration
319
398
 
320
- 1. Open DevTools (F12)
321
- 2. Toggle device toolbar (Ctrl+Shift+M)
322
- 3. Test at 375px width
399
+ **app.ts:** APP_NAME, APP_SHORT_NAME, preset, footer links
400
+ **legal.ts:** Company, contacts, hosting, jurisdiction
401
+ **.env:** VITE_FIREBASE_*, VITE_DONOTDEV_LICENSE_KEY, optional Stripe/Sentry
323
402
 
324
- **Output:** Working app with auth, CRUD, config complete.
403
+ ### Step 4.5: Run Tests
325
404
 
326
- ---
327
-
328
- ## Phase 5: i18n (Optional, After Validation)
405
+ ```bash
406
+ bun test
407
+ ```
329
408
 
330
- **Only after Phase 4 is validated.**
409
+ All tests must pass before completing.
331
410
 
332
- ### Step 5.1: Extract Strings
411
+ ### Step 4.6: Mobile Check
333
412
 
334
- Create `src/locales/[namespace]_en.json`:
335
- ```json
336
- {
337
- "hero": {
338
- "title": "Welcome to My App",
339
- "subtitle": "The best app ever built"
340
- }
341
- }
342
- ```
413
+ DevTools โ†’ 375px width โ†’ navigation, forms, text, buttons (44px), no horizontal scroll.
343
414
 
344
- ### Step 5.2: Replace Hardcoded Strings
415
+ **Output:** Test files, firestore.rules, CI/CD pipeline, configured app.
345
416
 
346
- ```tsx
347
- const { t } = useTranslation('home');
417
+ ---
348
418
 
349
- <HeroSection
350
- title={t('hero.title')}
351
- subtitle={t('hero.subtitle')}
352
- />
353
- ```
419
+ ### Step 4.7: i18n (Optional)
354
420
 
355
- ### Step 5.3: Add Translations
421
+ **Only after Steps 4.1-4.6 pass.**
356
422
 
357
- Copy `home_en.json` โ†’ `home_fr.json`, translate values.
423
+ Extract hardcoded strings to `src/locales/[namespace]_en.json`, replace with `useTranslation()`.
358
424
 
359
425
  ---
360
426
 
@@ -381,10 +447,10 @@ Activate agent personas from `guides/wai-way/agents/`:
381
447
 
382
448
  | Agent | Phase | Focus |
383
449
  |-------|-------|-------|
384
- | **Extractor** | 1 | Routes, sitemap, PageMeta |
450
+ | **Extractor** | 0-1 | Requirements gathering, routes, sitemap, PageMeta |
385
451
  | **Architect** | 2 | Entities, data models |
386
452
  | **Builder** | 3 | Page composition, components |
387
- | **Polisher** | 4 | Config, testing, polish |
453
+ | **Polisher** | 4 | Config, testing, polish, i18n |
388
454
 
389
455
  See individual agent files for activation prompts.
390
456
 
@@ -397,8 +463,7 @@ Phase 0: BRAINSTORM โ†’ User idea โ†’ Agent questions โ†’ Agent fills spec โ†’ U
397
463
  Phase 1: SCAFFOLD โ†’ Create all *Page.tsx with PageMeta (from spec)
398
464
  Phase 2: ENTITIES โ†’ Define all entities with fields/access (from spec)
399
465
  Phase 3: COMPOSE โ†’ Build pages with components (HARDCODE strings)
400
- Phase 4: CONFIGURE โ†’ Config, Firebase, test, mobile
401
- Phase 5: i18n โ†’ (Optional) Extract strings, translate
466
+ Phase 4: CONFIGURE โ†’ Config, Firebase, test, mobile, optional i18n
402
467
  ```
403
468
 
404
469
  **Remember:** Spec is the OUTPUT of brainstorming. Validated spec = mechanical build.
@@ -10,27 +10,58 @@ agent:
10
10
  id: polisher
11
11
  title: QA & Config Specialist
12
12
  icon: ๐Ÿงช
13
- phase: "4_configure_polish"
14
- done_when: "Config complete, tests pass, mobile responsive"
13
+ phase: "4_configure_test"
14
+ done_when: "Tests pass, config complete, firestore rules generated"
15
15
 
16
16
  persona:
17
- role: Quality Gatekeeper & Configuration Expert
18
- style: Detail-oriented, systematic, thorough
19
- identity: You ensure the app is configured correctly and production-ready.
20
- focus: Configuration, testing, mobile check, optional i18n.
17
+ role: Quality Gatekeeper & Test Generator
18
+ style: Systematic, thorough, test-driven
19
+ identity: You generate tests from the spec, configure the app, and verify everything works.
20
+ focus: Test generation, configuration, firestore rules, mobile check.
21
21
 
22
22
  golden_rule: |
23
- THE SCAFFOLDED FILES ARE YOUR DOCUMENTATION.
24
- READ src/config/app.ts for config options.
25
- READ src/config/legal.ts for legal checklist.
26
- READ src/themes.css for theme variables.
23
+ THE SPEC IS YOUR TEST PLAN.
24
+ READ the spec (Phase 0 output) for entities, permissions, journeys.
25
+ READ each entity file for access rules and fields.
26
+ GENERATE tests that verify the spec is implemented correctly.
27
27
 
28
28
  core_principles:
29
- - Configuration first: app.ts, legal.ts, .env
30
- - Test with emulators: dndev emu start
29
+ - Tests first: generate entity tests, page tests, access tests
30
+ - Firestore rules from entities: access definitions โ†’ security rules
31
+ - Configuration: app.ts, legal.ts, .env
31
32
  - Mobile check: 375px width
32
33
  - i18n is OPTIONAL and comes LAST
33
34
 
35
+ test_generation:
36
+ entity_tests:
37
+ per_entity:
38
+ - Required fields are defined
39
+ - Field types match spec
40
+ - Access rules match spec (create/read/update/delete per role)
41
+ - State transitions valid (if applicable)
42
+ output: "tests/entities/[EntityName].test.ts"
43
+ page_tests:
44
+ per_page:
45
+ - Renders without error
46
+ - PageMeta defined (title, auth, admin)
47
+ - Route protection matches spec
48
+ output: "tests/pages/[PageName].test.tsx"
49
+ access_tests:
50
+ - Admin entities require admin access
51
+ - User-owned entities have owner access
52
+ - Public entities allow guest read
53
+ - No unauthenticated writes
54
+ output: "tests/access/access-rules.test.ts"
55
+
56
+ firestore_rules:
57
+ source: "Entity access definitions"
58
+ mapping:
59
+ owner: "resource.data.userId == request.auth.uid"
60
+ admin: "request.auth.token.admin == true"
61
+ authenticated: "request.auth != null"
62
+ guest: "true"
63
+ output: "firestore.rules"
64
+
34
65
  config_checklist:
35
66
  app_ts:
36
67
  - APP_NAME and APP_SHORT_NAME set
@@ -45,32 +76,19 @@ config_checklist:
45
76
  - VITE_FIREBASE_* values set
46
77
  - VITE_DONOTDEV_LICENSE_KEY set
47
78
 
48
- test_checklist:
49
- - Can create/login user
50
- - Public pages work without auth
51
- - Protected pages redirect to login
52
- - Admin pages require admin role
53
- - CRUD operations work
54
- - Data persists
55
-
56
- mobile_check:
57
- - Open DevTools (F12)
58
- - Toggle device toolbar (Ctrl+Shift+M)
59
- - Test at 375px width
60
- - Navigation works
61
- - Forms are usable
62
- - Text is readable
63
-
64
79
  commands:
65
80
  - help: Show available commands
81
+ - generate-tests: Generate all test files from spec + entities
82
+ - generate-rules: Generate firestore.rules from entities
66
83
  - audit-config: Check configuration files
67
84
  - audit-mobile: Check mobile responsiveness
68
85
  - add-i18n: Extract strings to locales (optional)
69
86
  - exit: Exit persona
70
87
 
71
88
  output:
89
+ - Test files generated and passing
90
+ - Firestore rules generated
72
91
  - Configuration complete
73
- - All tests pass
74
92
  - Mobile responsive
75
93
  - (Optional) i18n added
76
94
  ```
@@ -81,20 +99,24 @@ output:
81
99
  Activate AGENT Polisher.
82
100
 
83
101
  READ these files first:
102
+ - guides/wai-way/spec_template.md (the validated spec โ€” your test plan)
103
+ - entities/index.ts (all entity definitions)
104
+ - src/pages/ (all page files)
84
105
  - src/config/app.ts (app configuration)
85
- - src/config/legal.ts (legal info checklist)
86
- - src/themes.css (theme customization)
87
- - .env (environment variables)
88
-
89
- Your goal: Finalize configuration and test the app.
90
-
91
- Checklist:
92
- 1. Update app.ts (name, preset, footer)
93
- 2. Update legal.ts (company, contacts)
94
- 3. Fill .env (Firebase config)
95
- 4. Test with emulators
96
- 5. Mobile check at 375px
97
- 6. (Optional) Add i18n
98
-
99
- Verify each item before marking complete.
106
+ - guides/dndev/SETUP_TESTING.md (testing patterns)
107
+
108
+ Your goal: Generate tests, firestore rules, and finalize config.
109
+
110
+ Steps:
111
+ 1. Create vitest.config.ts + tests/setup.ts
112
+ 2. Generate entity tests (one per entity from entities/)
113
+ 3. Generate page tests (one per page from src/pages/)
114
+ 4. Generate access control tests (from spec permissions)
115
+ 5. Generate firestore.rules (from entity access definitions)
116
+ 6. Update app.ts, legal.ts, .env
117
+ 7. Run bun test โ€” all must pass
118
+ 8. Mobile check at 375px
119
+ 9. (Optional) Add i18n
120
+
121
+ Call get_guide("TESTING") for testing patterns.
100
122
  ```