@claudetools/tools 0.8.10 → 0.9.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/dist/codedna/generators/astro.d.ts +18 -0
- package/dist/codedna/generators/astro.js +91 -0
- package/dist/codedna/generators/authjs.d.ts +18 -0
- package/dist/codedna/generators/authjs.js +68 -0
- package/dist/codedna/generators/better-auth.d.ts +18 -0
- package/dist/codedna/generators/better-auth.js +62 -0
- package/dist/codedna/generators/drizzle-orm.d.ts +18 -0
- package/dist/codedna/generators/drizzle-orm.js +65 -0
- package/dist/codedna/generators/elysia-api.d.ts +12 -0
- package/dist/codedna/generators/elysia-api.js +64 -0
- package/dist/codedna/generators/hono-api.d.ts +12 -0
- package/dist/codedna/generators/hono-api.js +64 -0
- package/dist/codedna/generators/lucia-auth.d.ts +18 -0
- package/dist/codedna/generators/lucia-auth.js +69 -0
- package/dist/codedna/generators/prisma.d.ts +18 -0
- package/dist/codedna/generators/prisma.js +64 -0
- package/dist/codedna/generators/react-router-v7.d.ts +18 -0
- package/dist/codedna/generators/react-router-v7.js +77 -0
- package/dist/codedna/generators/react19-shadcn.d.ts +21 -0
- package/dist/codedna/generators/react19-shadcn.js +367 -0
- package/dist/codedna/generators/sveltekit.d.ts +18 -0
- package/dist/codedna/generators/sveltekit.js +73 -0
- package/dist/codedna/generators/tanstack-start-drizzle.d.ts +92 -0
- package/dist/codedna/generators/tanstack-start-drizzle.js +824 -0
- package/dist/codedna/generators/trpc-api.d.ts +12 -0
- package/dist/codedna/generators/trpc-api.js +64 -0
- package/dist/codedna/index.d.ts +31 -0
- package/dist/codedna/index.js +39 -0
- package/dist/codedna/kappa-api-generator.d.ts +89 -0
- package/dist/codedna/kappa-api-generator.js +493 -0
- package/dist/codedna/kappa-ast.d.ts +552 -0
- package/dist/codedna/kappa-ast.js +141 -0
- package/dist/codedna/kappa-cli.d.ts +2 -0
- package/dist/codedna/kappa-cli.js +302 -0
- package/dist/codedna/kappa-component-generator.d.ts +47 -0
- package/dist/codedna/kappa-component-generator.js +295 -0
- package/dist/codedna/kappa-design-generator.d.ts +52 -0
- package/dist/codedna/kappa-design-generator.js +365 -0
- package/dist/codedna/kappa-drizzle-generator.d.ts +45 -0
- package/dist/codedna/kappa-drizzle-generator.js +355 -0
- package/dist/codedna/kappa-form-generator.d.ts +51 -0
- package/dist/codedna/kappa-form-generator.js +319 -0
- package/dist/codedna/kappa-lexer.d.ts +268 -0
- package/dist/codedna/kappa-lexer.js +757 -0
- package/dist/codedna/kappa-page-generator.d.ts +57 -0
- package/dist/codedna/kappa-page-generator.js +338 -0
- package/dist/codedna/kappa-parser.d.ts +261 -0
- package/dist/codedna/kappa-parser.js +2547 -0
- package/dist/codedna/kappa-provenance.d.ts +101 -0
- package/dist/codedna/kappa-provenance.js +199 -0
- package/dist/codedna/kappa-types-generator.d.ts +37 -0
- package/dist/codedna/kappa-types-generator.js +159 -0
- package/dist/codedna/kappa-validator.d.ts +86 -0
- package/dist/codedna/kappa-validator.js +638 -0
- package/dist/codedna/kappa-zod-generator.d.ts +32 -0
- package/dist/codedna/kappa-zod-generator.js +216 -0
- package/dist/handlers/codedna-handlers.d.ts +1 -1
- package/dist/handlers/kappa-handlers.d.ts +116 -0
- package/dist/handlers/kappa-handlers.js +465 -0
- package/dist/handlers/tool-handlers.js +121 -0
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.js +166 -9
- package/dist/tools.js +199 -0
- package/docs/research/2026-01-02-codedna-il-specification.md +639 -0
- package/docs/research/2026-01-02-codedna-v2-research.md +943 -0
- package/docs/research/2026-01-02-computation-foundations.md +564 -0
- package/docs/research/2026-01-02-hardware-description.md +814 -0
- package/docs/research/2026-01-02-kappa-specification.md +697 -0
- package/docs/research/2026-01-02-kappa-tanstack-example.md +527 -0
- package/docs/research/2026-01-02-kappa-v2-synthesis.md +406 -0
- package/docs/research/2026-01-02-kappa-v2.5-specification.md +1218 -0
- package/docs/research/2026-01-02-kappa-v3-specification.md +1864 -0
- package/docs/research/2026-01-02-kappa-whitepaper.md +662 -0
- package/docs/research/2026-01-02-logic-constraint.md +731 -0
- package/docs/research/2026-01-02-quantum-computation.md +635 -0
- package/package.json +4 -2
|
@@ -0,0 +1,1218 @@
|
|
|
1
|
+
# Kappa v2.5: The Practical Specification Language
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-02
|
|
4
|
+
**Status:** CodeDNA Foundation Spec
|
|
5
|
+
**Philosophy:** Novel enough to matter. Practical enough to ship.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Part I: Design Principles
|
|
10
|
+
|
|
11
|
+
### 1.1 What We Keep (Novel + Buildable)
|
|
12
|
+
|
|
13
|
+
| Feature | Why It's Novel | Why It's Buildable |
|
|
14
|
+
|---------|---------------|-------------------|
|
|
15
|
+
| Entity Capabilities | `can:` / `cannot:` replace scattered permission logic | Maps directly to middleware/guards |
|
|
16
|
+
| Lifecycle Hooks | `on_create:`, `on_delete:` are declarative | Generates event handlers |
|
|
17
|
+
| Journeys | User flows as first-class, not route derivatives | State machine generators exist |
|
|
18
|
+
| Effect Annotations | `-[DB, Auth]->` declares side effects | Generates middleware chains |
|
|
19
|
+
| Provenance | Every line traces to spec | Comment generation |
|
|
20
|
+
| Rich Field Constraints | `string(2..100)`, `email`, `unique` | Zod/Valibot schemas |
|
|
21
|
+
|
|
22
|
+
### 1.2 What We Drop (Research Territory)
|
|
23
|
+
|
|
24
|
+
| Feature | Why We Drop It |
|
|
25
|
+
|---------|---------------|
|
|
26
|
+
| Constraint Solver | Unbounded synthesis is research, not engineering |
|
|
27
|
+
| Mood → Design | Requires AI inference, non-deterministic |
|
|
28
|
+
| Bidirectional Sync | Every attempt at this has failed at scale |
|
|
29
|
+
| Goal Inference | "ensure: no duplicate accounts" needs AI to interpret |
|
|
30
|
+
| Learning System | Pattern extraction is ML research |
|
|
31
|
+
|
|
32
|
+
### 1.3 The Core Insight
|
|
33
|
+
|
|
34
|
+
**Kappa v2.5 is a high-level DSL that compiles to code via generators.**
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
Kappa Spec → Parser → AST → Generator(framework) → Code
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
No AI in the loop. No constraint solving. Deterministic compilation.
|
|
41
|
+
|
|
42
|
+
The AI writes the Kappa spec. The generator produces the code. Separation of concerns.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Part II: Language Specification
|
|
47
|
+
|
|
48
|
+
### 2.1 Project Declaration
|
|
49
|
+
|
|
50
|
+
```kappa
|
|
51
|
+
project TaskFlow {
|
|
52
|
+
version: "1.0.0"
|
|
53
|
+
stack: tanstack-start | next | remix | express
|
|
54
|
+
database: postgres | mysql | sqlite | turso
|
|
55
|
+
auth: jwt | session | oauth
|
|
56
|
+
ui: shadcn | mui | chakra | tailwind-only
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Generator behavior:** Stack choice selects generator. All other options configure it.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### 2.2 Auth Block
|
|
65
|
+
|
|
66
|
+
```kappa
|
|
67
|
+
auth jwt {
|
|
68
|
+
secret: env(JWT_SECRET)
|
|
69
|
+
issuer: "taskflow.app"
|
|
70
|
+
audience: "taskflow-api"
|
|
71
|
+
expires: 7d
|
|
72
|
+
refresh: sliding | fixed | none
|
|
73
|
+
|
|
74
|
+
hash: argon2id {
|
|
75
|
+
memory: 64mb
|
|
76
|
+
iterations: 3
|
|
77
|
+
parallelism: 1
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Or shorthand
|
|
81
|
+
hash: argon2id(memory: 64mb, iterations: 3)
|
|
82
|
+
|
|
83
|
+
# Or bcrypt
|
|
84
|
+
hash: bcrypt(rounds: 12)
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Generates:**
|
|
89
|
+
- `lib/auth.ts` - JWT sign/verify, password hashing
|
|
90
|
+
- `middleware/auth.ts` - requireAuth, optionalAuth
|
|
91
|
+
- Session management if `refresh: sliding`
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### 2.3 Entity Block
|
|
96
|
+
|
|
97
|
+
Entities are the core data model with capabilities and lifecycle.
|
|
98
|
+
|
|
99
|
+
```kappa
|
|
100
|
+
entity User {
|
|
101
|
+
# === FIELDS ===
|
|
102
|
+
id: uuid, primary, auto
|
|
103
|
+
email: email, unique, immutable
|
|
104
|
+
name: string(2..100)
|
|
105
|
+
password: string, hashed, internal # never exposed in API
|
|
106
|
+
role: admin | member | guest = member
|
|
107
|
+
avatar: url?
|
|
108
|
+
created_at: timestamp, auto
|
|
109
|
+
updated_at: timestamp, auto, on_update
|
|
110
|
+
|
|
111
|
+
# === RELATIONSHIPS ===
|
|
112
|
+
has_many: Project (as owner, cascade: nullify)
|
|
113
|
+
has_many: Membership
|
|
114
|
+
has_many: Team (through: Membership)
|
|
115
|
+
|
|
116
|
+
# === CAPABILITIES ===
|
|
117
|
+
can: [
|
|
118
|
+
create Project,
|
|
119
|
+
read Project (where: member_of),
|
|
120
|
+
update Project (where: owner_of),
|
|
121
|
+
delete Project (where: owner_of),
|
|
122
|
+
invite User (to: Team, where: admin_of)
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
cannot: [
|
|
126
|
+
delete self (unless: no_owned_projects),
|
|
127
|
+
change role (unless: admin)
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
# === LIFECYCLE ===
|
|
131
|
+
on_create: [
|
|
132
|
+
send_email(template: welcome),
|
|
133
|
+
log_audit(action: user_created),
|
|
134
|
+
enqueue(job: sync_to_crm)
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
on_update(email): [
|
|
138
|
+
send_email(template: email_changed, to: old.email),
|
|
139
|
+
require_reverification
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
on_delete: [
|
|
143
|
+
anonymize(fields: [email, name]),
|
|
144
|
+
transfer_ownership(to: system_user),
|
|
145
|
+
log_audit(action: user_deleted)
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
# === INDEXES ===
|
|
149
|
+
index: [email]
|
|
150
|
+
index: [role, created_at]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### Field Modifiers
|
|
155
|
+
|
|
156
|
+
| Modifier | Meaning | Generates |
|
|
157
|
+
|----------|---------|-----------|
|
|
158
|
+
| `primary` | Primary key | Schema primary key |
|
|
159
|
+
| `unique` | Unique constraint | DB constraint + validation |
|
|
160
|
+
| `auto` | Auto-generated | Default value / trigger |
|
|
161
|
+
| `immutable` | Cannot be changed after creation | Update validation |
|
|
162
|
+
| `internal` | Never exposed in API responses | DTO exclusion |
|
|
163
|
+
| `hashed` | Stored as hash | Hash on write, verify on read |
|
|
164
|
+
| `?` suffix | Optional/nullable | Optional in schema |
|
|
165
|
+
| `= value` | Default value | Schema default |
|
|
166
|
+
|
|
167
|
+
#### Field Types
|
|
168
|
+
|
|
169
|
+
```kappa
|
|
170
|
+
# Primitives
|
|
171
|
+
string # Any string
|
|
172
|
+
string(10) # Exactly 10 chars
|
|
173
|
+
string(2..100) # 2-100 chars
|
|
174
|
+
string(..500) # Max 500 chars
|
|
175
|
+
int # Integer
|
|
176
|
+
int(0..100) # Range constraint
|
|
177
|
+
float # Decimal
|
|
178
|
+
bool # Boolean
|
|
179
|
+
|
|
180
|
+
# Semantic Types (with built-in validation)
|
|
181
|
+
email # Valid email format
|
|
182
|
+
url # Valid URL
|
|
183
|
+
uuid # UUID v4
|
|
184
|
+
phone # Phone number (E.164)
|
|
185
|
+
slug # URL-safe string
|
|
186
|
+
markdown # Markdown content
|
|
187
|
+
json # Arbitrary JSON
|
|
188
|
+
|
|
189
|
+
# Temporal
|
|
190
|
+
timestamp # DateTime
|
|
191
|
+
date # Date only
|
|
192
|
+
time # Time only
|
|
193
|
+
duration # Time duration
|
|
194
|
+
|
|
195
|
+
# Enums (inline)
|
|
196
|
+
status: draft | published | archived
|
|
197
|
+
|
|
198
|
+
# References
|
|
199
|
+
owner: -> User # Foreign key
|
|
200
|
+
owner: -> User? # Optional foreign key
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### 2.4 API Block
|
|
206
|
+
|
|
207
|
+
Define API operations with effects.
|
|
208
|
+
|
|
209
|
+
```kappa
|
|
210
|
+
api Users {
|
|
211
|
+
# === AUTH ENDPOINTS ===
|
|
212
|
+
|
|
213
|
+
signup: (
|
|
214
|
+
email: email,
|
|
215
|
+
password: string(8..),
|
|
216
|
+
name: string(2..100)
|
|
217
|
+
) -[DB, Email, Audit]-> User
|
|
218
|
+
throws: EmailTaken, WeakPassword
|
|
219
|
+
rate_limit: 5/minute
|
|
220
|
+
|
|
221
|
+
login: (
|
|
222
|
+
email: email,
|
|
223
|
+
password: string
|
|
224
|
+
) -[DB, Auth]-> { user: User, token: string }
|
|
225
|
+
throws: InvalidCredentials
|
|
226
|
+
rate_limit: 10/minute
|
|
227
|
+
audit: always
|
|
228
|
+
|
|
229
|
+
logout: () -[Auth]-> void
|
|
230
|
+
|
|
231
|
+
me: () -[Auth]-> User
|
|
232
|
+
|
|
233
|
+
# === CRUD (shorthand) ===
|
|
234
|
+
|
|
235
|
+
crud Project {
|
|
236
|
+
create: -[Auth, DB]-> Project
|
|
237
|
+
read: -[Auth, DB]-> Project
|
|
238
|
+
update: -[Auth, DB]-> Project (check: owner_of)
|
|
239
|
+
delete: -[Auth, DB]-> void (check: owner_of)
|
|
240
|
+
list: -[Auth, DB]-> [Project] (filter: member_of)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
# === CUSTOM OPERATIONS ===
|
|
244
|
+
|
|
245
|
+
invite_to_project: (
|
|
246
|
+
project_id: uuid,
|
|
247
|
+
email: email,
|
|
248
|
+
role: owner | editor | viewer = viewer
|
|
249
|
+
) -[Auth, DB, Email]-> Invitation
|
|
250
|
+
check: owner_of(project_id)
|
|
251
|
+
throws: AlreadyMember, ProjectNotFound
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Effect Annotations
|
|
256
|
+
|
|
257
|
+
| Effect | Meaning | Generates |
|
|
258
|
+
|--------|---------|-----------|
|
|
259
|
+
| `DB` | Database access | Transaction wrapper |
|
|
260
|
+
| `Auth` | Requires authentication | Auth middleware |
|
|
261
|
+
| `Email` | Sends email | Email service call |
|
|
262
|
+
| `Audit` | Audit logging | Audit log entry |
|
|
263
|
+
| `Queue` | Background job | Queue enqueue |
|
|
264
|
+
| `Cache` | Uses cache | Cache read/write |
|
|
265
|
+
| `External` | External API call | HTTP client |
|
|
266
|
+
|
|
267
|
+
#### API Modifiers
|
|
268
|
+
|
|
269
|
+
| Modifier | Meaning |
|
|
270
|
+
|----------|---------|
|
|
271
|
+
| `throws: Error1, Error2` | Possible errors (generates error types) |
|
|
272
|
+
| `check: permission` | Capability check before execution |
|
|
273
|
+
| `rate_limit: N/period` | Rate limiting |
|
|
274
|
+
| `audit: always \| on_error \| never` | Audit logging behavior |
|
|
275
|
+
| `cache: duration` | Response caching |
|
|
276
|
+
| `deprecated: "message"` | Marks as deprecated |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### 2.5 Journey Block
|
|
281
|
+
|
|
282
|
+
User journeys are first-class. Not derived from routes.
|
|
283
|
+
|
|
284
|
+
```kappa
|
|
285
|
+
journey Onboarding {
|
|
286
|
+
actor: new_user
|
|
287
|
+
|
|
288
|
+
# === STEPS ===
|
|
289
|
+
steps {
|
|
290
|
+
signup {
|
|
291
|
+
page: SignupForm
|
|
292
|
+
action: api.signup
|
|
293
|
+
next: verify_email
|
|
294
|
+
on_error: show_error, stay
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
verify_email {
|
|
298
|
+
page: VerifyEmail
|
|
299
|
+
wait_for: email_verified
|
|
300
|
+
timeout: 24h -> resend_or_cancel
|
|
301
|
+
next: create_workspace
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
create_workspace {
|
|
305
|
+
page: WorkspaceSetup
|
|
306
|
+
action: api.create_workspace
|
|
307
|
+
next: invite_team
|
|
308
|
+
skip_if: joining_existing_workspace
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
invite_team {
|
|
312
|
+
page: InviteTeam
|
|
313
|
+
action: api.send_invites
|
|
314
|
+
next: ready
|
|
315
|
+
skippable: true
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
ready {
|
|
319
|
+
page: Dashboard
|
|
320
|
+
complete: true
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
# === ANALYTICS ===
|
|
325
|
+
track: [step_entered, step_completed, step_skipped, journey_completed]
|
|
326
|
+
|
|
327
|
+
# === RECOVERY ===
|
|
328
|
+
on_abandon(verify_email): send_reminder(after: 1h, max: 3)
|
|
329
|
+
on_abandon(create_workspace): send_help_email(after: 24h)
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Generates:**
|
|
334
|
+
- State machine for journey progression
|
|
335
|
+
- Route guards ensuring step order
|
|
336
|
+
- Analytics events
|
|
337
|
+
- Recovery job scheduling
|
|
338
|
+
- Progress persistence
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### 2.6 Page Block
|
|
343
|
+
|
|
344
|
+
Pages with data loading and layout.
|
|
345
|
+
|
|
346
|
+
```kappa
|
|
347
|
+
page Dashboard {
|
|
348
|
+
route: "/dashboard"
|
|
349
|
+
guard: authenticated
|
|
350
|
+
|
|
351
|
+
# === DATA ===
|
|
352
|
+
load {
|
|
353
|
+
projects: api.list_projects()
|
|
354
|
+
user: api.me()
|
|
355
|
+
notifications: api.notifications(unread: true, limit: 5)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# === LAYOUT ===
|
|
359
|
+
layout: AppShell {
|
|
360
|
+
header: Navbar(user: user, notifications: notifications)
|
|
361
|
+
sidebar: ProjectList(projects: projects)
|
|
362
|
+
content: ProjectGrid(projects: projects)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
# === ACTIONS ===
|
|
366
|
+
actions {
|
|
367
|
+
create_project: modal(CreateProjectForm) -> api.create_project -> refresh
|
|
368
|
+
mark_notification_read: api.mark_read -> refresh(notifications)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
# === META ===
|
|
372
|
+
title: "Dashboard | TaskFlow"
|
|
373
|
+
meta: { description: "Your projects and tasks" }
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
### 2.7 Component Block
|
|
380
|
+
|
|
381
|
+
Reusable UI components.
|
|
382
|
+
|
|
383
|
+
```kappa
|
|
384
|
+
component ProjectCard {
|
|
385
|
+
props {
|
|
386
|
+
project: Project
|
|
387
|
+
onEdit: () -> void
|
|
388
|
+
onDelete: () -> void
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
# === STRUCTURE ===
|
|
392
|
+
structure: card {
|
|
393
|
+
header {
|
|
394
|
+
title: project.name
|
|
395
|
+
badge: project.status
|
|
396
|
+
menu: [
|
|
397
|
+
item("Edit", onClick: onEdit, icon: edit),
|
|
398
|
+
item("Delete", onClick: onDelete, icon: trash, variant: danger)
|
|
399
|
+
]
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
body {
|
|
403
|
+
text: project.description ?? "No description"
|
|
404
|
+
meta: [
|
|
405
|
+
item(icon: calendar, value: format_date(project.created_at)),
|
|
406
|
+
item(icon: users, value: project.member_count)
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
footer {
|
|
411
|
+
avatar_group: project.members (max: 3)
|
|
412
|
+
link: "/projects/{project.id}"
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
# === VARIANTS ===
|
|
417
|
+
variants {
|
|
418
|
+
compact: hide(body.meta, footer.avatar_group)
|
|
419
|
+
minimal: only(header.title, footer.link)
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### Compound Component Pattern
|
|
425
|
+
|
|
426
|
+
```kappa
|
|
427
|
+
component DataTable {
|
|
428
|
+
props {
|
|
429
|
+
data: [T]
|
|
430
|
+
columns: [Column<T>]
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
compound {
|
|
434
|
+
Root: table_container
|
|
435
|
+
Header: thead
|
|
436
|
+
HeaderRow: tr
|
|
437
|
+
HeaderCell: th (sortable?, filterable?)
|
|
438
|
+
Body: tbody
|
|
439
|
+
Row: tr (selectable?, expandable?)
|
|
440
|
+
Cell: td
|
|
441
|
+
Pagination: nav
|
|
442
|
+
Empty: empty_state
|
|
443
|
+
Loading: skeleton
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
# Usage composes the compound parts
|
|
447
|
+
default_composition {
|
|
448
|
+
Root {
|
|
449
|
+
Header {
|
|
450
|
+
HeaderRow {
|
|
451
|
+
for column in columns: HeaderCell(column)
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
Body {
|
|
455
|
+
for row in data: Row {
|
|
456
|
+
for column in columns: Cell(row[column.key])
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
Pagination(total: data.length)
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### 2.8 Form Block
|
|
468
|
+
|
|
469
|
+
Forms with validation and submission.
|
|
470
|
+
|
|
471
|
+
```kappa
|
|
472
|
+
form CreateProject {
|
|
473
|
+
# === FIELDS ===
|
|
474
|
+
fields {
|
|
475
|
+
name: text {
|
|
476
|
+
label: "Project Name"
|
|
477
|
+
placeholder: "My Awesome Project"
|
|
478
|
+
validate: string(2..100)
|
|
479
|
+
required: true
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
description: textarea {
|
|
483
|
+
label: "Description"
|
|
484
|
+
placeholder: "What's this project about?"
|
|
485
|
+
validate: string(..1000)
|
|
486
|
+
rows: 4
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
visibility: select {
|
|
490
|
+
label: "Visibility"
|
|
491
|
+
options: [
|
|
492
|
+
{ value: "private", label: "Private", icon: lock },
|
|
493
|
+
{ value: "team", label: "Team", icon: users },
|
|
494
|
+
{ value: "public", label: "Public", icon: globe }
|
|
495
|
+
]
|
|
496
|
+
default: "private"
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
template: select {
|
|
500
|
+
label: "Template"
|
|
501
|
+
options: from(api.list_templates)
|
|
502
|
+
searchable: true
|
|
503
|
+
optional: true
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
# === SUBMIT ===
|
|
508
|
+
submit {
|
|
509
|
+
action: api.create_project
|
|
510
|
+
button: "Create Project"
|
|
511
|
+
loading: "Creating..."
|
|
512
|
+
on_success: navigate("/projects/{result.id}")
|
|
513
|
+
on_error: toast.error(error.message)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
# === LAYOUT ===
|
|
517
|
+
layout: stack(gap: 4) {
|
|
518
|
+
row { name }
|
|
519
|
+
row { description }
|
|
520
|
+
row(columns: 2) { visibility, template }
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
### 2.9 Design Block
|
|
528
|
+
|
|
529
|
+
Explicit design tokens. No mood interpretation.
|
|
530
|
+
|
|
531
|
+
```kappa
|
|
532
|
+
design {
|
|
533
|
+
# === COLORS ===
|
|
534
|
+
colors {
|
|
535
|
+
primary: #3B82F6
|
|
536
|
+
primary_hover: darken(primary, 10%)
|
|
537
|
+
primary_foreground: #FFFFFF
|
|
538
|
+
|
|
539
|
+
secondary: #6B7280
|
|
540
|
+
accent: #8B5CF6
|
|
541
|
+
|
|
542
|
+
background: #FFFFFF
|
|
543
|
+
foreground: #111827
|
|
544
|
+
muted: #F3F4F6
|
|
545
|
+
muted_foreground: #6B7280
|
|
546
|
+
|
|
547
|
+
success: #10B981
|
|
548
|
+
warning: #F59E0B
|
|
549
|
+
error: #EF4444
|
|
550
|
+
info: #3B82F6
|
|
551
|
+
|
|
552
|
+
# Dark mode overrides
|
|
553
|
+
dark {
|
|
554
|
+
background: #111827
|
|
555
|
+
foreground: #F9FAFB
|
|
556
|
+
muted: #1F2937
|
|
557
|
+
muted_foreground: #9CA3AF
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
# === TYPOGRAPHY ===
|
|
562
|
+
typography {
|
|
563
|
+
font_family: "Inter, system-ui, sans-serif"
|
|
564
|
+
font_mono: "JetBrains Mono, monospace"
|
|
565
|
+
|
|
566
|
+
scale {
|
|
567
|
+
xs: 0.75rem
|
|
568
|
+
sm: 0.875rem
|
|
569
|
+
base: 1rem
|
|
570
|
+
lg: 1.125rem
|
|
571
|
+
xl: 1.25rem
|
|
572
|
+
2xl: 1.5rem
|
|
573
|
+
3xl: 1.875rem
|
|
574
|
+
4xl: 2.25rem
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
weight {
|
|
578
|
+
normal: 400
|
|
579
|
+
medium: 500
|
|
580
|
+
semibold: 600
|
|
581
|
+
bold: 700
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
# === SPACING ===
|
|
586
|
+
spacing {
|
|
587
|
+
unit: 4px
|
|
588
|
+
scale: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 64]
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
# === BORDERS ===
|
|
592
|
+
borders {
|
|
593
|
+
radius {
|
|
594
|
+
none: 0
|
|
595
|
+
sm: 0.125rem
|
|
596
|
+
default: 0.25rem
|
|
597
|
+
md: 0.375rem
|
|
598
|
+
lg: 0.5rem
|
|
599
|
+
xl: 0.75rem
|
|
600
|
+
full: 9999px
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
width: 1px
|
|
604
|
+
color: muted
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
# === SHADOWS ===
|
|
608
|
+
shadows {
|
|
609
|
+
sm: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
610
|
+
default: "0 1px 3px rgba(0, 0, 0, 0.1)"
|
|
611
|
+
md: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
612
|
+
lg: "0 10px 15px rgba(0, 0, 0, 0.1)"
|
|
613
|
+
xl: "0 20px 25px rgba(0, 0, 0, 0.1)"
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
# === MOTION ===
|
|
617
|
+
motion {
|
|
618
|
+
duration {
|
|
619
|
+
fast: 150ms
|
|
620
|
+
default: 200ms
|
|
621
|
+
slow: 300ms
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
easing {
|
|
625
|
+
default: cubic-bezier(0.4, 0, 0.2, 1)
|
|
626
|
+
in: cubic-bezier(0.4, 0, 1, 1)
|
|
627
|
+
out: cubic-bezier(0, 0, 0.2, 1)
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
**Generates:**
|
|
634
|
+
- CSS custom properties
|
|
635
|
+
- Tailwind config
|
|
636
|
+
- Theme provider
|
|
637
|
+
- Dark mode toggle
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## Part III: Provenance Tracking
|
|
642
|
+
|
|
643
|
+
Every generated line includes its origin.
|
|
644
|
+
|
|
645
|
+
### 3.1 Provenance Comments
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
// Generated from: entity User > field email
|
|
649
|
+
// Spec: email: email, unique, immutable
|
|
650
|
+
export const users = pgTable('users', {
|
|
651
|
+
// ...
|
|
652
|
+
email: text('email').notNull().unique(),
|
|
653
|
+
// ...
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
// Generated from: entity User > on_create
|
|
657
|
+
// Spec: send_email(template: welcome)
|
|
658
|
+
async function onUserCreate(user: User) {
|
|
659
|
+
await emailService.send({
|
|
660
|
+
to: user.email,
|
|
661
|
+
template: 'welcome', // from: on_create > send_email > template
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Generated from: entity User > can > create Project
|
|
666
|
+
// Spec: can: create Project
|
|
667
|
+
export function canCreateProject(user: User): boolean {
|
|
668
|
+
return true; // All authenticated users can create projects
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Generated from: entity User > cannot > delete self
|
|
672
|
+
// Spec: cannot: delete self (unless: no_owned_projects)
|
|
673
|
+
export async function canDeleteSelf(user: User): Promise<boolean> {
|
|
674
|
+
const ownedProjects = await db.query.projects.findMany({
|
|
675
|
+
where: eq(projects.ownerId, user.id)
|
|
676
|
+
});
|
|
677
|
+
return ownedProjects.length === 0;
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
### 3.2 Source Maps
|
|
682
|
+
|
|
683
|
+
```json
|
|
684
|
+
{
|
|
685
|
+
"src/db/schema.ts": {
|
|
686
|
+
"lines": {
|
|
687
|
+
"15-20": { "source": "entity User", "spec_line": 12 },
|
|
688
|
+
"22": { "source": "entity User > field email", "spec_line": 14 }
|
|
689
|
+
}
|
|
690
|
+
},
|
|
691
|
+
"src/lib/permissions.ts": {
|
|
692
|
+
"lines": {
|
|
693
|
+
"8-12": { "source": "entity User > can", "spec_line": 28 }
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### 3.3 Why This Matters
|
|
700
|
+
|
|
701
|
+
When debugging, developers can:
|
|
702
|
+
1. See exactly what spec produced this code
|
|
703
|
+
2. Navigate from code → spec
|
|
704
|
+
3. Understand why a permission exists
|
|
705
|
+
4. Trace business logic to requirements
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
## Part IV: Generator Architecture
|
|
710
|
+
|
|
711
|
+
### 4.1 Pipeline
|
|
712
|
+
|
|
713
|
+
```
|
|
714
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
715
|
+
│ KAPPA SPEC │
|
|
716
|
+
│ (entities, apis, journeys, pages, components, design) │
|
|
717
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
718
|
+
│
|
|
719
|
+
▼
|
|
720
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
721
|
+
│ PARSER │
|
|
722
|
+
│ - Tokenizer │
|
|
723
|
+
│ - AST Builder │
|
|
724
|
+
│ - Semantic Validation │
|
|
725
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
726
|
+
│
|
|
727
|
+
▼
|
|
728
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
729
|
+
│ KAPPA AST │
|
|
730
|
+
│ Fully validated, typed abstract syntax tree │
|
|
731
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
732
|
+
│
|
|
733
|
+
▼
|
|
734
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
735
|
+
│ GENERATOR SELECTOR │
|
|
736
|
+
│ project.stack → selects framework generator │
|
|
737
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
738
|
+
│
|
|
739
|
+
┌──────────────────┼──────────────────┐
|
|
740
|
+
▼ ▼ ▼
|
|
741
|
+
┌────────────┐ ┌────────────┐ ┌────────────┐
|
|
742
|
+
│ TanStack │ │ Next.js │ │ Express │
|
|
743
|
+
│ Generator │ │ Generator │ │ Generator │
|
|
744
|
+
└────────────┘ └────────────┘ └────────────┘
|
|
745
|
+
│ │ │
|
|
746
|
+
└──────────────────┼──────────────────┘
|
|
747
|
+
▼
|
|
748
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
749
|
+
│ GENERATED CODE │
|
|
750
|
+
│ - Database schema │
|
|
751
|
+
│ - API routes │
|
|
752
|
+
│ - Auth middleware │
|
|
753
|
+
│ - UI components │
|
|
754
|
+
│ - Pages with loaders │
|
|
755
|
+
│ - Permissions │
|
|
756
|
+
│ - Design tokens │
|
|
757
|
+
│ - Provenance source maps │
|
|
758
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### 4.2 Generator Interface
|
|
762
|
+
|
|
763
|
+
```typescript
|
|
764
|
+
interface KappaGenerator {
|
|
765
|
+
name: string;
|
|
766
|
+
version: string;
|
|
767
|
+
|
|
768
|
+
// Generate all outputs from AST
|
|
769
|
+
generate(ast: KappaAST, options: GeneratorOptions): GeneratorOutput;
|
|
770
|
+
|
|
771
|
+
// Individual generators (for incremental updates)
|
|
772
|
+
generateSchema(entities: EntityNode[]): FileOutput[];
|
|
773
|
+
generateAPI(apis: APINode[]): FileOutput[];
|
|
774
|
+
generateAuth(auth: AuthNode): FileOutput[];
|
|
775
|
+
generatePages(pages: PageNode[]): FileOutput[];
|
|
776
|
+
generateComponents(components: ComponentNode[]): FileOutput[];
|
|
777
|
+
generateDesign(design: DesignNode): FileOutput[];
|
|
778
|
+
generateJourneys(journeys: JourneyNode[]): FileOutput[];
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
interface GeneratorOutput {
|
|
782
|
+
files: FileOutput[];
|
|
783
|
+
sourceMap: SourceMap;
|
|
784
|
+
warnings: Warning[];
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
interface FileOutput {
|
|
788
|
+
path: string;
|
|
789
|
+
content: string;
|
|
790
|
+
provenance: ProvenanceInfo[];
|
|
791
|
+
}
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### 4.3 Template System
|
|
795
|
+
|
|
796
|
+
Generators use templates with slots:
|
|
797
|
+
|
|
798
|
+
```typescript
|
|
799
|
+
// Template: api-route.ts.template
|
|
800
|
+
const template = `
|
|
801
|
+
// Generated from: {{provenance}}
|
|
802
|
+
import { createAPIFileRoute } from '@tanstack/start/api';
|
|
803
|
+
{{#if hasValidation}}
|
|
804
|
+
import { z } from 'zod';
|
|
805
|
+
{{/if}}
|
|
806
|
+
{{#if hasAuth}}
|
|
807
|
+
import { requireAuth } from '~/lib/auth';
|
|
808
|
+
{{/if}}
|
|
809
|
+
import { db } from '~/db';
|
|
810
|
+
|
|
811
|
+
{{#each schemas}}
|
|
812
|
+
const {{name}}Schema = {{zodSchema}};
|
|
813
|
+
{{/each}}
|
|
814
|
+
|
|
815
|
+
export const APIRoute = createAPIFileRoute('{{routePath}}')({
|
|
816
|
+
{{#each methods}}
|
|
817
|
+
{{method}}: async ({ request }) => {
|
|
818
|
+
{{#if requiresAuth}}
|
|
819
|
+
const user = await requireAuth(request);
|
|
820
|
+
{{/if}}
|
|
821
|
+
|
|
822
|
+
{{#if hasBody}}
|
|
823
|
+
const body = {{schema}}Schema.parse(await request.json());
|
|
824
|
+
{{/if}}
|
|
825
|
+
|
|
826
|
+
{{> methodBody}}
|
|
827
|
+
|
|
828
|
+
return Response.json({ data: result });
|
|
829
|
+
},
|
|
830
|
+
{{/each}}
|
|
831
|
+
});
|
|
832
|
+
`;
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
---
|
|
836
|
+
|
|
837
|
+
## Part V: Complete Example
|
|
838
|
+
|
|
839
|
+
### 5.1 TaskFlow Spec
|
|
840
|
+
|
|
841
|
+
```kappa
|
|
842
|
+
project TaskFlow {
|
|
843
|
+
version: "1.0.0"
|
|
844
|
+
stack: tanstack-start
|
|
845
|
+
database: turso
|
|
846
|
+
auth: jwt
|
|
847
|
+
ui: shadcn
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
# === AUTH ===
|
|
851
|
+
|
|
852
|
+
auth jwt {
|
|
853
|
+
secret: env(JWT_SECRET)
|
|
854
|
+
expires: 7d
|
|
855
|
+
refresh: sliding
|
|
856
|
+
hash: argon2id(memory: 64mb, iterations: 3)
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
# === ENTITIES ===
|
|
860
|
+
|
|
861
|
+
entity User {
|
|
862
|
+
id: uuid, primary, auto
|
|
863
|
+
email: email, unique, immutable
|
|
864
|
+
name: string(2..100)
|
|
865
|
+
password: string, hashed, internal
|
|
866
|
+
avatar: url?
|
|
867
|
+
role: admin | member = member
|
|
868
|
+
created_at: timestamp, auto
|
|
869
|
+
|
|
870
|
+
has_many: Project (as owner)
|
|
871
|
+
has_many: Membership
|
|
872
|
+
has_many: Team (through: Membership)
|
|
873
|
+
|
|
874
|
+
can: [
|
|
875
|
+
create Project,
|
|
876
|
+
read Project (where: member_of),
|
|
877
|
+
update Project (where: owner_of),
|
|
878
|
+
delete Project (where: owner_of)
|
|
879
|
+
]
|
|
880
|
+
|
|
881
|
+
on_create: send_email(template: welcome)
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
entity Project {
|
|
885
|
+
id: uuid, primary, auto
|
|
886
|
+
name: string(2..100)
|
|
887
|
+
description: string(..1000)?
|
|
888
|
+
status: active | archived = active
|
|
889
|
+
owner: -> User
|
|
890
|
+
created_at: timestamp, auto
|
|
891
|
+
updated_at: timestamp, auto, on_update
|
|
892
|
+
|
|
893
|
+
has_many: Task
|
|
894
|
+
has_many: Membership
|
|
895
|
+
has_many: User (through: Membership, as: members)
|
|
896
|
+
|
|
897
|
+
index: [owner, status]
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
entity Task {
|
|
901
|
+
id: uuid, primary, auto
|
|
902
|
+
title: string(2..200)
|
|
903
|
+
description: markdown?
|
|
904
|
+
status: todo | in_progress | done = todo
|
|
905
|
+
priority: low | medium | high = medium
|
|
906
|
+
due_date: date?
|
|
907
|
+
project: -> Project
|
|
908
|
+
assignee: -> User?
|
|
909
|
+
created_at: timestamp, auto
|
|
910
|
+
|
|
911
|
+
index: [project, status]
|
|
912
|
+
index: [assignee, status]
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
entity Membership {
|
|
916
|
+
user: -> User, primary
|
|
917
|
+
project: -> Project, primary
|
|
918
|
+
role: owner | editor | viewer
|
|
919
|
+
joined_at: timestamp, auto
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
# === API ===
|
|
923
|
+
|
|
924
|
+
api Auth {
|
|
925
|
+
signup: (email: email, password: string(8..), name: string(2..100))
|
|
926
|
+
-[DB, Email]-> User
|
|
927
|
+
throws: EmailTaken
|
|
928
|
+
rate_limit: 5/minute
|
|
929
|
+
|
|
930
|
+
login: (email: email, password: string)
|
|
931
|
+
-[DB, Auth]-> { user: User, token: string }
|
|
932
|
+
throws: InvalidCredentials
|
|
933
|
+
rate_limit: 10/minute
|
|
934
|
+
|
|
935
|
+
logout: () -[Auth]-> void
|
|
936
|
+
me: () -[Auth]-> User
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
api Projects {
|
|
940
|
+
crud Project {
|
|
941
|
+
create: -[Auth, DB]-> Project
|
|
942
|
+
read: -[Auth, DB]-> Project (check: member_of)
|
|
943
|
+
update: -[Auth, DB]-> Project (check: owner_of)
|
|
944
|
+
delete: -[Auth, DB]-> void (check: owner_of)
|
|
945
|
+
list: -[Auth, DB]-> [Project] (filter: member_of)
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
api Tasks {
|
|
950
|
+
crud Task {
|
|
951
|
+
create: -[Auth, DB]-> Task (scope: project)
|
|
952
|
+
read: -[Auth, DB]-> Task
|
|
953
|
+
update: -[Auth, DB]-> Task
|
|
954
|
+
delete: -[Auth, DB]-> void
|
|
955
|
+
list: -[Auth, DB]-> [Task] (scope: project)
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
assign: (task_id: uuid, user_id: uuid?)
|
|
959
|
+
-[Auth, DB]-> Task
|
|
960
|
+
|
|
961
|
+
move: (task_id: uuid, status: string)
|
|
962
|
+
-[Auth, DB]-> Task
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
# === JOURNEY ===
|
|
966
|
+
|
|
967
|
+
journey Onboarding {
|
|
968
|
+
actor: new_user
|
|
969
|
+
|
|
970
|
+
steps {
|
|
971
|
+
signup { page: SignupForm, action: Auth.signup, next: create_project }
|
|
972
|
+
create_project { page: CreateProjectForm, action: Projects.create, next: dashboard }
|
|
973
|
+
dashboard { page: Dashboard, complete: true }
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
# === PAGES ===
|
|
978
|
+
|
|
979
|
+
page Login {
|
|
980
|
+
route: "/login"
|
|
981
|
+
guard: guest_only
|
|
982
|
+
component: LoginForm
|
|
983
|
+
title: "Login | TaskFlow"
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
page Dashboard {
|
|
987
|
+
route: "/dashboard"
|
|
988
|
+
guard: authenticated
|
|
989
|
+
|
|
990
|
+
load {
|
|
991
|
+
projects: Projects.list()
|
|
992
|
+
user: Auth.me()
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
layout: AppShell {
|
|
996
|
+
content: ProjectGrid(projects)
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
title: "Dashboard | TaskFlow"
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
page ProjectDetail {
|
|
1003
|
+
route: "/projects/:id"
|
|
1004
|
+
guard: authenticated
|
|
1005
|
+
|
|
1006
|
+
load {
|
|
1007
|
+
project: Projects.read(params.id)
|
|
1008
|
+
tasks: Tasks.list(project_id: params.id)
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
layout: AppShell {
|
|
1012
|
+
content: TaskBoard(project, tasks)
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
title: "{project.name} | TaskFlow"
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
# === DESIGN ===
|
|
1019
|
+
|
|
1020
|
+
design {
|
|
1021
|
+
colors {
|
|
1022
|
+
primary: #3B82F6
|
|
1023
|
+
background: #FFFFFF
|
|
1024
|
+
foreground: #111827
|
|
1025
|
+
|
|
1026
|
+
dark {
|
|
1027
|
+
background: #111827
|
|
1028
|
+
foreground: #F9FAFB
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
typography {
|
|
1033
|
+
font_family: "Inter, system-ui, sans-serif"
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
borders {
|
|
1037
|
+
radius { default: 0.5rem }
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
### 5.2 Generated Output
|
|
1043
|
+
|
|
1044
|
+
**Total Kappa spec:** ~200 lines (~800 tokens)
|
|
1045
|
+
|
|
1046
|
+
**Generated files:**
|
|
1047
|
+
|
|
1048
|
+
| File | Lines | Purpose |
|
|
1049
|
+
|------|-------|---------|
|
|
1050
|
+
| `db/schema.ts` | 85 | Drizzle schema |
|
|
1051
|
+
| `db/migrations/001_init.sql` | 60 | SQL migration |
|
|
1052
|
+
| `lib/auth.ts` | 95 | JWT + Argon2 |
|
|
1053
|
+
| `middleware/auth.ts` | 45 | Auth guards |
|
|
1054
|
+
| `lib/permissions.ts` | 80 | Capability checks |
|
|
1055
|
+
| `api/auth.ts` | 120 | Auth endpoints |
|
|
1056
|
+
| `api/projects.ts` | 150 | Project CRUD |
|
|
1057
|
+
| `api/tasks.ts` | 180 | Task CRUD + actions |
|
|
1058
|
+
| `routes/login.tsx` | 90 | Login page |
|
|
1059
|
+
| `routes/dashboard.tsx` | 120 | Dashboard page |
|
|
1060
|
+
| `routes/projects.$id.tsx` | 140 | Project detail |
|
|
1061
|
+
| `components/LoginForm.tsx` | 85 | Login form |
|
|
1062
|
+
| `components/ProjectGrid.tsx` | 75 | Project grid |
|
|
1063
|
+
| `components/TaskBoard.tsx` | 150 | Kanban board |
|
|
1064
|
+
| `lib/journey.ts` | 60 | Onboarding state |
|
|
1065
|
+
| `styles/tokens.css` | 80 | CSS custom props |
|
|
1066
|
+
| `tailwind.config.ts` | 45 | Tailwind config |
|
|
1067
|
+
|
|
1068
|
+
**Total generated:** ~1,660 lines (~6,500 tokens)
|
|
1069
|
+
|
|
1070
|
+
**Expansion ratio:** 8x
|
|
1071
|
+
|
|
1072
|
+
---
|
|
1073
|
+
|
|
1074
|
+
## Part VI: Why This Works
|
|
1075
|
+
|
|
1076
|
+
### 6.1 Novel Enough
|
|
1077
|
+
|
|
1078
|
+
| Feature | Status Quo | Kappa v2.5 |
|
|
1079
|
+
|---------|-----------|------------|
|
|
1080
|
+
| Permissions | Scattered guards/checks | `can:` / `cannot:` on entities |
|
|
1081
|
+
| User flows | Implicit in routes | Explicit `journey` blocks |
|
|
1082
|
+
| Field validation | Separate schema + validator | Inline `string(2..100)` |
|
|
1083
|
+
| Lifecycle | Event listeners somewhere | `on_create:` on entities |
|
|
1084
|
+
| Effects | Hidden in implementations | `-[DB, Auth]->` declared |
|
|
1085
|
+
| Provenance | None | Every line traces to spec |
|
|
1086
|
+
|
|
1087
|
+
### 6.2 Practical Enough
|
|
1088
|
+
|
|
1089
|
+
| Aspect | How We Stay Practical |
|
|
1090
|
+
|--------|---------------------|
|
|
1091
|
+
| Parsing | Standard recursive descent, no AI |
|
|
1092
|
+
| Validation | Type checking at parse time |
|
|
1093
|
+
| Generation | Template-based, deterministic |
|
|
1094
|
+
| Output | Standard framework code |
|
|
1095
|
+
| Tooling | LSP, syntax highlighting achievable |
|
|
1096
|
+
| Debugging | Source maps, provenance comments |
|
|
1097
|
+
|
|
1098
|
+
### 6.3 The Sweet Spot
|
|
1099
|
+
|
|
1100
|
+
```
|
|
1101
|
+
Expressiveness ◄──────────────────────────────► Practicality
|
|
1102
|
+
|
|
1103
|
+
v1: Too simple ─────┐
|
|
1104
|
+
│
|
|
1105
|
+
v3: Too ambitious ──┼────────────────────────── Research territory
|
|
1106
|
+
│
|
|
1107
|
+
v2.5: ──────────────┴─── HERE ───────────────── Buildable, novel
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
---
|
|
1111
|
+
|
|
1112
|
+
## Part VII: Implementation Roadmap
|
|
1113
|
+
|
|
1114
|
+
### Phase 1: Core Language (4 weeks)
|
|
1115
|
+
|
|
1116
|
+
- [ ] Lexer and parser
|
|
1117
|
+
- [ ] AST definition
|
|
1118
|
+
- [ ] Semantic validation
|
|
1119
|
+
- [ ] Error reporting with locations
|
|
1120
|
+
|
|
1121
|
+
**Deliverable:** Parse Kappa specs, reject invalid ones.
|
|
1122
|
+
|
|
1123
|
+
### Phase 2: Entity Generator (3 weeks)
|
|
1124
|
+
|
|
1125
|
+
- [ ] Drizzle schema generation
|
|
1126
|
+
- [ ] Zod validation schemas
|
|
1127
|
+
- [ ] TypeScript types
|
|
1128
|
+
- [ ] Basic provenance comments
|
|
1129
|
+
|
|
1130
|
+
**Deliverable:** `entity` blocks → working database layer.
|
|
1131
|
+
|
|
1132
|
+
### Phase 3: API Generator (3 weeks)
|
|
1133
|
+
|
|
1134
|
+
- [ ] TanStack Start API routes
|
|
1135
|
+
- [ ] CRUD operations from `crud` shorthand
|
|
1136
|
+
- [ ] Effect → middleware mapping
|
|
1137
|
+
- [ ] Permission checks from capabilities
|
|
1138
|
+
|
|
1139
|
+
**Deliverable:** `api` blocks → working API endpoints.
|
|
1140
|
+
|
|
1141
|
+
### Phase 4: Auth Generator (2 weeks)
|
|
1142
|
+
|
|
1143
|
+
- [ ] JWT implementation from `auth jwt`
|
|
1144
|
+
- [ ] Password hashing from `hash:` config
|
|
1145
|
+
- [ ] Auth middleware
|
|
1146
|
+
- [ ] Session management
|
|
1147
|
+
|
|
1148
|
+
**Deliverable:** `auth` block → complete auth system.
|
|
1149
|
+
|
|
1150
|
+
### Phase 5: Page Generator (3 weeks)
|
|
1151
|
+
|
|
1152
|
+
- [ ] Route generation with guards
|
|
1153
|
+
- [ ] Loader generation from `load` block
|
|
1154
|
+
- [ ] Layout composition
|
|
1155
|
+
- [ ] Component wiring
|
|
1156
|
+
|
|
1157
|
+
**Deliverable:** `page` blocks → working pages with data.
|
|
1158
|
+
|
|
1159
|
+
### Phase 6: Journey Generator (2 weeks)
|
|
1160
|
+
|
|
1161
|
+
- [ ] State machine from journey steps
|
|
1162
|
+
- [ ] Step guards
|
|
1163
|
+
- [ ] Progress tracking
|
|
1164
|
+
- [ ] Recovery handlers
|
|
1165
|
+
|
|
1166
|
+
**Deliverable:** `journey` blocks → guided user flows.
|
|
1167
|
+
|
|
1168
|
+
### Phase 7: Design Generator (2 weeks)
|
|
1169
|
+
|
|
1170
|
+
- [ ] CSS custom properties
|
|
1171
|
+
- [ ] Tailwind config
|
|
1172
|
+
- [ ] Theme provider
|
|
1173
|
+
- [ ] Dark mode
|
|
1174
|
+
|
|
1175
|
+
**Deliverable:** `design` block → consistent styling.
|
|
1176
|
+
|
|
1177
|
+
### Phase 8: Tooling (3 weeks)
|
|
1178
|
+
|
|
1179
|
+
- [ ] VSCode extension (syntax highlighting)
|
|
1180
|
+
- [ ] LSP for autocomplete/errors
|
|
1181
|
+
- [ ] Source map viewer
|
|
1182
|
+
- [ ] CLI tool
|
|
1183
|
+
|
|
1184
|
+
**Deliverable:** First-class editor experience.
|
|
1185
|
+
|
|
1186
|
+
**Total: ~22 weeks** to full v2.5 implementation.
|
|
1187
|
+
|
|
1188
|
+
---
|
|
1189
|
+
|
|
1190
|
+
## Part VIII: Success Metrics
|
|
1191
|
+
|
|
1192
|
+
### For AI Code Generation
|
|
1193
|
+
|
|
1194
|
+
| Metric | Target |
|
|
1195
|
+
|--------|--------|
|
|
1196
|
+
| Token reduction | 80%+ (spec vs generated) |
|
|
1197
|
+
| Correctness | 95%+ (generates valid, runnable code) |
|
|
1198
|
+
| Completeness | One spec → full feature |
|
|
1199
|
+
|
|
1200
|
+
### For Developer Experience
|
|
1201
|
+
|
|
1202
|
+
| Metric | Target |
|
|
1203
|
+
|--------|--------|
|
|
1204
|
+
| Learning curve | < 1 hour to productivity |
|
|
1205
|
+
| Spec readability | Non-technical stakeholders can review |
|
|
1206
|
+
| Debug time | 50% reduction via provenance |
|
|
1207
|
+
|
|
1208
|
+
### For CodeDNA
|
|
1209
|
+
|
|
1210
|
+
| Metric | Target |
|
|
1211
|
+
|--------|--------|
|
|
1212
|
+
| Cost per feature | 90%+ reduction vs manual AI prompting |
|
|
1213
|
+
| Consistency | Same spec → same output |
|
|
1214
|
+
| Extensibility | New generators < 1 week to add |
|
|
1215
|
+
|
|
1216
|
+
---
|
|
1217
|
+
|
|
1218
|
+
*Kappa v2.5: Write what you mean. Generate what you need.*
|