ariadna 1.1.4 → 1.2.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.
- checksums.yaml +4 -4
- data/data/agents/ariadna-backend-executor.md +4 -1
- data/data/agents/ariadna-executor.md +4 -1
- data/data/agents/ariadna-frontend-executor.md +4 -1
- data/data/agents/ariadna-planner.md +28 -0
- data/data/agents/ariadna-test-executor.md +4 -1
- data/data/ariadna/references/rails-conventions.md +391 -0
- data/data/ariadna/templates/summary.md +11 -0
- data/data/ariadna/workflows/execute-phase.md +93 -5
- data/data/ariadna/workflows/execute-plan.md +12 -1
- data/data/ariadna/workflows/new-project.md +52 -129
- data/data/ariadna/workflows/plan-phase.md +125 -50
- data/data/commands/ariadna/execute-phase.md +4 -3
- data/data/commands/ariadna/new-project.md +8 -6
- data/data/commands/ariadna/plan-phase.md +9 -7
- data/data/guides/frontend.md +1044 -9
- data/lib/ariadna/tools/config_manager.rb +9 -3
- data/lib/ariadna/tools/frontmatter.rb +2 -0
- data/lib/ariadna/tools/init.rb +5 -0
- data/lib/ariadna/tools/phase_manager.rb +20 -2
- data/lib/ariadna/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d45bf8e96c2f2d1d07d2c3236cfaa5e3f6c6fa43cf5f4b785be66fc5160c9ee6
|
|
4
|
+
data.tar.gz: 69364ceaebbf8755a887e9a994dee5e6490d5144a9f681447d9a0946c3c1f095
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 175abad4e06b132ae2f3489fbf7e7db92a0aaa2758d42fc8bb374b2b6151d891cf963a9e592757fd7e872443da3a46c871f8f66ad83ca48c6299a42a4782cb93
|
|
7
|
+
data.tar.gz: 0c011641fa6e541200d0e0bcbb1c83066ede0c65296c285a0e7d51970b4e626fb916c4798f7e59618bab07b867bcfc997efdd898677c917ce1e56e40b05a9f4c
|
|
@@ -236,7 +236,10 @@ When spawned as part of a team (via `TeamCreate`/`Task` with `team_name`), follo
|
|
|
236
236
|
1. **Check for assigned tasks:** `TaskList` → find tasks owned by you with status `pending`
|
|
237
237
|
2. **Claim a task:** `TaskUpdate(taskId=..., status="in_progress")` — prefer lowest ID first
|
|
238
238
|
3. **Read the plan:** Extract the plan file path from the task description, read it with the Read tool
|
|
239
|
-
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary →
|
|
239
|
+
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary → self_check)
|
|
240
|
+
4b. **Skip STATE.md updates in team mode.** The orchestrator aggregates state.
|
|
241
|
+
Only create SUMMARY.md and commit plan files.
|
|
242
|
+
Do NOT call `ariadna-tools state advance-plan` or `ariadna-tools state record-metric`.
|
|
240
243
|
5. **Mark task complete:** `TaskUpdate(taskId=..., status="completed")`
|
|
241
244
|
6. **Check for more work:** `TaskList` → find next unblocked, unowned task matching your domain. If available, claim and execute it.
|
|
242
245
|
7. **When no tasks remain:** `SendMessage(type="message", recipient="team-lead", content="All backend tasks complete. No remaining tasks.")` then go idle.
|
|
@@ -397,7 +397,10 @@ When spawned as part of a team (via `TeamCreate`/`Task` with `team_name`), follo
|
|
|
397
397
|
1. **Check for assigned tasks:** `TaskList` → find tasks owned by you with status `pending`
|
|
398
398
|
2. **Claim a task:** `TaskUpdate(taskId=..., status="in_progress")` — prefer lowest ID first
|
|
399
399
|
3. **Read the plan:** Extract the plan file path from the task description, read it with the Read tool
|
|
400
|
-
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary →
|
|
400
|
+
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary → self_check)
|
|
401
|
+
4b. **Skip STATE.md updates in team mode.** The orchestrator aggregates state.
|
|
402
|
+
Only create SUMMARY.md and commit plan files.
|
|
403
|
+
Do NOT call `ariadna-tools state advance-plan` or `ariadna-tools state record-metric`.
|
|
401
404
|
5. **Mark task complete:** `TaskUpdate(taskId=..., status="completed")`
|
|
402
405
|
6. **Check for more work:** `TaskList` → find next unblocked, unowned task. If available, claim and execute it.
|
|
403
406
|
7. **When no tasks remain:** `SendMessage(type="message", recipient="team-lead", content="All assigned tasks complete. No remaining tasks.")` then go idle.
|
|
@@ -234,7 +234,10 @@ When spawned as part of a team (via `TeamCreate`/`Task` with `team_name`), follo
|
|
|
234
234
|
1. **Check for assigned tasks:** `TaskList` → find tasks owned by you with status `pending`
|
|
235
235
|
2. **Claim a task:** `TaskUpdate(taskId=..., status="in_progress")` — prefer lowest ID first
|
|
236
236
|
3. **Read the plan:** Extract the plan file path from the task description, read it with the Read tool
|
|
237
|
-
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary →
|
|
237
|
+
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary → self_check)
|
|
238
|
+
4b. **Skip STATE.md updates in team mode.** The orchestrator aggregates state.
|
|
239
|
+
Only create SUMMARY.md and commit plan files.
|
|
240
|
+
Do NOT call `ariadna-tools state advance-plan` or `ariadna-tools state record-metric`.
|
|
238
241
|
5. **Mark task complete:** `TaskUpdate(taskId=..., status="completed")`
|
|
239
242
|
6. **Check for more work:** `TaskList` → find next unblocked, unowned task matching your domain. If available, claim and execute it.
|
|
240
243
|
7. **When no tasks remain:** `SendMessage(type="message", recipient="team-lead", content="All frontend tasks complete. No remaining tasks.")` then go idle.
|
|
@@ -17,6 +17,7 @@ Your job: Produce PLAN.md files that Claude executors can implement without inte
|
|
|
17
17
|
|
|
18
18
|
**Core responsibilities:**
|
|
19
19
|
- **FIRST: Parse and honor user decisions from CONTEXT.md** (locked decisions are NON-NEGOTIABLE)
|
|
20
|
+
- Use Rails conventions (from `rails-conventions.md`) for standard task decomposition
|
|
20
21
|
- Decompose phases into parallel-optimized plans with 2-3 tasks each
|
|
21
22
|
- Build dependency graphs and assign execution waves
|
|
22
23
|
- Derive must-haves using goal-backward methodology
|
|
@@ -25,6 +26,33 @@ Your job: Produce PLAN.md files that Claude executors can implement without inte
|
|
|
25
26
|
- Return structured results to orchestrator
|
|
26
27
|
</role>
|
|
27
28
|
|
|
29
|
+
<rails_awareness>
|
|
30
|
+
## Rails-Aware Planning
|
|
31
|
+
|
|
32
|
+
Load Rails conventions from your required reading for standard task decomposition patterns.
|
|
33
|
+
|
|
34
|
+
@~/.claude/ariadna/references/rails-conventions.md
|
|
35
|
+
|
|
36
|
+
**Use domain templates** for common Rails work:
|
|
37
|
+
- "Add model" → migration + model + tests + fixtures
|
|
38
|
+
- "Add controller" → routes + controller + views + tests
|
|
39
|
+
- "Add authentication" → auth scaffold + user model + session controller + tests
|
|
40
|
+
- "Add background job" → job class + model method + tests
|
|
41
|
+
- "Add mailer" → mailer + views + tests
|
|
42
|
+
- "Add Turbo/Hotwire feature" → Turbo Frame + controller response + Stimulus (if needed) + system test
|
|
43
|
+
|
|
44
|
+
**Known domains (skip discovery):** Models, Controllers, Views, Auth, Jobs, Email, File Uploads, Real-time, Testing, API Mode, Caching. See `rails-conventions.md` `<known_domains>` for the full list.
|
|
45
|
+
|
|
46
|
+
**Discovery only for:** External API integrations, novel gems, payment systems, or anything not in the known domains list.
|
|
47
|
+
|
|
48
|
+
**Pitfall prevention:** Apply common Rails pitfalls from `rails-conventions.md` proactively:
|
|
49
|
+
- Include `includes()` for associations in controller queries (N+1)
|
|
50
|
+
- Add database indexes in migration tasks
|
|
51
|
+
- Use strong_parameters in controller tasks
|
|
52
|
+
- Keep controllers thin, models rich
|
|
53
|
+
- Use background jobs for external calls
|
|
54
|
+
</rails_awareness>
|
|
55
|
+
|
|
28
56
|
<context_fidelity>
|
|
29
57
|
## CRITICAL: User Decision Fidelity
|
|
30
58
|
|
|
@@ -240,7 +240,10 @@ When spawned as part of a team (via `TeamCreate`/`Task` with `team_name`), follo
|
|
|
240
240
|
1. **Check for assigned tasks:** `TaskList` → find tasks owned by you with status `pending`
|
|
241
241
|
2. **Claim a task:** `TaskUpdate(taskId=..., status="in_progress")` — prefer lowest ID first
|
|
242
242
|
3. **Read the plan:** Extract the plan file path from the task description, read it with the Read tool
|
|
243
|
-
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary →
|
|
243
|
+
4. **Execute the plan:** Follow the standard execution flow (load_plan → execute_tasks → summary → self_check)
|
|
244
|
+
4b. **Skip STATE.md updates in team mode.** The orchestrator aggregates state.
|
|
245
|
+
Only create SUMMARY.md and commit plan files.
|
|
246
|
+
Do NOT call `ariadna-tools state advance-plan` or `ariadna-tools state record-metric`.
|
|
244
247
|
5. **Mark task complete:** `TaskUpdate(taskId=..., status="completed")`
|
|
245
248
|
6. **Check for more work:** `TaskList` → find next unblocked, unowned task matching your domain. If available, claim and execute it.
|
|
246
249
|
7. **When no tasks remain:** `SendMessage(type="message", recipient="team-lead", content="All testing tasks complete. No remaining tasks.")` then go idle.
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
<rails_conventions>
|
|
2
|
+
|
|
3
|
+
Pre-baked Rails knowledge for Ariadna planning and execution agents. This document replaces generic research for standard Rails projects, encoding well-known conventions, patterns, and pitfalls so agents don't need to web-search for common Rails patterns.
|
|
4
|
+
|
|
5
|
+
<standard_stack>
|
|
6
|
+
|
|
7
|
+
## Standard Rails Stack (2025)
|
|
8
|
+
|
|
9
|
+
| Layer | Technology | Notes |
|
|
10
|
+
|-------|-----------|-------|
|
|
11
|
+
| Framework | Rails 8+ | Defaults to SQLite in dev, includes Solid Queue/Cache/Cable |
|
|
12
|
+
| Database | PostgreSQL (production) | SQLite for dev/test is fine for most projects |
|
|
13
|
+
| Background Jobs | Solid Queue | Rails 8 default, replaces Sidekiq for most cases |
|
|
14
|
+
| Caching | Solid Cache | Rails 8 default, database-backed cache |
|
|
15
|
+
| WebSockets | Action Cable + Solid Cable | Rails 8 default |
|
|
16
|
+
| Real-time UI | Turbo (Hotwire) | Turbo Drive, Frames, Streams |
|
|
17
|
+
| JS Sprinkles | Stimulus (Hotwire) | Controllers for interactive behavior |
|
|
18
|
+
| CSS | Tailwind CSS or Propshaft | Rails 8 defaults to Propshaft asset pipeline |
|
|
19
|
+
| Auth | Rails built-in `has_secure_password` or Devise | Rails 8 includes auth generator |
|
|
20
|
+
| Email | Action Mailer | Built-in |
|
|
21
|
+
| File Upload | Active Storage | Built-in |
|
|
22
|
+
| API | Rails API mode or Jbuilder | Built-in |
|
|
23
|
+
| Testing | Minitest | Rails default, use fixtures not factories |
|
|
24
|
+
| Linting | RuboCop + rubocop-rails | Standard community linting |
|
|
25
|
+
|
|
26
|
+
**What NOT to use (and why):**
|
|
27
|
+
- Factories (FactoryBot) when fixtures suffice — fixtures are faster, declarative, and Rails-native
|
|
28
|
+
- RSpec unless the project already uses it — Minitest is simpler and Rails-native
|
|
29
|
+
- Webpacker/Shakapacker — replaced by importmap-rails or jsbundling-rails
|
|
30
|
+
- Sprockets — replaced by Propshaft in Rails 8
|
|
31
|
+
- Redis for jobs/cache — Solid Queue/Cache use the database, simpler ops
|
|
32
|
+
|
|
33
|
+
</standard_stack>
|
|
34
|
+
|
|
35
|
+
<architecture_patterns>
|
|
36
|
+
|
|
37
|
+
## Rails Architecture Patterns
|
|
38
|
+
|
|
39
|
+
### MVC Foundation
|
|
40
|
+
- **Models:** Business logic lives here. Validations, scopes, callbacks, associations.
|
|
41
|
+
- **Controllers:** Thin. Receive request, call model, render response. 7 RESTful actions max.
|
|
42
|
+
- **Views:** ERB templates. Logic delegated to presenters or helpers.
|
|
43
|
+
|
|
44
|
+
### Concern-Driven Architecture
|
|
45
|
+
```
|
|
46
|
+
app/models/concerns/
|
|
47
|
+
shared/ # Cross-model concerns (Trackable, Searchable)
|
|
48
|
+
model_name/ # Model-specific concerns (User::Authenticatable)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**When to extract a concern:**
|
|
52
|
+
- Behavior reused across 2+ models → shared concern
|
|
53
|
+
- Model file exceeds ~100 lines → model-specific concern
|
|
54
|
+
- Logical grouping of related methods → named concern
|
|
55
|
+
|
|
56
|
+
### Service Objects (When Needed)
|
|
57
|
+
Use plain Ruby objects in `app/services/` for:
|
|
58
|
+
- Multi-model operations (CreateOrderWithPayment)
|
|
59
|
+
- External API integrations (StripeChargeService)
|
|
60
|
+
- Complex business processes spanning multiple steps
|
|
61
|
+
|
|
62
|
+
**Don't use for:** Simple CRUD, single-model operations, or anything a model method handles.
|
|
63
|
+
|
|
64
|
+
### Presenter Pattern
|
|
65
|
+
Plain Ruby classes for complex view logic:
|
|
66
|
+
```ruby
|
|
67
|
+
# app/models/dashboard_presenter.rb (NOT app/presenters/)
|
|
68
|
+
class DashboardPresenter
|
|
69
|
+
include ActionView::Helpers::TagHelper
|
|
70
|
+
|
|
71
|
+
def initialize(user)
|
|
72
|
+
@user = user
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def greeting
|
|
76
|
+
"Welcome, #{@user.name}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### RESTful Resource Design
|
|
82
|
+
- Prefer creating new controllers over adding custom actions
|
|
83
|
+
- `POST /messages/:id/archive` → `ArchivesController#create`
|
|
84
|
+
- Nest resources max 1 level: `/posts/:post_id/comments`
|
|
85
|
+
- Use `concerns` in routes for shared resource patterns
|
|
86
|
+
|
|
87
|
+
### Current Attributes
|
|
88
|
+
```ruby
|
|
89
|
+
# app/models/current.rb
|
|
90
|
+
class Current < ActiveSupport::CurrentAttributes
|
|
91
|
+
attribute :user, :session, :account
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
Set in `ApplicationController`, access everywhere. No parameter passing for auth context.
|
|
95
|
+
|
|
96
|
+
</architecture_patterns>
|
|
97
|
+
|
|
98
|
+
<common_pitfalls>
|
|
99
|
+
|
|
100
|
+
## Common Rails Pitfalls (with Prevention)
|
|
101
|
+
|
|
102
|
+
### 1. N+1 Queries
|
|
103
|
+
**Problem:** Loading associated records in a loop.
|
|
104
|
+
**Prevention:** Use `includes`, `preload`, or `eager_load` in controllers. Add `strict_loading` to models in development.
|
|
105
|
+
```ruby
|
|
106
|
+
# Bad
|
|
107
|
+
@posts = Post.all # then post.comments in view
|
|
108
|
+
|
|
109
|
+
# Good
|
|
110
|
+
@posts = Post.includes(:comments, :author).all
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 2. Missing Database Indexes
|
|
114
|
+
**Prevention:** Always add indexes for:
|
|
115
|
+
- Foreign keys (`add_index :posts, :user_id`)
|
|
116
|
+
- Columns used in `where` clauses
|
|
117
|
+
- Columns used in `order` clauses
|
|
118
|
+
- Unique constraints (`add_index :users, :email, unique: true`)
|
|
119
|
+
|
|
120
|
+
### 3. Mass Assignment Vulnerabilities
|
|
121
|
+
**Prevention:** Always use `strong_parameters` in controllers.
|
|
122
|
+
```ruby
|
|
123
|
+
def post_params
|
|
124
|
+
params.require(:post).permit(:title, :body, :published)
|
|
125
|
+
end
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 4. Callback Hell
|
|
129
|
+
**Prevention:** Limit callbacks to:
|
|
130
|
+
- `before_validation` for normalization (strip whitespace, downcase email)
|
|
131
|
+
- `after_create_commit` for async side effects (send email, broadcast)
|
|
132
|
+
- Avoid `after_save` chains that trigger cascading updates
|
|
133
|
+
|
|
134
|
+
### 5. Fat Controllers
|
|
135
|
+
**Prevention:** Controllers should only:
|
|
136
|
+
1. Authenticate/authorize
|
|
137
|
+
2. Load/build the resource
|
|
138
|
+
3. Call save/update/destroy
|
|
139
|
+
4. Respond with redirect or render
|
|
140
|
+
|
|
141
|
+
### 6. Missing Validations
|
|
142
|
+
**Prevention:** Validate at model level, not just in forms:
|
|
143
|
+
- Presence on required fields
|
|
144
|
+
- Uniqueness with database-level constraint
|
|
145
|
+
- Format for emails, URLs, phone numbers
|
|
146
|
+
- Numericality for quantities, prices
|
|
147
|
+
|
|
148
|
+
### 7. Unscoped Queries (Multi-tenancy)
|
|
149
|
+
**Prevention:** Always scope queries to current user/account:
|
|
150
|
+
```ruby
|
|
151
|
+
# Bad
|
|
152
|
+
Post.find(params[:id])
|
|
153
|
+
|
|
154
|
+
# Good
|
|
155
|
+
Current.user.posts.find(params[:id])
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 8. Missing Error Handling
|
|
159
|
+
**Prevention:** Add `rescue_from` in `ApplicationController`:
|
|
160
|
+
```ruby
|
|
161
|
+
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
|
162
|
+
rescue_from ActionController::ParameterMissing, with: :bad_request
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 9. Synchronous External Calls
|
|
166
|
+
**Prevention:** Always use background jobs for:
|
|
167
|
+
- Sending emails
|
|
168
|
+
- Calling external APIs
|
|
169
|
+
- Processing uploads
|
|
170
|
+
- Generating reports
|
|
171
|
+
|
|
172
|
+
### 10. Missing CSRF Protection
|
|
173
|
+
**Prevention:** Rails enables CSRF by default. Don't disable `protect_from_forgery`. For API endpoints, use token auth instead.
|
|
174
|
+
|
|
175
|
+
</common_pitfalls>
|
|
176
|
+
|
|
177
|
+
<testing_patterns>
|
|
178
|
+
|
|
179
|
+
## Rails Testing Patterns (Minitest)
|
|
180
|
+
|
|
181
|
+
### Test Organization
|
|
182
|
+
```
|
|
183
|
+
test/
|
|
184
|
+
models/ # Unit tests for models
|
|
185
|
+
controllers/ # Integration tests for request/response
|
|
186
|
+
system/ # Browser-based end-to-end tests
|
|
187
|
+
helpers/ # Helper method tests
|
|
188
|
+
jobs/ # Background job tests
|
|
189
|
+
mailers/ # Mailer tests
|
|
190
|
+
fixtures/ # YAML test data
|
|
191
|
+
test_helper.rb # Shared setup
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Fixtures Over Factories
|
|
195
|
+
```yaml
|
|
196
|
+
# test/fixtures/users.yml
|
|
197
|
+
alice:
|
|
198
|
+
name: Alice
|
|
199
|
+
email: alice@example.com
|
|
200
|
+
password_digest: <%= BCrypt::Password.create('password') %>
|
|
201
|
+
|
|
202
|
+
bob:
|
|
203
|
+
name: Bob
|
|
204
|
+
email: bob@example.com
|
|
205
|
+
password_digest: <%= BCrypt::Password.create('password') %>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Why fixtures:** Faster (loaded once per test suite), declarative, Rails-native, no external gem needed.
|
|
209
|
+
|
|
210
|
+
### Model Test Pattern
|
|
211
|
+
```ruby
|
|
212
|
+
class UserTest < ActiveSupport::TestCase
|
|
213
|
+
setup do
|
|
214
|
+
Current.session = sessions(:alice_session) # Always set Current context
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
test "validates email presence" do
|
|
218
|
+
user = User.new(name: "Test")
|
|
219
|
+
|
|
220
|
+
assert_not user.valid?
|
|
221
|
+
assert_includes user.errors[:email], "can't be blank"
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
test "creates user with valid attributes" do
|
|
225
|
+
assert_difference "User.count", 1 do
|
|
226
|
+
User.create!(name: "New", email: "new@example.com", password: "password")
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Controller Test Pattern (Integration)
|
|
233
|
+
```ruby
|
|
234
|
+
class PostsControllerTest < ActionDispatch::IntegrationTest
|
|
235
|
+
setup do
|
|
236
|
+
@user = users(:alice)
|
|
237
|
+
sign_in @user # Helper method
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
test "index returns posts" do
|
|
241
|
+
get posts_url
|
|
242
|
+
|
|
243
|
+
assert_response :success
|
|
244
|
+
assert_select "h2", posts(:first).title
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
test "create redirects on success" do
|
|
248
|
+
assert_difference "Post.count", 1 do
|
|
249
|
+
post posts_url, params: { post: { title: "New", body: "Content" } }
|
|
250
|
+
end
|
|
251
|
+
assert_redirected_to post_url(Post.last)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### System Test Pattern
|
|
257
|
+
```ruby
|
|
258
|
+
class UserFlowsTest < ApplicationSystemTestCase
|
|
259
|
+
test "user can sign up and create a post" do
|
|
260
|
+
visit new_registration_url
|
|
261
|
+
fill_in "Name", with: "Test User"
|
|
262
|
+
fill_in "Email", with: "test@example.com"
|
|
263
|
+
fill_in "Password", with: "password123"
|
|
264
|
+
click_on "Sign up"
|
|
265
|
+
|
|
266
|
+
assert_text "Welcome, Test User"
|
|
267
|
+
|
|
268
|
+
click_on "New Post"
|
|
269
|
+
fill_in "Title", with: "My First Post"
|
|
270
|
+
fill_in "Body", with: "Hello world"
|
|
271
|
+
click_on "Create Post"
|
|
272
|
+
|
|
273
|
+
assert_text "My First Post"
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Key Testing Conventions
|
|
279
|
+
- Use `assert_difference` for state changes, not just boolean checks
|
|
280
|
+
- Set `Current.session` in setup blocks for multi-tenancy
|
|
281
|
+
- Test happy path and one key failure path per method
|
|
282
|
+
- Use `assert_select` for HTML assertions in controller tests
|
|
283
|
+
- Run `bin/rails test` (not `rspec`) for the full suite
|
|
284
|
+
|
|
285
|
+
</testing_patterns>
|
|
286
|
+
|
|
287
|
+
<domain_templates>
|
|
288
|
+
|
|
289
|
+
## Rails Task Templates for Planning
|
|
290
|
+
|
|
291
|
+
These templates help the planner agent decompose common Rails work into well-structured tasks.
|
|
292
|
+
|
|
293
|
+
### Add Model
|
|
294
|
+
```
|
|
295
|
+
Tasks:
|
|
296
|
+
1. Create migration + model with validations, associations, and concerns
|
|
297
|
+
Files: db/migrate/xxx_create_[model].rb, app/models/[model].rb
|
|
298
|
+
2. Add model tests + fixtures
|
|
299
|
+
Files: test/models/[model]_test.rb, test/fixtures/[model].yml
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Add Controller (with views)
|
|
303
|
+
```
|
|
304
|
+
Tasks:
|
|
305
|
+
1. Add routes + controller with RESTful actions
|
|
306
|
+
Files: config/routes.rb, app/controllers/[model]_controller.rb
|
|
307
|
+
2. Add views (index, show, new, edit, _form partial)
|
|
308
|
+
Files: app/views/[model]/*.html.erb
|
|
309
|
+
3. Add controller tests
|
|
310
|
+
Files: test/controllers/[model]_controller_test.rb
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Add Authentication
|
|
314
|
+
```
|
|
315
|
+
Tasks:
|
|
316
|
+
1. Generate auth scaffold (Rails 8: bin/rails generate authentication)
|
|
317
|
+
or: Add User model with has_secure_password, Session model, SessionsController
|
|
318
|
+
Files: app/models/user.rb, app/models/session.rb, app/controllers/sessions_controller.rb
|
|
319
|
+
2. Add auth views (login, registration)
|
|
320
|
+
Files: app/views/sessions/*.html.erb, app/views/registrations/*.html.erb
|
|
321
|
+
3. Add auth tests
|
|
322
|
+
Files: test/controllers/sessions_controller_test.rb, test/models/user_test.rb
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Add Background Job
|
|
326
|
+
```
|
|
327
|
+
Tasks:
|
|
328
|
+
1. Create job class + model method it delegates to
|
|
329
|
+
Files: app/jobs/[name]_job.rb, app/models/[model].rb
|
|
330
|
+
2. Add job tests
|
|
331
|
+
Files: test/jobs/[name]_job_test.rb
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Add Mailer
|
|
335
|
+
```
|
|
336
|
+
Tasks:
|
|
337
|
+
1. Create mailer + views
|
|
338
|
+
Files: app/mailers/[name]_mailer.rb, app/views/[name]_mailer/*.html.erb
|
|
339
|
+
2. Add mailer tests
|
|
340
|
+
Files: test/mailers/[name]_mailer_test.rb
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Add Turbo/Hotwire Feature
|
|
344
|
+
```
|
|
345
|
+
Tasks:
|
|
346
|
+
1. Add Turbo Frame wrapping to target views + controller turbo_stream responses
|
|
347
|
+
Files: app/views/[model]/*.html.erb, app/controllers/[model]_controller.rb
|
|
348
|
+
Conventions: 422 for validation errors, 303 for redirects, dom_id for frame IDs
|
|
349
|
+
2. Add Stimulus controller (if interactive behavior needed)
|
|
350
|
+
Files: app/javascript/controllers/[name]_controller.js
|
|
351
|
+
Conventions: static values/targets/outlets first, connect/disconnect symmetry
|
|
352
|
+
3. Add Turbo Stream broadcasts (if real-time updates needed)
|
|
353
|
+
Files: app/models/[model].rb (after_create_commit callbacks)
|
|
354
|
+
Conventions: prefer default stream actions, broadcast_append_to/replace_to
|
|
355
|
+
4. Add system test for Turbo/Stimulus behavior
|
|
356
|
+
Files: test/system/[feature]_test.rb
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
</domain_templates>
|
|
360
|
+
|
|
361
|
+
<known_domains>
|
|
362
|
+
|
|
363
|
+
## Known Rails Domains (Skip Research)
|
|
364
|
+
|
|
365
|
+
These domains are well-understood in Rails and don't need web research:
|
|
366
|
+
|
|
367
|
+
| Domain | Key Patterns | Research Needed? |
|
|
368
|
+
|--------|-------------|-----------------|
|
|
369
|
+
| Models & Migrations | ActiveRecord, validations, associations, concerns | No |
|
|
370
|
+
| Controllers & Routes | RESTful resources, before_action, strong params | No |
|
|
371
|
+
| Views & Templates | ERB, partials, layouts, content_for | No |
|
|
372
|
+
| Authentication | has_secure_password, Devise, Rails 8 auth generator | No |
|
|
373
|
+
| Authorization | Pundit, CanCanCan, or hand-rolled | No |
|
|
374
|
+
| Background Jobs | Solid Queue, ActiveJob | No |
|
|
375
|
+
| Email | Action Mailer, letter_opener | No |
|
|
376
|
+
| File Uploads | Active Storage | No |
|
|
377
|
+
| Real-time | Action Cable, Turbo Streams | No |
|
|
378
|
+
| Testing | Minitest, fixtures, system tests | No |
|
|
379
|
+
| API Mode | Jbuilder, API-only controllers, token auth | No |
|
|
380
|
+
| Caching | Fragment caching, Russian doll, Solid Cache | No |
|
|
381
|
+
| Search | pg_search, Ransack | Maybe (depends on complexity) |
|
|
382
|
+
| Payments | Stripe, Pay gem | Yes (API details change) |
|
|
383
|
+
| External APIs | Third-party integrations | Yes (API-specific) |
|
|
384
|
+
| Novel Gems | Unfamiliar libraries | Yes |
|
|
385
|
+
| Infrastructure | Docker, Kamal, deployment | Maybe |
|
|
386
|
+
|
|
387
|
+
**Heuristic:** If all phase requirements map to "No" domains, skip research automatically. If any requirement maps to "Yes", consider `--research` flag.
|
|
388
|
+
|
|
389
|
+
</known_domains>
|
|
390
|
+
|
|
391
|
+
</rails_conventions>
|
|
@@ -38,6 +38,11 @@ patterns-established:
|
|
|
38
38
|
- "Pattern 1: description"
|
|
39
39
|
- "Pattern 2: description"
|
|
40
40
|
|
|
41
|
+
requirements_covered:
|
|
42
|
+
- id: "REQ-ID"
|
|
43
|
+
description: "Requirement description"
|
|
44
|
+
evidence: "File/class implementing it"
|
|
45
|
+
|
|
41
46
|
# Metrics
|
|
42
47
|
duration: Xmin
|
|
43
48
|
completed: YYYY-MM-DD
|
|
@@ -60,6 +65,12 @@ completed: YYYY-MM-DD
|
|
|
60
65
|
- [Second key accomplishment]
|
|
61
66
|
- [Third if applicable]
|
|
62
67
|
|
|
68
|
+
## Requirements Covered
|
|
69
|
+
| REQ-ID | Requirement | Evidence |
|
|
70
|
+
|--------|-------------|----------|
|
|
71
|
+
|
|
72
|
+
[Omit this section if no REQUIREMENTS.md exists or no requirements map to this phase/plan]
|
|
73
|
+
|
|
63
74
|
## Task Commits
|
|
64
75
|
|
|
65
76
|
Each task was committed atomically:
|