@fui-org/fui-cli 1.3.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +21 -3
  2. package/dist/fui-cx180e19.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +3 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/skills/fui-target/.claude-plugin/plugin.json +6 -0
  63. package/skills/fui-target/hooks/hooks.json +1 -0
  64. package/skills/fui-target/hooks/register.tsx +71 -0
  65. package/skills/fui-target/types/index.d.ts +7 -0
  66. package/dist/fui-y8an39cn.js +0 -420
  67. package/skills/fui-skill/README.md +0 -112
  68. package/skills/fui-skill/metadata.json +0 -75
  69. package/skills/fui-skill-cli/SKILL.md +0 -139
  70. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  71. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  72. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  73. package/skills/fui-skill-cli/references/component-design.md +0 -448
  74. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  75. package/skills/fui-skill-cli/references/component-table.md +0 -248
  76. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  77. package/skills/fui-skill-cli/references/components-display.md +0 -141
  78. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  79. package/skills/fui-skill-cli/references/components-input.md +0 -335
  80. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  81. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  82. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  83. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  84. package/skills/fui-skill-cli/references/default-function.md +0 -425
  85. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  86. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  87. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  88. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  89. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  90. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  91. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  92. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  93. package/skills/fui-skill-cli/references/new-session.md +0 -85
  94. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  95. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  96. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  97. package/skills/fui-skill-cli/references/project-config.md +0 -303
  98. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  99. package/skills/fui-skill-cli/references/script-map.md +0 -262
  100. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  101. package/skills/fui-skill-cli/references/system-design.md +0 -89
  102. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  103. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  104. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  105. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  106. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  107. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  108. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  109. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  110. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  111. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  112. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  113. package/skills/fui-skill-cli/references/verification.md +0 -236
  114. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  115. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,246 +1,236 @@
1
- # FUI Definition-of-Done Checklists
2
-
3
- > File này sở hữu: **checklist definition-of-done trước khi publish (module.json, `.vue`, SP, deploy workflow)** và **ma trận chọn tầng kiểm chứng theo triệu chứng**.
4
-
5
- Use these checklists before publishing any artifact. Each item is a gate — a module/SP/component is not ready if any required item is unchecked.
6
-
7
- ---
8
-
9
- ## Chọn tầng kiểm chứng theo TRIỆU CHỨNG (đọc trước khi render)
10
-
11
- Năm tầng, chênh nhau khoảng **hai bậc** về chi phí mỗi lượt:
12
-
13
- | Tầng | Lệnh | Chi phí | Thấy được gì |
14
- |---|---|---|---|
15
- | 1 | `module_validate` | tức thì, chỉ đọc file | lỗi quy tắc/tham chiếu tĩnh |
16
- | 2 | `module_outline` | tức thì | cấu trúc layout, action mồ côi, dialog không ai mở |
17
- | 3 | `module_simulate` | ~1 s | luồng chạy: action chain, watch, OUT gán gì |
18
- | 4 | `component_preview` | browser, 1 component | lỗi của riêng một `uc-*.vue` |
19
- | 5 | `module_simulate({renderUI:true})` | browser, ~10–30 s | **hình ảnh thật**: layout, chiều cao, style, responsive |
20
-
21
- **Quy tắc:** đi từ tầng rẻ nhất **bắt được triệu chứng đó**, không mặc định leo thẳng lên tầng 5. Tầng 5 là tầng duy nhất thấy được hình ảnh, nhưng cũng là tầng duy nhất **không nói được vì sao** — nó chỉ chụp lại hậu quả.
22
-
23
- | Triệu chứng | Tầng rẻ nhất bắt được | Vì sao |
24
- |---|---|---|
25
- | Trang trắng / app rỗng, **không** JS error, **không** `[Vue warn]` | **1** `module_validate` | dấu hiệu kinh điển của statement trong một `:attr` — Vue nuốt lỗi compile template, browser không có gì để báo |
26
- | `[Vue warn] Property or method "x" is not defined` | **1** | biến dùng trong template chưa khai trong `data[]` |
27
- | Nút bấm không làm gì | **1** (CALL target) → **3** (luồng thật) | |
28
- | `Unknown custom element: <f-…>` / component trống | **1** | sai tên component, hoặc thiếu import bắt buộc |
29
- | Chart không vẽ ra gì | **1** (thiếu `echarts.min.js`/`fechart.js`) → **5** (canvas 0-size) | thiếu import chiếm phần lớn số ca |
30
- | Cột lệch, một hàng quá chật | **2** `module_outline` (Σw > 12) | |
31
- | Dialog không mở được | **2** (`⚠ không thấy lệnh mở`) → **3** | |
32
- | Action chạy sai thứ tự · watch lặp vô hạn · CONFIRM/MESS không đúng nhánh | **3** `module_simulate` | |
33
- | Số liệu sai · `undefined`/`NaN` hiện trên trang | **3** | gần như luôn là `OUT`/mapData trỏ sai khoá, không phải lỗi hiển thị |
34
- | API trả không đúng shape mong đợi | `db_sp_verify` (suy luận tĩnh, **không gọi endpoint nào**) | suy luận từ thân SP thật + sinh sẵn `apiMocks` cho tầng 3. Không phải "zero HTTP" nguyên văn: khi chưa có `.sql` local nó lấy `OBJECT_DEFINITION`, và `checkGrant: true` hỏi `sys.database_permissions` — cả hai là **đọc metadata**, không chạy SP |
35
- | Một `uc-*.vue` hiển thị sai | **4** `component_preview` | chứng minh component đúng trước ⇒ mọi lỗi còn lại là lỗi lắp ráp |
36
- | Bảng tràn ngang · chiều cao sai · style rò rỉ · khoảng cách xấu · vỡ ở mobile | **5** `renderUI` | không tầng nào khác thấy được hình học |
37
- | Import/asset không nạp được | **5**, đọc section `⛔ MÔI TRƯỜNG THIẾU FILE` | lỗi của môi trường, **không** sửa module theo nó |
38
- | Nghi "thư viện platform có bug" | **5**, kiểm section `⛔ ASSET CŨ` TRƯỚC khi kết luận | asset stale ⇒ đang chạy bản trên đĩa, mọi kết luận về CDN đều vô giá trị |
39
- | Nút/menu **có gác quyền** không hiện với user thật (nhưng hiện trong preview) | **1** `module_validate` sau khi chạy `right_function_list` | mã quyền chưa được định nghĩa ⇒ `rightTest()` luôn false, không lỗi JS. Tầng 3/5 **cấp sẵn** đúng mã quét được nên chúng luôn hiện — xem [permission-system.md](permission-system.md) |
40
-
41
- **Không kết luận về platform từ một lượt render có asset stale.** renderUI revalidate mọi asset mỗi lượt (conditional GET), nên bình thường bạn đang xem đúng bản CDN hiện tại — dòng trace ghi `N revalidate 304`. Nhưng nếu report có khối `⛔ ASSET CŨ, KHÔNG XÁC MINH ĐƯỢC` thì mạng hỏng và trang đang chạy bằng bản trên đĩa: câu "thư viện X có bug" rút ra từ lượt đó **không dùng được**. Nối mạng render lại, hoặc `refreshAssets: true` để ép tải mới. Dòng `ℹ️ ASSET PLATFORM ĐÃ ĐỔI` nghĩa là file nền tảng vừa đổi giữa hai lượt — hành vi đổi mà `module.json` không đụng tới thì tìm nguyên nhân ở đó trước.
42
-
43
- **Đọc report renderUI đúng thứ tự:** khối `═══ CHẨN ĐOÁN ═══` ở đầu đã xếp mọi thứ hỏng vào ba nhóm theo **nơi phải sửa** — `[MÔI TRƯỜNG]` (sửa môi trường trước, lỗi hai nhóm dưới có thể chỉ là hệ quả) · `[MODULE]` (module.json/script.js/component) · `[HIỂN THỊ]` (DOM audit + ảnh). Dòng `↪` gợi ý tầng rẻ hơn lẽ ra bắt được triệu chứng đó.
44
-
45
- **Dấu hiệu phải DỪNG render lại:** dòng `Δ so với lượt trước` báo *không chỉ số nào đổi*. Nghĩa là thay đổi vừa rồi không chạm tới lỗi đang có — render lại lần nữa với cùng hướng sửa chỉ tốn thêm một lượt. Quay xuống tầng 1–3 để biết **vì sao**, rồi mới lên lại tầng 5.
46
-
47
- ---
48
-
49
- ## Module Checklist
50
-
51
- ### Structure
52
-
53
- - [ ] `_moduleInfo.json` exists with `ModuleID`, `ModuleName`, `Framework`, `mTitle`, `HTMLOnly`
54
- - [ ] `module.json` exists and is valid JSON (no trailing commas, no comments) — **validate trước khi ghi**: sau mỗi lần edit JSON dài, mentally check hoặc re-read để đảm bảo không có trailing comma sau element cuối cùng trong mảng/object
55
- - [ ] If custom components are used: `components/_components.json` exists and lists all `uc-*.vue` files
56
- - [ ] `imports/_imports.json` exists if module imports external JS/CSS
57
-
58
- ### module.json — Data
59
-
60
- - [ ] All reactive state variables declared in `data[]` before being referenced in actions
61
- - [ ] All named actions are reachable (at least one `CALL` or `watch` or button click references each)
62
- - [ ] No hardcoded IDs — inputs reference `vueData.someVar` not literal numbers
63
- - [ ] `OUT` keys match declared state variable names exactly (case-sensitive)
64
-
65
- ### module.json — Actions
66
-
67
- - [ ] Every `API` action has both `IN` and `OUT` (or `CALLBACK`) defined
68
- - [ ] Every delete action has `CONFIRM` before `API`
69
- - [ ] Every mutating action has a `CALLBACK` that either reloads data or shows `MESS`
70
- - [ ] Literal string values in `IN` use backtick prefix or single-quote wrap: `` "`winId" `` or `"'text'"`
71
- - [ ] `IF/THEN/ELSE` branches all have matching action structures
72
- - [ ] No raw `EXE` blocks that duplicate logic already expressible in actions
73
-
74
- ### module.json — Controls
75
-
76
- - [ ] `controls` array starts with `{ "prop": "fluid grid-list-md", "rows": [...] }`
77
- - [ ] Every item in `cols` has a `w` property
78
- - [ ] Events use `v-on:click` not `@click`
79
- - [ ] No `children` key — nesting uses `innerHTML` array
80
- - [ ] Permission gates use `col: { "v-if": "vueData.user.SystemRight>=N" }` (not on `attr`)
81
- - [ ] **Mọi mã `FunctionRight`/`SystemRight` đem gác đã TỒN TẠI thật** — đã chạy `right_function_list`/`right_system_list` (cũng là thứ tạo cache cho `module_validate` đối chiếu), mã chưa có thì `right_function_new`/`right_system_new` TRƯỚC. Mã bịa ra làm control biến mất im lặng và **preview vẫn hiện đúng** nên ảnh render không phát hiện được — xem [permission-system.md](permission-system.md)
82
- - [ ] All `v-if` expressions include `vueData.` prefix where referencing state
83
- - [ ] Dialog containers use `el: "hidden-container"` — one per dialog
84
-
85
- ### module.json — Watch
86
-
87
- - [ ] Watch keys reference declared state variables
88
- - [ ] `deep-watch` used for nested object/array observation
89
- - [ ] No watch entry calls an action that also triggers the same watch (infinite loop risk)
90
-
91
- ### UI Quality
92
-
93
- - [ ] Vuetify classes/props used before inline `style` (đúng version của project: FUI V2 = Vuetify 1.5, FUI V3 = Vuetify 3)
94
- - [ ] `f-*` components chosen over raw `v-*` when FUI equivalent exists
95
- - [ ] Tables use `f-table` (not `v-data-table`) — cả CRUD lẫn read-only (read-only = không khai `:update-api`)
96
- - [ ] Tổng cột dùng `sum-format` (object → hàng tổng trong bảng; string → dòng text dưới bảng) — không tự dựng hàng tổng thủ công
97
- - [ ] Charts dùng **`f-echart`** — không dùng `v-chart`, `<canvas>`, hay lib khác
98
- - [ ] Chart tuân thủ **Quy ước hiển thị mặc định** trong components-echart.md
99
- - [ ] Date/time fields use `f-date`/`f-time` (not `v-text-field` + manual parsing)
100
-
101
- ### Import JS/CSS
102
-
103
- - [ ] Với mỗi component có import (xem bảng trong `component-quickref.md`): đã gọi `file_import_list` để kiểm tra — import đang có hay chưa
104
- - [ ] Nếu thêm component cần import và chưa có → `file_import_new` cho từng file thiếu
105
- - [ ] Nếu bỏ component có import → kiểm tra import đó còn dùng ở component/module khác không; nếu không còn → `file_import_delete`
106
- - [ ] **Nếu có `f-echart`**: cả hai import phải có và đúng thứ tự — `echarts.min.js` trước, `fechart.js` sau:
107
- - `/include/chart/echarts.min.js`
108
- - `/include/chart/fechart.js`
109
-
110
- ### Validate trước khi publish
111
-
112
- - [ ] Module mới có cả UI lẫn API: đã dựng UI bằng dữ liệu cứng trong `data[]` + `module_simulate({ renderUI: true })` QA hình ảnh TRƯỚC khi chốt contract API và viết SP — xem quy trình đầy đủ ở [fullstack-workflow.md](fullstack-workflow.md)
113
- - [ ] Chạy `module_validate` sau khi sửa `module.json` — sửa hết **error** (CALL target không tồn tại, `@`/`#` shorthand, `children`, grid structure sai...)
114
- - [ ] Warning được review từng cái — có thể là chủ ý (component chưa có trong list, param optional...), nhưng không được bỏ qua mà không đọc
115
- - [ ] Warning nhóm **`[design]`** (toolbar dialog có màu, nút xóa màu đỏ, width dialog lạ, form không floating label, delete thiếu CONFIRM, nút Đóng thừa, tự dựng v-snackbar/v-alert thay vì MESS/MESSBOX, f-table/f-sheet bảng chính thiếu `":height": -16` nên cả trang cuộn thay vì cuộn trong bảng...) = vi phạm chuẩn thẩm mỹ mặc định — **phải sửa**, trừ khi chính user đã yêu cầu rõ kiểu khác trong phiên này
116
- - [ ] Strict mode (`FUI_MCP_STRICT=1`): error sẽ CHẶN publish — không thể bỏ qua
117
- - [ ] Chạy `module_outline` và ĐỌC cây layout để tự review cấu trúc UI: mỗi row có Σw hợp lý (≤12)? dialog nào có `⚠ không thấy lệnh mở`? action nào có `⚠ không thấy nơi gọi`? state nào `⚠ không thấy dùng`?
118
- - [ ] Với module có logic runtime phức tạp (action chain, watch cascade, dialog flow): chạy `module_simulate` với kịch bản luồng chính + `apiMocks` (shape lấy từ snippet do `db_sp_verify` sinh sẵn) + assert điều kiện then chốt — sửa mọi `⚠` và assert ✘ trong trace trước khi publish. **Lưu ý**: `apiMocks` bạn truyền luôn thắng, nhưng một API tĩnh KHÔNG có mock mà SP đích đã xác nhận chỉ đọc (`db_sp_verify`/đã có `.sql` local) sẽ tự động được gọi thật (giới hạn 8 lượt/lần, có cache `_testdata/`) thay vì rơi thẳng `{data:[]}` — đọc dòng "Live/Cache data" trong report để biết SP nào lấy từ đâu; SP có lệnh ghi thì không bao giờ bị gọi thật
119
- - [ ] **`apiMocks` của SP đã tồn tại phải đến từ `db_sp_verify`, không tự đoán** — thấy `module_simulate` trả cảnh báo `🚨 CẤU TRÚC MOCK CHƯA ĐƯỢC KIỂM CHỨNG` thì dừng, chạy `db_sp_verify` rồi copy nguyên văn snippet nó sinh ra, không tự sửa tay rồi bỏ qua. Bịa cấu trúc chỉ hợp lệ cho SP thật sự chưa tồn tại (chưa deploy)
120
- - [ ] **QA hiển thị cuối cùng (khi có Playwright)**: chạy `module_simulate({ renderUI: true, vueData: {..demo data..}, apiMocks: {...} })` — render browser thật, ĐỌC screenshot trả về (luôn có ảnh inline — PNG quá lớn tự nén JPEG) + DOM audit (app rỗng? tràn ngang? text "undefined"/"NaN"? ảnh vỡ? canvas chart 0-size?) + JS error/`[Vue warn]` + state cuối vueData — tự fix lỗi hiển thị rồi render lại cho tới khi sạch. **Có section `⛔ MÔI TRƯỜNG THIẾU FILE` thì đọc nó TRƯỚC**: import/asset chưa nạp được là lỗi môi trường (chạy lệnh nó gợi ý — `project_sync`/`module_get`), các lỗi JS/hiển thị bên dưới có thể chỉ là hệ quả — đừng sửa module.json theo chúng — cách ĐỌC ảnh có hệ thống: xem `ui-screenshot-review.md`. Chart/animation render thiếu trong ảnh → tăng `settleMs` (vd 1500). Dialog đang mở được chụp riêng `render-dialog.jpg`. Module có dùng trên mobile → render thêm lượt `device: "mobile"`. Không có Playwright → bỏ qua bước này (tool sẽ trả hướng dẫn cài)
121
- - [ ] **Vừa sửa cả cấp project lẫn cấp module** (component project, import project, `project.json`/menu): publish phần **cấp project** TRƯỚC rồi mới render — renderUI lấy `$projectData` + component project + CSS project từ server (`_aset`), nên bản project chưa publish sẽ không xuất hiện trong ảnh; ngược lại phần cấp module dựng cục bộ, cứ sửa-render-sửa thoải mái rồi publish sau. Riêng **component cấp project** thì không còn là lời nhắc: renderUI đối chiếu từng `uc-*.vue` local với bundle server và **chặn cứng** (không có cờ bỏ qua) nếu lệch — kiểm chứng bản local bằng `component_preview`, rồi `component_new`/`component_update`, rồi mới render. Bị chặn vì bản server mới hơn (ai đó sửa trên web IDE) → `project_sync`, đừng push đè
122
-
123
- ### Publish Workflow — Smart (sửa cái nào, up cái đó)
124
-
125
- Không phải lúc nào cũng dùng `module_publish_html`. Chọn tool theo phần đã thay đổi:
126
-
127
- - [ ] Chỉ sửa `module.json` → dùng `module_publish_json` (không cần preview/approval)
128
- - [ ] Sửa `header.html` / `body.html` / title → `module_preview` → user approve → `module_publish_html` (đã kèm module.json, không cần gọi thêm `module_publish_json`)
129
- - [ ] Sửa `script.js` (kể cả làm rỗng) → `module_publish_script` — **⚠️ `module_publish_html` không clear script rỗng trên server**
130
- - [ ] Sửa `uc-*.vue` → `component_new` (lần đẩy đầu tiên) hoặc `component_update` (các lần sau), per file — `component_update` lỗi cứng nếu component chưa có trên server, không âm thầm tạo
131
- - [ ] Nhiều phần → gọi tool tương ứng cho từng phần, lần lượt
132
-
133
- Khi dùng `module_publish_html`:
134
- - [ ] `module_preview` đã chạy và diff đã được review
135
- - [ ] User đã xác nhận rõ ràng
136
- - [ ] Có approval token từ `module_preview`
137
-
138
- ---
139
-
140
- ## Stored Procedure Checklist
141
-
142
- ### Naming
143
-
144
- - [ ] Prefix is `spAPI_` (e.g., `spAPI_ContractList`, `spAPI_ContractInsert`)
145
- - [ ] Name follows pattern: `spAPI_{Entity}{Action}` where Action is `List`/`Select`/`Insert`/`Update`/`Delete`/`Save`
146
- - [ ] No spaces, no lowercase prefix (`sp_`, `SP_`, etc.)
147
-
148
- ### Parameters
149
-
150
- - [ ] `@sys_UserID int` present in all write operations (INSERT/UPDATE/DELETE)
151
- - [ ] `@sys_SystemRight int` present when permission check is needed
152
- - [ ] Input parameters declared before system parameters
153
- - [ ] No unused parameters
154
-
155
- ### Security
156
-
157
- - [ ] Permission check at top: `IF @sys_SystemRight < N BEGIN RAISERROR(N'[Unauthorized]Bạn không có quyền...', 16, 1) RETURN END` — severity luôn là `16`, prefix `[Unauthorized]` bắt buộc trên lỗi thiếu quyền để tAPI trả HTTP 401 (xem [tapi-reference.md](tapi-reference.md) §5)
158
- - [ ] No direct string concatenation for SQL (use parameterized queries)
159
- - [ ] File `.sql` **KHÔNG chứa `GRANT EXECUTE`** — thân `CREATE PROCEDURE` kéo dài tới hết batch, mà tAPI gửi một batch và không hỗ trợ `GO`, nên câu GRANT viết sau `END` bị **nuốt vào thân SP**: nó chạy mỗi lần gọi SP chứ không cấp quyền lúc deploy, và không có lỗi nào nổi lên. `db_sp_deploy` tự cấp quyền cho procedure mới rồi **hỏi lại `sys.database_permissions` để xác nhận**
160
- - [ ] Kết quả `db_sp_deploy` báo `✓ [public] đã có quyền EXECUTE` — nếu thấy `❗` thì chạy đúng câu GRANT nó in ra (**đừng deploy lại**, SP đã lên server rồi). Deploy SP qua `db_sql_execute_nonquery` thì không có auto-grant; tool cảnh báo và nêu lệnh cần chạy. Nghi ngờ về sau: `db_sp_verify({ name, checkGrant: true })`
161
-
162
- ### Logic
163
-
164
- - [ ] SP returns exactly what FUI `OUT` expects (column names match exactly)
165
- - [ ] Error conditions use `RAISERROR(N'...', 16, 1)` followed by `RETURN` (not silent failures)
166
- - [ ] Transactions used for multi-step writes
167
- - [ ] SP logic reviewed statically (read the body, reason about branches/edge cases) before deploy — never smoke-tested against the live endpoint
168
-
169
- ### Deploy Workflow
170
-
171
- - [ ] `db_sp_save` called first (save to local, no DB change)
172
- - [ ] Full SP body reviewed in local file before deploy
173
- - [ ] Summary presented to user: SP name, operation type (CREATE/ALTER), affected tables
174
- - [ ] User has explicitly confirmed before `db_sp_deploy`
175
- - [ ] Sau deploy bất kỳ API nào (đọc hay ghi) sắp wire vào module.json → `db_sp_verify` một lần: suy luận tĩnh response shape/contract lỗi từ thân SP thật, đối chiếu params — **không gọi endpoint nào**. (Không phải "zero HTTP" nguyên văn: chưa có `.sql` local thì nó lấy `OBJECT_DEFINITION`, `checkGrant: true` thì hỏi `sys.database_permissions` — cả hai là *đọc metadata*, không chạy SP)
176
- - [ ] API **ghi** (Insert/Update/Delete) → kiểm tra tính đúng bằng cách đọc thân SP (`db_sp_get`/`db_sp_verify`) và suy luận logic tĩnh (WHERE, transaction, RAISERROR); test luồng UI gọi API ghi bằng `module_simulate({ apiMocks: {...} })` với dữ liệu giả (snippet có sẵn từ `db_sp_verify`), không gọi API thật
177
-
178
- ---
179
-
180
- ## Vue Component Checklist (`uc-*.vue`)
181
-
182
- ### File
183
-
184
- - [ ] Filename starts with `uc-` prefix
185
- - [ ] Registered in `_components.json`
186
- - [ ] `<style scoped>` block (nếu có): mọi selector đã tự tiền tố bằng class định danh của component — `scoped` KHÔNG scope thật (server chỉ nối text `ComCSS`), selector trần sẽ leak sang component khác. Xem [component-design.md](component-design.md)
187
- - [ ] No backtick template strings inside `<template>`
188
-
189
- ### API Design
190
-
191
- - [ ] All inputs declared as `props` with types
192
- - [ ] Component emits events upward (`input`, `change`, `select`, `action`) rather than mutating parent state
193
- - [ ] Props use neutral names (`items`, `value`, `label`) not screen-specific names
194
- - [ ] Loading, empty, and error states handled (prop or slot)
195
-
196
- ### Behavior
197
-
198
- - [ ] Component does not fetch data directly unless it is explicitly a data-owning component
199
- - [ ] No hardcoded route/module paths inside the component
200
- - [ ] No permission logic inside component — permission gating stays in `module.json`
201
-
202
- ### Kiểm chứng trong không gian riêng (trước khi ráp vào module / trước khi push)
203
-
204
- - [ ] Đã chạy `component_preview` với **ít nhất 2 case**: một case dữ liệu bình thường và một case biên (danh sách rỗng / chuỗi rất dài / thiếu trường) — component sai ở case biên là lỗi hay gặp nhất
205
- - [ ] Đã ĐỌC ảnh chụp của **cả desktop lẫn mobile** (mặc định tool render cả hai): không tràn ngang, không vỡ layout ở 390px, không text "undefined"/"NaN"
206
- - [ ] Không còn JS error / `[Vue warn]` trong report
207
- - [ ] Component có tương tác → `scenario` với `click`/`set` + `assert` đã chạy đúng (dùng `nth`, không `item`/`index`)
208
- - [ ] Component tự đo chiều cao (chart, table) → thử thêm `viewport` chiều cao thấp
209
- - [ ] **Component cấp project**: đã push (`component_new` lần đầu / `component_update` các lần sau) NGAY SAU khi preview sạch — renderUI của module sẽ chặn cứng nếu bản local còn lệch bản server
210
-
211
- ---
212
-
213
- ## Import File Checklist
214
-
215
- - [ ] File type matches declared `ContentType` (`.js` → `application/javascript`, `.css` → `text/css`)
216
- - [ ] `sort` >= 40 khi thêm import mới — giá trị 1–39 dành cho hệ thống, không dùng
217
- - [ ] Content tested locally before `file_import_upload_content`
218
- - [ ] No sensitive data (tokens, passwords) in JS/CSS import files
219
- - [ ] If updating an existing file: `file_import_get` called first to review current content
220
-
221
- ---
222
-
223
- ## Debug Workflow — Sau khi publish có lỗi
224
-
225
- Khi server báo lỗi hoặc trang hiển thị sai sau khi publish:
226
-
227
- 1. **Review file vừa sửa trước tiên** — đọc lại toàn bộ file đã chỉnh sửa trong lần publish đó, không nhảy sang nguyên nhân khác
228
- 2. Nếu file trông đúng: chạy `module_preview` để xem diff — kiểm tra server đang lưu gì so với local
229
- 3. Nếu preview báo `Controls: 0` / `Data keys: 0`: đó là server đang giữ bản cũ bị lỗi, không phải local — push lại để ghi đè
230
- 4. Chỉ khi local file đã xác nhận đúng mà lỗi vẫn còn: mới kiểm tra các file khác (header.html, script.js, imports)
231
-
232
- ---
233
-
234
- ## Quick Risk Gate
235
-
236
- Before any mutating tool call, answer:
237
-
238
- | Question | If NO → |
239
- |---|---|
240
- | Is this a ReadOnly tool? | Confirm intent with user |
241
- | Have I shown the user a summary? | Show summary first, then wait |
242
- | Is this a 🔴 Destructive tool? | Require explicit user confirmation |
243
- | For `module_publish_html`: do I have an approval token? | Run `module_preview` first |
244
- | For `db_sp_deploy`: has user seen the SP body? | Show SP body, wait for OK |
245
-
246
- See [tools-registry.md](tools-registry.md) for the full per-tool classification.
1
+ # FUI Definition-of-Done Checklists
2
+
3
+ > Owns: **definition-of-done checklists before publish (module.json, `.vue`, SP, deploy)** and **symptom → verification tier matrix**. Flags: `fui <command> --help`.
4
+
5
+ Each item is a gate: not ready while any required item is unchecked.
6
+
7
+ ---
8
+
9
+ ## Pick the tier by SYMPTOM (read before rendering)
10
+
11
+ Tiers differ ~100× in cost per run:
12
+
13
+ | Tier | Command | Cost | Sees |
14
+ | ---- | ------------------------------ | -------------------- | --------------------------------------------------- |
15
+ | 1 | `fui module validate` | instant, file-only | static rule/reference errors |
16
+ | 2 | `fui module outline` | instant | layout, orphan actions, dialogs nobody opens |
17
+ | 3 | `fui module simulate` | ~1 s | flow: action chain, watch, what OUT assigns |
18
+ | 4 | `fui component preview` | browser, 1 component | bugs in one `uc-*.vue` |
19
+ | 5 | `fui module simulate --render` | browser, ~10–30 s | **real visuals**: layout, height, style, responsive |
20
+
21
+ `fui module check` = tiers 1–3 in one step.
22
+
23
+ **Start at the cheapest tier that catches the symptom**, never tier 5 by default. Tier 5 alone sees visuals but can't say **why**.
24
+
25
+ | Symptom | Cheapest tier | Why |
26
+ | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
27
+ | Blank page, **no** JS error, **no** `[Vue warn]` | **1** | statement inside a `:attr` — Vue swallows template compile errors |
28
+ | `[Vue warn] Property or method "x" is not defined` | **1** | variable not in `data[]` |
29
+ | Button does nothing | **1** (CALL target) → **3** | |
30
+ | `Unknown custom element: <f-…>` / empty component | **1** | wrong name or missing required import |
31
+ | Chart draws nothing | **1** (missing `echarts.min.js`/`fechart.js`, most cases) → **5** (0-size canvas) | |
32
+ | Misaligned columns, cramped row | **2** (Σw > 12) | |
33
+ | Dialog won't open | **2** (`⚠ không thấy lệnh mở`) → **3** | |
34
+ | Wrong action order · infinite watch loop · CONFIRM/MESS wrong branch | **3** | |
35
+ | Wrong numbers · `undefined`/`NaN` on page | **3** | almost always `OUT`/mapData on the wrong key, not display |
36
+ | API returns unexpected shape | `fui sp verify` (static, **calls no endpoint**) | infers from the real SP body + generates `--mocks` for tier 3. Only metadata reads: `OBJECT_DEFINITION` when no local `.sql`, `sys.database_permissions` with `--check-grant`; never runs the SP |
37
+ | One `uc-*.vue` wrong | **4** | once proven, remaining bugs are assembly |
38
+ | Horizontal overflow · wrong height · leaking style · bad spacing · broken on mobile | **5** | only tier seeing geometry |
39
+ | Import/asset not loaded | **5**, section `⛔ MÔI TRƯỜNG THIẾU FILE` | environment error — **don't** edit the module for it |
40
+ | Suspected "platform library bug" | **5**, check `⛔ ASSET CŨ` FIRST | stale asset ⇒ on-disk copy ran; CDN conclusions worthless |
41
+ | **Permission-gated** button/menu hidden for real users but shown in preview | **1** after `fui right function list` | undefined code ⇒ `rightTest()` always false, no JS error. Tiers 3/5 **pre-grant** scanned codes so they always show — [permission-system.md](permission-system.md) |
42
+
43
+ **Stale assets:** `--render` revalidates every asset per run (conditional GET; trace shows `N revalidate 304`). `⛔ ASSET CŨ, KHÔNG XÁC MINH ĐƯỢC` = network failed, on-disk copy ran ⇒ "library X has a bug" from that run is **unusable**; reconnect and re-render, or `--refresh-assets`. `ℹ️ ASSET PLATFORM ĐÃ ĐỔI` = platform file changed between runs — behavior changed without a `module.json` edit ⇒ look there first.
44
+
45
+ **Read the `--render` report top-down:** `═══ CHẨN ĐOÁN ═══` groups failures by **where to fix** — `[MÔI TRƯỜNG]` (fix first; the others may be consequences) · `[MODULE]` (module.json/script.js/component) · `[HIỂN THỊ]` (DOM audit + image). `↪` = cheaper tier that should have caught it.
46
+
47
+ **STOP re-rendering** when `Δ so với lượt trước` shows _no metric changed_: the fix missed the bug. Drop to tiers 1–3 to learn why, then return.
48
+
49
+ ---
50
+
51
+ ## Module Checklist
52
+
53
+ ### Structure
54
+
55
+ - [ ] `_moduleInfo.json` has `ModuleID`, `ModuleName`, `Framework`, `mTitle`, `HTMLOnly`
56
+ - [ ] `module.json` is valid JSON (no trailing commas, no comments) — re-read after every long edit to catch a comma after the last array/object element
57
+ - [ ] Custom components ⇒ `components/_components.json` lists all `uc-*.vue`
58
+ - [ ] External JS/CSS ⇒ `imports/_imports.json` exists
59
+
60
+ ### module.json — Data
61
+
62
+ - [ ] All state declared in `data[]` before use in actions
63
+ - [ ] Every named action reachable (`CALL`, `watch` or button click)
64
+ - [ ] No hardcoded IDs — use `vueData.someVar`, not literal numbers
65
+ - [ ] `OUT` keys match state names exactly (case-sensitive)
66
+
67
+ ### module.json — Actions
68
+
69
+ - [ ] Every `API` has `IN` and `OUT` (or `CALLBACK`)
70
+ - [ ] Every delete has `CONFIRM` before `API`
71
+ - [ ] Every mutation has a `CALLBACK` that reloads data or shows `MESS`
72
+ - [ ] Literal strings in `IN`: backtick prefix or single quotes — ``"`winId"`` or `"'text'"`
73
+ - [ ] `IF/THEN/ELSE` branches have matching action structures
74
+ - [ ] No raw `EXE` duplicating logic expressible as actions
75
+
76
+ ### module.json — Controls
77
+
78
+ - [ ] `controls` starts with `{ "prop": "fluid grid-list-md", "rows": [...] }`
79
+ - [ ] Every `cols` item has `w`
80
+ - [ ] `v-on:click`, not `@click`
81
+ - [ ] No `children` — nest with `innerHTML` array
82
+ - [ ] Permission gates on `col: { "v-if": "vueData.user.SystemRight>=N" }` (not `attr`)
83
+ - [ ] **Every gated `FunctionRight`/`SystemRight` code EXISTS** — ran `fui right function list`/`fui right system list` (also builds the cache `fui module validate` checks); missing ⇒ `fui right function new`/`fui right system new` FIRST. Invented codes hide controls silently while **preview still shows them** — [permission-system.md](permission-system.md)
84
+ - [ ] `v-if` uses `vueData.` prefix for state
85
+ - [ ] Dialogs use `el: "hidden-container"`, one per dialog
86
+
87
+ ### module.json — Watch
88
+
89
+ - [ ] Keys reference declared state
90
+ - [ ] `deep-watch` for nested object/array
91
+ - [ ] No watch calls an action that re-triggers itself (infinite loop)
92
+
93
+ ### UI Quality
94
+
95
+ - [ ] Vuetify classes/props before inline `style` (FUI V2 = Vuetify 1.5, FUI V3 = Vuetify 3)
96
+ - [ ] `f-*` over raw `v-*` when an equivalent exists
97
+ - [ ] Tables: `f-table`, not `v-data-table` — CRUD and read-only (read-only = no `:update-api`)
98
+ - [ ] Totals via `sum-format` (object → total row; string → text line below) — never hand-built
99
+ - [ ] Charts: **`f-echart`** only — not `v-chart`, `<canvas>`, other libs; follow **default display conventions** in components-echart.md
100
+ - [ ] Date/time: `f-date`/`f-time`, not `v-text-field` + manual parsing
101
+
102
+ ### Import JS/CSS
103
+
104
+ - [ ] Each component needing imports (table in `component-quickref.md`): checked with `fui import list`
105
+ - [ ] Missing ⇒ `fui import new` per file
106
+ - [ ] Component removed ⇒ if its import is unused elsewhere, `fui import delete`
107
+ - [ ] **`f-echart`**: both imports, in order:
108
+ - `/include/chart/echarts.min.js`
109
+ - `/include/chart/fechart.js`
110
+
111
+ ### Validate before publish
112
+
113
+ - [ ] New module with UI + API: UI built with hardcoded `data[]` + visual QA (`fui module simulate --render`) BEFORE the API contract and SPs — [fullstack-workflow.md](fullstack-workflow.md)
114
+ - [ ] `fui module validate` after editing `module.json` — fix every **error** (missing CALL target, `@`/`#` shorthand, `children`, bad grid...)
115
+ - [ ] Read each warning — may be intentional (unlisted component, optional param...), never skip unread
116
+ - [ ] **`[design]`** warnings (colored dialog toolbar, red delete button, odd dialog width, no floating label, delete without CONFIRM, redundant Close button, hand-built v-snackbar/v-alert instead of MESS/MESSBOX, main f-table/f-sheet without `":height": -16` so the page scrolls instead of the table...) — **must fix** unless the user explicitly asked otherwise this session
117
+ - [ ] Strict mode (`FUI_STRICT=1`): errors BLOCK publish
118
+ - [ ] `fui module outline`, READ the tree: row Σw ≤12? `⚠ không thấy lệnh mở`? `⚠ không thấy nơi gọi`? `⚠ không thấy dùng`?
119
+ - [ ] Complex runtime logic (action chain, watch cascade, dialog flow): `fui module simulate` with main-flow `--scenario` + `--mocks` (shape from `fui sp verify` snippet) + asserts — fix every `⚠` and ✘ first. Your `--mocks` always win; a static API with NO mock whose SP is confirmed read-only (`fui sp verify`/local `.sql`) is called for real (max 8 calls/run, cached in `_testdata/`) instead of `{data:[]}` — see the "Live/Cache data" line. SPs with writes are never called
120
+ - [ ] **`--mocks` for existing SPs come from `fui sp verify`, never guessed** — on `🚨 CẤU TRÚC MOCK CHƯA ĐƯỢC KIỂM CHỨNG`, stop, run `fui sp verify`, copy the snippet verbatim (no hand edits). Invented shapes only for SPs not yet deployed
121
+ - [ ] **Final visual QA (Playwright available)**: `fui module simulate --render --vue-data '{..demo data..}' --mocks '{...}'`. READ the screenshot (always inline; big PNG → JPEG) + DOM audit (empty app, overflow, "undefined"/"NaN", broken image, 0-size chart canvas) + JS errors/`[Vue warn]` + final vueData; fix and re-render until clean. **`⛔ MÔI TRƯỜNG THIẾU FILE` first**: environment error — run its suggested command (`fui project sync`/`fui module get`); errors below may be consequences, don't edit module.json for them. How to read screenshots: `ui-screenshot-review.md`. Chart/animation missing → raise `--settle-ms` (e.g. 1500). Open dialog captured as `render-dialog.jpg`. Mobile use → extra run `--device mobile`. No Playwright → skip (command returns install steps)
122
+ - [ ] **Changed project level + module level** (project component/import, `project.json`/menu): publish **project level FIRST**, then render — `--render` loads `$projectData`, project components and project CSS from the server (`_aset`); module-level parts render locally (iterate freely, publish later). **Project components are hard-blocked** (no bypass flag) if a local `uc-*.vue` differs from the server bundle: `fui component preview` → `fui component new`/`update` → render. Blocked because server is newer (web IDE edit) → `fui project sync`, never push over
123
+
124
+ ### Publish — only what changed
125
+
126
+ - [ ] Only `module.json` → `fui module publish json` (no preview/approval)
127
+ - [ ] `header.html` / `body.html` / title → `fui module preview` → user approves → `fui module publish html --approval <token>` (includes module.json)
128
+ - [ ] `script.js` (even emptied) → `fui module publish script` — **⚠️ `publish html` does not clear an empty script on the server**
129
+ - [ ] `uc-*.vue` → `fui component new` (first) / `fui component update` (later), per file — `update` hard-errors if absent on server, never creates
130
+ - [ ] Several parts → one command each, in turn
131
+
132
+ For `fui module publish html`: preview ran and diff reviewed · user explicitly confirmed · approval token in hand.
133
+
134
+ ---
135
+
136
+ ## Stored Procedure Checklist
137
+
138
+ ### Naming
139
+
140
+ - [ ] `spAPI_{Entity}{Action}`, Action = `List`/`Select`/`Insert`/`Update`/`Delete`/`Save` (e.g. `spAPI_ContractList`, `spAPI_ContractInsert`)
141
+ - [ ] No spaces, no `sp_`/`SP_` prefix
142
+
143
+ ### Parameters
144
+
145
+ - [ ] `@sys_UserID int` in all writes (INSERT/UPDATE/DELETE)
146
+ - [ ] `@sys_SystemRight int` when checking permission
147
+ - [ ] Input params before system params; no unused params
148
+
149
+ ### Security
150
+
151
+ - [ ] Permission check at top: `IF @sys_SystemRight < N BEGIN RAISERROR(N'[Unauthorized]Bạn không có quyền...', 16, 1) RETURN END` — severity always `16`; `[Unauthorized]` prefix required so tAPI returns HTTP 401 ([tapi-reference.md](tapi-reference.md) §5)
152
+ - [ ] No SQL string concatenation (parameterize)
153
+ - [ ] `.sql` has **NO `GRANT EXECUTE`** — tAPI sends one batch, no `GO`, so a GRANT after `END` is **swallowed into the SP body** and runs on every call, silently. `fui sp deploy` grants new procedures and **re-queries `sys.database_permissions` to confirm**
154
+ - [ ] `fui sp deploy` shows `✓ [public] đã có quyền EXECUTE`; on `❗` run exactly the printed GRANT (**don't redeploy**). `fui exec` deploys have no auto-grant (fui warns with the command). Later doubts: `fui sp verify <name> --check-grant`
155
+
156
+ ### Logic
157
+
158
+ - [ ] Returns exactly the columns `OUT` expects
159
+ - [ ] Errors: `RAISERROR(N'...', 16, 1)` then `RETURN`, never silent
160
+ - [ ] Transactions for multi-step writes
161
+ - [ ] Reviewed statically (read body, reason about branches/edge cases) — never smoke-tested against the live endpoint
162
+
163
+ ### Deploy
164
+
165
+ - [ ] `fui sp save` first (local only)
166
+ - [ ] Full body reviewed in the local file
167
+ - [ ] Summary to user: SP name, CREATE/ALTER, affected tables
168
+ - [ ] User explicitly confirmed before `fui sp deploy`
169
+ - [ ] Any API (read or write) about to be wired into module.json → `fui sp verify` once: static shape/error contract + param check, **no endpoint call** (metadata reads only, as above)
170
+ - [ ] **Write** APIs: verify by reading the body (`fui sp get`/`fui sp verify`) — WHERE, transaction, RAISERROR; test the UI flow with `fui module simulate --mocks '{...}'` (snippet from `fui sp verify`), never the real API
171
+
172
+ ---
173
+
174
+ ## Vue Component Checklist (`uc-*.vue`)
175
+
176
+ ### File
177
+
178
+ - [ ] Name starts with `uc-`; registered in `_components.json`
179
+ - [ ] `<style scoped>`: every selector prefixed with the component's own class — `scoped` does NOT scope (server concatenates `ComCSS`), bare selectors leak. [component-design.md](component-design.md)
180
+ - [ ] No backtick template strings in `<template>`
181
+
182
+ ### API Design
183
+
184
+ - [ ] Inputs are typed `props`; neutral names (`items`, `value`, `label`)
185
+ - [ ] Emits events (`input`, `change`, `select`, `action`), never mutates parent state
186
+ - [ ] Loading, empty, error states handled (prop or slot)
187
+
188
+ ### Behavior
189
+
190
+ - [ ] No data fetching unless explicitly data-owning
191
+ - [ ] No hardcoded route/module paths
192
+ - [ ] No permission logic — gating stays in `module.json`
193
+
194
+ ### Verify in isolation (before assembling / pushing)
195
+
196
+ - [ ] `fui component preview` with **≥2 cases**: normal + edge (empty list / very long string / missing field) — edge cases fail most
197
+ - [ ] READ **desktop and mobile** screenshots (default): no overflow, no break at 390px, no "undefined"/"NaN"
198
+ - [ ] No JS error / `[Vue warn]`
199
+ - [ ] Interactive ⇒ `scenario` with `click`/`set` + `assert` passes (use `nth`, not `item`/`index`)
200
+ - [ ] Self-sizing (chart, table) ⇒ also a low-height `viewport`
201
+ - [ ] **Project-level component**: push (`fui component new`/`update`) RIGHT AFTER a clean preview — module `--render` hard-blocks on mismatch
202
+
203
+ ---
204
+
205
+ ## Import File Checklist
206
+
207
+ - [ ] File type matches `ContentType` (`.js` → `application/javascript`, `.css` → `text/css`)
208
+ - [ ] `sort` >= 40 for new imports (1–39 reserved)
209
+ - [ ] Content tested locally before `fui import upload`
210
+ - [ ] No tokens/passwords in JS/CSS
211
+ - [ ] Updating ⇒ `fui import get` first
212
+
213
+ ---
214
+
215
+ ## Debug — errors after publish
216
+
217
+ 1. **Re-read every file changed in that publish first**; don't jump elsewhere
218
+ 2. Looks right ⇒ `fui module preview` for server vs local diff
219
+ 3. Preview shows `Controls: 0` / `Data keys: 0` ⇒ server holds a broken old version — push again
220
+ 4. Only when local is confirmed correct: check other files (header.html, script.js, imports)
221
+
222
+ ---
223
+
224
+ ## Quick Risk Gate
225
+
226
+ Before any mutating command:
227
+
228
+ | Question | If NO → |
229
+ | ------------------------------------------ | ------------------------------ |
230
+ | Read-only command? | Confirm intent with user |
231
+ | Summary shown to user? | Show it, then wait |
232
+ | 🔴 Destructive? | Require explicit confirmation |
233
+ | `fui module publish html`: approval token? | Run `fui module preview` first |
234
+ | `fui sp deploy`: user saw the SP body? | Show it, wait for OK |
235
+
236
+ Per-command classification: [tools-registry.md](tools-registry.md).