create-wakii-stack 0.0.0-stage → 0.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 (998) hide show
  1. package/README.md +66 -2
  2. package/dist/chunk-7XGW4UJ5.js +75 -0
  3. package/dist/chunk-AKPWS7FJ.js +76 -0
  4. package/dist/chunk-ELM6GGC5.js +50 -0
  5. package/dist/chunk-ON2WTGZH.js +77 -0
  6. package/dist/index.js +385 -0
  7. package/dist/manifest-2JVLRMDB.js +10 -0
  8. package/dist/manifest-O35TPW73.js +10 -0
  9. package/dist/manifest-TXTY67BF.js +10 -0
  10. package/dist/manifest-XWHR7Y3F.js +10 -0
  11. package/package.json +23 -4
  12. package/stack-template/.changeset/config.json +15 -0
  13. package/stack-template/.changeset/vu53-ui-redesign.md +11 -0
  14. package/stack-template/.claude/agents/be-dev.md +56 -0
  15. package/stack-template/.claude/agents/contracts-keeper.md +51 -0
  16. package/stack-template/.claude/agents/e2e-runner.md +61 -0
  17. package/stack-template/.claude/agents/fe-dev.md +53 -0
  18. package/stack-template/.claude/settings.json +77 -0
  19. package/stack-template/.claude/settings.local.json +9 -0
  20. package/stack-template/.claude/skills/add-service/SKILL.md +81 -0
  21. package/stack-template/.claude/skills/sync-contracts/SKILL.md +74 -0
  22. package/stack-template/.editorconfig +21 -0
  23. package/stack-template/.gitattributes +10 -0
  24. package/stack-template/.github/pull_request_template.md +26 -0
  25. package/stack-template/.github/workflow-templates/services-ci.yml.example +69 -0
  26. package/stack-template/.github/workflows/contracts.yml +133 -0
  27. package/stack-template/.github/workflows/convergence.yml +209 -0
  28. package/stack-template/.github/workflows/git-guard.yml +44 -0
  29. package/stack-template/.github/workflows/publish-uikit.yml +96 -0
  30. package/stack-template/.github/workflows/remotes-activity.yml +82 -0
  31. package/stack-template/.github/workflows/remotes-tasks.yml +82 -0
  32. package/stack-template/.github/workflows/services-auth-svc.yml +153 -0
  33. package/stack-template/.github/workflows/services-go-svc.yml +281 -0
  34. package/stack-template/.github/workflows/services-node-svc.yml +173 -0
  35. package/stack-template/.github/workflows/services-spring-svc.yml +132 -0
  36. package/stack-template/.github/workflows/shell.yml +78 -0
  37. package/stack-template/.github/workflows/ui-kit.yml +51 -0
  38. package/stack-template/.husky/commit-msg +14 -0
  39. package/stack-template/.husky/pre-push +51 -0
  40. package/stack-template/.spectral.yaml +17 -0
  41. package/stack-template/AGENTS.md +197 -0
  42. package/stack-template/CLAUDE.md +114 -0
  43. package/stack-template/README.md +172 -0
  44. package/stack-template/app/admin/index.html +12 -0
  45. package/stack-template/app/admin/package.json +40 -0
  46. package/stack-template/app/admin/scripts/verify-chart.mjs +49 -0
  47. package/stack-template/app/admin/src/App.test.tsx +70 -0
  48. package/stack-template/app/admin/src/App.tsx +33 -0
  49. package/stack-template/app/admin/src/data/users.ts +47 -0
  50. package/stack-template/app/admin/src/layout/AdminLayout.tsx +212 -0
  51. package/stack-template/app/admin/src/main.tsx +17 -0
  52. package/stack-template/app/admin/src/pages/ComponentsDemo.tsx +138 -0
  53. package/stack-template/app/admin/src/pages/Dashboard.tsx +182 -0
  54. package/stack-template/app/admin/src/pages/HooksDemo.tsx +153 -0
  55. package/stack-template/app/admin/src/pages/Settings.tsx +156 -0
  56. package/stack-template/app/admin/src/pages/UploadPage.tsx +34 -0
  57. package/stack-template/app/admin/src/pages/Users.test.tsx +66 -0
  58. package/stack-template/app/admin/src/pages/Users.tsx +245 -0
  59. package/stack-template/app/admin/src/styles.css +9 -0
  60. package/stack-template/app/admin/src/tests/setup.ts +15 -0
  61. package/stack-template/app/admin/tsconfig.json +18 -0
  62. package/stack-template/app/admin/vite.config.ts +11 -0
  63. package/stack-template/app/admin/vitest.config.ts +14 -0
  64. package/stack-template/app/create-wakii-app/README.md +71 -0
  65. package/stack-template/app/create-wakii-app/package.json +27 -0
  66. package/stack-template/app/create-wakii-app/scripts/publish-npm.sh +38 -0
  67. package/stack-template/app/create-wakii-app/src/index.ts +127 -0
  68. package/stack-template/app/create-wakii-app/src/options.test.ts +80 -0
  69. package/stack-template/app/create-wakii-app/src/options.ts +117 -0
  70. package/stack-template/app/create-wakii-app/src/scaffold.test.ts +143 -0
  71. package/stack-template/app/create-wakii-app/src/scaffold.ts +194 -0
  72. package/stack-template/app/create-wakii-app/tsconfig.json +17 -0
  73. package/stack-template/app/create-wakii-app/vitest.config.ts +9 -0
  74. package/stack-template/app/create-wakii-stack/package.json +27 -0
  75. package/stack-template/app/create-wakii-stack/src/manifest.ts +101 -0
  76. package/stack-template/app/create-wakii-stack/src/options.ts +106 -0
  77. package/stack-template/app/create-wakii-stack/src/scaffold.ts +315 -0
  78. package/stack-template/app/create-wakii-stack/tsconfig.json +17 -0
  79. package/stack-template/app/create-wakii-stack/vitest.config.ts +9 -0
  80. package/stack-template/app/remotes/activity/Dockerfile +36 -0
  81. package/stack-template/app/remotes/activity/README.md +59 -0
  82. package/stack-template/app/remotes/activity/index.html +11 -0
  83. package/stack-template/app/remotes/activity/nginx.conf +35 -0
  84. package/stack-template/app/remotes/activity/package.json +40 -0
  85. package/stack-template/app/remotes/activity/rspack.config.mjs +152 -0
  86. package/stack-template/app/remotes/activity/src/ActivityPage.tsx +139 -0
  87. package/stack-template/app/remotes/activity/src/api.ts +63 -0
  88. package/stack-template/app/remotes/activity/src/app.css +7 -0
  89. package/stack-template/app/remotes/activity/src/components/FeedItem.tsx +39 -0
  90. package/stack-template/app/remotes/activity/src/components/StatTile.tsx +24 -0
  91. package/stack-template/app/remotes/activity/src/components/Timeline.tsx +53 -0
  92. package/stack-template/app/remotes/activity/src/components/time.ts +30 -0
  93. package/stack-template/app/remotes/activity/src/env.d.ts +5 -0
  94. package/stack-template/app/remotes/activity/src/index.tsx +12 -0
  95. package/stack-template/app/remotes/activity/src/standalone.tsx +36 -0
  96. package/stack-template/app/remotes/activity/tests/ActivityPage.test.tsx +260 -0
  97. package/stack-template/app/remotes/activity/tests/api.test.ts +61 -0
  98. package/stack-template/app/remotes/activity/tests/setup.ts +1 -0
  99. package/stack-template/app/remotes/activity/tests/test-utils.tsx +16 -0
  100. package/stack-template/app/remotes/activity/tsconfig.json +26 -0
  101. package/stack-template/app/remotes/activity/vitest.config.ts +38 -0
  102. package/stack-template/app/remotes/tasks/Dockerfile +36 -0
  103. package/stack-template/app/remotes/tasks/README.md +59 -0
  104. package/stack-template/app/remotes/tasks/index.html +11 -0
  105. package/stack-template/app/remotes/tasks/nginx.conf +35 -0
  106. package/stack-template/app/remotes/tasks/package.json +41 -0
  107. package/stack-template/app/remotes/tasks/rspack.config.mjs +153 -0
  108. package/stack-template/app/remotes/tasks/src/TasksPage.tsx +284 -0
  109. package/stack-template/app/remotes/tasks/src/api.ts +109 -0
  110. package/stack-template/app/remotes/tasks/src/app.css +7 -0
  111. package/stack-template/app/remotes/tasks/src/components/StatusBadge.tsx +20 -0
  112. package/stack-template/app/remotes/tasks/src/components/StatusSelect.tsx +27 -0
  113. package/stack-template/app/remotes/tasks/src/components/TaskForm.tsx +74 -0
  114. package/stack-template/app/remotes/tasks/src/components/TaskItem.tsx +199 -0
  115. package/stack-template/app/remotes/tasks/src/components/TaskList.tsx +60 -0
  116. package/stack-template/app/remotes/tasks/src/components/status.ts +23 -0
  117. package/stack-template/app/remotes/tasks/src/env.d.ts +5 -0
  118. package/stack-template/app/remotes/tasks/src/index.tsx +12 -0
  119. package/stack-template/app/remotes/tasks/src/standalone.tsx +38 -0
  120. package/stack-template/app/remotes/tasks/tests/TasksPage.test.tsx +445 -0
  121. package/stack-template/app/remotes/tasks/tests/api.test.ts +159 -0
  122. package/stack-template/app/remotes/tasks/tests/setup.ts +1 -0
  123. package/stack-template/app/remotes/tasks/tests/test-utils.tsx +16 -0
  124. package/stack-template/app/remotes/tasks/tsconfig.json +26 -0
  125. package/stack-template/app/remotes/tasks/vitest.config.ts +34 -0
  126. package/stack-template/app/shared/README.md +21 -0
  127. package/stack-template/app/shared/package.json +37 -0
  128. package/stack-template/app/shared/src/api-client.ts +66 -0
  129. package/stack-template/app/shared/src/error-envelope.ts +38 -0
  130. package/stack-template/app/shared/src/index.ts +21 -0
  131. package/stack-template/app/shared/src/mf-bootstrap.ts +89 -0
  132. package/stack-template/app/shared/src/refresh-client.ts +170 -0
  133. package/stack-template/app/shared/src/token-storage.ts +57 -0
  134. package/stack-template/app/shell/Dockerfile +37 -0
  135. package/stack-template/app/shell/README.md +79 -0
  136. package/stack-template/app/shell/index.html +11 -0
  137. package/stack-template/app/shell/nginx.conf +23 -0
  138. package/stack-template/app/shell/package.json +43 -0
  139. package/stack-template/app/shell/rspack.config.mjs +147 -0
  140. package/stack-template/app/shell/src/App.tsx +57 -0
  141. package/stack-template/app/shell/src/api.ts +36 -0
  142. package/stack-template/app/shell/src/app.css +11 -0
  143. package/stack-template/app/shell/src/bootstrap.tsx +24 -0
  144. package/stack-template/app/shell/src/components/Layout.tsx +35 -0
  145. package/stack-template/app/shell/src/components/NavBar.tsx +118 -0
  146. package/stack-template/app/shell/src/components/RemoteSlot.tsx +82 -0
  147. package/stack-template/app/shell/src/components/RequireAuth.tsx +14 -0
  148. package/stack-template/app/shell/src/env.d.ts +7 -0
  149. package/stack-template/app/shell/src/index.tsx +3 -0
  150. package/stack-template/app/shell/src/pages/HomePage.tsx +70 -0
  151. package/stack-template/app/shell/src/pages/LoginPage.tsx +217 -0
  152. package/stack-template/app/shell/src/remote-urls.ts +18 -0
  153. package/stack-template/app/shell/tests/a11y.test.tsx +53 -0
  154. package/stack-template/app/shell/tests/api-timeout.test.ts +43 -0
  155. package/stack-template/app/shell/tests/integration.test.tsx +93 -0
  156. package/stack-template/app/shell/tests/login.test.tsx +227 -0
  157. package/stack-template/app/shell/tests/mf-retry.test.ts +76 -0
  158. package/stack-template/app/shell/tests/refresh-client.test.ts +301 -0
  159. package/stack-template/app/shell/tests/remote-slot.test.tsx +109 -0
  160. package/stack-template/app/shell/tests/remote-urls.test.ts +26 -0
  161. package/stack-template/app/shell/tests/setup.ts +15 -0
  162. package/stack-template/app/shell/tests/shell-chrome.test.tsx +126 -0
  163. package/stack-template/app/shell/tsconfig.json +26 -0
  164. package/stack-template/app/shell/vitest.config.ts +42 -0
  165. package/stack-template/app/spike/README.md +35 -0
  166. package/stack-template/app/spike/host/index.html +11 -0
  167. package/stack-template/app/spike/host/package.json +17 -0
  168. package/stack-template/app/spike/host/rspack.config.mjs +34 -0
  169. package/stack-template/app/spike/host/src/bootstrap.jsx +26 -0
  170. package/stack-template/app/spike/host/src/index.jsx +3 -0
  171. package/stack-template/app/spike/remote/package.json +17 -0
  172. package/stack-template/app/spike/remote/rspack.config.mjs +36 -0
  173. package/stack-template/app/spike/remote/src/Hello.jsx +7 -0
  174. package/stack-template/app/spike/remote/src/index.js +2 -0
  175. package/stack-template/app/spike/serve.mjs +31 -0
  176. package/stack-template/app/starter-templates/template-feats/extras/carousel/src/DemoCarousel.tsx +99 -0
  177. package/stack-template/app/starter-templates/template-feats/extras/chart/src/DemoChart.tsx +84 -0
  178. package/stack-template/app/starter-templates/template-feats/extras/editor/src/DemoEditor.tsx +110 -0
  179. package/stack-template/app/starter-templates/template-feats/extras/schedule/src/DemoSchedule.tsx +81 -0
  180. package/stack-template/app/starter-templates/template-feats/router/src/App.tsx +332 -0
  181. package/stack-template/app/starter-templates/template-feats/router/src/main.tsx +14 -0
  182. package/stack-template/app/starter-templates/vite-js/README.md +72 -0
  183. package/stack-template/app/starter-templates/vite-js/index.html +12 -0
  184. package/stack-template/app/starter-templates/vite-js/jsconfig.json +10 -0
  185. package/stack-template/app/starter-templates/vite-js/package.json +22 -0
  186. package/stack-template/app/starter-templates/vite-js/src/App.jsx +158 -0
  187. package/stack-template/app/starter-templates/vite-js/src/main.jsx +10 -0
  188. package/stack-template/app/starter-templates/vite-js/src/styles.css +15 -0
  189. package/stack-template/app/starter-templates/vite-js/src/theme.js +21 -0
  190. package/stack-template/app/starter-templates/vite-js/vite.config.mjs +8 -0
  191. package/stack-template/app/starter-templates/vite-ts/README.md +53 -0
  192. package/stack-template/app/starter-templates/vite-ts/index.html +12 -0
  193. package/stack-template/app/starter-templates/vite-ts/package.json +29 -0
  194. package/stack-template/app/starter-templates/vite-ts/src/App.tsx +181 -0
  195. package/stack-template/app/starter-templates/vite-ts/src/main.tsx +12 -0
  196. package/stack-template/app/starter-templates/vite-ts/src/styles.css +21 -0
  197. package/stack-template/app/starter-templates/vite-ts/src/theme.ts +16 -0
  198. package/stack-template/app/starter-templates/vite-ts/tsconfig.json +25 -0
  199. package/stack-template/app/starter-templates/vite-ts/tsconfig.node.json +11 -0
  200. package/stack-template/app/starter-templates/vite-ts/vite.config.ts +10 -0
  201. package/stack-template/app/ui-kit/.storybook/main.ts +29 -0
  202. package/stack-template/app/ui-kit/.storybook/manager-head.html +97 -0
  203. package/stack-template/app/ui-kit/.storybook/manager.ts +138 -0
  204. package/stack-template/app/ui-kit/.storybook/preview-head.html +57 -0
  205. package/stack-template/app/ui-kit/.storybook/preview.ts +62 -0
  206. package/stack-template/app/ui-kit/.storybook/tailwind-preview.css +3 -0
  207. package/stack-template/app/ui-kit/.storybook/test-runner.config.ts +20 -0
  208. package/stack-template/app/ui-kit/CHANGELOG.md +137 -0
  209. package/stack-template/app/ui-kit/LICENSE +21 -0
  210. package/stack-template/app/ui-kit/MIGRATION.md +84 -0
  211. package/stack-template/app/ui-kit/README.md +173 -0
  212. package/stack-template/app/ui-kit/RELEASE.md +77 -0
  213. package/stack-template/app/ui-kit/USAGE.md +380 -0
  214. package/stack-template/app/ui-kit/eslint.config.js +47 -0
  215. package/stack-template/app/ui-kit/package.json +166 -0
  216. package/stack-template/app/ui-kit/scripts/publish-github.sh +39 -0
  217. package/stack-template/app/ui-kit/scripts/publish-npm.sh +76 -0
  218. package/stack-template/app/ui-kit/scripts/stamp-build.cjs +13 -0
  219. package/stack-template/app/ui-kit/src/KitchenSink.stories.tsx +576 -0
  220. package/stack-template/app/ui-kit/src/Tokens.stories.tsx +193 -0
  221. package/stack-template/app/ui-kit/src/entries/carousel.ts +7 -0
  222. package/stack-template/app/ui-kit/src/entries/chart.ts +4 -0
  223. package/stack-template/app/ui-kit/src/entries/editor.ts +4 -0
  224. package/stack-template/app/ui-kit/src/entries/experience3d.ts +5 -0
  225. package/stack-template/app/ui-kit/src/entries/schedule.ts +5 -0
  226. package/stack-template/app/ui-kit/src/env.d.ts +3 -0
  227. package/stack-template/app/ui-kit/src/hooks/form.stories.tsx +80 -0
  228. package/stack-template/app/ui-kit/src/hooks/hooks-new.stories.tsx +392 -0
  229. package/stack-template/app/ui-kit/src/hooks/hooks.stories.tsx +167 -0
  230. package/stack-template/app/ui-kit/src/hooks/useClickAway.test.tsx +63 -0
  231. package/stack-template/app/ui-kit/src/hooks/useClickAway.ts +30 -0
  232. package/stack-template/app/ui-kit/src/hooks/useControllableState.test.ts +36 -0
  233. package/stack-template/app/ui-kit/src/hooks/useControllableState.ts +41 -0
  234. package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.test.ts +89 -0
  235. package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.ts +20 -0
  236. package/stack-template/app/ui-kit/src/hooks/useCountdown.test.ts +88 -0
  237. package/stack-template/app/ui-kit/src/hooks/useCountdown.ts +38 -0
  238. package/stack-template/app/ui-kit/src/hooks/useDebounce.test.ts +71 -0
  239. package/stack-template/app/ui-kit/src/hooks/useDebounce.ts +14 -0
  240. package/stack-template/app/ui-kit/src/hooks/useDefault.test.ts +37 -0
  241. package/stack-template/app/ui-kit/src/hooks/useDefault.ts +15 -0
  242. package/stack-template/app/ui-kit/src/hooks/useEventListener.test.ts +47 -0
  243. package/stack-template/app/ui-kit/src/hooks/useEventListener.ts +28 -0
  244. package/stack-template/app/ui-kit/src/hooks/useFieldArray.test.tsx +160 -0
  245. package/stack-template/app/ui-kit/src/hooks/useFieldArray.ts +85 -0
  246. package/stack-template/app/ui-kit/src/hooks/useFocusTrap.ts +67 -0
  247. package/stack-template/app/ui-kit/src/hooks/useForm.test.tsx +192 -0
  248. package/stack-template/app/ui-kit/src/hooks/useForm.ts +119 -0
  249. package/stack-template/app/ui-kit/src/hooks/useFullscreen.test.tsx +71 -0
  250. package/stack-template/app/ui-kit/src/hooks/useFullscreen.ts +68 -0
  251. package/stack-template/app/ui-kit/src/hooks/useHover.test.tsx +30 -0
  252. package/stack-template/app/ui-kit/src/hooks/useHover.ts +23 -0
  253. package/stack-template/app/ui-kit/src/hooks/useInView.test.tsx +70 -0
  254. package/stack-template/app/ui-kit/src/hooks/useInView.ts +55 -0
  255. package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.test.tsx +72 -0
  256. package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.ts +45 -0
  257. package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.test.ts +30 -0
  258. package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.ts +14 -0
  259. package/stack-template/app/ui-kit/src/hooks/useKeyPress.test.ts +45 -0
  260. package/stack-template/app/ui-kit/src/hooks/useKeyPress.ts +31 -0
  261. package/stack-template/app/ui-kit/src/hooks/useLocalStorage.test.ts +102 -0
  262. package/stack-template/app/ui-kit/src/hooks/useLocalStorage.ts +34 -0
  263. package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.test.ts +42 -0
  264. package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.ts +13 -0
  265. package/stack-template/app/ui-kit/src/hooks/useMeasure.test.tsx +57 -0
  266. package/stack-template/app/ui-kit/src/hooks/useMeasure.ts +32 -0
  267. package/stack-template/app/ui-kit/src/hooks/useMediaQuery.test.ts +73 -0
  268. package/stack-template/app/ui-kit/src/hooks/useMediaQuery.ts +20 -0
  269. package/stack-template/app/ui-kit/src/hooks/useMountEffect.test.ts +22 -0
  270. package/stack-template/app/ui-kit/src/hooks/useMountEffect.ts +10 -0
  271. package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.test.ts +36 -0
  272. package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.ts +21 -0
  273. package/stack-template/app/ui-kit/src/hooks/usePrevious.test.ts +35 -0
  274. package/stack-template/app/ui-kit/src/hooks/usePrevious.ts +13 -0
  275. package/stack-template/app/ui-kit/src/hooks/useScrollProgress.test.ts +59 -0
  276. package/stack-template/app/ui-kit/src/hooks/useScrollProgress.ts +31 -0
  277. package/stack-template/app/ui-kit/src/hooks/useSessionStorage.test.ts +80 -0
  278. package/stack-template/app/ui-kit/src/hooks/useSessionStorage.ts +34 -0
  279. package/stack-template/app/ui-kit/src/hooks/useThrottle.test.ts +61 -0
  280. package/stack-template/app/ui-kit/src/hooks/useThrottle.ts +30 -0
  281. package/stack-template/app/ui-kit/src/hooks/useTimeout.test.ts +95 -0
  282. package/stack-template/app/ui-kit/src/hooks/useTimeout.ts +38 -0
  283. package/stack-template/app/ui-kit/src/hooks/useTitle.test.ts +34 -0
  284. package/stack-template/app/ui-kit/src/hooks/useTitle.ts +24 -0
  285. package/stack-template/app/ui-kit/src/hooks/useToggle.test.ts +46 -0
  286. package/stack-template/app/ui-kit/src/hooks/useToggle.ts +16 -0
  287. package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.test.ts +25 -0
  288. package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.ts +18 -0
  289. package/stack-template/app/ui-kit/src/hooks/useWindowSize.test.ts +33 -0
  290. package/stack-template/app/ui-kit/src/hooks/useWindowSize.ts +23 -0
  291. package/stack-template/app/ui-kit/src/index.ts +218 -0
  292. package/stack-template/app/ui-kit/src/intro-showcase.stories.tsx +272 -0
  293. package/stack-template/app/ui-kit/src/intro.docs.mdx +247 -0
  294. package/stack-template/app/ui-kit/src/motion/motion-showcase.stories.tsx +234 -0
  295. package/stack-template/app/ui-kit/src/motion/motion.md +38 -0
  296. package/stack-template/app/ui-kit/src/provider/index.tsx +77 -0
  297. package/stack-template/app/ui-kit/src/provider/provider.stories.tsx +87 -0
  298. package/stack-template/app/ui-kit/src/provider/provider.test.tsx +121 -0
  299. package/stack-template/app/ui-kit/src/styles/base.css +171 -0
  300. package/stack-template/app/ui-kit/src/styles/dark-theme.test.ts +21 -0
  301. package/stack-template/app/ui-kit/src/styles/tailwind.css +220 -0
  302. package/stack-template/app/ui-kit/src/styles/themes/dark.css +71 -0
  303. package/stack-template/app/ui-kit/src/styles/tokens.css +133 -0
  304. package/stack-template/app/ui-kit/src/styles/ui-kit.css +10 -0
  305. package/stack-template/app/ui-kit/src/templates/auth.stories.tsx +425 -0
  306. package/stack-template/app/ui-kit/src/templates/crud.stories.tsx +416 -0
  307. package/stack-template/app/ui-kit/src/templates/dashboard.stories.tsx +504 -0
  308. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch1-deep-focus.tsx +96 -0
  309. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch2-living-docs.tsx +134 -0
  310. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch3-team-velocity.tsx +148 -0
  311. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch4-ship-your-app.tsx +100 -0
  312. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch5-future.tsx +67 -0
  313. package/stack-template/app/ui-kit/src/templates/experience/chapters/hero.tsx +434 -0
  314. package/stack-template/app/ui-kit/src/templates/experience/chapters/nav-footer.tsx +85 -0
  315. package/stack-template/app/ui-kit/src/templates/experience/hero.stories.tsx +27 -0
  316. package/stack-template/app/ui-kit/src/templates/experience/hero.test.tsx +108 -0
  317. package/stack-template/app/ui-kit/src/templates/experience/index.stories.tsx +51 -0
  318. package/stack-template/app/ui-kit/src/templates/experience/lib/ChapterShell.tsx +84 -0
  319. package/stack-template/app/ui-kit/src/templates/experience/lib/SideNav.tsx +173 -0
  320. package/stack-template/app/ui-kit/src/templates/experience/lib/chapter-shell.test.tsx +266 -0
  321. package/stack-template/app/ui-kit/src/templates/experience/lib/scroll-mood.tsx +143 -0
  322. package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.test.tsx +31 -0
  323. package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.tsx +190 -0
  324. package/stack-template/app/ui-kit/src/templates/experience/mood-engine.stories.tsx +114 -0
  325. package/stack-template/app/ui-kit/src/templates/experience/shell-nav.stories.tsx +113 -0
  326. package/stack-template/app/ui-kit/src/templates/kanban-project.stories.tsx +352 -0
  327. package/stack-template/app/ui-kit/src/templates/landing.stories.tsx +380 -0
  328. package/stack-template/app/ui-kit/src/templates/parallax-landing.stories.tsx +633 -0
  329. package/stack-template/app/ui-kit/src/templates/settings.stories.tsx +474 -0
  330. package/stack-template/app/ui-kit/src/ui/accordion/accordion.stories.tsx +91 -0
  331. package/stack-template/app/ui-kit/src/ui/accordion/accordion.test.tsx +99 -0
  332. package/stack-template/app/ui-kit/src/ui/accordion/index.tsx +107 -0
  333. package/stack-template/app/ui-kit/src/ui/affix/affix.stories.tsx +104 -0
  334. package/stack-template/app/ui-kit/src/ui/affix/affix.test.tsx +138 -0
  335. package/stack-template/app/ui-kit/src/ui/affix/index.tsx +89 -0
  336. package/stack-template/app/ui-kit/src/ui/alert/alert.stories.tsx +149 -0
  337. package/stack-template/app/ui-kit/src/ui/alert/alert.test.tsx +85 -0
  338. package/stack-template/app/ui-kit/src/ui/alert/index.tsx +118 -0
  339. package/stack-template/app/ui-kit/src/ui/anchor/anchor.stories.tsx +96 -0
  340. package/stack-template/app/ui-kit/src/ui/anchor/anchor.test.tsx +191 -0
  341. package/stack-template/app/ui-kit/src/ui/anchor/index.tsx +144 -0
  342. package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.stories.tsx +67 -0
  343. package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.test.tsx +94 -0
  344. package/stack-template/app/ui-kit/src/ui/auto-complete/index.tsx +54 -0
  345. package/stack-template/app/ui-kit/src/ui/avatar/avatar.stories.tsx +132 -0
  346. package/stack-template/app/ui-kit/src/ui/avatar/avatar.test.tsx +65 -0
  347. package/stack-template/app/ui-kit/src/ui/avatar/index.tsx +48 -0
  348. package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.stories.tsx +113 -0
  349. package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.test.tsx +71 -0
  350. package/stack-template/app/ui-kit/src/ui/avatar-group/index.tsx +66 -0
  351. package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.stories.tsx +66 -0
  352. package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.test.tsx +37 -0
  353. package/stack-template/app/ui-kit/src/ui/backdrop/index.tsx +29 -0
  354. package/stack-template/app/ui-kit/src/ui/badge/badge.stories.tsx +105 -0
  355. package/stack-template/app/ui-kit/src/ui/badge/badge.test.tsx +115 -0
  356. package/stack-template/app/ui-kit/src/ui/badge/index.tsx +154 -0
  357. package/stack-template/app/ui-kit/src/ui/blockui/blockui.stories.tsx +34 -0
  358. package/stack-template/app/ui-kit/src/ui/blockui/blockui.test.tsx +29 -0
  359. package/stack-template/app/ui-kit/src/ui/blockui/index.tsx +25 -0
  360. package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.stories.tsx +70 -0
  361. package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.test.tsx +68 -0
  362. package/stack-template/app/ui-kit/src/ui/bottom-navigation/index.tsx +82 -0
  363. package/stack-template/app/ui-kit/src/ui/branch-fill.test.tsx +245 -0
  364. package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.stories.tsx +103 -0
  365. package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.test.tsx +49 -0
  366. package/stack-template/app/ui-kit/src/ui/breadcrumb/index.tsx +37 -0
  367. package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.stories.tsx +30 -0
  368. package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.test.tsx +29 -0
  369. package/stack-template/app/ui-kit/src/ui/busy-box/index.tsx +25 -0
  370. package/stack-template/app/ui-kit/src/ui/button/button.stories.tsx +121 -0
  371. package/stack-template/app/ui-kit/src/ui/button/button.test.tsx +207 -0
  372. package/stack-template/app/ui-kit/src/ui/button/index.tsx +128 -0
  373. package/stack-template/app/ui-kit/src/ui/calendar/calendar.stories.tsx +100 -0
  374. package/stack-template/app/ui-kit/src/ui/calendar/calendar.test.tsx +92 -0
  375. package/stack-template/app/ui-kit/src/ui/calendar/index.tsx +163 -0
  376. package/stack-template/app/ui-kit/src/ui/card/card.stories.tsx +203 -0
  377. package/stack-template/app/ui-kit/src/ui/card/card.test.tsx +135 -0
  378. package/stack-template/app/ui-kit/src/ui/card/index.tsx +84 -0
  379. package/stack-template/app/ui-kit/src/ui/carousel/carousel.stories.tsx +533 -0
  380. package/stack-template/app/ui-kit/src/ui/carousel/carousel.test.tsx +148 -0
  381. package/stack-template/app/ui-kit/src/ui/carousel/index.tsx +195 -0
  382. package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.stories.tsx +126 -0
  383. package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.test.tsx +132 -0
  384. package/stack-template/app/ui-kit/src/ui/cascade-select/index.tsx +87 -0
  385. package/stack-template/app/ui-kit/src/ui/chart/chart-theme.test.tsx +79 -0
  386. package/stack-template/app/ui-kit/src/ui/chart/chart.stories.tsx +278 -0
  387. package/stack-template/app/ui-kit/src/ui/chart/chart.test.tsx +103 -0
  388. package/stack-template/app/ui-kit/src/ui/chart/index.tsx +172 -0
  389. package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.stories.tsx +67 -0
  390. package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.test.tsx +99 -0
  391. package/stack-template/app/ui-kit/src/ui/checkbox/index.tsx +52 -0
  392. package/stack-template/app/ui-kit/src/ui/chips/chips.stories.tsx +53 -0
  393. package/stack-template/app/ui-kit/src/ui/chips/chips.test.tsx +86 -0
  394. package/stack-template/app/ui-kit/src/ui/chips/index.tsx +44 -0
  395. package/stack-template/app/ui-kit/src/ui/collapse/collapse.stories.tsx +93 -0
  396. package/stack-template/app/ui-kit/src/ui/collapse/collapse.test.tsx +128 -0
  397. package/stack-template/app/ui-kit/src/ui/collapse/index.tsx +75 -0
  398. package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.stories.tsx +48 -0
  399. package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.test.tsx +68 -0
  400. package/stack-template/app/ui-kit/src/ui/color-picker/index.tsx +38 -0
  401. package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.stories.tsx +73 -0
  402. package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.test.tsx +93 -0
  403. package/stack-template/app/ui-kit/src/ui/context-menu/index.tsx +79 -0
  404. package/stack-template/app/ui-kit/src/ui/count-up/count-up.stories.tsx +80 -0
  405. package/stack-template/app/ui-kit/src/ui/count-up/count-up.test.tsx +121 -0
  406. package/stack-template/app/ui-kit/src/ui/count-up/index.tsx +70 -0
  407. package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.stories.tsx +154 -0
  408. package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.test.tsx +221 -0
  409. package/stack-template/app/ui-kit/src/ui/date-picker/index.tsx +287 -0
  410. package/stack-template/app/ui-kit/src/ui/date-picker/locale-constants.ts +90 -0
  411. package/stack-template/app/ui-kit/src/ui/date-picker/locale.tsx +15 -0
  412. package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.stories.tsx +62 -0
  413. package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.test.tsx +94 -0
  414. package/stack-template/app/ui-kit/src/ui/deferred-content/index.tsx +61 -0
  415. package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.stories.tsx +114 -0
  416. package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.test.tsx +75 -0
  417. package/stack-template/app/ui-kit/src/ui/descriptions/index.tsx +48 -0
  418. package/stack-template/app/ui-kit/src/ui/divider/divider.stories.tsx +66 -0
  419. package/stack-template/app/ui-kit/src/ui/divider/divider.test.tsx +83 -0
  420. package/stack-template/app/ui-kit/src/ui/divider/index.tsx +65 -0
  421. package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.stories.tsx +145 -0
  422. package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.test.tsx +352 -0
  423. package/stack-template/app/ui-kit/src/ui/drag-drop/index.tsx +456 -0
  424. package/stack-template/app/ui-kit/src/ui/drawer/drawer.stories.tsx +108 -0
  425. package/stack-template/app/ui-kit/src/ui/drawer/drawer.test.tsx +132 -0
  426. package/stack-template/app/ui-kit/src/ui/drawer/index.tsx +113 -0
  427. package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.stories.tsx +61 -0
  428. package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.test.tsx +101 -0
  429. package/stack-template/app/ui-kit/src/ui/dropdown/index.tsx +162 -0
  430. package/stack-template/app/ui-kit/src/ui/editor/EditorInner.tsx +93 -0
  431. package/stack-template/app/ui-kit/src/ui/editor/editor.stories.tsx +37 -0
  432. package/stack-template/app/ui-kit/src/ui/editor/editor.test.tsx +84 -0
  433. package/stack-template/app/ui-kit/src/ui/editor/index.tsx +58 -0
  434. package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.stories.tsx +24 -0
  435. package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.test.tsx +48 -0
  436. package/stack-template/app/ui-kit/src/ui/empty-state/index.tsx +22 -0
  437. package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.stories.tsx +66 -0
  438. package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.test.tsx +50 -0
  439. package/stack-template/app/ui-kit/src/ui/experience3d/index.tsx +457 -0
  440. package/stack-template/app/ui-kit/src/ui/field/field-array.stories.tsx +214 -0
  441. package/stack-template/app/ui-kit/src/ui/field/field.stories.tsx +158 -0
  442. package/stack-template/app/ui-kit/src/ui/field/field.test.tsx +68 -0
  443. package/stack-template/app/ui-kit/src/ui/field/index.tsx +48 -0
  444. package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.stories.tsx +49 -0
  445. package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.test.tsx +88 -0
  446. package/stack-template/app/ui-kit/src/ui/fieldset/index.tsx +62 -0
  447. package/stack-template/app/ui-kit/src/ui/flex/flex.stories.tsx +96 -0
  448. package/stack-template/app/ui-kit/src/ui/flex/flex.test.tsx +79 -0
  449. package/stack-template/app/ui-kit/src/ui/flex/index.tsx +45 -0
  450. package/stack-template/app/ui-kit/src/ui/float-button/float-button.stories.tsx +82 -0
  451. package/stack-template/app/ui-kit/src/ui/float-button/float-button.test.tsx +107 -0
  452. package/stack-template/app/ui-kit/src/ui/float-button/index.tsx +124 -0
  453. package/stack-template/app/ui-kit/src/ui/galleria/galleria.stories.tsx +78 -0
  454. package/stack-template/app/ui-kit/src/ui/galleria/galleria.test.tsx +67 -0
  455. package/stack-template/app/ui-kit/src/ui/galleria/index.tsx +47 -0
  456. package/stack-template/app/ui-kit/src/ui/grid/grid.stories.tsx +179 -0
  457. package/stack-template/app/ui-kit/src/ui/grid/grid.test.tsx +286 -0
  458. package/stack-template/app/ui-kit/src/ui/grid/index.tsx +104 -0
  459. package/stack-template/app/ui-kit/src/ui/icons/icons.stories.tsx +52 -0
  460. package/stack-template/app/ui-kit/src/ui/icons/icons.test.tsx +60 -0
  461. package/stack-template/app/ui-kit/src/ui/icons/index.tsx +294 -0
  462. package/stack-template/app/ui-kit/src/ui/image/image.stories.tsx +231 -0
  463. package/stack-template/app/ui-kit/src/ui/image/image.test.tsx +79 -0
  464. package/stack-template/app/ui-kit/src/ui/image/index.tsx +76 -0
  465. package/stack-template/app/ui-kit/src/ui/inplace/index.tsx +33 -0
  466. package/stack-template/app/ui-kit/src/ui/inplace/inplace.stories.tsx +75 -0
  467. package/stack-template/app/ui-kit/src/ui/inplace/inplace.test.tsx +58 -0
  468. package/stack-template/app/ui-kit/src/ui/input/index.tsx +133 -0
  469. package/stack-template/app/ui-kit/src/ui/input/input-search.stories.tsx +112 -0
  470. package/stack-template/app/ui-kit/src/ui/input/input-search.test.tsx +116 -0
  471. package/stack-template/app/ui-kit/src/ui/input/input-search.tsx +116 -0
  472. package/stack-template/app/ui-kit/src/ui/input/input.stories.tsx +176 -0
  473. package/stack-template/app/ui-kit/src/ui/input/input.test.tsx +106 -0
  474. package/stack-template/app/ui-kit/src/ui/input-mask/index.tsx +39 -0
  475. package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.stories.tsx +46 -0
  476. package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.test.tsx +57 -0
  477. package/stack-template/app/ui-kit/src/ui/input-number/index.tsx +125 -0
  478. package/stack-template/app/ui-kit/src/ui/input-number/input-number.stories.tsx +190 -0
  479. package/stack-template/app/ui-kit/src/ui/input-number/input-number.test.tsx +157 -0
  480. package/stack-template/app/ui-kit/src/ui/input-otp/index.tsx +57 -0
  481. package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.stories.tsx +90 -0
  482. package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.test.tsx +66 -0
  483. package/stack-template/app/ui-kit/src/ui/kanban/index.tsx +277 -0
  484. package/stack-template/app/ui-kit/src/ui/kanban/kanban.stories.tsx +219 -0
  485. package/stack-template/app/ui-kit/src/ui/kanban/kanban.test.tsx +234 -0
  486. package/stack-template/app/ui-kit/src/ui/knob/index.tsx +58 -0
  487. package/stack-template/app/ui-kit/src/ui/knob/knob.stories.tsx +49 -0
  488. package/stack-template/app/ui-kit/src/ui/knob/knob.test.tsx +42 -0
  489. package/stack-template/app/ui-kit/src/ui/layout/index.tsx +145 -0
  490. package/stack-template/app/ui-kit/src/ui/layout/layout.stories.tsx +158 -0
  491. package/stack-template/app/ui-kit/src/ui/layout/layout.test.tsx +154 -0
  492. package/stack-template/app/ui-kit/src/ui/link/index.tsx +61 -0
  493. package/stack-template/app/ui-kit/src/ui/link/link.stories.tsx +68 -0
  494. package/stack-template/app/ui-kit/src/ui/link/link.test.tsx +69 -0
  495. package/stack-template/app/ui-kit/src/ui/list/index.tsx +135 -0
  496. package/stack-template/app/ui-kit/src/ui/list/list.stories.tsx +194 -0
  497. package/stack-template/app/ui-kit/src/ui/list/list.test.tsx +164 -0
  498. package/stack-template/app/ui-kit/src/ui/listbox/index.tsx +27 -0
  499. package/stack-template/app/ui-kit/src/ui/listbox/listbox.stories.tsx +57 -0
  500. package/stack-template/app/ui-kit/src/ui/listbox/listbox.test.tsx +49 -0
  501. package/stack-template/app/ui-kit/src/ui/mega-menu/index.tsx +142 -0
  502. package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.stories.tsx +137 -0
  503. package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.test.tsx +130 -0
  504. package/stack-template/app/ui-kit/src/ui/mention/index.tsx +76 -0
  505. package/stack-template/app/ui-kit/src/ui/mention/mention.stories.tsx +44 -0
  506. package/stack-template/app/ui-kit/src/ui/mention/mention.test.tsx +87 -0
  507. package/stack-template/app/ui-kit/src/ui/menu/index.tsx +256 -0
  508. package/stack-template/app/ui-kit/src/ui/menu/menu.stories.tsx +124 -0
  509. package/stack-template/app/ui-kit/src/ui/menu/menu.test.tsx +251 -0
  510. package/stack-template/app/ui-kit/src/ui/menubar/index.tsx +42 -0
  511. package/stack-template/app/ui-kit/src/ui/menubar/menubar.stories.tsx +66 -0
  512. package/stack-template/app/ui-kit/src/ui/menubar/menubar.test.tsx +65 -0
  513. package/stack-template/app/ui-kit/src/ui/message/index.tsx +123 -0
  514. package/stack-template/app/ui-kit/src/ui/message/message.stories.tsx +104 -0
  515. package/stack-template/app/ui-kit/src/ui/message/message.test.tsx +109 -0
  516. package/stack-template/app/ui-kit/src/ui/modal/index.tsx +142 -0
  517. package/stack-template/app/ui-kit/src/ui/modal/modal.stories.tsx +128 -0
  518. package/stack-template/app/ui-kit/src/ui/modal/modal.test.tsx +166 -0
  519. package/stack-template/app/ui-kit/src/ui/notification/index.tsx +142 -0
  520. package/stack-template/app/ui-kit/src/ui/notification/notification.stories.tsx +155 -0
  521. package/stack-template/app/ui-kit/src/ui/notification/notification.test.tsx +83 -0
  522. package/stack-template/app/ui-kit/src/ui/order-list/index.tsx +38 -0
  523. package/stack-template/app/ui-kit/src/ui/order-list/order-list.stories.tsx +38 -0
  524. package/stack-template/app/ui-kit/src/ui/order-list/order-list.test.tsx +54 -0
  525. package/stack-template/app/ui-kit/src/ui/org-chart/index.tsx +138 -0
  526. package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.stories.tsx +76 -0
  527. package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.test.tsx +98 -0
  528. package/stack-template/app/ui-kit/src/ui/pagination/index.tsx +102 -0
  529. package/stack-template/app/ui-kit/src/ui/pagination/pagination.stories.tsx +103 -0
  530. package/stack-template/app/ui-kit/src/ui/pagination/pagination.test.tsx +112 -0
  531. package/stack-template/app/ui-kit/src/ui/panel-menu/index.tsx +59 -0
  532. package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.stories.tsx +96 -0
  533. package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.test.tsx +64 -0
  534. package/stack-template/app/ui-kit/src/ui/parallax/index.tsx +62 -0
  535. package/stack-template/app/ui-kit/src/ui/parallax/parallax.stories.tsx +115 -0
  536. package/stack-template/app/ui-kit/src/ui/parallax/parallax.test.tsx +148 -0
  537. package/stack-template/app/ui-kit/src/ui/password/index.tsx +67 -0
  538. package/stack-template/app/ui-kit/src/ui/password/password.stories.tsx +43 -0
  539. package/stack-template/app/ui-kit/src/ui/password/password.test.tsx +45 -0
  540. package/stack-template/app/ui-kit/src/ui/pick-list/index.tsx +103 -0
  541. package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.stories.tsx +59 -0
  542. package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.test.tsx +94 -0
  543. package/stack-template/app/ui-kit/src/ui/popconfirm/index.tsx +102 -0
  544. package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.stories.tsx +73 -0
  545. package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.test.tsx +127 -0
  546. package/stack-template/app/ui-kit/src/ui/popover/index.tsx +136 -0
  547. package/stack-template/app/ui-kit/src/ui/popover/popover.stories.tsx +114 -0
  548. package/stack-template/app/ui-kit/src/ui/popover/popover.test.tsx +172 -0
  549. package/stack-template/app/ui-kit/src/ui/progress/index.tsx +46 -0
  550. package/stack-template/app/ui-kit/src/ui/progress/progress.stories.tsx +57 -0
  551. package/stack-template/app/ui-kit/src/ui/progress/progress.test.tsx +90 -0
  552. package/stack-template/app/ui-kit/src/ui/qr-code/index.tsx +88 -0
  553. package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.stories.tsx +109 -0
  554. package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.test.tsx +155 -0
  555. package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-core.ts +56 -0
  556. package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-generator.vendor.ts +2300 -0
  557. package/stack-template/app/ui-kit/src/ui/radio/index.tsx +62 -0
  558. package/stack-template/app/ui-kit/src/ui/radio/radio.stories.tsx +94 -0
  559. package/stack-template/app/ui-kit/src/ui/radio/radio.test.tsx +83 -0
  560. package/stack-template/app/ui-kit/src/ui/rating/index.tsx +36 -0
  561. package/stack-template/app/ui-kit/src/ui/rating/rating.stories.tsx +42 -0
  562. package/stack-template/app/ui-kit/src/ui/rating/rating.test.tsx +45 -0
  563. package/stack-template/app/ui-kit/src/ui/result/index.tsx +72 -0
  564. package/stack-template/app/ui-kit/src/ui/result/result.stories.tsx +82 -0
  565. package/stack-template/app/ui-kit/src/ui/result/result.test.tsx +57 -0
  566. package/stack-template/app/ui-kit/src/ui/reveal/index.tsx +83 -0
  567. package/stack-template/app/ui-kit/src/ui/reveal/reveal.stories.tsx +91 -0
  568. package/stack-template/app/ui-kit/src/ui/reveal/reveal.test.tsx +148 -0
  569. package/stack-template/app/ui-kit/src/ui/schedule/index.tsx +104 -0
  570. package/stack-template/app/ui-kit/src/ui/schedule/schedule.fc.test.tsx +95 -0
  571. package/stack-template/app/ui-kit/src/ui/schedule/schedule.stories.tsx +61 -0
  572. package/stack-template/app/ui-kit/src/ui/schedule/schedule.test.tsx +41 -0
  573. package/stack-template/app/ui-kit/src/ui/scroll-page/index.tsx +46 -0
  574. package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.stories.tsx +92 -0
  575. package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.test.tsx +51 -0
  576. package/stack-template/app/ui-kit/src/ui/scroll-panel/index.tsx +16 -0
  577. package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.stories.tsx +37 -0
  578. package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.test.tsx +41 -0
  579. package/stack-template/app/ui-kit/src/ui/scrolltop/index.tsx +27 -0
  580. package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.stories.tsx +41 -0
  581. package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.test.tsx +37 -0
  582. package/stack-template/app/ui-kit/src/ui/segmented/index.tsx +47 -0
  583. package/stack-template/app/ui-kit/src/ui/segmented/segmented.stories.tsx +126 -0
  584. package/stack-template/app/ui-kit/src/ui/segmented/segmented.test.tsx +77 -0
  585. package/stack-template/app/ui-kit/src/ui/select/index.tsx +302 -0
  586. package/stack-template/app/ui-kit/src/ui/select/select.stories.tsx +268 -0
  587. package/stack-template/app/ui-kit/src/ui/select/select.test.tsx +226 -0
  588. package/stack-template/app/ui-kit/src/ui/sidebar/index.tsx +83 -0
  589. package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.stories.tsx +71 -0
  590. package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.test.tsx +101 -0
  591. package/stack-template/app/ui-kit/src/ui/skeleton/index.tsx +55 -0
  592. package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.stories.tsx +110 -0
  593. package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.test.tsx +74 -0
  594. package/stack-template/app/ui-kit/src/ui/slide-menu/index.tsx +103 -0
  595. package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.stories.tsx +92 -0
  596. package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.test.tsx +120 -0
  597. package/stack-template/app/ui-kit/src/ui/slider/index.tsx +90 -0
  598. package/stack-template/app/ui-kit/src/ui/slider/slider.stories.tsx +60 -0
  599. package/stack-template/app/ui-kit/src/ui/slider/slider.test.tsx +66 -0
  600. package/stack-template/app/ui-kit/src/ui/space/index.tsx +32 -0
  601. package/stack-template/app/ui-kit/src/ui/space/space.stories.tsx +66 -0
  602. package/stack-template/app/ui-kit/src/ui/space/space.test.tsx +56 -0
  603. package/stack-template/app/ui-kit/src/ui/speed-dial/index.tsx +32 -0
  604. package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.stories.tsx +34 -0
  605. package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.test.tsx +34 -0
  606. package/stack-template/app/ui-kit/src/ui/spinner/index.tsx +74 -0
  607. package/stack-template/app/ui-kit/src/ui/spinner/spinner.stories.tsx +64 -0
  608. package/stack-template/app/ui-kit/src/ui/spinner/spinner.test.tsx +66 -0
  609. package/stack-template/app/ui-kit/src/ui/split-button/index.tsx +155 -0
  610. package/stack-template/app/ui-kit/src/ui/split-button/split-button.stories.tsx +137 -0
  611. package/stack-template/app/ui-kit/src/ui/split-button/split-button.test.tsx +152 -0
  612. package/stack-template/app/ui-kit/src/ui/splitter/index.tsx +49 -0
  613. package/stack-template/app/ui-kit/src/ui/splitter/splitter.stories.tsx +24 -0
  614. package/stack-template/app/ui-kit/src/ui/splitter/splitter.test.tsx +21 -0
  615. package/stack-template/app/ui-kit/src/ui/statistic/index.tsx +28 -0
  616. package/stack-template/app/ui-kit/src/ui/statistic/statistic.stories.tsx +112 -0
  617. package/stack-template/app/ui-kit/src/ui/statistic/statistic.test.tsx +39 -0
  618. package/stack-template/app/ui-kit/src/ui/steps/index.tsx +50 -0
  619. package/stack-template/app/ui-kit/src/ui/steps/steps.stories.tsx +57 -0
  620. package/stack-template/app/ui-kit/src/ui/steps/steps.test.tsx +55 -0
  621. package/stack-template/app/ui-kit/src/ui/switch/index.tsx +87 -0
  622. package/stack-template/app/ui-kit/src/ui/switch/switch.stories.tsx +123 -0
  623. package/stack-template/app/ui-kit/src/ui/switch/switch.test.tsx +98 -0
  624. package/stack-template/app/ui-kit/src/ui/tab-menu/index.tsx +33 -0
  625. package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.stories.tsx +49 -0
  626. package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.test.tsx +50 -0
  627. package/stack-template/app/ui-kit/src/ui/table/index.tsx +690 -0
  628. package/stack-template/app/ui-kit/src/ui/table/table-advanced.stories.tsx +91 -0
  629. package/stack-template/app/ui-kit/src/ui/table/table-advanced.test.tsx +188 -0
  630. package/stack-template/app/ui-kit/src/ui/table/table-expandable.stories.tsx +91 -0
  631. package/stack-template/app/ui-kit/src/ui/table/table-expandable.test.tsx +143 -0
  632. package/stack-template/app/ui-kit/src/ui/table/table.stories.tsx +342 -0
  633. package/stack-template/app/ui-kit/src/ui/table/table.test.tsx +465 -0
  634. package/stack-template/app/ui-kit/src/ui/table/types.ts +173 -0
  635. package/stack-template/app/ui-kit/src/ui/tabs/index.tsx +118 -0
  636. package/stack-template/app/ui-kit/src/ui/tabs/tabs.stories.tsx +113 -0
  637. package/stack-template/app/ui-kit/src/ui/tabs/tabs.test.tsx +77 -0
  638. package/stack-template/app/ui-kit/src/ui/tag/index.tsx +68 -0
  639. package/stack-template/app/ui-kit/src/ui/tag/tag.stories.tsx +88 -0
  640. package/stack-template/app/ui-kit/src/ui/tag/tag.test.tsx +126 -0
  641. package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.stories.tsx +52 -0
  642. package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.test.tsx +72 -0
  643. package/stack-template/app/ui-kit/src/ui/team/debt-board/index.tsx +125 -0
  644. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.stories.tsx +70 -0
  645. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.test.tsx +56 -0
  646. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/index.tsx +107 -0
  647. package/stack-template/app/ui-kit/src/ui/team/ping-feed/index.tsx +102 -0
  648. package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.stories.tsx +57 -0
  649. package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.test.tsx +60 -0
  650. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/index.tsx +60 -0
  651. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.stories.tsx +68 -0
  652. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.test.tsx +50 -0
  653. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/index.tsx +103 -0
  654. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.stories.tsx +72 -0
  655. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.test.tsx +72 -0
  656. package/stack-template/app/ui-kit/src/ui/time-picker/index.tsx +143 -0
  657. package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.stories.tsx +90 -0
  658. package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.test.tsx +64 -0
  659. package/stack-template/app/ui-kit/src/ui/timeline/index.tsx +91 -0
  660. package/stack-template/app/ui-kit/src/ui/timeline/timeline.stories.tsx +209 -0
  661. package/stack-template/app/ui-kit/src/ui/timeline/timeline.test.tsx +116 -0
  662. package/stack-template/app/ui-kit/src/ui/timesheet/index.tsx +277 -0
  663. package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.stories.tsx +97 -0
  664. package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.test.tsx +103 -0
  665. package/stack-template/app/ui-kit/src/ui/toggle-button/index.tsx +28 -0
  666. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.stories.tsx +85 -0
  667. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.test.tsx +97 -0
  668. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.tsx +81 -0
  669. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.stories.tsx +46 -0
  670. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.test.tsx +38 -0
  671. package/stack-template/app/ui-kit/src/ui/toolbar/index.tsx +18 -0
  672. package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.stories.tsx +35 -0
  673. package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.test.tsx +11 -0
  674. package/stack-template/app/ui-kit/src/ui/tooltip/index.tsx +61 -0
  675. package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.stories.tsx +81 -0
  676. package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.test.tsx +120 -0
  677. package/stack-template/app/ui-kit/src/ui/tour/index.tsx +210 -0
  678. package/stack-template/app/ui-kit/src/ui/tour/tour.stories.tsx +153 -0
  679. package/stack-template/app/ui-kit/src/ui/tour/tour.test.tsx +131 -0
  680. package/stack-template/app/ui-kit/src/ui/transition/index.tsx +377 -0
  681. package/stack-template/app/ui-kit/src/ui/transition/transition.stories.tsx +254 -0
  682. package/stack-template/app/ui-kit/src/ui/transition/transition.test.tsx +285 -0
  683. package/stack-template/app/ui-kit/src/ui/tree/index.tsx +68 -0
  684. package/stack-template/app/ui-kit/src/ui/tree/tree.stories.tsx +139 -0
  685. package/stack-template/app/ui-kit/src/ui/tree/tree.test.tsx +77 -0
  686. package/stack-template/app/ui-kit/src/ui/tree-select/index.tsx +251 -0
  687. package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.stories.tsx +105 -0
  688. package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.test.tsx +174 -0
  689. package/stack-template/app/ui-kit/src/ui/tree-table/index.tsx +229 -0
  690. package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.stories.tsx +111 -0
  691. package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.test.tsx +137 -0
  692. package/stack-template/app/ui-kit/src/ui/typography/index.tsx +124 -0
  693. package/stack-template/app/ui-kit/src/ui/typography/typography.stories.tsx +65 -0
  694. package/stack-template/app/ui-kit/src/ui/typography/typography.test.tsx +117 -0
  695. package/stack-template/app/ui-kit/src/ui/upload/index.tsx +39 -0
  696. package/stack-template/app/ui-kit/src/ui/upload/upload-core.tsx +204 -0
  697. package/stack-template/app/ui-kit/src/ui/upload/upload-dropzone.tsx +79 -0
  698. package/stack-template/app/ui-kit/src/ui/upload/upload.stories.tsx +67 -0
  699. package/stack-template/app/ui-kit/src/ui/upload/upload.test.tsx +204 -0
  700. package/stack-template/app/ui-kit/src/ui/virtual-scroll/index.tsx +86 -0
  701. package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.stories.tsx +111 -0
  702. package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.test.tsx +125 -0
  703. package/stack-template/app/ui-kit/src/ui/watermark/index.tsx +182 -0
  704. package/stack-template/app/ui-kit/src/ui/watermark/watermark.stories.tsx +96 -0
  705. package/stack-template/app/ui-kit/src/ui/watermark/watermark.test.tsx +120 -0
  706. package/stack-template/app/ui-kit/src/utils/array.test.ts +88 -0
  707. package/stack-template/app/ui-kit/src/utils/array.ts +51 -0
  708. package/stack-template/app/ui-kit/src/utils/dom.test.tsx +69 -0
  709. package/stack-template/app/ui-kit/src/utils/dom.ts +38 -0
  710. package/stack-template/app/ui-kit/src/utils/format.test.ts +63 -0
  711. package/stack-template/app/ui-kit/src/utils/format.ts +81 -0
  712. package/stack-template/app/ui-kit/tests/setup.ts +15 -0
  713. package/stack-template/app/ui-kit/tsconfig.json +18 -0
  714. package/stack-template/app/ui-kit/tsup.config.ts +37 -0
  715. package/stack-template/app/ui-kit/vercel.json +6 -0
  716. package/stack-template/app/ui-kit/vitest.config.ts +22 -0
  717. package/stack-template/contracts/auth/token-contract.md +119 -0
  718. package/stack-template/contracts/auth/users.json +35 -0
  719. package/stack-template/contracts/db/tasks-schema.sql +62 -0
  720. package/stack-template/contracts/events/fixtures/task.assigned.json +11 -0
  721. package/stack-template/contracts/events/fixtures/task.assignment_failed.json +11 -0
  722. package/stack-template/contracts/events/fixtures/task.created.json +12 -0
  723. package/stack-template/contracts/events/fixtures/task.deleted.json +10 -0
  724. package/stack-template/contracts/events/fixtures/task.updated.json +12 -0
  725. package/stack-template/contracts/events/task-events.md +80 -0
  726. package/stack-template/contracts/openapi/activity.yaml +196 -0
  727. package/stack-template/contracts/openapi/auth.yaml +310 -0
  728. package/stack-template/contracts/openapi/tasks.yaml +316 -0
  729. package/stack-template/contracts/openapi/users.yaml +345 -0
  730. package/stack-template/docs/adr/0001-mixed-stack.md +14 -0
  731. package/stack-template/docs/adr/0002-mf-rspack.md +14 -0
  732. package/stack-template/docs/adr/0003-contract-first.md +14 -0
  733. package/stack-template/docs/adr/0004-readonly-schema-tradeoff.md +14 -0
  734. package/stack-template/docs/adr/0005-fail-closed.md +14 -0
  735. package/stack-template/docs/adr/0006-fire-and-forget-events.md +14 -0
  736. package/stack-template/docs/adr/0007-fork-not-upgrade.md +14 -0
  737. package/stack-template/docs/adr/0008-kafka-outbox-saga.md +24 -0
  738. package/stack-template/docs/adr/0009-ui-kit-split.md +39 -0
  739. package/stack-template/docs/adr/README.md +15 -0
  740. package/stack-template/docs/ai/recipes.md +956 -0
  741. package/stack-template/docs/ai/table-Theming.md +25 -0
  742. package/stack-template/docs/ai/table-datadisplay-mz.md +20 -0
  743. package/stack-template/docs/ai/table-feedback.md +20 -0
  744. package/stack-template/docs/ai/table-forms.md +26 -0
  745. package/stack-template/docs/git-flow.md +70 -0
  746. package/stack-template/docs/parity-matrix.md +102 -0
  747. package/stack-template/docs/superpowers/contexts/auth-real/gap-answer.md +195 -0
  748. package/stack-template/docs/superpowers/contexts/auth-real/sf-1.md +21 -0
  749. package/stack-template/docs/superpowers/contexts/auth-real/sf-2.md +21 -0
  750. package/stack-template/docs/superpowers/contexts/auth-real/sf-3.md +17 -0
  751. package/stack-template/docs/superpowers/contexts/auth-real/sf-4.md +20 -0
  752. package/stack-template/docs/superpowers/contexts/auth-real/sf-5.md +21 -0
  753. package/stack-template/docs/superpowers/contexts/experience-design.md +85 -0
  754. package/stack-template/docs/superpowers/contexts/sf-1.md +39 -0
  755. package/stack-template/docs/superpowers/contexts/sf-2.md +42 -0
  756. package/stack-template/docs/superpowers/contexts/sf-3.md +42 -0
  757. package/stack-template/docs/superpowers/contexts/sf-4.md +26 -0
  758. package/stack-template/docs/superpowers/contexts/sf-5.md +36 -0
  759. package/stack-template/docs/superpowers/contexts/sf-6.md +36 -0
  760. package/stack-template/docs/superpowers/contexts/sf-7.md +35 -0
  761. package/stack-template/docs/superpowers/contexts/sf-cin-overview.md +21 -0
  762. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-1.md +46 -0
  763. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-2.md +44 -0
  764. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-3.md +47 -0
  765. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-4.md +44 -0
  766. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-5.md +36 -0
  767. package/stack-template/docs/superpowers/designs/direction-approved.md +11 -0
  768. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/a-roulette-soundviz.html +353 -0
  769. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/b-reference.html +347 -0
  770. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/c-designer.html +375 -0
  771. package/stack-template/docs/superpowers/designs/ui-redesign/ds-demo.html +140 -0
  772. package/stack-template/docs/superpowers/designs/ui-redesign-direction.md +93 -0
  773. package/stack-template/docs/superpowers/improvements-log.md +158 -0
  774. package/stack-template/docs/superpowers/mindmaps/auth-real.wakii +115 -0
  775. package/stack-template/docs/superpowers/mindmaps/kafka-outbox-saga.wakii +110 -0
  776. package/stack-template/docs/superpowers/mindmaps/micro-boilerplate.wakii +171 -0
  777. package/stack-template/docs/superpowers/mindmaps/ui-redesign.wakii +116 -0
  778. package/stack-template/docs/superpowers/mindmaps/vu53-cinematic-experience.wakii +32 -0
  779. package/stack-template/docs/superpowers/plans/2026-10-12-sf-1-contracts-platform-plan.md +44 -0
  780. package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-impact.md +69 -0
  781. package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-plan.md +27 -0
  782. package/stack-template/docs/superpowers/plans/2026-10-12-sf-4-go-svc-plan.md +99 -0
  783. package/stack-template/docs/superpowers/plans/2026-10-12-sf-5-fe-shell-plan.md +64 -0
  784. package/stack-template/docs/superpowers/plans/2026-10-12-sf-6-fe-remotes-plan.md +83 -0
  785. package/stack-template/docs/superpowers/plans/2026-10-12-sf-7-convergence-plan.md +59 -0
  786. package/stack-template/docs/superpowers/plans/2026-10-12-sf2-node-svc-plan.md +19 -0
  787. package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-kafka-foundation-plan.md +30 -0
  788. package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-ui-redesign-plan.md +28 -0
  789. package/stack-template/docs/superpowers/plans/2026-10-13-sf-2-node-outbox-plan.md +46 -0
  790. package/stack-template/docs/superpowers/plans/2026-10-13-sf-3-go-consumer-plan.md +31 -0
  791. package/stack-template/docs/superpowers/plans/2026-10-13-sf-4-spring-tx-plan.md +96 -0
  792. package/stack-template/docs/superpowers/plans/2026-10-13-sf-5-convergence-plan.md +21 -0
  793. package/stack-template/docs/superpowers/plans/2026-10-14-sf-2-ui-redesign-plan.md +32 -0
  794. package/stack-template/docs/superpowers/plans/2026-10-14-sf-3-ui-redesign-plan.md +34 -0
  795. package/stack-template/docs/superpowers/plans/2026-10-14-sf-5-ui-redesign-plan.md +35 -0
  796. package/stack-template/docs/superpowers/plans/2026-10-17-auth-real-plan.md +112 -0
  797. package/stack-template/docs/superpowers/plans/2026-10-17-ui-kit-split-plan.md +18 -0
  798. package/stack-template/docs/superpowers/reviews/2026-10-18-data-display-coverage.md +52 -0
  799. package/stack-template/docs/superpowers/reviews/code-reviewer-sf-5-r1.md +65 -0
  800. package/stack-template/docs/superpowers/reviews/security-audit-sf-5-auth-real.md +39 -0
  801. package/stack-template/docs/superpowers/specs/2026-10-12-boilerplate-microservice-mfe.md +110 -0
  802. package/stack-template/docs/superpowers/specs/2026-10-12-sf-3-spring-svc-design.md +160 -0
  803. package/stack-template/docs/superpowers/specs/2026-10-12-sf-7-convergence-spec.md +114 -0
  804. package/stack-template/docs/superpowers/specs/2026-10-12-sf2-node-svc-spec.md +42 -0
  805. package/stack-template/docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md +111 -0
  806. package/stack-template/docs/superpowers/specs/2026-10-13-ui-redesign.md +173 -0
  807. package/stack-template/docs/superpowers/specs/2026-10-14-sf-3-ui-redesign.md +46 -0
  808. package/stack-template/docs/superpowers/specs/2026-10-14-sf-5-ui-redesign.md +30 -0
  809. package/stack-template/docs/superpowers/specs/2026-10-17-antd-look-tokens.md +28 -0
  810. package/stack-template/docs/superpowers/specs/2026-10-17-auth-real-design.md +124 -0
  811. package/stack-template/docs/superpowers/specs/2026-10-17-tailwind-migration.md +32 -0
  812. package/stack-template/docs/superpowers/specs/2026-10-17-ui-kit-split.md +44 -0
  813. package/stack-template/docs/superpowers/specs/2026-10-18-0.3.0-release-notes.md +77 -0
  814. package/stack-template/docs/toolchain.md +28 -0
  815. package/stack-template/docs/wakii-playbook.md +172 -0
  816. package/stack-template/docs/walkthrough.md +204 -0
  817. package/stack-template/orca.yaml +146 -0
  818. package/stack-template/package.json +19 -0
  819. package/stack-template/platform/.env.example +72 -0
  820. package/stack-template/platform/conventions/01-dockerfile-pattern.md +78 -0
  821. package/stack-template/platform/conventions/02-healthcheck.md +26 -0
  822. package/stack-template/platform/conventions/03-logging.md +41 -0
  823. package/stack-template/platform/conventions/04-error-envelope.md +41 -0
  824. package/stack-template/platform/conventions/05-ports.md +38 -0
  825. package/stack-template/platform/conventions/06-configuration.md +25 -0
  826. package/stack-template/platform/conventions/07-cors.md +23 -0
  827. package/stack-template/platform/conventions/08-gateway-and-remotes.md +33 -0
  828. package/stack-template/platform/conventions/09-async-messaging.md +42 -0
  829. package/stack-template/platform/conventions/README.md +15 -0
  830. package/stack-template/platform/docker-compose.yml +255 -0
  831. package/stack-template/platform/gateway/nginx/nginx.conf +137 -0
  832. package/stack-template/platform/postgres/init/01-init.sh +55 -0
  833. package/stack-template/pnpm-lock.yaml +15992 -0
  834. package/stack-template/pnpm-workspace.yaml +24 -0
  835. package/stack-template/scripts/scaffold/scaffold.sh +110 -0
  836. package/stack-template/scripts/smoke/e2e.sh +305 -0
  837. package/stack-template/scripts/snapshot-stack-template.sh +84 -0
  838. package/stack-template/services/auth-svc/.dockerignore +5 -0
  839. package/stack-template/services/auth-svc/Dockerfile +32 -0
  840. package/stack-template/services/auth-svc/README.md +101 -0
  841. package/stack-template/services/auth-svc/drizzle/0000_init.sql +25 -0
  842. package/stack-template/services/auth-svc/drizzle/meta/0000_snapshot.json +190 -0
  843. package/stack-template/services/auth-svc/drizzle/meta/_journal.json +13 -0
  844. package/stack-template/services/auth-svc/drizzle.config.ts +10 -0
  845. package/stack-template/services/auth-svc/package.json +35 -0
  846. package/stack-template/services/auth-svc/pnpm-lock.yaml +2425 -0
  847. package/stack-template/services/auth-svc/src/app.test.ts +403 -0
  848. package/stack-template/services/auth-svc/src/app.ts +103 -0
  849. package/stack-template/services/auth-svc/src/auth-crypto.test.ts +32 -0
  850. package/stack-template/services/auth-svc/src/auth-crypto.ts +25 -0
  851. package/stack-template/services/auth-svc/src/db/client.ts +24 -0
  852. package/stack-template/services/auth-svc/src/db/migrate.ts +72 -0
  853. package/stack-template/services/auth-svc/src/db/schema.ts +39 -0
  854. package/stack-template/services/auth-svc/src/db/seed.ts +60 -0
  855. package/stack-template/services/auth-svc/src/env.test.ts +55 -0
  856. package/stack-template/services/auth-svc/src/env.ts +57 -0
  857. package/stack-template/services/auth-svc/src/logger.ts +31 -0
  858. package/stack-template/services/auth-svc/src/plugins/auth.ts +70 -0
  859. package/stack-template/services/auth-svc/src/repo.drizzle.integration.test.ts +182 -0
  860. package/stack-template/services/auth-svc/src/repo.drizzle.ts +144 -0
  861. package/stack-template/services/auth-svc/src/repo.test-support.ts +168 -0
  862. package/stack-template/services/auth-svc/src/repo.ts +60 -0
  863. package/stack-template/services/auth-svc/src/routes/auth.ts +193 -0
  864. package/stack-template/services/auth-svc/src/routes/health.ts +40 -0
  865. package/stack-template/services/auth-svc/src/server.ts +54 -0
  866. package/stack-template/services/auth-svc/tsconfig.json +20 -0
  867. package/stack-template/services/go-svc/.dockerignore +5 -0
  868. package/stack-template/services/go-svc/Dockerfile +19 -0
  869. package/stack-template/services/go-svc/README.md +93 -0
  870. package/stack-template/services/go-svc/cmd/server/main.go +105 -0
  871. package/stack-template/services/go-svc/go.mod +12 -0
  872. package/stack-template/services/go-svc/internal/api/auth.go +83 -0
  873. package/stack-template/services/go-svc/internal/api/auth_test.go +92 -0
  874. package/stack-template/services/go-svc/internal/api/envelope.go +61 -0
  875. package/stack-template/services/go-svc/internal/api/envelope_test.go +51 -0
  876. package/stack-template/services/go-svc/internal/api/fakes_test.go +105 -0
  877. package/stack-template/services/go-svc/internal/api/feed.go +98 -0
  878. package/stack-template/services/go-svc/internal/api/feed_test.go +118 -0
  879. package/stack-template/services/go-svc/internal/api/health.go +34 -0
  880. package/stack-template/services/go-svc/internal/api/health_test.go +46 -0
  881. package/stack-template/services/go-svc/internal/api/json.go +13 -0
  882. package/stack-template/services/go-svc/internal/api/middleware.go +82 -0
  883. package/stack-template/services/go-svc/internal/api/middleware_test.go +48 -0
  884. package/stack-template/services/go-svc/internal/api/openapi/activity.yaml +196 -0
  885. package/stack-template/services/go-svc/internal/api/openapi.go +29 -0
  886. package/stack-template/services/go-svc/internal/api/openapi_test.go +38 -0
  887. package/stack-template/services/go-svc/internal/api/router.go +86 -0
  888. package/stack-template/services/go-svc/internal/api/stats.go +63 -0
  889. package/stack-template/services/go-svc/internal/api/stats_test.go +83 -0
  890. package/stack-template/services/go-svc/internal/api/types.go +32 -0
  891. package/stack-template/services/go-svc/internal/apperr/apperr.go +9 -0
  892. package/stack-template/services/go-svc/internal/config/config.go +115 -0
  893. package/stack-template/services/go-svc/internal/config/config_test.go +92 -0
  894. package/stack-template/services/go-svc/internal/consumer/envelope.go +78 -0
  895. package/stack-template/services/go-svc/internal/consumer/envelope_test.go +154 -0
  896. package/stack-template/services/go-svc/internal/consumer/handler.go +91 -0
  897. package/stack-template/services/go-svc/internal/consumer/handler_test.go +136 -0
  898. package/stack-template/services/go-svc/internal/consumer/producer.go +117 -0
  899. package/stack-template/services/go-svc/internal/consumer/runner.go +194 -0
  900. package/stack-template/services/go-svc/internal/consumer/runner_test.go +351 -0
  901. package/stack-template/services/go-svc/internal/logging/logging.go +49 -0
  902. package/stack-template/services/go-svc/internal/model/model.go +37 -0
  903. package/stack-template/services/go-svc/internal/resolve/resolver.go +134 -0
  904. package/stack-template/services/go-svc/internal/resolve/resolver_test.go +82 -0
  905. package/stack-template/services/go-svc/internal/resolve/token.go +130 -0
  906. package/stack-template/services/go-svc/internal/resolve/token_test.go +151 -0
  907. package/stack-template/services/go-svc/internal/store/events.go +71 -0
  908. package/stack-template/services/go-svc/internal/store/migrate.go +90 -0
  909. package/stack-template/services/go-svc/internal/store/migrate_test.go +34 -0
  910. package/stack-template/services/go-svc/internal/store/migrations/0001_create_events.sql +20 -0
  911. package/stack-template/services/go-svc/internal/store/migrations/0002_widen_action_cascade.sql +14 -0
  912. package/stack-template/services/go-svc/internal/store/store.go +65 -0
  913. package/stack-template/services/go-svc/internal/store/tasks.go +109 -0
  914. package/stack-template/services/go-svc/internal/swagger/assets/LICENSE +202 -0
  915. package/stack-template/services/go-svc/internal/swagger/assets/NOTICE +2 -0
  916. package/stack-template/services/go-svc/internal/swagger/assets/favicon-16x16.png +0 -0
  917. package/stack-template/services/go-svc/internal/swagger/assets/favicon-32x32.png +0 -0
  918. package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui-bundle.js +2 -0
  919. package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui.css +3 -0
  920. package/stack-template/services/go-svc/internal/swagger/index.html +28 -0
  921. package/stack-template/services/go-svc/internal/swagger/swagger.go +38 -0
  922. package/stack-template/services/go-svc/test/integration/integration_test.go +523 -0
  923. package/stack-template/services/node-svc/.dockerignore +5 -0
  924. package/stack-template/services/node-svc/Dockerfile +27 -0
  925. package/stack-template/services/node-svc/README.md +155 -0
  926. package/stack-template/services/node-svc/drizzle/0000_init.sql +17 -0
  927. package/stack-template/services/node-svc/drizzle/0001_status-assignment-failed.sql +2 -0
  928. package/stack-template/services/node-svc/drizzle/0002_outbox-table.sql +7 -0
  929. package/stack-template/services/node-svc/drizzle/meta/0000_snapshot.json +136 -0
  930. package/stack-template/services/node-svc/drizzle/meta/0001_snapshot.json +136 -0
  931. package/stack-template/services/node-svc/drizzle/meta/0002_snapshot.json +180 -0
  932. package/stack-template/services/node-svc/drizzle/meta/_journal.json +27 -0
  933. package/stack-template/services/node-svc/drizzle.config.ts +10 -0
  934. package/stack-template/services/node-svc/package.json +39 -0
  935. package/stack-template/services/node-svc/pnpm-lock.yaml +2706 -0
  936. package/stack-template/services/node-svc/src/app.test.ts +611 -0
  937. package/stack-template/services/node-svc/src/app.ts +126 -0
  938. package/stack-template/services/node-svc/src/clients/spring.ts +53 -0
  939. package/stack-template/services/node-svc/src/compensation-consumer.test.ts +157 -0
  940. package/stack-template/services/node-svc/src/compensation-consumer.ts +170 -0
  941. package/stack-template/services/node-svc/src/db/client.ts +23 -0
  942. package/stack-template/services/node-svc/src/db/migrate.ts +63 -0
  943. package/stack-template/services/node-svc/src/db/schema-diff.test.ts +252 -0
  944. package/stack-template/services/node-svc/src/db/schema.ts +64 -0
  945. package/stack-template/services/node-svc/src/env.ts +52 -0
  946. package/stack-template/services/node-svc/src/logger.ts +18 -0
  947. package/stack-template/services/node-svc/src/outbox-relay.test.ts +141 -0
  948. package/stack-template/services/node-svc/src/outbox-relay.ts +182 -0
  949. package/stack-template/services/node-svc/src/plugins/auth.ts +76 -0
  950. package/stack-template/services/node-svc/src/repo.drizzle.test.ts +182 -0
  951. package/stack-template/services/node-svc/src/repo.drizzle.ts +158 -0
  952. package/stack-template/services/node-svc/src/repo.ts +73 -0
  953. package/stack-template/services/node-svc/src/routes/health.ts +42 -0
  954. package/stack-template/services/node-svc/src/routes/tasks.ts +287 -0
  955. package/stack-template/services/node-svc/src/server.ts +91 -0
  956. package/stack-template/services/node-svc/src/types/api.d.ts +391 -0
  957. package/stack-template/services/node-svc/src/types/log.ts +3 -0
  958. package/stack-template/services/node-svc/tsconfig.json +20 -0
  959. package/stack-template/services/spring-svc/.dockerignore +5 -0
  960. package/stack-template/services/spring-svc/.mvn/wrapper/maven-wrapper.properties +20 -0
  961. package/stack-template/services/spring-svc/Dockerfile +22 -0
  962. package/stack-template/services/spring-svc/README.md +121 -0
  963. package/stack-template/services/spring-svc/mvnw +332 -0
  964. package/stack-template/services/spring-svc/mvnw.cmd +206 -0
  965. package/stack-template/services/spring-svc/pom.xml +144 -0
  966. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/SpringSvcApplication.java +12 -0
  967. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/Team.java +64 -0
  968. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/TeamRepository.java +34 -0
  969. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/User.java +72 -0
  970. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/UserRepository.java +10 -0
  971. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/logging/LowercaseLevelJsonProvider.java +24 -0
  972. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtAuthFilter.java +89 -0
  973. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtVerifier.java +48 -0
  974. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/service/TeamService.java +84 -0
  975. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiError.java +15 -0
  976. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiException.java +37 -0
  977. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/DevCorsConfig.java +41 -0
  978. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ErrorEnvelope.java +27 -0
  979. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/GlobalExceptionHandler.java +90 -0
  980. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/HealthController.java +46 -0
  981. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ReadinessService.java +40 -0
  982. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/TeamController.java +79 -0
  983. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/UserController.java +187 -0
  984. package/stack-template/services/spring-svc/src/main/java/db/migration/V2__SeedUsers.java +66 -0
  985. package/stack-template/services/spring-svc/src/main/resources/application.yml +42 -0
  986. package/stack-template/services/spring-svc/src/main/resources/db/migration/V1__init.sql +24 -0
  987. package/stack-template/services/spring-svc/src/main/resources/logback-spring.xml +34 -0
  988. package/stack-template/services/spring-svc/src/main/resources/openapi/users.yaml +345 -0
  989. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/logging/LogShapeTest.java +39 -0
  990. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/security/JwtAuthFilterTest.java +106 -0
  991. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/seed/SeedMatchIntegrationTest.java +68 -0
  992. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/service/TeamServiceRollbackTest.java +122 -0
  993. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/DevCorsTest.java +45 -0
  994. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/HealthCheckTest.java +56 -0
  995. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TeamApiTest.java +139 -0
  996. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TestPingController.java +21 -0
  997. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/UserApiTest.java +182 -0
  998. package/stack-template/stack-manifest.json +285 -0
@@ -0,0 +1,59 @@
1
+ # Plan: SF-7 Convergence & Scaffold
2
+ Date: 2026-10-12 | Linear: FI-75 | Worktree: sf-7-convergence | Story: FI-62
3
+
4
+ ## 0. Root cause analysis (WHY — before "what")
5
+ ### Root cause
6
+ SF-1..6 xây song song, mỗi SF chỉ chứng minh phần mình → không artifact committed nào chứng minh CHUỖI login→tạo task→đọc feed chạy liền mạch; docs viết ở thời SF-1 đã lệch thực tế; không có đường fresh-clone→demo cho người copy; không có scaffold; chưa có security-audit hội tụ.
7
+ ### Current state (before feature)
8
+ dest @ec7c3d3: 6 services impl + CI per-stack xanh + browser e2e SF-6 verify native (evidence sf-6). scripts/ KHÔNG tồn tại. README stale ("khung rỗng, SF-2/3/4 điền"). Compose: 3 service BE chưa có healthcheck, chưa có health-gated chain.
9
+ ### Expected outcome
10
+ Người copy: fresh-clone → đọc walkthrough → chạy demo được; CI chứng minh e2e + copy-dir + scaffold; scaffold sinh project mới tên riêng chạy được cùng flow; 0 P0/P1 security.
11
+ ### Constraints & hardships
12
+ Dev machine KHÔNG Docker (verify local native; docker compose chỉ qua CI) · browser KHÔNG vào CI (human gate) · services/frontend READ-ONLY · compose CHỈ được sửa phần health-gated · go-svc distroless không có shell/wget → healthcheck in-container bất khả không đụng Dockerfile (đã probe) → go-svc dùng `service_started` + e2e retry, flag story-level.
13
+ ### High-level strategy
14
+ Hội tụ tại chỗ: chứng minh bằng script + CI job mới (file convergence riêng), docs đồng bộ, scaffold copy-thuần. Không re-architect, không thêm tính năng.
15
+
16
+ ## 1. Problem (intent, NOT solution)
17
+ Người mua boilerplate chưa thể tin chuỗi e2e chạy được (không proof committed), chưa chứng minh copy-dir standalone, chưa có script sinh project mới, docs không dẫn được người mới từ fresh-clone đến demo.
18
+
19
+ ## 2. Scope
20
+ - In scope: scripts/smoke/e2e.sh · CI convergence.yml (3 job: e2e-smoke, copy-dir-smoke, scaffold-verify) · compose health-gated (chỉ healthcheck+depends_on) · docs (ADR ×7, toolchain, walkthrough, README sync) · scripts/scaffold/ · 2 findings SF-1-owned (conventions/02 mirror rule; DDL CREATE SCHEMA note) + [p6-flag] sync (01, 08) · security-audit checkpoint · Rule 0 native smoke + evidence.
21
+ - Out of scope: browser trong CI; fix business logic services/FE; merge main/PR; tính năng mới; sửa workflow-templates (READ-ONLY — thiếu gì = flag).
22
+ - Success criteria (observable): xem ACCEPTANCE context pack sf-7.md — từng dòng verify tại Task 10; CI 3 job mới xanh sau push; story-verify B1-B3 sạch.
23
+
24
+ ## 3. Touch map
25
+ - Files modify: `scripts/smoke/e2e.sh` (tạo) · `scripts/scaffold/scaffold.sh` + README (tạo) · `.github/workflows/convergence.yml` (tạo) · `docs/adr/*` + `docs/toolchain.md` + `docs/walkthrough.md` (tạo) · `README.md` (sửa) · `platform/docker-compose.yml` (sửa — chỉ healthcheck/depends_on) · `platform/conventions/01|02|08` (sửa — sync) · `contracts/db/tasks-schema.sql` (sửa — comment-only) · `docs/superpowers/evidence/sf-7-convergence/*` (tạo).
26
+ - Consumers/regression candidates: CI workflows hiện có (contracts.yml, per-service) — file mới không được phá chúng; SF-6 native mode — compose sửa không ảnh hưởng native; SF-1 compose pre-seed — sửa giữ nguyên entry/env.
27
+ - Shared surfaces: compose env vars (không thêm biến mới); healthcheck endpoints /readyz đã có sẵn ở cả 3 service (conventions/02).
28
+
29
+ ## 4. Design
30
+ - Approach chosen: A — smoke curl thuần + CI compose; scaffold copy+rename+prune. (B browser-CI, C generator — dismissed theo spec.)
31
+ - Alternatives considered: jq trong e2e.sh (dismissed — giữ curl+grep thuần chạy được Git Bash không jq); go-svc healthcheck bằng sửa Dockerfile (dismissed — READ-ONLY, flag story-level).
32
+ - Edge cases / second-order effects:
33
+ - go-svc distroless → gateway `depends_on: go-svc: service_started`; e2e.sh retry feed tối đa N lần (chống race go-svc init chậm hơn gateway-ready).
34
+ - CI compose `${VAR:?}` fail hard → job sinh `.env` đầy đủ từ placeholder CI (không secret thật).
35
+ - Scaffold rename `@boilerplate/*` phá pnpm-lock importers → scaffold chạy `pnpm install --no-frozen-lockfile` ghi trong hướng dẫn + job verify dùng flag đó.
36
+ - e2e re-run: title prefix `smoke-<epoch>` tránh trùng dữ liệu cũ.
37
+ - Non-functional: security (secrets/exec-bit/lockfile — checkpoint riêng); perf/a11y/i18n — skip (không UI mới, không hot path).
38
+
39
+ ## 5. Implementation outline
40
+ - Tasks (ordered, DAG):
41
+ 1. `docs-sync` — conventions/02 mirror rule + DDL CREATE SCHEMA note + conventions/01 standalone-lockfile variant + conventions/08 requiredVersion:false. Conditional: 04-error-envelope chỉ ghi note nếu quyết additionalProperties ĐÃ chốt ở node-svc source — KHÔNG tự chốt, chưa chốt thì flag. Exit: 2 findings SF-1-owned xử lý xong + [p6-flag] sync xong.
42
+ 2. `smoke-script` — scripts/smoke/e2e.sh (login→POST task assignee bob→feed poll 10×1s có action task.created + title; stats fetch baseline TRƯỚC khi tạo, assert ≥ baseline+1; wait poll /api/auth/readyz qua :8080; env GATEWAY_URL/SMOKE_*; title prefix smoke-<epoch>). **T2 TỰ verify exit của mình: tự start native stack từ ~/Tools/sf6-e2e (script biến thể SF-7 trỏ worktree này) rồi chạy script thật** — không đợi T10. Exit: script chạy THẬT native tại T2 + exit-code đúng từng bước fail.
43
+ 3. `compose-health` — healthcheck node/spring (wget /readyz — alpine busybox, ĐÃ PROBE); KHÔNG healthcheck gateway (nginx không route /readyz — P1 critic vòng 2, probe sẽ 404 deadlock); depends_on: node→spring healthy; gateway → auth-mock+node+spring service_healthy, go-svc service_started (distroless NGOẠI LỆ có chủ đích — P0 spec-critic; readiness go-svc do e2e poll stats). **+ spec slice #6 (P0 plan-critic): rà multi-stage + pinned base images toàn bộ 6 Dockerfile (3 svc + auth-mock + shell + 2 remotes) — report status vào evidence, KHÔNG sửa trừ khi P0.** Exit: `docker compose --env-file platform/.env.example config -q` pass + banner ownership SF-7 + **git diff compose chỉ chạm healthcheck/depends_on/banner (diff-guard)** + report multi-stage/pinned.
44
+ 4. `ci-smoke` — convergence.yml job e2e-smoke: reuse `--env-file platform/.env.example` → compose up -d --build → poll /api/auth/readyz qua :8080 → bash scripts/smoke/e2e.sh → khi fail dump logs (compose gọi lại CÙNG --env-file — p6-flag SF-2). Trigger branches:** + workflow_dispatch. File convergence.yml RIÊNG, không đụng workflow-templates. Exit: workflow YAML hợp lệ (CI push là gate thật).
45
+ 5. `ci-copydir` — job copy-dir-smoke: copy services/node-svc ra tmp: pnpm install --ignore-workspace + test + build (theo README standalone); copy frontend/shared ra tmp: tsc --noEmit typecheck (fe-shared KHÔNG có scripts riêng — inert cho node-svc, ghi tường minh trong job; proof FE mạnh hơn = follow-up). Exit: job định nghĩa, lệnh khớp README từng repo-con.
46
+ 6. `scaffold` — scripts/scaffold/scaffold.sh (cp/tar-based KHÔNG rsync; prune .git/.github/workflow-templates/docs/superpowers/spike/node_modules/.story-brief.md + workflows/convergence.yml; rename @boilerplate→@<name> + root package name + compose name + README title; xử lý pnpm-lock importers strip spike + rename scope; ghi SCAFFOLD.md kèm full-e2e human gate note). Exit: chạy local Git Bash ra project mới; **"diff sạch" = output tree khớp expected** — không rò .git/.github/workflow-templates/docs/superpowers/frontend/spike/node_modules/.story-brief.md/workflows-convergence.yml; rename @boilerplate đủ trong package.json + lockfile importers.
47
+ 7. `ci-scaffold` — job scaffold-verify: scaffold --name demo-app → pnpm install --no-frozen-lockfile → build FE shell + `docker compose -f <out>/platform/docker-compose.yml --env-file <out>/platform/.env.example config -q` trong output. Narrowing đã duyệt (context pack: "CI verify scaffold output build được") — full e2e trên output = human gate. Exit: convergence.yml parse OK + **step-sequence job khớp SCAFFOLD.md do T6 output** (scaffold → install → build → compose config).
48
+ 8. `adr-toolchain` — docs/adr/ (7 quyết định: mixed-stack, MF-Rspack, contract-first, readonly-schema, fail-closed, fire-and-forget, fork-not-upgrade) + README index + docs/toolchain.md. Exit: đủ 7 ADR khớp danh sách spec.
49
+ 9. `readme-walkthrough` — README sync (kiến trúc 6 svc thật, mục Chạy compose+native+smoke, repo map mới) + docs/walkthrough.md fresh-clone checklist. Exit: lệnh walkthrough **khớp script e2e.sh (T2) + lệnh native đã chạy tay tại T2**; không còn text stale SF-1. T10 chỉ reconcile lệch (nếu có).
50
+ 10. `verify-evidence` — Rule 0: tái dùng native stack đã sống từ T2 → chạy e2e.sh chính thức + evidence docs/superpowers/evidence/sf-7-convergence/test-run.txt; verify từng dòng ACCEPTANCE; browser walkthrough = **human gate — chỉ GHI hướng dẫn cho user, evidence note "human-gate pending user"** (P2 plan-critic); security-audit agent; code-reviewer độc lập; commit + push. **Exit: VERDICT APPROVED + evidence /tmp/story/fi62/code-reviewer-sf-7-convergence.md + CI convergence.yml 3/3 job XANH sau push (hoặc FAIL-flag kèm run link) + fix-commits (nếu audit/review sinh fix) commit TRƯỚC, evidence là commit cuối (chống B1 hash flip — improvements-log SF-6).** Fix-loop 2 nhánh: issue trong artifacts SF-7 → fix tại T10; issue trong services/FE (READ-ONLY) → report coordinator.
51
+ - File structure: scripts/ (mới, root) · docs/adr/ (mới) · giữ conventions của platform/.
52
+ - **Execution-order contract (P1 plan-critic):** DAG thực chỉ có T10←T1,T5 (task-update không hỗ trợ thêm deps) — **T10 CHỈ chạy sau T4,T7,T9: coordinator-enforced khi inline**; nếu bất kỳ task bị dispatch ra worker/rollback giữa chừng, coordinator phải kiểm T4/T7/T9 completed trước khi mở T10.
53
+ - Testing strategy: e2e.sh chạy thật native TỪ T2 (stack tự start) + CI job chạy lại trên compose (gate thật) · `docker compose config` cho compose · scaffold chạy local thật · docs walkthrough khớp lệnh đã chạy (không test tự động — ghi rõ).
54
+ - Numbering đối chiếu (P2 critic): DAG task id ↔ plan numbering — T1 docs-sync=task_6fa252c9274a · T2 smoke=task_34b7de0c22bf · T3 compose=task_ecf7929531ca · T4 ci-smoke=task_aa83884a9e64 · T5 copydir=task_6e21f4739d17 · T6 scaffold=task_7daa14f8c2ad · T7 ci-scaffold=task_62413473ffd1 · T8 adr=task_e984c41cafd5 · T9 readme=task_dafd27e9aa62 · T10 verify=task_5cab41e0ee8f.
55
+
56
+ ## 6. Risks & unknowns
57
+ - Must verify: Dockerfile base images (ĐÃ PROBE: node alpine wget ✓, spring temurin-alpine wget ✓, go distroless ✗ → service_started + e2e poll; gateway KHÔNG healthcheck — probe sẽ 404) · event action string (ĐÃ PROBE: 'task.created' tại node-svc/src/routes/tasks.ts:134) · README standalone node-svc (ĐÃ PROBE: local lockfile + --ignore-workspace) · toolchain ~/Tools/sf6-e2e (ĐÃ PROBE: còn sống).
58
+ - Unverified assumptions: frontend/shared tsc --noEmit đứng độc lập ngoài workspace (probe tại Task 5) · gateway nginx route /api/activity/feed không đổi path (probe contracts đã xác nhận servers /api/activity).
59
+ - CI env: compose reuse `--env-file platform/.env.example`; lockfile scaffold strip spike importers + rename scope (xem plan T6).
@@ -0,0 +1,19 @@
1
+ # Plan — SF-2 node-svc task API (FI-70)
2
+
3
+ > Spec: `docs/superpowers/specs/2026-10-12-sf2-node-svc-spec.md` · Epic: FI-62 · Worktree `__STACK_ORG__/sf-2-node-svc`
4
+ > Mỗi task = 1 atomic commit. Tests chạy native (Node 24 local, engines >=22; docker verify qua CI).
5
+
6
+ - [x] Task 1 — Scaffold services/node-svc: `package.json` (fastify 5, @fastify/cors, @fastify/swagger, @fastify/swagger-ui, drizzle-orm, pg, pino, jsonwebtoken, http-jwt ?= jsonwebtoken; dev: typescript, tsx, vitest, drizzle-kit, openapi-typescript, @types/*), `tsconfig.json` (NodeNext, strict), `.dockerignore`, `src/env.ts` (fail-fast env parse: PORT, DATABASE_URL, JWT_SECRET, SPRING_SVC_URL, GO_SVC_URL, CORS_DEV_ORIGIN, LOG_LEVEL). `pnpm install` cập nhật lockfile workspace (commit cả root lockfile).
7
+ - [x] Task 2 — Codegen types: script `generate:types` = `openapi-typescript ../../contracts/openapi/tasks.yaml -o src/types/api.d.ts` (types only). Chạy 1 lần + commit output; CI job re-generate + `git diff --exit-code` để chống drift contract.
8
+ - [x] Task 3 — Drizzle schema + migration khớp canonical DDL: `src/db/schema.ts` (bảng tasks: uuid pk app-generated, title varchar(200), description text, status varchar(20) default todo + CHECK, assignee_id uuid, created_by uuid, created_at/updated_at timestamptz default now, 3 indexes) + `drizzle/` SQL migration commit sẵn (generated). Test `schema-diff.test.ts`: introspect migration SQL vs `contracts/db/tasks-schema.sql` → normalised diff = 0. `src/db/client.ts` (pg Pool + drizzle, search_path tasks).
9
+ - [x] Task 4 — Platform middleware: `src/plugins/auth.ts` (verify JWT HS256 + exp + iss=auth-mock từ JWT_SECRET, 401 envelope UNAUTHORIZED, healthz/readyz exempt), `src/plugins/requestId.ts` + pino logger shape conventions/03, error handler map mọi error (kể cả FST_ERR_*) sang envelope conventions/04, CORS @fastify/cors từ CORS_DEV_ORIGIN (deny-by-default rỗng).
10
+ - [x] Task 5 — Health: `/healthz` 200 {"status":"ok"}; `/readyz` = DB migrated + SELECT 1 ok (503 envelope khi fail); boot-time spring reachability check 1 lần + log warn (không gate ready). `src/server.ts` listen PORT.
11
+ - [x] Task 6 — CRUD routes `/api/tasks`: list (filter status/assigneeId, limit<=100/offset, trả TaskList {items,total}), get-by-id (404 TASK_NOT_FOUND), create (validate title qua schema; nếu có assigneeId → spring GET /api/users/{id} timeout 2s: 404→422 UNPROCESSABLE, network/timeout→503 DEPENDENCY_DOWN; insert uuid v4; push event task.created fire-and-forget), patch (minProperties 1, cùng validate nếu đổi assigneeId; event task.updated), delete (204, event task.deleted). Event push: POST {GO_SVC_URL}/api/activity/events, payload ActivityEventInput, fail → pino warn "event push failed", không retry.
12
+ - [x] Task 7 — Swagger UI `/api/tasks/docs` (mirror tối thiểu tasks.yaml, pattern auth-mock) + README services/node-svc (native/docker, env vars, API summary, failure semantics + ADR degrade, readyz deviation note).
13
+ - [x] Task 8 — Tests vitest: unit routes (happy path CRUD, 400 validation, 404, 401 no/bad/expired token, 422 assignee lạ, 503 spring down — inject fake spring, fire-and-forget go-svc down → vẫn 201 + warn), healthz/readyz (DB down → 503), schema-diff test. Mọi external call inject qua app factory opts (không network thật).
14
+ - [x] Task 9 — Dockerfile multi-stage (conventions/01: node:22-alpine, pnpm frozen, build dist, USER node, EXPOSE 3001) + CI `.github/workflows/services-node-svc.yml` (build-test native; docker build; boot-smoke: compose up postgres + node-svc → healthz/readyz 200 → ký JWT CI → POST task (không assignee) 201 → GET list thấy → DELETE 204; typegen drift check). Evidence `docs/superpowers/evidence/sf-2-node-svc/test-run.txt`.
15
+
16
+ ## Verification
17
+ - Local: `pnpm --filter node-svc test` xanh + `pnpm --filter node-svc build` + boot native vs postgres local? (không postgres local — DB tests dùng pg-mem? Không: dùng container-free mock qua inject + fake db. Boot thật để CI boot-smoke chứng minh.)
18
+ - CI: 3 jobs xanh (URL ghi evidence).
19
+ - Review: code-reviewer độc lập trên diff full → APPROVED (CHECKLIST-4Q) → push → story-verify.
@@ -0,0 +1,30 @@
1
+ # SF-1 Plan — Kafka foundation + async contracts (FI-77)
2
+
3
+ > Story FI-76 · spec slice: `docs/superpowers/contexts/sf-1.md` · epic spec rev 3: `docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md`
4
+ > Worktree: `sf-1-kafka-foundation` (nhánh `__STACK_ORG__/sf-1-kafka-foundation` fork từ `__STACK_ORG__/story-fi76-kafka-outbox-saga`)
5
+ > Ràng buộc: dev machine KHÔNG Docker — mọi verify compose/kafka qua CI. Compose sửa ĐÚNG 1 commit duy nhất.
6
+
7
+ ## Tasks (10)
8
+
9
+ | # | Task | Files | Commit |
10
+ |---|------|-------|--------|
11
+ | T1 | Compose: kafka entry (apache/kafka KRaft, heap 512m, healthcheck full-path `/opt/kafka/bin/kafka-broker-api-versions.sh`, KHÔNG depend_on, KHÔNG expose 9092) + PRE-ADD env downstream (node-svc `KAFKA_BROKERS`; go-svc `KAFKA_BROKERS` + `AUTH_MOCK_URL` + `SVC_ACTIVITY_PASSWORD`) + header ownership | `platform/docker-compose.yml` | 1 commit (cùng .env.example — conventions/06) |
12
+ | T2 | .env.example: `KAFKA_BROKERS=kafka:9092` + `SVC_ACTIVITY_PASSWORD=demo-password` (+ comment) | `platform/.env.example` | cùng commit T1 |
13
+ | T3 | Contract: `contracts/events/task-events.md` — envelope `{schemaVersion:1, id UUID, type, occurredAt RFC3339, payload}`, payload shape theo 5 event type, filter-by-type (group `go-svc-activity` trừ `task.assignment_failed`; `node-svc-compensation` chỉ `task.assignment_failed`), topics `task-events`+`task-events.dlq` 1 partition, retry ×3 in-memory → DLQ, manual commit sau DB tx, `auto.offset.reset: earliest` | contracts/events/task-events.md | 1 commit |
14
+ | T4 | Golden fixtures: 5 file JSON (`task.created/updated/assigned/deleted/assignment_failed.json`) đúng envelope — machine-checkable cho SF-2 relay test + SF-3 consumer test + CI console-producer | `contracts/events/fixtures/*.json` | 1 commit |
15
+ | T5 | Fixture users: + `svc-fail` (`fail@demo.local`), `svc-activity` (service user) — roles `["user"]`, UUID cố định pattern | `contracts/auth/users.json` | 1 commit |
16
+ | T6 | Conventions: `platform/conventions/09-async-messaging.md` — producer/consumer/retry/DLQ/idempotency + lazy-connect rule + conventions README row | conventions/09 + README.md (conventions) | 1 commit |
17
+ | T7 | ADR-0008 supersede ADR-0006 (Kafka KRaft, outbox tự viết, presence-based trigger, in-memory retry, PLAINTEXT, segmentio/kafka-go, saga choreography) + adr README row | `docs/adr/0008-*.md` + docs/adr/README.md | 1 commit |
18
+ | T8 | README section compose: 10 services + kafka lazy-connect note | `README.md` | 1 commit |
19
+ | T9 | Verify local không-Docker: fixtures parse JSON + đủ field envelope (jq), users.json roles hợp lệ, compose YAML parse; push + CI watch (contracts/compose-config + convergence xanh) | — | — |
20
+ | T10 | Code-reviewer độc lập trên diff → verdict file /tmp/story/fi62/code-reviewer-sf-1-kafka-foundation.md; evidence `docs/superpowers/evidence/sf-1-kafka-foundation/`; story-verify sf-1; Linear comment DONE | — | — |
21
+
22
+ ## Acceptance (user-visible — từ context pack)
23
+ 1. `docker compose config -q` validate với entry kafka + env mới (CI-verified).
24
+ 2. CI convergence không đỏ vì kafka entry (không service depend kafka).
25
+ 3. Golden fixtures parse JSON, envelope đủ field, mỗi event type 1 file.
26
+ 4. users.json 2 user mới, roles hợp lệ, spring SeedMatch (SF-4) vẫn pass khi merge.
27
+ 5. ADR-0008 + conventions/09 tồn tại, supersede 0006 rõ ràng.
28
+
29
+ ## Boundary
30
+ KHÔNG đụng: `contracts/db/`, `contracts/openapi/`, `services/**`, FE. KHÔNG kafka vào readyz/depends_on. KHÔNG expose 9092. KHÔNG SASL/SSL. Compose 1 commit duy nhất.
@@ -0,0 +1,28 @@
1
+ # Plan — SF-1 Design-system nền móng (VU-54, story VU-53 UI redesign)
2
+
3
+ > Tier: Standard. Spec: `docs/superpowers/contexts/ui-redesign/sf-1.md` + hand-off
4
+ > `docs/superpowers/designs/ui-redesign-direction.md` (source of truth — user đã duyệt hướng B).
5
+ > Worktree: `sf-1-ui-redesign-dsys` (story-hub model — push nhánh, coordinator merge).
6
+ > Cứng: `pnpm-lock.yaml` KHÔNG đổi; 4 file logic fe-shared + `mfToolkit` READ-LOCKED.
7
+
8
+ ## Tasks
9
+
10
+ - [x] T1 — `fe-shared/src/styles/tokens.css` + `base.css` đúng hand-off §1-2 (tokens `:root` idempotent; base `@layer reset,base`; shell là chủ global khi SF-2 wire — SF-1 không đụng shell entry)
11
+ - [x] T2 — Rspack ×3: remotes thêm css rule (`type:'css'`) + `experiments.css` (copy shell `rspack.config.mjs:42-45,85-87`); `'react/jsx-runtime'` singleton + `requiredVersion:false` vào shared CẢ 3 config; `output.cssFilename` contenthash prod ×3; `declare module '*.css'` env.d.ts ×3
12
+ - [x] T3 — SPIKE R2 SỚM: JSX stub (useState + onClick) trong `fe-shared/src/ui/jsx-probe.tsx`, temp-render trong tasks remote; build 3 package; dev servers riêng (3100/4101/4102 — FE docker chiếm 3000/4001/4002); login → tasks → đổi status qua select; console KHÔNG có "Invalid hook call"/"2 copies of React"; screenshot evidence
13
+ - [x] T4 — Primitives TDD: tests `shell/tests/primitives.test.tsx` TRƯỚC (RED) → implement `Badge/EmptyState/Skeleton/Spinner` đúng props API hand-off §3 (CSS `bp-*` trong base.css) → GREEN; gỡ JSX stub khỏi tasks remote
14
+ - [x] T5 — Barrel `src/index.ts` + exports map (styles + ui) + README + ownership comments (`pnpm-workspace.yaml`, `fe-shared/package.json` description; `mfToolkit` nguyên vẹn)
15
+ - [x] T6 — Remotes `src/index.tsx` standalone (:4001/:4002) import tokens+base (fix "trơ trụi"; comment cho SF-3/4 banner)
16
+ - [x] T7 — Demo primitives sống: `docs/superpowers/designs/ui-redesign/ds-demo.html` (link CSS thật của fe-shared, markup = đúng DOM components render)
17
+ - [x] T8 — Verify: `pnpm build` ×3 + `pnpm test` (shell) + `typecheck` ×3 xanh; evidence `evidence/sf-1-ui-redesign-dsys/test-run.txt` (HEAD hash + `tdd: RED→GREEN`)
18
+ - [x] T9 — Browser verify 3 tầng (DOM / VISUAL so `b-reference.png` / FLOW shell→remote mount→đổi status) + ACCEPTANCE từng dòng; screenshots evidence
19
+ - [x] T10 — Code-reviewer độc lập trên diff SF → verdict post Linear VU-54 (VERDICT + CHECKLIST-4Q)
20
+ - [x] T11 — Commit atomic + push nhánh `__STACK_ORG__/sf-1-ui-redesign-dsys` + `story-verify sf-1` sạch (B4 merge là phần coordinator) — KHÔNG set Done
21
+
22
+ ## Exit criteria (ACCEPTANCE pack)
23
+
24
+ 1. Standalone `:4001`/`:4002` có baseline style (không trơ trụi); primitives render đúng hand-off.
25
+ 2. 3 package `pnpm build` xanh; spike R2 PASS có screenshot (console sạch duplicate-react).
26
+ 3. `pnpm test` shell xanh kèm tests primitives.
27
+ 4. `pnpm-lock.yaml` không đổi (0 deps mới).
28
+ 5. Design gate: không re-design — implement thẳng hand-off (đã user-duyệt 2026-10-13).
@@ -0,0 +1,46 @@
1
+ # SF-2 Plan — node-svc Outbox + Producer + compensation consumer (FI-79)
2
+
3
+ > Story FI-76 · Epic spec rev 3: `docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md`
4
+ > Context pack: `docs/superpowers/contexts/sf-2.md` · conventions/09 · ADR-0008
5
+ > Branch: `__STACK_ORG__/sf-2-node-outbox` (fork từ dest @8d04e6d) · 1 commit / task · KHÔNG merge dest
6
+ > Baseline probe (đã đọc): `repo.ts:38-45` interface CRUD thuần · `repo.drizzle.ts` không `.transaction()` ·
7
+ > `schema-diff.test.ts:146` normalizer throw ở DDL chưa handle (chỉ CREATE SCHEMA/TABLE/INDEX — ALTER
8
+ > CONSTRAINT phải mở rộng normalizer, phát hiện mới ngoài context pack).
9
+
10
+ ## Tasks
11
+
12
+ ^- [x] **T1 — Cụm nguyên tử status cascade (DDL + drizzle mirror + migration CHECK)**: `contracts/db/tasks-schema.sql` CHECK `status IN ('todo','in_progress','done','assignment_failed')` (varchar(20) đủ — 17 ký tự) + comment; `src/db/schema.ts` mirror; migration `0001` qua `drizzle-kit generate` (DROP/ADD CONSTRAINT `status_check`). Migration KHÔNG đụng phần khác.
13
+ Exit: `schema-diff.test` chạy được (T3 sẽ mở rộng normalizer); DDL comment ghi assignment_failed là system-owned.
14
+ ^- [x] **T2 — tasks.yaml TaskStatus split + typegen**: `TaskStatus` giữ 3 giá trị (query param + PATCH body — WRITABLE, description ghi rõ); thêm `TaskStatusExtended` 4 giá trị (chỉ `Task.status` response — READ-ONLY); PATCH KHÔNG nhận `assignment_failed`. Chạy `pnpm --filter node-svc generate:types` → commit `api.d.ts`.
15
+ Exit: typegen diff-check CI pass (route hard-code 3 giá trị giữ nguyên — đã đúng từ trước).
16
+ ^- [x] **T3 — Pin schema-diff.test scope (P0)**: mở rộng normalizer handle `ALTER TABLE ... DROP CONSTRAINT` / `ADD CONSTRAINT` (không throw); WHITELIST bảng outbox với expected-def RIÊNG (so khớp def, KHÔNG đếm vào canonical); assert `tasks.outbox` tồn tại trong migrated; canonical + `indexes.length === 3` GIỮ NGUYÊN (hướng ngược làm đỏ copy-dir standalone).
17
+ Exit: test xanh với migration 0001; đỏ nếu outbox lệch def.
18
+ ^- [x] **T4 — Outbox table migration + drizzle schema**: `tasks.outbox` (id UUID do node sinh PK, type varchar(40), payload jsonb NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), published_at timestamptz NULL) — KHÔNG index (đúng spec, purge lo scan); `schema.ts` thêm bảng; migration `0002` generate. Outbox KHÔNG vào canonical DDL (node-internal infra).
19
+ Exit: schema-diff whitelist T3 thấy đúng def; migration áp được bằng custom runner.
20
+ ^- [x] **T5 — Transactional TaskRepo API + tx rollback test (seam)**: đổi interface `repo.ts` — mutation method nhận outbox op (`create(input, events)`, `update(id, patch, events)`, `remove(id, events)`, thêm `markAssignmentFailed(taskId, assigneeId): Promise<boolean>` conditional guard); **envelope id (UUIDv4) + occurredAt sinh TRONG repo**; drizzle impl bọc mutation + INSERT outbox trong 1 `.transaction()`; fake repo có seam tiêm lỗi giữa 2 step (mô phỏng rollback: cả 2 cùng biến mất). Test tx rollback: mock-db `transaction()` ghi nhận 2 op, outbox insert throw → task + outbox cùng biến mất (không còn row nào).
21
+ Exit: `repo.drizzle.test.ts` (mới) xanh: happy path 2 op trong cùng tx callback + seam-fail rollback.
22
+ ^- [x] **T6 — Route event matrix (presence-based) + xóa clients/activity.ts**: build events từ body tại `routes/tasks.ts` (POST→`task.created`; PATCH có `assigneeId`→`task.assigned` + `task.updated` nếu body còn title/status; PATCH không→`task.updated`; DELETE→`task.deleted`; KHÔNG có unassign; payload `task.updated` chỉ title/status/assigneeId — KHÔNG description); xóa `clients/activity.ts` + 5 refs (`app.ts:24`, `app.test.ts`, `routes/tasks.ts:30`, `server.ts:5,22`); `server.ts` wire relay + consumer thay activity client.
23
+ Exit: tsc build sạch; không còn ref activity client.
24
+ ^- [x] **T7 — app.test.ts cập nhật theo matrix (23/23 cũ không vỡ hoặc cập nhật chính đáng)**: test POST/PATCH/DELETE assert events ghi trong fake repo đúng type + payload shape (so golden fixture `contracts/events/fixtures/*.json` — load chung file); PATCH `status: assignment_failed` → 400 VALIDATION_ERROR; GET task `assignment_failed` hợp lệ (fake trả extended); bỏ test fire-and-forget go-svc (thay bằng outbox-in-tx assert).
25
+ Exit: toàn bộ node-svc unit test xanh.
26
+ ^- [x] **T8 — Relay worker + KAFKA_BROKERS lazy + relay unit test (golden fixture)**: `env.ts` thêm `kafkaBrokers` (optional — thiếu = warn + không start relay/consumer, KHÔNG crash, KHÔNG vào readyz); `outbox-relay.ts` poll 500ms: SELECT unpublished → kafkajs producer send topic `task-events` **key = payload.taskId**, envelope `{schemaVersion:1, id, type, occurredAt, payload}` → mark `published_at` (publish TRƯỚC mark — crash giữa chừng = duplicate, consumer dedupe); purge published cũ > 7 ngày; lazy-connect retry backoff, fail = warn không crash. Unit test: fake producer + fake repo, assert message khớp golden fixture format (2 đầu load chung file).
27
+ Exit: relay test xanh không cần broker.
28
+ ^- [x] **T9 — Compensation consumer + unit test (conditional guard)**: `compensation-consumer.ts` group `node-svc-compensation`, CHỈ xử lý `type === 'task.assignment_failed'` (type khác = commit + skip); xử lý = `markAssignmentFailed` (conditional UPDATE `WHERE assignee_id = payload.assigneeId AND status <> 'assignment_failed'` — stale event KHÔNG đổi); manual offset commit SAU khi DB op xong (kafkajs `autoCommit: false` + `commitOffsets`); retry ×3 in-memory backoff → hết lượt publish message gốc + metadata vào `task-events.dlq` rồi commit (KHÔNG block partition). Unit test: happy (status đổi), stale (assignee khác → không đổi, vẫn commit), filter (type khác skip), idempotent (event lặp → lần 2 match 0 row).
29
+ Exit: consumer unit test xanh không cần broker/postgres.
30
+ ^- [x] **T10 — CI kafka boot-smoke (P0)**: `services-node-svc.yml` thêm job `kafka-boot-smoke`: `up -d postgres kafka node-svc` (env-file .env.example) → readyz 200 → POST task (JWT tự ký) → poll `tasks.outbox` `published_at IS NOT NULL` (psql trong container postgres, timeout) → assert `type='task.created'` + payload có taskId. Relay THẬT trên CI (không fake). Lưu ý YAML block-scalar (improvements-log SF-7): không heredoc/JSON cột 0 trong `run: |`.
31
+ Exit: job mới có trong workflow; logic poll đúng cú pháp (CI chạy thật ở bước 3 checklist).
32
+ ^- [x] **T11 — README node-svc + evidence + audit**: README thêm outbox/kafka section (relay, compensation consumer, event matrix, KAFKA_BROKERS lazy) + mục standalone ghi dependency `contracts/db/tasks-schema.sql` + `contracts/events/fixtures` (FLAG sẵn convergence.yml:62); evidence `docs/superpowers/evidence/sf-2-node-outbox/test-run.txt` (HEAD + test output); Linear audit comment FI-79.
33
+ Exit: README đầy đủ; evidence đúng convention B1.
34
+
35
+ ## Nhóm review (rolling — code-reviewer độc lập)
36
+ - Nhóm A sau T5: schema cascade + outbox + repo tx (T1-T5).
37
+ - Nhóm B sau T9: routes/relay/consumer/tests (T6-T9).
38
+ - Final: T10-T11 + verdict materialize `/tmp/story/fi62/code-reviewer-sf-2-node-outbox.md` + Linear comment (VERDICT + CHECKLIST-4Q) cho gate B3.
39
+
40
+ ## ACCEPTANCE (từ context pack — verify từng dòng trước DONE)
41
+ 1. Tạo task → outbox row trong cùng tx (seam-fail test: task + outbox cùng biến mất).
42
+ 2. Relay publish format KHỚP golden fixture (test 2 đầu load chung file).
43
+ 3. CI node workflow xanh gồm boot-smoke kafka: outbox row `published_at IS NOT NULL` trên broker thật.
44
+ 4. PATCH `status: assignment_failed` bị từ chối; GET task `assignment_failed` hợp lệ.
45
+ 5. Consumer: event assignment_failed → status đổi; stale event (assignee khác) KHÔNG đổi.
46
+ 6. 23/23 tests cũ không vỡ (hoặc cập nhật chính đáng theo matrix).
@@ -0,0 +1,31 @@
1
+ # SF-3 Plan — go-svc Consumer + Saga + thanh lý ingest (FI-80)
2
+
3
+ > Story FI-76 · spec slice: `docs/superpowers/contexts/sf-3.md` · epic spec rev 3: `docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md`
4
+ > Worktree: `sf-3-go-consumer` (nhánh `__STACK_ORG__/sf-3-go-consumer` fork từ dest @8d04e6d — SF-1 đã merge)
5
+ > Ràng buộc: dev machine KHÔNG Go/Docker — build/test/kafka verify QUA CI. KHÔNG sửa compose/.env.example/contracts-events/conventions-09/users.json/tasks-schema/tasks.yaml/node/spring. KHÔNG franz-go (segmentio theo spec).
6
+
7
+ ## Tasks (11)
8
+
9
+ - [ ] T1 — Migration `0002_widen_action_cascade.sql`: `ALTER COLUMN action TYPE varchar(40)` (`task.assignment_failed` = 22 ký tự) + drop CHECK cũ / recreate CHECK 5 giá trị (thêm `task.assigned`, `task.assignment_failed`). Width + CHECK CÙNG file — P0 ×2.
10
+ - [ ] T2 — Store idempotency: `store/events.go` InsertEvent `INSERT ... ON CONFLICT (id) DO NOTHING` (id = envelope id từ caller); `model/model.go` +action constants; `store/tasks.go` byStatus + `api/stats.go` seed map thêm `assignment_failed`.
11
+ - [ ] T3 — Config: +`KafkaBrokers` (required fail-fast), `KafkaGroup` (default `go-svc-activity`), `KafkaTopic` (default `task-events`), `KafkaDLQTopic` (default `task-events.dlq`), `AuthMockURL`, `SvcActivityPassword`; +`config_test.go`.
12
+ - [ ] T4 — Resolver service-token: token source login `svc-activity` (`AUTH_MOCK_URL` + `SVC_ACTIVITY_PASSWORD`) — retry backoff lúc boot KHÔNG crash (go chỉ depends_on postgres), lazy re-login khi 401/expiry, cache JWT; consumer enrich userName bằng token này. Tests: fake auth server (backoff, 401 → re-login).
13
+ - [ ] T5 — Consumer package `internal/consumer/` (segmentio/kafka-go): parse envelope (schemaVersion 1, 5 type), filter-by-type bỏ qua `task.assignment_failed`, handler = [1 DB tx: INSERT activity idempotent + resolve display] SAU ĐÓ commit offset (manual commit sau tx); simulate fail hook `assigneeId == svc-fail UUID` → error; retry ×3 in-memory backoff → publish `task.assignment_failed` (envelope id MỚI do go sinh) vào `task-events` + push message gốc vào `task-events.dlq`. Tests: load golden fixtures (READ-ONLY), idempotency, retry/DLQ (fake producer).
14
+ - [ ] T6 — Wiring + thanh lý ingest: `main.go` chạy consumer goroutine (lazy connect); router bỏ `/events` + `EventsHandler`; XÓA `internal/api/events.go` + `events_test.go`; integration test cập nhật (POST /events → 404; idempotency trên postgres thật; giữ readonly-exit criterion).
15
+ - [ ] T7 — activity.yaml ×2 FILE (P0 — sửa 1 bỏ 1 = docs lệch im lặng): canonical `contracts/openapi/activity.yaml` + snapshot `services/go-svc/internal/api/openapi/activity.yaml` GIỮ BIT-IDENTICAL: xóa `/events` path + `ActivityEventInput` + `EventAccepted` + tag events; `ActivityFeedItem.action` enum 5 giá trị; description bỏ "fire-and-forget" (Kafka consumer); `tasksByStatus` thêm `assignment_failed`.
16
+ - [ ] T8 — CI `services-go-svc.yml` 3 điểm chạm + diff-guard: (a) boot-smoke subset +kafka, `kafka-topics.sh --create` task-events + dlq tường minh, console producer publish golden fixture (exec trong container), poll feed đến khi có row (proof event→feed); (b) stats assert nới 4 keys exact; (c) giữ ≥1 proof event→feed; + job drift-guard diff 2 file yaml (precedent spring drift-guard); paths filter + contracts/openapi/activity.yaml; bỏ step POST /events.
17
+ - [ ] T9 — FE remote-tasks: `Task.status` → `TaskStatusExtended` (4 giá trị); `STATUS_LABELS` +`assignment_failed` ('Gán thất bại'); select CHỈ 3 writable; badge khi `assignment_failed`; tests cập nhật. Remote-activity: `ACTION_LABELS` +`task.assigned`/`task.assignment_failed`; `ActivityStats.tasksByStatus` +key; tests cập nhật.
18
+ - [ ] T10 — go-svc README (consumer + env mới + saga flow) + verify local static (yaml parse ×2 identical, fixtures JSON, gofmt qua CI) + push + CI watch xanh (boot-smoke kafka MỚI).
19
+ - [ ] T11 — TESTER REVIEW ĐỘC LẬP → verdict `/tmp/story/fi62/code-reviewer-sf-3-go-consumer.md` (VERDICT: APPROVED + evidence, CHECKLIST-4Q); evidence `docs/superpowers/evidence/sf-3-go-consumer/test-run.txt`; Linear comment DONE (hash + CI URL + files); story-verify sf-3 (B1-B3). KHÔNG set Done, KHÔNG merge dest.
20
+
21
+ ## Acceptance (user-visible — từ context pack sf-3.md)
22
+ 1. CI go-svc xanh: boot-smoke subset có kafka, console producer publish golden fixture → feed có row, stats nới pass, diff-guard pass.
23
+ 2. Consumer unit: golden fixture → activity row đúng; duplicate envelope id → vẫn 1 row (idempotency).
24
+ 3. Retry/DLQ: simulate svc-fail → 3 retry → `task.assignment_failed` publish + event gốc vào DLQ.
25
+ 4. Resolver: enrich userName bằng service-token; auth-mock down lúc boot → không crash; 401 → lazy re-login.
26
+ 5. GET /api/activity/events → 404; docs endpoint khớp contract (diff-guard).
27
+ 6. FE remote-tasks badge `assignment_failed` đúng; remote-activity action label mới có.
28
+
29
+ ## Boundary (KHÔNG làm)
30
+ - compose/.env.example, contracts/events/**, conventions/09, contracts/db, tasks.yaml, node-svc, spring-svc, services-node-svc.yml — đụng = FLAG.
31
+ - KHÔNG SASL/SSL; KHÔNG kafka vào readyz/depends_on; KHÔNG thử docker/kafka local — CI verify.
@@ -0,0 +1,96 @@
1
+ # Plan: SF-4 spring-svc @Transactional demo (FI-78)
2
+ Date: 2026-10-13 | Linear: FI-78 | Worktree: sf-4-spring-tx-demo (branch __STACK_ORG__/sf-4-spring-tx-demo)
3
+ Spec slice: docs/superpowers/contexts/sf-4.md · Epic spec rev 3 §SF-4 · Story FI-76
4
+
5
+ ## 0. Root cause analysis (WHY)
6
+ ### Root cause
7
+ Epic FI-76 dạy 2 tình huống transaction: Situation B (cross-service saga: SF-2/SF-3) và
8
+ Situation A (nhiều step CÙNG 1 DB — 1 transaction là đủ). spring-svc hiện CHƯA có service layer:
9
+ `TeamController` gọi thẳng `TeamRepository`, team + members được ghi bằng MỘT `save()` cascade —
10
+ không thể demo "fail giữa chừng nhiều step → rollback toàn bộ".
11
+ ### Current state (before feature)
12
+ POST /api/users/teams lưu team + members trong 1 cascade; không có chỗ nào chứng minh được
13
+ @Transactional rollback nhiều lệnh ghi. Thành viên copy boilerplate thiếu mẫu Situation A.
14
+ ### Expected outcome
15
+ `service/TeamService` tạo team qua N lệnh ghi riêng biệt (teams.save + team_members từng dòng);
16
+ member trùng `alice@demo.local` (fixture có sẵn) ở giữa → throw → rollback toàn bộ; test assert
17
+ QUA REPOSITORY rằng DB không còn team lẫn members (Rule 0).
18
+ ### Constraints & hardships
19
+ Dev machine KHÔNG Docker/JDK → mvnw verify chỉ chạy trong CI (postgres service container,
20
+ workflow hiện có). KHÔNG đổi API contract teams (path/shape giữ nguyên). KHÔNG đụng
21
+ compose/contracts/users.json (file của SF-1/epic). KHÔNG dính Kafka.
22
+ ### High-level strategy
23
+ Thêm service layer mỏng giữa controller và repository; chuyển ghi members từ cascade sang
24
+ insert từng dòng qua repository; trigger rollback deterministic theo email fixture.
25
+
26
+ ## 1. Problem (intent, NOT solution)
27
+ Thiếu mẫu Situation A (@Transactional nhiều step 1 DB) trong boilerplate — người học không có
28
+ code tham chiếu khi nào 1 transaction là đủ (so với Situation B cần saga).
29
+
30
+ ## 2. Scope
31
+ - In scope: TeamService (mới) + TeamController delegate + TeamRepository helpers + tests
32
+ (happy + rollback assert qua repository + envelope 409) + README section Situation A vs B.
33
+ - Out of scope: Kafka/outbox/compose/users.json/contracts; ĐỔI path/shape API teams; user mới
34
+ trong fixture; docker local.
35
+ - Success criteria (observable):
36
+ 1. POST team members hợp lệ → 201, team + members CÓ trong DB (assert qua repository).
37
+ 2. POST team member trùng alice@demo.local ở vị trí giữa → error envelope 409
38
+ (`$.error.code = CONFLICT`), DB KHÔNG có team lẫn members (assert qua repository).
39
+ 3. CI services-spring-svc xanh: `mvnw verify` + boot-smoke + drift-guard không vỡ.
40
+
41
+ ## 3. Touch map
42
+ - Files modify:
43
+ - `services/spring-svc/src/main/java/com/example/springsvc/service/TeamService.java` (MỚI)
44
+ - `services/spring-svc/src/main/java/com/example/springsvc/domain/TeamRepository.java` (thêm
45
+ `insertMember` native + `existsByName` + `countMembersByTeamName` + `deleteByName` cho test cleanup)
46
+ - `services/spring-svc/src/main/java/com/example/springsvc/web/TeamController.java` (delegate,
47
+ bỏ @Transactional khỏi controller)
48
+ - `services/spring-svc/src/test/java/com/example/springsvc/service/TeamServiceRollbackTest.java` (MỚI)
49
+ - `services/spring-svc/src/test/java/com/example/springsvc/web/TeamApiTest.java` (swap alice
50
+ khỏi happy tests — alice giờ là rollback trigger; thêm test envelope 409)
51
+ - `services/spring-svc/README.md` (section @Transactional demo)
52
+ - Consumers/regression candidates: TeamApiTest (dùng ALICE làm member — PHẢI swap); boot-smoke CI
53
+ (không tạo team — an toàn); FE/node callers (contract giữ nguyên).
54
+ - Shared surfaces: KHÔNG đổi API/DB schema/config. `team_members` DDL giữ nguyên.
55
+
56
+ ## 4. Design
57
+ - Approach chosen (A): giữ nguyên entity `Team` (@ElementCollection) + thêm native
58
+ `INSERT INTO team_members` trên `TeamRepository` — service gọi từng dòng. Lý do: touch map
59
+ nhỏ nhất, không thêm entity/id-class, đọc members (getTeam/list) vẫn qua collection như cũ.
60
+ - Alternatives considered:
61
+ - (B) Entity `TeamMember` + `TeamMemberRepository` riêng: chuẩn hơn về mặt học thuật nhưng
62
+ thêm entity + @EmbeddedId chỉ để demo — drive-by abstraction (P2 surgical scope).
63
+ - (C) JdbcTemplate trong service: bỏ qua repository — trái spec slice ("từng dòng qua repository").
64
+ - Edge cases / second-order effects:
65
+ - `saveAndFlush` step 1 — native INSERT phải chạy SAU khi teams row có mặt (FK team_members).
66
+ - Response createTeam echo deduped memberIds từ service (collection của entity KHÔNG bị native
67
+ insert cập nhật — không mutate managed collection, tránh cascade ghi trùng PK).
68
+ - Member UUID không tồn tại trong users: giữ nguyên hiện trạng (không FK — chấp nhận, qua qua);
69
+ trigger chỉ kích hoạt khi user tồn tại + email khớp.
70
+ - Dedupe LinkedHashSet giữ insertion order → "vị trí giữa" deterministic.
71
+ - Non-functional: không đổi perf surface (vẫn 1 tx/request); error envelope theo conventions/04.
72
+
73
+ ## 5. Implementation outline
74
+ - Tasks (ordered):
75
+ - [x] 1. TeamRepository: `insertMember` (@Modifying native), `existsByName`, `countMembersByTeamName`, `deleteByName`.
76
+ - [x] 2. TeamService (MỚI): `@Transactional createTeam(name, memberIds)` — validate name, dedupe,
77
+ saveAndFlush team, loop members: lookup users repo → email trùng trigger → ApiException.conflict
78
+ (409 CONFLICT) TRƯỚC khi insert member đó; ngược lại `insertMember`.
79
+ - [x] 3. TeamController: delegate sang service (validate DTO giữ ở controller), bỏ @Transactional.
80
+ - [x] 4. TeamServiceRollbackTest (MỚI, KHÔNG @Transactional — server tx thật; cleanup @AfterEach):
81
+ happy path assert DB qua repository; rollback assert `existsByName=false` +
82
+ `countMembersByTeamName=0`; thêm case trigger ở vị trí đầu.
83
+ - [x] 5. TeamApiTest: swap alice → bob/carol trong dedupe + echo tests; thêm test envelope 409 trigger.
84
+ - [x] 6. README: section "Situation A vs B".
85
+ - File structure: `service/` package mới ngang `web/`, `domain/` (Spring convention).
86
+ - Testing strategy: MockMvc @SpringBootTest trên postgres service container (CI) — integration
87
+ tests là chính (đúng bản chất @Transactional demo); assert Rule 0 qua repository.
88
+
89
+ ## 6. Risks & unknowns
90
+ - Must verify: `mvnw verify` trong CI (dev machine không JDK — KHÔNG chạy local).
91
+ - Unverified assumptions:
92
+ - Native INSERT + saveAndFlush cùng tx hoạt động đúng thứ tự (đã có saveAndFlush chặn; CI test
93
+ happy path sẽ chứng minh).
94
+ - Derived `deleteByName` + DB cascade ON DELETE CASCADE dọn team_members trong test cleanup.
95
+ - Trigger test data: ALICE=11111111-1111-4111-8111-111111111111, BOB=22222222-…, CAROL=33333333-…
96
+ (đã đối chiếu contracts/auth/users.json — KHÔNG sửa file này).
@@ -0,0 +1,21 @@
1
+ # Plan — SF-5 Convergence + ADR sync + docs (FI-81, story FI-76)
2
+
3
+ > Context pack: `docs/superpowers/contexts/sf-5.md` · Epic spec rev 3 §Tier 2 · Branch `__STACK_ORG__/sf-5-convergence` @f23d217.
4
+ > Verify: CI-only (máy dev không Docker) — push + `gh run watch` convergence. Services/FE/contracts READ-ONLY.
5
+
6
+ ## Tasks
7
+
8
+ - [x] T1 — `scripts/smoke/e2e.sh` saga path: PATCH task assigneeId = svc-fail fixture (55555555-5555-4555-8555-555555555555) → poll GET task `status=assignment_failed` → assert DLQ: `kafka-console-consumer` trong container kafka đọc `task-events.dlq` thấy message chứa taskId gốc. Poll nới (feed 30s, saga 60s). Opt-out `SMOKE_SAGA=0` cho đường B native không Kafka. `bash -n` sạch.
9
+ - [x] T2 — `.github/workflows/convergence.yml`: e2e job boot đủ 10 services (kafka vào title), tạo topic tường minh `task-events` + `task-events.dlq` (`--if-not-exists`, wait kafka healthy) trước e2e, timeout 20→30 phút, dump khi fail thêm DLQ + consumer logs (node/go).
10
+ - [x] T3 — `docs/walkthrough.md`: saga demo (assign fail@demo.local → badge/status `assignment_failed` + lệnh đọc DLQ), note Flyway V2 seed chạy 1 lần — pgdata volume CŨ thiếu svc users → `docker compose down -v` sau pull, CI table convergence 10 services 2 chiều, note SMOKE_SAGA cho đường B.
11
+ - [x] T4 — `README.md` sync lần cuối: 3 service + compose mô tả khớp thực tế (kafka/outbox/saga) — chỉ sửa chỗ lệch.
12
+ - [x] T5 — ADR-0008 consistency rà vs code thật (segmentio, envelope, presence-based, retry in-memory ×3, DLQ shape) — sửa ADR nếu lệch.
13
+ - [x] T6 — Security pass cuối: 9092 không expose host; JWT_SECRET/passwords không vào envelope/event payload/DLQ; `.env` không trong git.
14
+ - [x] T7 — CI convergence xanh 3/3 jobs (e2e 2 chiều + copy-dir + scaffold) — push + `gh run watch`.
15
+ - [x] T8 — Evidence `docs/superpowers/evidence/sf-5-convergence/test-run.txt` (HEAD code commit + `tdd: skipped-tdd: CI-only`), tester review độc lập, comment FI-81, story-verify.
16
+
17
+ ## Boundary
18
+
19
+ - services/*, frontend/*, contracts/* READ-ONLY — bug thấy được = report coordinator (step 7 context pack).
20
+ - KHÔNG merge main / KHÔNG PR / KHÔNG set Linear Done (coordinator làm).
21
+ - compose: chỉ health-gated depends_on nếu cần — còn lại FLAG.
@@ -0,0 +1,32 @@
1
+ # Plan — SF-2 Shell: layout, login, nav, remote fallback (VU-55, story VU-53 UI redesign)
2
+
3
+ > Tier: Standard. Spec: `docs/superpowers/contexts/ui-redesign/sf-2.md` + hand-off
4
+ > `docs/superpowers/designs/ui-redesign-direction.md` (§4 App chrome/Login card áp shell;
5
+ > visual tham chiếu `drafts/b-reference.html` — mâu thuẫn nhỏ resolved: nav active dùng
6
+ > gạch `--accent` 2px dưới theo hand-off §4 vì .wakii quy định "restyle theo hand-off",
7
+ > brand mark/user chip/ghost logout lấy từ reference).
8
+ > Worktree: `sf-2-ui-redesign-shell` (story-hub model — push nhánh, coordinator merge).
9
+ > Cứng: `pnpm-lock.yaml` KHÔNG đổi; `frontend/shared/**`, `frontend/remotes/**` READ-ONLY;
10
+ > a11y 3 test case NGUYÊN VẸN; text contracts giữ (login errors, "Thử lại", headings,
11
+ > skip-link, `data-testid="nav-user"`, `aria-label="Điều hướng chính"`).
12
+
13
+ ## Tasks
14
+
15
+ - [x] T1 — TDD RED: thêm tests shell mới trước (nav active `aria-current="page"`, HomePage quick links + demo hints, login card cấu trúc) — chạy FAIL trước khi implement
16
+ - [x] T2 — `bootstrap.tsx`: import chain `@boilerplate/fe-shared/styles/tokens.css` + `base.css` LÀM CHỦ global rồi `./styles.css` (unlayered scoped thắng base theo kiến trúc `@layer`)
17
+ - [x] T3 — `styles.css` rewrite scoped `sh-*` (topbar/nav/chip/avatar/login card/home cards/remote fallback/error banner usage); 0 element selector toàn cục; chỉ tokens; media ≤768px wrap
18
+ - [x] T4 — `NavBar.tsx`: NavLink active (`aria-current="page"` + gạch accent) + brand mark + user chip (avatar chữ cái đầu nền accent@15% + email `--fs-meta`) + logout ghost / login link; giữ contracts
19
+ - [x] T5 — `Layout.tsx`: className container/main only — skip-link text + href, `main#main-content` tabIndex, focus-on-route logic NGUYÊN VẸN
20
+ - [x] T6 — `LoginPage.tsx`: card giữa màn hình (`--c-s2` `--r-3` viền `--line` padding `--sp-6`) + wordmark "Boilerplate" + heading "Đăng nhập" (giữ role heading cho test) + hint demo mono đẹp (alice + fail@demo.local saga); behavior + error messages + redirect/deep-link GIỮ
21
+ - [x] T7 — `HomePage.tsx`: dashboard chào + quick links 2 remote (cards Tokens) + demo hints (alice@demo.local / demo-password; fail@demo.local saga) — giữ h1 "Trang chủ"
22
+ - [x] T8 — `RemoteSlot.tsx`: Suspense fallback = `Skeleton` primitive (bỏ `<p>Đang tải…</p>` — không test assert chuỗi này); error fallback visual giữ text "Không tải được phần …" + nút "Thử lại"
23
+ - [x] T9 — Verify: `pnpm test` + `pnpm typecheck` shell xanh (a11y 3 case nguyên vẹn); browser verify 3 tầng (DOM eval / VISUAL so `b-reference.png` / FLOW login→nav active→dashboard→remote-fallback qua SHELL_PORT=3100, remote-down simulate port chết — KHÔNG kill container docker chung) + screenshots evidence
24
+ - [x] T10 — Code-reviewer độc lập trên diff SF → verdict post Linear VU-55 (VERDICT + CHECKLIST-4Q); CHANGES-REQUESTED → fix → re-review tới APPROVED
25
+ - [x] T11 — Evidence `evidence/sf-2-ui-redesign-shell/test-run.txt` (HEAD hash + `tdd:` line) + plan tick + commit atomic + push `__STACK_ORG__/sf-2-ui-redesign-shell` + `story-verify sf-2` sạch (B4 merge/B5 Done là phần coordinator) — KHÔNG set Done
26
+
27
+ ## Exit criteria (ACCEPTANCE pack)
28
+
29
+ 1. Qua gateway :8080 hoặc dev :3100: login card đẹp giữa màn hình + hint đọc được; sau login nav hiện email chip + trang đang đứng active; HomePage dashboard có quick links Tasks/Activity + hint saga.
30
+ 2. ≤768px: nav wrap, không overflow ngang.
31
+ 3. Remote down: slot skeleton lúc tải + fallback đẹp nút "Thử lại" hoạt động.
32
+ 4. `pnpm test` + `pnpm typecheck` shell xanh; 3 test a11y pass nguyên vẹn; 0 deps mới (lockfile không đổi).
@@ -0,0 +1,34 @@
1
+ # Plan — SF-3 ui-redesign: TasksPage redesign + UX gaps (VU-56)
2
+
3
+ > Story VU-53 · spec: `docs/superpowers/specs/2026-10-14-sf-3-ui-redesign.md` · slice canonical: `docs/superpowers/contexts/ui-redesign/sf-3.md`
4
+ > Worktree: `sf-3-ui-redesign-tasks` (nhánh `__STACK_ORG__/sf-3-ui-redesign-tasks`, base = đích `__STACK_ORG__/story-vu53-ui-redesign` @492d072 — SF-1 đã merge) · Tier: Full · TDD: RED→GREEN per task
5
+ > Commit: atomic per task, `feat(sf-3): …` / `test(sf-3): …`. KHÔNG merge, KHÔNG đụng shell/** + activity/** + shared/**.
6
+
7
+ ## Phase 0 — Impact analysis (SF-scoped; epic đã có P0 10 chiều, đây là phần bám code thật của slice)
8
+
9
+ **Problem**: TasksPage 181 dòng 1 component — list 1 cột + select status; bỏ lỡ DELETE/edit/assignee/pagination/filter dù `tasks.yaml` có sẵn hết. Là màn hình demo chính (walkthrough 4.2) nhưng chưa xứng direction B.
10
+
11
+ **Touch map** (context pack — giữ nguyên): SỞ HỮU `frontend/remotes/tasks/**` (TasksPage.tsx, components/*.tsx MỚI, styles.css MỚI, api.ts, standalone.tsx, tests/*). READ-ONLY: shell/**, activity/**, shared/**, rspack.config.mjs, env.d.ts, contracts/**, platform/**, services/**. `index.tsx` giữ nguyên (async boundary RUNTIME-006).
12
+
13
+ **Second-order effects**: (1) `fetchTasks` đổi signature — consumer duy nhất là package này (grep xác nhận); (2) css chunk mới theo expose — shell đã có css experiment + runtime chunk fetch (SF-1 spike); (3) "x/total" giờ = số đã tải/total (load-more làm x tăng) — format chuỗi giữ nguyên cho test contract; (4) standalone :4101 origin không token → 401 banner là hành vi đúng (đã document trong banner).
14
+
15
+ **Alternatives đã cân**: window.confirm vs inline confirm → inline (testable + styled); sửa BadgeProps thêm aria-label vs bọc span → bọc span (fe-shared đóng băng); Skeleton lúc load-more vs nút busy → nút busy (không nhảy layout); PAGE_SIZE 10 vs 20 → 10 (demo thấy pagination sớm).
16
+
17
+ **Risks**: tên label trùng "Tiêu đề" (mît: aria-label riêng cho edit); nested role=status khi bọc Badge (chấp nhận — giữ contract aria-label); css import trong vitest (vite stub mặc định — verify khi chạy test); SF-2/SF-4 song song (mît: chỉ touch tasks/** + docs của mình).
18
+
19
+ **Dimensions sweep**: functional ✓ (13 mục slice) · technical ✓ (MF/css/scope) · data ✓ (clamp limit/offset đúng contract) · perf — skip (demo scale, list ≤100) · security ✓ (React escape text user; confirm chống xoá nhầm; không secrets/asset ngoài) · backward-compat ✓ (registry/aria/labels giữ) · UX ✓ (lõi của SF) · maintenance ✓ (tách 5 component) · operational — skip (không infra) · business ✓ (màn demo chính).
20
+
21
+ ## Tasks
22
+
23
+ - [x] T1 — `api.ts` mở rộng: `FetchTasksParams` (limit clamp 1..100 default 10 / offset ≥ 0 / status), `buildTasksPath`, `deleteTask` (DELETE 204); RED→GREEN `api.test.ts` (URL mới + params + clamp + delete + 404 envelope)
24
+ - [x] T2 — Components RED: viết `TasksPage.test.tsx` mới đủ ~17 case theo component tree (sửa inline PATCH payload, xoá confirm DELETE, Tải thêm offset, filter ?status=, per-item busy, assignee/createdAt, skeleton) — chạy ĐỎ
25
+ - [x] T3 — Components GREEN: `components/status.ts` (labels/variants/writable) + `StatusBadge` + `StatusSelect` + `TaskForm` + `TaskItem` + `TaskList` + `TasksPage` rewrite (state owner, filter chips, skeleton/empty/load-more, error banner 503 giữ) — chạy XANH
26
+ - [x] T4 — `styles.css` scoped (`.tsk-*`, tokens, media ≤768px) + standalone banner debug đẹp (standalone.tsx, giữ import tokens+base SF-1)
27
+ - [x] T5 — Full verify package: `pnpm test` + `pnpm typecheck` + `pnpm build` tasks — 3 lệnh xanh; ghi `docs/superpowers/evidence/sf-3-ui-redesign-tasks/test-run.txt` (HEAD hash + tdd line)
28
+ - [x] T6 — Rule 0 browser verify 3 tầng: DOM eval + screenshot so direction + flow login→CRUD→filter→load-more→saga 4b badge→logout trên dev stack isolate (:3100 shell + :4101 tasks dev, backend compose) + standalone :4101
29
+ - [x] T7 — Code-reviewer độc lập (cyan) trên diff SF → verdict APPROVED + CHECKLIST-4Q post lên VU-56; CHANGES-REQUESTED → fix → re-review
30
+ - [x] T8 — Commit cuối: evidence hash sync (HEAD~1) + improvements-log + plan tick; push `-u origin __STACK_ORG__/sf-3-ui-redesign-tasks`; chạy `~/.claude/bin/story-verify sf-3` — B1/B2/B2b/B3 phải PASS (B4 pending merge là trạng thái đúng của story-hub — coordinator merge)
31
+
32
+ ## Exit criteria
33
+
34
+ Context pack ACCEPTANCE từng dòng kiểm được (T6 evidence); tests+typecheck xanh (T5); reviewer APPROVED (T7); gate B1/B2/B2b/B3 PASS (T8).
@@ -0,0 +1,35 @@
1
+ # Plan — SF-5 ui-redesign: Convergence — browser walkthrough + docs + security (VU-58)
2
+
3
+ > Story VU-53 · spec: `docs/superpowers/specs/2026-10-14-sf-5-ui-redesign.md` · slice canonical: `docs/superpowers/contexts/ui-redesign/sf-5.md`
4
+ > Worktree: `sf-5-ui-redesign-conv` (nhánh `__STACK_ORG__/sf-5-ui-redesign-conv`, base = đích `__STACK_ORG__/story-vu53-ui-redesign` @1a6a7aa — SF-1+2+3+4 đã merge) · Tier: **Full** (convergence — nhiều lớp verify)
5
+ > Commit: atomic per task, `docs(sf-5): …` / `test(sf-5): …`. KHÔNG merge, KHÔNG đụng `frontend/** services/** scripts/** platform/**` (READ-ONLY — bug = report coordinator).
6
+
7
+ ## Phase 0 — Impact analysis (SF-scoped; epic đã có P0 10 chiều)
8
+
9
+ **Problem**: Story VU-53 có UI mới (SF-1..4 merged) nhưng CHƯA ai chứng minh 8/8 acceptance epic trên build compose thật qua trình duyệt; docs (walkthrough.md mục 4/4b, README repo-map, FE READMEs) còn mô tả UI cũ/trống; security pass cuối story chưa chạy. CI e2e là API-level — không nhìn UI (epic: human gate duy nhất).
10
+
11
+ **Touch map** (context pack — giữ nguyên): SỞ HỮU `docs/walkthrough.md`, `README.md`, `frontend/{shell,remotes/*}/README.md`, `docs/superpowers/evidence/ui-redesign/**` (mới), `docs/superpowers/evidence/sf-5-ui-redesign-conv/**` (mới — gate B1), `docs/superpowers/improvements-log.md`, spec/plan của mình. READ-ONLY toàn bộ còn lại (`frontend/** services/** platform/** scripts/** contracts/** .github/**`).
12
+
13
+ **Second-order effects**: (1) stack compose 10 container đang chạy 15h từ build story-đích — nội dung code = HEAD của nhánh đích = HEAD của nhánh SF-5 (SF-5 chỉ thêm docs → build vẫn đúng, không cần rebuild); (2) walkthrough tạo data thật (tasks) trên DB demo — chấp nhận (repo demo, người walkthrough cần data để thấy pagination/load-more); (3) kill container remote-tasks làm healthcheck đỏ tạm thời → start lại + đợi healthy trước khi kết thúc; (4) docs đổi nhãn UI = phải khớp NGHIÊM text thật trên màn (badge "Gán thất bại", nút "Tải thêm", "Thử lại") — lấy từ screenshot/DOM thực, không từ nhớ.
14
+
15
+ **Alternatives đã cân**: (a) walkthrough trên dev stack isolate như SF-2/3/4 → LOẠI, pack ép compose :8080 là chuẩn duy nhất; (b) 375px bằng CSS media-query analysis → LOẠI, Rule 0 đòi pixel thật — headless Chrome cùng build; (c) seed pagination data qua UI 11 lần → chỉ dùng khi thiếu, curl seed nhanh hơn nhưng vẫn đi CRUD qua UI; (d) tự tick human-gate 8/8 → CẤM, để coordinator relay user.
16
+
17
+ **Risks**: Orca CDP screenshot timeout (tái diễn SF-2/SF-24/SF-1) → fallback headless Chrome cùng build, khai báo trung thực (FI-464); saga badge trễ (retry ×3 backoff) → poll tối đa ~60s; container kill quên start lại → checklist khôi phục trước khi rời bước; `pnpm -r test` kéo cả node-svc/spike (workspace lớn hơn 3 FE package) → đọc output theo package, 3 FE package phải xanh.
18
+
19
+ **Dimensions sweep**: functional ✓ (8 acceptance = lõi) · technical ✓ (compose topology kill-remote, browser tooling) · data ✓ (demo data walkthrough tạo) · perf — skip (không code, không hot path) · security ✓ (security pass cuối story là deliverable) · backward-compat ✓ (docs-only, không đụng contract) · UX ✓ (375px + walkthrough đọc được bởi người mới) · maintenance ✓ (docs sync chống drift UI↔docs) · operational ✓ (stack sống + hướng dẫn human gate) · business ✓ (epic chỉ xong khi người đi hết walkthrough).
20
+
21
+ ## Tasks
22
+
23
+ - [x] T1 — Full suite: `pnpm -r test` + `pnpm -r typecheck` + `pnpm -r build` (3 FE package xanh) + `git diff pnpm-lock.yaml` rỗng → ghi `docs/superpowers/evidence/sf-5-ui-redesign-conv/test-run.txt` (hash + tdd line)
24
+ - [x] T2 — e2e smoke PASS 1 lần chứng minh: `bash scripts/smoke/e2e.sh` (2 chiều happy+saga) → output vào evidence
25
+ - [x] T3 — Rule 0 browser walkthrough 8/8 trên compose :8080 (3 tầng DOM/VISUAL/FLOW): login → nav active → Tasks CRUD (tạo/sửa inline/đổi status/xoá confirm/filter/Tải thêm + x/total) → Activity phản ánh (stats + feed vi-VN) → saga 4b (assign fail@demo.local → badge "Gán thất bại" → re-assign bob + PATCH todo → về luồng thường) → kill remote-tasks → shell còn nguyên + fallback "Thử lại" + retry OK → activity vẫn chạy → standalone :4001/:4002 có style. Screenshots → `docs/superpowers/evidence/ui-redesign/conv-*.png`
26
+ - [x] T4 — Responsive 375px: 3 màn chính (Tasks/Activity/Home sau login) không overflow ngang — headless Chrome cùng build :8080, screenshots + DOM check `scrollWidth<=innerWidth` vào evidence
27
+ - [x] T5 — Docs sync: `docs/walkthrough.md` mục 4/4b đối chiếu UI mới (nhãn/badge thật) + compose kill-remote; `README.md` repo-map (fe-shared design tokens + UI primitives); `frontend/shell/README.md` + `frontend/remotes/{tasks,activity}/README.md` import tokens/primitives
28
+ - [x] T6 — Security pass: scan diff toàn story (secrets pattern, .env không track, exec-bit mới, asset ngoài/CSP untouched) + scaffold sanity verify-only (output có `frontend/shared/src/{styles,ui}` + build shell OK + xoá) → kết quả vào evidence
29
+ - [x] T7 — `docs/superpowers/improvements-log.md`: patterns hội tụ của SF-5
30
+ - [x] T8 — Code-reviewer độc lập (cyan) trên diff SF (docs/evidence) → APPROVED + CHECKLIST-4Q post VU-58; CHANGES-REQUESTED → fix → re-review
31
+ - [x] T9 — Commit cuối + push `-u origin __STACK_ORG__/sf-5-ui-redesign-conv` + `~/.claude/bin/story-verify sf-5` (B1/B2/B2b/B3 sạch; B4 pending merge = đúng story-hub) + worktree comment hướng dẫn walkthrough human gate + audit log VU-58. KHÔNG set Done Linear.
32
+
33
+ ## Exit criteria
34
+
35
+ Context pack ACCEPTANCE từng dòng kiểm được (T3/T4 evidence); suite + smoke xanh (T1/T2); reviewer APPROVED (T8); gate B1/B2/B2b/B3 PASS (T9 — B4 pending merge là trạng thái đúng của story-hub, coordinator merge); stack :8080 còn sống + hướng dẫn walkthrough đã đẩy coordinator.