hoang-phan

ai-worker-ui

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.

hoang-phan 0 Updated 4d ago
GitHub

Install

npx skillscat add hoang-phan/ai-worker/ai-worker-ui

Install via the SkillsCat registry.

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_syncs and bugsnag_syncs (no index/show; each has a member run), and workflows (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. stages nest under a workflow (new/create/edit/update/destroy only). Top-level: resources :prompt_templates, singular resource :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. show is 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 / start and 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. Only development and runbook workflows are created here (pr_review ones 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) enqueue WorkflowSchedulerJob so the scheduler doesn't wait for the next cron tick. show renders the workflow's details, stages (runbooks also get Add/Edit/Remove stage and Run) and the full StageRun history (flattened across stages, newest first) — the only observability screen; there is no StageRuns controller.
  • app/controllers/stages_controller.rb + app/views/stages/{new,edit,_form}.html.erb — per-workflow stage editing. Adding and removing is runbook-only (runbook_step stages; 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 a run action 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 lists PromptTemplate::PLACEHOLDERS as 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 through AiCli::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 by controllers/index.js via eagerLoadControllersFrom) — inserts /skill-name at the cursor of the textarea marked data-skill-insert-target="input"; the surrounding form card carries data-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/update re-render :new/:edit with status: :unprocessable_entity on failure, destroy redirects with a flash notice, forms are form_with model: partials shared between new/edit.
  • Controllers stay thin. State changes beyond CRUD (start, resume, advance, rollback, run) check preconditions and redirect with a flash alert when they don't hold, and do the work through model methods (advance!, start_runbook!, resume_status) or by calling a service's blockers / 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 run RAILS_ENV=test bundle exec rspec. Never run scratch scripts, bin/rails runner or 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.

Categories