source_monitor 0.1.3 → 0.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/CHANGELOG.md +22 -0
- data/Gemfile.lock +1 -1
- data/app/assets/javascripts/source_monitor/application.js +4 -0
- data/app/assets/javascripts/source_monitor/controllers/confirm_navigation_controller.js +49 -0
- data/app/assets/javascripts/source_monitor/controllers/select_all_controller.js +36 -0
- data/app/controllers/source_monitor/import_sessions_controller.rb +791 -0
- data/app/controllers/source_monitor/sources_controller.rb +5 -36
- data/app/helpers/source_monitor/application_helper.rb +17 -0
- data/app/jobs/source_monitor/import_opml_job.rb +150 -0
- data/app/jobs/source_monitor/import_session_health_check_job.rb +93 -0
- data/app/models/source_monitor/import_history.rb +35 -0
- data/app/models/source_monitor/import_session.rb +34 -0
- data/app/views/source_monitor/import_sessions/_header.html.erb +12 -0
- data/app/views/source_monitor/import_sessions/_sidebar.html.erb +23 -0
- data/app/views/source_monitor/import_sessions/health_check/_progress.html.erb +20 -0
- data/app/views/source_monitor/import_sessions/health_check/_row.html.erb +44 -0
- data/app/views/source_monitor/import_sessions/show.html.erb +15 -0
- data/app/views/source_monitor/import_sessions/show.turbo_stream.erb +1 -0
- data/app/views/source_monitor/import_sessions/steps/_configure.html.erb +53 -0
- data/app/views/source_monitor/import_sessions/steps/_confirm.html.erb +121 -0
- data/app/views/source_monitor/import_sessions/steps/_health_check.html.erb +82 -0
- data/app/views/source_monitor/import_sessions/steps/_navigation.html.erb +29 -0
- data/app/views/source_monitor/import_sessions/steps/_preview.html.erb +172 -0
- data/app/views/source_monitor/import_sessions/steps/_upload.html.erb +42 -0
- data/app/views/source_monitor/sources/_form.html.erb +8 -138
- data/app/views/source_monitor/sources/_form_fields.html.erb +142 -0
- data/app/views/source_monitor/sources/_import_history_panel.html.erb +53 -0
- data/app/views/source_monitor/sources/index.html.erb +7 -1
- data/config/coverage_baseline.json +91 -15
- data/config/routes.rb +6 -0
- data/db/migrate/20251124090000_create_import_sessions.rb +18 -0
- data/db/migrate/20251124153000_add_health_fields_to_import_sessions.rb +14 -0
- data/db/migrate/20251125094500_create_import_histories.rb +19 -0
- data/lib/source_monitor/health/import_source_health_check.rb +55 -0
- data/lib/source_monitor/health.rb +1 -0
- data/lib/source_monitor/import_sessions/entry_normalizer.rb +30 -0
- data/lib/source_monitor/import_sessions/health_check_broadcaster.rb +103 -0
- data/lib/source_monitor/sources/params.rb +52 -0
- data/lib/source_monitor/version.rb +1 -1
- data/tasks/completed/codebase_audit_2025.md +1396 -0
- data/tasks/completed/engine-asset-configuration.md +203 -0
- data/tasks/completed/opml-import-wizard/opml-import-wizard-product-brief.md +58 -0
- data/tasks/completed/opml-import-wizard/opml-import-wizard-tech-brief.md +75 -0
- data/tasks/completed/opml-import-wizard/task-01/instructions.md +81 -0
- data/tasks/completed/opml-import-wizard/task-01/requirements.md +19 -0
- data/tasks/completed/opml-import-wizard/task-02/instructions.md +83 -0
- data/tasks/completed/opml-import-wizard/task-02/requirements.md +18 -0
- data/tasks/completed/opml-import-wizard/task-03/instructions.md +58 -0
- data/tasks/completed/opml-import-wizard/task-03/requirements.md +18 -0
- data/tasks/completed/opml-import-wizard/task-04/instructions.md +84 -0
- data/tasks/completed/opml-import-wizard/task-04/requirements.md +17 -0
- data/tasks/completed/opml-import-wizard/task-05/instructions.md +50 -0
- data/tasks/completed/opml-import-wizard/task-05/requirements.md +17 -0
- data/tasks/completed/opml-import-wizard/task-06/instructions.md +92 -0
- data/tasks/completed/opml-import-wizard/task-06/requirements.md +21 -0
- data/tasks/completed/phase_17_01_complexity_audit_2025-10-12.md +62 -0
- data/tasks/completed/phase_17_02_complexity_findings_2025-10-12.md +74 -0
- data/tasks/completed/phase_17_03_refactor_plan_2025-10-12.md +37 -0
- data/tasks/completed/phase_21_01_log_consolidation_2025-10-15.md +30 -0
- data/tasks/completed/release_checklist.md +23 -0
- data/tasks/completed/routes_refactor_evaluation.md +109 -0
- data/tasks/completed/source_monitor_rename_plan.md +70 -0
- data/tasks/completed/tasks.md +952 -0
- data/tasks/ideas.md +10 -0
- metadata +56 -3
- /data/tasks/{prd-setup-workflow-streamlining.md → completed/prd-setup-workflow-streamlining.md} +0 -0
- /data/tasks/{tasks-setup-workflow-streamlining.md → completed/tasks-setup-workflow-streamlining.md} +0 -0
|
@@ -0,0 +1,952 @@
|
|
|
1
|
+
# SourceMonitor Engine - Rails 8 Thin Slice TDD Development Roadmap
|
|
2
|
+
|
|
3
|
+
## Active Slice Tracker
|
|
4
|
+
|
|
5
|
+
- PRD: `tasks/prd-setup-workflow-streamlining.md`
|
|
6
|
+
- Task list: `tasks/tasks-setup-workflow-streamlining.md`
|
|
7
|
+
|
|
8
|
+
## Coverage Workflow
|
|
9
|
+
|
|
10
|
+
- Always run `bin/test-coverage` followed by `bin/check-diff-coverage` before pushing.
|
|
11
|
+
- When legitimate changes lower coverage, run `bin/update-coverage-baseline` and commit the refreshed `config/coverage_baseline.json` in the same branch.
|
|
12
|
+
- CI enforces these steps (diff coverage + setup test presence), so follow them locally to avoid failures.
|
|
13
|
+
|
|
14
|
+
## Phase 01: Minimal Engine Setup & Rails Integration
|
|
15
|
+
|
|
16
|
+
**Goal: Get engine mountable in host Rails 8 app immediately**
|
|
17
|
+
|
|
18
|
+
### 01.01 Generate Mountable Engine
|
|
19
|
+
|
|
20
|
+
- [x] 01.01.01 Generate Rails engine with `rails plugin new source_monitor --mountable`
|
|
21
|
+
- [x] 01.01.02 Configure isolate_namespace in engine.rb
|
|
22
|
+
|
|
23
|
+
### 01.02 Create Installation Generator
|
|
24
|
+
|
|
25
|
+
- [x] 01.02.01 Write test for install generator existence
|
|
26
|
+
- [x] 01.02.02 Create basic install generator class
|
|
27
|
+
- [x] 01.02.03 Make mount path configurable (default /source_monitor)
|
|
28
|
+
- [x] 01.02.04 Add generator usage instructions to README
|
|
29
|
+
|
|
30
|
+
### 01.03 Mount Engine in Host App
|
|
31
|
+
|
|
32
|
+
- [x] 01.03.01 Write test for route mounting
|
|
33
|
+
- [x] 01.03.02 Generator adds configurable mount to host routes.rb
|
|
34
|
+
- [x] 01.03.03 Create minimal ApplicationController
|
|
35
|
+
- [x] 01.03.04 Test engine responds at mounted path
|
|
36
|
+
|
|
37
|
+
**Deliverable: Engine installs and mounts at configurable path in Rails 8 app**
|
|
38
|
+
**Test: Visit mounted path and see welcome page**
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Phase 02: Testing Infrastructure & Observability
|
|
43
|
+
|
|
44
|
+
**Goal: Solid testing and monitoring foundation**
|
|
45
|
+
|
|
46
|
+
### 02.01 Setup Test Framework
|
|
47
|
+
|
|
48
|
+
- [x] 02.01.01 Configure MiniTest with Rails system tests
|
|
49
|
+
- [x] 02.01.02 Add WebMock and VCR for HTTP stubbing
|
|
50
|
+
- [x] 02.01.03 Create RSS, Atom, JSON Feed fixtures
|
|
51
|
+
- [x] 02.01.04 Add edge case fixtures (no GUID, malformed dates)
|
|
52
|
+
|
|
53
|
+
### 02.02 Add Observability
|
|
54
|
+
|
|
55
|
+
- [x] 02.02.01 Setup ActiveSupport::Notifications events
|
|
56
|
+
- [x] 02.02.02 Add source_monitor.fetch.start/finish events
|
|
57
|
+
- [x] 02.02.03 Create /health endpoint
|
|
58
|
+
- [x] 02.02.04 Add basic metrics collection module
|
|
59
|
+
|
|
60
|
+
**Deliverable: Comprehensive testing and observability from day one**
|
|
61
|
+
**Test: Run test suite and visit /health endpoint**
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Phase 03: Complete Data Model Foundation
|
|
66
|
+
|
|
67
|
+
**Goal: Complete data model with all necessary fields and proper constraints**
|
|
68
|
+
|
|
69
|
+
### 03.01 Create Source Model & Migration
|
|
70
|
+
|
|
71
|
+
- [x] 03.01.01 Create sources migration with all fields: name, feed_url (unique/indexed), website_url, active (default true/indexed), feed_format, fetch_interval_hours (default 6), next_fetch_at (indexed), last_fetched_at, last_fetch_duration_ms, last_http_status, last_error (text), last_error_at, etag, last_modified, failure_count (default 0), backoff_until, items_count (counter cache), scraping_enabled (default false), auto_scrape (default false), scrape_settings (jsonb), scraper_adapter (default 'readability'), requires_javascript (default false), custom_headers (jsonb), items_retention_days, max_items, metadata (jsonb), timestamps
|
|
72
|
+
- [x] 03.01.02 Create SourceMonitor::Source model with validations
|
|
73
|
+
- [x] 03.01.03 Add URL validation and normalization
|
|
74
|
+
- [x] 03.01.04 Add scopes for active, due_for_fetch, failed, healthy
|
|
75
|
+
- [x] 03.01.05 Test creating source via console and UI form
|
|
76
|
+
|
|
77
|
+
### 03.02 Create Item Model & Migration
|
|
78
|
+
|
|
79
|
+
- [x] 03.02.01 Create items migration with all fields: source_id (references/indexed/fk), guid (indexed), content_fingerprint (indexed SHA256), title, url (indexed), canonical_url, author, authors (jsonb), summary (text), content (text), scraped_html (text), scraped_content (text), scraped_at, scrape_status (indexed), published_at (indexed), updated_at_source, categories (jsonb), tags (jsonb), keywords (jsonb), enclosures (jsonb), media_thumbnail_url, media_content (jsonb), language, copyright, comments_url, comments_count, metadata (jsonb), timestamps; add unique constraints on (source_id, guid) and (source_id, content_fingerprint)
|
|
80
|
+
- [x] 03.02.02 Create SourceMonitor::Item model
|
|
81
|
+
- [x] 03.02.03 Add associations to Source
|
|
82
|
+
- [x] 03.02.04 Add validations and scopes
|
|
83
|
+
- [x] 03.02.05 Test creating items programmatically
|
|
84
|
+
|
|
85
|
+
### 03.03 Create FetchLog Model & Migration
|
|
86
|
+
|
|
87
|
+
- [x] 03.03.01 Create fetch_logs migration with all fields: source_id (references/indexed/fk), success (indexed), items_created (default 0), items_updated (default 0), items_failed (default 0), started_at (indexed), completed_at, duration_ms, http_status, http_response_headers (jsonb), error_class, error_message (text), error_backtrace (text), feed_size_bytes, items_in_feed, job_id (indexed), metadata (jsonb), created_at (indexed)
|
|
88
|
+
- [x] 03.03.02 Create SourceMonitor::FetchLog model
|
|
89
|
+
- [x] 03.03.03 Add associations and scopes
|
|
90
|
+
- [x] 03.03.04 Test log creation with various scenarios
|
|
91
|
+
|
|
92
|
+
### 03.04 Create ScrapeLog Model & Migration
|
|
93
|
+
|
|
94
|
+
- [x] 03.04.01 Create scrape_logs migration with all fields: item_id (references/indexed/fk), source_id (references/indexed/fk), success (indexed), started_at, completed_at, duration_ms, http_status, scraper_adapter, content_length, error_class, error_message (text), metadata (jsonb), created_at (indexed)
|
|
95
|
+
- [x] 03.04.02 Create SourceMonitor::ScrapeLog model
|
|
96
|
+
- [x] 03.04.03 Add associations
|
|
97
|
+
- [x] 03.04.04 Test scrape log tracking
|
|
98
|
+
|
|
99
|
+
**Deliverable: Complete, production-ready data model with all necessary fields**
|
|
100
|
+
**Test: Create all models via console, verify constraints and associations work**
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Phase 04: Simple Admin Interface with Tailwind
|
|
105
|
+
|
|
106
|
+
**Goal: Functional admin UI using Rails defaults + Tailwind**
|
|
107
|
+
|
|
108
|
+
### 04.01 Setup Tailwind CSS
|
|
109
|
+
|
|
110
|
+
- [x] 04.01.01 Add tailwindcss-rails to gemspec
|
|
111
|
+
- [x] 04.01.02 Generate Tailwind configuration for engine
|
|
112
|
+
- [x] 04.01.03 Scope CSS to .fm-admin namespace
|
|
113
|
+
- [x] 04.01.04 Create base layout with navigation
|
|
114
|
+
|
|
115
|
+
### 04.02 Create Dashboard
|
|
116
|
+
|
|
117
|
+
- [x] 04.02.01 Create DashboardController with index action
|
|
118
|
+
- [x] 04.02.02 Build stats partial showing source counts
|
|
119
|
+
- [x] 04.02.03 Add recent activity feed (latest logs)
|
|
120
|
+
- [x] 04.02.04 Display quick action buttons
|
|
121
|
+
- [x] 04.02.05 Test dashboard loads and shows data
|
|
122
|
+
|
|
123
|
+
### 04.03 Build Source Management
|
|
124
|
+
|
|
125
|
+
- [x] 04.03.01 Create SourcesController with full CRUD
|
|
126
|
+
- [x] 04.03.02 Build index view with status indicators
|
|
127
|
+
- [x] 04.03.03 Create form partial for new/edit
|
|
128
|
+
- [x] 04.03.04 Add show view with source details
|
|
129
|
+
- [x] 04.03.05 Test complete source lifecycle
|
|
130
|
+
|
|
131
|
+
### 04.04 Add Item Browser
|
|
132
|
+
|
|
133
|
+
- [x] 04.04.01 Create ItemsController with index and show
|
|
134
|
+
- [x] 04.04.02 Build paginated item list view
|
|
135
|
+
- [x] 04.04.03 Create item detail view with all content versions
|
|
136
|
+
- [x] 04.04.04 Add simple search by title
|
|
137
|
+
- [x] 04.04.05 Test browsing and viewing items
|
|
138
|
+
|
|
139
|
+
### 04.05 Create Log Viewers
|
|
140
|
+
|
|
141
|
+
- [x] 04.05.01 Create FetchLogsController with index and show
|
|
142
|
+
- [x] 04.05.02 Build log list view with filtering
|
|
143
|
+
- [x] 04.05.03 Create log detail view showing all data
|
|
144
|
+
- [x] 04.05.04 Add scrape logs view
|
|
145
|
+
- [x] 04.05.05 Test viewing success and failure logs
|
|
146
|
+
|
|
147
|
+
**Deliverable: Complete functional admin UI using Rails + Tailwind only**
|
|
148
|
+
**Test: Navigate through all admin pages, perform CRUD operations**
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Phase 05: Modern HTTP Stack & Feed Fetching
|
|
153
|
+
|
|
154
|
+
**Goal: Reliable feed fetching with logging using Feedjira**
|
|
155
|
+
|
|
156
|
+
### 05.01 Setup Faraday HTTP Client & Feedjira
|
|
157
|
+
|
|
158
|
+
- [x] 05.01.01 Add feedjira, faraday, and faraday-retry to gemspec
|
|
159
|
+
- [x] 05.01.02 Configure Feedjira global options (parser order, whitespace)
|
|
160
|
+
- [x] 05.01.03 Configure timeouts, redirects, compression
|
|
161
|
+
- [x] 05.01.04 Add retry middleware with exponential backoff and proxy support
|
|
162
|
+
- [x] 05.01.05 Smoke-test HTTP + Feedjira configuration against sample feeds
|
|
163
|
+
|
|
164
|
+
### 05.02 Build Feed Fetcher with Feedjira & Conditional GET
|
|
165
|
+
|
|
166
|
+
- [x] 05.02.01 Write FeedFetcher service tests with VCR using Feedjira.parse
|
|
167
|
+
- [x] 05.02.02 Implement ETag and Last-Modified support
|
|
168
|
+
- [x] 05.02.03 Handle 304 Not Modified responses
|
|
169
|
+
- [x] 05.02.04 Leverage Feedjira auto-detection for RSS/Atom/JSON parsing
|
|
170
|
+
- [x] 05.02.05 Validate Feedjira parser coverage across varied feed types
|
|
171
|
+
|
|
172
|
+
### 05.03 Add Structured Error Handling
|
|
173
|
+
|
|
174
|
+
- [x] 05.03.01 Create FetchError class hierarchy
|
|
175
|
+
- [x] 05.03.02 Log all fetch attempts to FetchLog
|
|
176
|
+
- [x] 05.03.03 Update source status on fetch
|
|
177
|
+
- [x] 05.03.04 Emit ActiveSupport notifications
|
|
178
|
+
- [x] 05.03.05 Test error scenarios (timeout, 404, malformed)
|
|
179
|
+
|
|
180
|
+
### 05.04 Implement Rate Limiting
|
|
181
|
+
|
|
182
|
+
- [x] 05.04.01 Add adaptive fetch interval logic based on feed activity
|
|
183
|
+
- [x] 05.04.02 Add source-level jitter to avoid stampedes
|
|
184
|
+
- [x] 05.04.03 Respect backoff_until field
|
|
185
|
+
- [x] 05.04.04 Update failure_count on errors
|
|
186
|
+
- [x] 05.04.05 Test rate limiting behavior
|
|
187
|
+
|
|
188
|
+
**Deliverable: Production-grade fetching with Feedjira-backed parsing**
|
|
189
|
+
**Test: Fetch real feeds via console, verify Feedjira parsing and conditional GET**
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Phase 06: Item Processing with Complete Metadata
|
|
194
|
+
|
|
195
|
+
**Goal: Extract and store all feed item data via Feedjira entries**
|
|
196
|
+
|
|
197
|
+
### 06.01 Build Item Creator Service
|
|
198
|
+
|
|
199
|
+
- [x] 06.01.01 Write tests for item creation using Feedjira entry objects
|
|
200
|
+
- [x] 06.01.02 Generate content fingerprints from title+url+content
|
|
201
|
+
- [x] 06.01.03 Normalize and canonicalize URLs
|
|
202
|
+
- [x] 06.01.04 Handle missing GUIDs gracefully
|
|
203
|
+
- [x] 06.01.05 Test item creation with Feedjira across various feed formats
|
|
204
|
+
|
|
205
|
+
### 06.02 Extract All Metadata Fields
|
|
206
|
+
|
|
207
|
+
- [x] 06.02.01 Map Feedjira fields: title, url, guid, author, content
|
|
208
|
+
- [x] 06.02.02 Extract authors array and handle DC creator via Feedjira APIs
|
|
209
|
+
- [x] 06.02.03 Extend Feedjira parsers to expose categories, tags, keywords
|
|
210
|
+
- [x] 06.02.04 Extract enclosures for media (podcasts/videos)
|
|
211
|
+
- [x] 06.02.05 Parse media:thumbnail and media:content
|
|
212
|
+
- [x] 06.02.06 Expose comments URL and count via Feedjira parser extensions
|
|
213
|
+
- [x] 06.02.07 Capture all other fields in metadata JSONB
|
|
214
|
+
- [x] 06.02.08 Test metadata extraction with real feeds through Feedjira
|
|
215
|
+
|
|
216
|
+
### 06.03 Implement Deduplication Logic
|
|
217
|
+
|
|
218
|
+
- [x] 06.03.01 Check GUID uniqueness first
|
|
219
|
+
- [x] 06.03.02 Fall back to content fingerprint
|
|
220
|
+
- [x] 06.03.03 Use upsert for idempotent creation
|
|
221
|
+
- [x] 06.03.04 Track duplicate attempts in logs
|
|
222
|
+
- [x] 06.03.05 Test deduplication with repeated fetches
|
|
223
|
+
|
|
224
|
+
### 06.04 Wire Up Feed Fetcher to Item Creator
|
|
225
|
+
|
|
226
|
+
- [x] 06.04.01 Integrate FeedFetcher with ItemCreator
|
|
227
|
+
- [x] 06.04.02 Update items_count counter cache
|
|
228
|
+
- [x] 06.04.03 Log items created/updated/failed
|
|
229
|
+
- [x] 06.04.04 Test end-to-end fetch and item creation
|
|
230
|
+
- [x] 06.04.05 Add manual fetch button in admin UI
|
|
231
|
+
|
|
232
|
+
**Deliverable: Complete item metadata extraction and storage via Feedjira**
|
|
233
|
+
**Test: Fetch feed via admin UI, verify Feedjira-driven items have complete metadata**
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Phase 07: Content Scraping with Multiple Storage Layers
|
|
238
|
+
|
|
239
|
+
**Goal: Store raw HTML and extracted content in a dedicated table while complementing Feedjira data**
|
|
240
|
+
|
|
241
|
+
### 07.01 Create Scraper Adapter Interface
|
|
242
|
+
|
|
243
|
+
- [x] 07.01.01 Define Scrapers::Base abstract class
|
|
244
|
+
- [x] 07.01.02 Create contract tests for adapter interface
|
|
245
|
+
- [x] 07.01.03 Add settings parameter support
|
|
246
|
+
- [x] 07.01.04 Document adapter requirements
|
|
247
|
+
|
|
248
|
+
### 07.02 Implement Readability Scraper
|
|
249
|
+
|
|
250
|
+
- [x] 07.02.01 Add nokolexbor for fast HTML parsing
|
|
251
|
+
- [x] 07.02.02 Add ruby-readability for extraction
|
|
252
|
+
- [x] 07.02.03 Create Scrapers::Readability adapter
|
|
253
|
+
- [x] 07.02.04 Support custom CSS selectors via scrape_settings
|
|
254
|
+
- [x] 07.02.05 Test scraper with various article pages
|
|
255
|
+
|
|
256
|
+
### 07.03 Persist Scraped Content Separately
|
|
257
|
+
|
|
258
|
+
- [x] 07.03.01 Create dedicated table (e.g. item_contents) with scraped_html and scraped_content columns
|
|
259
|
+
- [x] 07.03.02 Add has_one association from Item and migrate existing data
|
|
260
|
+
- [x] 07.03.03 Update scraping pipeline to write to the associated content record
|
|
261
|
+
- [x] 07.03.04 Ensure Items table drops scraped_html and scraped_content columns while keeping status fields
|
|
262
|
+
- [x] 07.03.05 Test persistence using the separate table alongside Feedjira content
|
|
263
|
+
|
|
264
|
+
### 07.04 Add Scraping UI Controls
|
|
265
|
+
|
|
266
|
+
- [x] 07.04.01 Add scraping configuration form to source edit
|
|
267
|
+
- [x] 07.04.02 Add manual scrape button on item detail page
|
|
268
|
+
- [x] 07.04.03 Display all content versions in item view with Feedjira comparison
|
|
269
|
+
- [x] 07.04.04 Show scraping status and errors
|
|
270
|
+
- [x] 07.04.05 Test manual scraping workflow
|
|
271
|
+
|
|
272
|
+
**Deliverable: Multi-layer content storage aligned with Feedjira base content and smaller Items table**
|
|
273
|
+
**Test: Scrape article via admin UI, verify scraped layers stored via associated content record**
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Phase 08: Background Jobs with Solid Queue
|
|
278
|
+
|
|
279
|
+
**Goal: Unified job orchestration that powers both async processing and manual actions without duplicating logic**
|
|
280
|
+
|
|
281
|
+
### 08.01 Establish Job Infrastructure
|
|
282
|
+
|
|
283
|
+
- [x] 08.01.01 Ensure Solid Queue/Postgres are the default while allowing host apps to override ActiveJob backend if already configured
|
|
284
|
+
- [x] 08.01.02 Introduce `SourceMonitor::ApplicationJob` that inherits the host `ApplicationJob` when present, falling back to `ActiveJob::Base`
|
|
285
|
+
- [x] 08.01.03 Provide configurable queue names/concurrency that respect host settings and avoid namespace clashes
|
|
286
|
+
- [x] 08.01.04 Add lightweight job visibility in the engine (e.g., queue depth/last run) and document optional Mission Control integration without hard dependency
|
|
287
|
+
- [x] 08.01.05 Verify job execution path inside dummy app with Postgres-backed Solid Queue
|
|
288
|
+
|
|
289
|
+
### 08.02 Implement FetchFeedJob Pipeline
|
|
290
|
+
|
|
291
|
+
- [x] 08.02.01 Create `FetchFeedJob` as the canonical entry point for fetching, delegating to existing fetch orchestration logic
|
|
292
|
+
- [x] 08.02.02 Extract a shared fetch runner/enqueuer used by both the job and manual “Fetch Now” UI to prevent duplicated code paths
|
|
293
|
+
- [x] 08.02.03 Guard concurrent fetches via advisory locking or equivalent coordination
|
|
294
|
+
- [x] 08.02.04 After processing, enqueue `ScrapeItemJob` instances for any new items flagged for scraping via the shared enqueuer
|
|
295
|
+
- [x] 08.02.05 Add tests covering job execution, retry behavior, and automatic follow-up scraping
|
|
296
|
+
|
|
297
|
+
### 08.03 Implement ScrapeItemJob Pipeline
|
|
298
|
+
|
|
299
|
+
- [x] 08.03.01 Create `ScrapeItemJob` as the canonical scraping entry point that reuses the existing scraper orchestration
|
|
300
|
+
- [x] 08.03.02 Introduce shared scraping enqueue logic invoked by both background jobs and manual UI actions
|
|
301
|
+
- [x] 08.03.03 Respect per-source scraping configuration and deduplicate in-flight jobs when queuing
|
|
302
|
+
- [x] 08.03.04 Persist `ScrapeLog` updates and propagate status/errors consistently with the manual flow
|
|
303
|
+
- [x] 08.03.05 Add tests for scraping job workflow, including cases triggered by both automatic and manual paths
|
|
304
|
+
|
|
305
|
+
### 08.04 Unify UI and Job Queueing
|
|
306
|
+
|
|
307
|
+
- [x] 08.04.01 Update manual fetch button to call the shared fetch enqueuer so the UI and jobs share the same foundation
|
|
308
|
+
- [x] 08.04.02 Update manual scrape actions to leverage the shared scraping enqueuer
|
|
309
|
+
- [x] 08.04.03 Surface job state/metrics in the admin dashboard using the lightweight visibility layer from 08.01
|
|
310
|
+
- [x] 08.04.04 Expose optional Mission Control links/documentation when the host app enables it
|
|
311
|
+
- [x] 08.04.05 Add system/integration tests ensuring manual actions enqueue the proper jobs and display status
|
|
312
|
+
|
|
313
|
+
### 08.05 Separate readability from scraper configuration settings for sources
|
|
314
|
+
|
|
315
|
+
- [x] 08.05.01 Ensure that a source has independent settings for enabling or disabling using readability on the feed's Content (from the rss feed), separate of using readability on the html scraping method (if enabled for a feed) (so a feed can have its content ingested raw (no readability), content processed with readability, or site scraped with readability enabled))
|
|
316
|
+
|
|
317
|
+
**Deliverable: Production-ready background processing that keeps manual and async flows in sync**
|
|
318
|
+
**Test: Trigger fetch/scrape from UI and scheduler, confirm shared logic enqueues jobs and surfaces status**
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Phase 09: Scheduler with Single Entry Point
|
|
323
|
+
|
|
324
|
+
**Goal: Flexible scheduling strategy**
|
|
325
|
+
|
|
326
|
+
### 09.01 Build Core Scheduler
|
|
327
|
+
|
|
328
|
+
- [x] 09.01.01 Create Scheduler.run entry point
|
|
329
|
+
- [x] 09.01.02 Find sources due for fetch (next_fetch_at <= now)
|
|
330
|
+
- [x] 09.01.03 Use SELECT FOR UPDATE SKIP LOCKED
|
|
331
|
+
- [x] 09.01.04 Enqueue FetchFeedJob for each due source
|
|
332
|
+
- [x] 09.01.05 Test scheduler finds and enqueues jobs
|
|
333
|
+
|
|
334
|
+
### 09.02 Restore Mission Control Dashboard
|
|
335
|
+
|
|
336
|
+
- [x] 09.02.01 Ensure Solid Queue is eagerly loaded and becomes the default Active Job adapter unless the host overrides it
|
|
337
|
+
- [x] 09.02.02 Install and run Solid Queue migrations for the dummy app so Mission Control can read queue data
|
|
338
|
+
- [x] 09.02.03 Override the Mission Control layout to force the light theme and load bundled assets correctly
|
|
339
|
+
- [x] 09.02.04 Verify Mission Control shows queue metrics/sections once Solid Queue is configured and a worker is running
|
|
340
|
+
- [x] 09.02.05 Capture the configuration updates in docs/notes so host apps understand the setup requirements
|
|
341
|
+
|
|
342
|
+
### 09.03 Configure Solid Queue Recurring Tasks
|
|
343
|
+
|
|
344
|
+
- [x] 09.03.01 Define recurring fetch/scrape jobs in `config/recurring.yml` using Solid Queue schedule syntax (class/args/command).
|
|
345
|
+
- [x] 09.03.02 Ensure `bin/jobs` loads the recurring schedule and document overriding it with `--recurring_schedule_file`.
|
|
346
|
+
- [x] 09.03.03 Explain how to disable recurring execution via `SOLID_QUEUE_SKIP_RECURRING` or `bin/jobs --skip-recurring`.
|
|
347
|
+
- [x] 09.03.04 Provide a hook to swap the default recurring job class for host-specific command execution.
|
|
348
|
+
- [x] 09.03.05 Verify recurring tasks enqueue expected jobs (integration/system coverage or supervised run script).
|
|
349
|
+
|
|
350
|
+
### 09.04 Refactor Job Queues card on dashboard to pull data directly from solid queue db tables, not from event metrics
|
|
351
|
+
|
|
352
|
+
- [x] 09.04.01 Implement a service/query that aggregates counts from Solid Queue job tables (ready, scheduled, failed, recurring).
|
|
353
|
+
- [x] 09.04.02 Update the dashboard card to render database-driven metrics and handle empty/paused queue states gracefully.
|
|
354
|
+
- [x] 09.04.03 Add automated coverage (unit + system) confirming the dashboard shows the new metrics.
|
|
355
|
+
- [x] 09.04.04 Document the metrics source change and required Solid Queue configuration/migrations for host apps.
|
|
356
|
+
|
|
357
|
+
## 09.05 Sources analytics
|
|
358
|
+
|
|
359
|
+
- [x] 09.05.01 add a heatmap histogram table visual showing how many sources have fetch intervals in which timespan buckets (5-30 minutes, 30-60, 60-120, 120-240, 240-480, 480+)
|
|
360
|
+
- [x] 09.05.02 Add a column to source index table showing new item rate per day to see how active different sources are
|
|
361
|
+
|
|
362
|
+
**Deliverable: Robust scheduling that works with standard Rails tools**
|
|
363
|
+
**Test: Run scheduler via rake task, verify jobs enqueued for due sources**
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Phase 10: Data Retention & Maintenance
|
|
368
|
+
|
|
369
|
+
**Goal: Manage data growth**
|
|
370
|
+
|
|
371
|
+
### 10.01 Add Retention Policies
|
|
372
|
+
|
|
373
|
+
- [x] 10.01.01 Implement retention by items_retention_days
|
|
374
|
+
- [x] 10.01.02 Implement retention by max_items per source
|
|
375
|
+
- [x] 10.01.03 Add UI controls for retention settings
|
|
376
|
+
- [x] 10.01.04 Document retention strategies
|
|
377
|
+
|
|
378
|
+
### 10.02 Build Cleanup Jobs
|
|
379
|
+
|
|
380
|
+
- [x] 10.02.01 Create ItemCleanupJob respecting retention policies
|
|
381
|
+
- [x] 10.02.02 Create LogCleanupJob for old fetch/scrape logs
|
|
382
|
+
- [x] 10.02.03 Add soft delete option for items
|
|
383
|
+
- [x] 10.02.04 Create rake tasks for manual cleanup
|
|
384
|
+
- [x] 10.02.05 Test cleanup jobs work correctly
|
|
385
|
+
|
|
386
|
+
**Deliverable: Sustainable data management with cleanup automation**
|
|
387
|
+
**Test: Run cleanup jobs, verify old data removed per policies**
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Phase 11: Host App Integration & Extensibility
|
|
392
|
+
|
|
393
|
+
**Goal: Hooks for host application customization**
|
|
394
|
+
|
|
395
|
+
### 11.01 Configuration DSL
|
|
396
|
+
|
|
397
|
+
- [x] 11.01.01 Create SourceMonitor.configure method
|
|
398
|
+
- [x] 11.01.02 Add HTTP client settings (timeouts, retries)
|
|
399
|
+
- [x] 11.01.03 Configure scraper adapters
|
|
400
|
+
- [x] 11.01.04 Set retention policies globally
|
|
401
|
+
- [x] 11.01.05 Document configuration options
|
|
402
|
+
|
|
403
|
+
### 11.02 Event System
|
|
404
|
+
|
|
405
|
+
- [x] 11.02.01 Add after_item_created callback hook
|
|
406
|
+
- [x] 11.02.02 Add after_item_scraped callback hook
|
|
407
|
+
- [x] 11.02.03 Add after_fetch_completed callback hook
|
|
408
|
+
- [x] 11.02.04 Support custom item processors
|
|
409
|
+
- [x] 11.02.05 Document event API with examples
|
|
410
|
+
|
|
411
|
+
### 11.03 Model Extensions
|
|
412
|
+
|
|
413
|
+
- [x] 11.03.01 Allow custom fields via table_name_prefix
|
|
414
|
+
- [x] 11.03.02 Support concerns for adding behavior
|
|
415
|
+
- [x] 11.03.03 Enable custom validations via config
|
|
416
|
+
- [x] 11.03.04 Provide STI examples for source types
|
|
417
|
+
- [x] 11.03.05 Create example app showing extensions
|
|
418
|
+
|
|
419
|
+
**Deliverable: Fully extensible for host application needs**
|
|
420
|
+
**Test: Create example host app with custom callbacks and fields**
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Phase 12: Real-time Updates with Turbo
|
|
425
|
+
|
|
426
|
+
**Goal: Live UI updates using Rails 8 defaults and Stimulus Components as documented in context7 mcp here: https://context7.com/stimulus-components/stimulus-components **
|
|
427
|
+
|
|
428
|
+
### 12.01 Add Turbo Streams
|
|
429
|
+
|
|
430
|
+
- [x] 12.01.01 Configure Turbo (included in Rails 8)
|
|
431
|
+
- [x] 12.01.02 Setup Turbo Stream broadcasts for fetch completion
|
|
432
|
+
- [x] 12.01.03 Stream new items to dashboard
|
|
433
|
+
- [x] 12.01.04 Update stats in real-time
|
|
434
|
+
- [x] 12.01.05 Test live updates in browser
|
|
435
|
+
|
|
436
|
+
### 12.02 Add Progress Indicators
|
|
437
|
+
|
|
438
|
+
- [x] 12.02.01 Show fetch status indicators per source on source index, updated with turbo streams
|
|
439
|
+
- [x] 12.02.03 Add loading states for async actions
|
|
440
|
+
- [x] 12.02.04 Toast notifications for manually initiated job completion (Stimulus Component: Notification)
|
|
441
|
+
- [x] 12.02.05 Real-time updates for source show when manually fetching
|
|
442
|
+
- [x] 12.02.06 Real-time updates for item show when manually fetching or scraping
|
|
443
|
+
- [x] 12.02.07 Test UX improvements
|
|
444
|
+
|
|
445
|
+
### 12.03 Add Stimulus Controllers
|
|
446
|
+
|
|
447
|
+
- [x] 12.03.03 Allow the search of items and feeds from their indexes (use ransack gem, documented in context7 mcp here: https://context7.com/activerecord-hackery/ransack)
|
|
448
|
+
|
|
449
|
+
## 12.04 Fetch Schedule
|
|
450
|
+
|
|
451
|
+
- [x] 12.04.01 When clicking a box in the fetch interval histogram table on source index, filter the list of sources to the ones that have that fetch interval
|
|
452
|
+
- [x] 12.04.02 On Dashboard, show an upcoming fetch schedule, grouped in 15 minute intervals for first hour, 30 minute intervals for hours 2-4, and then all remaining sources with intevals > 4 hours from current time. Show these as a stack of cards containing tables of the sources for each interval
|
|
453
|
+
- [x] 12.04.03 While on the Dashboard, as sources are fetched by the job queue, real-time update the upcoming fetch interval cards with turbo streams
|
|
454
|
+
- [x] 12.04.04 Make source fetch interval back off and speed up (based on if items are fetched) user configurable in the initalizer
|
|
455
|
+
|
|
456
|
+
**Deliverable: Modern real-time UI using Rails 8 defaults**
|
|
457
|
+
**Test: Trigger fetch, watch dashboard update in real-time**
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## Phase 13: Advanced Error Recovery
|
|
462
|
+
|
|
463
|
+
**Goal: Self-healing system**
|
|
464
|
+
|
|
465
|
+
### 13.01 Implement Smart Retries
|
|
466
|
+
|
|
467
|
+
- [x] 13.01.01 Add retry strategies per error type
|
|
468
|
+
- [x] 13.01.02 Implement circuit breaker pattern
|
|
469
|
+
- [x] 13.01.03 Auto-adjust fetch intervals on failure
|
|
470
|
+
- [x] 13.01.04 Add manual retry from UI
|
|
471
|
+
- [x] 13.01.05 Test retry behavior
|
|
472
|
+
|
|
473
|
+
### 13.02 Source Health Monitoring
|
|
474
|
+
|
|
475
|
+
- [x] 13.02.01 Calculate rolling success rates
|
|
476
|
+
- [x] 13.02.02 Auto-pause failing sources after threshold (user configurable in initializer and per source)
|
|
477
|
+
- [x] 13.02.03 Add health status indicators in UI
|
|
478
|
+
- [x] 13.02.04 Auto-recovery detection and resume
|
|
479
|
+
- [x] 13.02.05 Test health monitoring
|
|
480
|
+
|
|
481
|
+
**Deliverable: Self-managing feed system with health monitoring**
|
|
482
|
+
**Test: Simulate failures, verify auto-pause and recovery**
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Phase 14: Performance Optimization
|
|
487
|
+
|
|
488
|
+
**Goal: Scale to thousands of sources**
|
|
489
|
+
|
|
490
|
+
### 14.01 Database Performance
|
|
491
|
+
|
|
492
|
+
- [x] 14.01.01 Verify all indexes from migrations
|
|
493
|
+
- [x] 14.01.02 Add missing indexes based on query analysis
|
|
494
|
+
- [x] 14.01.03 Optimize counter caches (items_count)
|
|
495
|
+
- [x] 14.01.04 Eliminate N+1 queries with includes
|
|
496
|
+
- [x] 14.01.05 Add query performance tests
|
|
497
|
+
|
|
498
|
+
**Deliverable: Handle 1000+ sources efficiently**
|
|
499
|
+
**Test: Load test with large number of sources, measure performance**
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Phase 16: Security Hardening & UX improvements
|
|
504
|
+
|
|
505
|
+
**Goal: Production security**
|
|
506
|
+
|
|
507
|
+
### 16.01 Input Validation
|
|
508
|
+
|
|
509
|
+
- [x] 16.01.01 Sanitize all user inputs
|
|
510
|
+
- [x] 16.01.05 Test security validations
|
|
511
|
+
|
|
512
|
+
### 16.02 Authentication & Authorization
|
|
513
|
+
|
|
514
|
+
- [x] 16.02.01 Integrate with host app auth (if configured)
|
|
515
|
+
- [x] 16.02.02 Add before_action filters for auth
|
|
516
|
+
- [x] 16.02.03 Test auth integration
|
|
517
|
+
- [x] 16.02.04 Verify CSRF protection active
|
|
518
|
+
|
|
519
|
+
### 16.03 Table sorting by columns
|
|
520
|
+
|
|
521
|
+
- [x] 16.03.01 Column headers in tables are clickable, flipping sort direction by asc and desc by the attribute for that column with arrows showing sort direction. use hotwire/turbo to refresh table upon column heading click without forcing full page reload
|
|
522
|
+
- [x] 16.03.02 Items index table default sorts by published timestamp desc
|
|
523
|
+
- [x] 16.03.03 move health monitoring card below source details sidebar card on source show view
|
|
524
|
+
- [x] 16.03.04 remove new source link from navbar
|
|
525
|
+
- [x] 16.03.05 show categories and tags on the item show view in the sidebar Item Details card
|
|
526
|
+
- [x] 16.03.06 Show categories and tags columns on the source show view in the items table
|
|
527
|
+
- [x] 16.03.07 source title should link to the source show page from the source index page table. View/Edit links per source row should be in a dropdown behind a gear icon (use dropdown from Stimulus Components as documented in context7 mcp here: https://context7.com/stimulus-components/stimulus-components)
|
|
528
|
+
- [x] 16.03.08 Move "View Original" and "Manual Scrape" buttons to be above the Content Comparison card to fix wrapping issues
|
|
529
|
+
- [x] 16.03.09 the title of each row in Recent Activity table on dashboard should link to the show view of that thing (fetch logs, scrape logs, items, etc)
|
|
530
|
+
|
|
531
|
+
**Deliverable: Enterprise-ready security**
|
|
532
|
+
**Test: Security scan with brakeman, verify protections**
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## Phase 17: Complexity Analysis & Rails Conventions and Best Practices
|
|
537
|
+
|
|
538
|
+
**Goal: Simple, conventional implementations**
|
|
539
|
+
|
|
540
|
+
### 17.01 Comprehensive Complexity Audit
|
|
541
|
+
|
|
542
|
+
- [x] 17.01.01 Compile an inventory of all controllers, models, jobs, services, view components, and front-end assets to set audit scope
|
|
543
|
+
- [x] 17.01.02 Review controller actions for RESTful conventions, before_action bloat, and opportunities to slim controllers in favour of service objects
|
|
544
|
+
- [x] 17.01.03 Evaluate models, service objects, and modules for SRP adherence, duplication, and opportunities to encapsulate behaviour cleanly
|
|
545
|
+
- [x] 17.01.04 Inspect background jobs, Solid Queue workers, and scheduling flows for redundant logic, excessive coupling, or non-idiomatic patterns
|
|
546
|
+
- [x] 17.01.05 Audit front-end assets (Stimulus controllers, Turbo Streams, Tailwind, JS package management) for anti-patterns, dependency drift, or missing build steps
|
|
547
|
+
- [x] 17.01.06 Summarize complexity hotspots (long methods, deep conditionals, callback chains) with supporting metrics from tools like `bundle exec brakeman`, `bundle exec rubocop`, and SimpleCov trends and save to .ai/ folder as markdown file
|
|
548
|
+
|
|
549
|
+
### 17.02 Findings Report & Recommendations
|
|
550
|
+
|
|
551
|
+
- [x] 17.02.01 Produce an audit report cataloging each issue with file references, context, and impacted behaviour
|
|
552
|
+
- [x] 17.02.02 Document recommended Rails-aligned remediation for controller, model, job, and service object issues (RESTful routing, skinny controllers, fat models, dependency injection)
|
|
553
|
+
- [x] 17.02.03 Outline DRY and complexity reduction strategies (extractions, shared concerns, presenters) with implementation guidance and prerequisites
|
|
554
|
+
- [x] 17.02.04 Capture front-end package management and view-layer recommendations (Stimulus module boundaries, Turbo usage, asset bundling hygiene)
|
|
555
|
+
- [x] 17.02.05 Prioritize findings with effort/impact scoring, required stakeholders, and suggested sequencing across future roadmap phases
|
|
556
|
+
- [x] 17.02.06 Save final analysis to .ai/ folder as markdown file
|
|
557
|
+
|
|
558
|
+
### 17.03 Refactoring Execution Planning
|
|
559
|
+
|
|
560
|
+
- [x] 17.03.01 Break prioritized findings into actionable refactor workstreams (controllers, models/services, background jobs, front-end) with owners
|
|
561
|
+
- [x] 17.03.02 Define success criteria and regression test coverage requirements for each workstream, including new automated tests or fixtures needed
|
|
562
|
+
- [x] 17.03.03 Sequence refactor tasks into incremental deliveries, noting dependencies, rollout strategy, and migration considerations
|
|
563
|
+
- [x] 17.03.04 Establish monitoring and QA checkpoints (notifications, metrics dashboards, manual verification) to validate behavioural parity post-refactor
|
|
564
|
+
- [x] 17.03.05 Create follow-up tickets for any deferred or risky refactors, ensuring documentation links back to the audit report and recommendations
|
|
565
|
+
|
|
566
|
+
### 17.04 Controller & View Cleanup
|
|
567
|
+
|
|
568
|
+
- [x] 17.04.01 Extract a shared sanitized search helper and replace duplicated logic in sources, items, and logs controllers
|
|
569
|
+
- [x] 17.04.02 Introduce a shared pagination service (or Pagy adoption) with unit coverage and integrate into items index flows
|
|
570
|
+
- [x] 17.04.03 Create Turbo presenter/responder objects for notifications and details partial updates, updating controller actions accordingly
|
|
571
|
+
- [x] 17.04.04 Consolidate fetch and scrape log filtering into a shared concern with tests for query parameter casting and scopes
|
|
572
|
+
- [x] 17.04.05 Move analytics aggregation/bucketing logic out of `SourcesController#index` into a reusable query/presenter with dedicated tests
|
|
573
|
+
|
|
574
|
+
### 17.05 Service Decomposition
|
|
575
|
+
|
|
576
|
+
- [x] 17.05.01 Extract advisory lock management from `SourceMonitor::Fetching::FetchRunner` into a dedicated collaborator with unit tests
|
|
577
|
+
- [x] 17.05.02 Split fetch completion responsibilities (retention, scrape enqueue, events) into injectable services and cover with integration specs
|
|
578
|
+
- [x] 17.05.03 Refactor `SourceMonitor::Scraping::ItemScraper` into adapter resolver and persistence steps with contract tests for adapters
|
|
579
|
+
- [x] 17.05.04 Break `SourceMonitor::Items::RetentionPruner` strategies into separate classes/modules and expand test coverage for destroy vs soft delete
|
|
580
|
+
- [x] 17.05.05 Introduce a shared sanitization module for models (e.g., Source, future models) and migrate existing callbacks with unit coverage
|
|
581
|
+
- [x] 17.05.06 Extract reusable URL normalization helpers for Item and other URL-backed models with regression tests
|
|
582
|
+
|
|
583
|
+
### 17.06 Job & Scheduling Reliability
|
|
584
|
+
|
|
585
|
+
- [x] 17.06.01 Align `SourceMonitor::ScrapeItemJob` with shared state helpers, ensuring consistent pending/processing transitions and job tests
|
|
586
|
+
- [x] 17.06.02 Centralize cleanup job option parsing into a shared utility and update ItemCleanupJob/LogCleanupJob specs
|
|
587
|
+
- [x] 17.06.03 Add explicit retry/backoff policy for transient errors in `SourceMonitor::FetchFeedJob` with coverage for retry scheduling
|
|
588
|
+
- [x] 17.06.04 Instrument `SourceMonitor::Scheduler` runs and expose metrics/hooks verified by integration tests
|
|
589
|
+
|
|
590
|
+
### 17.07 Front-End Pipeline Modernization
|
|
591
|
+
|
|
592
|
+
- [x] 17.07.01 Convert Stimulus controllers to ES module/importmap loading and remove global registration, with smoke/system tests
|
|
593
|
+
- [x] 17.07.02 Provide graceful fallback when optional dropdown dependency is missing, including documentation and JS tests
|
|
594
|
+
- [x] 17.07.03 Replace or realign the transition shim with maintained stimulus-use utilities and verify behaviour via integration tests
|
|
595
|
+
- [x] 17.07.04 Automate Tailwind rebuilds and add asset verification scripts to the development/CI workflow
|
|
596
|
+
|
|
597
|
+
### 17.08 Tooling & Coverage Guardrails
|
|
598
|
+
|
|
599
|
+
- [x] 17.08.01 Establish Rubocop autocorrect baseline and enforce lint step in CI with developer documentation
|
|
600
|
+
- [x] 17.08.02 Add Brakeman to the bundle, configure ignore list if needed, and wire into CI security stage
|
|
601
|
+
- [x] 17.08.03 Enable SimpleCov with coverage gating (≥90% for new/changed lines) and surface reports in CI
|
|
602
|
+
- [x] 17.08.04 Add asset lint/test commands (e.g., eslint/stylelint or equivalent) and integrate into CI
|
|
603
|
+
- [x] 17.08.05 Update contributor docs with new lint/test workflows and ensure bin scripts support local runs
|
|
604
|
+
|
|
605
|
+
### 17.09 Dashboard Performance Enhancements
|
|
606
|
+
|
|
607
|
+
- [x] 17.09.01 Refactor `SourceMonitor::Dashboard::Queries` to batch/cache queries and separate routing/presentation concerns, with performance-focused tests
|
|
608
|
+
- [x] 17.09.02 Add instrumentation for dashboard query durations and expose metrics for Mission Control integration
|
|
609
|
+
- [x] 17.09.03 Document dashboard configuration expectations for host apps, including Mission Control linking prerequisites
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## Phase 18: Documentation & Release
|
|
614
|
+
|
|
615
|
+
**Goal: Production-ready gem**
|
|
616
|
+
|
|
617
|
+
### 18.01 Complete Documentation
|
|
618
|
+
|
|
619
|
+
- [x] 18.01.01 Write comprehensive README
|
|
620
|
+
- [x] 18.01.02 Create installation guide
|
|
621
|
+
- [x] 18.01.03 Add API/configuration documentation
|
|
622
|
+
- [x] 18.01.04 Write deployment guides
|
|
623
|
+
- [x] 18.01.05 Create troubleshooting guide
|
|
624
|
+
|
|
625
|
+
### 18.02 Example Applications
|
|
626
|
+
|
|
627
|
+
- [x] 18.02.01 Create basic example app
|
|
628
|
+
- [x] 18.02.02 Add advanced integration example
|
|
629
|
+
- [x] 18.02.03 Show custom adapter example
|
|
630
|
+
- [x] 18.02.04 Include Docker configuration
|
|
631
|
+
- [x] 18.02.05 Document production deployment
|
|
632
|
+
|
|
633
|
+
**Deliverable: Production-ready, well-documented gem**
|
|
634
|
+
**Test: Install in fresh Rails 8 app using published gem**
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## Phase 19: Admin UI Refinements
|
|
639
|
+
|
|
640
|
+
**Goal: Streamline source management workflows and centralize log visibility without adding complexity**
|
|
641
|
+
|
|
642
|
+
### 19.01 Surface Item Scraping Status on Source Detail
|
|
643
|
+
|
|
644
|
+
- [x] 19.01.01 Audit the source show item table partials to confirm which attributes are available for display and document the intended status states (pending, processing, success, failure, disabled)
|
|
645
|
+
- [x] 19.01.02 Update the item rows to render a scraping status badge/icon that reflects the latest `scrape_status` and gracefully handles items that have never been scraped
|
|
646
|
+
- [x] 19.01.03 Ensure Turbo/Hotwire updates push status changes in real time after scrapes complete, covering manual and background flows
|
|
647
|
+
- [x] 19.01.04 Add system coverage verifying that newly scraped items show the correct status badge and that status changes broadcast without full page reloads
|
|
648
|
+
|
|
649
|
+
### 19.02 Add "Scrape All" Control to Source Show
|
|
650
|
+
|
|
651
|
+
- [x] 19.02.01 Define UX placement, confirmation copy, and authorization expectations for a "Scrape All" button on the source detail page. Default to scraping all items on the current page of the table, with a radio button, and another option for "all unscraped items for this source ([count])" and also "All items (even those previously scraped) ([count])" that the user can toggle
|
|
652
|
+
- [x] 19.02.02 Wire the control to enqueue scraping for eligible items via the existing `SourceMonitor::Scraping::Enqueuer`, respecting auto-scrape settings and avoiding duplicate jobs
|
|
653
|
+
- [x] 19.02.03 Provide user feedback (flash/turbo partial) summarizing how many items were enqueued and expose errors when nothing qualifies
|
|
654
|
+
- [x] 19.02.04 Ensure the system allows per-source scraping rate limits so that the queue is properly metered to not denial of service the source to scrape their items
|
|
655
|
+
- [x] 19.02.05 Cover the new control with system and service tests, including a regression case for sources with no scrape-eligible items
|
|
656
|
+
|
|
657
|
+
### 19.03 Add Source Deletion from Index Table
|
|
658
|
+
|
|
659
|
+
- [x] 19.03.01 Specify the destructive action UX (button location, confirmation modal/text, tooltip) for deleting a source directly from the index list
|
|
660
|
+
- [x] 19.03.02 Implement the delete button using standard Rails RESTful routes, ensuring Turbo seamlessly removes the row and updates counters without full refreshes
|
|
661
|
+
- [x] 19.03.03 Validate that dependent records (items, logs, schedules) are handled according to existing retention/deletion rules and document any follow-up work
|
|
662
|
+
- [x] 19.03.04 Add controller and system tests covering successful deletion, cancellation, and unauthorized attempts
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## Phase 20: Rails Convention & Architecture Cleanup
|
|
667
|
+
|
|
668
|
+
**Goal: Ensure entire codebase follows the rails way and is approachable and understandable**
|
|
669
|
+
|
|
670
|
+
**Reference:** Complete audit findings in `.ai/codebase_audit_2025.md`
|
|
671
|
+
|
|
672
|
+
**Total Estimated Effort:** 36-53 hours across 4 sub-phases
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
### 20.01 Critical Fixes - Phase 1 (8-12 hours)
|
|
677
|
+
|
|
678
|
+
**Reference:** `.ai/codebase_audit_2025.md:1203-1223`
|
|
679
|
+
|
|
680
|
+
**Priority:** MUST FIX - Immediate impact on code quality and performance
|
|
681
|
+
|
|
682
|
+
- [x] 20.01.01 **Refactor SourcesController destroy method** (2-3 hours) - Extract 61-line method into service object. Reference: `.ai/codebase_audit_2025.md:41-216` - Create `SourceMonitor::Sources::DestroyService` that handles deletion, query rebuilding, metrics recalculation, and returns Result object. Reduce controller method to <15 lines.
|
|
683
|
+
- [x] 20.01.02 **Extract BulkScrapeResultPresenter** (2-3 hours) - Extract 47-line flash message builder from controller. Reference: `.ai/codebase_audit_2025.md:941-1015` - Create `SourceMonitor::Scraping::BulkResultPresenter` that handles all message formatting logic. Testable without mocking view_context.
|
|
684
|
+
- [x] 20.01.03 **Create TurboStreamPresenter for sources** (2-3 hours) - Extract duplicated Turbo Stream response building. Reference: `.ai/codebase_audit_2025.md:90-215` - Create `SourceMonitor::Sources::TurboStreamPresenter` with methods for deletion, heatmap updates, empty state rendering. Consolidate 40+ lines of repeated logic.
|
|
685
|
+
- [x] 20.01.04 **Fix N+1 query in sources index** (1-2 hours) - Pre-calculate activity rates for all sources. Reference: `.ai/codebase_audit_2025.md:220-311` - Ensure `@item_activity_rates` hash contains entries for ALL sources in result set. Update view to never fall back to individual queries. Verify with query log that N+1 is eliminated.
|
|
686
|
+
- [x] 20.01.05 **Remove inline script from turbo_visit partial** (1-2 hours) - Replace inline JavaScript with Turbo Stream action. Reference: `.ai/codebase_audit_2025.md:313-389` - Create custom `StreamActions.redirect` function in `turbo_actions.js`. Update all usages of `_turbo_visit.html.erb` partial. Test CSP compliance.
|
|
687
|
+
|
|
688
|
+
**Acceptance Criteria:**
|
|
689
|
+
|
|
690
|
+
- SourcesController reduced from 356 lines to <200 lines
|
|
691
|
+
- All controller methods <20 lines
|
|
692
|
+
- Zero N+1 queries in sources#index (verify with bullet gem or query log)
|
|
693
|
+
- No inline `<script>` tags in views
|
|
694
|
+
- All tests passing
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
### 20.02 High-Impact DRY Violations - Phase 2 (12-16 hours)
|
|
699
|
+
|
|
700
|
+
**Reference:** `.ai/codebase_audit_2025.md:1226-1262`
|
|
701
|
+
|
|
702
|
+
**Priority:** HIGH - Significant maintainability impact
|
|
703
|
+
|
|
704
|
+
- [x] 20.02.01 **Replace default_scope anti-pattern in Item model** (4-6 hours) - Remove global default_scope for soft deletes. Reference: `.ai/codebase_audit_2025.md:391-452` - Remove `default_scope { where(deleted_at: nil) }`. Add explicit `.active` scope. Update Source associations to use `-> { active }` lambda. Update ALL Item queries in controllers/services to explicitly use `.active`. Update 7+ controller actions and 10+ service objects. Test thoroughly.
|
|
705
|
+
- [x] 20.02.02 **Create validates_url_format method in UrlNormalizable concern** (2-3 hours) - Eliminate 5 duplicated URL validation methods. Reference: `.ai/codebase_audit_2025.md:456-544` - Add `validates_url_format(*attributes)` class method to `lib/source_monitor/models/url_normalizable.rb`. Dynamically define validation methods. Update Source model to use `validates_url_format :feed_url, :website_url`. Update Item model to use `validates_url_format :url, :canonical_url, :comments_url`. Remove 5 manual validation methods.
|
|
706
|
+
- [x] 20.02.03 **Create Loggable concern for shared log behavior** (1-2 hours) - Consolidate FetchLog and ScrapeLog duplicated code. Reference: `.ai/codebase_audit_2025.md:548-626` - Create `app/models/concerns/source_monitor/loggable.rb` with shared validations, scopes, and attribute defaults. Include in both FetchLog and ScrapeLog models. Remove duplicated code from both models.
|
|
707
|
+
- [x] 20.02.04 **Create TurboStreamable concern for response building** (3-4 hours) - DRY up 50+ lines repeated 5+ times. Reference: `.ai/codebase_audit_2025.md:630-736` - **COMPLETE**: Phase 20.01 already created `SourceMonitor::Sources::TurboStreamPresenter` which adequately addresses the major duplication. Remaining duplication in `render_fetch_enqueue_response` and `respond_to_bulk_scrape` serves different purposes and doesn't warrant a generic concern. Presenter pattern is superior to a generic concern for these use cases.
|
|
708
|
+
- [x] 20.02.05 **Enhance SanitizesSearchParams with query building** (2-3 hours) - Consolidate ransack query setup. Reference: `.ai/codebase_audit_2025.md:740-824` - Add `searchable_with` class method accepting scope and default_sorts. Add `build_search_query` instance method. Update SourcesController and ItemsController to use new DSL. Remove duplicated ransack initialization code from 3+ locations. All duplication eliminated.
|
|
709
|
+
- [x] 20.02.06 **Add NOT NULL database constraints** (2-3 hours) - Enforce critical field constraints at DB level. Reference: `.ai/codebase_audit_2025.md:826-903` - Create migration to add NOT NULL constraints on `items.guid` and `items.url`. Write data cleanup script to handle existing nulls. Run migration and verify constraints applied. All constraints active.
|
|
710
|
+
|
|
711
|
+
**Acceptance Criteria:**
|
|
712
|
+
|
|
713
|
+
- ✅ All Item queries explicitly use `.active` scope
|
|
714
|
+
- ✅ Zero duplicated URL validation methods (5 removed)
|
|
715
|
+
- ✅ Zero duplicated log model code (FetchLog/ScrapeLog share concern)
|
|
716
|
+
- ✅ Turbo Stream response building addressed by Phase 20.01 presenter
|
|
717
|
+
- ✅ Ransack query setup uses DSL (no duplication)
|
|
718
|
+
- ✅ Database enforces NOT NULL on critical fields
|
|
719
|
+
- ✅ All tests passing (266 runs, 1147 assertions)
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
### 20.03 Medium Priority Improvements - Phase 3 (10-15 hours)
|
|
724
|
+
|
|
725
|
+
**Reference:** `.ai/codebase_audit_2025.md:1264-1286`
|
|
726
|
+
|
|
727
|
+
**Priority:** NICE TO HAVE - Quality of life improvements
|
|
728
|
+
|
|
729
|
+
- [x] 20.03.01 **Consolidate after_initialize callbacks** (1 hour) - Use Rails attribute API for defaults. Reference: `.ai/codebase_audit_2025.md:1016-1040` - In Source model, replace 3 `after_initialize` callbacks with `attribute :field, default: -> { value }` declarations. Remove `ensure_hash_defaults`, `ensure_fetch_status_default`, and `ensure_health_defaults` methods.
|
|
730
|
+
- [x] 20.03.02 **Convert due_for_fetch scope to class method** (30 min) - Scopes with variables should be class methods. Reference: `.ai/codebase_audit_2025.md:1042-1067` - Convert `scope :due_for_fetch, lambda { ... }` to `def self.due_for_fetch(reference_time: Time.current)`. Add explicit parameter. Update all callers.
|
|
731
|
+
- [x] 20.03.03 **Refactor routes to be more RESTful** (3-4 hours, OPTIONAL) - Non-RESTful custom member actions. Reference: `.ai/codebase_audit_2025.md:905-940` - Consider creating nested resource controllers: `SourceFetchesController`, `SourceRetriesController`, `SourceBulkScrapesController`. Evaluate effort vs benefit. Document decision. **Decision documented in `.ai/routes_refactor_evaluation.md` - DO NOT REFACTOR.**
|
|
732
|
+
- [x] 20.03.04 **Add Turbo Frame to search forms** (2 hours) - Search submissions trigger full page reloads. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Wrap search forms in Turbo Frame targeting results table. Add debounced search Stimulus controller. Test search without page reload.
|
|
733
|
+
- [x] 20.03.05 **Add Turbo Frame to pagination** (1 hour) - Pagination triggers full page reloads. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Add `data: { turbo_frame: "..." }` to pagination links. Test pagination without page reload. Optional: Add keyboard navigation (arrow keys).
|
|
734
|
+
- [x] 20.03.06 **Fix manual counter cache logic** (2 hours) - Manual counter updates are error-prone. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Wrap `soft_delete!` in transaction. Use `save!` instead of `update_columns`. Add `reset_items_counter!` method to Source. Test counter cache accuracy.
|
|
735
|
+
- [x] 20.03.07 **Tighten scrape_settings strong params** (1 hour) - Overly permissive nested parameters. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Explicitly permit only expected keys under `scrape_settings`: `{ selectors: [:content, :title], timeout: [], javascript_enabled: [] }`. Test rejected params.
|
|
736
|
+
|
|
737
|
+
**Acceptance Criteria:**
|
|
738
|
+
|
|
739
|
+
- ✅ Source model uses attribute API for defaults (3 callbacks removed)
|
|
740
|
+
- ✅ `due_for_fetch` is a class method with explicit parameters
|
|
741
|
+
- ✅ Routes refactoring evaluated and documented (decision: DO NOT REFACTOR)
|
|
742
|
+
- ✅ Search and pagination use Turbo Frames (no page reloads)
|
|
743
|
+
- ✅ Counter cache logic improved with `reset_items_counter!` method
|
|
744
|
+
- ✅ Strong params explicitly list allowed keys for scrape_settings
|
|
745
|
+
- ✅ All tests passing (280 runs, 1180 assertions)
|
|
746
|
+
|
|
747
|
+
---
|
|
748
|
+
|
|
749
|
+
### 20.04 RESTful Routes Refactor - Phase 4 (8 hours, OPTIONAL/DEFERRED)
|
|
750
|
+
|
|
751
|
+
**Reference:** `.ai/routes_refactor_evaluation.md`
|
|
752
|
+
|
|
753
|
+
- [x] 20.04.01 **Create nested resource controllers** (2 hours) - Extract member actions to dedicated controllers. Reference: `.ai/routes_refactor_evaluation.md:44-48` - Create `SourceFetchesController`, `SourceRetriesController`, `SourceBulkScrapesController`. Move action logic from SourcesController. Preserve all before_action filters and helper methods.
|
|
754
|
+
- [x] 20.04.02 **Update routes configuration** (1 hour) - Convert member actions to nested resources. Reference: `.ai/routes_refactor_evaluation.md:57-60` - Update `config/routes.rb` to use nested resource syntax: `resource :fetch, only: [:create]`, etc. Document route changes in CHANGELOG.
|
|
755
|
+
- [x] 20.04.03 **Update all view route helpers** (2 hours) - Update route helpers throughout views. Reference: `.ai/routes_refactor_evaluation.md:62-66` - Update all `link_to` and `button_to` calls from `fetch_source_path` to `source_fetch_path`. Update all Turbo Stream rendering. Update all redirect paths. Verify no broken links.
|
|
756
|
+
- [x] 20.04.04 **Update test suite for new routes** (2 hours) - Update controller and system tests. Reference: `.ai/routes_refactor_evaluation.md:68-72` - Create controller tests for 3 new controllers. Update integration tests. Update system tests. Update all route helper references. Ensure 100% test coverage maintained.
|
|
757
|
+
- [x] 20.04.05 **Testing and validation** (1 hour) - Verify behavioral parity. Reference: `.ai/routes_refactor_evaluation.md:74-81` - Run full test suite. Manual testing of fetch, retry, scrape_all actions. Verify Turbo Stream responses work correctly. Load test with 100+ sources. Document any behavioral changes.
|
|
758
|
+
|
|
759
|
+
**Acceptance Criteria:**
|
|
760
|
+
|
|
761
|
+
- 3 new nested resource controllers created
|
|
762
|
+
- All member actions converted to RESTful nested resources
|
|
763
|
+
- All view route helpers updated
|
|
764
|
+
- All tests passing with same coverage
|
|
765
|
+
- Zero behavioral changes (functional parity maintained)
|
|
766
|
+
- Documentation updated with route changes
|
|
767
|
+
|
|
768
|
+
**When to Reconsider (from evaluation):**
|
|
769
|
+
|
|
770
|
+
- Controllers grow beyond 300 lines (currently ~293 after Phase 20.01-20.02)
|
|
771
|
+
- New team members report confusion about action locations
|
|
772
|
+
- Need to add 5+ more custom actions
|
|
773
|
+
- Performance profiling shows controller bloat affecting response times
|
|
774
|
+
|
|
775
|
+
---
|
|
776
|
+
|
|
777
|
+
### 20.05 Polish & Optimization - Phase 5 (6-10 hours)
|
|
778
|
+
|
|
779
|
+
**Reference:** `.ai/codebase_audit_2025.md:1274-1286`
|
|
780
|
+
|
|
781
|
+
**Priority:** OPTIONAL - Performance and consistency improvements
|
|
782
|
+
|
|
783
|
+
- [x] 20.05.01 **Extract toast delay constants** (30 min) - Magic numbers scattered across controllers. Reference: `.ai/codebase_audit_2025.md:1105-1127` - Add `TOAST_DURATION_DEFAULT = 5000` and `TOAST_DURATION_ERROR = 6000` to ApplicationController. Create `toast_delay_for(level)` helper. Update all toast calls.
|
|
784
|
+
- [x] 20.05.02 **Clean up global event listener** (30 min) - Unused/unclear custom event. Reference: `.ai/codebase_audit_2025.md:1085-1103` - Document purpose of `feed-monitor:form-finished` event or remove if unused. Move to Stimulus controller if needed for cleanup. **Decision: Removed unused event listener.**
|
|
785
|
+
- [x] 20.05.03 **Rename log filtering methods** (1 hour) - Inconsistent naming conventions. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Rename `log_filter_status` to `status_filter`, `log_filter_item_id` to `item_id_filter`. Rename `filter_fetch_logs` to `apply_fetch_log_filters`. Use consistent verb/noun patterns.
|
|
786
|
+
- [x] 20.05.04 **Add performance indexes** (2-3 hours) - Missing indexes for common queries. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Create migration adding: `index_items_on_source_and_created_at_for_rates`, `index_sources_on_active_and_next_fetch` (partial), `index_sources_on_failures` (partial). Analyze query performance before/after.
|
|
787
|
+
- [x] 20.05.05 **Add check constraint on fetch_status enum** (1-2 hours) - Application-level validation only. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Create migration adding PostgreSQL CHECK constraint: `CHECK (fetch_status IN ('idle', 'queued', 'fetching', 'failed'))`. Test invalid status rejection at DB level.
|
|
788
|
+
- [x] 20.05.06 **Optimize dashboard queries with JOINs** (2-3 hours) - Subqueries less efficient than JOINs. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Refactor `SourceMonitor::Dashboard::Queries` correlated subqueries to use LEFT JOINs. Measure query performance improvement. Update `scrape_log_sql` and `item_sql` methods.
|
|
789
|
+
- [x] 20.05.07 **Simplify dropdown controller async import** (30 min, OPTIONAL) - Over-engineered progressive enhancement. Reference: `.ai/codebase_audit_2025.md:1069-1082` - Evaluate static import of stimulus-use vs dynamic import. Document trade-offs. Simplify if benefits outweigh loss of progressive enhancement. **Decision: Keep current implementation, documented reasoning in code.**
|
|
790
|
+
|
|
791
|
+
**Acceptance Criteria:**
|
|
792
|
+
|
|
793
|
+
- ✅ Toast delays use named constants (`TOAST_DURATION_DEFAULT`, `TOAST_DURATION_ERROR`)
|
|
794
|
+
- ✅ Helper method `toast_delay_for(level)` created and used throughout controllers
|
|
795
|
+
- ✅ Unused global event listener removed
|
|
796
|
+
- ✅ Method naming follows consistent verb/noun patterns (all renamed)
|
|
797
|
+
- ✅ Performance indexes added: `index_items_on_source_and_created_at_for_rates`, `index_sources_on_active_and_next_fetch`, `index_sources_on_failures`
|
|
798
|
+
- ✅ Database enforces fetch_status enum constraints with CHECK constraint
|
|
799
|
+
- ✅ Dashboard queries use LEFT JOINs instead of correlated subqueries
|
|
800
|
+
- ✅ Dropdown controller evaluated - decided to keep current implementation with documented reasoning
|
|
801
|
+
- ✅ All 283 tests passing with 1192 assertions
|
|
802
|
+
|
|
803
|
+
---
|
|
804
|
+
|
|
805
|
+
### 20.06 Fix and Optimize Front End asset management for engine
|
|
806
|
+
|
|
807
|
+
**Reference:** `.ai/engine-asset-configuration.md:11-188`
|
|
808
|
+
|
|
809
|
+
- [x] 20.06.01 **Audit current asset tooling and bundler deps** (2h) - Completed. Updated gemspec to include `cssbundling-rails`/`jsbundling-rails`, refreshed `package.json` scripts and dependencies. Reference: `.ai/engine-asset-configuration.md:11-28`.
|
|
810
|
+
- [x] 20.06.02 **Document current dummy app breakage** (1h) - Captured the missing Tailwind/JS failure mode and added troubleshooting guidance referencing the asset guide. Reference: `.ai/engine-asset-configuration.md:11-28`.
|
|
811
|
+
- [x] 20.06.03 **Plan asset directory realignment** (1.5h) - Namespaced builds, images, and svgs per guide recommendations. Reference: `.ai/engine-asset-configuration.md:32-44`.
|
|
812
|
+
- [x] 20.06.04 **Implement bundling pipeline setup** (3h) - Installed bundling toolchain via dummy app flow, established npm build/watch scripts, and added `SourceMonitor::Assets::Bundler`. Reference: `.ai/engine-asset-configuration.md:21-28`.
|
|
813
|
+
- [x] 20.06.05 **Expose asset paths via engine initializer** (1.5h) - Engine initializer now exposes builds/images/svgs for both pipelines. Reference: `.ai/engine-asset-configuration.md:48-76`.
|
|
814
|
+
- [x] 20.06.06 **Add Sprockets precompile automation** (2h) - Added programmable precompile list and tests covering Sprockets discovery. Reference: `.ai/engine-asset-configuration.md:79-113`.
|
|
815
|
+
- [x] 20.06.07 **Assess manifest fallback path** (optional, 1h) - Documented manifest fallback option in configuration docs; keeping programmatic approach as default. Reference: `.ai/engine-asset-configuration.md:114-143`.
|
|
816
|
+
- [x] 20.06.08 **Align asset usage in views/stylesheets** (1.5h) - Layout now loads bundled CSS/JS modules; controllers consume local imports. Reference: `.ai/engine-asset-configuration.md:147-167`.
|
|
817
|
+
- [x] 20.06.09 **Cross-pipeline verification** (2h) - Added automated coverage for asset exposure, verified Propshaft tests, and ensured Sprockets manifests precompile. Reference: `.ai/engine-asset-configuration.md:180-188`.
|
|
818
|
+
- [x] 20.06.10 **Document asset setup & troubleshooting** (1h) - README/config/troubleshooting now call out bundling steps and fallback guidance. Reference: `.ai/engine-asset-configuration.md:11-188`.
|
|
819
|
+
|
|
820
|
+
---
|
|
821
|
+
|
|
822
|
+
### 20.07 Additional Improvements - Phase 6 (Low Priority)
|
|
823
|
+
|
|
824
|
+
**Reference:** `.ai/codebase_audit_2025.md:1105-1127`
|
|
825
|
+
|
|
826
|
+
- [x] 20.07.01 **Consolidate `refreshed` variable naming** - Use `@source.reload` directly or be consistent. Reference: `.ai/codebase_audit_2025.md:1105-1127`
|
|
827
|
+
- [x] 20.07.02 **Document or simplify assign_content_attribute pattern** - Complex delegation logic may be candidate for concern if pattern repeats. Reference: `.ai/codebase_audit_2025.md:1105-1127`
|
|
828
|
+
|
|
829
|
+
**Deliverable for Phase 20:**
|
|
830
|
+
|
|
831
|
+
- SourcesController reduced from 356 lines to <150 lines
|
|
832
|
+
- 5 duplicated validation methods consolidated to 1 concern method
|
|
833
|
+
- Zero N+1 queries verified with bullet gem
|
|
834
|
+
- All inline scripts removed
|
|
835
|
+
- default_scope anti-pattern eliminated
|
|
836
|
+
- 50+ lines of Turbo Stream duplication consolidated
|
|
837
|
+
- Database constraints enforce data integrity
|
|
838
|
+
- Performance indexes added for common queries
|
|
839
|
+
- All tests passing (aim for >90% coverage on changed code)
|
|
840
|
+
|
|
841
|
+
**Testing Strategy for Phase 20:**
|
|
842
|
+
|
|
843
|
+
1. Run full test suite after each subtask
|
|
844
|
+
2. Use bullet gem to verify N+1 query elimination
|
|
845
|
+
3. Use query log to verify index usage
|
|
846
|
+
4. Run brakeman for security validation
|
|
847
|
+
5. Measure controller line count reduction
|
|
848
|
+
6. System tests for all Turbo Frame changes
|
|
849
|
+
7. Load test sources index with 100+ sources
|
|
850
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
## Phase 21: Log UX Improvements
|
|
854
|
+
|
|
855
|
+
**Goal: Consolidate Fetch & Scrape Logs to one unified UX**
|
|
856
|
+
|
|
857
|
+
### 21.01 Consolidate Fetch & Scrape Logs into a single viewing experience
|
|
858
|
+
|
|
859
|
+
- [x] 21.01.01 Inventory current fetch and scrape log views/partials to outline the combined layout, including shared columns and log-type specific metadata
|
|
860
|
+
- [x] 21.01.02 Design a unified log query object/presenter that supports filtering by log type, timeframe ranges, source selection, search terms, and pagination
|
|
861
|
+
- [x] 21.01.03 Implement the consolidated table/section in the UI with filter controls and ensure the controller accepts/validates the new params without duplicating logic
|
|
862
|
+
- [x] 21.01.04 Update instrumentation and documentation to reflect the merged log view and add automated coverage (unit + system) for filtering, searching, and pagination paths
|
|
863
|
+
|
|
864
|
+
**Deliverable: Source management UI exposes clear scraping controls and a single consolidated log explorer**
|
|
865
|
+
**Test: Drive the new controls via system specs to confirm status rendering, bulk scraping, deletions, and log filtering behave as expected**
|
|
866
|
+
|
|
867
|
+
---
|
|
868
|
+
|
|
869
|
+
## Phase 22: Release Readiness & Host Installation Experience
|
|
870
|
+
|
|
871
|
+
**Goal: Ship SourceMonitor as an installable gem with bulletproof host app onboarding**
|
|
872
|
+
|
|
873
|
+
### 22.01 Package Readiness Audit
|
|
874
|
+
|
|
875
|
+
- [x] 22.01.01 Review `source_monitor.gemspec` metadata, dependencies, and executables to match release expectations (homepage, changelog, docs URLs, Ruby/Rails version constraints)
|
|
876
|
+
- [x] 22.01.02 Establish semantic versioning policy and release cadence, updating `.ai/project_overview.md` and `CHANGELOG.md` with the release checklist
|
|
877
|
+
- [x] 22.01.03 Confirm gem build artifacts (`gem build source_monitor.gemspec`) exclude development-only files via `.gemspec` and `.npmignore`/`.gitignore` alignment
|
|
878
|
+
|
|
879
|
+
### 22.02 Fresh Host App Installation Flow
|
|
880
|
+
|
|
881
|
+
- [x] 22.02.01 Script a disposable Rails 8 host app harness (e.g., `tmp/host_app`) that installs the gem from the local path and exercises the install generator
|
|
882
|
+
- [x] 22.02.02 Add automated test suite (bin/rails test or RSpec) that boots the harness, runs `rails g source_monitor:install`, and asserts migrations/routes initializers mount without manual edits
|
|
883
|
+
- [x] 22.02.03 Verify host app retains existing configuration (environment settings, Solid Queue adapter, Action Cable config) by snapshotting before/after diffs in the harness tests
|
|
884
|
+
|
|
885
|
+
### 22.03 Isolation & Compatibility Guarantees
|
|
886
|
+
|
|
887
|
+
- [x] 22.03.01 Audit engine initializers, Railties, and configuration hooks to ensure they no-op when host overrides are present; document guard clauses or configuration fallbacks
|
|
888
|
+
- [x] 22.03.02 Add regression tests ensuring engine generators do not overwrite existing host files (e.g., `config/application.rb`, `config/cable.yml`), using temporary fixtures to simulate conflict scenarios
|
|
889
|
+
- [x] 22.03.03 Validate mounting options for varied host setups (API-only apps, custom queue_db, Redis Action Cable) and record support matrix in docs
|
|
890
|
+
|
|
891
|
+
### 22.04 Installation & Upgrade Documentation
|
|
892
|
+
|
|
893
|
+
- [x] 22.04.01 Produce a dedicated `docs/installation.md` (linked from README) covering Gemfile entry, bundle install, generator invocation, migrations, mount instructions, and Solid Queue prerequisites
|
|
894
|
+
- [x] 22.04.02 Update README quickstart and CHANGELOG release sections with step-by-step upgrade notes (engine migrations, configuration diffs, optional Mission Control integration)
|
|
895
|
+
- [x] 22.04.03 Draft troubleshooting guide for common install issues (missing Solid Queue tables, Tailwind build failures, mission_control-jobs not mounted) and cross-link from generator output
|
|
896
|
+
|
|
897
|
+
### 22.05 Release Pipeline & Quality Gates
|
|
898
|
+
|
|
899
|
+
- [x] 22.05.01 Create release automation task (e.g., `bin/release`) that runs the full set of quality gates (`bin/rubocop`, `bin/brakeman`, `bin/test-coverage`, `bin/check-diff-coverage`), builds the gem, and tags versions with an annotated changelog entry
|
|
900
|
+
- [x] 22.05.02 Expand CI with a release-verification job that installs the built gem into the disposable host app harness, runs the install generator and smoke tests, and reuses stored coverage to fail if diff coverage or harness assertions regress
|
|
901
|
+
- [x] 22.05.03 Document manual release verification in `.ai/release_checklist.md`, including checking coverage artifacts/baseline freshness, gem size, README rendering on RubyGems, and confirmation that `bin/release` + the release-verification job both passed
|
|
902
|
+
|
|
903
|
+
### 22.06 Failure Recovery Experience
|
|
904
|
+
|
|
905
|
+
- [x] 22.06.01 Replace failing/auto-paused status badges with dropdown triggers (sources index + show) that expose recovery actions alongside concise helper copy, wired up with Turbo streams.
|
|
906
|
+
- [x] 22.06.02 Hook existing "Fetch Now" runner into a dropdown action that queues a full fetch, swaps the badge for an inline `Processing` state with spinner, and emits a toast confirmation via Turbo.
|
|
907
|
+
- [x] 22.06.03 Add a lightweight health-check job that enqueues through Solid Queue, performs a single fetch request without mutating items, records a dedicated log entry, and surfaces completion through the shared inline + toast UI.
|
|
908
|
+
- [x] 22.06.04 Implement "Reset to Active Status" for auto-paused sources to clear pause/backoff timestamps, failure counters, last error metadata, and restore the next fetch interval using source-level override or global default.
|
|
909
|
+
- [x] 22.06.05 Expand system/unit coverage to exercise dropdown UX, Turbo responses, log visibility, and state-reset behaviors for both failing and auto-paused sources.
|
|
910
|
+
|
|
911
|
+
**Deliverable: Operators can recover failing or auto-paused sources inline with Turbo-powered dropdowns, clear state resets, and auditable logs.**
|
|
912
|
+
**Test: System tests assert badge-to-dropdown flow, spinner/toast feedback, health-check log visibility, and reset-side effects on source scheduling.**
|
|
913
|
+
|
|
914
|
+
**Deliverable: Engine publishes as a gem with automated host app install verification, zero configuration bleed, and clear onboarding docs**
|
|
915
|
+
**Test: Release pipeline builds the gem, CI installs it into a fresh Rails 8 host app, and generator-driven smoke tests pass without modifying host configurations**
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
## Success Criteria Per Phase
|
|
920
|
+
|
|
921
|
+
Each phase must:
|
|
922
|
+
|
|
923
|
+
1. **Install cleanly** in a fresh Rails 8 app
|
|
924
|
+
2. **Not break** existing functionality
|
|
925
|
+
3. **Be testable** via automated tests
|
|
926
|
+
4. **Be usable** immediately via UI or console
|
|
927
|
+
5. **Add tangible value** that can be demonstrated
|
|
928
|
+
|
|
929
|
+
---
|
|
930
|
+
|
|
931
|
+
## Phase 23: Test Suite Performance Guardrails
|
|
932
|
+
|
|
933
|
+
- [x] 23.01 Add TestProf tooling and helpers for Minitest (TagProf, EventProf, StackProf, setup_once support)
|
|
934
|
+
- [x] 23.02 Optimize slow integration/lib suites, introduce smoke test target, and remove redundant DB writes
|
|
935
|
+
- [x] 23.03 Automate profiling in CI with guardrails and document contributor guidelines
|
|
936
|
+
|
|
937
|
+
## Testing Strategy
|
|
938
|
+
|
|
939
|
+
- **Unit Tests**: Every service, model, job
|
|
940
|
+
- **Integration Tests**: Full workflows with VCR
|
|
941
|
+
- **System Tests**: UI interactions with Capybara
|
|
942
|
+
- **Contract Tests**: Adapter interfaces
|
|
943
|
+
- **Performance Tests**: Benchmarks for large datasets
|
|
944
|
+
|
|
945
|
+
## Key Design Principles
|
|
946
|
+
|
|
947
|
+
1. **Rails 8 Native**: Use Rails 8 defaults (Solid Queue, Solid Cache, Turbo)
|
|
948
|
+
2. **Minimal Dependencies**: Tailwind + essential gems only
|
|
949
|
+
3. **Thin Vertical Slices**: Each phase is immediately testable
|
|
950
|
+
4. **Progressive Enhancement**: Start simple, add features incrementally
|
|
951
|
+
5. **Host App Extensibility**: Hooks for customization without forking
|
|
952
|
+
6. **Production Ready**: Security, performance, and observability built-in
|