source_monitor 0.3.3 → 0.5.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/.claude/commands/release.md +101 -58
- data/.claude/skills/sm-configure/SKILL.md +13 -2
- data/.claude/skills/sm-configure/reference/configuration-reference.md +33 -0
- data/.claude/skills/sm-host-setup/SKILL.md +18 -2
- data/.claude/skills/sm-host-setup/reference/setup-checklist.md +33 -0
- data/.claude/skills/sm-job/SKILL.md +1 -1
- data/.claude/skills/sm-upgrade/SKILL.md +102 -0
- data/.claude/skills/sm-upgrade/reference/upgrade-workflow.md +92 -0
- data/.claude/skills/sm-upgrade/reference/version-history.md +68 -0
- data/.vbw-planning/SHIPPED.md +35 -0
- data/.vbw-planning/config.json +24 -1
- data/.vbw-planning/discovery.json +3 -1
- data/.vbw-planning/{REQUIREMENTS.md → milestones/generator-enhancements/REQUIREMENTS.md} +22 -0
- data/.vbw-planning/milestones/generator-enhancements/ROADMAP.md +125 -0
- data/.vbw-planning/milestones/generator-enhancements/SHIPPED.md +40 -0
- data/.vbw-planning/milestones/generator-enhancements/STATE.md +43 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/01-CONTEXT.md +33 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/01-VERIFICATION.md +86 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/PLAN-01-SUMMARY.md +61 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/PLAN-01.md +380 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/02-VERIFICATION.md +78 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01-SUMMARY.md +46 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01.md +500 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/03-VERIFICATION.md +89 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/PLAN-01-SUMMARY.md +48 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/PLAN-01.md +456 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/04-VERIFICATION.md +129 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/PLAN-01-SUMMARY.md +70 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/PLAN-01.md +747 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/05-VERIFICATION.md +156 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-01-SUMMARY.md +69 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-01.md +455 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-02-SUMMARY.md +39 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-02.md +488 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/06-VERIFICATION.md +100 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/PLAN-01-SUMMARY.md +37 -0
- data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/PLAN-01.md +345 -0
- data/.vbw-planning/milestones/upgrade-assurance/REQUIREMENTS.md +80 -0
- data/.vbw-planning/milestones/upgrade-assurance/ROADMAP.md +75 -0
- data/.vbw-planning/milestones/upgrade-assurance/STATE.md +29 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/01-VERIFICATION.md +144 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/PLAN-01-SUMMARY.md +43 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/PLAN-01.md +405 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/02-config-deprecation/PLAN-01-SUMMARY.md +27 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/02-config-deprecation/PLAN-01.md +303 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/03-VERIFICATION.md +380 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/PLAN-01-SUMMARY.md +36 -0
- data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/PLAN-01.md +652 -0
- data/CHANGELOG.md +48 -0
- data/CLAUDE.md +5 -3
- data/Gemfile.lock +1 -1
- data/VERSION +1 -1
- data/app/assets/builds/source_monitor/application.css +9 -0
- data/app/helpers/source_monitor/application_helper.rb +38 -0
- data/app/jobs/source_monitor/download_content_images_job.rb +72 -0
- data/app/models/source_monitor/item_content.rb +2 -0
- data/app/views/source_monitor/dashboard/_recent_activity.html.erb +9 -0
- data/app/views/source_monitor/items/_details.html.erb +2 -2
- data/app/views/source_monitor/logs/index.html.erb +9 -0
- data/app/views/source_monitor/sources/_details.html.erb +2 -2
- data/app/views/source_monitor/sources/_row.html.erb +1 -1
- data/docs/setup.md +10 -1
- data/docs/troubleshooting.md +38 -7
- data/docs/upgrade.md +140 -0
- data/lib/generators/source_monitor/install/install_generator.rb +101 -0
- data/lib/source_monitor/configuration/deprecation_registry.rb +237 -0
- data/lib/source_monitor/configuration/http_settings.rb +7 -1
- data/lib/source_monitor/configuration/images_settings.rb +37 -0
- data/lib/source_monitor/configuration.rb +11 -1
- data/lib/source_monitor/dashboard/queries/recent_activity_query.rb +16 -7
- data/lib/source_monitor/dashboard/recent_activity.rb +1 -0
- data/lib/source_monitor/dashboard/recent_activity_presenter.rb +15 -2
- data/lib/source_monitor/fetching/feed_fetcher/entry_processor.rb +13 -0
- data/lib/source_monitor/http.rb +23 -0
- data/lib/source_monitor/images/content_rewriter.rb +81 -0
- data/lib/source_monitor/images/downloader.rb +82 -0
- data/lib/source_monitor/logs/table_presenter.rb +25 -0
- data/lib/source_monitor/setup/cli.rb +7 -0
- data/lib/source_monitor/setup/procfile_patcher.rb +31 -0
- data/lib/source_monitor/setup/queue_config_patcher.rb +84 -0
- data/lib/source_monitor/setup/skills_installer.rb +1 -0
- data/lib/source_monitor/setup/upgrade_command.rb +59 -0
- data/lib/source_monitor/setup/verification/pending_migrations_verifier.rb +92 -0
- data/lib/source_monitor/setup/verification/recurring_schedule_verifier.rb +102 -0
- data/lib/source_monitor/setup/verification/runner.rb +1 -1
- data/lib/source_monitor/setup/verification/solid_queue_verifier.rb +1 -1
- data/lib/source_monitor/setup/workflow.rb +10 -0
- data/lib/source_monitor/version.rb +1 -1
- data/lib/source_monitor.rb +11 -0
- metadata +51 -2
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
---
|
|
2
|
+
phase: 1
|
|
3
|
+
plan: "01"
|
|
4
|
+
title: procfile-queue-generator-steps
|
|
5
|
+
type: execute
|
|
6
|
+
wave: 1
|
|
7
|
+
depends_on: []
|
|
8
|
+
cross_phase_deps: []
|
|
9
|
+
autonomous: true
|
|
10
|
+
effort_override: thorough
|
|
11
|
+
skills_used: []
|
|
12
|
+
files_modified:
|
|
13
|
+
- lib/generators/source_monitor/install/install_generator.rb
|
|
14
|
+
- test/lib/generators/install_generator_test.rb
|
|
15
|
+
- lib/source_monitor/setup/procfile_patcher.rb
|
|
16
|
+
- lib/source_monitor/setup/queue_config_patcher.rb
|
|
17
|
+
- lib/source_monitor/setup/workflow.rb
|
|
18
|
+
- test/lib/source_monitor/setup/workflow_test.rb
|
|
19
|
+
must_haves:
|
|
20
|
+
truths:
|
|
21
|
+
- "Running `bin/rails test test/lib/generators/install_generator_test.rb` exits 0 with 0 failures"
|
|
22
|
+
- "Running `bin/rails test test/lib/source_monitor/setup/workflow_test.rb` exits 0 with 0 failures"
|
|
23
|
+
- "Running `bin/rubocop lib/generators/source_monitor/install/install_generator.rb lib/source_monitor/setup/procfile_patcher.rb lib/source_monitor/setup/queue_config_patcher.rb lib/source_monitor/setup/workflow.rb` exits 0 with no offenses"
|
|
24
|
+
- "Running the generator against an empty destination creates a Procfile.dev with both `web:` and `jobs:` lines"
|
|
25
|
+
- "Running the generator against an existing Procfile.dev that has no `jobs:` line appends one"
|
|
26
|
+
- "Running the generator against an existing Procfile.dev that already has a `jobs:` line skips with say_status :skip"
|
|
27
|
+
- "Running the generator against a queue.yml with dispatchers but no recurring_schedule adds it"
|
|
28
|
+
- "Running the generator against a queue.yml that already has recurring_schedule skips"
|
|
29
|
+
artifacts:
|
|
30
|
+
- path: "lib/generators/source_monitor/install/install_generator.rb"
|
|
31
|
+
provides: "Procfile.dev and queue.yml generator steps"
|
|
32
|
+
contains: "def patch_procfile_dev"
|
|
33
|
+
- path: "lib/generators/source_monitor/install/install_generator.rb"
|
|
34
|
+
provides: "queue.yml dispatcher patching"
|
|
35
|
+
contains: "def configure_queue_dispatcher"
|
|
36
|
+
- path: "test/lib/generators/install_generator_test.rb"
|
|
37
|
+
provides: "Tests for both new generator steps"
|
|
38
|
+
contains: "test_creates_procfile_dev_when_none_exists"
|
|
39
|
+
- path: "lib/source_monitor/setup/procfile_patcher.rb"
|
|
40
|
+
provides: "Workflow helper for Procfile.dev patching"
|
|
41
|
+
contains: "class ProcfilePatcher"
|
|
42
|
+
- path: "lib/source_monitor/setup/queue_config_patcher.rb"
|
|
43
|
+
provides: "Workflow helper for queue.yml patching"
|
|
44
|
+
contains: "class QueueConfigPatcher"
|
|
45
|
+
- path: "lib/source_monitor/setup/workflow.rb"
|
|
46
|
+
provides: "Workflow integration of both new steps"
|
|
47
|
+
contains: "procfile_patcher"
|
|
48
|
+
key_links:
|
|
49
|
+
- from: "install_generator.rb#patch_procfile_dev"
|
|
50
|
+
to: "REQ-16"
|
|
51
|
+
via: "Generator patches Procfile.dev with jobs: entry"
|
|
52
|
+
- from: "install_generator.rb#configure_queue_dispatcher"
|
|
53
|
+
to: "REQ-17"
|
|
54
|
+
via: "Generator patches queue config with recurring_schedule"
|
|
55
|
+
- from: "workflow.rb"
|
|
56
|
+
to: "REQ-18"
|
|
57
|
+
via: "Guided workflow integrates both new steps"
|
|
58
|
+
---
|
|
59
|
+
<objective>
|
|
60
|
+
Add two new idempotent steps to the install generator (Procfile.dev patching and queue.yml dispatcher wiring) and integrate both into the guided Setup::Workflow. All steps must follow existing generator conventions: idempotent, skip-if-present, say_status output. REQ-16, REQ-17, REQ-18.
|
|
61
|
+
</objective>
|
|
62
|
+
<context>
|
|
63
|
+
@lib/generators/source_monitor/install/install_generator.rb -- The existing generator with 3 public steps: add_routes_mount, create_initializer, configure_recurring_jobs. New steps must be added as public methods BEFORE print_next_steps (Rails generators execute public methods in definition order). Each step follows the pattern: check-if-already-done -> skip with say_status :skip OR perform action with say_status :create/:append. The recurring jobs step is the best pattern to follow -- it handles both fresh-file and existing-file cases with YAML parsing.
|
|
64
|
+
|
|
65
|
+
@test/lib/generators/install_generator_test.rb -- 11 existing tests using Rails::Generators::TestCase. Tests use `run_generator` to execute, `assert_file` to check contents, and manually create pre-existing files in `destination_root` to test idempotent skip paths. The WORKER_SUFFIX pattern handles parallel test isolation. New tests should follow the same patterns.
|
|
66
|
+
|
|
67
|
+
@lib/source_monitor/setup/workflow.rb -- The guided installer. Collaborators are injected via constructor kwargs with defaults. The `run` method calls them in sequence. New patchers should be added AFTER `install_generator.run` (which runs the generator) and BEFORE `verifier.call`. Two new kwargs needed: `procfile_patcher:` and `queue_config_patcher:`.
|
|
68
|
+
|
|
69
|
+
@lib/source_monitor/setup/install_generator.rb -- Existing wrapper that shells out to `bin/rails generate source_monitor:install`. The generator handles Procfile.dev and queue.yml, so the workflow helpers only need to handle the guided-mode post-generator patching if the generator didn't run (edge case) OR to provide explicit say-status output in the guided flow. However, since the workflow already delegates to the generator, the simplest approach is to add the patching logic directly to the generator (which the workflow already calls) and add lightweight workflow helpers that handle standalone guided-mode usage.
|
|
70
|
+
|
|
71
|
+
@test/lib/source_monitor/setup/workflow_test.rb -- Uses Spy objects and Minitest::Mock for all collaborators. New patchers need Spy instances in test setup. Existing test "run orchestrates all installers" expects a specific prompter call count -- adding new steps MUST NOT add new prompter calls (the patching is unconditional, no user prompt needed).
|
|
72
|
+
|
|
73
|
+
@.vbw-planning/phases/01-generator-steps/01-CONTEXT.md -- Phase context with user decisions and acceptance criteria.
|
|
74
|
+
|
|
75
|
+
**Rationale:** The generator is the primary entry point -- both `bin/rails g source_monitor:install` and the guided workflow funnel through it. Adding the steps directly to the generator ensures both paths are covered. The workflow helpers provide explicit visibility in the guided flow.
|
|
76
|
+
|
|
77
|
+
**Key design decisions:**
|
|
78
|
+
1. Procfile.dev default content: `web: bin/rails server -p 3000\njobs: bundle exec rake solid_queue:start` (standard Rails 8 Procfile.dev pattern)
|
|
79
|
+
2. The `jobs:` line check should match any line starting with `jobs:` (case-sensitive, anchored to line start)
|
|
80
|
+
3. Queue.yml patching targets any dispatcher block under any environment key and adds `recurring_schedule: config/recurring.yml` if not present
|
|
81
|
+
4. Queue.yml patching must handle both `default: &default` with env aliases AND flat per-environment configs
|
|
82
|
+
5. If queue.yml does not exist, skip with a helpful message (the file is Rails-generated; creating it from scratch could conflict with the host app's queue backend choice)
|
|
83
|
+
</context>
|
|
84
|
+
<tasks>
|
|
85
|
+
<task type="auto">
|
|
86
|
+
<name>add-procfile-dev-generator-step</name>
|
|
87
|
+
<files>
|
|
88
|
+
lib/generators/source_monitor/install/install_generator.rb
|
|
89
|
+
</files>
|
|
90
|
+
<action>
|
|
91
|
+
Add a new public method `patch_procfile_dev` to InstallGenerator, placed AFTER `configure_recurring_jobs` and BEFORE `print_next_steps`. This ensures Rails generators execute it in the correct order.
|
|
92
|
+
|
|
93
|
+
The method must:
|
|
94
|
+
1. Build the Procfile.dev path: `File.join(destination_root, "Procfile.dev")`
|
|
95
|
+
2. If the file exists AND already contains a line matching `/^jobs:/` -> `say_status :skip, "Procfile.dev (jobs entry already present)", :yellow` and return
|
|
96
|
+
3. If the file exists but has no `jobs:` line -> append `\njobs: bundle exec rake solid_queue:start\n` to the file, then `say_status :append, "Procfile.dev", :green`
|
|
97
|
+
4. If the file does not exist -> create it with content:
|
|
98
|
+
```
|
|
99
|
+
web: bin/rails server -p 3000
|
|
100
|
+
jobs: bundle exec rake solid_queue:start
|
|
101
|
+
```
|
|
102
|
+
Then `say_status :create, "Procfile.dev", :green`
|
|
103
|
+
|
|
104
|
+
Add a private constant for the jobs line:
|
|
105
|
+
```ruby
|
|
106
|
+
PROCFILE_JOBS_ENTRY = "jobs: bundle exec rake solid_queue:start"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Update `print_next_steps` to mention Procfile.dev:
|
|
110
|
+
```ruby
|
|
111
|
+
say_status :info,
|
|
112
|
+
"Procfile.dev configured -- run bin/dev to start both web server and Solid Queue workers.",
|
|
113
|
+
:green
|
|
114
|
+
```
|
|
115
|
+
</action>
|
|
116
|
+
<verify>
|
|
117
|
+
Read the modified file and confirm: (a) `patch_procfile_dev` is defined between `configure_recurring_jobs` and `print_next_steps`, (b) it handles all 3 cases (create, append, skip), (c) the PROCFILE_JOBS_ENTRY constant is in the private section.
|
|
118
|
+
</verify>
|
|
119
|
+
<done>
|
|
120
|
+
The generator has a `patch_procfile_dev` method that creates, appends to, or skips Procfile.dev depending on current state. The method follows the same idempotent pattern as `configure_recurring_jobs`.
|
|
121
|
+
</done>
|
|
122
|
+
</task>
|
|
123
|
+
<task type="auto">
|
|
124
|
+
<name>add-queue-config-generator-step</name>
|
|
125
|
+
<files>
|
|
126
|
+
lib/generators/source_monitor/install/install_generator.rb
|
|
127
|
+
</files>
|
|
128
|
+
<action>
|
|
129
|
+
Add a new public method `configure_queue_dispatcher` to InstallGenerator, placed AFTER `patch_procfile_dev` and BEFORE `print_next_steps`.
|
|
130
|
+
|
|
131
|
+
The method must:
|
|
132
|
+
1. Build the queue.yml path: `File.join(destination_root, "config/queue.yml")`
|
|
133
|
+
2. If the file does not exist -> `say_status :skip, "config/queue.yml (file not found -- create it or run rails app:update to generate)", :yellow` and return
|
|
134
|
+
3. Read and parse the YAML with `YAML.safe_load(File.read(path), aliases: true)`
|
|
135
|
+
4. If the parsed content already contains `recurring_schedule` anywhere in any dispatcher entry -> `say_status :skip, "config/queue.yml (recurring_schedule already configured)", :yellow` and return
|
|
136
|
+
5. Otherwise, find dispatcher entries and add `"recurring_schedule" => "config/recurring.yml"` to each one. The structure is:
|
|
137
|
+
- Environment-based: `{ "default" => { "dispatchers" => [{ "polling_interval" => 1 }] } }`
|
|
138
|
+
- Or flat: `{ "dispatchers" => [{ "polling_interval" => 1 }] }`
|
|
139
|
+
6. Write back the modified YAML and `say_status :append, "config/queue.yml (added recurring_schedule to dispatchers)", :green`
|
|
140
|
+
|
|
141
|
+
Add a private helper `queue_config_has_recurring_schedule?(parsed)` that recursively checks if any hash value under `dispatchers` contains `recurring_schedule`.
|
|
142
|
+
|
|
143
|
+
Add a private helper `add_recurring_schedule_to_dispatchers!(parsed)` that walks the parsed hash and adds `"recurring_schedule" => "config/recurring.yml"` to each dispatcher hash that lacks it.
|
|
144
|
+
|
|
145
|
+
**Important edge case:** If the queue.yml has no `dispatchers` key at any level, add a default dispatcher section:
|
|
146
|
+
```yaml
|
|
147
|
+
dispatchers:
|
|
148
|
+
- polling_interval: 1
|
|
149
|
+
batch_size: 500
|
|
150
|
+
recurring_schedule: config/recurring.yml
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Write back using `YAML.dump` (the file is machine-managed YAML, not hand-formatted like recurring.yml).
|
|
154
|
+
</action>
|
|
155
|
+
<verify>
|
|
156
|
+
Read the modified file and confirm: (a) `configure_queue_dispatcher` is defined between `patch_procfile_dev` and `print_next_steps`, (b) it handles all cases (missing file, already configured, needs patching, no dispatchers key), (c) helper methods are private.
|
|
157
|
+
</verify>
|
|
158
|
+
<done>
|
|
159
|
+
The generator has a `configure_queue_dispatcher` method that patches queue.yml dispatchers with recurring_schedule. It handles missing files, already-configured files, and files needing patching.
|
|
160
|
+
</done>
|
|
161
|
+
</task>
|
|
162
|
+
<task type="auto">
|
|
163
|
+
<name>add-generator-tests</name>
|
|
164
|
+
<files>
|
|
165
|
+
test/lib/generators/install_generator_test.rb
|
|
166
|
+
</files>
|
|
167
|
+
<action>
|
|
168
|
+
Add the following tests to InstallGeneratorTest, following existing patterns:
|
|
169
|
+
|
|
170
|
+
**Procfile.dev tests:**
|
|
171
|
+
|
|
172
|
+
1. `test_creates_procfile_dev_when_none_exists` -- Run generator, assert Procfile.dev exists with both `web:` and `jobs:` lines.
|
|
173
|
+
|
|
174
|
+
2. `test_appends_jobs_entry_to_existing_procfile_dev` -- Create a Procfile.dev with only `web: bin/rails server -p 3000`, run generator, assert file now contains `jobs:` line AND still contains `web:` line.
|
|
175
|
+
|
|
176
|
+
3. `test_skips_procfile_dev_when_jobs_entry_already_present` -- Create a Procfile.dev with `web:` and `jobs:` lines, run generator, capture output, assert output contains "skip".
|
|
177
|
+
|
|
178
|
+
4. `test_does_not_duplicate_jobs_entry_when_rerun` -- Run generator twice, assert Procfile.dev contains exactly 1 line matching `/^jobs:/`.
|
|
179
|
+
|
|
180
|
+
**Queue config tests:**
|
|
181
|
+
|
|
182
|
+
5. `test_patches_queue_yml_dispatcher_with_recurring_schedule` -- Create a config/queue.yml with dispatchers section (no recurring_schedule), run generator, assert file contains `recurring_schedule`.
|
|
183
|
+
|
|
184
|
+
6. `test_skips_queue_yml_when_recurring_schedule_already_present` -- Create a config/queue.yml that already has `recurring_schedule: config/recurring.yml` in the dispatcher, run generator, capture output, assert output contains "skip".
|
|
185
|
+
|
|
186
|
+
7. `test_skips_queue_yml_when_file_missing` -- Do NOT create config/queue.yml, run generator, capture output, assert output contains "skip" and "not found".
|
|
187
|
+
|
|
188
|
+
8. `test_adds_default_dispatcher_when_none_exists_in_queue_yml` -- Create a config/queue.yml with queues but no dispatchers section, run generator, assert file now contains both `dispatchers` and `recurring_schedule`.
|
|
189
|
+
|
|
190
|
+
For queue.yml tests, create realistic YAML content matching the Rails 8 default structure (from host_app_harness.rb):
|
|
191
|
+
```yaml
|
|
192
|
+
default: &default
|
|
193
|
+
dispatchers:
|
|
194
|
+
- polling_interval: 1
|
|
195
|
+
batch_size: 500
|
|
196
|
+
workers:
|
|
197
|
+
- queues: "*"
|
|
198
|
+
threads: 3
|
|
199
|
+
polling_interval: 0.1
|
|
200
|
+
|
|
201
|
+
development:
|
|
202
|
+
<<: *default
|
|
203
|
+
|
|
204
|
+
test:
|
|
205
|
+
<<: *default
|
|
206
|
+
|
|
207
|
+
production:
|
|
208
|
+
<<: *default
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Use `File.join(destination_root, "config")` + `FileUtils.mkdir_p` to create pre-existing files, matching the pattern from `test_merges_into_existing_recurring_yml_with_default_key`.
|
|
212
|
+
</action>
|
|
213
|
+
<verify>
|
|
214
|
+
Run `PARALLEL_WORKERS=1 bin/rails test test/lib/generators/install_generator_test.rb` and confirm all tests pass (existing + new). Run `bin/rubocop test/lib/generators/install_generator_test.rb` and confirm no offenses.
|
|
215
|
+
</verify>
|
|
216
|
+
<done>
|
|
217
|
+
8 new tests covering all Procfile.dev and queue.yml scenarios. All 19 tests (11 existing + 8 new) pass. RuboCop clean.
|
|
218
|
+
</done>
|
|
219
|
+
</task>
|
|
220
|
+
<task type="auto">
|
|
221
|
+
<name>add-workflow-helpers-and-integration</name>
|
|
222
|
+
<files>
|
|
223
|
+
lib/source_monitor/setup/procfile_patcher.rb
|
|
224
|
+
lib/source_monitor/setup/queue_config_patcher.rb
|
|
225
|
+
lib/source_monitor/setup/workflow.rb
|
|
226
|
+
test/lib/source_monitor/setup/workflow_test.rb
|
|
227
|
+
</files>
|
|
228
|
+
<action>
|
|
229
|
+
**Create `lib/source_monitor/setup/procfile_patcher.rb`:**
|
|
230
|
+
|
|
231
|
+
Follow the pattern from `install_generator.rb` (the setup wrapper, not the Rails generator). This is a lightweight wrapper that patches Procfile.dev in the host app's root directory. Since the Rails generator already handles this when run via `bin/rails g source_monitor:install`, this helper exists for guided workflow usage where explicit step visibility is desired.
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
# frozen_string_literal: true
|
|
235
|
+
|
|
236
|
+
module SourceMonitor
|
|
237
|
+
module Setup
|
|
238
|
+
class ProcfilePatcher
|
|
239
|
+
JOBS_ENTRY = "jobs: bundle exec rake solid_queue:start"
|
|
240
|
+
|
|
241
|
+
def initialize(path: "Procfile.dev")
|
|
242
|
+
@path = Pathname.new(path)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def patch
|
|
246
|
+
if path.exist?
|
|
247
|
+
content = path.read
|
|
248
|
+
return false if content.match?(/^jobs:/)
|
|
249
|
+
path.open("a") { |f| f.puts("", JOBS_ENTRY) }
|
|
250
|
+
else
|
|
251
|
+
path.write("web: bin/rails server -p 3000\n#{JOBS_ENTRY}\n")
|
|
252
|
+
end
|
|
253
|
+
true
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
private
|
|
257
|
+
|
|
258
|
+
attr_reader :path
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Create `lib/source_monitor/setup/queue_config_patcher.rb`:**
|
|
265
|
+
|
|
266
|
+
```ruby
|
|
267
|
+
# frozen_string_literal: true
|
|
268
|
+
|
|
269
|
+
require "yaml"
|
|
270
|
+
|
|
271
|
+
module SourceMonitor
|
|
272
|
+
module Setup
|
|
273
|
+
class QueueConfigPatcher
|
|
274
|
+
RECURRING_SCHEDULE_VALUE = "config/recurring.yml"
|
|
275
|
+
|
|
276
|
+
def initialize(path: "config/queue.yml")
|
|
277
|
+
@path = Pathname.new(path)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def patch
|
|
281
|
+
return false unless path.exist?
|
|
282
|
+
|
|
283
|
+
parsed = YAML.safe_load(path.read, aliases: true) || {}
|
|
284
|
+
return false if has_recurring_schedule?(parsed)
|
|
285
|
+
|
|
286
|
+
add_recurring_schedule!(parsed)
|
|
287
|
+
path.write(YAML.dump(parsed))
|
|
288
|
+
true
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
private
|
|
292
|
+
|
|
293
|
+
attr_reader :path
|
|
294
|
+
|
|
295
|
+
# (include the same recursive helpers as the generator)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Modify `lib/source_monitor/setup/workflow.rb`:**
|
|
302
|
+
|
|
303
|
+
1. Add `require_relative "procfile_patcher"` and `require_relative "queue_config_patcher"` at the top (after existing require_relative lines).
|
|
304
|
+
2. Add two new kwargs to `initialize`: `procfile_patcher: ProcfilePatcher.new` and `queue_config_patcher: QueueConfigPatcher.new`.
|
|
305
|
+
3. Store them as instance variables and add to `attr_reader`.
|
|
306
|
+
4. In the `run` method, call both AFTER `initializer_patcher.ensure_navigation_hint` and BEFORE the devise check:
|
|
307
|
+
```ruby
|
|
308
|
+
procfile_patcher.patch
|
|
309
|
+
queue_config_patcher.patch
|
|
310
|
+
```
|
|
311
|
+
These are unconditional (no user prompt -- maximum hand-holding per user decision).
|
|
312
|
+
|
|
313
|
+
**Modify `test/lib/source_monitor/setup/workflow_test.rb`:**
|
|
314
|
+
|
|
315
|
+
1. In the "run orchestrates all installers" test: add `procfile_patcher = Spy.new(true)` and `queue_config_patcher = Spy.new(true)`, pass them to `Workflow.new`, and assert `assert_equal :patch, procfile_patcher.calls.first.first` and `assert_equal :patch, queue_config_patcher.calls.first.first`.
|
|
316
|
+
2. In ALL other tests that construct a Workflow: add `procfile_patcher: Spy.new(true)` and `queue_config_patcher: Spy.new(true)` kwargs to prevent test failures from missing the new required collaborators (they have defaults, but the Spy pattern is used for isolation).
|
|
317
|
+
</action>
|
|
318
|
+
<verify>
|
|
319
|
+
Run `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/workflow_test.rb` and confirm all tests pass. Run `bin/rubocop lib/source_monitor/setup/procfile_patcher.rb lib/source_monitor/setup/queue_config_patcher.rb lib/source_monitor/setup/workflow.rb` and confirm no offenses.
|
|
320
|
+
</verify>
|
|
321
|
+
<done>
|
|
322
|
+
Two new workflow helper classes created. Workflow.rb wires both patchers into the guided install flow. All workflow tests pass with the new collaborators injected. RuboCop clean.
|
|
323
|
+
</done>
|
|
324
|
+
</task>
|
|
325
|
+
<task type="auto">
|
|
326
|
+
<name>full-suite-verification</name>
|
|
327
|
+
<files>
|
|
328
|
+
lib/generators/source_monitor/install/install_generator.rb
|
|
329
|
+
test/lib/generators/install_generator_test.rb
|
|
330
|
+
lib/source_monitor/setup/workflow.rb
|
|
331
|
+
test/lib/source_monitor/setup/workflow_test.rb
|
|
332
|
+
</files>
|
|
333
|
+
<action>
|
|
334
|
+
Run the full test suite and linting to confirm no regressions:
|
|
335
|
+
|
|
336
|
+
1. `PARALLEL_WORKERS=1 bin/rails test test/lib/generators/install_generator_test.rb test/lib/source_monitor/setup/workflow_test.rb` -- all targeted tests pass
|
|
337
|
+
2. `bin/rails test` -- full suite passes with 841+ runs and 0 failures
|
|
338
|
+
3. `bin/rubocop` -- zero offenses
|
|
339
|
+
4. Review the final state of all modified files to confirm:
|
|
340
|
+
- Generator public methods are in correct order: add_routes_mount, create_initializer, configure_recurring_jobs, patch_procfile_dev, configure_queue_dispatcher, print_next_steps
|
|
341
|
+
- All new private methods and constants are in the private section
|
|
342
|
+
- Workflow constructor has all collaborators with sensible defaults
|
|
343
|
+
- Workflow.run calls patchers in correct position (after generator, before verifier)
|
|
344
|
+
|
|
345
|
+
If any test failures or RuboCop offenses are found, fix them before completing.
|
|
346
|
+
</action>
|
|
347
|
+
<verify>
|
|
348
|
+
`bin/rails test` exits 0 with 841+ runs, 0 failures. `bin/rubocop` exits 0 with 0 offenses. `bin/brakeman --no-pager` exits 0 with 0 warnings.
|
|
349
|
+
</verify>
|
|
350
|
+
<done>
|
|
351
|
+
Full test suite passes. RuboCop clean. Brakeman clean. All REQ-16, REQ-17, REQ-18 acceptance criteria met.
|
|
352
|
+
</done>
|
|
353
|
+
</task>
|
|
354
|
+
</tasks>
|
|
355
|
+
<verification>
|
|
356
|
+
1. `PARALLEL_WORKERS=1 bin/rails test test/lib/generators/install_generator_test.rb` -- 19+ tests pass (11 existing + 8 new)
|
|
357
|
+
2. `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/workflow_test.rb` -- all workflow tests pass
|
|
358
|
+
3. `bin/rails test` -- 841+ runs, 0 failures
|
|
359
|
+
4. `bin/rubocop` -- 0 offenses
|
|
360
|
+
5. `bin/brakeman --no-pager` -- 0 warnings
|
|
361
|
+
6. `grep -n 'def patch_procfile_dev' lib/generators/source_monitor/install/install_generator.rb` returns a match
|
|
362
|
+
7. `grep -n 'def configure_queue_dispatcher' lib/generators/source_monitor/install/install_generator.rb` returns a match
|
|
363
|
+
8. `grep -n 'procfile_patcher' lib/source_monitor/setup/workflow.rb` returns matches in initialize and run
|
|
364
|
+
9. `grep -n 'queue_config_patcher' lib/source_monitor/setup/workflow.rb` returns matches in initialize and run
|
|
365
|
+
</verification>
|
|
366
|
+
<success_criteria>
|
|
367
|
+
- Generator creates Procfile.dev with web: + jobs: entries when none exists (REQ-16)
|
|
368
|
+
- Generator appends jobs: entry to existing Procfile.dev without duplicating (REQ-16)
|
|
369
|
+
- Generator skips Procfile.dev when jobs: entry already present (REQ-16 idempotency)
|
|
370
|
+
- Generator patches queue.yml dispatchers with recurring_schedule (REQ-17)
|
|
371
|
+
- Generator skips queue.yml when recurring_schedule already configured (REQ-17 idempotency)
|
|
372
|
+
- Generator handles missing queue.yml gracefully (REQ-17 edge case)
|
|
373
|
+
- Guided workflow runs both patchers after generator step (REQ-18)
|
|
374
|
+
- All existing tests continue to pass (no regressions)
|
|
375
|
+
- 8+ new generator tests cover all scenarios
|
|
376
|
+
- RuboCop clean, Brakeman clean
|
|
377
|
+
</success_criteria>
|
|
378
|
+
<output>
|
|
379
|
+
.vbw-planning/phases/01-generator-steps/PLAN-01-SUMMARY.md
|
|
380
|
+
</output>
|
data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/02-VERIFICATION.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# PLAN-01 Verification Report: recurring-schedule-verifier
|
|
2
|
+
|
|
3
|
+
**Verifier:** QA Agent (deep tier, 30 checks)
|
|
4
|
+
**Date:** 2026-02-11
|
|
5
|
+
**Verdict:** PASS
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Functional Checks (1-5)
|
|
10
|
+
|
|
11
|
+
| # | Check | Result | Details |
|
|
12
|
+
|---|-------|--------|---------|
|
|
13
|
+
| 1 | `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/` | PASS | 19 runs, 65 assertions, 0 failures, 0 errors |
|
|
14
|
+
| 2 | `bin/rails test` (full suite) | PASS | 874 runs, 2926 assertions, 0 failures, 0 errors |
|
|
15
|
+
| 3 | `bin/rubocop` (modified files) | PASS | 6 files inspected, 0 offenses |
|
|
16
|
+
| 4 | `bin/brakeman --no-pager` | PASS | 0 warnings, 0 errors |
|
|
17
|
+
| 5 | `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/runner_test.rb` | PASS | 2 runs, 8 assertions, 0 failures |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Code Review (6-20)
|
|
22
|
+
|
|
23
|
+
| # | Check | Result | Details |
|
|
24
|
+
|---|-------|--------|---------|
|
|
25
|
+
| 6 | RecurringScheduleVerifier follows same pattern as SolidQueueVerifier | PASS | Same structure: constructor with DI defaults, `call` with guard clauses + branching + rescue, private helpers, Result factory methods. Module nesting matches: `SourceMonitor::Setup::Verification::RecurringScheduleVerifier` |
|
|
26
|
+
| 7 | Constructor uses dependency injection (`task_relation`, `connection`) | PASS | `def initialize(task_relation: default_task_relation, connection: default_connection)` -- keyword args with private default methods, identical pattern to SolidQueueVerifier's `process_relation:` / `connection:` |
|
|
27
|
+
| 8 | `call` method returns Result with proper key/name/status | PASS | All paths return `Result.new(key: :recurring_schedule, name: "Recurring Schedule", status: ...)` via `ok_result`, `warning_result`, `error_result` helpers |
|
|
28
|
+
| 9 | All 5 branches covered (ok, 2x warning, 2x error + rescue) | PASS | Lines 16 (missing gem error), 17 (missing table error), 22-23 (ok), 24-28 (warning: non-SM tasks), 29-33 (warning: no tasks), 35-39 (rescue error). Six distinct branches total (5 explicit + 1 rescue), all tested |
|
|
29
|
+
| 10 | SourceMonitor task detection logic (key prefix, class_name, command) | PASS | `source_monitor_tasks` method checks: `task.key.start_with?(SOURCE_MONITOR_KEY_PREFIX)` OR `task.class_name.to_s.start_with?(SOURCE_MONITOR_NAMESPACE)` OR `task.command.to_s.include?(SOURCE_MONITOR_NAMESPACE)`. `.to_s` on class_name/command handles nil safely |
|
|
30
|
+
| 11 | `frozen_string_literal` on new files | PASS | Both `recurring_schedule_verifier.rb` (line 1) and `recurring_schedule_verifier_test.rb` (line 1) have `# frozen_string_literal: true` |
|
|
31
|
+
| 12 | Private methods properly scoped | PASS | `private` keyword at line 42, followed by `attr_reader`, `default_task_relation`, `default_connection`, `tables_present?`, `all_tasks`, `source_monitor_tasks`, `missing_gem_result`, `missing_tables_result`, `ok_result`, `warning_result`, `error_result` -- all correctly private |
|
|
32
|
+
| 13 | SolidQueueVerifier remediation mentions Procfile.dev (REQ-20) | PASS | Line 24: `"Start a Solid Queue worker with \`bin/rails solid_queue:start\` or add \`jobs: bundle exec rake solid_queue:start\` to Procfile.dev and run \`bin/dev\`"` |
|
|
33
|
+
| 14 | Runner includes RecurringScheduleVerifier in default_verifiers | PASS | `runner.rb` line 21: `[ SolidQueueVerifier.new, RecurringScheduleVerifier.new, ActionCableVerifier.new ]` |
|
|
34
|
+
| 15 | Autoload entry in lib/source_monitor.rb | PASS | Line 174: `autoload :RecurringScheduleVerifier, "source_monitor/setup/verification/recurring_schedule_verifier"` -- correctly placed within the `module Verification` block |
|
|
35
|
+
| 16 | Tests use mocked/stubbed relations (no real DB) | PASS | `FakeTask` (Struct), `FakeTaskRelation` (custom class with `all`/`to_a`), `FakeConnection` (custom class with `table_exists?`) -- no ActiveRecord, no database queries |
|
|
36
|
+
| 17 | Tests cover all branches | PASS | 7 tests: ok (key prefix), ok (command), warning (non-SM tasks), warning (no tasks), error (missing gem), error (missing table), error (unexpected exception) |
|
|
37
|
+
| 18 | No hardcoded paths | PASS | Table name comes from `task_relation.table_name`, no filesystem paths. Constants are strings ("source_monitor_", "SourceMonitor::") which are correct domain identifiers, not paths |
|
|
38
|
+
| 19 | Error handling (rescue StandardError) | PASS | Line 35: `rescue StandardError => e` wraps the entire `call` body. Returns error_result with `e.message` interpolated. Test "rescues unexpected failures" covers this with a `raise "boom"` |
|
|
39
|
+
| 20 | Result key is `:recurring_schedule` | PASS | All three result helpers (`ok_result`, `warning_result`, `error_result`) use `key: :recurring_schedule` |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Edge Cases (21-25)
|
|
44
|
+
|
|
45
|
+
| # | Check | Result | Details |
|
|
46
|
+
|---|-------|--------|---------|
|
|
47
|
+
| 21 | What if `SolidQueue::RecurringTask` doesn't exist? | PASS | `default_task_relation` returns `nil` via `defined?` guard. `call` hits `return missing_gem_result unless task_relation` on line 16. Test "errors when solid queue gem is missing" covers this with `task_relation: nil` |
|
|
48
|
+
| 22 | What if table exists but is empty? | PASS | `all_tasks` returns `[]`, `source_monitor_tasks([])` returns `[]`, falls through to `else` branch on line 29: "No recurring tasks are registered". Test "warns when no recurring tasks are registered" covers this |
|
|
49
|
+
| 23 | What if tasks exist but none match SourceMonitor? | PASS | `sm_tasks` is empty, `tasks.any?` is true, hits `elsif` on line 24: "Recurring tasks exist but none belong to SourceMonitor". Test "warns when tasks exist but none belong to source monitor" covers this |
|
|
50
|
+
| 24 | What if connection is nil? | PASS | `tables_present?` returns `false` on line 57 (`return false unless connection`), which triggers `missing_tables_result`. If `task_relation` is also nil, the missing gem guard on line 16 fires first. Both paths are safe |
|
|
51
|
+
| 25 | What if an exception is raised during verification? | PASS | `rescue StandardError => e` at line 35 catches any exception from `all_tasks`, `source_monitor_tasks`, or `tables_present?`. Test "rescues unexpected failures" triggers this with `def all = raise "boom"` |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Requirements (26-30)
|
|
56
|
+
|
|
57
|
+
| # | Check | Result | Details |
|
|
58
|
+
|---|-------|--------|---------|
|
|
59
|
+
| 26 | REQ-19: RecurringScheduleVerifier checks recurring task registration | PASS | Verifier queries `SolidQueue::RecurringTask`, filters by key prefix / class_name / command namespace, returns ok/warning/error based on findings |
|
|
60
|
+
| 27 | REQ-20: SolidQueueVerifier mentions Procfile.dev | PASS | Remediation string includes `Procfile.dev` and `bin/dev`. Test assertion `assert_match(/Procfile\.dev/, result.remediation)` confirms |
|
|
61
|
+
| 28 | Test count increased (was 867, should be 874+) | PASS | 874 runs (was 867 before plan, +7 new RecurringScheduleVerifier tests) |
|
|
62
|
+
| 29 | No regressions in existing tests | PASS | Full suite: 874 runs, 2926 assertions, 0 failures, 0 errors, 0 skips |
|
|
63
|
+
| 30 | Verification integrates properly with Runner flow | PASS | Runner `default_verifiers` returns 3 verifiers in order: SolidQueue, RecurringSchedule, ActionCable. Runner test stubs all 3, asserts 3 results, confirms each called exactly once |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Summary
|
|
68
|
+
|
|
69
|
+
- **30/30 checks passed**
|
|
70
|
+
- **0 issues found**
|
|
71
|
+
- Full test suite: 874 runs, 2926 assertions, 0 failures
|
|
72
|
+
- RuboCop: 0 offenses across all modified files
|
|
73
|
+
- Brakeman: 0 warnings
|
|
74
|
+
- RecurringScheduleVerifier follows established verifier patterns exactly
|
|
75
|
+
- All branches (6 paths) tested with appropriate fakes/stubs
|
|
76
|
+
- Both REQ-19 and REQ-20 satisfied
|
|
77
|
+
|
|
78
|
+
**VERDICT: PASS**
|
data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01-SUMMARY.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# PLAN-01 Summary: recurring-schedule-verifier
|
|
2
|
+
|
|
3
|
+
## Status: COMPLETE
|
|
4
|
+
|
|
5
|
+
## What Was Done
|
|
6
|
+
|
|
7
|
+
### Task 1: Create RecurringScheduleVerifier
|
|
8
|
+
- Created `lib/source_monitor/setup/verification/recurring_schedule_verifier.rb`
|
|
9
|
+
- Follows exact same pattern as SolidQueueVerifier and ActionCableVerifier
|
|
10
|
+
- Constructor accepts `task_relation:` and `connection:` for dependency injection
|
|
11
|
+
- Detects SourceMonitor tasks by key prefix (`source_monitor_`), class_name namespace (`SourceMonitor::`), or command namespace
|
|
12
|
+
- Five outcomes: ok (SM tasks found), warning (tasks exist but no SM ones), warning (no tasks at all), error (gem missing), error (table missing), plus rescue for unexpected failures
|
|
13
|
+
|
|
14
|
+
### Task 2: Enhance SolidQueueVerifier Remediation
|
|
15
|
+
- Updated remediation message in `solid_queue_verifier.rb` line 24 to mention `Procfile.dev` and `bin/dev` workflow (REQ-20)
|
|
16
|
+
- Updated test assertion to verify Procfile.dev appears in remediation
|
|
17
|
+
|
|
18
|
+
### Task 3: Add RecurringScheduleVerifier Tests
|
|
19
|
+
- Created `test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb`
|
|
20
|
+
- 7 tests covering all branches: ok (by key prefix), ok (by command), warning (non-SM tasks), warning (no tasks), error (missing gem), error (missing table), error (unexpected exception)
|
|
21
|
+
|
|
22
|
+
### Task 4: Wire Into Runner + Autoload
|
|
23
|
+
- Added `RecurringScheduleVerifier.new` to `Runner#default_verifiers` between SolidQueue and ActionCable
|
|
24
|
+
- Added autoload declaration in `lib/source_monitor.rb` Verification module block
|
|
25
|
+
- Updated runner_test.rb to stub 3 verifiers and assert 3 results
|
|
26
|
+
|
|
27
|
+
### Task 5: Full Suite Verification
|
|
28
|
+
- 874 runs, 2926 assertions, 0 failures, 0 errors
|
|
29
|
+
- RuboCop: 0 offenses
|
|
30
|
+
- Brakeman: 0 warnings
|
|
31
|
+
|
|
32
|
+
## Files Modified
|
|
33
|
+
- `lib/source_monitor/setup/verification/recurring_schedule_verifier.rb` (new)
|
|
34
|
+
- `lib/source_monitor/setup/verification/solid_queue_verifier.rb` (remediation update)
|
|
35
|
+
- `lib/source_monitor/setup/verification/runner.rb` (added to default_verifiers)
|
|
36
|
+
- `lib/source_monitor.rb` (autoload declaration)
|
|
37
|
+
- `test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb` (new, 7 tests)
|
|
38
|
+
- `test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb` (Procfile.dev assertion)
|
|
39
|
+
- `test/lib/source_monitor/setup/verification/runner_test.rb` (3-verifier expectation)
|
|
40
|
+
|
|
41
|
+
## Commit
|
|
42
|
+
- `d03e3b9` feat(verification): add RecurringScheduleVerifier and enhance SolidQueue remediation
|
|
43
|
+
|
|
44
|
+
## Requirements Satisfied
|
|
45
|
+
- REQ-19: RecurringScheduleVerifier checks SolidQueue recurring tasks registration
|
|
46
|
+
- REQ-20: SolidQueueVerifier remediation mentions Procfile.dev and bin/dev
|