Applies ai-worker's CRUD-screen discipline. Use for any task touching app/controllers/**, app/views/**, or config/routes.rb — the Projects, Workflows (including runbooks and their Stages), PromptTemplates, Jira/Bugsnag syncs and Settings screens.
Instal·la
npx skillscat add hoang-phan/ai-worker/ai-worker-ui Instal·la des del registre de SkillsCat.
SKILL.md
ai-worker-ui
Scope: app/controllers/**, app/views/**, config/routes.rb. Read app/models/*.rb only for attribute/validation/enum names when building forms — do not modify models here (that's ai-worker-domain's scope) and do not touch app/jobs/app/services (that's ai-worker-orchestration's scope).
File map (the whole scope)
config/routes.rb—resources :projects(plus member actions to trigger a Slack sync and a brainstorm run) nests:jira_syncsandbugsnag_syncs(no index/show; each has a memberrun), andworkflows(no index) with member actions for start, run a runbook stage, clone, advance (Next), resume an errored workflow, roll back to review, and delete an image.stagesnest under a workflow (new/create/edit/update/destroy only). Top-level:resources :prompt_templates, singularresource :settings(show/update),root "projects#index". Sidekiq Web is mounted at/sidekiq, plus the health check.app/controllers/projects_controller.rb+app/views/projects/{index,show,new,edit,_form}.html.erb— Project CRUD.showis the project's dashboard: its workflows (with current stage and PR link, plus Start/Edit actions and a New runbook button) and one section each for Jira syncs, Bugsnag triage, Brainstorm and Slack PR reviews, each with a "run now" button. The form groups the per-project settings (kind, defaults, Jira, Slack, UAT, local test, brainstorm). The two password fields are never pre-filled and a blank submission keeps the saved value. The sync and brainstorm member actions only call the services'blockers/startand redirect with a flash; the jobs do the importing.app/controllers/workflows_controller.rb+app/views/workflows/{show,new,edit,_form}.html.erb— Workflow CRUD, always nested under a project. Onlydevelopmentandrunbookworkflows are created here (pr_reviewones come from the Slack sync). The form varies by kind (Jira ticket fields, personal task text, runbook variables and "copy stages from"), accepts reference image uploads, and shows skill hint chips. The custom member actions are small state transitions guarded by status/kind checks that redirect with a notice or alert; Run stage (and Next, when the runbook is in auto-run) enqueueWorkflowSchedulerJobso the scheduler doesn't wait for the next cron tick.showrenders the workflow's details, stages (runbooks also get Add/Edit/Remove stage and Run) and the fullStageRunhistory (flattened across stages, newest first) — the only observability screen; there is noStageRunscontroller.app/controllers/stages_controller.rb+app/views/stages/{new,edit,_form}.html.erb— per-workflow stage editing. Adding and removing is runbook-only (runbook_stepstages; the current stage can't be removed); editing is allowed on any workflow's stage, where runbooks also expose name/run mode/channel/position/auto-advance/wait-for-workflow and every stage can pick a prompt template or write its own prompt. The form has inline JS that previews the template with the workflow's placeholder values.app/controllers/jira_syncs_controller.rb+app/views/jira_syncs/{new,edit,_form}.html.erb,app/controllers/bugsnag_syncs_controller.rb+app/views/bugsnag_syncs/{new,edit,_form}.html.erb— CRUD for a project's sync definitions (no index/show; the project page lists them) and arunaction that starts the matching service and reports why it was blocked.app/controllers/prompt_templates_controller.rb+app/views/prompt_templates/{index,show,new,edit,_form}.html.erb— Prompt Template CRUD. The form listsPromptTemplate::PLACEHOLDERSas a cheatsheet next to the body textarea.app/controllers/settings_controller.rb+app/views/settings/show.html.erb— the single app-wide setting: which agent CLI runs (read and written throughAiCli::Runner, not a model). Invalid names re-render with an error.app/controllers/application_controller.rb,app/helpers/application_helper.rb,app/views/layouts/application.html.erb,app/views/shared/_skill_hints.html.erb— layout with nav (Projects, Prompt templates, Settings) and flash display; the helper lists the skill directories under the project's<local_directory>/.agents/skills, and the partial renders them as clickable chips.app/javascript/controllers/skill_insert_controller.js(Stimulus, auto-registered bycontrollers/index.jsviaeagerLoadControllersFrom) — inserts/skill-nameat the cursor of the textarea markeddata-skill-insert-target="input"; the surrounding form card carriesdata-controller="skill-insert". Used by the project defaults and the workflow task/skills fields.app/views/pwa/,app/assets/— Rails PWA defaults, images and stylesheets; no per-screen JS besides the above.
Conventions
- These are plain Rails server-rendered CRUD controllers — no admin gem, no API-only mode, no JS framework beyond Turbo/Stimulus via importmap. Keep that:
create/updatere-render:new/:editwithstatus: :unprocessable_entityon failure,destroyredirects with a flashnotice, forms areform_with model:partials shared betweennew/edit. - Controllers stay thin. State changes beyond CRUD (start, resume, advance, rollback, run) check preconditions and redirect with a flash
alertwhen they don't hold, and do the work through model methods (advance!,start_runbook!,resume_status) or by calling a service'sblockers/start. Don't put scheduler or agent logic in a controller, and don't run an agent or git command from a request. - Enum-backed selects use the model's own keys (
PromptTemplate.stage_types.keys,Project.kinds.keys,Stage.run_modes.keys) — never hardcode the value list in a view. Enum-dependent UI branches (workflow.runbook?,project.personal?) use the predicate methods. - System-set fields are not editable from forms and not in strong params:
github_pr_url(set by the implementation run, or by the Slack sync for review workflows),status,kind(the workflow controller derives it from a param limited to development/runbook), the agent run-tracking columns,current_stage_id. Don't add a field for them. - Secrets (
uat_password,local_password) are never rendered back into a form; a blank value means "keep". - Each user-facing action that triggers an agent run gives a flash explaining what happens next and where the result will show. Keep that wording tied to the real behaviour (e.g. results are imported by the next job tick).
- Test with RSpec, not scratch runners: add request/controller or model specs under
spec/and runRAILS_ENV=test bundle exec rspec. Never run scratch scripts,bin/rails runneror console code against the development DB, and never click through a running dev server's destructive buttons (Delete, Start, Run) on real projects to "verify" a change.