source_monitor 0.13.0 → 0.14.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.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/sm-configuration-setting/reference/settings-catalog.md +1 -0
  3. data/.claude/skills/sm-configure/SKILL.md +8 -1
  4. data/.claude/skills/sm-configure/reference/configuration-reference.md +11 -0
  5. data/.claude/skills/sm-event-handler/SKILL.md +1 -1
  6. data/.claude/skills/sm-event-handler/reference/events-api.md +1 -1
  7. data/.claude/skills/sm-host-setup/SKILL.md +13 -3
  8. data/.claude/skills/sm-host-setup/reference/initializer-template.md +11 -0
  9. data/.claude/skills/sm-host-setup/reference/setup-checklist.md +9 -1
  10. data/.claude/skills/sm-upgrade/reference/version-history.md +12 -0
  11. data/CHANGELOG.md +19 -0
  12. data/Gemfile.lock +1 -1
  13. data/README.md +3 -3
  14. data/VERSION +1 -1
  15. data/app/assets/builds/source_monitor/application.css +4 -0
  16. data/app/controllers/source_monitor/application_controller.rb +73 -14
  17. data/app/controllers/source_monitor/bulk_scrape_enablements_controller.rb +1 -1
  18. data/app/controllers/source_monitor/import_sessions/bulk_configuration.rb +3 -1
  19. data/app/controllers/source_monitor/import_sessions_controller.rb +118 -72
  20. data/app/controllers/source_monitor/sources_controller.rb +4 -18
  21. data/app/models/source_monitor/source.rb +1 -1
  22. data/app/views/layouts/source_monitor/application.html.erb +6 -0
  23. data/docs/configuration.md +18 -1
  24. data/docs/deployment.md +1 -1
  25. data/docs/goals/engine-hardening/.goalbuddy-board/app.js +543 -0
  26. data/docs/goals/engine-hardening/.goalbuddy-board/goalbuddy-mark.png +0 -0
  27. data/docs/goals/engine-hardening/.goalbuddy-board/index.html +111 -0
  28. data/docs/goals/engine-hardening/.goalbuddy-board/styles.css +991 -0
  29. data/docs/goals/engine-hardening/goal.md +97 -0
  30. data/docs/goals/engine-hardening/notes/T001-spec-validation.md +37 -0
  31. data/docs/goals/engine-hardening/state.yaml +324 -0
  32. data/docs/setup.md +3 -3
  33. data/docs/upgrade.md +41 -0
  34. data/lib/generators/source_monitor/install/templates/source_monitor.rb.tt +10 -0
  35. data/lib/source_monitor/analytics/scrape_recommendations.rb +21 -2
  36. data/lib/source_monitor/configuration/authentication_settings.rb +5 -1
  37. data/lib/source_monitor/fetching/feed_fetcher/failure_outcome.rb +85 -0
  38. data/lib/source_monitor/fetching/feed_fetcher/success_outcome.rb +85 -0
  39. data/lib/source_monitor/fetching/feed_fetcher.rb +27 -88
  40. data/lib/source_monitor/fetching/fetch_runner.rb +12 -5
  41. data/lib/source_monitor/import_sessions/wizard.rb +612 -0
  42. data/lib/source_monitor/items/batch_item_creator.rb +7 -6
  43. data/lib/source_monitor/items/item_creator.rb +7 -14
  44. data/lib/source_monitor/items/normalized_entry.rb +61 -0
  45. data/lib/source_monitor/security/authentication.rb +10 -0
  46. data/lib/source_monitor/version.rb +1 -1
  47. data/lib/source_monitor.rb +2 -0
  48. data/source_monitor.gemspec +7 -2
  49. metadata +12 -68
  50. data/.claude/agent-memory/vbw-vbw-debugger/MEMORY.md +0 -15
  51. data/.claude/agent-memory/vbw-vbw-dev/MEMORY.md +0 -34
  52. data/.claude/agent-memory/vbw-vbw-lead/MEMORY.md +0 -49
  53. data/.claude/agents/rails-concern.md +0 -464
  54. data/.claude/agents/rails-controller.md +0 -424
  55. data/.claude/agents/rails-hotwire.md +0 -446
  56. data/.claude/agents/rails-implement.md +0 -374
  57. data/.claude/agents/rails-job.md +0 -334
  58. data/.claude/agents/rails-lint.md +0 -294
  59. data/.claude/agents/rails-mailer.md +0 -371
  60. data/.claude/agents/rails-migration.md +0 -449
  61. data/.claude/agents/rails-model.md +0 -420
  62. data/.claude/agents/rails-policy.md +0 -443
  63. data/.claude/agents/rails-presenter.md +0 -427
  64. data/.claude/agents/rails-query.md +0 -412
  65. data/.claude/agents/rails-review.md +0 -490
  66. data/.claude/agents/rails-service.md +0 -458
  67. data/.claude/agents/rails-state-records.md +0 -465
  68. data/.claude/agents/rails-tdd.md +0 -314
  69. data/.claude/agents/rails-test.md +0 -441
  70. data/.claude/agents/rails-view-component.md +0 -418
  71. data/.claude/commands/rails-audit.md +0 -77
  72. data/.claude/commands/release.md +0 -366
  73. data/.claude/hooks/block-secrets.sh +0 -52
  74. data/.claude/settings.json +0 -85
  75. data/.claude/skills/action-cable-patterns/SKILL.md +0 -296
  76. data/.claude/skills/action-mailer-patterns/SKILL.md +0 -295
  77. data/.claude/skills/active-storage-setup/SKILL.md +0 -311
  78. data/.claude/skills/api-versioning/SKILL.md +0 -294
  79. data/.claude/skills/authentication-flow/SKILL.md +0 -335
  80. data/.claude/skills/authentication-flow/reference/current.md +0 -248
  81. data/.claude/skills/authentication-flow/reference/passwordless.md +0 -253
  82. data/.claude/skills/authentication-flow/reference/sessions.md +0 -201
  83. data/.claude/skills/authorization-pundit/SKILL.md +0 -462
  84. data/.claude/skills/caching-strategies/SKILL.md +0 -350
  85. data/.claude/skills/database-migrations/SKILL.md +0 -354
  86. data/.claude/skills/form-object-patterns/SKILL.md +0 -399
  87. data/.claude/skills/hotwire-patterns/SKILL.md +0 -247
  88. data/.claude/skills/hotwire-patterns/reference/stimulus.md +0 -307
  89. data/.claude/skills/hotwire-patterns/reference/tailwind-integration.md +0 -112
  90. data/.claude/skills/hotwire-patterns/reference/turbo-frames.md +0 -158
  91. data/.claude/skills/hotwire-patterns/reference/turbo-streams.md +0 -218
  92. data/.claude/skills/i18n-patterns/SKILL.md +0 -320
  93. data/.claude/skills/install/SKILL.md +0 -367
  94. data/.claude/skills/performance-optimization/SKILL.md +0 -311
  95. data/.claude/skills/rails-architecture/SKILL.md +0 -259
  96. data/.claude/skills/rails-architecture/reference/error-handling.md +0 -333
  97. data/.claude/skills/rails-architecture/reference/event-tracking.md +0 -142
  98. data/.claude/skills/rails-architecture/reference/layer-interactions.md +0 -417
  99. data/.claude/skills/rails-architecture/reference/multi-tenancy.md +0 -152
  100. data/.claude/skills/rails-architecture/reference/query-patterns.md +0 -342
  101. data/.claude/skills/rails-architecture/reference/service-patterns.md +0 -286
  102. data/.claude/skills/rails-architecture/reference/state-records.md +0 -250
  103. data/.claude/skills/rails-architecture/reference/testing-strategy.md +0 -326
  104. data/.claude/skills/rails-concern/SKILL.md +0 -399
  105. data/.claude/skills/rails-controller/SKILL.md +0 -336
  106. data/.claude/skills/rails-model-generator/SKILL.md +0 -321
  107. data/.claude/skills/rails-model-generator/reference/validations.md +0 -298
  108. data/.claude/skills/rails-presenter/SKILL.md +0 -274
  109. data/.claude/skills/rails-query-object/SKILL.md +0 -289
  110. data/.claude/skills/rails-service-object/SKILL.md +0 -349
  111. data/.claude/skills/solid-queue-setup/SKILL.md +0 -307
  112. data/.claude/skills/tdd-cycle/SKILL.md +0 -359
  113. data/.claude/skills/viewcomponent-patterns/SKILL.md +0 -333
  114. data/app/controllers/source_monitor/import_sessions/entry_annotation.rb +0 -187
  115. data/app/controllers/source_monitor/import_sessions/health_check_management.rb +0 -112
  116. data/app/controllers/source_monitor/import_sessions/opml_parser.rb +0 -130
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/blank"
4
+ require "source_monitor/items/item_creator/entry_parser"
5
+ require "source_monitor/items/item_creator/content_extractor"
6
+
7
+ module SourceMonitor
8
+ module Items
9
+ class NormalizedEntry
10
+ def self.call(source:, entry:, content_extractor: nil)
11
+ new(source: source, entry: entry, content_extractor: content_extractor).item_attributes
12
+ end
13
+
14
+ def initialize(source:, entry:, content_extractor: nil)
15
+ @source = source
16
+ @entry = entry
17
+ @content_extractor = content_extractor || ItemCreator::ContentExtractor.new(source: source)
18
+ end
19
+
20
+ def attributes
21
+ @attributes ||= parser.parse
22
+ end
23
+
24
+ def item_attributes
25
+ attributes.merge(guid: item_guid)
26
+ end
27
+
28
+ def raw_guid
29
+ attributes[:guid]
30
+ end
31
+
32
+ def normalized_guid
33
+ raw_guid.present? ? raw_guid.downcase : nil
34
+ end
35
+
36
+ def raw_guid_present?
37
+ normalized_guid.present?
38
+ end
39
+
40
+ def item_guid
41
+ normalized_guid.presence || content_fingerprint
42
+ end
43
+
44
+ def content_fingerprint
45
+ attributes[:content_fingerprint]
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :source, :entry, :content_extractor
51
+
52
+ def parser
53
+ @parser ||= ItemCreator::EntryParser.new(
54
+ source: source,
55
+ entry: entry,
56
+ content_extractor: content_extractor
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
@@ -31,6 +31,16 @@ module SourceMonitor
31
31
  config.authenticate_handler.present? || config.authorize_handler.present?
32
32
  end
33
33
 
34
+ # Fail-closed predicate. The engine denies access when the host app has
35
+ # configured no authentication/authorization handler AND has not
36
+ # explicitly opted into open access. Configured handlers always win: when
37
+ # a handler is present the handler decides and this returns false.
38
+ def self.access_denied_by_default?(_controller = nil)
39
+ return false if authentication_configured?
40
+
41
+ !SourceMonitor.config.authentication.open_access
42
+ end
43
+
34
44
  def self.authorize_configured?
35
45
  SourceMonitor.config.authentication.authorize_handler.present?
36
46
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SourceMonitor
4
- VERSION = "0.13.0"
4
+ VERSION = "0.14.0"
5
5
  end
@@ -89,6 +89,7 @@ module SourceMonitor
89
89
 
90
90
  module ImportSessions
91
91
  autoload :EntryNormalizer, "source_monitor/import_sessions/entry_normalizer"
92
+ autoload :Wizard, "source_monitor/import_sessions/wizard"
92
93
  autoload :HealthCheckBroadcaster, "source_monitor/import_sessions/health_check_broadcaster"
93
94
  autoload :HealthCheckUpdater, "source_monitor/import_sessions/health_check_updater"
94
95
  autoload :OPMLImporter, "source_monitor/import_sessions/opml_importer"
@@ -108,6 +109,7 @@ module SourceMonitor
108
109
 
109
110
  module Items
110
111
  autoload :ItemCreator, "source_monitor/items/item_creator"
112
+ autoload :NormalizedEntry, "source_monitor/items/normalized_entry"
111
113
  autoload :RetentionPruner, "source_monitor/items/retention_pruner"
112
114
  autoload :RetentionStrategies, "source_monitor/items/retention_strategies"
113
115
  end
@@ -23,11 +23,16 @@ Gem::Specification.new do |spec|
23
23
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
24
  tracked_files = `git ls-files -z`.split("\x0")
25
25
  tracked_files.reject do |file|
26
- file.start_with?(".ai/", ".github/", ".vbw-planning/", "coverage/", "node_modules/", "pkg/", "spec/", "test/", "tmp/", "vendor/", "examples/", "bin/")
26
+ file.start_with?(".ai/", ".github/", ".vbw-planning/", "coverage/", "node_modules/", "pkg/", "spec/", "test/", "tmp/", "vendor/", "examples/", "bin/") ||
27
+ # Exclude all .claude internals (agents, hooks, agent-memory, settings,
28
+ # commands) but keep the intended SourceMonitor sm-* skills. Driven from
29
+ # git ls-files (inside Dir.chdir) so packaging is CWD-independent --- a
30
+ # bare Dir[] glob here returned nothing on CI when another test had
31
+ # changed the process working directory.
32
+ (file.start_with?(".claude/") && !file.start_with?(".claude/skills/sm-"))
27
33
  end
28
34
  end
29
35
  spec.files += [ "CHANGELOG.md" ].select { |path| File.exist?(File.join(__dir__, path)) }
30
- spec.files += Dir[".claude/skills/sm-*/**/*"]
31
36
  spec.files.uniq!
32
37
 
33
38
  spec.require_paths = [ "lib" ]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: source_monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dchuk
@@ -258,67 +258,6 @@ executables: []
258
258
  extensions: []
259
259
  extra_rdoc_files: []
260
260
  files:
261
- - ".claude/agent-memory/vbw-vbw-debugger/MEMORY.md"
262
- - ".claude/agent-memory/vbw-vbw-dev/MEMORY.md"
263
- - ".claude/agent-memory/vbw-vbw-lead/MEMORY.md"
264
- - ".claude/agents/rails-concern.md"
265
- - ".claude/agents/rails-controller.md"
266
- - ".claude/agents/rails-hotwire.md"
267
- - ".claude/agents/rails-implement.md"
268
- - ".claude/agents/rails-job.md"
269
- - ".claude/agents/rails-lint.md"
270
- - ".claude/agents/rails-mailer.md"
271
- - ".claude/agents/rails-migration.md"
272
- - ".claude/agents/rails-model.md"
273
- - ".claude/agents/rails-policy.md"
274
- - ".claude/agents/rails-presenter.md"
275
- - ".claude/agents/rails-query.md"
276
- - ".claude/agents/rails-review.md"
277
- - ".claude/agents/rails-service.md"
278
- - ".claude/agents/rails-state-records.md"
279
- - ".claude/agents/rails-tdd.md"
280
- - ".claude/agents/rails-test.md"
281
- - ".claude/agents/rails-view-component.md"
282
- - ".claude/commands/rails-audit.md"
283
- - ".claude/commands/release.md"
284
- - ".claude/hooks/block-secrets.sh"
285
- - ".claude/settings.json"
286
- - ".claude/skills/action-cable-patterns/SKILL.md"
287
- - ".claude/skills/action-mailer-patterns/SKILL.md"
288
- - ".claude/skills/active-storage-setup/SKILL.md"
289
- - ".claude/skills/api-versioning/SKILL.md"
290
- - ".claude/skills/authentication-flow/SKILL.md"
291
- - ".claude/skills/authentication-flow/reference/current.md"
292
- - ".claude/skills/authentication-flow/reference/passwordless.md"
293
- - ".claude/skills/authentication-flow/reference/sessions.md"
294
- - ".claude/skills/authorization-pundit/SKILL.md"
295
- - ".claude/skills/caching-strategies/SKILL.md"
296
- - ".claude/skills/database-migrations/SKILL.md"
297
- - ".claude/skills/form-object-patterns/SKILL.md"
298
- - ".claude/skills/hotwire-patterns/SKILL.md"
299
- - ".claude/skills/hotwire-patterns/reference/stimulus.md"
300
- - ".claude/skills/hotwire-patterns/reference/tailwind-integration.md"
301
- - ".claude/skills/hotwire-patterns/reference/turbo-frames.md"
302
- - ".claude/skills/hotwire-patterns/reference/turbo-streams.md"
303
- - ".claude/skills/i18n-patterns/SKILL.md"
304
- - ".claude/skills/install/SKILL.md"
305
- - ".claude/skills/performance-optimization/SKILL.md"
306
- - ".claude/skills/rails-architecture/SKILL.md"
307
- - ".claude/skills/rails-architecture/reference/error-handling.md"
308
- - ".claude/skills/rails-architecture/reference/event-tracking.md"
309
- - ".claude/skills/rails-architecture/reference/layer-interactions.md"
310
- - ".claude/skills/rails-architecture/reference/multi-tenancy.md"
311
- - ".claude/skills/rails-architecture/reference/query-patterns.md"
312
- - ".claude/skills/rails-architecture/reference/service-patterns.md"
313
- - ".claude/skills/rails-architecture/reference/state-records.md"
314
- - ".claude/skills/rails-architecture/reference/testing-strategy.md"
315
- - ".claude/skills/rails-concern/SKILL.md"
316
- - ".claude/skills/rails-controller/SKILL.md"
317
- - ".claude/skills/rails-model-generator/SKILL.md"
318
- - ".claude/skills/rails-model-generator/reference/validations.md"
319
- - ".claude/skills/rails-presenter/SKILL.md"
320
- - ".claude/skills/rails-query-object/SKILL.md"
321
- - ".claude/skills/rails-service-object/SKILL.md"
322
261
  - ".claude/skills/sm-architecture/SKILL.md"
323
262
  - ".claude/skills/sm-architecture/reference/extraction-patterns.md"
324
263
  - ".claude/skills/sm-architecture/reference/module-map.md"
@@ -358,9 +297,6 @@ files:
358
297
  - ".claude/skills/sm-upgrade/SKILL.md"
359
298
  - ".claude/skills/sm-upgrade/reference/upgrade-workflow.md"
360
299
  - ".claude/skills/sm-upgrade/reference/version-history.md"
361
- - ".claude/skills/solid-queue-setup/SKILL.md"
362
- - ".claude/skills/tdd-cycle/SKILL.md"
363
- - ".claude/skills/viewcomponent-patterns/SKILL.md"
364
300
  - ".gitignore"
365
301
  - ".rubocop.yml"
366
302
  - ".ruby-version"
@@ -408,9 +344,6 @@ files:
408
344
  - app/controllers/source_monitor/health_controller.rb
409
345
  - app/controllers/source_monitor/import_history_dismissals_controller.rb
410
346
  - app/controllers/source_monitor/import_sessions/bulk_configuration.rb
411
- - app/controllers/source_monitor/import_sessions/entry_annotation.rb
412
- - app/controllers/source_monitor/import_sessions/health_check_management.rb
413
- - app/controllers/source_monitor/import_sessions/opml_parser.rb
414
347
  - app/controllers/source_monitor/import_sessions_controller.rb
415
348
  - app/controllers/source_monitor/item_scrapes_controller.rb
416
349
  - app/controllers/source_monitor/items_controller.rb
@@ -545,6 +478,13 @@ files:
545
478
  - docs/configuration.md
546
479
  - docs/deployment.md
547
480
  - docs/gh-cli-workflow.md
481
+ - docs/goals/engine-hardening/.goalbuddy-board/app.js
482
+ - docs/goals/engine-hardening/.goalbuddy-board/goalbuddy-mark.png
483
+ - docs/goals/engine-hardening/.goalbuddy-board/index.html
484
+ - docs/goals/engine-hardening/.goalbuddy-board/styles.css
485
+ - docs/goals/engine-hardening/goal.md
486
+ - docs/goals/engine-hardening/notes/T001-spec-validation.md
487
+ - docs/goals/engine-hardening/state.yaml
548
488
  - docs/setup-validation-log.md
549
489
  - docs/setup.md
550
490
  - docs/troubleshooting.md
@@ -598,7 +538,9 @@ files:
598
538
  - lib/source_monitor/fetching/feed_fetcher.rb
599
539
  - lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb
600
540
  - lib/source_monitor/fetching/feed_fetcher/entry_processor.rb
541
+ - lib/source_monitor/fetching/feed_fetcher/failure_outcome.rb
601
542
  - lib/source_monitor/fetching/feed_fetcher/source_updater.rb
543
+ - lib/source_monitor/fetching/feed_fetcher/success_outcome.rb
602
544
  - lib/source_monitor/fetching/fetch_error.rb
603
545
  - lib/source_monitor/fetching/fetch_runner.rb
604
546
  - lib/source_monitor/fetching/retry_orchestrator.rb
@@ -619,12 +561,14 @@ files:
619
561
  - lib/source_monitor/import_sessions/health_check_broadcaster.rb
620
562
  - lib/source_monitor/import_sessions/health_check_updater.rb
621
563
  - lib/source_monitor/import_sessions/opml_importer.rb
564
+ - lib/source_monitor/import_sessions/wizard.rb
622
565
  - lib/source_monitor/instrumentation.rb
623
566
  - lib/source_monitor/items/batch_item_creator.rb
624
567
  - lib/source_monitor/items/item_creator.rb
625
568
  - lib/source_monitor/items/item_creator/content_extractor.rb
626
569
  - lib/source_monitor/items/item_creator/entry_parser.rb
627
570
  - lib/source_monitor/items/item_creator/entry_parser/media_extraction.rb
571
+ - lib/source_monitor/items/normalized_entry.rb
628
572
  - lib/source_monitor/items/retention_pruner.rb
629
573
  - lib/source_monitor/items/retention_strategies.rb
630
574
  - lib/source_monitor/items/retention_strategies/destroy.rb
@@ -1,15 +0,0 @@
1
- # Debugger Memory
2
-
3
- ## Rails Association Cache Pollution Pattern
4
- - `source.items.new` AND `Item.new(source: source)` both add to the loaded association cache via inverse_of
5
- - Only `Item.new(source_id: source.id)` truly bypasses inverse_of and avoids cache pollution
6
- - When unsaved/invalid records are in a loaded has_many cache, `parent.update!` triggers auto-save and fails with `RecordInvalid: Items is invalid`
7
- - `update_columns` bypasses all callbacks and auto-save, safe to use with polluted caches
8
- - After `update_columns`, call `reload` so the in-memory object reflects DB state
9
-
10
- ## Test Patterns
11
- - Use `clean_source_monitor_tables!` in setup for blank-slate DB
12
- - `create_source!` is the factory helper (in test_helper.rb)
13
- - WebMock stubs + VCR cassettes for HTTP; `stub_request(:get, url)`
14
- - Stub class methods with `singleton_class.define_method` pattern
15
- - Always restore stubs in `ensure` block
@@ -1,34 +0,0 @@
1
- # VBW Dev Agent Memory
2
-
3
- ## Project: source_monitor
4
- - Rails engine gem for RSS/feed monitoring
5
- - Ruby 3.4.4, Rails 8.x
6
- - Test suite: 473 tests via `bin/rails test` (takes ~76 seconds)
7
- - RuboCop uses `rubocop-rails-omakase` base config
8
-
9
- ## Key Learnings
10
-
11
- ### Shell/Bash in zsh
12
- - `!` in zsh inline scripts causes `command not found` errors. Use `case` statements instead of `if ! ...` patterns.
13
- - Use `IFS= read -r` when reading filenames from pipes to handle edge cases.
14
-
15
- ### RuboCop scope vs git scope
16
- - RuboCop inspects ALL Ruby-like files (Gemfile, Rakefile, .gemspec, .rake, bin/*, config.ru), not just `.rb` files.
17
- - `git ls-files -- '*.rb'` only matches `.rb` extensions. Plans scoped to `.rb` files may miss RuboCop violations in non-`.rb` Ruby files.
18
- - `test/tmp/` contains untracked generated Rails app templates. These are NOT git-tracked but RuboCop scans them unless excluded.
19
-
20
- ### File structure
21
- - `test/lib/tmp/install_generator/` contains test fixtures (1 tracked file: `config/initializers/source_monitor.rb`)
22
- - `test/tmp/host_app_template_*` directories are generated test artifacts, not git-tracked
23
- - `.rubocop.yml` is at project root, inherits from `rubocop-rails-omakase`
24
-
25
- ### Frozen string literal pragma
26
- - Completed in commit `5f02db8` -- 113 files modified
27
- - Added `test/tmp/**/*` to RuboCop exclude list
28
-
29
- ### RuboCop omakase ruleset details
30
- - Only 45 cops enabled (out of 775 available)
31
- - ALL Metrics cops disabled (ClassLength, MethodLength, BlockLength, etc.)
32
- - After frozen_string_literal fix, codebase had zero remaining violations
33
- - No `.rubocop.yml` exclusions needed for large files since Metrics cops are off
34
- - Plan 02 completed with no code changes required
@@ -1,49 +0,0 @@
1
- # Lead Agent Memory -- SourceMonitor
2
-
3
- ## Project Quick Facts
4
- - Rails 8 engine, Ruby 3.4+, PostgreSQL-only
5
- - 325 git-tracked Ruby files, 130 test files
6
- - Coverage baseline: 2328 uncovered lines in config/coverage_baseline.json
7
- - RuboCop: rubocop-rails-omakase, config at .rubocop.yml
8
- - CI: .github/workflows/ci.yml (lint, security, test, release-verify, nightly profiling)
9
- - Large files: FeedFetcher (627), Configuration (655), ImportSessionsController (792)
10
-
11
- ## Phase 1 Findings
12
- - 98 git-tracked .rb files missing frozen_string_literal (out of 325)
13
- - Breakdown: app/(5), lib/(24), test/(43 non-dummy), test/dummy/(22), config/(1), db/migrate/(4)
14
- - test/tmp/ is NOT git-tracked (generated by install_generator tests) -- exclude from changes
15
- - test/lib/tmp/install_generator/config/initializers/source_monitor.rb IS tracked and already has pragma
16
- - bin/rubocop wrapper forces --config .rubocop.yml
17
- - Phase 1 criterion #3 (10% coverage shrink) not addressed by plans 01/02 -- noted for future
18
-
19
- ## Phase 2 Planning Insights
20
- - Coverage baseline.json has 2117 uncovered lines across 105 files (not 2328 -- that was line count)
21
- - Top 7 files account for ~743 uncovered lines (35% of total)
22
- - FeedFetcher: 245 uncovered, 12 existing tests, uses VCR+WebMock
23
- - ItemCreator: 228 uncovered, 8 existing tests, needs mock entries for Atom/JSON branches
24
- - Configuration: 94 uncovered, 5 existing tests, ~12 nested settings classes
25
- - Dashboard::Queries: 66 uncovered, 7 existing tests, uses raw SQL + Cache
26
- - BulkSourceScraper: 66 uncovered, 6 existing tests, ActiveJob test adapter
27
- - Broadcaster: 48 uncovered, NO existing test file -- needs creation
28
- - SourcesIndexMetrics: 34 uncovered, 3 existing tests
29
- - All 5 Phase 2 plans are Wave 1 (no inter-plan dependencies, no file conflicts)
30
- - Testing main files will indirectly cover supporting files (retry_policy, fetch_error, state, enqueuer, etc.)
31
- - Broadcaster tests need Turbo::StreamsChannel stubs -- no full Action Cable required
32
- - 50% coverage target requires ~1059 lines covered; direct plans target ~630, rest from indirect
33
-
34
- ## Phase 4 Planning Insights
35
- - 3 plans: conventions-audit (wave 1), item-creator-extraction (wave 1), final-verification (wave 2)
36
- - SourcesController has dead `fetch`/`retry` methods (leftover from Phase 3 CRUD extraction)
37
- - ImportSessionsController `new` and `create` are byte-for-byte identical
38
- - 4 RuboCop violations in db/migrate/20260210204022_add_composite_index_to_log_entries.rb
39
- - Duplicate test: test/controllers/concerns/ vs test/controllers/source_monitor/concerns/
40
- - ItemCreator at 601 lines is the last file over 300 lines -- extract to entry_parser + content_extractor
41
- - Coverage baseline still at 2117 uncovered (not regenerated since Phase 1) -- must regenerate
42
- - 60% reduction target: at most 847 uncovered lines
43
- - dashboard/queries.rb (356) and application_helper.rb (346) are near 300 but acceptable as view/query code
44
- - `bin/update-coverage-baseline` requires `COVERAGE=1 bin/rails test` first
45
-
46
- ## Bash/Shell Notes
47
- - zsh on macOS -- `!` in shell conditionals causes `command not found` errors
48
- - Use `case` statements instead of `if ! grep` patterns in zsh
49
- - git ls-files piped to while loops works reliably for file enumeration