source_monitor 0.7.0 → 0.8.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 +45 -22
- data/.claude/skills/sm-configure/SKILL.md +10 -1
- data/.claude/skills/sm-configure/reference/configuration-reference.md +44 -0
- data/.claude/skills/sm-host-setup/reference/initializer-template.md +17 -0
- data/.claude/skills/sm-host-setup/reference/setup-checklist.md +2 -0
- data/.claude/skills/sm-job/reference/job-conventions.md +26 -0
- data/.claude/skills/sm-upgrade/reference/version-history.md +22 -0
- data/.gitignore +10 -0
- data/AGENTS.md +1 -1
- data/CHANGELOG.md +56 -0
- data/CLAUDE.md +11 -5
- data/Gemfile.lock +1 -1
- data/README.md +6 -4
- data/VERSION +1 -1
- data/app/assets/builds/source_monitor/application.css +43 -0
- data/app/assets/builds/source_monitor/application.js +127 -0
- data/app/assets/builds/source_monitor/application.js.map +3 -3
- data/app/assets/javascripts/source_monitor/application.js +2 -0
- data/app/assets/javascripts/source_monitor/controllers/notification_container_controller.js +138 -0
- data/app/assets/javascripts/source_monitor/controllers/notification_controller.js +11 -0
- data/app/controllers/source_monitor/source_favicon_fetches_controller.rb +38 -0
- data/app/controllers/source_monitor/sources_controller.rb +11 -0
- data/app/helpers/source_monitor/application_helper.rb +51 -0
- data/app/jobs/source_monitor/favicon_fetch_job.rb +71 -0
- data/app/jobs/source_monitor/import_opml_job.rb +9 -0
- data/app/jobs/source_monitor/source_health_check_job.rb +10 -0
- data/app/models/source_monitor/source.rb +2 -0
- data/app/views/layouts/source_monitor/application.html.erb +23 -2
- data/app/views/source_monitor/shared/_toast.html.erb +1 -0
- data/app/views/source_monitor/sources/_details.html.erb +34 -5
- data/app/views/source_monitor/sources/_row.html.erb +11 -6
- data/config/routes.rb +1 -0
- data/docs/configuration.md +1 -1
- data/docs/upgrade.md +22 -0
- data/lib/generators/source_monitor/install/templates/source_monitor.rb.tt +15 -1
- data/lib/source_monitor/configuration/favicons_settings.rb +42 -0
- data/lib/source_monitor/configuration/http_settings.rb +1 -1
- data/lib/source_monitor/configuration/scraping_settings.rb +1 -1
- data/lib/source_monitor/configuration.rb +3 -1
- data/lib/source_monitor/favicons/discoverer.rb +196 -0
- data/lib/source_monitor/fetching/feed_fetcher/source_updater.rb +21 -0
- data/lib/source_monitor/fetching/feed_fetcher.rb +1 -0
- data/lib/source_monitor/http.rb +5 -3
- data/lib/source_monitor/version.rb +1 -1
- data/lib/source_monitor.rb +4 -0
- data/lib/tasks/test_fast.rake +11 -0
- data/source_monitor.gemspec +1 -1
- metadata +7 -93
- data/.vbw-planning/PROJECT.md +0 -51
- data/.vbw-planning/ROADMAP.md +0 -32
- data/.vbw-planning/SHIPPED.md +0 -63
- data/.vbw-planning/STATE.md +0 -27
- data/.vbw-planning/codebase/ARCHITECTURE.md +0 -147
- data/.vbw-planning/codebase/CONCERNS.md +0 -99
- data/.vbw-planning/codebase/CONVENTIONS.md +0 -97
- data/.vbw-planning/codebase/DEPENDENCIES.md +0 -100
- data/.vbw-planning/codebase/INDEX.md +0 -86
- data/.vbw-planning/codebase/META.md +0 -42
- data/.vbw-planning/codebase/PATTERNS.md +0 -262
- data/.vbw-planning/codebase/STACK.md +0 -101
- data/.vbw-planning/codebase/STRUCTURE.md +0 -324
- data/.vbw-planning/codebase/TESTING.md +0 -154
- data/.vbw-planning/config.json +0 -53
- data/.vbw-planning/discovery.json +0 -26
- data/.vbw-planning/milestones/default/ROADMAP.md +0 -115
- data/.vbw-planning/milestones/default/STATE.md +0 -82
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-01-SUMMARY.md +0 -56
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-01.md +0 -187
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-02-SUMMARY.md +0 -64
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-02.md +0 -137
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-01-SUMMARY.md +0 -67
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-01.md +0 -142
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-02-SUMMARY.md +0 -64
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-02.md +0 -138
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-03-SUMMARY.md +0 -85
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-03.md +0 -147
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-04-SUMMARY.md +0 -63
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-04.md +0 -129
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-05-SUMMARY.md +0 -74
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-05.md +0 -154
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/03-VERIFICATION-wave1.md +0 -303
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/03-VERIFICATION.md +0 -510
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-01-SUMMARY.md +0 -61
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-01.md +0 -161
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-02-SUMMARY.md +0 -66
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-02.md +0 -132
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-03-SUMMARY.md +0 -59
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-03.md +0 -171
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-04-SUMMARY.md +0 -56
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-04.md +0 -152
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/04-CONTEXT.md +0 -33
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-01-SUMMARY.md +0 -42
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-01.md +0 -119
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-02-SUMMARY.md +0 -52
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-02.md +0 -195
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-03-SUMMARY.md +0 -79
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-03.md +0 -130
- data/.vbw-planning/milestones/generator-enhancements/REQUIREMENTS.md +0 -72
- data/.vbw-planning/milestones/generator-enhancements/ROADMAP.md +0 -125
- data/.vbw-planning/milestones/generator-enhancements/SHIPPED.md +0 -40
- data/.vbw-planning/milestones/generator-enhancements/STATE.md +0 -43
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/01-CONTEXT.md +0 -33
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/01-VERIFICATION.md +0 -86
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/PLAN-01-SUMMARY.md +0 -61
- data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/PLAN-01.md +0 -380
- data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/02-VERIFICATION.md +0 -78
- data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01-SUMMARY.md +0 -46
- data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01.md +0 -500
- data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/03-VERIFICATION.md +0 -89
- data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/PLAN-01-SUMMARY.md +0 -48
- data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/PLAN-01.md +0 -456
- data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/04-VERIFICATION.md +0 -129
- data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/PLAN-01-SUMMARY.md +0 -70
- data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/PLAN-01.md +0 -747
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/05-VERIFICATION.md +0 -156
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-01-SUMMARY.md +0 -69
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-01.md +0 -455
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-02-SUMMARY.md +0 -39
- data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-02.md +0 -488
- data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/06-VERIFICATION.md +0 -100
- data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/PLAN-01-SUMMARY.md +0 -37
- data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/PLAN-01.md +0 -345
- data/.vbw-planning/milestones/upgrade-assurance/REQUIREMENTS.md +0 -80
- data/.vbw-planning/milestones/upgrade-assurance/ROADMAP.md +0 -75
- data/.vbw-planning/milestones/upgrade-assurance/STATE.md +0 -29
- data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/01-VERIFICATION.md +0 -144
- data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/PLAN-01-SUMMARY.md +0 -43
- data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/PLAN-01.md +0 -405
- data/.vbw-planning/milestones/upgrade-assurance/phases/02-config-deprecation/PLAN-01-SUMMARY.md +0 -27
- data/.vbw-planning/milestones/upgrade-assurance/phases/02-config-deprecation/PLAN-01.md +0 -303
- data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/03-VERIFICATION.md +0 -380
- data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/PLAN-01-SUMMARY.md +0 -36
- data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/PLAN-01.md +0 -652
- data/.vbw-planning/phases/01-aia-certificate-resolution/.context-dev.md +0 -17
- data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-01-SUMMARY.md +0 -26
- data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-01.md +0 -71
- data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-02-SUMMARY.md +0 -16
- data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-02.md +0 -56
- data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-03-SUMMARY.md +0 -17
- data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-03.md +0 -98
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 932dca7d7b8f754262dd37aac3cf722aee017ec53e662116dd97527ec2a8a1f3
|
|
4
|
+
data.tar.gz: 7d6ff568a5e3eb1cf5269736771474f19da9e82b18759232b03855735f284819
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1318387b90d5811d52fc5d852a2be9578515a0d69f77baa90ecc1fbab930a3d2067a1e7056f8d2bd15940de2c0799e147203b31e4d91784e3078fb0fa8edc6e5
|
|
7
|
+
data.tar.gz: b35f81be14c230f1865642b5aa9f8fd462791c8fe3db293bf0f6326f2fc9fc1295eaef5f9899488d298e01e6eb3e6b316c00ed53595341a17973edd50cbb7b10
|
data/.claude/commands/release.md
CHANGED
|
@@ -15,8 +15,10 @@ These are real issues encountered in previous releases. Each step below accounts
|
|
|
15
15
|
3. **VBW volatile files**: Files in `.vbw-planning/` (`.cost-ledger.json`, `.notification-log.jsonl`, `.session-log.jsonl`, `.hook-errors.log`) are continuously modified by VBW hooks. They should be in `.gitignore`. If they aren't, add them before proceeding.
|
|
16
16
|
4. **Pre-push hook**: The VBW pre-push hook at `.git/hooks/pre-push` requires the `VERSION` file to appear in the diff for any push. For new branches, it compares the commit against the working tree -- any dirty files will trigger a false positive. For force-pushes to existing branches where `VERSION` hasn't changed since the last push, use `--no-verify`.
|
|
17
17
|
5. **Single squashed commit**: Always create ONE commit on the release branch with ALL changes (version bump, changelog, Gemfile.lock, any fixes). Multiple commits cause pre-push hook issues.
|
|
18
|
-
6. **Diff coverage CI gate**: The `test` CI job enforces diff coverage. Any changed lines in source code (not just test files) must have test coverage.
|
|
19
|
-
7. **Local main divergence after merge**: After the PR merges,
|
|
18
|
+
6. **Diff coverage CI gate**: The `test` CI job enforces diff coverage. Any changed lines in source code (not just test files) must have test coverage. **This applies to ALL changes in the PR diff vs main, including unpushed commits made before the release started.** If the release includes source code changes (bug fixes, features), every changed source line must be covered.
|
|
19
|
+
7. **Local main divergence after merge**: After the PR merges, `gh pr merge --merge --delete-branch` will attempt to fast-forward local main. This usually succeeds automatically. If it doesn't (divergent history), you must `git reset --hard origin/main` to sync -- this requires user approval since the sandbox blocks it.
|
|
20
|
+
8. **Run local checks BEFORE pushing**: Always run `bin/rubocop` and `PARALLEL_WORKERS=1 bin/rails test` locally before the first push to the release branch. Each CI roundtrip (fail → fix → amend → force-push → re-run) costs ~5 minutes. In v0.7.0, skipping local checks caused two wasted CI cycles: first for uncovered diff lines, then for a RuboCop violation in the fix.
|
|
21
|
+
9. **Zsh glob nomatch**: Commands like `rm -f *.gem` fail in zsh when no files match. Always use `rm -f *.gem 2>/dev/null || true` or check existence first with `ls`.
|
|
20
22
|
|
|
21
23
|
## Step 1: Git Hygiene
|
|
22
24
|
|
|
@@ -112,7 +114,25 @@ The changelog follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) f
|
|
|
112
114
|
2. Verify the output shows the new version: `Using source_monitor X.Y.Z (was X.Y.Z-1)`.
|
|
113
115
|
3. If `bundle install` fails, resolve the issue before proceeding.
|
|
114
116
|
|
|
115
|
-
## Step 5:
|
|
117
|
+
## Step 5: Local Pre-flight Checks
|
|
118
|
+
|
|
119
|
+
**CRITICAL**: Run these checks BEFORE creating the release branch and pushing. Each CI failure → fix → amend → force-push cycle wastes ~5 minutes. In v0.7.0, skipping this step caused two wasted CI roundtrips.
|
|
120
|
+
|
|
121
|
+
1. **RuboCop**: Run `bin/rubocop` and fix any violations. Auto-fix with `bin/rubocop -a` if needed. This catches lint issues (like `SpaceInsideArrayLiteralBrackets`) that would fail the CI lint job.
|
|
122
|
+
|
|
123
|
+
2. **Tests**: Run `PARALLEL_WORKERS=1 bin/rails test` and ensure all tests pass.
|
|
124
|
+
|
|
125
|
+
3. **Diff coverage pre-check**: If the release includes source code changes beyond version/changelog/lockfile (check with `git diff --name-only origin/main`), review those files for uncovered branches. The CI diff coverage gate will reject any changed source lines without test coverage. Common blind spots:
|
|
126
|
+
- Fallback/else branches in new methods
|
|
127
|
+
- Error handling paths
|
|
128
|
+
- Guard clauses
|
|
129
|
+
If you find uncovered source lines, write tests for them NOW before creating the release commit — it's far cheaper than a CI roundtrip.
|
|
130
|
+
|
|
131
|
+
4. **Brakeman**: Run `bin/brakeman --no-pager` and ensure zero warnings.
|
|
132
|
+
|
|
133
|
+
Only proceed to Step 6 when all local checks pass.
|
|
134
|
+
|
|
135
|
+
## Step 6: Create Release Branch with Single Squashed Commit
|
|
116
136
|
|
|
117
137
|
**IMPORTANT**: All release changes MUST be in a single commit on the release branch. This avoids pre-push hook issues where individual commits are checked for VERSION changes.
|
|
118
138
|
|
|
@@ -124,13 +144,13 @@ The changelog follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) f
|
|
|
124
144
|
Also stage any other files that were changed (updated skills, docs, etc.).
|
|
125
145
|
3. Create a single commit:
|
|
126
146
|
```
|
|
127
|
-
chore: release vX.Y.Z
|
|
147
|
+
chore(release): release vX.Y.Z
|
|
128
148
|
```
|
|
129
149
|
4. Push the branch: `git push -u origin release/vX.Y.Z`
|
|
130
150
|
- If the pre-push hook blocks with a false positive (e.g., VBW files dirty in working tree despite being gitignored), use `git push -u --no-verify origin release/vX.Y.Z`. This is safe because we've verified VERSION is in the commit.
|
|
131
151
|
5. If the push fails for other reasons, diagnose and fix before proceeding.
|
|
132
152
|
|
|
133
|
-
## Step
|
|
153
|
+
## Step 7: Create PR
|
|
134
154
|
|
|
135
155
|
1. Create the PR using `gh pr create`:
|
|
136
156
|
- Title: `Release vX.Y.Z`
|
|
@@ -152,7 +172,7 @@ The changelog follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) f
|
|
|
152
172
|
- Base: `main`
|
|
153
173
|
2. Report the PR URL to the user.
|
|
154
174
|
|
|
155
|
-
## Step
|
|
175
|
+
## Step 8: Monitor CI Pipeline
|
|
156
176
|
|
|
157
177
|
Poll the CI status using repeated `gh pr checks <PR_NUMBER>` calls. The CI has 4 required jobs: `lint`, `security`, `test`, `release_verification` (release_verification only runs after test passes).
|
|
158
178
|
|
|
@@ -163,7 +183,7 @@ Poll the CI status using repeated `gh pr checks <PR_NUMBER>` calls. The CI has 4
|
|
|
163
183
|
|
|
164
184
|
### If CI PASSES (all checks green):
|
|
165
185
|
|
|
166
|
-
Continue to Step
|
|
186
|
+
Continue to Step 9. If Step 5 (local pre-flight) was done properly, CI should pass on the first attempt.
|
|
167
187
|
|
|
168
188
|
### If CI FAILS:
|
|
169
189
|
|
|
@@ -173,32 +193,32 @@ Continue to Step 8.
|
|
|
173
193
|
gh run view <RUN_ID> --log-failed | tail -80
|
|
174
194
|
```
|
|
175
195
|
3. **Common failure: diff coverage** -- If the `test` job fails on "Enforce diff coverage", it means changed source lines lack test coverage. Read the error to identify uncovered files/lines, write tests, and add them to the release commit.
|
|
176
|
-
4. **Common failure: Gemfile.lock frozen** -- If `bundle install` fails in CI with "frozen mode", you forgot to run `bundle install` locally (Step 4).
|
|
177
|
-
5.
|
|
178
|
-
|
|
196
|
+
4. **Common failure: Gemfile.lock frozen** -- If `bundle install` fails in CI with "frozen mode", you forgot to run `bundle install` locally (Step 4). Amend the commit with the updated lockfile.
|
|
197
|
+
5. **Common failure: RuboCop lint** -- If the `lint` job fails, a RuboCop violation slipped through. This should have been caught in Step 5.
|
|
198
|
+
6. **IMPORTANT: When fixing CI failures, run ALL local checks again before re-pushing.** Don't just fix the one failure — run `bin/rubocop` AND `PARALLEL_WORKERS=1 bin/rails test` to catch cascading issues. In v0.7.0, fixing a diff coverage failure introduced a RuboCop violation, requiring a third CI cycle.
|
|
199
|
+
7. Present failure details to the user and ask what to do:
|
|
200
|
+
- "Fix the issues and re-push" -- Fix issues, run ALL local checks (rubocop + tests), amend the commit (`git commit --amend --no-edit`), force push (`git push --force-with-lease --no-verify origin release/vX.Y.Z`), and restart CI monitoring.
|
|
179
201
|
- "Close the PR and abort" -- Close the PR, delete the branch, switch back to main.
|
|
180
202
|
- "Investigate manually" -- Stop and let the user handle it.
|
|
181
203
|
|
|
182
204
|
**Note on force pushes**: When force-pushing the release branch after amending, always use `--no-verify` because the pre-push hook will see the diff between old and new branch tips, and `VERSION` won't appear as changed (it's the same in both). This is expected and safe.
|
|
183
205
|
|
|
184
|
-
## Step
|
|
206
|
+
## Step 9: Auto-Merge PR
|
|
185
207
|
|
|
186
208
|
Once CI is green:
|
|
187
209
|
|
|
188
210
|
1. Merge the PR: `gh pr merge <PR_NUMBER> --merge --delete-branch`
|
|
211
|
+
- The `--delete-branch` flag also fetches and fast-forwards local main in most cases.
|
|
189
212
|
|
|
190
|
-
2. **Sync local main with remote
|
|
191
|
-
- The merge creates a merge commit on origin/main that doesn't exist locally.
|
|
192
|
-
- Local main may have different commits (pre-squash) than what was merged.
|
|
213
|
+
2. **Sync local main with remote**:
|
|
193
214
|
- Switch to main: `git checkout main`
|
|
194
|
-
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
- Verify with `git log --oneline -3` that local matches remote.
|
|
215
|
+
- The `gh pr merge` command usually auto-syncs local main via fast-forward. Verify with `git log --oneline -3` that local matches remote (`git rev-parse HEAD` == `git rev-parse origin/main`).
|
|
216
|
+
- If local is behind or diverged, try `git pull origin main`.
|
|
217
|
+
- If pull fails with conflicts or divergence (rare): ask the user to run `git reset --hard origin/main` (the sandbox blocks this command). Explain this is safe because the PR is merged and all changes are on origin/main.
|
|
198
218
|
|
|
199
219
|
3. Report: "PR #N merged successfully."
|
|
200
220
|
|
|
201
|
-
## Step
|
|
221
|
+
## Step 10: Tag the Release
|
|
202
222
|
|
|
203
223
|
1. Verify you're on main and synced with origin.
|
|
204
224
|
2. Create an annotated tag:
|
|
@@ -212,14 +232,17 @@ Once CI is green:
|
|
|
212
232
|
```
|
|
213
233
|
5. Report the release URL.
|
|
214
234
|
|
|
215
|
-
## Step
|
|
235
|
+
## Step 11: Build the Gem
|
|
216
236
|
|
|
217
|
-
1. Clean any old gem files
|
|
237
|
+
1. Clean any old gem files. **Note**: zsh fails on `rm -f *.gem` when no files match due to `nomatch`. Use:
|
|
238
|
+
```
|
|
239
|
+
find . -maxdepth 1 -name 'source_monitor-*.gem' -delete
|
|
240
|
+
```
|
|
218
241
|
2. Build the gem: `gem build source_monitor.gemspec`
|
|
219
242
|
3. Verify the gem was built: check for `source_monitor-X.Y.Z.gem` in the project root.
|
|
220
243
|
4. Show the file size: `ls -la source_monitor-X.Y.Z.gem`
|
|
221
244
|
|
|
222
|
-
## Step
|
|
245
|
+
## Step 12: Gem Push Instructions
|
|
223
246
|
|
|
224
247
|
Present the final instructions to the user:
|
|
225
248
|
|
|
@@ -29,7 +29,7 @@ After the block executes, `ModelExtensions.reload!` runs automatically to apply
|
|
|
29
29
|
|
|
30
30
|
## Configuration Sections
|
|
31
31
|
|
|
32
|
-
The `config` object (`SourceMonitor::Configuration`) has
|
|
32
|
+
The `config` object (`SourceMonitor::Configuration`) has 13 sub-sections plus top-level queue/job settings:
|
|
33
33
|
|
|
34
34
|
| Section | Accessor | Class |
|
|
35
35
|
|---|---|---|
|
|
@@ -45,6 +45,7 @@ The `config` object (`SourceMonitor::Configuration`) has 11 sub-sections plus to
|
|
|
45
45
|
| Realtime | `config.realtime` | `RealtimeSettings` |
|
|
46
46
|
| Authentication | `config.authentication` | `AuthenticationSettings` |
|
|
47
47
|
| Images | `config.images` | `ImagesSettings` |
|
|
48
|
+
| Favicons | `config.favicons` | `FaviconsSettings` |
|
|
48
49
|
|
|
49
50
|
See `reference/configuration-reference.md` for every setting with types, defaults, and examples.
|
|
50
51
|
|
|
@@ -91,6 +92,14 @@ config.models.source.include_concern "MyApp::SourceExtension"
|
|
|
91
92
|
config.models.item.validate :custom_check
|
|
92
93
|
```
|
|
93
94
|
|
|
95
|
+
### Favicons (Active Storage)
|
|
96
|
+
```ruby
|
|
97
|
+
config.favicons.enabled = true
|
|
98
|
+
config.favicons.fetch_timeout = 10
|
|
99
|
+
config.favicons.max_download_size = 512 * 1024 # 512 KB
|
|
100
|
+
config.favicons.retry_cooldown_days = 14
|
|
101
|
+
```
|
|
102
|
+
|
|
94
103
|
### Realtime
|
|
95
104
|
```ruby
|
|
96
105
|
config.realtime.adapter = :redis
|
|
@@ -342,6 +342,50 @@ When enabled, `DownloadContentImagesJob` is automatically enqueued after new ite
|
|
|
342
342
|
|
|
343
343
|
---
|
|
344
344
|
|
|
345
|
+
## Favicons Settings (`config.favicons`)
|
|
346
|
+
|
|
347
|
+
Class: `SourceMonitor::Configuration::FaviconsSettings`
|
|
348
|
+
|
|
349
|
+
Controls automatic favicon fetching and storage for sources via Active Storage.
|
|
350
|
+
|
|
351
|
+
**Prerequisite:** The host app must have Active Storage installed (`rails active_storage:install` + migrations). Without Active Storage, favicons are silently disabled and colored initials placeholders are shown instead.
|
|
352
|
+
|
|
353
|
+
| Setting | Type | Default | Description |
|
|
354
|
+
|---|---|---|---|
|
|
355
|
+
| `enabled` | Boolean | `true` | Enable automatic favicon fetching |
|
|
356
|
+
| `fetch_timeout` | Integer | `5` | HTTP timeout for favicon requests (seconds) |
|
|
357
|
+
| `max_download_size` | Integer | `1048576` (1 MB) | Maximum favicon file size in bytes; larger files are skipped |
|
|
358
|
+
| `retry_cooldown_days` | Integer | `7` | Days to wait before retrying a failed favicon fetch |
|
|
359
|
+
| `allowed_content_types` | Array | `["image/x-icon", "image/vnd.microsoft.icon", "image/png", "image/jpeg", "image/gif", "image/svg+xml", "image/webp"]` | Permitted MIME types for downloaded favicons |
|
|
360
|
+
|
|
361
|
+
### Helper Method
|
|
362
|
+
|
|
363
|
+
| Method | Returns | Description |
|
|
364
|
+
|---|---|---|
|
|
365
|
+
| `enabled?` | Boolean | Returns `true` when `enabled` is truthy AND `ActiveStorage` is defined |
|
|
366
|
+
|
|
367
|
+
```ruby
|
|
368
|
+
# Customize favicon settings
|
|
369
|
+
config.favicons.enabled = true
|
|
370
|
+
config.favicons.fetch_timeout = 10
|
|
371
|
+
config.favicons.max_download_size = 512 * 1024 # 512 KB
|
|
372
|
+
config.favicons.retry_cooldown_days = 14
|
|
373
|
+
config.favicons.allowed_content_types = %w[image/png image/x-icon image/svg+xml]
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
When enabled, `FaviconFetchJob` is automatically enqueued:
|
|
377
|
+
1. After a new source is created (via UI or OPML import) with a `website_url`
|
|
378
|
+
2. After a successful feed fetch when the source has no favicon attached and is outside the retry cooldown
|
|
379
|
+
|
|
380
|
+
The job uses `Favicons::Discoverer` which tries three strategies in order:
|
|
381
|
+
1. Direct `/favicon.ico` fetch from the source's domain
|
|
382
|
+
2. HTML page parsing for `<link rel="icon">`, `<link rel="apple-touch-icon">`, and similar tags (prefers largest by `sizes` attribute)
|
|
383
|
+
3. Google Favicon API as a last resort
|
|
384
|
+
|
|
385
|
+
Failed attempts are tracked in the source's `metadata` JSONB column (`favicon_last_attempted_at`) to respect the cooldown period.
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
345
389
|
## Environment Variables
|
|
346
390
|
|
|
347
391
|
| Variable | Purpose |
|
|
@@ -176,6 +176,23 @@ SourceMonitor.configure do |config|
|
|
|
176
176
|
# record.errors.add(:base, "custom error") unless record.valid_for_my_app?
|
|
177
177
|
# }
|
|
178
178
|
|
|
179
|
+
# ===========================================================================
|
|
180
|
+
# Favicons (Active Storage)
|
|
181
|
+
# ===========================================================================
|
|
182
|
+
# Automatically fetch and store source favicons via Active Storage.
|
|
183
|
+
# Requires Active Storage in the host app (rails active_storage:install).
|
|
184
|
+
# Without Active Storage, favicons are silently disabled -- colored
|
|
185
|
+
# initials placeholders are shown instead.
|
|
186
|
+
|
|
187
|
+
# config.favicons.enabled = true # default: true
|
|
188
|
+
# config.favicons.fetch_timeout = 5 # seconds
|
|
189
|
+
# config.favicons.max_download_size = 1_048_576 # 1 MB
|
|
190
|
+
# config.favicons.retry_cooldown_days = 7
|
|
191
|
+
# config.favicons.allowed_content_types = %w[
|
|
192
|
+
# image/x-icon image/vnd.microsoft.icon image/png
|
|
193
|
+
# image/jpeg image/gif image/svg+xml image/webp
|
|
194
|
+
# ]
|
|
195
|
+
|
|
179
196
|
# ===========================================================================
|
|
180
197
|
# Realtime (Action Cable) Adapter
|
|
181
198
|
# ===========================================================================
|
|
@@ -155,6 +155,8 @@ bin/source_monitor verify
|
|
|
155
155
|
- [ ] Event callbacks wired for host integration
|
|
156
156
|
- [ ] Realtime adapter confirmed (Solid Cable or Redis)
|
|
157
157
|
- [ ] Mission Control integration enabled (if desired)
|
|
158
|
+
- [ ] Active Storage installed (required for favicons and image downloads)
|
|
159
|
+
- [ ] Favicon settings configured (`config.favicons.*`) if customization needed
|
|
158
160
|
|
|
159
161
|
## Troubleshooting
|
|
160
162
|
|
|
@@ -164,6 +164,32 @@ class ScheduleFetchesJob < ApplicationJob
|
|
|
164
164
|
end
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
### Lightweight Fetch Job (FaviconFetchJob)
|
|
168
|
+
|
|
169
|
+
Demonstrates multi-strategy cascade with guard clauses:
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
class FaviconFetchJob < ApplicationJob
|
|
173
|
+
source_monitor_queue :fetch
|
|
174
|
+
discard_on ActiveJob::DeserializationError
|
|
175
|
+
|
|
176
|
+
def perform(source_id)
|
|
177
|
+
source = Source.find_by(id: source_id)
|
|
178
|
+
return unless source
|
|
179
|
+
return unless should_fetch?(source)
|
|
180
|
+
|
|
181
|
+
result = Favicons::Discoverer.new(source: source).call
|
|
182
|
+
attach_favicon(source, result) if result.success?
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Notable patterns:
|
|
188
|
+
- Multiple guard clauses: source exists, Active Storage defined, no existing favicon, outside cooldown period
|
|
189
|
+
- Uses `Favicons::Discoverer` service with 3-strategy cascade (direct `/favicon.ico`, HTML parsing, Google API)
|
|
190
|
+
- Failed attempts tracked in source `metadata` JSONB (`favicon_last_attempted_at`) for retry cooldown
|
|
191
|
+
- Graceful degradation: host apps without Active Storage never enqueue this job
|
|
192
|
+
|
|
167
193
|
### Broadcast Job (SourceHealthCheckJob)
|
|
168
194
|
|
|
169
195
|
Demonstrates result broadcasting:
|
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Version-specific migration notes for each major/minor version transition. Agents should reference this file when guiding users through multi-version upgrades.
|
|
4
4
|
|
|
5
|
+
## 0.7.x to 0.8.0
|
|
6
|
+
|
|
7
|
+
**Key changes:**
|
|
8
|
+
- Default HTTP User-Agent changed from `SourceMonitor/<version>` to `Mozilla/5.0 (compatible; SourceMonitor/<version>)` with browser-like headers (Accept-Language, DNT, Referer). Prevents bot-blocking by feed servers.
|
|
9
|
+
- Default `max_in_flight_per_source` changed from `25` to `nil` (unlimited). If you relied on the previous default for per-source rate limiting, set it explicitly.
|
|
10
|
+
- Successful manual health checks on degraded sources now trigger a feed fetch for faster recovery.
|
|
11
|
+
- Automatic source favicons via Active Storage with multi-strategy discovery (direct `/favicon.ico`, HTML `<link>` parsing, Google Favicon API fallback)
|
|
12
|
+
- New configuration section: `config.favicons` with `enabled`, `fetch_timeout`, `max_download_size`, `retry_cooldown_days`, and `allowed_content_types` settings
|
|
13
|
+
- Colored initials placeholder shown when no favicon is available or Active Storage is not installed
|
|
14
|
+
- OPML imports trigger favicon fetches for each imported source with a `website_url`
|
|
15
|
+
- Toast notifications capped at 3 visible with "+N more" badge, click-to-expand, and "Clear all" button
|
|
16
|
+
- Error-level toasts auto-dismiss after 10 seconds (vs 5 seconds for info/success)
|
|
17
|
+
|
|
18
|
+
**Action items:**
|
|
19
|
+
1. Re-run `bin/rails source_monitor:upgrade` to get updated initializer template
|
|
20
|
+
2. If you explicitly set `config.http.user_agent`, your value is preserved. Otherwise the new browser-like default applies automatically.
|
|
21
|
+
3. If you need per-source scrape rate limiting, add `config.scraping.max_in_flight_per_source = 25` (or your preferred value) to your initializer
|
|
22
|
+
4. If using Active Storage, favicons are enabled by default -- no action needed
|
|
23
|
+
5. If NOT using Active Storage, favicons are silently disabled -- no action needed
|
|
24
|
+
6. Toast stacking is automatic -- no configuration needed
|
|
25
|
+
7. No breaking changes -- all existing configuration remains valid
|
|
26
|
+
|
|
5
27
|
## 0.3.x to 0.4.0
|
|
6
28
|
|
|
7
29
|
**Released:** 2026-02-12
|
data/.gitignore
CHANGED
|
@@ -27,5 +27,15 @@
|
|
|
27
27
|
.vbw-planning/.active-agent
|
|
28
28
|
.vbw-planning/.active-agent-count
|
|
29
29
|
.vbw-planning/.todo-flat-migrated
|
|
30
|
+
.vbw-planning/.agent-worktrees/
|
|
31
|
+
.vbw-planning/.cache/
|
|
32
|
+
.vbw-planning/.context-usage
|
|
33
|
+
.vbw-planning/.contracts/
|
|
34
|
+
.vbw-planning/.events/
|
|
35
|
+
.vbw-planning/.execution-state.json
|
|
30
36
|
/codebase_analysis.md
|
|
37
|
+
/VERIFICATION.md
|
|
38
|
+
/test/dummy/public/assets/
|
|
39
|
+
/test/lib/tmp/
|
|
31
40
|
*.gem
|
|
41
|
+
.vbw-worktrees/
|
data/AGENTS.md
CHANGED
|
@@ -83,7 +83,7 @@ Store secrets (API keys, webhook tokens) in `config/credentials/` and never comm
|
|
|
83
83
|
|
|
84
84
|
## Claude Code Skills
|
|
85
85
|
|
|
86
|
-
SourceMonitor ships
|
|
86
|
+
SourceMonitor ships 15 engine-specific Claude Code skills (`sm-*` prefix) covering the domain model, configuration DSL, pipeline stages, testing conventions, and more. Skills are distributed with the gem and installed into `.claude/skills/` via rake tasks:
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
89
|
bin/rails source_monitor:skills:install # Consumer skills (host app integration)
|
data/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,62 @@ All notable changes to this project are documented below. The format follows [Ke
|
|
|
15
15
|
|
|
16
16
|
- No unreleased changes yet.
|
|
17
17
|
|
|
18
|
+
## [0.8.0] - 2026-02-21
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **Automatic source favicons.** Sources now display favicons next to their names in list and detail views. Favicons are fetched automatically via background job on source creation and successful feed fetches using a multi-strategy cascade: `/favicon.ico` direct fetch, HTML `<link>` tag parsing (preferring largest available), and Google Favicon API fallback. Requires Active Storage in the host app.
|
|
23
|
+
- New configuration section: `config.favicons` with `enabled` (default: `true`), `fetch_timeout` (5s), `max_download_size` (1MB), `retry_cooldown_days` (7), and `allowed_content_types` settings.
|
|
24
|
+
- Colored initials placeholder shown when no favicon is available (consistent HSL color derived from source name).
|
|
25
|
+
- Graceful degradation: host apps without Active Storage see placeholders only, no errors.
|
|
26
|
+
- OPML imports also trigger favicon fetches for each imported source with a `website_url`.
|
|
27
|
+
- Manual "Fetch Favicon" button on source detail pages; favicon fetch also triggered on 304 Not Modified responses when missing.
|
|
28
|
+
- Redirect-following in favicon discoverer for domains that redirect (e.g., `reddit.com` -> `www.reddit.com`).
|
|
29
|
+
- **Toast notification stacking.** Bulk operations no longer flood the screen with overlapping toasts. At most 3 toasts are visible at a time; overflow is shown as a "+N more" badge that expands the full stack on click. "Clear all" button dismisses every toast at once.
|
|
30
|
+
- Error-level toasts persist for 10 seconds (vs 5 seconds for info/success).
|
|
31
|
+
- Hidden toasts promote into visible slots as earlier toasts auto-dismiss.
|
|
32
|
+
- Container controller tracks DOM changes via MutationObserver and properly cleans up event listeners on disconnect.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **Browser-like default User-Agent.** Default HTTP User-Agent changed from `SourceMonitor/<version>` to `Mozilla/5.0 (compatible; SourceMonitor/<version>)` with full browser-like headers (Accept, Accept-Language, DNT, Referer from source `website_url`). This prevents bot-blocking by feed servers.
|
|
37
|
+
- **Smarter scrape rate limiting.** Default `max_in_flight_per_source` changed from `25` to `nil` (unlimited). The previous default unnecessarily throttled scraping for sources with many items. Set an explicit value in your initializer if you need per-source caps.
|
|
38
|
+
- **Health check triggers status re-evaluation.** A successful manual health check on a degraded (declining/critical/warning) source now triggers a feed fetch, allowing the health monitor to transition the source back to "improving" status instead of requiring the source to recover on its own schedule.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Favicon discoverer properly follows HTTP redirects (e.g., `reddit.com` -> `www.reddit.com`).
|
|
43
|
+
- Favicon fetch uses `rails_blob_path` for correct routing within the engine context.
|
|
44
|
+
- Favicon display prefers PNG format (via Google Favicon API) over raw ICO for better browser compatibility.
|
|
45
|
+
- Gemspec excludes `.vbw-planning/` from gem package to reduce gem size.
|
|
46
|
+
|
|
47
|
+
### Testing
|
|
48
|
+
|
|
49
|
+
- 1,125 tests, 0 failures.
|
|
50
|
+
- RuboCop: 0 offenses.
|
|
51
|
+
- Brakeman: 0 warnings.
|
|
52
|
+
|
|
53
|
+
## [0.7.1] - 2026-02-18
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- **Test suite 60% faster (118s → 46s).** Disabled Faraday retry middleware in tests — WebMock-stubbed timeout errors triggered 4 retries with exponential backoff (7.5s of real sleep per test), consuming 73% of total runtime across 11 FeedFetcher tests.
|
|
58
|
+
- Split monolithic FeedFetcherTest (71 tests, 84.8s) into 6 concern-based test classes for better parallelization and maintainability.
|
|
59
|
+
- Switched default test parallelism from fork-based to thread-based, eliminating PG segfault on single-file runs.
|
|
60
|
+
- Reduced test log IO by setting test log level to `:warn` (was `:debug`, generating 95MB of output).
|
|
61
|
+
- Adopted `setup_once`/`before_all` in 5 DB-heavy analytics/dashboard test files.
|
|
62
|
+
- Added `test:fast` rake task to exclude integration and system tests during development.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- Suppressed spurious TestProf "before_all is not implemented for threads" warning by loading TestProf after `parallelize` call.
|
|
67
|
+
|
|
68
|
+
### Testing
|
|
69
|
+
|
|
70
|
+
- 1,033 tests, 3,302 assertions, 0 failures.
|
|
71
|
+
- RuboCop: 0 offenses.
|
|
72
|
+
- Brakeman: 0 warnings.
|
|
73
|
+
|
|
18
74
|
## [0.7.0] - 2026-02-18
|
|
19
75
|
|
|
20
76
|
### Fixed
|
data/CLAUDE.md
CHANGED
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
## Active Context
|
|
6
6
|
|
|
7
|
-
**Milestone:**
|
|
8
|
-
**
|
|
9
|
-
**
|
|
10
|
-
**
|
|
7
|
+
**Milestone:** polish-and-reliability
|
|
8
|
+
**Phase:** 1 -- Backend Fixes (pending planning)
|
|
9
|
+
**Last shipped:** aia-ssl-fix (2026-02-20) -- 2 phases, 7 plans, 8 commits
|
|
10
|
+
**Previous:** upgrade-assurance (2026-02-13), generator-enhancements (2026-02-12)
|
|
11
11
|
|
|
12
12
|
## Key Decisions
|
|
13
13
|
|
|
14
14
|
- Keep PostgreSQL-only for now
|
|
15
15
|
- Keep host-app auth model
|
|
16
16
|
- Ruby autoload for lib/ modules (not Zeitwerk)
|
|
17
|
-
- PG parallel fork segfault
|
|
17
|
+
- PG parallel fork segfault resolved: switched to thread-based parallelism in aia-ssl-fix milestone
|
|
18
18
|
|
|
19
19
|
## Installed Skills
|
|
20
20
|
|
|
@@ -100,6 +100,12 @@ Run /vbw:help for all commands.
|
|
|
100
100
|
- No N+1 queries (use `includes`/`preload`).
|
|
101
101
|
- No hardcoded credentials (use Rails credentials or ENV).
|
|
102
102
|
|
|
103
|
+
## QA and UAT Rules
|
|
104
|
+
|
|
105
|
+
- **Browser-first verification:** During VBW QA (`/vbw:qa`) and UAT (`/vbw:verify`), ALWAYS start by using `agent-browser` to test UI scenarios yourself before presenting checkpoints to the user. Navigate to the dummy app (port 3002), take snapshots/screenshots, and verify visual and functional behavior with agents first.
|
|
106
|
+
- **Automate what you can:** Any test that can be verified programmatically (config defaults, job enqueue behavior, controller responses) should be automated -- only present truly visual/interactive tests to the user.
|
|
107
|
+
- **Dummy app port:** The SourceMonitor dummy app runs on port 3002 (`cd test/dummy && bin/rails server -p 3002`).
|
|
108
|
+
|
|
103
109
|
## Security Rules
|
|
104
110
|
|
|
105
111
|
### Protected Files (NEVER read or output)
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -9,8 +9,8 @@ SourceMonitor is a production-ready Rails 8 mountable engine for ingesting, norm
|
|
|
9
9
|
In your host Rails app:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
bundle add source_monitor --version "~> 0.
|
|
13
|
-
# or add `gem "source_monitor", "~> 0.
|
|
12
|
+
bundle add source_monitor --version "~> 0.7.1"
|
|
13
|
+
# or add `gem "source_monitor", "~> 0.7.1"` manually, then run:
|
|
14
14
|
bundle install
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -19,7 +19,9 @@ This exposes `bin/source_monitor` (via Bundler binstubs) so you can run the guid
|
|
|
19
19
|
## Highlights
|
|
20
20
|
- Full-featured source and item administration backed by Turbo Streams and Tailwind UI components
|
|
21
21
|
- Adaptive fetch pipeline (Feedjira + Faraday) with conditional GETs, retention pruning, and scrape orchestration
|
|
22
|
+
- Automatic source favicons via Active Storage with multi-strategy discovery and graceful fallback
|
|
22
23
|
- Realtime dashboard metrics, batching/caching query layer, and Mission Control integration hooks
|
|
24
|
+
- Smart toast notification stacking (max 3 visible, "+N more" overflow badge, click-to-expand)
|
|
23
25
|
- Extensible scraper adapters (Readability included) with per-source settings and structured result metadata
|
|
24
26
|
- Declarative configuration DSL covering queues, HTTP, retention, events, model extensions, authentication, and realtime transports
|
|
25
27
|
- First-class observability through ActiveSupport notifications and `SourceMonitor::Metrics` counters/gauges
|
|
@@ -41,7 +43,7 @@ This exposes `bin/source_monitor` (via Bundler binstubs) so you can run the guid
|
|
|
41
43
|
Before running any SourceMonitor commands inside your host app, add the gem and install dependencies:
|
|
42
44
|
|
|
43
45
|
```bash
|
|
44
|
-
bundle add source_monitor --version "~> 0.
|
|
46
|
+
bundle add source_monitor --version "~> 0.7.1"
|
|
45
47
|
# or edit your Gemfile, then run
|
|
46
48
|
bundle install
|
|
47
49
|
```
|
|
@@ -113,7 +115,7 @@ See [docs/configuration.md](docs/configuration.md) for exhaustive coverage and e
|
|
|
113
115
|
|
|
114
116
|
## Claude Code Skills
|
|
115
117
|
|
|
116
|
-
SourceMonitor ships
|
|
118
|
+
SourceMonitor ships 15 engine-specific Claude Code skills (`sm-*` prefix) that give AI agents deep context about the engine's domain model, configuration DSL, pipeline stages, and testing conventions. Skills are bundled with the gem and installed into your host app's `.claude/skills/` directory.
|
|
117
119
|
|
|
118
120
|
```bash
|
|
119
121
|
bin/rails source_monitor:skills:install # Consumer skills (host app integration)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.8.0
|
|
@@ -651,6 +651,14 @@ video {
|
|
|
651
651
|
right: 0px;
|
|
652
652
|
}
|
|
653
653
|
|
|
654
|
+
.fm-admin .-bottom-1 {
|
|
655
|
+
bottom: -0.25rem;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
.fm-admin .-right-1 {
|
|
659
|
+
right: -0.25rem;
|
|
660
|
+
}
|
|
661
|
+
|
|
654
662
|
.fm-admin .left-4 {
|
|
655
663
|
left: 1rem;
|
|
656
664
|
}
|
|
@@ -957,6 +965,10 @@ video {
|
|
|
957
965
|
align-items: flex-start;
|
|
958
966
|
}
|
|
959
967
|
|
|
968
|
+
.fm-admin .items-end {
|
|
969
|
+
align-items: flex-end;
|
|
970
|
+
}
|
|
971
|
+
|
|
960
972
|
.fm-admin .items-center {
|
|
961
973
|
align-items: center;
|
|
962
974
|
}
|
|
@@ -977,6 +989,10 @@ video {
|
|
|
977
989
|
gap: 0.25rem;
|
|
978
990
|
}
|
|
979
991
|
|
|
992
|
+
.fm-admin .gap-1\.5 {
|
|
993
|
+
gap: 0.375rem;
|
|
994
|
+
}
|
|
995
|
+
|
|
980
996
|
.fm-admin .gap-2 {
|
|
981
997
|
gap: 0.5rem;
|
|
982
998
|
}
|
|
@@ -1348,6 +1364,11 @@ video {
|
|
|
1348
1364
|
background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));
|
|
1349
1365
|
}
|
|
1350
1366
|
|
|
1367
|
+
.fm-admin .bg-slate-700 {
|
|
1368
|
+
--tw-bg-opacity: 1;
|
|
1369
|
+
background-color: rgb(51 65 85 / var(--tw-bg-opacity, 1));
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1351
1372
|
.fm-admin .bg-slate-800 {
|
|
1352
1373
|
--tw-bg-opacity: 1;
|
|
1353
1374
|
background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1));
|
|
@@ -1367,6 +1388,15 @@ video {
|
|
|
1367
1388
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
|
1368
1389
|
}
|
|
1369
1390
|
|
|
1391
|
+
.fm-admin .object-contain {
|
|
1392
|
+
-o-object-fit: contain;
|
|
1393
|
+
object-fit: contain;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
.fm-admin .p-0\.5 {
|
|
1397
|
+
padding: 0.125rem;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1370
1400
|
.fm-admin .p-3 {
|
|
1371
1401
|
padding: 0.75rem;
|
|
1372
1402
|
}
|
|
@@ -1726,6 +1756,10 @@ video {
|
|
|
1726
1756
|
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
|
|
1727
1757
|
}
|
|
1728
1758
|
|
|
1759
|
+
.fm-admin .underline {
|
|
1760
|
+
text-decoration-line: underline;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1729
1763
|
.fm-admin .opacity-0 {
|
|
1730
1764
|
opacity: 0;
|
|
1731
1765
|
}
|
|
@@ -1848,6 +1882,11 @@ video {
|
|
|
1848
1882
|
background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));
|
|
1849
1883
|
}
|
|
1850
1884
|
|
|
1885
|
+
.fm-admin .hover\:bg-slate-600:hover {
|
|
1886
|
+
--tw-bg-opacity: 1;
|
|
1887
|
+
background-color: rgb(71 85 105 / var(--tw-bg-opacity, 1));
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1851
1890
|
.fm-admin .hover\:bg-slate-700:hover {
|
|
1852
1891
|
--tw-bg-opacity: 1;
|
|
1853
1892
|
background-color: rgb(51 65 85 / var(--tw-bg-opacity, 1));
|
|
@@ -1962,6 +2001,10 @@ video {
|
|
|
1962
2001
|
background-color: rgb(241 245 249 / var(--tw-bg-opacity, 1));
|
|
1963
2002
|
}
|
|
1964
2003
|
|
|
2004
|
+
.fm-admin :is(.group:hover .group-hover\:inline-flex) {
|
|
2005
|
+
display: inline-flex;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
1965
2008
|
.fm-admin :is(.peer:checked ~ .peer-checked\:border-blue-500) {
|
|
1966
2009
|
--tw-border-opacity: 1;
|
|
1967
2010
|
border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));
|