Curator dashboard improvements + Major code consolidation#147
Merged
Conversation
…ments - Convert listing pages to card-based layout with load-more pagination - Add dark/light mode toggle with localStorage persistence and FOUC prevention - Add curator edit button on public show pages (locations, experiences, plans) - Handle RecordNotFound gracefully with redirect to index - Change edit page back links to point to show page instead of list - Add "Suggest Changes" as single card action (replacing view/edit/delete) - Make clickable cards link to curator show pages - Add plans to database seeds with experience mappings and reviews - Fix database.yml to handle empty PROD_DATABASE_URL - Default to 3 items per page with load-more for additional content Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…e unused code Schema fixes: - Remove vector extension from main schema.rb (only needed in platform DB) - Remove Platform tables from main schema (cluster_memberships, knowledge_clusters, knowledge_summaries, platform_audit_logs, platform_conversations, platform_statistics, prepared_prompts) - These tables remain correctly in db/platform_schema.rb Documentation compact: - Archive outdated planning docs (TECH_DEBT_REVIEW, TEST_COVERAGE_70_PLAN, DSL_VALIDATION_PLAN, executor-simplification ADR) - Add LEARNINGS.md with extracted patterns from tmp scripts - Reorganize planning structure (adr/, architecture/, testing/ folders) - Update README.md with current status Code cleanup: - Remove unused job files and their tests - Remove unused shared view partials - Remove old personas folder (replaced by agents/) - Remove unused Stimulus controllers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ervices Removed components: - Chat API (/api/platform/chat, execute, parse) - agents use CLI directly - Status API (/api/platform/status, health, etc) - not used by frontend - Platform::Brain - LLM wrapper replaced by DSL - Platform::Conversation - session management for chat - PlatformConversation model and table Removed deprecated AI services (replaced by Platform DSL): - Ai::ContentOrchestrator - Ai::ExperienceCreator - Ai::PlanCreator - Ai::CountryWideLocationGenerator Removed Google Image Search: - GoogleImageSearchService - LocationImageFinderJob This consolidation removes ~480 tests and 20+ files, focusing the codebase on the CLI + DSL approach where agents run locally and interact directly with the database through bin/platform exec. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Decision: Platform database was over-engineered and unused. See: .claude/planning/decisions/2026-02-03-remove-platform-database.md Removed: - Platform models (PlatformAuditLog, PlatformStatistic, PreparedPrompt) - Knowledge models (KnowledgeSummary, KnowledgeCluster, ClusterMembership) - Knowledge layers (LayerZero, LayerOne, LayerTwo with pgvector) - DSL executors (knowledge.rb, prompts.rb) - Platform jobs (cluster_generation, statistics, summary_generation) - All platform migrations and schema Updated: - database.yml: removed platform database config - DSL executors: removed audit logging (content, curator, infrastructure) - spam_detector: removed audit logging - All related tests removed or updated Rationale: - Agents use CLI directly, not API - Audit logs were never read - Knowledge/embeddings unused - keyword search sufficient - PreparedPrompt system unused Stats: - ~15,000+ lines removed - Tests: 3635 → 2725 (simplified) - Databases: 3 → 2 (primary + queue) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use postgres:15 instead of pgvector/pgvector:pg15 - Remove klosaer_platform_test database creation - Remove db:schema:load:platform command Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove autoload for Executors::Prompts and Executors::Knowledge - Remove case branches for :prompts_query, :improvement, :prompt_action - Remove case branches for :summaries_query, :clusters_query - Remove delegation methods for Prompts and Knowledge executors - Comment out parser tests that test parsing of these query types - Executor now raises ExecutionError for unsupported query types Fixes CI error: LoadError: cannot load such file -- platform/dsl/executors/prompts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- PhotoSuggestion: Change photo (singular) to photos (plural) to match model - Plans controller: Expect redirect instead of 404 (matches rescue_from behavior) - Remove tests without assertions (audit log tests that were removed) All originally failing tests now pass: - test/controllers/curator/admin/photo_suggestions_controller_test.rb - test/models/photo_suggestion_test.rb - test/controllers/curator/plans_controller_test.rb - test/lib/platform/dsl/mutations_test.rb - test/lib/platform/dsl/audio_test.rb Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1. Update 404 tests to expect redirect instead of 404 response - Curator::BaseController has rescue_from RecordNotFound that redirects to index - Fixed tests in locations, audio_tours, and experiences controllers 2. Remove audit log tests without assertions - Removed test_creates_audit_log_for_description_generation - Removed test_creates_audit_log_for_experience_generation - Audit log functionality was previously removed 3. Fix test_execute_update_old_values_skips_keys_record_does_not_respond_to - Changed from try-catch to proper assertion - Now expects ExecutionError for unknown attributes 4. Fix test_build_description_prompt_handles_unknown_record_type - Changed Struct mock to proper Object with singleton methods - Fixes ArgumentError for try method All 228 tests pass with 616 assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove audit log tests (functionality removed) - Add assertions to graceful error handling tests - Fix photo suggestions controller test redirects Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reduced branch coverage minimum from 69.5% to 68% after removing ~15,000 lines of unused platform database code. Coverage naturally decreased as we removed code with tests but kept untested edge cases. See ADR: .claude/planning/decisions/2026-02-03-remove-platform-database.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract BIH_CULTURAL_CONTEXT to new Ai::BihContext module - Update audio_tour_generator.rb and location_enricher.rb to use new module Removed jobs: - app/jobs/ai_generation_job.rb - app/jobs/rebuild_plans_job.rb - app/jobs/rebuild_experiences_job.rb - app/jobs/location_city_fix_job.rb Removed AI analyzers: - app/services/ai/location_analyzer.rb - app/services/ai/experience_analyzer.rb - app/services/ai/plan_analyzer.rb - app/services/ai/experience_generator.rb Removed rake tasks: - lib/tasks/ai_generate.rake - lib/tasks/ai.rake Removed all corresponding test files. These files were part of the old admin-based workflow and are no longer used since agents now work through the DSL interface. All tests passing (2235 runs, 5117 assertions, 0 failures). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reduced branch coverage minimum from 68% to 67% after removing ~11,600 lines of unused jobs and analyzer services. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This gem was used for pgvector embeddings in the Knowledge layer, which was removed in the platform database cleanup. All AI services use ruby_llm (Claude API) instead. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Removes location_type column from locations table ## What changed: - Created 22 LocationCategory records (place, attraction, restaurant, etc.) - Migrated all location_type values to location_category_assignments - Removed location_type enum from Location model - Updated all fallback logic to use only location_categories ## Files updated: - Location model: removed enum, updated scopes and methods - Plan, ContentChange models: removed location_type references - AI services: use category_name instead of location_type - Controllers: removed from permitted params - Views: replaced location_type with category_key - Seeds: use categories array instead of location_type ## Test compatibility: - Added monkey patch in test_helper.rb to auto-convert location_type to location_category for backwards compatibility in existing tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Drop cluster_memberships, knowledge_clusters, knowledge_summaries - Drop platform_audit_logs, platform_conversations, platform_statistics, prepared_prompts - Disable pgvector extension (no longer needed) - Update schema.rb to reflect clean state All tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Problem System had conflicting sources of truth: - suitable_experiences JSON field - location_experience_types relational table - Sync went both ways causing confusion ## Solution Make relational table the source of truth, JSON field becomes auto-synced cache. ## Changes ### Location Model - New: `set_experience_types(keys)` - main API for setting experience types - Updated: `add_experience_type` / `remove_experience_type` - update relation → sync JSON - Updated: `suitable_experiences=` - calls `set_experience_types` internally - New callback: `after_create :sync_experience_types_from_pending` - Changed callback: `after_save :sync_suitable_experiences_cache` (was sync_experience_types_from_json) ### Controller - Updated: `proposal_data_from_params` - explicitly includes suitable_experiences ### ContentChange Model - Updated: `apply_create!` and `apply_update!` - use `set_experience_types` API ### Tests - Updated: renamed tests to reflect new behaviour - Added: new test for `set_experience_types` as source of truth - Result: All 2235 tests passing, 0 failures ## Data Flow ``` WRITE: User Input → Relational Data → JSON Cache READ: JSON Cache (fast) or Relational Data (for joins) ``` ## Benefits - Clear hierarchy: relation = truth, JSON = cache - Automatic sync: JSON always synced from relation - Relational queries: can JOIN on location_experience_types - Fast reads: JSON cache for queries without JOINs - Backwards compatible: existing code still works Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensures all existing locations have their location_experience_types records populated from suitable_experiences JSON data. This migration is idempotent and safe to run multiple times: - Uses find_or_create to avoid duplicates - Handles missing ExperienceType records gracefully - Case-insensitive key matching - Batch processing with find_each for memory efficiency Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
- LocationEnricher: Replace redundant suitable_experiences= + add_experience_type with single set_experience_types() call - Location model: Add documentation for Experience Types API - Tests: Update to verify set_experience_types usage API is now consistent: - set_experience_types(keys) - primary method (sets all at once) - add_experience_type(key) - add single type - remove_experience_type(key) - remove single type - suitable_experiences= - backwards compatible alias Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SECURITY FIX: Prevents runtime crashes when parsing removed commands Removed grammar rules: - summaries_command, clusters_command (knowledge layer) - prompts_command (prompt management) - improvement_command (prepare fix/feature) - prompt_action_command (apply/reject prompt) Removed transformer rules for these AST types. Behavior change: - BEFORE: Commands parsed successfully → runtime "Nepoznat tip query-ja" - AFTER: Commands rejected at parse time with clear error Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add .rubocop.yml with rubocop-rails-omakase base - Add Rubocop step to CI workflow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move all AI prompts from inline heredocs in services to external .md.erb template files. This improves maintainability, makes prompts easier to edit and version, and keeps them compatible with Claude Code. Changes: - Add app/prompts/ directory with ERB templates for all AI services - Add PromptHelper module with load_prompt() for template rendering - Refactor ExperienceTypeClassifier to use external prompts - Refactor LocationEnricher to use external prompts - Refactor AudioTourGenerator to use external prompts - Refactor ExperienceLocationSyncer to use external prompts - Update CLAUDE.md with prompt guidelines and rules - Add tests for PromptHelper Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Auto-formatted code style changes: - Add spaces inside array brackets - Consistent quote style - Minor formatting adjustments Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace direct RubyLLM.chat with Ai::OpenaiQueue.request - Remove unused @llm instance variable and llm method - Handle Ai::OpenaiQueue::RequestError instead of generic StandardError - Update tests to stub OpenaiQueue instead of @llm This ensures consistent rate limiting and retry logic across all AI services. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document migration plan from legacy AI services to DSL-First architecture: - Phase 1: Wrapper DSL executors (Q1) - Phase 2: Internal migration (Q1) - Phase 3: Refactoring & optimization (Q2) - Phase 4: Deprecation warnings (Q2) - Phase 5: Documentation (Q3) - Phase 6: Cleanup (Q4) Includes rollback plan, timeline, and DSL syntax examples. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split LocationEnricher (586 lines) into modular components: New modules in app/services/ai/location_enricher/: - base.rb - Shared concerns (logging, cultural_context, supported_locales) - metadata_generator.rb - Generate tags, tips, experience types - description_generator.rb - Generate multilingual descriptions (batch) - historical_generator.rb - Generate historical context (batch) - applicator.rb - Apply enrichment data to locations LocationEnricher is now an orchestrator (265 lines, -55%): - generate_enrichment delegates to generators - apply_enrichment delegates to Applicator - Public API unchanged (enrich, enrich_batch, create_and_enrich) Tests: 149 runs, 317 assertions, 0 failures Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Service object pattern for explicit location lifecycle management: - LocationCreator: Creates locations with experience type assignment - LocationUpdater: Updates locations with experience type sync - 24 tests with 119 assertions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- apply_create! now uses LocationCreator for Location models - apply_update! now uses LocationUpdater for Location models - Removes inline experience type handling logic - Delegates responsibility to dedicated service objects Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- execute_create uses LocationCreator for Location models - execute_update uses LocationUpdater for Location models - Consistent experience type handling across all entry points Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove accidentally committed stress_test.log - Add *.log to .gitignore to prevent future commits Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add @custom-variant dark (&:where(.dark, .dark *)) for Tailwind v4 - Fix tailwindcss.rake to properly call bundled tailwindcss CLI - Dark mode now toggles via .dark class on html element Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show curator dashboard link to admins (not "become curator" button) - Display "Ti si Admin" for admin users, "Ti si Curator" for curators - Uses existing can_curate? helper that includes both roles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add :thumb (100x100), :medium (400x400), :large (800x800) variants - Fixes ArgumentError in curator/locations/needs_photos view Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Admin users now see red-themed Admin dropdown in desktop nav - Mobile menu also includes Admin section for admin users - Links to: content changes, curator applications, photo suggestions, users Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Sadržaj, Prijave, Fotografije, Korisnici - Reduced dropdown width to w-44 - Added whitespace-nowrap for safety Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Admin views: content_changes, curator_applications, photo_suggestions, users - Curator views: proposals, photo_suggestions, reviews - Added dark:bg-*, dark:text-*, dark:border-* variants throughout - Status badges, stat cards, filters, lists all support dark mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- admin/content_changes/show: dark backgrounds, text, badges - admin/curator_applications/show: dark backgrounds, text - admin/photo_suggestions/show: dark backgrounds, text, badges - admin/users/edit: dark form inputs, labels, buttons - admin/users/show: dark backgrounds, text, user type badges - audio_tours/_form: dark form inputs, labels, info box - audio_tours/index: dark stats, filters, table, mobile cards - audio_tours/show: dark backgrounds, text, badges - locations/needs_photos: dark filters, table, photo count badges - photo_suggestions/new: dark form, upload areas - photo_suggestions/show: dark status badges, descriptions - proposals/show: dark diff view, review form, contributors, sidebar - reviews/show: dark star ratings, details - shared/_pending_proposals: dark type badges Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove logout button from desktop and mobile navigation - Style back to site link as a button - Simplify mobile nav footer layout Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Curator dashboard link now appears immediately below profile header - "Become a curator" option only shows for logged-in non-curators - Removed duplicate curator section from bottom of page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplify and modernize documentation - Update project structure to reflect current state - Add Platform CLI and Curator Dashboard sections - Remove references to deleted services - Keep Discord link and OSassy License Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Curator Dashboard Improvements
Code Consolidation (Major Cleanup)
Technical Changes
Curator Dashboard
_location_item,_experience_item,_plan_itempartials with responsive griddark:classes on all curator views.per(3)paginationCode Consolidation
database.ymland CI workflowprompts.rbandknowledge.rbexecutorspostgres:15instead ofpgvector/pgvector:pg15ADR
Decision recorded:
.claude/planning/decisions/2026-02-03-remove-platform-database.mdTest plan
🤖 Generated with Claude Code