CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 25s
CI & Build / integration (push) Successful in 35s
CI & Build / Python tests (push) Successful in 1m2s
CI & Build / Build & push image (push) Successful in 44s
Rule #27 — the backend half shipped without a surface an operator can touch, so this is the other half of #2349. StarterRolePicker is a component rather than inline markup because DesignSystemsView has TWO creation forms: the empty state is a sibling branch of the body, not a parent, so a form written into one is unreachable from the other. Inlining the checklist would have made it the next thing in this codebase defined twice and free to drift — which is what the button migration spent nine commits undoing. What it offers is names and purposes, never values. "Named now, valued later": a role you haven't filled shows as to-be-decided, while a role that doesn't exist is what gets written as a literal instead. Every group unchecks individually, and the prefix is editable because `--fs-` is one family's convention, not the product's. Three deliberate details: - All groups checked by DEFAULT, and that default lives in the UI, not the service. create_design_system treats None and [] alike (seed nothing) so it can never write 40 rows into a system whose caller never asked; a UI default is visible and reversible before the click. Different layers, different safe answers. - A failed catalogue fetch is NOT fatal and does not read as an error. Starter roles are an accelerator, not a prerequisite — the form still creates, and the operator adds tokens by hand. - The refs are not cleared after a successful create. The picker owns them and re-seeds on mount; resetting here would race that and silently create the next system with no roles. props + defineEmits rather than defineModel, matching TagInput and the rest of components/. defineModel is available (Vue 3.5) and would be shorter, but being the only file in the codebase using a different binding idiom costs more than the lines it saves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs