chati-dev 1.4.0 → 2.0.2
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 +40 -24
- package/framework/agents/build/dev.md +343 -0
- package/framework/agents/clarity/architect.md +112 -0
- package/framework/agents/clarity/brief.md +182 -0
- package/framework/agents/clarity/brownfield-wu.md +181 -0
- package/framework/agents/clarity/detail.md +110 -0
- package/framework/agents/clarity/greenfield-wu.md +153 -0
- package/framework/agents/clarity/ux.md +112 -0
- package/framework/config.yaml +3 -3
- package/framework/constitution.md +31 -1
- package/framework/context/governance.md +37 -0
- package/framework/context/protocols.md +34 -0
- package/framework/context/quality.md +27 -0
- package/framework/context/root.md +24 -0
- package/framework/data/entity-registry.yaml +1 -1
- package/framework/domains/agents/architect.yaml +51 -0
- package/framework/domains/agents/brief.yaml +47 -0
- package/framework/domains/agents/brownfield-wu.yaml +49 -0
- package/framework/domains/agents/detail.yaml +47 -0
- package/framework/domains/agents/dev.yaml +49 -0
- package/framework/domains/agents/devops.yaml +43 -0
- package/framework/domains/agents/greenfield-wu.yaml +47 -0
- package/framework/domains/agents/orchestrator.yaml +49 -0
- package/framework/domains/agents/phases.yaml +47 -0
- package/framework/domains/agents/qa-implementation.yaml +43 -0
- package/framework/domains/agents/qa-planning.yaml +44 -0
- package/framework/domains/agents/tasks.yaml +48 -0
- package/framework/domains/agents/ux.yaml +50 -0
- package/framework/domains/constitution.yaml +77 -0
- package/framework/domains/global.yaml +64 -0
- package/framework/domains/workflows/brownfield-discovery.yaml +16 -0
- package/framework/domains/workflows/brownfield-fullstack.yaml +26 -0
- package/framework/domains/workflows/brownfield-service.yaml +22 -0
- package/framework/domains/workflows/brownfield-ui.yaml +22 -0
- package/framework/domains/workflows/greenfield-fullstack.yaml +26 -0
- package/framework/hooks/constitution-guard.js +101 -0
- package/framework/hooks/mode-governance.js +92 -0
- package/framework/hooks/model-governance.js +76 -0
- package/framework/hooks/prism-engine.js +89 -0
- package/framework/hooks/session-digest.js +60 -0
- package/framework/hooks/settings.json +44 -0
- package/framework/i18n/en.yaml +3 -3
- package/framework/i18n/es.yaml +3 -3
- package/framework/i18n/fr.yaml +3 -3
- package/framework/i18n/pt.yaml +3 -3
- package/framework/intelligence/decision-engine.md +1 -1
- package/framework/migrations/v1.4-to-v2.0.yaml +167 -0
- package/framework/migrations/v2.0-to-v2.0.1.yaml +132 -0
- package/framework/orchestrator/chati.md +284 -6
- package/framework/tasks/architect-api-design.md +63 -0
- package/framework/tasks/architect-consolidate.md +47 -0
- package/framework/tasks/architect-db-design.md +73 -0
- package/framework/tasks/architect-design.md +95 -0
- package/framework/tasks/architect-security-review.md +62 -0
- package/framework/tasks/architect-stack-selection.md +53 -0
- package/framework/tasks/brief-consolidate.md +249 -0
- package/framework/tasks/brief-constraint-identify.md +277 -0
- package/framework/tasks/brief-extract-requirements.md +339 -0
- package/framework/tasks/brief-stakeholder-map.md +176 -0
- package/framework/tasks/brief-validate-completeness.md +121 -0
- package/framework/tasks/brownfield-wu-architecture-map.md +394 -0
- package/framework/tasks/brownfield-wu-deep-discovery.md +312 -0
- package/framework/tasks/brownfield-wu-dependency-scan.md +359 -0
- package/framework/tasks/brownfield-wu-migration-plan.md +483 -0
- package/framework/tasks/brownfield-wu-report.md +325 -0
- package/framework/tasks/brownfield-wu-risk-assess.md +424 -0
- package/framework/tasks/detail-acceptance-criteria.md +372 -0
- package/framework/tasks/detail-consolidate.md +138 -0
- package/framework/tasks/detail-edge-case-analysis.md +300 -0
- package/framework/tasks/detail-expand-prd.md +389 -0
- package/framework/tasks/detail-nfr-extraction.md +223 -0
- package/framework/tasks/dev-code-review.md +404 -0
- package/framework/tasks/dev-consolidate.md +543 -0
- package/framework/tasks/dev-debug.md +322 -0
- package/framework/tasks/dev-implement.md +252 -0
- package/framework/tasks/dev-iterate.md +411 -0
- package/framework/tasks/dev-pr-prepare.md +497 -0
- package/framework/tasks/dev-refactor.md +342 -0
- package/framework/tasks/dev-test-write.md +306 -0
- package/framework/tasks/devops-ci-setup.md +412 -0
- package/framework/tasks/devops-consolidate.md +712 -0
- package/framework/tasks/devops-deploy-config.md +598 -0
- package/framework/tasks/devops-monitoring-setup.md +658 -0
- package/framework/tasks/devops-release-prepare.md +673 -0
- package/framework/tasks/greenfield-wu-analyze-empty.md +169 -0
- package/framework/tasks/greenfield-wu-report.md +266 -0
- package/framework/tasks/greenfield-wu-scaffold-detection.md +203 -0
- package/framework/tasks/greenfield-wu-tech-stack-assess.md +255 -0
- package/framework/tasks/orchestrator-deviation.md +260 -0
- package/framework/tasks/orchestrator-escalate.md +276 -0
- package/framework/tasks/orchestrator-handoff.md +243 -0
- package/framework/tasks/orchestrator-health.md +372 -0
- package/framework/tasks/orchestrator-mode-switch.md +262 -0
- package/framework/tasks/orchestrator-resume.md +189 -0
- package/framework/tasks/orchestrator-route.md +169 -0
- package/framework/tasks/orchestrator-spawn-terminal.md +358 -0
- package/framework/tasks/orchestrator-status.md +260 -0
- package/framework/tasks/orchestrator-suggest-mode.md +372 -0
- package/framework/tasks/phases-breakdown.md +91 -0
- package/framework/tasks/phases-dependency-mapping.md +67 -0
- package/framework/tasks/phases-mvp-scoping.md +94 -0
- package/framework/tasks/qa-impl-consolidate.md +522 -0
- package/framework/tasks/qa-impl-performance-test.md +487 -0
- package/framework/tasks/qa-impl-regression-check.md +413 -0
- package/framework/tasks/qa-impl-sast-scan.md +402 -0
- package/framework/tasks/qa-impl-test-execute.md +344 -0
- package/framework/tasks/qa-impl-verdict.md +339 -0
- package/framework/tasks/qa-planning-consolidate.md +309 -0
- package/framework/tasks/qa-planning-coverage-plan.md +338 -0
- package/framework/tasks/qa-planning-gate-define.md +339 -0
- package/framework/tasks/qa-planning-risk-matrix.md +631 -0
- package/framework/tasks/qa-planning-test-strategy.md +217 -0
- package/framework/tasks/tasks-acceptance-write.md +75 -0
- package/framework/tasks/tasks-consolidate.md +57 -0
- package/framework/tasks/tasks-decompose.md +80 -0
- package/framework/tasks/tasks-estimate.md +66 -0
- package/framework/tasks/ux-a11y-check.md +49 -0
- package/framework/tasks/ux-component-map.md +55 -0
- package/framework/tasks/ux-consolidate.md +46 -0
- package/framework/tasks/ux-user-flow.md +46 -0
- package/framework/tasks/ux-wireframe.md +76 -0
- package/package.json +2 -2
- package/scripts/bundle-framework.js +2 -0
- package/scripts/changelog-generator.js +222 -0
- package/scripts/codebase-mapper.js +728 -0
- package/scripts/commit-message-generator.js +167 -0
- package/scripts/coverage-analyzer.js +260 -0
- package/scripts/dependency-analyzer.js +280 -0
- package/scripts/framework-analyzer.js +308 -0
- package/scripts/generate-constitution-domain.js +253 -0
- package/scripts/health-check.js +481 -0
- package/scripts/ide-sync.js +327 -0
- package/scripts/performance-analyzer.js +325 -0
- package/scripts/plan-tracker.js +278 -0
- package/scripts/populate-entity-registry.js +481 -0
- package/scripts/pr-review.js +317 -0
- package/scripts/rollback-manager.js +310 -0
- package/scripts/stuck-detector.js +343 -0
- package/scripts/test-quality-assessment.js +257 -0
- package/scripts/validate-agents.js +367 -0
- package/scripts/validate-tasks.js +465 -0
- package/src/autonomy/autonomous-gate.js +293 -0
- package/src/autonomy/index.js +51 -0
- package/src/autonomy/mode-manager.js +225 -0
- package/src/autonomy/mode-suggester.js +283 -0
- package/src/autonomy/progress-reporter.js +268 -0
- package/src/autonomy/safety-net.js +320 -0
- package/src/context/bracket-tracker.js +79 -0
- package/src/context/domain-loader.js +107 -0
- package/src/context/engine.js +144 -0
- package/src/context/formatter.js +184 -0
- package/src/context/index.js +4 -0
- package/src/context/layers/l0-constitution.js +28 -0
- package/src/context/layers/l1-global.js +37 -0
- package/src/context/layers/l2-agent.js +39 -0
- package/src/context/layers/l3-workflow.js +42 -0
- package/src/context/layers/l4-task.js +24 -0
- package/src/decision/analyzer.js +167 -0
- package/src/decision/engine.js +270 -0
- package/src/decision/index.js +38 -0
- package/src/decision/registry-healer.js +450 -0
- package/src/decision/registry-updater.js +330 -0
- package/src/gates/circuit-breaker.js +119 -0
- package/src/gates/g1-planning-complete.js +153 -0
- package/src/gates/g2-qa-planning.js +153 -0
- package/src/gates/g3-implementation.js +188 -0
- package/src/gates/g4-qa-implementation.js +207 -0
- package/src/gates/g5-deploy-ready.js +180 -0
- package/src/gates/gate-base.js +144 -0
- package/src/gates/index.js +46 -0
- package/src/installer/brownfield-upgrader.js +249 -0
- package/src/installer/core.js +82 -11
- package/src/installer/file-hasher.js +51 -0
- package/src/installer/manifest.js +117 -0
- package/src/installer/templates.js +17 -15
- package/src/installer/transaction.js +229 -0
- package/src/installer/validator.js +18 -1
- package/src/intelligence/registry-manager.js +2 -2
- package/src/memory/agent-memory.js +255 -0
- package/src/memory/gotchas-injector.js +72 -0
- package/src/memory/gotchas.js +361 -0
- package/src/memory/index.js +35 -0
- package/src/memory/search.js +233 -0
- package/src/memory/session-digest.js +239 -0
- package/src/merger/env-merger.js +112 -0
- package/src/merger/index.js +56 -0
- package/src/merger/replace-merger.js +51 -0
- package/src/merger/yaml-merger.js +127 -0
- package/src/orchestrator/agent-selector.js +285 -0
- package/src/orchestrator/deviation-handler.js +350 -0
- package/src/orchestrator/handoff-engine.js +271 -0
- package/src/orchestrator/index.js +67 -0
- package/src/orchestrator/intent-classifier.js +264 -0
- package/src/orchestrator/pipeline-manager.js +492 -0
- package/src/orchestrator/pipeline-state.js +223 -0
- package/src/orchestrator/session-manager.js +409 -0
- package/src/tasks/executor.js +195 -0
- package/src/tasks/handoff.js +226 -0
- package/src/tasks/index.js +4 -0
- package/src/tasks/loader.js +210 -0
- package/src/tasks/router.js +182 -0
- package/src/terminal/collector.js +216 -0
- package/src/terminal/index.js +30 -0
- package/src/terminal/isolation.js +129 -0
- package/src/terminal/monitor.js +277 -0
- package/src/terminal/spawner.js +269 -0
- package/src/upgrade/checker.js +1 -1
- package/src/wizard/i18n.js +3 -3
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: detail-edge-case-analysis
|
|
3
|
+
agent: detail
|
|
4
|
+
trigger: detail-nfr-extraction
|
|
5
|
+
phase: clarity
|
|
6
|
+
requires_input: false
|
|
7
|
+
parallelizable: true
|
|
8
|
+
outputs: [edge-cases.yaml]
|
|
9
|
+
handoff_to: detail-acceptance-criteria
|
|
10
|
+
autonomous_gate: true
|
|
11
|
+
criteria:
|
|
12
|
+
- Edge cases identified for all critical features
|
|
13
|
+
- Error scenarios documented
|
|
14
|
+
- Boundary conditions defined
|
|
15
|
+
---
|
|
16
|
+
# Analyze Edge Cases and Error Scenarios
|
|
17
|
+
|
|
18
|
+
## Purpose
|
|
19
|
+
Identify edge cases, error scenarios, and boundary conditions that must be handled for robust implementation.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
- `prd-draft.yaml` with functional requirements
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
### 1. Analyze Each Functional Requirement
|
|
27
|
+
For each FR, identify potential edge cases.
|
|
28
|
+
|
|
29
|
+
### 2. Identify Input Boundary Conditions
|
|
30
|
+
- Empty input (empty string, null, undefined)
|
|
31
|
+
- Max length exceeded
|
|
32
|
+
- Invalid format (malformed email, weak password)
|
|
33
|
+
- Special characters (SQL, XSS, Unicode)
|
|
34
|
+
- Very large input (10MB text, huge arrays)
|
|
35
|
+
|
|
36
|
+
### 3. Identify State Edge Cases
|
|
37
|
+
- User not logged in attempts protected action
|
|
38
|
+
- User tries to edit others' posts
|
|
39
|
+
- Concurrent edits to same post
|
|
40
|
+
- Deleted resource accessed
|
|
41
|
+
- Expired JWT token
|
|
42
|
+
|
|
43
|
+
### 4. Identify Timing Edge Cases
|
|
44
|
+
- Rapid successive requests (double submit)
|
|
45
|
+
- Long-running operations timeout
|
|
46
|
+
- Race conditions in parallel operations
|
|
47
|
+
- Token expires mid-operation
|
|
48
|
+
|
|
49
|
+
### 5. Identify Network Edge Cases
|
|
50
|
+
- API request fails mid-flight
|
|
51
|
+
- Slow network (3G, offline)
|
|
52
|
+
- Partial response received
|
|
53
|
+
- WebSocket disconnection
|
|
54
|
+
|
|
55
|
+
### 6. Identify Data Edge Cases
|
|
56
|
+
- Foreign key constraints violated
|
|
57
|
+
- Unique constraint violations
|
|
58
|
+
- Database connection pool exhausted
|
|
59
|
+
- Transaction deadlock
|
|
60
|
+
- Cascading deletes
|
|
61
|
+
|
|
62
|
+
### 7. Document Error Scenarios
|
|
63
|
+
For each edge case:
|
|
64
|
+
- Scenario description
|
|
65
|
+
- Expected behavior
|
|
66
|
+
- Error message
|
|
67
|
+
- User impact
|
|
68
|
+
- Recovery strategy
|
|
69
|
+
|
|
70
|
+
### 8. Define Boundary Conditions
|
|
71
|
+
For numerical/string limits:
|
|
72
|
+
- Minimum and maximum values
|
|
73
|
+
- What happens at boundaries
|
|
74
|
+
- What happens beyond boundaries
|
|
75
|
+
|
|
76
|
+
### 9. Identify Security Edge Cases
|
|
77
|
+
- Injection attempts (SQL, XSS, command injection)
|
|
78
|
+
- Authorization bypass attempts
|
|
79
|
+
- Token manipulation
|
|
80
|
+
- Brute force attacks
|
|
81
|
+
- Mass assignment vulnerabilities
|
|
82
|
+
|
|
83
|
+
### 10. Create Edge Case Catalog
|
|
84
|
+
Comprehensive list with test scenarios.
|
|
85
|
+
|
|
86
|
+
## Decision Points
|
|
87
|
+
None - systematic analysis of all features.
|
|
88
|
+
|
|
89
|
+
## Error Handling
|
|
90
|
+
- **Too Many Edge Cases**: Prioritize by severity and likelihood
|
|
91
|
+
|
|
92
|
+
## Output Format
|
|
93
|
+
```yaml
|
|
94
|
+
# edge-cases.yaml
|
|
95
|
+
timestamp: 2026-02-13T15:15:00Z
|
|
96
|
+
|
|
97
|
+
authentication_edge_cases:
|
|
98
|
+
- scenario: User submits empty email
|
|
99
|
+
input: {email: "", password: "Valid123"}
|
|
100
|
+
expected_behavior: Validation error, form not submitted
|
|
101
|
+
error_message: "Email is required"
|
|
102
|
+
http_status: 400
|
|
103
|
+
- scenario: User submits malformed email
|
|
104
|
+
input: {email: "not-an-email", password: "Valid123"}
|
|
105
|
+
expected_behavior: Validation error
|
|
106
|
+
error_message: "Invalid email format"
|
|
107
|
+
http_status: 400
|
|
108
|
+
- scenario: Password with only lowercase
|
|
109
|
+
input: {email: "test@example.com", password: "alllowercase123"}
|
|
110
|
+
expected_behavior: Validation error
|
|
111
|
+
error_message: "Password must contain at least one uppercase letter"
|
|
112
|
+
http_status: 400
|
|
113
|
+
- scenario: Extremely long password (>1000 chars)
|
|
114
|
+
input: {email: "test@example.com", password: "A1" + "x"*1000}
|
|
115
|
+
expected_behavior: Accept but truncate or reject with max length
|
|
116
|
+
error_message: "Password exceeds maximum length (256 characters)"
|
|
117
|
+
http_status: 400
|
|
118
|
+
- scenario: SQL injection attempt in email
|
|
119
|
+
input: {email: "admin'--", password: "Valid123"}
|
|
120
|
+
expected_behavior: Parameterized query prevents injection, email validation fails
|
|
121
|
+
error_message: "Invalid email format"
|
|
122
|
+
http_status: 400
|
|
123
|
+
- scenario: Concurrent registration with same email
|
|
124
|
+
input: Two users submit same email simultaneously
|
|
125
|
+
expected_behavior: First succeeds, second fails with duplicate email error
|
|
126
|
+
error_message: "Email already registered"
|
|
127
|
+
http_status: 409
|
|
128
|
+
- scenario: JWT token expired
|
|
129
|
+
input: Request with expired token
|
|
130
|
+
expected_behavior: 401 error, redirect to login, clear token
|
|
131
|
+
error_message: "Session expired, please log in again"
|
|
132
|
+
http_status: 401
|
|
133
|
+
|
|
134
|
+
post_management_edge_cases:
|
|
135
|
+
- scenario: Create post with empty title
|
|
136
|
+
input: {title: "", content: "Content"}
|
|
137
|
+
expected_behavior: Validation error
|
|
138
|
+
error_message: "Title is required"
|
|
139
|
+
http_status: 400
|
|
140
|
+
- scenario: Title exceeds 200 characters
|
|
141
|
+
input: {title: "x"*201, content: "Content"}
|
|
142
|
+
expected_behavior: Validation error
|
|
143
|
+
error_message: "Title must be 200 characters or less"
|
|
144
|
+
http_status: 400
|
|
145
|
+
- scenario: Create post with XSS attempt in content
|
|
146
|
+
input: {title: "Test", content: "<script>alert('xss')</script>"}
|
|
147
|
+
expected_behavior: Content sanitized before storage and display
|
|
148
|
+
error_message: None (sanitized silently)
|
|
149
|
+
- scenario: Upload image >5MB
|
|
150
|
+
input: Image file of 6MB
|
|
151
|
+
expected_behavior: Upload rejected
|
|
152
|
+
error_message: "Image must be smaller than 5MB"
|
|
153
|
+
http_status: 413
|
|
154
|
+
- scenario: Upload non-image file
|
|
155
|
+
input: .exe file
|
|
156
|
+
expected_behavior: Upload rejected
|
|
157
|
+
error_message: "Only JPG and PNG images are allowed"
|
|
158
|
+
http_status: 400
|
|
159
|
+
- scenario: User tries to edit another user's post
|
|
160
|
+
input: PUT /api/posts/:id where post.user_id != current_user.id
|
|
161
|
+
expected_behavior: 403 Forbidden
|
|
162
|
+
error_message: "You don't have permission to edit this post"
|
|
163
|
+
http_status: 403
|
|
164
|
+
- scenario: User tries to delete non-existent post
|
|
165
|
+
input: DELETE /api/posts/invalid-uuid
|
|
166
|
+
expected_behavior: 404 Not Found
|
|
167
|
+
error_message: "Post not found"
|
|
168
|
+
http_status: 404
|
|
169
|
+
- scenario: Concurrent edits to same post
|
|
170
|
+
input: Two users edit same post simultaneously
|
|
171
|
+
expected_behavior: Last write wins (simple approach) or optimistic locking (advanced)
|
|
172
|
+
mitigation: Show warning if post was modified since user loaded it
|
|
173
|
+
- scenario: Create post with 1000 tags
|
|
174
|
+
input: {title: "Test", content: "Content", tags: ["tag1", "tag2", ..., "tag1000"]}
|
|
175
|
+
expected_behavior: Accept but limit to first 20 tags
|
|
176
|
+
error_message: "Maximum 20 tags allowed"
|
|
177
|
+
http_status: 400
|
|
178
|
+
|
|
179
|
+
search_edge_cases:
|
|
180
|
+
- scenario: Search with empty query
|
|
181
|
+
input: GET /api/search?q=
|
|
182
|
+
expected_behavior: Return all posts (paginated) or require non-empty query
|
|
183
|
+
response: All posts or 400 error
|
|
184
|
+
- scenario: Search with special characters
|
|
185
|
+
input: GET /api/search?q=%#@!
|
|
186
|
+
expected_behavior: Escape special characters, perform search
|
|
187
|
+
response: Empty results or posts matching literal characters
|
|
188
|
+
- scenario: Search with extremely long query (>1000 chars)
|
|
189
|
+
input: GET /api/search?q=x*1000
|
|
190
|
+
expected_behavior: Truncate to reasonable length (256 chars) or reject
|
|
191
|
+
error_message: "Search query too long"
|
|
192
|
+
http_status: 400
|
|
193
|
+
- scenario: Search returns 10,000 results
|
|
194
|
+
input: GET /api/search?q=common-word
|
|
195
|
+
expected_behavior: Paginate results, return first page
|
|
196
|
+
response: 20 results + pagination metadata
|
|
197
|
+
- scenario: Search with SQL injection attempt
|
|
198
|
+
input: GET /api/search?q=' OR '1'='1
|
|
199
|
+
expected_behavior: Parameterized query or full-text search prevents injection
|
|
200
|
+
response: Empty results or posts matching literal string
|
|
201
|
+
|
|
202
|
+
network_edge_cases:
|
|
203
|
+
- scenario: API request timeout (>30s)
|
|
204
|
+
expected_behavior: Client shows timeout error, allows retry
|
|
205
|
+
user_impact: Temporary inability to complete action
|
|
206
|
+
recovery: Retry button, exponential backoff
|
|
207
|
+
- scenario: Request fails mid-flight
|
|
208
|
+
expected_behavior: Client detects network error, offers retry
|
|
209
|
+
user_impact: Action not completed
|
|
210
|
+
recovery: Auto-retry up to 3 times, then manual retry
|
|
211
|
+
- scenario: User goes offline mid-form
|
|
212
|
+
expected_behavior: Form data preserved in localStorage
|
|
213
|
+
user_impact: Work not lost
|
|
214
|
+
recovery: Auto-submit when online again (with user confirmation)
|
|
215
|
+
- scenario: Partial response received
|
|
216
|
+
expected_behavior: Detect incomplete JSON, treat as error
|
|
217
|
+
recovery: Retry request
|
|
218
|
+
|
|
219
|
+
database_edge_cases:
|
|
220
|
+
- scenario: Database connection pool exhausted
|
|
221
|
+
expected_behavior: New requests wait or fail with 503
|
|
222
|
+
error_message: "Service temporarily unavailable, please try again"
|
|
223
|
+
http_status: 503
|
|
224
|
+
mitigation: Connection pooling with reasonable limits, monitoring
|
|
225
|
+
- scenario: Unique constraint violation (duplicate email race condition)
|
|
226
|
+
expected_behavior: Database rejects insert, return 409
|
|
227
|
+
error_message: "Email already registered"
|
|
228
|
+
http_status: 409
|
|
229
|
+
- scenario: Foreign key constraint violation (delete user with posts)
|
|
230
|
+
expected_behavior: Cascade delete posts or prevent user deletion
|
|
231
|
+
implementation: CASCADE on foreign key or check before delete
|
|
232
|
+
- scenario: Transaction deadlock
|
|
233
|
+
expected_behavior: Database rolls back one transaction, retry
|
|
234
|
+
mitigation: Keep transactions short, retry with exponential backoff
|
|
235
|
+
|
|
236
|
+
security_edge_cases:
|
|
237
|
+
- scenario: Mass assignment attempt
|
|
238
|
+
input: POST /api/users with {email, password, is_admin: true}
|
|
239
|
+
expected_behavior: is_admin field ignored
|
|
240
|
+
implementation: Explicitly whitelist allowed fields
|
|
241
|
+
- scenario: Brute force password attempts
|
|
242
|
+
expected_behavior: Rate limit to 5 attempts per 15 minutes
|
|
243
|
+
error_message: "Too many login attempts, please try again in 15 minutes"
|
|
244
|
+
http_status: 429
|
|
245
|
+
- scenario: JWT token tampered with
|
|
246
|
+
expected_behavior: Signature verification fails, 401 error
|
|
247
|
+
error_message: "Invalid authentication token"
|
|
248
|
+
http_status: 401
|
|
249
|
+
- scenario: User changes email in token to impersonate another
|
|
250
|
+
expected_behavior: Signature verification fails
|
|
251
|
+
security_control: JWT signature validation
|
|
252
|
+
|
|
253
|
+
boundary_conditions:
|
|
254
|
+
- field: title
|
|
255
|
+
type: string
|
|
256
|
+
min_length: 1
|
|
257
|
+
max_length: 200
|
|
258
|
+
at_min: Accepted (1 char title)
|
|
259
|
+
at_max: Accepted (200 char title)
|
|
260
|
+
below_min: Rejected (empty string)
|
|
261
|
+
above_max: Rejected (201+ chars)
|
|
262
|
+
- field: password
|
|
263
|
+
type: string
|
|
264
|
+
min_length: 8
|
|
265
|
+
max_length: 256
|
|
266
|
+
pattern: At least 1 uppercase, 1 lowercase, 1 number
|
|
267
|
+
at_min: Accepted if meets pattern
|
|
268
|
+
at_max: Accepted
|
|
269
|
+
below_min: Rejected (<8 chars)
|
|
270
|
+
above_max: Rejected (>256 chars)
|
|
271
|
+
- field: image_size
|
|
272
|
+
type: file
|
|
273
|
+
max_size: 5242880 (5MB)
|
|
274
|
+
at_max: Accepted (exactly 5MB)
|
|
275
|
+
above_max: Rejected (>5MB)
|
|
276
|
+
- field: pagination_limit
|
|
277
|
+
type: integer
|
|
278
|
+
min: 1
|
|
279
|
+
max: 100
|
|
280
|
+
default: 20
|
|
281
|
+
at_min: Return 1 result
|
|
282
|
+
at_max: Return 100 results
|
|
283
|
+
below_min: Use default (20)
|
|
284
|
+
above_max: Use max (100)
|
|
285
|
+
- field: concurrent_users
|
|
286
|
+
type: system_load
|
|
287
|
+
target: 10000
|
|
288
|
+
at_target: System performs normally
|
|
289
|
+
above_target: Graceful degradation, may slow down but not crash
|
|
290
|
+
|
|
291
|
+
testing_scenarios:
|
|
292
|
+
- Create post with boundary title lengths (0, 1, 200, 201 chars)
|
|
293
|
+
- Register with various invalid emails
|
|
294
|
+
- Upload files of various types and sizes
|
|
295
|
+
- Attempt unauthorized actions (edit others' posts)
|
|
296
|
+
- Simulate network failures and timeouts
|
|
297
|
+
- Test concurrent operations (double submit, parallel edits)
|
|
298
|
+
- Inject SQL, XSS, command injection attempts
|
|
299
|
+
- Stress test with 10k+ concurrent users
|
|
300
|
+
```
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: detail-expand-prd
|
|
3
|
+
agent: detail
|
|
4
|
+
trigger: brief
|
|
5
|
+
phase: clarity
|
|
6
|
+
requires_input: false
|
|
7
|
+
parallelizable: false
|
|
8
|
+
outputs: [prd-draft.yaml]
|
|
9
|
+
handoff_to: detail-nfr-extraction
|
|
10
|
+
autonomous_gate: true
|
|
11
|
+
criteria:
|
|
12
|
+
- All functional requirements expanded with details
|
|
13
|
+
- User stories written in Given-When-Then format
|
|
14
|
+
- Data models identified
|
|
15
|
+
- API endpoints outlined
|
|
16
|
+
---
|
|
17
|
+
# Expand Brief into Formal PRD
|
|
18
|
+
|
|
19
|
+
## Purpose
|
|
20
|
+
Transform the approved brief into a comprehensive Product Requirements Document with technical details.
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
- `brief.yaml` approved by user
|
|
24
|
+
|
|
25
|
+
## Steps
|
|
26
|
+
|
|
27
|
+
### 1. Load Approved Brief
|
|
28
|
+
Read brief.yaml and extract all requirements and context.
|
|
29
|
+
|
|
30
|
+
### 2. Expand Each Functional Requirement
|
|
31
|
+
For each FR, add:
|
|
32
|
+
- **Description**: Detailed explanation of what it does
|
|
33
|
+
- **User Story**: As a [persona], I want [action] so that [benefit]
|
|
34
|
+
- **Acceptance Criteria**: Given-When-Then scenarios
|
|
35
|
+
- **Priority**: P0 (must-have), P1 (should-have), P2 (nice-to-have)
|
|
36
|
+
- **Estimated Complexity**: Small (1-3 days), Medium (4-7 days), Large (8+ days)
|
|
37
|
+
- **Dependencies**: Other FRs that must be completed first
|
|
38
|
+
|
|
39
|
+
### 3. Define Data Models
|
|
40
|
+
Identify entities and their relationships:
|
|
41
|
+
- User (id, email, password_hash, created_at, updated_at)
|
|
42
|
+
- Post (id, user_id, title, content, tags, images, created_at, updated_at, published_at)
|
|
43
|
+
- Tag (id, name)
|
|
44
|
+
- PostTag (post_id, tag_id) - many-to-many relationship
|
|
45
|
+
|
|
46
|
+
Document:
|
|
47
|
+
- Entity name
|
|
48
|
+
- Attributes with types
|
|
49
|
+
- Relationships (one-to-one, one-to-many, many-to-many)
|
|
50
|
+
- Constraints (unique, required, foreign keys)
|
|
51
|
+
|
|
52
|
+
### 4. Outline API Endpoints
|
|
53
|
+
For each FR, define required endpoints:
|
|
54
|
+
- **Method**: GET, POST, PUT, DELETE
|
|
55
|
+
- **Path**: /api/users, /api/posts/:id
|
|
56
|
+
- **Request**: Body, query params, path params
|
|
57
|
+
- **Response**: Success (200, 201) and error codes (400, 401, 404, 500)
|
|
58
|
+
- **Authentication**: Required or public
|
|
59
|
+
|
|
60
|
+
### 5. Define UI Screens
|
|
61
|
+
For each user-facing FR:
|
|
62
|
+
- Screen name
|
|
63
|
+
- Purpose
|
|
64
|
+
- Key elements (forms, buttons, lists)
|
|
65
|
+
- Navigation flow
|
|
66
|
+
- Responsive breakpoints
|
|
67
|
+
|
|
68
|
+
### 6. Document Business Rules
|
|
69
|
+
Extract business logic:
|
|
70
|
+
- Validation rules (email format, password strength, max image size)
|
|
71
|
+
- Authorization rules (users can only edit own posts)
|
|
72
|
+
- Data constraints (post title max 200 chars)
|
|
73
|
+
- Workflow rules (post must have title to publish)
|
|
74
|
+
|
|
75
|
+
### 7. Identify Integration Points
|
|
76
|
+
For external systems:
|
|
77
|
+
- WordPress API: Read posts and metadata
|
|
78
|
+
- Email service: Registration confirmation (if needed)
|
|
79
|
+
- File storage: Image uploads (Supabase storage)
|
|
80
|
+
|
|
81
|
+
### 8. Define Error Handling
|
|
82
|
+
- Input validation errors
|
|
83
|
+
- Authentication/authorization failures
|
|
84
|
+
- Network failures
|
|
85
|
+
- Database errors
|
|
86
|
+
- External API failures
|
|
87
|
+
|
|
88
|
+
### 9. Document State Management
|
|
89
|
+
- Authentication state (logged in/out)
|
|
90
|
+
- Form state (draft, submitting, submitted)
|
|
91
|
+
- Data loading state (loading, success, error)
|
|
92
|
+
- Cache invalidation strategy
|
|
93
|
+
|
|
94
|
+
### 10. Create Initial PRD Draft
|
|
95
|
+
Structured document with all sections populated.
|
|
96
|
+
|
|
97
|
+
## Decision Points
|
|
98
|
+
- **Missing Technical Details**: Make reasonable assumptions based on best practices
|
|
99
|
+
- **Ambiguous Requirements**: Note for NFR extraction or edge case analysis
|
|
100
|
+
|
|
101
|
+
## Error Handling
|
|
102
|
+
- **Incomplete Brief**: Request brief completion before proceeding
|
|
103
|
+
- **Contradictory Requirements**: Flag and request clarification
|
|
104
|
+
|
|
105
|
+
## Output Format
|
|
106
|
+
```yaml
|
|
107
|
+
# prd-draft.yaml
|
|
108
|
+
timestamp: 2026-02-13T14:30:00Z
|
|
109
|
+
|
|
110
|
+
functional_requirements_detailed:
|
|
111
|
+
- id: FR-001
|
|
112
|
+
title: User Registration
|
|
113
|
+
description: |
|
|
114
|
+
New users can create an account by providing email and password.
|
|
115
|
+
Email must be unique and valid format. Password must meet strength requirements.
|
|
116
|
+
Upon successful registration, user is automatically logged in.
|
|
117
|
+
user_story: |
|
|
118
|
+
As a content creator, I want to register for an account with my email and
|
|
119
|
+
password so that I can start publishing blog posts.
|
|
120
|
+
acceptance_criteria:
|
|
121
|
+
- scenario: Successful registration
|
|
122
|
+
given: User is on registration page and not logged in
|
|
123
|
+
when: User submits valid email and password
|
|
124
|
+
then: |
|
|
125
|
+
- Account is created in database
|
|
126
|
+
- User receives JWT token
|
|
127
|
+
- User is redirected to dashboard
|
|
128
|
+
- Confirmation email is sent (future phase)
|
|
129
|
+
- scenario: Duplicate email
|
|
130
|
+
given: Email already exists in database
|
|
131
|
+
when: User submits registration form with existing email
|
|
132
|
+
then: |
|
|
133
|
+
- Registration fails with 409 error
|
|
134
|
+
- User sees "Email already registered" message
|
|
135
|
+
- Form remains populated (password cleared)
|
|
136
|
+
- scenario: Invalid password
|
|
137
|
+
given: User is on registration page
|
|
138
|
+
when: User submits password that doesn't meet requirements
|
|
139
|
+
then: |
|
|
140
|
+
- Registration fails with 400 error
|
|
141
|
+
- User sees specific validation errors
|
|
142
|
+
- Form shows password requirements
|
|
143
|
+
priority: P0
|
|
144
|
+
complexity: medium (5 days)
|
|
145
|
+
dependencies: []
|
|
146
|
+
api_endpoints:
|
|
147
|
+
- method: POST
|
|
148
|
+
path: /api/auth/register
|
|
149
|
+
request:
|
|
150
|
+
body:
|
|
151
|
+
email: string (required, valid email)
|
|
152
|
+
password: string (required, min 8 chars, 1 uppercase, 1 number)
|
|
153
|
+
response:
|
|
154
|
+
success: 201 Created
|
|
155
|
+
body:
|
|
156
|
+
user: {id, email, created_at}
|
|
157
|
+
token: string (JWT)
|
|
158
|
+
errors:
|
|
159
|
+
400: Invalid input (validation errors)
|
|
160
|
+
409: Email already registered
|
|
161
|
+
ui_screens:
|
|
162
|
+
- name: Registration Page
|
|
163
|
+
route: /register
|
|
164
|
+
elements:
|
|
165
|
+
- Email input field
|
|
166
|
+
- Password input field
|
|
167
|
+
- Password strength indicator
|
|
168
|
+
- Submit button
|
|
169
|
+
- Link to login page
|
|
170
|
+
validation:
|
|
171
|
+
- Real-time email format validation
|
|
172
|
+
- Real-time password strength check
|
|
173
|
+
- Disable submit until valid
|
|
174
|
+
data_model:
|
|
175
|
+
entity: User
|
|
176
|
+
attributes:
|
|
177
|
+
id: uuid (primary key)
|
|
178
|
+
email: string (unique, required)
|
|
179
|
+
password_hash: string (required)
|
|
180
|
+
created_at: timestamp
|
|
181
|
+
updated_at: timestamp
|
|
182
|
+
business_rules:
|
|
183
|
+
- Email must be unique across all users
|
|
184
|
+
- Password must be at least 8 characters
|
|
185
|
+
- Password must contain 1 uppercase, 1 lowercase, 1 number
|
|
186
|
+
- Email must be valid format (regex validation)
|
|
187
|
+
- Password must be hashed with bcrypt before storage
|
|
188
|
+
|
|
189
|
+
- id: FR-002
|
|
190
|
+
title: User Login
|
|
191
|
+
description: |
|
|
192
|
+
Registered users can log in with email and password to access protected features.
|
|
193
|
+
user_story: |
|
|
194
|
+
As a registered user, I want to log in with my credentials so that I can
|
|
195
|
+
access my dashboard and manage my posts.
|
|
196
|
+
acceptance_criteria:
|
|
197
|
+
- scenario: Successful login
|
|
198
|
+
given: User has valid account
|
|
199
|
+
when: User submits correct email and password
|
|
200
|
+
then: |
|
|
201
|
+
- User receives JWT token
|
|
202
|
+
- User is redirected to dashboard
|
|
203
|
+
- Token is stored in localStorage
|
|
204
|
+
- scenario: Invalid credentials
|
|
205
|
+
given: User is on login page
|
|
206
|
+
when: User submits incorrect email or password
|
|
207
|
+
then: |
|
|
208
|
+
- Login fails with 401 error
|
|
209
|
+
- User sees "Invalid credentials" message
|
|
210
|
+
- Form is cleared for security
|
|
211
|
+
priority: P0
|
|
212
|
+
complexity: medium (4 days)
|
|
213
|
+
dependencies: [FR-001]
|
|
214
|
+
api_endpoints:
|
|
215
|
+
- method: POST
|
|
216
|
+
path: /api/auth/login
|
|
217
|
+
request:
|
|
218
|
+
body:
|
|
219
|
+
email: string (required)
|
|
220
|
+
password: string (required)
|
|
221
|
+
response:
|
|
222
|
+
success: 200 OK
|
|
223
|
+
body:
|
|
224
|
+
user: {id, email}
|
|
225
|
+
token: string (JWT)
|
|
226
|
+
errors:
|
|
227
|
+
401: Invalid credentials
|
|
228
|
+
ui_screens:
|
|
229
|
+
- name: Login Page
|
|
230
|
+
route: /login
|
|
231
|
+
elements:
|
|
232
|
+
- Email input
|
|
233
|
+
- Password input
|
|
234
|
+
- Submit button
|
|
235
|
+
- Link to registration
|
|
236
|
+
- "Forgot password" link (future)
|
|
237
|
+
|
|
238
|
+
data_models:
|
|
239
|
+
- name: User
|
|
240
|
+
attributes:
|
|
241
|
+
- name: id
|
|
242
|
+
type: uuid
|
|
243
|
+
constraints: [primary_key]
|
|
244
|
+
- name: email
|
|
245
|
+
type: string
|
|
246
|
+
constraints: [unique, required]
|
|
247
|
+
- name: password_hash
|
|
248
|
+
type: string
|
|
249
|
+
constraints: [required]
|
|
250
|
+
- name: created_at
|
|
251
|
+
type: timestamp
|
|
252
|
+
constraints: [required, default_now]
|
|
253
|
+
- name: updated_at
|
|
254
|
+
type: timestamp
|
|
255
|
+
constraints: [required, default_now, update_on_change]
|
|
256
|
+
- name: Post
|
|
257
|
+
attributes:
|
|
258
|
+
- name: id
|
|
259
|
+
type: uuid
|
|
260
|
+
constraints: [primary_key]
|
|
261
|
+
- name: user_id
|
|
262
|
+
type: uuid
|
|
263
|
+
constraints: [required, foreign_key(User.id)]
|
|
264
|
+
- name: title
|
|
265
|
+
type: string
|
|
266
|
+
constraints: [required, max_length(200)]
|
|
267
|
+
- name: content
|
|
268
|
+
type: text
|
|
269
|
+
constraints: [required]
|
|
270
|
+
- name: tags
|
|
271
|
+
type: array(string)
|
|
272
|
+
constraints: []
|
|
273
|
+
- name: image_urls
|
|
274
|
+
type: array(string)
|
|
275
|
+
constraints: []
|
|
276
|
+
- name: published_at
|
|
277
|
+
type: timestamp
|
|
278
|
+
constraints: [nullable]
|
|
279
|
+
- name: created_at
|
|
280
|
+
type: timestamp
|
|
281
|
+
constraints: [required, default_now]
|
|
282
|
+
- name: updated_at
|
|
283
|
+
type: timestamp
|
|
284
|
+
constraints: [required, default_now, update_on_change]
|
|
285
|
+
relationships:
|
|
286
|
+
- type: many_to_one
|
|
287
|
+
entity: User
|
|
288
|
+
description: Each post belongs to one user
|
|
289
|
+
|
|
290
|
+
api_endpoints_summary:
|
|
291
|
+
authentication:
|
|
292
|
+
- POST /api/auth/register
|
|
293
|
+
- POST /api/auth/login
|
|
294
|
+
- GET /api/auth/me (get current user)
|
|
295
|
+
- POST /api/auth/logout
|
|
296
|
+
posts:
|
|
297
|
+
- GET /api/posts (list all, with pagination)
|
|
298
|
+
- GET /api/posts/:id (get single post)
|
|
299
|
+
- POST /api/posts (create new post, auth required)
|
|
300
|
+
- PUT /api/posts/:id (update post, auth required, owner only)
|
|
301
|
+
- DELETE /api/posts/:id (delete post, auth required, owner only)
|
|
302
|
+
search:
|
|
303
|
+
- GET /api/search?q=keyword&tag=tagname
|
|
304
|
+
wordpress:
|
|
305
|
+
- GET /api/wordpress/posts (fetch from WordPress API)
|
|
306
|
+
|
|
307
|
+
ui_screens_summary:
|
|
308
|
+
public:
|
|
309
|
+
- / (home page with post list)
|
|
310
|
+
- /posts/:id (post detail page)
|
|
311
|
+
- /register (registration page)
|
|
312
|
+
- /login (login page)
|
|
313
|
+
- /search (search results page)
|
|
314
|
+
authenticated:
|
|
315
|
+
- /dashboard (user dashboard)
|
|
316
|
+
- /posts/new (create post page)
|
|
317
|
+
- /posts/:id/edit (edit post page)
|
|
318
|
+
- /profile (user profile, future)
|
|
319
|
+
|
|
320
|
+
business_rules:
|
|
321
|
+
authentication:
|
|
322
|
+
- Password must be 8+ chars with 1 uppercase, 1 number
|
|
323
|
+
- JWT token expires after 7 days
|
|
324
|
+
- Email must be unique
|
|
325
|
+
posts:
|
|
326
|
+
- Title required, max 200 characters
|
|
327
|
+
- Content required, no max length
|
|
328
|
+
- Users can only edit/delete their own posts
|
|
329
|
+
- Published posts visible to all, drafts only to owner
|
|
330
|
+
- Tags are optional, stored as array
|
|
331
|
+
- Images must be <5MB, JPG/PNG only
|
|
332
|
+
search:
|
|
333
|
+
- Search is case-insensitive
|
|
334
|
+
- Matches in title, content, and tags
|
|
335
|
+
- Results paginated (20 per page)
|
|
336
|
+
|
|
337
|
+
integration_points:
|
|
338
|
+
- name: WordPress API
|
|
339
|
+
purpose: Fetch existing blog posts
|
|
340
|
+
endpoint: https://existing-blog.com/wp-json/wp/v2/posts
|
|
341
|
+
authentication: API key in header
|
|
342
|
+
data_format: JSON
|
|
343
|
+
error_handling: Cache results, show stale data if API down
|
|
344
|
+
- name: Supabase
|
|
345
|
+
services: [auth, database, storage]
|
|
346
|
+
purpose: Backend infrastructure
|
|
347
|
+
- name: Image Storage
|
|
348
|
+
service: Supabase Storage
|
|
349
|
+
purpose: Store uploaded images
|
|
350
|
+
constraints: 5MB max per file, JPG/PNG only
|
|
351
|
+
|
|
352
|
+
error_handling_strategy:
|
|
353
|
+
input_validation:
|
|
354
|
+
- Client-side validation for immediate feedback
|
|
355
|
+
- Server-side validation for security
|
|
356
|
+
- Return specific error messages (not generic "invalid input")
|
|
357
|
+
authentication:
|
|
358
|
+
- 401 for missing/invalid token
|
|
359
|
+
- Redirect to login page
|
|
360
|
+
- Clear token from localStorage
|
|
361
|
+
authorization:
|
|
362
|
+
- 403 for insufficient permissions
|
|
363
|
+
- User-friendly error message
|
|
364
|
+
network_errors:
|
|
365
|
+
- Retry up to 3 times with exponential backoff
|
|
366
|
+
- Show user-friendly error message
|
|
367
|
+
- Provide offline capability where possible
|
|
368
|
+
database_errors:
|
|
369
|
+
- Log error details server-side
|
|
370
|
+
- Return generic 500 error to client
|
|
371
|
+
- Do not expose database structure
|
|
372
|
+
|
|
373
|
+
state_management:
|
|
374
|
+
authentication_state:
|
|
375
|
+
- Stored in React Context
|
|
376
|
+
- Persisted in localStorage (JWT)
|
|
377
|
+
- Checked on app initialization
|
|
378
|
+
- Cleared on logout
|
|
379
|
+
data_cache:
|
|
380
|
+
- Use TanStack Query for server state
|
|
381
|
+
- 5-minute stale time
|
|
382
|
+
- Background refetch on window focus
|
|
383
|
+
form_state:
|
|
384
|
+
- React Hook Form for form management
|
|
385
|
+
- Validation on blur and submit
|
|
386
|
+
- Autosave drafts every 30 seconds (future)
|
|
387
|
+
|
|
388
|
+
next_step: nfr_extraction
|
|
389
|
+
```
|