ariadna 1.1.3 → 1.2.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.
- checksums.yaml +4 -4
- data/data/agents/ariadna-backend-executor.md +1 -1
- data/data/agents/ariadna-planner.md +29 -1
- data/data/agents/ariadna-test-executor.md +1 -1
- data/data/ariadna/references/rails-conventions.md +384 -0
- data/data/ariadna/templates/codebase/architecture.md +3 -9
- data/data/ariadna/templates/codebase/concerns.md +2 -2
- data/data/ariadna/templates/codebase/conventions.md +1 -1
- data/data/ariadna/templates/codebase/stack.md +1 -2
- data/data/ariadna/templates/research-project/ARCHITECTURE.md +60 -1
- data/data/ariadna/templates/research-project/PITFALLS.md +51 -2
- data/data/ariadna/templates/research-project/STACK.md +23 -22
- data/data/ariadna/templates/research-project/SUMMARY.md +2 -2
- data/data/ariadna/workflows/new-project.md +52 -129
- data/data/ariadna/workflows/plan-phase.md +100 -49
- data/data/commands/ariadna/new-project.md +8 -6
- data/data/commands/ariadna/plan-phase.md +9 -7
- data/data/guides/backend.md +5 -52
- data/data/templates.md +2 -2
- data/lib/ariadna/tools/config_manager.rb +3 -2
- data/lib/ariadna/tools/frontmatter.rb +2 -0
- data/lib/ariadna/tools/phase_manager.rb +1 -0
- 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: a59ce08ab4d7f1165dd59dac034ac04e5725263a3022bebbd2c3c39fdb0a3c23
|
|
4
|
+
data.tar.gz: 2eb175ba24a25c5114e3b76f83bbfef0275a21dc114f00d7376390508cb54a87
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 11f2127685615ea902f97bfc9fc813e20e74f354b055672568d39552d3d551d31896ba73b5ad3434d1ac84dc6d593f8d385818e78fc7cae24844f45720558f80
|
|
7
|
+
data.tar.gz: cec523e574d6182711229ddf5fa7519929f3c9fb9a144a0eb4928cf46a24d4761e9f718cf3678cf2dde812f9cd655647ca2c12776fcf29aa526831ad9df017a9
|
|
@@ -23,7 +23,7 @@ Load and follow the project's backend guide for domain-specific patterns:
|
|
|
23
23
|
- **Models & Concerns:** Concern-driven architecture, intention-revealing APIs, smart association defaults
|
|
24
24
|
- **Controllers:** Thin controllers delegating to rich models, RESTful resource nesting
|
|
25
25
|
- **Jobs:** Ultra-thin jobs with _now/_later pattern, multi-tenancy context
|
|
26
|
-
- **Migrations:**
|
|
26
|
+
- **Migrations:** Proper foreign key references
|
|
27
27
|
- **Configuration:** Rails conventions, initializers, routing
|
|
28
28
|
|
|
29
29
|
**When executing backend tasks:**
|
|
@@ -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
|
|
|
@@ -180,7 +208,7 @@ Each task: **15-60 minutes** Claude execution time.
|
|
|
180
208
|
| "Create the API" | "Create POST /projects endpoint in ProjectsController#create accepting {name, description}, validates name length 3-50 chars, returns 201 with project JSON" |
|
|
181
209
|
| "Style the dashboard" | "Add CSS classes to dashboard view: grid layout (3 cols on lg via media query, 1 on mobile), card shadows via --shadow variable, hover states on action buttons per style guide" |
|
|
182
210
|
| "Handle errors" | "Add rescue_from in ApplicationController, render JSON errors on 4xx/5xx, show flash messages on server-rendered pages" |
|
|
183
|
-
| "Set up the database" | "Add User and Project models
|
|
211
|
+
| "Set up the database" | "Add User and Project models, email unique constraint, timestamps, run rails db:migrate" |
|
|
184
212
|
|
|
185
213
|
**Test:** Could a different Claude instance execute without asking clarifying questions? If not, add specificity.
|
|
186
214
|
|
|
@@ -21,7 +21,7 @@ Load and follow the project's testing guide for domain-specific patterns:
|
|
|
21
21
|
|
|
22
22
|
**Focus areas:**
|
|
23
23
|
- **Minitest conventions:** `ActiveSupport::TestCase` for models, `ActionDispatch::IntegrationTest` for controllers
|
|
24
|
-
- **Fixtures:** YAML fixtures for deterministic test data
|
|
24
|
+
- **Fixtures:** YAML fixtures for deterministic test data
|
|
25
25
|
- **Current context:** Always set `Current.session = sessions(:name)` in setup blocks
|
|
26
26
|
- **assert_difference:** Use for state changes, nest for multiple record types
|
|
27
27
|
- **Testing patterns:** Model tests for business logic, controller tests for delegation, job tests for enqueuing
|
|
@@ -0,0 +1,384 @@
|
|
|
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
|
+
assert_not user.valid?
|
|
220
|
+
assert_includes user.errors[:email], "can't be blank"
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
test "creates user with valid attributes" do
|
|
224
|
+
assert_difference "User.count", 1 do
|
|
225
|
+
User.create!(name: "New", email: "new@example.com", password: "password")
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Controller Test Pattern (Integration)
|
|
232
|
+
```ruby
|
|
233
|
+
class PostsControllerTest < ActionDispatch::IntegrationTest
|
|
234
|
+
setup do
|
|
235
|
+
@user = users(:alice)
|
|
236
|
+
sign_in @user # Helper method
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
test "index returns posts" do
|
|
240
|
+
get posts_url
|
|
241
|
+
assert_response :success
|
|
242
|
+
assert_select "h2", posts(:first).title
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
test "create redirects on success" do
|
|
246
|
+
assert_difference "Post.count", 1 do
|
|
247
|
+
post posts_url, params: { post: { title: "New", body: "Content" } }
|
|
248
|
+
end
|
|
249
|
+
assert_redirected_to post_url(Post.last)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### System Test Pattern
|
|
255
|
+
```ruby
|
|
256
|
+
class UserFlowsTest < ApplicationSystemTestCase
|
|
257
|
+
test "user can sign up and create a post" do
|
|
258
|
+
visit new_registration_url
|
|
259
|
+
fill_in "Name", with: "Test User"
|
|
260
|
+
fill_in "Email", with: "test@example.com"
|
|
261
|
+
fill_in "Password", with: "password123"
|
|
262
|
+
click_on "Sign up"
|
|
263
|
+
|
|
264
|
+
assert_text "Welcome, Test User"
|
|
265
|
+
|
|
266
|
+
click_on "New Post"
|
|
267
|
+
fill_in "Title", with: "My First Post"
|
|
268
|
+
fill_in "Body", with: "Hello world"
|
|
269
|
+
click_on "Create Post"
|
|
270
|
+
|
|
271
|
+
assert_text "My First Post"
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Key Testing Conventions
|
|
277
|
+
- Use `assert_difference` for state changes, not just boolean checks
|
|
278
|
+
- Set `Current.session` in setup blocks for multi-tenancy
|
|
279
|
+
- Test happy path and one key failure path per method
|
|
280
|
+
- Use `assert_select` for HTML assertions in controller tests
|
|
281
|
+
- Run `bin/rails test` (not `rspec`) for the full suite
|
|
282
|
+
|
|
283
|
+
</testing_patterns>
|
|
284
|
+
|
|
285
|
+
<domain_templates>
|
|
286
|
+
|
|
287
|
+
## Rails Task Templates for Planning
|
|
288
|
+
|
|
289
|
+
These templates help the planner agent decompose common Rails work into well-structured tasks.
|
|
290
|
+
|
|
291
|
+
### Add Model
|
|
292
|
+
```
|
|
293
|
+
Tasks:
|
|
294
|
+
1. Create migration + model with validations, associations, and concerns
|
|
295
|
+
Files: db/migrate/xxx_create_[model].rb, app/models/[model].rb
|
|
296
|
+
2. Add model tests + fixtures
|
|
297
|
+
Files: test/models/[model]_test.rb, test/fixtures/[model].yml
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Add Controller (with views)
|
|
301
|
+
```
|
|
302
|
+
Tasks:
|
|
303
|
+
1. Add routes + controller with RESTful actions
|
|
304
|
+
Files: config/routes.rb, app/controllers/[model]_controller.rb
|
|
305
|
+
2. Add views (index, show, new, edit, _form partial)
|
|
306
|
+
Files: app/views/[model]/*.html.erb
|
|
307
|
+
3. Add controller tests
|
|
308
|
+
Files: test/controllers/[model]_controller_test.rb
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Add Authentication
|
|
312
|
+
```
|
|
313
|
+
Tasks:
|
|
314
|
+
1. Generate auth scaffold (Rails 8: bin/rails generate authentication)
|
|
315
|
+
or: Add User model with has_secure_password, Session model, SessionsController
|
|
316
|
+
Files: app/models/user.rb, app/models/session.rb, app/controllers/sessions_controller.rb
|
|
317
|
+
2. Add auth views (login, registration)
|
|
318
|
+
Files: app/views/sessions/*.html.erb, app/views/registrations/*.html.erb
|
|
319
|
+
3. Add auth tests
|
|
320
|
+
Files: test/controllers/sessions_controller_test.rb, test/models/user_test.rb
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Add Background Job
|
|
324
|
+
```
|
|
325
|
+
Tasks:
|
|
326
|
+
1. Create job class + model method it delegates to
|
|
327
|
+
Files: app/jobs/[name]_job.rb, app/models/[model].rb
|
|
328
|
+
2. Add job tests
|
|
329
|
+
Files: test/jobs/[name]_job_test.rb
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Add Mailer
|
|
333
|
+
```
|
|
334
|
+
Tasks:
|
|
335
|
+
1. Create mailer + views
|
|
336
|
+
Files: app/mailers/[name]_mailer.rb, app/views/[name]_mailer/*.html.erb
|
|
337
|
+
2. Add mailer tests
|
|
338
|
+
Files: test/mailers/[name]_mailer_test.rb
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Add Turbo/Hotwire Feature
|
|
342
|
+
```
|
|
343
|
+
Tasks:
|
|
344
|
+
1. Add Turbo Frame wrapping + controller turbo_stream response
|
|
345
|
+
Files: app/views/[model]/*.html.erb, app/controllers/[model]_controller.rb
|
|
346
|
+
2. Add Stimulus controller (if interactive behavior needed)
|
|
347
|
+
Files: app/javascript/controllers/[name]_controller.js
|
|
348
|
+
3. Add system test for real-time behavior
|
|
349
|
+
Files: test/system/[feature]_test.rb
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
</domain_templates>
|
|
353
|
+
|
|
354
|
+
<known_domains>
|
|
355
|
+
|
|
356
|
+
## Known Rails Domains (Skip Research)
|
|
357
|
+
|
|
358
|
+
These domains are well-understood in Rails and don't need web research:
|
|
359
|
+
|
|
360
|
+
| Domain | Key Patterns | Research Needed? |
|
|
361
|
+
|--------|-------------|-----------------|
|
|
362
|
+
| Models & Migrations | ActiveRecord, validations, associations, concerns | No |
|
|
363
|
+
| Controllers & Routes | RESTful resources, before_action, strong params | No |
|
|
364
|
+
| Views & Templates | ERB, partials, layouts, content_for | No |
|
|
365
|
+
| Authentication | has_secure_password, Devise, Rails 8 auth generator | No |
|
|
366
|
+
| Authorization | Pundit, CanCanCan, or hand-rolled | No |
|
|
367
|
+
| Background Jobs | Solid Queue, ActiveJob | No |
|
|
368
|
+
| Email | Action Mailer, letter_opener | No |
|
|
369
|
+
| File Uploads | Active Storage | No |
|
|
370
|
+
| Real-time | Action Cable, Turbo Streams | No |
|
|
371
|
+
| Testing | Minitest, fixtures, system tests | No |
|
|
372
|
+
| API Mode | Jbuilder, API-only controllers, token auth | No |
|
|
373
|
+
| Caching | Fragment caching, Russian doll, Solid Cache | No |
|
|
374
|
+
| Search | pg_search, Ransack | Maybe (depends on complexity) |
|
|
375
|
+
| Payments | Stripe, Pay gem | Yes (API details change) |
|
|
376
|
+
| External APIs | Third-party integrations | Yes (API-specific) |
|
|
377
|
+
| Novel Gems | Unfamiliar libraries | Yes |
|
|
378
|
+
| Infrastructure | Docker, Kamal, deployment | Maybe |
|
|
379
|
+
|
|
380
|
+
**Heuristic:** If all phase requirements map to "No" domains, skip research automatically. If any requirement maps to "Yes", consider `--research` flag.
|
|
381
|
+
|
|
382
|
+
</known_domains>
|
|
383
|
+
|
|
384
|
+
</rails_conventions>
|
|
@@ -17,7 +17,7 @@ Template for `.planning/codebase/ARCHITECTURE.md` - captures conceptual code org
|
|
|
17
17
|
|
|
18
18
|
**Overall:** [Pattern name: e.g., "Rails Monolith", "Rails API-only", "Rails + Hotwire", "Rails Engine-based"]
|
|
19
19
|
|
|
20
|
-
**Multi-Tenancy:** [e.g., "Path-based with CurrentAttributes", "Subdomain-based", "
|
|
20
|
+
**Multi-Tenancy:** [e.g., "Path-based with CurrentAttributes", "Subdomain-based", "session based", "Single-tenant", "None"]
|
|
21
21
|
|
|
22
22
|
**Key Characteristics:**
|
|
23
23
|
- [Characteristic 1: e.g., "Server-rendered with Turbo"]
|
|
@@ -277,7 +277,7 @@ Template for `.planning/codebase/ARCHITECTURE.md` - captures conceptual code org
|
|
|
277
277
|
**Key Domain Models:**
|
|
278
278
|
- `Account` — Tenant root. All data scoped to an account
|
|
279
279
|
- `Board` — Project workspace containing cards, columns, and access rules
|
|
280
|
-
- `Card` — Primary work item. Most concern-composed model (20+ concerns).
|
|
280
|
+
- `Card` — Primary work item. Most concern-composed model (20+ concerns).
|
|
281
281
|
- `Event` — Audit trail record. Polymorphic `eventable`, JSON `particulars` for action-specific data
|
|
282
282
|
- `User` — Account member with role-based permissions. Resolved from `Current.session` → `identity` → `user`
|
|
283
283
|
|
|
@@ -357,11 +357,6 @@ Template for `.planning/codebase/ARCHITECTURE.md` - captures conceptual code org
|
|
|
357
357
|
- Location: `app/models/` subdirectories — `User::Filtering`, `Event::Description`, `User::DayTimeline`
|
|
358
358
|
- Pattern: Constructor injection, memoized collections (`@boards ||= ...`), boolean methods for conditional display (`show_tags?`), cache keys for fragment caching. Some include `ActionView::Helpers::TagHelper` for HTML generation. Instantiated via controller concerns or factory methods on models (`event.description_for(user)`)
|
|
359
359
|
|
|
360
|
-
**Pundit Policies:**
|
|
361
|
-
- Purpose: Authorize user actions on resources
|
|
362
|
-
- Examples: `ProjectPolicy`, `TaskPolicy`, `MembershipPolicy`
|
|
363
|
-
- Pattern: Policy class per model with `?` predicate methods
|
|
364
|
-
|
|
365
360
|
## Multi-Tenancy & Current Context
|
|
366
361
|
|
|
367
362
|
**Approach:** Path-based — account slug extracted from URL path by `AccountSlug::Extractor` middleware. Slug moves from `PATH_INFO` to `SCRIPT_NAME`. No subdomain configuration needed.
|
|
@@ -400,7 +395,7 @@ Template for `.planning/codebase/ARCHITECTURE.md` - captures conceptual code org
|
|
|
400
395
|
|
|
401
396
|
**Patterns:**
|
|
402
397
|
- `rescue_from ActiveRecord::RecordNotFound` → 404 page
|
|
403
|
-
- `rescue_from
|
|
398
|
+
- `rescue_from NotAuthorizedError` → 403 or redirect with flash
|
|
404
399
|
- Model validation errors re-render form with `@model.errors`
|
|
405
400
|
- Service objects return `Result` structs (success/failure) instead of raising
|
|
406
401
|
- Jobs use `retry_on` for transient failures, `discard_on` for permanent ones
|
|
@@ -421,7 +416,6 @@ Template for `.planning/codebase/ARCHITECTURE.md` - captures conceptual code org
|
|
|
421
416
|
- `require_authentication` filter on all non-public controllers
|
|
422
417
|
|
|
423
418
|
**Authorization:**
|
|
424
|
-
- Pundit policies per resource
|
|
425
419
|
- `authorize` calls in controller actions
|
|
426
420
|
- Scoped queries via `policy_scope`
|
|
427
421
|
|
|
@@ -190,8 +190,8 @@ Template for `.planning/codebase/CONCERNS.md` - captures known issues and areas
|
|
|
190
190
|
**Missing authorization checks on nested resources:**
|
|
191
191
|
- Risk: Card comments endpoint does not verify user has access to the parent board
|
|
192
192
|
- Files: `app/controllers/comments_controller.rb`, missing `authorize @comment` call
|
|
193
|
-
- Current mitigation:
|
|
194
|
-
- Recommendations: Add
|
|
193
|
+
- Current mitigation: Denormalise tables so all include account_id and rely on `Current.account` scope, but no explicit check on board access.
|
|
194
|
+
- Recommendations: Add `before_action` scope check.
|
|
195
195
|
|
|
196
196
|
**Unscoped queries leaking tenant data:**
|
|
197
197
|
- Risk: `Admin::ReportsController` uses `Card.where(created_at: range)` without `Current.account` scope
|
|
@@ -251,7 +251,7 @@ end
|
|
|
251
251
|
- Model validation errors re-render form with `@model.errors`
|
|
252
252
|
|
|
253
253
|
**Error Types:**
|
|
254
|
-
- Raise on authorization failures: `rescue_from
|
|
254
|
+
- Raise on authorization failures: `rescue_from NotAuthorizedError`
|
|
255
255
|
- Raise on missing records: `rescue_from ActiveRecord::RecordNotFound`
|
|
256
256
|
- Return `false`/`nil` for expected domain failures
|
|
257
257
|
- Jobs: `retry_on` for transient failures (network, timeouts), `discard_on ActiveRecord::RecordNotFound`
|
|
@@ -123,9 +123,8 @@ Template for `.planning/codebase/STACK.md` - captures the technology foundation.
|
|
|
123
123
|
|
|
124
124
|
**Critical:**
|
|
125
125
|
- authentication (built-in) — Session-based auth
|
|
126
|
-
-
|
|
126
|
+
- authorization - custom implementation (no gem) — Role-based access control, pundit
|
|
127
127
|
- solid_queue — Background jobs (Rails 8 default)
|
|
128
|
-
- stripe — Payment processing
|
|
129
128
|
|
|
130
129
|
**Infrastructure:**
|
|
131
130
|
- sqlite3 — SQLite adapter (Rails default)
|
|
@@ -164,7 +164,57 @@ test/ # [test framework: Minitest (default) or spec/ if RSp
|
|
|
164
164
|
### Authentication and Authorization
|
|
165
165
|
|
|
166
166
|
**Authentication:** [Rails authentication generator / has_secure_password / custom / other]
|
|
167
|
-
**Authorization:** [
|
|
167
|
+
**Authorization:** [Custom / Pundit / CanCanCan / Action Policy / other]
|
|
168
|
+
|
|
169
|
+
### Internationalization (I18n)
|
|
170
|
+
|
|
171
|
+
**Configuration:**
|
|
172
|
+
- Default locale: [discovered from `config.i18n.default_locale`]
|
|
173
|
+
- Available locales: [discovered from `config.i18n.available_locales`]
|
|
174
|
+
- Fallback chain: [discovered from `config.i18n.fallbacks`]
|
|
175
|
+
|
|
176
|
+
**Locale file organization:**
|
|
177
|
+
```
|
|
178
|
+
config/locales/
|
|
179
|
+
├── [default locale].yml # [application-wide defaults]
|
|
180
|
+
├── activerecord.[lang].yml # [model and attribute translations]
|
|
181
|
+
├── [feature].[lang].yml # [per-feature locale files if present]
|
|
182
|
+
└── [additional locale files discovered]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**ActiveRecord translations:**
|
|
186
|
+
```yaml
|
|
187
|
+
# config/locales/activerecord.[lang].yml
|
|
188
|
+
[lang]:
|
|
189
|
+
activerecord:
|
|
190
|
+
models:
|
|
191
|
+
[model]: [translated model name]
|
|
192
|
+
attributes:
|
|
193
|
+
[model]:
|
|
194
|
+
[attribute]: [translated attribute name]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Translation approach:**
|
|
198
|
+
|
|
199
|
+
| Context | Recommended Approach | What This Project Does |
|
|
200
|
+
|---------|---------------------|------------------------|
|
|
201
|
+
| Model names | `activerecord.models.*` — automatic lookup by Rails | [discovered approach] |
|
|
202
|
+
| Attribute names | `activerecord.attributes.*` — automatic lookup by `form.label`, validations, etc. | [discovered approach] |
|
|
203
|
+
| Form labels | `form.label :name` — resolves from `activerecord.attributes` automatically | [discovered approach] |
|
|
204
|
+
| Validation messages | `activerecord.errors.models.*` / `errors.messages.*` — automatic lookup | [discovered approach] |
|
|
205
|
+
| View text | Lazy lookup `t(".title")` or explicit `t("views.controller.action.title")` | [discovered approach] |
|
|
206
|
+
| Enum values | `activerecord.attributes.[model].[enum_attribute]/[value]` | [discovered approach] |
|
|
207
|
+
| Flash messages | Controller lazy lookup `t(".success")` or explicit keys | [discovered approach] |
|
|
208
|
+
| Mailer subjects | `I18n.t("mailer_name.action_name.subject")` — automatic from mailer class | [discovered approach] |
|
|
209
|
+
|
|
210
|
+
**CLDR / base locale data:**
|
|
211
|
+
- `rails-i18n` gem: [present/absent — provides date, time, currency, number formats for non-English locales]
|
|
212
|
+
- Custom date/time formats: [discovered in locale files or initializers]
|
|
213
|
+
|
|
214
|
+
**Example from codebase:**
|
|
215
|
+
```ruby
|
|
216
|
+
# [Brief code example showing the project's actual I18n usage pattern]
|
|
217
|
+
```
|
|
168
218
|
|
|
169
219
|
## Data Flow
|
|
170
220
|
|
|
@@ -377,4 +427,13 @@ Client receives → DOM update
|
|
|
377
427
|
- Note external API integration patterns and HTTP client choices
|
|
378
428
|
- Look for engine boundaries and module interfaces
|
|
379
429
|
|
|
430
|
+
**Internationalization (I18n):**
|
|
431
|
+
- Check `config/application.rb` for `i18n.default_locale`, `i18n.available_locales`, and `i18n.fallbacks`
|
|
432
|
+
- Inspect `config/locales/` file organization — per-model, per-feature, or flat structure
|
|
433
|
+
- Look for `activerecord.models.*` and `activerecord.attributes.*` keys in locale files — these power automatic lookup for model names, form labels, and validation messages
|
|
434
|
+
- Check whether form labels use automatic lookup (`form.label :name`) vs explicit `t()` calls — explicit calls duplicate what Rails provides for free
|
|
435
|
+
- Check Gemfile for `rails-i18n` gem — provides CLDR base data (dates, times, currency, numbers) for non-English locales
|
|
436
|
+
- Look for validation error message customization under `activerecord.errors.models.*`
|
|
437
|
+
- Check for lazy lookup usage in views (`t(".key")`) and controllers
|
|
438
|
+
|
|
380
439
|
</guidelines>
|