@prmichaelsen/acp-visualizer 0.1.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.
- package/README.md +68 -0
- package/agent/commands/acp.clarification-address.md +417 -0
- package/agent/commands/acp.clarification-capture.md +386 -0
- package/agent/commands/acp.clarification-create.md +437 -0
- package/agent/commands/acp.clarifications-research.md +326 -0
- package/agent/commands/acp.command-create.md +432 -0
- package/agent/commands/acp.design-create.md +286 -0
- package/agent/commands/acp.design-reference.md +355 -0
- package/agent/commands/acp.handoff.md +270 -0
- package/agent/commands/acp.index.md +423 -0
- package/agent/commands/acp.init.md +546 -0
- package/agent/commands/acp.package-create.md +895 -0
- package/agent/commands/acp.package-info.md +212 -0
- package/agent/commands/acp.package-install.md +539 -0
- package/agent/commands/acp.package-list.md +280 -0
- package/agent/commands/acp.package-publish.md +541 -0
- package/agent/commands/acp.package-remove.md +293 -0
- package/agent/commands/acp.package-search.md +307 -0
- package/agent/commands/acp.package-update.md +361 -0
- package/agent/commands/acp.package-validate.md +540 -0
- package/agent/commands/acp.pattern-create.md +386 -0
- package/agent/commands/acp.plan.md +587 -0
- package/agent/commands/acp.proceed.md +882 -0
- package/agent/commands/acp.project-create.md +675 -0
- package/agent/commands/acp.project-info.md +312 -0
- package/agent/commands/acp.project-list.md +226 -0
- package/agent/commands/acp.project-remove.md +379 -0
- package/agent/commands/acp.project-set.md +227 -0
- package/agent/commands/acp.project-update.md +307 -0
- package/agent/commands/acp.projects-restore.md +228 -0
- package/agent/commands/acp.projects-sync.md +347 -0
- package/agent/commands/acp.report.md +407 -0
- package/agent/commands/acp.resume.md +239 -0
- package/agent/commands/acp.sessions.md +301 -0
- package/agent/commands/acp.status.md +293 -0
- package/agent/commands/acp.sync.md +364 -0
- package/agent/commands/acp.task-create.md +500 -0
- package/agent/commands/acp.update.md +302 -0
- package/agent/commands/acp.validate.md +466 -0
- package/agent/commands/acp.version-check-for-updates.md +276 -0
- package/agent/commands/acp.version-check.md +191 -0
- package/agent/commands/acp.version-update.md +289 -0
- package/agent/commands/command.template.md +339 -0
- package/agent/commands/git.commit.md +526 -0
- package/agent/commands/git.init.md +514 -0
- package/agent/commands/tanstack-cloudflare.deploy.md +272 -0
- package/agent/commands/tanstack-cloudflare.tail.md +275 -0
- package/agent/design/.gitkeep +0 -0
- package/agent/design/design.template.md +154 -0
- package/agent/design/local.dashboard-layout-routing.md +288 -0
- package/agent/design/local.data-model-yaml-parsing.md +310 -0
- package/agent/design/local.search-filtering.md +331 -0
- package/agent/design/local.server-api-auto-refresh.md +235 -0
- package/agent/design/local.table-tree-views.md +299 -0
- package/agent/design/local.visualizer-requirements.md +349 -0
- package/agent/design/requirements.template.md +387 -0
- package/agent/index/.gitkeep +0 -0
- package/agent/index/acp.core.yaml +137 -0
- package/agent/index/local.main.template.yaml +37 -0
- package/agent/manifest.template.yaml +13 -0
- package/agent/manifest.yaml +302 -0
- package/agent/milestones/.gitkeep +0 -0
- package/agent/milestones/milestone-1-project-scaffold-data-pipeline.md +67 -0
- package/agent/milestones/milestone-1-{title}.template.md +206 -0
- package/agent/milestones/milestone-2-dashboard-views-interaction.md +79 -0
- package/agent/package.template.yaml +86 -0
- package/agent/patterns/.gitkeep +0 -0
- package/agent/patterns/bootstrap.template.md +1237 -0
- package/agent/patterns/pattern.template.md +382 -0
- package/agent/patterns/tanstack-cloudflare.acl-permissions.md +332 -0
- package/agent/patterns/tanstack-cloudflare.action-bar-item.md +416 -0
- package/agent/patterns/tanstack-cloudflare.api-route-handlers.md +401 -0
- package/agent/patterns/tanstack-cloudflare.auth-session-management.md +387 -0
- package/agent/patterns/tanstack-cloudflare.card-and-list.md +271 -0
- package/agent/patterns/tanstack-cloudflare.chat-engine.md +353 -0
- package/agent/patterns/tanstack-cloudflare.confirmation-tokens.md +346 -0
- package/agent/patterns/tanstack-cloudflare.durable-objects-websocket.md +516 -0
- package/agent/patterns/tanstack-cloudflare.email-service.md +431 -0
- package/agent/patterns/tanstack-cloudflare.expander.md +98 -0
- package/agent/patterns/tanstack-cloudflare.fcm-push.md +115 -0
- package/agent/patterns/tanstack-cloudflare.firebase-anonymous-sessions.md +441 -0
- package/agent/patterns/tanstack-cloudflare.firebase-auth.md +348 -0
- package/agent/patterns/tanstack-cloudflare.firebase-firestore.md +550 -0
- package/agent/patterns/tanstack-cloudflare.firebase-storage.md +369 -0
- package/agent/patterns/tanstack-cloudflare.form-controls.md +145 -0
- package/agent/patterns/tanstack-cloudflare.global-search-context.md +93 -0
- package/agent/patterns/tanstack-cloudflare.image-carousel.md +126 -0
- package/agent/patterns/tanstack-cloudflare.library-services.md +553 -0
- package/agent/patterns/tanstack-cloudflare.lightbox.md +169 -0
- package/agent/patterns/tanstack-cloudflare.markdown-content.md +115 -0
- package/agent/patterns/tanstack-cloudflare.mention-suggestions.md +98 -0
- package/agent/patterns/tanstack-cloudflare.modal.md +156 -0
- package/agent/patterns/tanstack-cloudflare.nextjs-to-tanstack-routing.md +461 -0
- package/agent/patterns/tanstack-cloudflare.notifications-engine.md +151 -0
- package/agent/patterns/tanstack-cloudflare.oauth-token-refresh.md +90 -0
- package/agent/patterns/tanstack-cloudflare.og-metadata.md +296 -0
- package/agent/patterns/tanstack-cloudflare.pagination.md +442 -0
- package/agent/patterns/tanstack-cloudflare.pill-input.md +220 -0
- package/agent/patterns/tanstack-cloudflare.provider-adapter.md +401 -0
- package/agent/patterns/tanstack-cloudflare.rate-limiting.md +323 -0
- package/agent/patterns/tanstack-cloudflare.scheduled-tasks.md +338 -0
- package/agent/patterns/tanstack-cloudflare.searchable-settings.md +375 -0
- package/agent/patterns/tanstack-cloudflare.slide-over.md +129 -0
- package/agent/patterns/tanstack-cloudflare.ssr-preload.md +571 -0
- package/agent/patterns/tanstack-cloudflare.third-party-api-integration.md +508 -0
- package/agent/patterns/tanstack-cloudflare.toast-system.md +142 -0
- package/agent/patterns/tanstack-cloudflare.unified-header.md +280 -0
- package/agent/patterns/tanstack-cloudflare.user-scoped-collections.md +628 -0
- package/agent/patterns/tanstack-cloudflare.websocket-manager.md +237 -0
- package/agent/patterns/tanstack-cloudflare.wrangler-configuration.md +358 -0
- package/agent/patterns/tanstack-cloudflare.zod-schema-validation.md +336 -0
- package/agent/progress.template.yaml +161 -0
- package/agent/progress.yaml +145 -0
- package/agent/schemas/package.schema.yaml +276 -0
- package/agent/scripts/acp.common.sh +1781 -0
- package/agent/scripts/acp.install.sh +333 -0
- package/agent/scripts/acp.package-create.sh +924 -0
- package/agent/scripts/acp.package-info.sh +288 -0
- package/agent/scripts/acp.package-install.sh +893 -0
- package/agent/scripts/acp.package-list.sh +311 -0
- package/agent/scripts/acp.package-publish.sh +420 -0
- package/agent/scripts/acp.package-remove.sh +348 -0
- package/agent/scripts/acp.package-search.sh +156 -0
- package/agent/scripts/acp.package-update.sh +517 -0
- package/agent/scripts/acp.package-validate.sh +1018 -0
- package/agent/scripts/acp.uninstall.sh +85 -0
- package/agent/scripts/acp.version-check-for-updates.sh +98 -0
- package/agent/scripts/acp.version-check.sh +47 -0
- package/agent/scripts/acp.version-update.sh +176 -0
- package/agent/scripts/acp.yaml-parser.sh +985 -0
- package/agent/scripts/acp.yaml-validate.sh +205 -0
- package/agent/tasks/.gitkeep +0 -0
- package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-1-initialize-tanstack-start-project.md +210 -0
- package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-2-implement-data-model-yaml-parser.md +294 -0
- package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-3-build-server-api-data-loading.md +193 -0
- package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-4-add-auto-refresh-sse.md +262 -0
- package/agent/tasks/milestone-2-dashboard-views-interaction/task-10-polish-integration-testing.md +156 -0
- package/agent/tasks/milestone-2-dashboard-views-interaction/task-5-build-dashboard-layout-routing.md +178 -0
- package/agent/tasks/milestone-2-dashboard-views-interaction/task-6-build-overview-page.md +141 -0
- package/agent/tasks/milestone-2-dashboard-views-interaction/task-7-implement-milestone-table-view.md +153 -0
- package/agent/tasks/milestone-2-dashboard-views-interaction/task-8-implement-milestone-tree-view.md +174 -0
- package/agent/tasks/milestone-2-dashboard-views-interaction/task-9-implement-search-filtering.md +233 -0
- package/agent/tasks/task-1-{title}.template.md +244 -0
- package/bin/visualize.mjs +84 -0
- package/package.json +48 -0
- package/src/components/ExtraFieldsBadge.tsx +15 -0
- package/src/components/FilterBar.tsx +33 -0
- package/src/components/Header.tsx +23 -0
- package/src/components/MilestoneTable.tsx +167 -0
- package/src/components/MilestoneTree.tsx +84 -0
- package/src/components/ProgressBar.tsx +20 -0
- package/src/components/SearchInput.tsx +22 -0
- package/src/components/Sidebar.tsx +54 -0
- package/src/components/StatusBadge.tsx +23 -0
- package/src/components/StatusDot.tsx +12 -0
- package/src/components/TaskList.tsx +36 -0
- package/src/components/ViewToggle.tsx +31 -0
- package/src/lib/config.ts +8 -0
- package/src/lib/file-watcher.ts +43 -0
- package/src/lib/search.ts +48 -0
- package/src/lib/types.ts +73 -0
- package/src/lib/useAutoRefresh.ts +31 -0
- package/src/lib/useCollapse.ts +31 -0
- package/src/lib/useFilteredData.ts +55 -0
- package/src/lib/yaml-loader-real.spec.ts +47 -0
- package/src/lib/yaml-loader.spec.ts +201 -0
- package/src/lib/yaml-loader.ts +265 -0
- package/src/routeTree.gen.ts +140 -0
- package/src/router.tsx +10 -0
- package/src/routes/__root.tsx +75 -0
- package/src/routes/api/watch.ts +29 -0
- package/src/routes/index.tsx +115 -0
- package/src/routes/milestones.tsx +50 -0
- package/src/routes/search.tsx +84 -0
- package/src/routes/tasks.tsx +63 -0
- package/src/services/progress-database.service.ts +46 -0
- package/src/styles.css +25 -0
- package/tsconfig.json +24 -0
- package/vite.config.ts +16 -0
- package/vitest.config.ts +27 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Zod Schema Validation Pattern
|
|
2
|
+
|
|
3
|
+
**Category**: Architecture
|
|
4
|
+
**Applicable To**: TanStack Start + Cloudflare Workers applications with typed data models
|
|
5
|
+
**Status**: Stable
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
All data models are defined as Zod schemas in a centralized `src/schemas/` directory. Schemas serve as the single source of truth for data shape, validation, and TypeScript types. Types are derived from schemas using `z.infer<>`, ensuring runtime validation and compile-time types are always in sync.
|
|
12
|
+
|
|
13
|
+
This pattern ensures data integrity at every boundary: API request bodies are validated on entry, database documents are validated on read, and all types flow from the schema definitions.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## When to Use This Pattern
|
|
18
|
+
|
|
19
|
+
✅ **Use this pattern when:**
|
|
20
|
+
- Building applications with structured data models
|
|
21
|
+
- Need runtime validation at system boundaries (API inputs, database reads)
|
|
22
|
+
- Want TypeScript types derived from a single source of truth
|
|
23
|
+
- Working with Firestore or other schemaless databases
|
|
24
|
+
- Need separate schemas for create, update, and read operations
|
|
25
|
+
|
|
26
|
+
❌ **Don't use this pattern when:**
|
|
27
|
+
- Working with trivial data (single primitive values)
|
|
28
|
+
- Using an ORM that handles validation (Prisma, Drizzle)
|
|
29
|
+
- Performance-critical hot paths where validation overhead matters
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Core Principles
|
|
34
|
+
|
|
35
|
+
1. **Single Source of Truth**: Zod schemas define data shape; TypeScript types are derived, not hand-written
|
|
36
|
+
2. **Centralized Schemas Directory**: All schemas live in `src/schemas/`, organized by domain
|
|
37
|
+
3. **Separate CRUD Schemas**: Separate schemas for create input, update input, and full entity
|
|
38
|
+
4. **Path-Based Documentation**: Schema files document where data is stored (Firestore path in JSDoc)
|
|
39
|
+
5. **Safe Parse in Services**: Use `safeParse` (not `parse`) in services to handle invalid data gracefully
|
|
40
|
+
6. **No Redundant Fields**: Schemas for user-scoped data don't include `user_id` (it's in the path)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Implementation
|
|
45
|
+
|
|
46
|
+
### Structure
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
src/schemas/
|
|
50
|
+
├── profile.ts # UserProfile, UpdateProfileInput
|
|
51
|
+
├── relationship.ts # Relationship, RelationshipFlags
|
|
52
|
+
├── group-conversation.ts # GroupConversation, MemberPermissions
|
|
53
|
+
├── dm-conversation.ts # DMConversation
|
|
54
|
+
├── credentials.ts # InstagramCredentials, etc.
|
|
55
|
+
├── oauth-integration.ts # OAuthIntegration
|
|
56
|
+
└── mcp-integration.ts # MCPIntegration
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Code Example
|
|
60
|
+
|
|
61
|
+
#### Step 1: Define Entity Schema
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// src/schemas/profile.ts
|
|
65
|
+
import { z } from 'zod'
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* User Profile Schema
|
|
69
|
+
*
|
|
70
|
+
* Stored at: {BASE}.users/{userId}/profile/default
|
|
71
|
+
* Each user has exactly one profile document.
|
|
72
|
+
*/
|
|
73
|
+
export const UserProfileSchema = z.object({
|
|
74
|
+
user_id: z.string(),
|
|
75
|
+
display_name: z.string(),
|
|
76
|
+
short_bio: z.string().optional(),
|
|
77
|
+
profile_picture_path: z.string().optional(),
|
|
78
|
+
banner_path: z.string().optional(),
|
|
79
|
+
friend_count: z.number().int().min(0),
|
|
80
|
+
created_at: z.number(),
|
|
81
|
+
updated_at: z.number(),
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Derive TypeScript type from schema
|
|
85
|
+
export type UserProfile = z.infer<typeof UserProfileSchema>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### Step 2: Define Separate Update Schema
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// src/schemas/profile.ts (continued)
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Update Profile Schema — only mutable fields
|
|
95
|
+
*/
|
|
96
|
+
export const UpdateProfileSchema = z.object({
|
|
97
|
+
display_name: z.string().optional(),
|
|
98
|
+
short_bio: z.string().optional(),
|
|
99
|
+
profile_picture_path: z.string().optional(),
|
|
100
|
+
banner_path: z.string().optional(),
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
export type UpdateProfileInput = z.infer<typeof UpdateProfileSchema>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Step 3: Complex Schema with Nested Types
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// src/schemas/group-conversation.ts
|
|
110
|
+
import { z } from 'zod'
|
|
111
|
+
|
|
112
|
+
// Nested permission schema
|
|
113
|
+
export const MemberPermissionsSchema = z.object({
|
|
114
|
+
auth_level: z.number().int().min(0),
|
|
115
|
+
can_read: z.boolean(),
|
|
116
|
+
can_publish: z.boolean(),
|
|
117
|
+
can_revise: z.boolean(),
|
|
118
|
+
can_propose: z.boolean(),
|
|
119
|
+
can_overwrite: z.boolean(),
|
|
120
|
+
can_comment: z.boolean(),
|
|
121
|
+
can_retract_own: z.boolean(),
|
|
122
|
+
can_retract_any: z.boolean(),
|
|
123
|
+
can_manage_members: z.boolean(),
|
|
124
|
+
can_update_properties: z.boolean(),
|
|
125
|
+
can_moderate: z.boolean(),
|
|
126
|
+
can_kick: z.boolean(),
|
|
127
|
+
can_mute: z.boolean(),
|
|
128
|
+
can_ban: z.boolean(),
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
export type MemberPermissions = z.infer<typeof MemberPermissionsSchema>
|
|
132
|
+
|
|
133
|
+
// Permission presets
|
|
134
|
+
export const OWNER_PRESET: MemberPermissions = {
|
|
135
|
+
auth_level: 0,
|
|
136
|
+
can_read: true, can_publish: true, can_revise: true,
|
|
137
|
+
can_propose: true, can_overwrite: true, can_comment: true,
|
|
138
|
+
can_retract_own: true, can_retract_any: true, can_manage_members: true,
|
|
139
|
+
can_update_properties: true, can_moderate: true,
|
|
140
|
+
can_kick: true, can_mute: true, can_ban: true,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const MEMBER_PRESET: MemberPermissions = {
|
|
144
|
+
auth_level: 5,
|
|
145
|
+
can_read: true, can_publish: true, can_revise: false,
|
|
146
|
+
can_propose: true, can_overwrite: false, can_comment: true,
|
|
147
|
+
can_retract_own: true, can_retract_any: false, can_manage_members: false,
|
|
148
|
+
can_update_properties: false, can_moderate: false,
|
|
149
|
+
can_kick: false, can_mute: false, can_ban: false,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Full entity schema
|
|
153
|
+
export const GroupConversationSchema = z.object({
|
|
154
|
+
id: z.string(),
|
|
155
|
+
type: z.literal('group'),
|
|
156
|
+
name: z.string(),
|
|
157
|
+
description: z.string().nullable().optional(),
|
|
158
|
+
owner_user_id: z.string(),
|
|
159
|
+
participant_user_ids: z.array(z.string()),
|
|
160
|
+
member_permissions: z.record(z.string(), MemberPermissionsSchema),
|
|
161
|
+
last_message_at: z.string().datetime().nullable().optional(),
|
|
162
|
+
created_at: z.string().datetime(),
|
|
163
|
+
updated_at: z.string().datetime(),
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
export type GroupConversation = z.infer<typeof GroupConversationSchema>
|
|
167
|
+
|
|
168
|
+
// Update schema (only mutable fields)
|
|
169
|
+
export const UpdateGroupConversationSchema = z.object({
|
|
170
|
+
name: z.string().optional(),
|
|
171
|
+
description: z.string().optional(),
|
|
172
|
+
last_message_at: z.string().datetime().optional(),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
export type UpdateGroupConversationInput = z.infer<typeof UpdateGroupConversationSchema>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### Step 4: Use safeParse in Services
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// src/services/profile-database.service.ts
|
|
182
|
+
import { UserProfileSchema, type UserProfile } from '@/schemas/profile'
|
|
183
|
+
|
|
184
|
+
export class ProfileDatabaseService {
|
|
185
|
+
static async getProfile(userId: string): Promise<UserProfile | null> {
|
|
186
|
+
const doc = await getDocument(getUserProfile(userId), 'default')
|
|
187
|
+
if (!doc) return null
|
|
188
|
+
|
|
189
|
+
// Validate data from schemaless database
|
|
190
|
+
const result = UserProfileSchema.safeParse(doc)
|
|
191
|
+
if (!result.success) {
|
|
192
|
+
console.error('Invalid profile data:', result.error)
|
|
193
|
+
return null // Don't crash on invalid data
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return result.data
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Step 5: Validate API Request Bodies
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// src/routes/api/groups/create.tsx
|
|
205
|
+
import { CreateGroupSchema } from '@/schemas/group-conversation'
|
|
206
|
+
|
|
207
|
+
POST: async ({ request }) => {
|
|
208
|
+
const body = await request.json()
|
|
209
|
+
const parsed = CreateGroupSchema.safeParse(body)
|
|
210
|
+
|
|
211
|
+
if (!parsed.success) {
|
|
212
|
+
return new Response(JSON.stringify({
|
|
213
|
+
error: 'Validation error',
|
|
214
|
+
details: parsed.error.issues,
|
|
215
|
+
}), {
|
|
216
|
+
status: 400,
|
|
217
|
+
headers: { 'Content-Type': 'application/json' },
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Use parsed.data (fully typed and validated)
|
|
222
|
+
const group = await service.create(user.uid, parsed.data)
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Schema Naming Conventions
|
|
229
|
+
|
|
230
|
+
| Schema | Type | Purpose |
|
|
231
|
+
|--------|------|---------|
|
|
232
|
+
| `{Entity}Schema` | `z.object(...)` | Full entity (read from DB) |
|
|
233
|
+
| `Create{Entity}Schema` | `z.object(...)` | Input for creation (fewer fields) |
|
|
234
|
+
| `Update{Entity}Schema` | `z.object(...)` | Input for update (all optional) |
|
|
235
|
+
| `{Entity}` | `z.infer<>` | TypeScript type for full entity |
|
|
236
|
+
| `Create{Entity}Input` | `z.infer<>` | TypeScript type for creation |
|
|
237
|
+
| `Update{Entity}Input` | `z.infer<>` | TypeScript type for update |
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Benefits
|
|
242
|
+
|
|
243
|
+
### 1. Runtime + Compile-Time Safety
|
|
244
|
+
Zod validates at runtime; `z.infer<>` provides compile-time types. Both from one definition.
|
|
245
|
+
|
|
246
|
+
### 2. Self-Documenting
|
|
247
|
+
Schemas serve as documentation for data models, including optional fields, constraints, and defaults.
|
|
248
|
+
|
|
249
|
+
### 3. Schemaless DB Safety
|
|
250
|
+
Firestore doesn't enforce schemas — Zod catches invalid or corrupted data on read.
|
|
251
|
+
|
|
252
|
+
### 4. API Input Validation
|
|
253
|
+
`safeParse` provides detailed validation errors (field-level) returned to clients.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Trade-offs
|
|
258
|
+
|
|
259
|
+
### 1. Validation Overhead
|
|
260
|
+
**Downside**: Parsing every database read adds CPU time.
|
|
261
|
+
**Mitigation**: Only `safeParse` at boundaries. Internal data passed between services is already validated.
|
|
262
|
+
|
|
263
|
+
### 2. Schema Duplication
|
|
264
|
+
**Downside**: Separate create/update/read schemas can feel repetitive.
|
|
265
|
+
**Mitigation**: Use Zod utilities: `.pick()`, `.omit()`, `.partial()` to derive schemas from the base.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Anti-Patterns
|
|
270
|
+
|
|
271
|
+
### ❌ Anti-Pattern 1: Hand-Written Types Alongside Schemas
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
// ❌ BAD: Types defined separately — can drift from schema
|
|
275
|
+
const ProfileSchema = z.object({ display_name: z.string() })
|
|
276
|
+
interface Profile { displayName: string } // Mismatch!
|
|
277
|
+
|
|
278
|
+
// ✅ GOOD: Derive types from schema
|
|
279
|
+
const ProfileSchema = z.object({ display_name: z.string() })
|
|
280
|
+
type Profile = z.infer<typeof ProfileSchema>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### ❌ Anti-Pattern 2: Using parse Instead of safeParse
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
// ❌ BAD: parse throws on invalid data — crashes the service
|
|
287
|
+
const profile = ProfileSchema.parse(doc) // Throws ZodError!
|
|
288
|
+
|
|
289
|
+
// ✅ GOOD: safeParse returns result object
|
|
290
|
+
const result = ProfileSchema.safeParse(doc)
|
|
291
|
+
if (!result.success) {
|
|
292
|
+
console.error('Invalid data:', result.error)
|
|
293
|
+
return null
|
|
294
|
+
}
|
|
295
|
+
return result.data
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### ❌ Anti-Pattern 3: Schemas Outside schemas/ Directory
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
// ❌ BAD: Schema defined inline in service file
|
|
302
|
+
// src/services/profile.service.ts
|
|
303
|
+
const ProfileSchema = z.object({ ... }) // Not discoverable
|
|
304
|
+
|
|
305
|
+
// ✅ GOOD: Schema in centralized directory
|
|
306
|
+
// src/schemas/profile.ts — discoverable, importable, documented
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Related Patterns
|
|
312
|
+
|
|
313
|
+
- **[Library Services Pattern](./tanstack-cloudflare.library-services.md)**: Services use Zod schemas for validation
|
|
314
|
+
- **[API Route Handlers](./tanstack-cloudflare.api-route-handlers.md)**: API routes validate request bodies with schemas
|
|
315
|
+
- **[User-Scoped Collections](./tanstack-cloudflare.user-scoped-collections.md)**: Schemas document Firestore storage paths
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Checklist for Implementation
|
|
320
|
+
|
|
321
|
+
- [ ] All data models defined as Zod schemas in `src/schemas/`
|
|
322
|
+
- [ ] TypeScript types derived with `z.infer<>`, not hand-written
|
|
323
|
+
- [ ] Separate schemas for create, update, and full entity
|
|
324
|
+
- [ ] JSDoc comments document Firestore storage path
|
|
325
|
+
- [ ] Services use `safeParse` (not `parse`) for database reads
|
|
326
|
+
- [ ] API routes use `safeParse` for request body validation
|
|
327
|
+
- [ ] 400 responses include `details: zodError.issues`
|
|
328
|
+
- [ ] Permission presets defined alongside schemas
|
|
329
|
+
- [ ] No `user_id` field in user-scoped document schemas
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
**Status**: Stable - Core data integrity pattern
|
|
334
|
+
**Recommendation**: Use for all applications with structured data models
|
|
335
|
+
**Last Updated**: 2026-02-28
|
|
336
|
+
**Contributors**: Patrick Michaelsen
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Project Progress Tracking
|
|
2
|
+
# This file tracks the overall progress of the project, including milestones, tasks, and recent work.
|
|
3
|
+
# Update this file regularly as work progresses.
|
|
4
|
+
|
|
5
|
+
project:
|
|
6
|
+
name: project-name # Replace with your project name
|
|
7
|
+
version: 0.1.0 # Current version (semantic versioning)
|
|
8
|
+
started: YYYY-MM-DD # Date project started
|
|
9
|
+
status: not_started # not_started | in_progress | completed
|
|
10
|
+
current_milestone: M1 # Current milestone identifier
|
|
11
|
+
description: | # Brief project description
|
|
12
|
+
A short description of what this project does and its main purpose.
|
|
13
|
+
|
|
14
|
+
# Milestones represent major phases of the project
|
|
15
|
+
milestones:
|
|
16
|
+
- id: M1 # Unique milestone identifier
|
|
17
|
+
name: Milestone Name # Descriptive name
|
|
18
|
+
status: not_started # not_started | in_progress | completed
|
|
19
|
+
progress: 0 # Percentage complete (0-100)
|
|
20
|
+
started: null # YYYY-MM-DD when started, null if not started
|
|
21
|
+
completed: null # YYYY-MM-DD when completed, null if not completed
|
|
22
|
+
estimated_weeks: 2 # Estimated duration in weeks
|
|
23
|
+
tasks_completed: 0 # Number of tasks completed
|
|
24
|
+
tasks_total: 5 # Total number of tasks in this milestone
|
|
25
|
+
notes: | # Progress notes and observations
|
|
26
|
+
Notes about this milestone's progress, blockers, or important decisions.
|
|
27
|
+
|
|
28
|
+
- id: M2
|
|
29
|
+
name: Second Milestone Name
|
|
30
|
+
status: not_started
|
|
31
|
+
progress: 0
|
|
32
|
+
started: null
|
|
33
|
+
completed: null
|
|
34
|
+
estimated_weeks: 3
|
|
35
|
+
tasks_completed: 0
|
|
36
|
+
tasks_total: 7
|
|
37
|
+
notes: |
|
|
38
|
+
This milestone depends on M1 completion.
|
|
39
|
+
|
|
40
|
+
# Tasks are granular work items within milestones
|
|
41
|
+
tasks:
|
|
42
|
+
milestone_1: # Group tasks by milestone
|
|
43
|
+
- id: task-1 # Unique task identifier
|
|
44
|
+
name: Task Name # Descriptive task name
|
|
45
|
+
status: not_started # not_started | in_progress | completed
|
|
46
|
+
file: agent/tasks/task-1-name.md # Path to task document
|
|
47
|
+
estimated_hours: 4 # Estimated time in hours
|
|
48
|
+
actual_hours: null # Actual time spent (null until completed)
|
|
49
|
+
completed_date: null # YYYY-MM-DD when completed, null if not completed
|
|
50
|
+
notes: | # Task-specific notes
|
|
51
|
+
Any important notes about this task.
|
|
52
|
+
|
|
53
|
+
- id: task-2
|
|
54
|
+
name: Second Task Name
|
|
55
|
+
status: not_started
|
|
56
|
+
file: agent/tasks/task-2-name.md
|
|
57
|
+
estimated_hours: 2
|
|
58
|
+
actual_hours: null
|
|
59
|
+
completed_date: null
|
|
60
|
+
notes: |
|
|
61
|
+
Depends on task-1 completion.
|
|
62
|
+
|
|
63
|
+
milestone_2:
|
|
64
|
+
- id: task-3
|
|
65
|
+
name: Third Task Name
|
|
66
|
+
status: not_started
|
|
67
|
+
file: agent/tasks/task-3-name.md
|
|
68
|
+
estimated_hours: 6
|
|
69
|
+
actual_hours: null
|
|
70
|
+
completed_date: null
|
|
71
|
+
notes: |
|
|
72
|
+
First task of second milestone.
|
|
73
|
+
|
|
74
|
+
# Documentation tracking
|
|
75
|
+
documentation:
|
|
76
|
+
design_documents: 0 # Number of design documents created
|
|
77
|
+
milestone_documents: 0 # Number of milestone documents
|
|
78
|
+
pattern_documents: 0 # Number of pattern documents
|
|
79
|
+
task_documents: 0 # Number of task documents
|
|
80
|
+
last_updated: YYYY-MM-DD # Last documentation update date
|
|
81
|
+
|
|
82
|
+
# Overall progress metrics
|
|
83
|
+
progress:
|
|
84
|
+
planning: 0 # Planning phase completion (0-100%)
|
|
85
|
+
implementation: 0 # Implementation phase completion (0-100%)
|
|
86
|
+
testing: 0 # Testing phase completion (0-100%)
|
|
87
|
+
documentation: 0 # Documentation completion (0-100%)
|
|
88
|
+
overall: 0 # Overall project completion (0-100%)
|
|
89
|
+
|
|
90
|
+
# Recent work log (most recent first)
|
|
91
|
+
recent_work:
|
|
92
|
+
- date: YYYY-MM-DD # Date of work
|
|
93
|
+
description: | # Description of what was done
|
|
94
|
+
Brief description of work completed on this date.
|
|
95
|
+
items: # Specific items completed
|
|
96
|
+
- ✅ Completed item 1
|
|
97
|
+
- ✅ Completed item 2
|
|
98
|
+
- ⚠️ Warning or note about something
|
|
99
|
+
- 📋 Pending item or follow-up needed
|
|
100
|
+
|
|
101
|
+
- date: YYYY-MM-DD
|
|
102
|
+
description: |
|
|
103
|
+
Earlier work session description.
|
|
104
|
+
items:
|
|
105
|
+
- ✅ Another completed item
|
|
106
|
+
- 📋 Something to revisit
|
|
107
|
+
|
|
108
|
+
# Next steps (prioritized list)
|
|
109
|
+
next_steps:
|
|
110
|
+
- Next action item 1 (highest priority)
|
|
111
|
+
- Next action item 2
|
|
112
|
+
- Next action item 3
|
|
113
|
+
- Future consideration or enhancement
|
|
114
|
+
|
|
115
|
+
# General notes and observations
|
|
116
|
+
notes:
|
|
117
|
+
- Important note 1 about the project
|
|
118
|
+
- Important note 2 about architectural decisions
|
|
119
|
+
- Important note 3 about dependencies or constraints
|
|
120
|
+
|
|
121
|
+
# Current blockers (remove when resolved)
|
|
122
|
+
current_blockers:
|
|
123
|
+
- Blocker 1: Description of what's blocking progress
|
|
124
|
+
- Blocker 2: Another blocker and potential resolution
|
|
125
|
+
|
|
126
|
+
# Team and contributors (if applicable)
|
|
127
|
+
team:
|
|
128
|
+
- role: Lead Developer # Role or responsibility
|
|
129
|
+
name: Name or "Agent" # Name or identifier
|
|
130
|
+
focus: | # Current focus area
|
|
131
|
+
What this person/agent is currently working on
|
|
132
|
+
|
|
133
|
+
- role: Documentation
|
|
134
|
+
name: Name or "Agent"
|
|
135
|
+
focus: |
|
|
136
|
+
Maintaining documentation and patterns
|
|
137
|
+
|
|
138
|
+
# Dependencies and integrations
|
|
139
|
+
dependencies:
|
|
140
|
+
external_services: # External services this project depends on
|
|
141
|
+
- name: Service Name
|
|
142
|
+
status: configured | pending | blocked
|
|
143
|
+
notes: |
|
|
144
|
+
Notes about this dependency
|
|
145
|
+
|
|
146
|
+
libraries: # Key library dependencies
|
|
147
|
+
- name: Library Name
|
|
148
|
+
version: 1.0.0
|
|
149
|
+
purpose: |
|
|
150
|
+
Why this library is used
|
|
151
|
+
|
|
152
|
+
infrastructure: # Infrastructure requirements
|
|
153
|
+
- name: Infrastructure Component
|
|
154
|
+
status: ready | pending | blocked
|
|
155
|
+
notes: |
|
|
156
|
+
Notes about this infrastructure
|
|
157
|
+
|
|
158
|
+
# Quality metrics (optional)
|
|
159
|
+
quality:
|
|
160
|
+
test_coverage: 0 # Percentage (0-100)
|
|
161
|
+
code_review_status: pending # pending | in
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
project:
|
|
2
|
+
name: agent-context-protocol-visualizer
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
started: 2026-03-14
|
|
5
|
+
status: completed
|
|
6
|
+
current_milestone: milestone_2
|
|
7
|
+
description: |
|
|
8
|
+
Browser-based read-only dashboard for visualizing ACP progress.yaml data.
|
|
9
|
+
TanStack Start app with table/tree/kanban views, search, filtering, and auto-refresh.
|
|
10
|
+
|
|
11
|
+
milestones:
|
|
12
|
+
- id: milestone_1
|
|
13
|
+
name: Project Scaffold & Data Pipeline
|
|
14
|
+
status: completed
|
|
15
|
+
progress: 100
|
|
16
|
+
started: "2026-03-14"
|
|
17
|
+
completed: "2026-03-14"
|
|
18
|
+
estimated_weeks: "1"
|
|
19
|
+
tasks_completed: 4
|
|
20
|
+
tasks_total: 4
|
|
21
|
+
notes: Foundation milestone — all subsequent work depends on this data pipeline
|
|
22
|
+
|
|
23
|
+
- id: milestone_2
|
|
24
|
+
name: Dashboard Views & Interaction
|
|
25
|
+
status: completed
|
|
26
|
+
progress: 100
|
|
27
|
+
started: "2026-03-14"
|
|
28
|
+
completed: "2026-03-14"
|
|
29
|
+
estimated_weeks: "1.5"
|
|
30
|
+
tasks_completed: 6
|
|
31
|
+
tasks_total: 6
|
|
32
|
+
notes: P0 dashboard UI — table, tree, search, filtering
|
|
33
|
+
|
|
34
|
+
tasks:
|
|
35
|
+
milestone_1:
|
|
36
|
+
- id: task_1
|
|
37
|
+
name: Initialize TanStack Start Project
|
|
38
|
+
status: completed
|
|
39
|
+
file: agent/tasks/milestone-1-project-scaffold-data-pipeline/task-1-initialize-tanstack-start-project.md
|
|
40
|
+
estimated_hours: "2"
|
|
41
|
+
completed_date: "2026-03-14"
|
|
42
|
+
notes: Scaffold project with Vite, Tailwind, all P0 deps
|
|
43
|
+
|
|
44
|
+
- id: task_2
|
|
45
|
+
name: Implement Data Model & YAML Parser
|
|
46
|
+
status: completed
|
|
47
|
+
file: agent/tasks/milestone-1-project-scaffold-data-pipeline/task-2-implement-data-model-yaml-parser.md
|
|
48
|
+
estimated_hours: "3"
|
|
49
|
+
completed_date: "2026-03-14"
|
|
50
|
+
notes: Types, lenient parsing, agent-drift handling
|
|
51
|
+
|
|
52
|
+
- id: task_3
|
|
53
|
+
name: Build Server API & Data Loading
|
|
54
|
+
status: completed
|
|
55
|
+
file: agent/tasks/milestone-1-project-scaffold-data-pipeline/task-3-build-server-api-data-loading.md
|
|
56
|
+
estimated_hours: "2"
|
|
57
|
+
completed_date: "2026-03-14"
|
|
58
|
+
notes: ProgressDatabaseService, beforeLoad SSR
|
|
59
|
+
|
|
60
|
+
- id: task_4
|
|
61
|
+
name: Add Auto-Refresh via SSE
|
|
62
|
+
status: completed
|
|
63
|
+
file: agent/tasks/milestone-1-project-scaffold-data-pipeline/task-4-add-auto-refresh-sse.md
|
|
64
|
+
estimated_hours: "2"
|
|
65
|
+
completed_date: "2026-03-14"
|
|
66
|
+
notes: File watcher, SSE endpoint, useAutoRefresh hook
|
|
67
|
+
|
|
68
|
+
milestone_2:
|
|
69
|
+
- id: task_5
|
|
70
|
+
name: Build Dashboard Layout & Routing
|
|
71
|
+
status: completed
|
|
72
|
+
file: agent/tasks/milestone-2-dashboard-views-interaction/task-5-build-dashboard-layout-routing.md
|
|
73
|
+
estimated_hours: "3"
|
|
74
|
+
completed_date: "2026-03-14"
|
|
75
|
+
notes: Root layout, sidebar, header, design tokens
|
|
76
|
+
|
|
77
|
+
- id: task_6
|
|
78
|
+
name: Build Overview Page
|
|
79
|
+
status: completed
|
|
80
|
+
file: agent/tasks/milestone-2-dashboard-views-interaction/task-6-build-overview-page.md
|
|
81
|
+
estimated_hours: "2"
|
|
82
|
+
completed_date: "2026-03-14"
|
|
83
|
+
notes: Project summary dashboard
|
|
84
|
+
|
|
85
|
+
- id: task_7
|
|
86
|
+
name: Implement Milestone Table View
|
|
87
|
+
status: completed
|
|
88
|
+
file: agent/tasks/milestone-2-dashboard-views-interaction/task-7-implement-milestone-table-view.md
|
|
89
|
+
estimated_hours: "3"
|
|
90
|
+
completed_date: "2026-03-14"
|
|
91
|
+
notes: "@tanstack/react-table with sorting, row expansion"
|
|
92
|
+
|
|
93
|
+
- id: task_8
|
|
94
|
+
name: Implement Milestone Tree View
|
|
95
|
+
status: completed
|
|
96
|
+
file: agent/tasks/milestone-2-dashboard-views-interaction/task-8-implement-milestone-tree-view.md
|
|
97
|
+
estimated_hours: "2"
|
|
98
|
+
completed_date: "2026-03-14"
|
|
99
|
+
notes: Expandable hierarchy, useCollapse animation
|
|
100
|
+
|
|
101
|
+
- id: task_9
|
|
102
|
+
name: Implement Search & Filtering
|
|
103
|
+
status: completed
|
|
104
|
+
file: agent/tasks/milestone-2-dashboard-views-interaction/task-9-implement-search-filtering.md
|
|
105
|
+
estimated_hours: "3"
|
|
106
|
+
completed_date: "2026-03-14"
|
|
107
|
+
notes: Fuse.js, FilterBar, SearchInput, useFilteredData
|
|
108
|
+
|
|
109
|
+
- id: task_10
|
|
110
|
+
name: Polish & Integration Testing
|
|
111
|
+
status: completed
|
|
112
|
+
file: agent/tasks/milestone-2-dashboard-views-interaction/task-10-polish-integration-testing.md
|
|
113
|
+
estimated_hours: "2"
|
|
114
|
+
completed_date: "2026-03-14"
|
|
115
|
+
notes: Error states, empty states, end-to-end verification
|
|
116
|
+
|
|
117
|
+
documentation:
|
|
118
|
+
design_documents: 6
|
|
119
|
+
milestone_documents: 2
|
|
120
|
+
pattern_documents: 42
|
|
121
|
+
task_documents: 10
|
|
122
|
+
|
|
123
|
+
progress:
|
|
124
|
+
planning: 100
|
|
125
|
+
implementation: 100
|
|
126
|
+
overall: 100
|
|
127
|
+
|
|
128
|
+
recent_work:
|
|
129
|
+
- date: "2026-03-14"
|
|
130
|
+
description: Project planning complete
|
|
131
|
+
items:
|
|
132
|
+
- Created requirements document (local.visualizer-requirements.md)
|
|
133
|
+
- Created 5 functional design documents with pattern references
|
|
134
|
+
- Installed tanstack-cloudflare package (42 patterns)
|
|
135
|
+
- Planned 2 milestones with 10 tasks
|
|
136
|
+
- Created milestone and task documents
|
|
137
|
+
|
|
138
|
+
next_steps:
|
|
139
|
+
- "P0 complete — test with other ACP project progress.yaml files"
|
|
140
|
+
- "Point visualizer at remember-core via PROGRESS_YAML_PATH env var"
|
|
141
|
+
- "Plan P1 features: kanban view, activity timeline, GitHub remote loading"
|
|
142
|
+
|
|
143
|
+
notes: []
|
|
144
|
+
|
|
145
|
+
current_blockers: []
|