tasks/completed/phase_17_02_complexity_findings_2025-10-12.md
app/controllers/source_monitor/items_controller.rb:120 and app/controllers/source_monitor/sources_controller.rb:172 both implement identical sanitized_search_params; keeping these in each controller risks divergence in future filters.app/controllers/source_monitor/items_controller.rb:13-33 mixes pagination math, search setup, and view state assembly, crowding the action and duplicating paging behaviour elsewhere.app/controllers/source_monitor/sources_controller.rb:11-27 performs distribution bucketing and analytics queries in-controller, making the action heavy and difficult to unit test.app/controllers/source_monitor/items_controller.rb:38-83 and app/controllers/source_monitor/sources_controller.rb:140-168 contain sizeable arrays of Turbo Stream operations; changes to toast behaviour or DOM IDs now require controller edits.app/controllers/source_monitor/fetch_logs_controller.rb:5-23 and app/controllers/source_monitor/scrape_logs_controller.rb:5-45 share similar scoping patterns but diverge in parameter casting, inviting subtle inconsistencies.SourceMonitor::Source doing too much — app/models/source_monitor/source.rb:20-150 handles sanitization, URL normalization, defaulting, and health thresholds; the breadth complicates reuse of sanitization rules by other models.SourceMonitor::Item URL normalization — app/models/source_monitor/item.rb:52-133 embeds URL parsing logic; other URL-backed models cannot reuse the behaviour without duplication.Fetching::FetchRunner orchestration sprawl — lib/source_monitor/fetching/fetch_runner.rb:39-186 owns locking, state transitions, retention pruning, scrape enqueueing, retry scheduling, and instrumentation dispatch in one class.Scraping::ItemScraper responsibilities — lib/source_monitor/scraping/item_scraper.rb:28-200 combines adapter discovery, HTTP metadata handling, persistence, logging, and event publication within a single method flow.Items::RetentionPruner strategy branching — lib/source_monitor/items/retention_pruner.rb:21-162 interleaves strategy selection with batch execution and counter maintenance, making soft-delete vs destroy paths harder to evolve.lib/source_monitor/dashboard/queries.rb:17-87 fires multiple fresh queries for every request without caching or batching, and mixes routing helpers with aggregation logic.app/jobs/source_monitor/fetch_feed_job.rb:5-19 rescues only concurrency errors; transient network failures rely on defaults rather than an explicit retry/backoff plan.app/jobs/source_monitor/scrape_item_job.rb:25-45 issues update_columns inside locks; behaviour overlaps with Scraping::Enqueuer, risking drift between enqueue-time and job-time state handling.app/jobs/source_monitor/item_cleanup_job.rb:18-69 and app/jobs/source_monitor/log_cleanup_job.rb:18-71 repeat the same option-shaping logic, increasing maintenance costs as CLI flags expand.lib/source_monitor/scheduler.rb:7-49 enqueues fetches but emits no instrumentation or metrics, limiting observability when schedule gaps occur.app/assets/javascripts/source_monitor/application.js:1-32 depends on global window.Stimulus, diverging from modern ES module patterns and risking double registration.app/assets/javascripts/source_monitor/controllers/dropdown_controller.js:1-14 assumes window.StimulusDropdown exists; missing UMD bundle breaks dropdowns without fallback.app/assets/javascripts/source_monitor/dropdown_transition_shim.js:1-24 implements a custom useTransition that may fall behind the upstream library API.app/assets/builds/tailwind.css (~1.4k lines) is committed without guardrails ensuring regeneration during releases.bundle exec rubocop --format offenses reports 366 issues (352 auto-correctable spacing offenses), indicating style drift.bundle exec brakeman fails because the gem is not declared; security checks are currently blocked.test/test_helper.rb lacks SimpleCov hooks, so coverage regressions are invisible.SourceMonitor::Sanitization), encapsulate URL normalization in a dedicated module, break FetchRunner into concurrency, state, and follow-up collaborators, and separate ItemScraper responsibilities into adapter resolver, persistence handler, and logger.StimulusDropdown) are missing.@hotwired/stimulus-use package or document divergence to keep behaviour in sync.bin/rails test:assets or yarn lint) and document Tailwind rebuild requirements in contributor guides.| Issue | Area | Effort | Impact | Priority |
|---|---|---|---|---|
Decompose FetchRunner responsibilities | Fetching services | Medium | High | P1 |
| Shared controller sanitization/pagination helpers | Controllers | Low | High | P1 |
| Align Scraping enqueue vs job state handling | Jobs/Services | Medium | High | P1 |
| Formalize Stimulus asset pipeline | Front-end | Medium | Medium | P2 |
| Consolidate cleanup job option parsing | Background jobs | Low | Medium | P2 |
| Introduce Rubocop/Brakeman & coverage baselines | Tooling | Low | Medium | P2 |
Replace ItemScraper adapter/persistence monolith | Scraping services | High | High | P1 |
| Dashboard query caching | Dashboard | Medium | Medium | P3 |
| Tailwind rebuild automation | Front-end | Low | Medium | P2 |
P1 items should seed Phase 17.03 workstreams; P2 items follow once shared utilities exist; P3 items can ride along with subsequent dashboard improvements.
.ai/phase_17_02_complexity_findings_2025-10-12.md.