devlyn-cli 0.0.1
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 +43 -0
- package/bin/devlyn.js +362 -0
- package/config/commands/devlyn.design-system.md +502 -0
- package/config/commands/devlyn.discover-product.md +116 -0
- package/config/commands/devlyn.feature-spec.md +630 -0
- package/config/commands/devlyn.handoff.md +13 -0
- package/config/commands/devlyn.product-spec.md +603 -0
- package/config/commands/devlyn.recommend-features.md +286 -0
- package/config/commands/devlyn.resolve.md +108 -0
- package/config/commands/devlyn.review.md +99 -0
- package/config/commands/devlyn.ui.md +342 -0
- package/config/commit-conventions.md +28 -0
- package/config/skills/feature-gap-analysis/SKILL.md +111 -0
- package/config/skills/investigate/SKILL.md +71 -0
- package/config/skills/prompt-engineering/SKILL.md +243 -0
- package/config/templates/prompt-templates.md +71 -0
- package/config/templates/template-feature.spec.md +255 -0
- package/config/templates/template-product-spec.md +680 -0
- package/package.json +25 -0
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
# Product Spec
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Source of truth for WHAT to build and WHY.
|
|
4
|
+
> **Usage**: Input for AI agents generating Feature Specs → Plans → Tasks → Code.
|
|
5
|
+
> **Principle**: Define the WHAT and WHY. Downstream agents derive the HOW.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 1. META
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
meta:
|
|
13
|
+
name: "{Product Name}"
|
|
14
|
+
version: "{X.Y}"
|
|
15
|
+
updated: "{YYYY-MM-DD}"
|
|
16
|
+
status: "{draft | review | approved | implementing}"
|
|
17
|
+
owner: "{decision maker}"
|
|
18
|
+
|
|
19
|
+
platform:
|
|
20
|
+
type: "{web | mobile | desktop | cli | backend}"
|
|
21
|
+
framework: "{framework + version}"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# 2. IDENTITY
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
identity:
|
|
30
|
+
summary: "{X is a Y that does Z for W}"
|
|
31
|
+
|
|
32
|
+
insight: "{Core belief that makes this viable — what do we believe that others don't?}"
|
|
33
|
+
|
|
34
|
+
principles:
|
|
35
|
+
# Guide ALL downstream decisions. Feature Specs apply these.
|
|
36
|
+
- principle: "{name}"
|
|
37
|
+
meaning: "{what this means in practice}"
|
|
38
|
+
tradeoff: "{what we sacrifice}"
|
|
39
|
+
|
|
40
|
+
# Common principles to consider:
|
|
41
|
+
# - Optimistic UI (show result before server confirms)
|
|
42
|
+
# - Keyboard-first (every action without mouse)
|
|
43
|
+
# - Progressive disclosure (simple first, reveal complexity)
|
|
44
|
+
# - Undo over confirm (reverse actions vs block with dialogs)
|
|
45
|
+
# - Offline-capable (works without network)
|
|
46
|
+
# - Responsive feedback (user knows state within 100ms)
|
|
47
|
+
|
|
48
|
+
anti_goals:
|
|
49
|
+
- "{what we will NOT build, even if users ask}"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# 3. USERS
|
|
55
|
+
|
|
56
|
+
```yaml
|
|
57
|
+
users:
|
|
58
|
+
primary:
|
|
59
|
+
who: "{description}"
|
|
60
|
+
goals: ["{what they want to accomplish}"]
|
|
61
|
+
pains: ["{current problems}"]
|
|
62
|
+
context: "{when/where they use this}"
|
|
63
|
+
capabilities:
|
|
64
|
+
technical: "{novice | intermediate | expert}"
|
|
65
|
+
domain: "{none | familiar | expert}"
|
|
66
|
+
|
|
67
|
+
not_for:
|
|
68
|
+
- "{who we don't serve, and why}"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
# 4. INVARIANTS
|
|
74
|
+
|
|
75
|
+
> Rules that must NEVER break. Violations are bugs.
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
invariants:
|
|
79
|
+
- rule: "{invariant}"
|
|
80
|
+
why: "{rationale}"
|
|
81
|
+
|
|
82
|
+
# Common invariants:
|
|
83
|
+
# - "Users cannot access other users' data"
|
|
84
|
+
# - "All mutations require authentication"
|
|
85
|
+
# - "User data is never permanently deleted without explicit request"
|
|
86
|
+
# - "Secrets never appear in logs or API responses"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
# 5. BEHAVIORS
|
|
90
|
+
|
|
91
|
+
> All actions in the system. Feature Specs derive implementation.
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
behaviors:
|
|
95
|
+
"{behavior_name}":
|
|
96
|
+
purpose: "{what this accomplishes}"
|
|
97
|
+
actor: "{user | system | schedule}"
|
|
98
|
+
trigger: "{what initiates}"
|
|
99
|
+
|
|
100
|
+
input:
|
|
101
|
+
- name: "{name}"
|
|
102
|
+
type: "{type}"
|
|
103
|
+
required: "{true | false}"
|
|
104
|
+
validation: "{rules}"
|
|
105
|
+
|
|
106
|
+
outcome: "{what changes when successful}"
|
|
107
|
+
|
|
108
|
+
rules: # business logic
|
|
109
|
+
- "{rule}"
|
|
110
|
+
|
|
111
|
+
errors:
|
|
112
|
+
- when: "{condition}"
|
|
113
|
+
error: "{code}"
|
|
114
|
+
message: "{user-facing}"
|
|
115
|
+
recovery: "{what user can do}"
|
|
116
|
+
|
|
117
|
+
emits: ["{triggered behaviors or events}"] # optional
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
<details>
|
|
121
|
+
<summary>Behavior Examples</summary>
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
paste_content:
|
|
125
|
+
purpose: "Save content from clipboard to inbox"
|
|
126
|
+
actor: user
|
|
127
|
+
trigger: "Paste in drop zone or keyboard shortcut"
|
|
128
|
+
|
|
129
|
+
input:
|
|
130
|
+
- name: content
|
|
131
|
+
type: string | file
|
|
132
|
+
required: true
|
|
133
|
+
validation: "Max 10MB"
|
|
134
|
+
- name: space_id
|
|
135
|
+
type: uuid
|
|
136
|
+
required: false
|
|
137
|
+
validation: "User's space"
|
|
138
|
+
|
|
139
|
+
outcome: "Source created with status=pending"
|
|
140
|
+
|
|
141
|
+
rules:
|
|
142
|
+
- "Detect content type (URL, text, image, file)"
|
|
143
|
+
- "If URL: check for duplicate"
|
|
144
|
+
- "If duplicate: surface existing instead"
|
|
145
|
+
|
|
146
|
+
errors:
|
|
147
|
+
- when: "Clipboard empty"
|
|
148
|
+
error: "EMPTY_CLIPBOARD"
|
|
149
|
+
message: "Nothing to paste"
|
|
150
|
+
recovery: "Copy content first"
|
|
151
|
+
- when: "Exceeds limit"
|
|
152
|
+
error: "TOO_LARGE"
|
|
153
|
+
message: "Content exceeds 10MB"
|
|
154
|
+
recovery: "Try smaller content"
|
|
155
|
+
- when: "Duplicate URL"
|
|
156
|
+
error: "DUPLICATE"
|
|
157
|
+
message: "Already saved"
|
|
158
|
+
recovery: "View existing"
|
|
159
|
+
|
|
160
|
+
emits: [process_source]
|
|
161
|
+
|
|
162
|
+
process_source:
|
|
163
|
+
purpose: "Extract content and generate embedding"
|
|
164
|
+
actor: system
|
|
165
|
+
trigger: "Source created with status=pending"
|
|
166
|
+
|
|
167
|
+
input:
|
|
168
|
+
- name: source_id
|
|
169
|
+
type: uuid
|
|
170
|
+
required: true
|
|
171
|
+
|
|
172
|
+
outcome: "Source has content, embedding, status=complete"
|
|
173
|
+
|
|
174
|
+
rules:
|
|
175
|
+
- "URL: fetch and extract main content"
|
|
176
|
+
- "YouTube: extract transcript"
|
|
177
|
+
- "Image: OCR"
|
|
178
|
+
- "Timeout: 60s"
|
|
179
|
+
|
|
180
|
+
errors:
|
|
181
|
+
- when: "URL unreachable"
|
|
182
|
+
error: "UNREACHABLE"
|
|
183
|
+
message: "Couldn't reach URL"
|
|
184
|
+
recovery: "Check link and retry"
|
|
185
|
+
- when: "Extraction failed"
|
|
186
|
+
error: "EXTRACTION_FAILED"
|
|
187
|
+
message: "Couldn't extract content"
|
|
188
|
+
recovery: "Try different content"
|
|
189
|
+
|
|
190
|
+
search:
|
|
191
|
+
purpose: "Find sources by semantic similarity"
|
|
192
|
+
actor: user
|
|
193
|
+
trigger: "User enters query"
|
|
194
|
+
|
|
195
|
+
input:
|
|
196
|
+
- name: query
|
|
197
|
+
type: string
|
|
198
|
+
required: true
|
|
199
|
+
validation: "1-500 chars"
|
|
200
|
+
- name: space_id
|
|
201
|
+
type: uuid
|
|
202
|
+
required: false
|
|
203
|
+
|
|
204
|
+
outcome: "Ranked list of matching sources (max 20)"
|
|
205
|
+
|
|
206
|
+
rules:
|
|
207
|
+
- "Generate query embedding"
|
|
208
|
+
- "Vector similarity against user's sources"
|
|
209
|
+
- "Only status=complete sources"
|
|
210
|
+
|
|
211
|
+
errors:
|
|
212
|
+
- when: "Query too short"
|
|
213
|
+
error: "QUERY_SHORT"
|
|
214
|
+
message: "Enter a few more words"
|
|
215
|
+
recovery: "Add detail"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
</details>
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
# 6. PERMISSIONS
|
|
223
|
+
|
|
224
|
+
> Who can do what. Business rules, not implementation.
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
permissions:
|
|
228
|
+
"{Entity}":
|
|
229
|
+
create: "{who}"
|
|
230
|
+
read: "{who}"
|
|
231
|
+
update: "{who}"
|
|
232
|
+
delete: "{who}"
|
|
233
|
+
|
|
234
|
+
# "who" examples:
|
|
235
|
+
# - "authenticated" (any logged-in user)
|
|
236
|
+
# - "owner" (created/owns the resource)
|
|
237
|
+
# - "owner + invited" (shared access)
|
|
238
|
+
# - "admin" (admin role only)
|
|
239
|
+
# - "public" (no auth required)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Example:
|
|
243
|
+
|
|
244
|
+
```yaml
|
|
245
|
+
permissions:
|
|
246
|
+
Source:
|
|
247
|
+
create: authenticated
|
|
248
|
+
read: owner
|
|
249
|
+
update: owner
|
|
250
|
+
delete: owner
|
|
251
|
+
|
|
252
|
+
Space:
|
|
253
|
+
create: authenticated
|
|
254
|
+
read: owner
|
|
255
|
+
update: owner
|
|
256
|
+
delete: owner
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
# 7. LIMITS
|
|
262
|
+
|
|
263
|
+
> Business constraints and quotas.
|
|
264
|
+
|
|
265
|
+
```yaml
|
|
266
|
+
limits:
|
|
267
|
+
tiers:
|
|
268
|
+
"{tier_name}":
|
|
269
|
+
"{resource}": "{limit}"
|
|
270
|
+
price: "{price}" # if paid
|
|
271
|
+
|
|
272
|
+
on_limit: "{block | upgrade_prompt | soft_warning}"
|
|
273
|
+
|
|
274
|
+
# Per-action limits (if different from tier)
|
|
275
|
+
actions:
|
|
276
|
+
"{behavior}": "{limit per time}"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Example:
|
|
280
|
+
|
|
281
|
+
```yaml
|
|
282
|
+
limits:
|
|
283
|
+
tiers:
|
|
284
|
+
free:
|
|
285
|
+
sources: 100
|
|
286
|
+
storage: "100MB"
|
|
287
|
+
ai_queries: "50/month"
|
|
288
|
+
|
|
289
|
+
pro:
|
|
290
|
+
sources: unlimited
|
|
291
|
+
storage: "10GB"
|
|
292
|
+
ai_queries: unlimited
|
|
293
|
+
price: "$10/month"
|
|
294
|
+
|
|
295
|
+
on_limit: upgrade_prompt
|
|
296
|
+
|
|
297
|
+
actions:
|
|
298
|
+
process_source: "10/minute" # rate limit
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
# 8. INTEGRATIONS
|
|
304
|
+
|
|
305
|
+
> External services we depend on.
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
integrations:
|
|
309
|
+
"{service}":
|
|
310
|
+
purpose: "{why we use this}"
|
|
311
|
+
used_by: ["{behavior}"]
|
|
312
|
+
fallback: "{what happens if unavailable}" # optional
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Example:
|
|
316
|
+
|
|
317
|
+
```yaml
|
|
318
|
+
integrations:
|
|
319
|
+
openai:
|
|
320
|
+
purpose: "Embeddings (text-embedding-3-small) and chat (gpt-4)"
|
|
321
|
+
used_by: [process_source, chat_with_sources]
|
|
322
|
+
fallback: "Queue for retry, show 'AI temporarily unavailable'"
|
|
323
|
+
|
|
324
|
+
youtube_transcript:
|
|
325
|
+
purpose: "Extract video transcripts"
|
|
326
|
+
used_by: [process_source]
|
|
327
|
+
fallback: "Index title/description only"
|
|
328
|
+
|
|
329
|
+
readability:
|
|
330
|
+
purpose: "Extract article content from URLs"
|
|
331
|
+
used_by: [process_source]
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
# 9. VIEWS
|
|
337
|
+
|
|
338
|
+
> UI surfaces and their states.
|
|
339
|
+
|
|
340
|
+
```yaml
|
|
341
|
+
views:
|
|
342
|
+
"{view_name}":
|
|
343
|
+
purpose: "{what user does here}"
|
|
344
|
+
route: "{path}"
|
|
345
|
+
|
|
346
|
+
states:
|
|
347
|
+
"{state}":
|
|
348
|
+
when: "{condition}"
|
|
349
|
+
shows: ["{elements}"]
|
|
350
|
+
|
|
351
|
+
data: ["{Entity}"]
|
|
352
|
+
actions: ["{behavior}"]
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Example:
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
views:
|
|
359
|
+
home:
|
|
360
|
+
purpose: "Capture content and browse sources"
|
|
361
|
+
route: "/"
|
|
362
|
+
|
|
363
|
+
states:
|
|
364
|
+
empty:
|
|
365
|
+
when: "No sources"
|
|
366
|
+
shows: [drop_zone, onboarding_hint]
|
|
367
|
+
has_content:
|
|
368
|
+
when: "Has sources"
|
|
369
|
+
shows: [drop_zone, source_list, chat_input]
|
|
370
|
+
viewing_source:
|
|
371
|
+
when: "Source selected"
|
|
372
|
+
shows: [source_list, source_detail_panel]
|
|
373
|
+
|
|
374
|
+
data: [Source, Space]
|
|
375
|
+
actions: [paste_content, search, view_source, delete_source]
|
|
376
|
+
|
|
377
|
+
source_detail:
|
|
378
|
+
purpose: "View and interact with single source"
|
|
379
|
+
route: "/source/:id"
|
|
380
|
+
|
|
381
|
+
states:
|
|
382
|
+
loading:
|
|
383
|
+
when: "Data loading"
|
|
384
|
+
shows: [skeleton]
|
|
385
|
+
processing:
|
|
386
|
+
when: "status=pending|processing"
|
|
387
|
+
shows: [header, processing_indicator]
|
|
388
|
+
ready:
|
|
389
|
+
when: "status=complete"
|
|
390
|
+
shows: [header, content, chat]
|
|
391
|
+
failed:
|
|
392
|
+
when: "status=failed"
|
|
393
|
+
shows: [header, error_state, retry_button]
|
|
394
|
+
|
|
395
|
+
data: [Source, ChatMessage]
|
|
396
|
+
actions: [chat_with_source, edit_source, delete_source]
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
# 10. DESIGN
|
|
402
|
+
|
|
403
|
+
> Visual and verbal direction. Feature Specs derive specifics.
|
|
404
|
+
|
|
405
|
+
```yaml
|
|
406
|
+
design:
|
|
407
|
+
foundation:
|
|
408
|
+
system: "{base system}" # e.g., "tailwind + shadcn/ui"
|
|
409
|
+
|
|
410
|
+
aesthetic:
|
|
411
|
+
personality: ["{adjective}", "{adjective}", "{adjective}"]
|
|
412
|
+
inspiration:
|
|
413
|
+
- source: "{reference}"
|
|
414
|
+
take: "{what to learn}"
|
|
415
|
+
avoid:
|
|
416
|
+
- "{anti-pattern}"
|
|
417
|
+
signature:
|
|
418
|
+
- "{distinctive element}"
|
|
419
|
+
|
|
420
|
+
patterns:
|
|
421
|
+
# UX conventions — Feature Specs apply these
|
|
422
|
+
list_order: "{newest_first | oldest_first | manual}"
|
|
423
|
+
new_items: "{prepend | append}"
|
|
424
|
+
empty_states: "{illustration | minimal | action-focused}"
|
|
425
|
+
loading: "{skeleton | spinner}"
|
|
426
|
+
optimistic: "{true | false}"
|
|
427
|
+
detail_view: "{panel | page | modal}"
|
|
428
|
+
destructive_actions: "{undo | confirm}"
|
|
429
|
+
density: "{compact | comfortable | spacious}"
|
|
430
|
+
|
|
431
|
+
voice:
|
|
432
|
+
tone: ["{adjective}", "{adjective}"]
|
|
433
|
+
formality: "{formal | conversational | casual}"
|
|
434
|
+
patterns:
|
|
435
|
+
success: "{how to say it}"
|
|
436
|
+
error: "{how to say it}"
|
|
437
|
+
empty: "{how to say it}"
|
|
438
|
+
vocabulary:
|
|
439
|
+
prefer: ["{word}"]
|
|
440
|
+
avoid: ["{word}"]
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
<details>
|
|
444
|
+
<summary>Full Design Example</summary>
|
|
445
|
+
|
|
446
|
+
```yaml
|
|
447
|
+
design:
|
|
448
|
+
foundation:
|
|
449
|
+
system: "tailwind + shadcn/ui"
|
|
450
|
+
|
|
451
|
+
aesthetic:
|
|
452
|
+
personality: ["calm", "focused", "intelligent"]
|
|
453
|
+
inspiration:
|
|
454
|
+
- source: "Linear"
|
|
455
|
+
take: "command palette, keyboard-first"
|
|
456
|
+
- source: "Notion"
|
|
457
|
+
take: "content-focused, subtle interactions"
|
|
458
|
+
- source: "Arc"
|
|
459
|
+
take: "spatial organization"
|
|
460
|
+
avoid:
|
|
461
|
+
- "generic SaaS gradients"
|
|
462
|
+
- "stock illustrations"
|
|
463
|
+
- "modal overload"
|
|
464
|
+
- "hamburger menus on desktop"
|
|
465
|
+
signature:
|
|
466
|
+
- "command palette as primary nav"
|
|
467
|
+
- "persistent AI chat sidebar"
|
|
468
|
+
- "monospace for metadata"
|
|
469
|
+
|
|
470
|
+
patterns:
|
|
471
|
+
list_order: newest_first
|
|
472
|
+
new_items: prepend
|
|
473
|
+
empty_states: action-focused
|
|
474
|
+
loading: skeleton
|
|
475
|
+
optimistic: true
|
|
476
|
+
detail_view: panel
|
|
477
|
+
destructive_actions: undo
|
|
478
|
+
density: comfortable
|
|
479
|
+
|
|
480
|
+
voice:
|
|
481
|
+
tone: ["helpful", "concise"]
|
|
482
|
+
formality: conversational
|
|
483
|
+
patterns:
|
|
484
|
+
success: "Brief, no exclamation"
|
|
485
|
+
error: "Cause + fix. No apology."
|
|
486
|
+
empty: "What's missing + one action"
|
|
487
|
+
vocabulary:
|
|
488
|
+
prefer: [save, source, space]
|
|
489
|
+
avoid: [submit, item, folder, oops, please]
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
</details>
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
# 11. POLICIES
|
|
497
|
+
|
|
498
|
+
> Cross-cutting requirements.
|
|
499
|
+
|
|
500
|
+
```yaml
|
|
501
|
+
policies:
|
|
502
|
+
auth:
|
|
503
|
+
method: "{session | jwt | oauth}"
|
|
504
|
+
providers: ["{provider}"]
|
|
505
|
+
|
|
506
|
+
privacy:
|
|
507
|
+
data_export: "{yes | no}"
|
|
508
|
+
data_deletion: "{soft | hard | on_request}"
|
|
509
|
+
|
|
510
|
+
i18n:
|
|
511
|
+
default: "{locale}"
|
|
512
|
+
supported: ["{locale}"]
|
|
513
|
+
|
|
514
|
+
accessibility:
|
|
515
|
+
standard: "{WCAG 2.1 AA | none}"
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
# 12. PHASES
|
|
521
|
+
|
|
522
|
+
> What's in each release.
|
|
523
|
+
|
|
524
|
+
```yaml
|
|
525
|
+
phases:
|
|
526
|
+
"{n}":
|
|
527
|
+
name: "{name}"
|
|
528
|
+
goal: "{what users can do after}"
|
|
529
|
+
|
|
530
|
+
includes:
|
|
531
|
+
entities: ["{name}"]
|
|
532
|
+
behaviors: ["{name}"]
|
|
533
|
+
views: ["{name}"]
|
|
534
|
+
|
|
535
|
+
excludes:
|
|
536
|
+
- what: "{deferred}"
|
|
537
|
+
why: "{reason}"
|
|
538
|
+
|
|
539
|
+
success: "{measurable outcome}"
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Example:
|
|
543
|
+
|
|
544
|
+
```yaml
|
|
545
|
+
phases:
|
|
546
|
+
1:
|
|
547
|
+
name: "Core Capture"
|
|
548
|
+
goal: "Save URLs/text, view, search"
|
|
549
|
+
|
|
550
|
+
includes:
|
|
551
|
+
entities: [User, Source]
|
|
552
|
+
behaviors: [paste_content, process_source, search, delete_source]
|
|
553
|
+
views: [home, source_detail]
|
|
554
|
+
|
|
555
|
+
excludes:
|
|
556
|
+
- what: "AI chat"
|
|
557
|
+
why: "Capture loop first"
|
|
558
|
+
- what: "Spaces"
|
|
559
|
+
why: "Inbox-only simplifies UX"
|
|
560
|
+
|
|
561
|
+
success: "Save URL → find via search in <30s"
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
# 13. DECISIONS
|
|
567
|
+
|
|
568
|
+
> What was decided and WHY.
|
|
569
|
+
|
|
570
|
+
```yaml
|
|
571
|
+
decisions:
|
|
572
|
+
- id: "D-{n}"
|
|
573
|
+
date: "{YYYY-MM-DD}"
|
|
574
|
+
context: "{what question arose}"
|
|
575
|
+
decision: "{what was decided}"
|
|
576
|
+
why: "{reasoning}"
|
|
577
|
+
implications: ["{consequence}"]
|
|
578
|
+
revisit: "{when to reconsider}"
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
Example:
|
|
582
|
+
|
|
583
|
+
```yaml
|
|
584
|
+
decisions:
|
|
585
|
+
- id: "D-001"
|
|
586
|
+
date: "2024-01-15"
|
|
587
|
+
context: "Users want shared spaces for teams"
|
|
588
|
+
decision: "Single-user only for v1"
|
|
589
|
+
why: |
|
|
590
|
+
Collaboration adds complexity (permissions, sync, conflicts).
|
|
591
|
+
Core value is personal knowledge management.
|
|
592
|
+
Teams can layer on once core is solid.
|
|
593
|
+
implications:
|
|
594
|
+
- "No sharing UI"
|
|
595
|
+
- "Simpler permissions"
|
|
596
|
+
revisit: "Post-launch based on feedback"
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
# 14. OPEN
|
|
602
|
+
|
|
603
|
+
> Undecided items.
|
|
604
|
+
|
|
605
|
+
```yaml
|
|
606
|
+
open:
|
|
607
|
+
- id: "Q-{n}"
|
|
608
|
+
question: "{decision needed}"
|
|
609
|
+
options:
|
|
610
|
+
- "{option}: {tradeoff}"
|
|
611
|
+
blocks: ["{what can't proceed}"]
|
|
612
|
+
owner: "{who decides}"
|
|
613
|
+
deadline: "{when}"
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
# 15. GLOSSARY
|
|
619
|
+
|
|
620
|
+
> Precise definitions.
|
|
621
|
+
|
|
622
|
+
```yaml
|
|
623
|
+
glossary:
|
|
624
|
+
"{Term}": "{definition in this product's context}"
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
Example:
|
|
628
|
+
|
|
629
|
+
```yaml
|
|
630
|
+
glossary:
|
|
631
|
+
Source: "Content saved by user (URL, note, file, etc.)"
|
|
632
|
+
Space: "User-created container for organizing sources"
|
|
633
|
+
Inbox: "Default location for new sources before organized"
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
# Validation Checklist
|
|
639
|
+
|
|
640
|
+
Before generating Feature Specs:
|
|
641
|
+
|
|
642
|
+
- [ ] Principles cover key UX decisions (optimistic? keyboard? undo vs confirm?)
|
|
643
|
+
- [ ] Every entity has complete fields and examples
|
|
644
|
+
- [ ] Every behavior has outcome and errors defined
|
|
645
|
+
- [ ] Permissions cover all entities
|
|
646
|
+
- [ ] Limits define tier boundaries
|
|
647
|
+
- [ ] Integrations list all external dependencies
|
|
648
|
+
- [ ] Design patterns answer: loading? new items? destructive actions?
|
|
649
|
+
- [ ] Decisions explain WHY, not just WHAT
|
|
650
|
+
- [ ] No [TBD] — move to Open Questions
|
|
651
|
+
|
|
652
|
+
---
|
|
653
|
+
|
|
654
|
+
# Size Guide
|
|
655
|
+
|
|
656
|
+
| Complexity | Lines |
|
|
657
|
+
| ---------- | --------- |
|
|
658
|
+
| MVP | 300-500 |
|
|
659
|
+
| Small | 500-700 |
|
|
660
|
+
| Medium | 700-1000 |
|
|
661
|
+
| Large | 1000-1300 |
|
|
662
|
+
|
|
663
|
+
Over 1300 lines → split into Core + Domain specs.
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
667
|
+
# Derivation Reference
|
|
668
|
+
|
|
669
|
+
| Product Spec | → Feature Spec Derives |
|
|
670
|
+
| ------------------------ | ----------------------------- |
|
|
671
|
+
| Entity fields | Schema, types, validators |
|
|
672
|
+
| Entity examples | Test fixtures |
|
|
673
|
+
| Behavior outcome + rules | Logic, sequences |
|
|
674
|
+
| Behavior errors | Error handling, UI feedback |
|
|
675
|
+
| Permissions | Auth middleware |
|
|
676
|
+
| Limits | Quota checks, upgrade prompts |
|
|
677
|
+
| Integrations | API clients, fallbacks |
|
|
678
|
+
| View states | Components, routing |
|
|
679
|
+
| Design patterns | Layout, interactions, loading |
|
|
680
|
+
| Voice | Copy, messages |
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devlyn-cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Claude Code configuration toolkit for teams",
|
|
5
|
+
"bin": {
|
|
6
|
+
"devlyn": "bin/devlyn.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"config"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claude",
|
|
14
|
+
"claude-code",
|
|
15
|
+
"ai",
|
|
16
|
+
"config",
|
|
17
|
+
"devlyn"
|
|
18
|
+
],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/fysoul17/devlyn-cli.git"
|
|
24
|
+
}
|
|
25
|
+
}
|