Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fcbe1d1
fix: resolve RuboCop configuration warnings
fabionl Feb 1, 2026
9ef057d
Fix rubocop autocorrectable violation
fabionl Feb 1, 2026
f83b7d0
Refactor facility schedule, service, and welcome builders for improve…
fabionl Feb 1, 2026
7ff79c9
chore: add RuboCop remediation plan and tracker documentation
fabionl Feb 1, 2026
cf7b88a
fix: update time handling to use in_time_zone and remove redundant va…
fabionl Feb 1, 2026
104e806
Fix RuboCop: Stage 4-5 - RSpec/ReceiveMessages (159 offenses) and RSp…
fabionl Feb 1, 2026
30a5606
refactor: rename GeoLocation method from find_by_address to for_addre…
fabionl Feb 1, 2026
bbaff1d
docs: add Git policy to prevent agents from modifying git history
fabionl Feb 1, 2026
06b9b36
fix: update model references in Rails agent files to use github-copil…
fabionl Feb 1, 2026
f6ce235
chore: update instance_double usage to remove string literals in loca…
fabionl Feb 1, 2026
a615e7b
chore: update RSpec shared examples to use string literals for consis…
fabionl Feb 1, 2026
c0b8b40
chore: update RSpec tests to improve clarity and consistency in metho…
fabionl Feb 1, 2026
ac34d22
Refactor spec files to improve readability by renaming let variables …
fabionl Feb 2, 2026
3024d03
chore: streamline URL generation in Facilities::ShowComponent and imp…
fabionl Feb 2, 2026
a3ae07a
chore: Fix misplaced spec files
fabionl Feb 2, 2026
adb4643
chore: Update RSpec describe blocks to use method names for clarity
fabionl Feb 2, 2026
8ea3cb6
chore: Add rubocop:disable comments for validation skips in analytics…
fabionl Feb 2, 2026
6fb5cc6
chore: Update RuboCop remediation tracker and improve error handling …
fabionl Feb 2, 2026
f5cf5d0
update agents to use minimax coding plan's model
fabionl Mar 14, 2026
756358a
chore(rubocop): apply Stage 15 auto-corrections
fabionl Mar 14, 2026
f527532
chore(rubocop): complete Stage 15 - fix RSpec patterns and extract er…
fabionl Mar 14, 2026
72a9361
chore(rubocop): complete Stage 16 - fix RSpec naming patterns
fabionl Mar 14, 2026
179beda
chore(rubocop): complete Stage 17 - fix style issues
fabionl Mar 14, 2026
9e00f1c
chore(rubocop): complete Stage 18 - fix RSpec test patterns
fabionl Mar 14, 2026
616ee9e
chore(rubocop): complete RuboCop remediation - 99.3% offense reduction
fabionl Mar 14, 2026
858dc69
chore(rubocop): disable acceptable complexity metrics
fabionl Mar 14, 2026
c5022f0
docs: mark RuboCop remediation plan as complete
fabionl Mar 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .opencode/agents/rails-code-auditor.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Review code for quality and Rails conventions (report + suggest on request)
mode: subagent
model: opencode/big-pickle
model: minimax-coding-plan/MiniMax-M2.5
permission:
skill:
"rails-code-quality": "allow"
Expand Down
2 changes: 1 addition & 1 deletion .opencode/agents/rails-migration-manager.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Manage Rails migrations - create, run, rollback, and troubleshoot
mode: subagent
model: opencode/big-pickle
model: minimax-coding-plan/MiniMax-M2.5
permission:
skill:
"rails-migrations": "allow"
Expand Down
2 changes: 1 addition & 1 deletion .opencode/agents/rails-refactor.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Refactor code following Rails and project conventions
mode: subagent
model: opencode/big-pickle
model: minimax-coding-plan/MiniMax-M2.5
permission:
skill:
"rails-code-quality": "allow"
Expand Down
2 changes: 1 addition & 1 deletion .opencode/agents/rails-resource-builder.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Generate complete Rails resources (models, controllers, routes, tests)
mode: subagent
model: github-copilot/grok-code-fast-1
model: minimax-coding-plan/MiniMax-M2.5
permission:
skill:
"rails-models": "allow"
Expand Down
2 changes: 1 addition & 1 deletion .opencode/agents/rails-test-runner.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Execute tests and report results only
mode: subagent
model: github-copilot/grok-code-fast-1
model: minimax-coding-plan/MiniMax-M2.5
permission:
skill:
"rspec-testing": "allow"
Expand Down
41 changes: 34 additions & 7 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
require:
plugins:
- rubocop-packaging
- rubocop-performance
- rubocop-ast
- rubocop-rails
- rubocop-rspec

require:
- rubocop-ast



AllCops:
TargetRubyVersion: 3.1
Expand All @@ -29,7 +34,7 @@ Performance:
- '**/spec/**/*'

Rails:
StyleGuideBaseURL: https://rails.rubystyle.guide
DocumentationBaseURL: https://rails.rubystyle.guide

Rails/BulkChangeTable:
Exclude:
Expand Down Expand Up @@ -59,6 +64,11 @@ Rails/FilePath:
Enabled: true
EnforcedStyle: arguments

Rails/I18nLocaleTexts:
Enabled: false



# Prefer &&/|| over and/or.
Style/AndOr:
Enabled: true
Expand Down Expand Up @@ -89,10 +99,6 @@ Layout/EndAlignment:
Layout/EmptyLineAfterMagicComment:
Enabled: true

Layout/EmptyLinesAroundAccessModifier:
Enabled: false
EnforcedStyle: only_before

Layout/EmptyLinesAroundBlockBody:
Enabled: true

Expand Down Expand Up @@ -129,6 +135,11 @@ Layout/IndentationConsistency:
Enabled: true
EnforcedStyle: normal #indented_internal_methods

Layout/MultilineMethodCallIndentation:
EnforcedStyle: indented
Include:
- '**/spec/**/*'

# Two spaces, no tabs (for indentation).
Layout/IndentationWidth:
Enabled: true
Expand Down Expand Up @@ -323,6 +334,22 @@ Performance/DeletePrefix:
Performance/DeleteSuffix:
Enabled: true

# Disable RSpec/MultipleExpectations cop to reduce noise (443 instances)
# Note: Despite correct syntax, this configuration appears to not be properly
# respected by rubocop-rspec 3.7.0. Use --except RSpec/MultipleExpectations
# command-line flag to disable when needed.
RSpec/MultipleExpectations:
Enabled: false

RSpec/ExampleLength:
Enabled: false

RSpec/MultipleMemoizedHelpers:
Enabled: false

RSpec/NestedGroups:
Enabled: false

##########
# Metrics

Expand Down
20 changes: 20 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,26 @@ This codebase includes specialized agents for Rails development workflows. Invok
- Hotwire/Turbo (frontend)
- Devise (authentication), Pagy (pagination)

## Git Policy

**CRITICAL: Agents must never modify git history.** The following git operations are explicitly prohibited:

- `git add` or `git stage` - Agents must NOT stage changes
- `git reset HEAD` - Agents must NOT unstage changes
- `git commit` - Agents must NOT create commits
- `git commit --amend` - Agents must NOT amend commits
- `git rebase` - Agents must NOT perform rebases
- `git push` - Agents must NOT push to remote repositories
- Any other git history modification operations

**If agents require git operations:**
1. Complete all code changes using standard file tools (Read, Write, Edit)
2. Run tests and quality checks to verify the changes are correct
3. Ask the user to perform git staging, committing, or other git operations
4. Provide clear instructions on what commands to run and what changes to commit

**Rationale:** Git history modifications are destructive operations that should always be performed intentionally by the user. This policy prevents accidental data loss and ensures the user maintains full control over version control operations.

## Important Notes

- Active development on `develop` branch
Expand Down
2 changes: 2 additions & 0 deletions app/components/alerts/table_component.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

class Alerts::TableComponent < ViewComponent::Base
attr_reader :alerts

Expand Down
90 changes: 66 additions & 24 deletions app/components/facilities/show_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def switch_status_button
title = "Switch to Pending Reviews"
end

target_url = switch_status_admin_facility_path(id: facility.id, status: new_status)
target_url = switch_status_url(new_status)

link_to target_url, data: { turbo_method: :put } do
tag.span(class: "icon", title: title) do
Expand All @@ -51,6 +51,10 @@ def switch_status_button
end
end

def switch_status_url(new_status)
switch_status_admin_facility_path(id: facility.id, status: new_status)
end

def link_to_website
link_to facility.website_url, facility.website_url, target: "_blank", rel: "noopener" if facility.website_url.present?
end
Expand Down Expand Up @@ -79,7 +83,7 @@ def switch_button(service)
}

if provides_service?(service)
target_url = admin_facility_service_path(facility_id: facility.id, service_id: service.id)
target_url = switch_service_url(service, :delete)
options[:data][:turbo_method] = :delete
options[:title] = "Switch '#{service.name}' service OFF"

Expand All @@ -90,7 +94,7 @@ def switch_button(service)
].join("\n")
end
else
target_url = admin_facility_services_path(facility_id: facility.id, service_id: service.id)
target_url = switch_service_url(service, :post)
options[:data][:turbo_method] = :post
options[:title] = "Switch '#{service.name}' service ON"
end
Expand All @@ -100,11 +104,19 @@ def switch_button(service)
end
end

def switch_service_url(service, method)
if method == :delete
admin_facility_service_path(facility_id: facility.id, service_id: service.id)
else
admin_facility_services_path(facility_id: facility.id, service_id: service.id)
end
end

def show_notes_button(service)
return if facility_service_for(service).blank?

button_data = { modal_id: note_modal_id(service) }
tag.with_button class: "button is-white show_notes_button is-pulled-right", title: 'Show/Edit Notes', data: button_data do
tag.with_button class: "button is-white show_notes_button is-pulled-right", title: "Show/Edit Notes", data: button_data do
tag.span class: "icon" do
tag.i class: "fas fa-edit"
end
Expand Down Expand Up @@ -148,15 +160,12 @@ def switch_button(customer)
customer_value = customer_value_for(customer)

if welcomes?(customer_value)
target_url = admin_facility_welcome_path(id: facility_welcome_for(customer),
customer: customer_value,
facility_id: facility.id)
target_url = switch_welcome_url(customer, :delete)
options[:data] = { confirm: "Are you sure you want to turn off welcome '#{customer_value}' for this facility?",
turbo_method: :delete }
options[:title] = "Switch OFF"
else
target_url = admin_facility_welcomes_path(facility_id: facility.id,
customer: customer_value)
target_url = switch_welcome_url(customer, :post)
options[:data] = { turbo_method: :post }
options[:title] = "Switch ON"
end
Expand All @@ -166,6 +175,18 @@ def switch_button(customer)
end
end

def switch_welcome_url(customer, method)
customer_value = customer_value_for(customer)
if method == :delete
admin_facility_welcome_path(id: facility_welcome_for(customer),
customer: customer_value,
facility_id: facility.id)
else
admin_facility_welcomes_path(facility_id: facility.id,
customer: customer_value)
end
end

def welcomes?(customer)
facility.facility_welcomes.exists?(customer: customer_value_for(customer))
end
Expand Down Expand Up @@ -201,8 +222,7 @@ def switch_button(schedule)

if schedule.new_record?
# Create a new Schedule
target_url = admin_facility_schedules_path(facility_id: facility.id,
schedule: schedule_params)
target_url = switch_schedule_url(schedule, :create)

options[:data][:turbo_method] = :post
options[:title] = "Switch to Open"
Expand All @@ -211,7 +231,7 @@ def switch_button(schedule)
# Schedule is closed_all_day. Update it to open_all_day
schedule_params[:closed_all_day] = false
schedule_params[:open_all_day] = true
options[:title] = "Switch to Open"
options[:title] = "Switch to Open"
else
# Schedule is open_all_day or set_times. Update it to closed_all_day
schedule_params[:closed_all_day] = true
Expand All @@ -227,9 +247,7 @@ def switch_button(schedule)
options[:title] = "Switch to Closed"
end

target_url = admin_facility_schedule_path(facility_id: facility.id,
id: schedule.id,
schedule: schedule_params)
target_url = switch_schedule_url(schedule, :update, schedule_params)
options[:data][:turbo_method] = :put
end

Expand All @@ -238,6 +256,18 @@ def switch_button(schedule)
end
end

def switch_schedule_url(schedule, action, schedule_params = nil)
case action
when :create
admin_facility_schedules_path(facility_id: facility.id,
schedule: { week_day: schedule.week_day, closed_all_day: false, open_all_day: true })
when :update
admin_facility_schedule_path(facility_id: facility.id,
id: schedule.id,
schedule: schedule_params)
end
end

def full_schedule
return to_enum(:full_schedule) unless block_given?

Expand Down Expand Up @@ -266,37 +296,49 @@ def schedules
end

def link_to_add_time_slot(schedule)
action = new_admin_facility_time_slot_path(facility_id: facility.id, schedule_id: schedule.id)
action = add_time_slot_url(schedule)

link_to action, class: "button is-pulled-right is-white", title: "Add open time slot" do
icon_element("fa-plus-square")
end
end

def add_time_slot_url(schedule)
new_admin_facility_time_slot_path(facility_id: facility.id, schedule_id: schedule.id)
end

def link_to_edit(schedule)
action = if schedule.new_record?
new_admin_facility_schedule_path(facility_id: facility.id)
else
edit_admin_facility_schedule_path(id: schedule.id, facility_id: facility.id)
end
action = edit_schedule_url(schedule)

link_to action, class: "button is-pulled-right is-white" do
icon_element("fa-edit")
end
end

def edit_schedule_url(schedule)
if schedule.new_record?
new_admin_facility_schedule_path(facility_id: facility.id)
else
edit_admin_facility_schedule_path(id: schedule.id, facility_id: facility.id)
end
end

def link_to_destroy(time_slot)
schedule_id = time_slot.facility_schedule.id

action = admin_facility_time_slot_path(facility_id: facility.id,
schedule_id: schedule_id,
id: time_slot.id)
action = destroy_time_slot_url(time_slot, schedule_id)

link_to action, class: "button is-pulled-right is-white", data: { turbo_method: :delete } do
icon_element("fa-trash")
end
end

def destroy_time_slot_url(time_slot, schedule_id)
admin_facility_time_slot_path(facility_id: facility.id,
schedule_id: schedule_id,
id: time_slot.id)
end

def icon_for(_schedule)
icon_class = "fa-plus-square"

Expand Down
2 changes: 1 addition & 1 deletion app/components/locations/embed_map_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def render?
end

def call
tag.iframe(**options.merge(src: embed_map_url))
tag.iframe(**options, src: embed_map_url)
end

private
Expand Down
2 changes: 2 additions & 0 deletions app/components/notices/table_component.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

class Notices::TableComponent < ViewComponent::Base
attr_reader :notices

Expand Down
6 changes: 3 additions & 3 deletions app/components/shared/card_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ def initialize(title:, path: nil, method: :get, icon_class: "fa-pen", data: nil)
end

def render?
@title.present? #&& @path.present?
@title.present?
end

def call
params = { class: "button" }
if @method.present? && @method != :get
params[:data] = @data.to_h.merge(turbo_method: @method)
else
params[:data] = @data if @data.present?
elsif @data.present?
params[:data] = @data
end

return tag.span(button_content, **params) if @path.blank?
Expand Down
Loading
Loading