|
| 1 | +--- |
| 2 | +name: ui-refactor-review |
| 3 | +description: >- |
| 4 | + Review ui/goose2 frontend changes specifically for refactoring opportunities |
| 5 | + and long-term maintainability. Use when the user wants cleanup feedback or |
| 6 | + wants to improve structure, decomposition, layering, type hygiene, |
| 7 | + duplication, dead code, readability, and extensibility in goose2 React + |
| 8 | + TypeScript + Tauri UI code. |
| 9 | +--- |
| 10 | + |
| 11 | +# UI Refactor Quality |
| 12 | + |
| 13 | +Use this skill for `ui/goose2` pull requests. |
| 14 | + |
| 15 | +Keep the focus on behavior-preserving frontend improvement. Favor the repo's |
| 16 | +existing architecture and patterns over generic frontend advice. |
| 17 | + |
| 18 | +## Goals |
| 19 | + |
| 20 | +- Review changed code for refactor quality, not just correctness. |
| 21 | +- Bias toward detecting maintainability smells even when the code is still functionally correct. |
| 22 | +- Review the final shape of the changed code, not whether it is better than what came before. |
| 23 | +- Judge changes by whether they leave the code easier to maintain and extend in future work, not just whether they are correct today. |
| 24 | +- Produce an actionable checklist instead of vague feedback. |
| 25 | +- Ask for approval before making code changes unless the user explicitly asks for fixes. |
| 26 | +- Preserve `ui/goose2` boundaries: `ui/`, `hooks/`, `api/`, `lib/`, `stores/`, and `shared/`. |
| 27 | + |
| 28 | +## Workflow |
| 29 | + |
| 30 | +1. Determine the review scope. |
| 31 | + - Review only the changed lines in the branch or working tree. |
| 32 | + - If both committed and uncommitted changes exist, clarify which scope to review when needed. |
| 33 | + - If the change mixes feature work with refactoring, call that out explicitly and review the feature changes separately from the cleanup quality. |
| 34 | +2. Inspect only the changed lines in that scope, but follow each changed code path into surrounding modules when needed to judge whether the shape is clean. |
| 35 | +3. Run the `Smell Checklist` below before looking for bugs. |
| 36 | + - Do not require a user-visible bug before calling out a maintainability problem. |
| 37 | + - Prefer concrete findings like "this responsibility is misplaced" or "this logic should be extracted" over generic style commentary. |
| 38 | + - If a Smell Checklist item is true, turn it into an `Issue`. |
| 39 | + - Do not leave a confirmed smell unaccounted for in the final review. |
| 40 | + - Do not suppress an `Issue` because the PR already improved the previous version. |
| 41 | + - Do not treat partial cleanup as resolution. A smell that remains in the post-PR code is still an `Issue`. |
| 42 | +4. Evaluate the changed code against the `Rules` below and identify what the PR already improved and what should still be refactored or cleaned up. |
| 43 | +5. Review the changed code separately for these buckets: |
| 44 | + - decomposition |
| 45 | + - layering |
| 46 | + - hooks/effects |
| 47 | + - pure helpers |
| 48 | + - type shapes |
| 49 | + - duplication |
| 50 | + - tests |
| 51 | + - feature wiring |
| 52 | + - For each bucket, explicitly determine whether zero, one, or multiple `Issues` remain. |
| 53 | + - If any remain, report all distinct `Issues` you can verify in that bucket. |
| 54 | +6. Verify each non-trivial issue against the actual code before turning it into a task. |
| 55 | + - Trace the relevant code path end to end. |
| 56 | + - Check whether the issue is already handled elsewhere. |
| 57 | + - Confirm the suggested cleanup would actually simplify the code. |
| 58 | + - Keep the finding if the maintainability problem is real, local, and behavior-preserving to fix, even when the code still works. |
| 59 | + - Drop speculative or preference-only findings. |
| 60 | +7. Before finalizing the review, run a second pass focused only on finding issues not already listed. |
| 61 | + - Discover issues before prioritizing them. |
| 62 | + - Do not stop after the first few findings. |
| 63 | + - Do not omit a verified issue because it is lower priority than other findings. |
| 64 | +8. Produce review output in this order: |
| 65 | + - `Applied Well` |
| 66 | + - `Issues` |
| 67 | + - one ordered `Checklist` for the whole reviewed scope |
| 68 | + - Do not stop after the findings until the ordered checklist is complete. |
| 69 | +9. Stop after the checklist and ask for approval before making code changes, unless the user explicitly asked to implement fixes. |
| 70 | +10. Fix approved checklist items in order, using the `Rules` below as the quality bar for the implementation. |
| 71 | + - State the main maintainability problem in one sentence. |
| 72 | + - Fix the highest-value items first. |
| 73 | + - Make the smallest behavior-preserving change that clearly improves the code. |
| 74 | +11. Summarize what changed, what remains, and what verification ran. |
| 75 | + |
| 76 | +## Strict Mode |
| 77 | + |
| 78 | +- Any confirmed smell in the changed code must be reported as an `Issue`. |
| 79 | +- Review the post-PR shape. Do not grade on a curve. |
| 80 | +- Partial extraction, partial deduplication, or partial cleanup does not clear a remaining smell. |
| 81 | +- If multiple distinct smells remain in one file, report each distinct responsibility problem separately. |
| 82 | + |
| 83 | +## Smell Checklist |
| 84 | + |
| 85 | +Before finalizing the review, explicitly ask: |
| 86 | + |
| 87 | +- Is any view or page component still doing too many jobs? |
| 88 | +- Is any pure derivation logic still trapped in a component instead of `lib/`? |
| 89 | +- Is any repeated async UI workflow ready for a focused hook? |
| 90 | +- Are helpers duplicated or living in the wrong layer? |
| 91 | +- Are any inline object shapes large enough to deserve a named type? |
| 92 | +- Did logic move without moving or adding the right tests? |
| 93 | +- Did the refactor preserve feature wiring while improving structure? |
| 94 | + |
| 95 | +## Rules |
| 96 | + |
| 97 | +### Size And Decomposition |
| 98 | + |
| 99 | +- Treat these as smell thresholds, not hard limits: |
| 100 | + - components around 200 lines |
| 101 | + - functions around 40 lines |
| 102 | + - files around 300 lines |
| 103 | + - JSX nesting around 4 levels |
| 104 | +- Treat "many unrelated state variables + many handlers + many effects in one view" as a smell even when the line count is still tolerated. |
| 105 | +- Treat a file that owns multiple unrelated responsibilities across data loading, derivation, mutation, and rendering orchestration as a smell unless there is a strong reason to keep it together. |
| 106 | +- If a component does more than its name claims, rename it or split it. |
| 107 | +- Split by responsibility, not by arbitrary line count. |
| 108 | +- When a view contains substantial pure derivation logic, prefer extracting it into `lib/` helpers with direct tests. |
| 109 | +- When a view contains substantial effectful workflow logic, prefer extracting it into a focused hook. |
| 110 | +- Do not suppress a decomposition `Issue` just because the PR already extracted some responsibilities. |
| 111 | +- If the remaining file still does too many jobs, report that as an `Issue`. |
| 112 | +- File size alone is not the finding. The finding is the number of unrelated responsibilities still owned by the final file. |
| 113 | + |
| 114 | +### Naming Reveals Intent |
| 115 | + |
| 116 | +- Use names that describe intent, not implementation trivia. |
| 117 | +- Prefer domain terms over generic placeholders like `data`, `value`, or `handler`. |
| 118 | +- A helper name should describe what it returns or decides, not how it computes it. |
| 119 | +- Rename misleading functions before adding comments to explain them. |
| 120 | + |
| 121 | +### Layer Discipline |
| 122 | + |
| 123 | +- `ui/`: rendering and light view logic only. |
| 124 | +- `hooks/`: glue between React state/effects and lower layers. |
| 125 | +- `api/`: backend transport wrappers and DTO adaptation only. |
| 126 | +- `lib/`: pure functions and domain helpers only. |
| 127 | +- `stores/`: shared feature state only. |
| 128 | +- Keep business logic out of render-heavy components when a hook or utility would make it clearer. |
| 129 | +- If a component mixes pure transforms and UI event orchestration, split the pure transforms out first. |
| 130 | +- Do not move simple local state into a store unless multiple consumers truly need it. |
| 131 | +- Keep `api/` free of UI imports, path logic, and unrelated domain policy. |
| 132 | +- Keep `lib/` free of React, DOM, `window`, and I/O. |
| 133 | +- Prefer shared domain helpers in `lib/` when the same normalization, formatting, or parsing logic appears in multiple modules. |
| 134 | +- If logic lives in the wrong layer after the PR, report that as an `Issue` even if the PR reduced the amount of misplaced logic. |
| 135 | + |
| 136 | +### Module Encapsulation |
| 137 | + |
| 138 | +- Export the minimum surface a module needs to share. |
| 139 | +- Keep helpers, constants, and intermediate transforms private unless another module genuinely needs them. |
| 140 | +- Treat removing stale exports as a quality improvement. |
| 141 | +- If a helper is used in only one module, default to keeping it local. |
| 142 | +- If similar helpers appear across two modules, default to extracting them. |
| 143 | + |
| 144 | +### DRY And Hooks |
| 145 | + |
| 146 | +- Extract shared behavior once the duplication is clear and the shared abstraction is stable. |
| 147 | +- Two call sites can be enough when the shared shape is obvious and both call sites become simpler. |
| 148 | +- Prefer a hook when the shared logic is stateful or effectful. |
| 149 | +- Keep each hook focused on one job. |
| 150 | +- Keep hook return shapes stable so callers are not forced to handle shifting contracts. |
| 151 | +- Do not use a hook as the default extraction target for oversized components. |
| 152 | +- If the logic is pure and React-independent, report extraction to `lib/`. |
| 153 | +- If the logic coordinates React state, effects, async actions, or UI event orchestration, report extraction to `hooks/`. |
| 154 | +- Treat repeated pure UI derivation logic as helper extraction candidates. |
| 155 | +- If repeated effectful orchestration remains in the changed code, report that as an `Issue`. |
| 156 | +- If repeated pure transforms remain in the changed code, report that as an `Issue`. |
| 157 | + |
| 158 | +### Type Hygiene |
| 159 | + |
| 160 | +- Keep canonical cross-feature types in `src/shared/types/`. |
| 161 | +- Do not duplicate types across features when one shared type should exist. |
| 162 | +- Give inline object types with 3 or more fields a name when they start obscuring the code. |
| 163 | +- Prefer `Pick`, `Omit`, and `Partial` over restating shapes by hand. |
| 164 | +- Avoid `any`, unchecked `as`, non-null assertions, and string-encoded pseudo-unions when a discriminated union would be clearer. |
| 165 | +- Treat repeated or verbose inline object shapes as extraction candidates for named types. |
| 166 | +- If verbose or repeated inline shapes remain after the PR, report that as an `Issue`. |
| 167 | + |
| 168 | +### React And UI |
| 169 | + |
| 170 | +- Prefer straight-line render logic, guard clauses, and early returns over deep nesting. |
| 171 | +- Prefer controlled components where practical. |
| 172 | +- Use semantic HTML like `<main>`, `<nav>`, `<header>`, and `<aside>`. |
| 173 | +- Prefer existing shared UI button primitives over plain `<button>` elements. |
| 174 | +- Treat new plain `<button>` usage as a refactor smell unless there is a specific semantic or integration reason. |
| 175 | +- If a plain `<button>` is genuinely necessary, it must use `type="button"` in goose2. |
| 176 | +- Use `cn()` from `@/shared/lib/cn` for Tailwind class merging. |
| 177 | +- Prefer existing shared UI primitives before creating new one-off markup patterns. |
| 178 | +- Avoid inline styles except for truly dynamic values. |
| 179 | +- Respect reduced-motion behavior when touching animation. |
| 180 | + |
| 181 | +### Notifications, Localization, And Accessibility |
| 182 | + |
| 183 | +- Route success and error feedback through the app's shared notification primitive. |
| 184 | +- Route user-facing Goose UI copy through `react-i18next` in already-migrated surfaces. |
| 185 | +- Prefer stable translation keys over inline English strings. |
| 186 | +- Avoid raw user-facing strings inside `catch` blocks. |
| 187 | +- Add text alternatives for icon-only or color-only affordances. |
| 188 | +- Keep interactive semantics explicit with labels, roles, and selected state where applicable. |
| 189 | + |
| 190 | +### Tauri And Backend Boundaries |
| 191 | + |
| 192 | +- Frontend-to-core communication goes through `SDK -> ACP -> goose`. |
| 193 | +- Do not add ad hoc `fetch()` calls for goose core behavior. |
| 194 | +- Do not add `invoke()` calls as proxies to goose core behavior; reserve them for desktop-shell concerns. |
| 195 | +- Do not call ACP clients directly from UI components; keep backend access in `shared/api/` or `features/*/api/`. |
| 196 | + |
| 197 | +### Errors, State Drift, And Dead Code |
| 198 | + |
| 199 | +- Handle errors explicitly and close to the source. |
| 200 | +- Keep the happy path easy to see. |
| 201 | +- In async UI flows, keep local state, persisted state, and backend-confirmed state from drifting apart. |
| 202 | +- Delete unused exports, imports, parameters, fields, and commented-out code. |
| 203 | +- Remove tests that only protect deleted internals rather than user-visible behavior. |
| 204 | +- When logic moves across modules, expect coverage to move with it rather than disappear. |
| 205 | +- Treat coverage loss in refactors as suspicious unless the behavior was intentionally removed. |
| 206 | +- If behavior-preserving logic moved but coverage did not move with it, report that as an `Issue`. |
| 207 | +- Report redundant props, fields, parameters, and intermediate values as `Issues`. |
| 208 | + |
| 209 | +## Review Output |
| 210 | + |
| 211 | +### Applied Well |
| 212 | + |
| 213 | +- List what the PR already improved. |
| 214 | +- Use concrete examples with file references. |
| 215 | +- Skip generic praise. |
| 216 | + |
| 217 | +### Issues |
| 218 | + |
| 219 | +- List only issues that are actually in scope for the changed code. |
| 220 | +- For each issue, explain: |
| 221 | + - what is wrong |
| 222 | + - why it matters |
| 223 | + - the smallest change that would improve it |
| 224 | +- Only include issues that survived a verification pass against the actual code. |
| 225 | + |
| 226 | +### Checklist |
| 227 | + |
| 228 | +- End with one ordered actionable checklist for the whole reviewed scope. |
| 229 | +- Do not create a separate checklist per issue. |
| 230 | +- Each item should be specific enough to implement directly. |
| 231 | +- Each item should be small enough to fix as one unit. |
| 232 | +- If an item would require sub-steps, split it into multiple checklist items instead of nesting. |
| 233 | +- Treat `Checklist` as the complete fix inventory for the reviewed scope. |
| 234 | +- Do not defer concrete fix items from `Checklist` into later sections. |
| 235 | +- Each checklist item must describe a concrete code change, not a high-level goal. |
| 236 | +- A user should be able to implement the fix directly from the `Checklist`. |
| 237 | +- Order the checklist by implementation sequence: |
| 238 | + - boundary and layering issues first |
| 239 | + - naming and decomposition next |
| 240 | + - type and hook cleanup after that |
| 241 | + - dead code and polish last |
| 242 | + |
| 243 | +## Done Criteria |
| 244 | + |
| 245 | +- No unresolved in-scope boundary violations remain. |
| 246 | +- The code is clearer without changing intended behavior. |
| 247 | +- No new dead code or needless exports were introduced. |
| 248 | +- Naming and decomposition are improved where the review identified them. |
| 249 | +- Review findings were verified before being turned into fix tasks. |
| 250 | +- Verification was run when appropriate, or explicitly called out if not run. |
0 commit comments