@micha.bigler/ui-core-micha 3.14.3 → 4.0.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 (367) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +7 -0
  3. package/dist/auth/UserMenu.js +1 -1
  4. package/dist/auth/apiClient.js +7 -6
  5. package/dist/chat/ChatList.js +1 -1
  6. package/dist/chat/ChatThread.js +2 -1
  7. package/dist/chat/ChatWorkspace.js +1 -1
  8. package/dist/chat/ModelPicker.js +2 -5
  9. package/dist/chat/kitSxRegistry.js +9 -0
  10. package/dist/chat/useChatSocket.js +1 -1
  11. package/dist/components/LoginForm.js +1 -1
  12. package/dist/components/SecurityComponent.js +1 -1
  13. package/dist/components/UserListComponent.js +2 -8
  14. package/dist/components/charts/ChartFrame.js +1 -1
  15. package/dist/components/charts/ScatterChart.js +2 -1
  16. package/dist/components/charts/kitSxRegistry.js +6 -0
  17. package/dist/entries/charts.js +6 -0
  18. package/dist/entries/chat.js +8 -0
  19. package/dist/entries/markdown.js +1 -0
  20. package/dist/index.js +0 -14
  21. package/dist/layout/SectionNav.js +1 -1
  22. package/dist/messaging/AttachmentList.js +2 -2
  23. package/dist/messaging/Composer.js +2 -1
  24. package/dist/messaging/ConversationLaunchers.js +1 -4
  25. package/dist/messaging/ConversationList.js +1 -1
  26. package/dist/messaging/DirectMessageLauncher.js +1 -1
  27. package/dist/messaging/MessagingProvider.js +0 -0
  28. package/dist/messaging/PollCard.js +7 -5
  29. package/dist/messaging/ReadTicks.js +2 -2
  30. package/dist/messaging/Thread.js +5 -3
  31. package/dist/notifications/NotificationBell.js +4 -7
  32. package/dist/notifications/NotificationSettings.js +1 -1
  33. package/dist/onboarding/OnboardingProvider.js +3 -6
  34. package/dist/pages/AccountPage.js +1 -2
  35. package/dist/pages/LoginPage.js +2 -3
  36. package/dist/pages/PasswordChangePage.js +2 -3
  37. package/dist/pages/PasswordInvitePage.js +2 -3
  38. package/dist/pages/PasswordResetRequestPage.js +2 -3
  39. package/dist/pages/SignUpPage.js +2 -3
  40. package/dist/pages/SignupConfirmPage.js +2 -3
  41. package/dist/theme/createAppTheme.js +5 -4
  42. package/dist/theme/kitSxEntry.js +11 -0
  43. package/dist/theme/kitSxRegistry.js +2 -15
  44. package/dist/theme/themeCompleteness.js +3 -12
  45. package/dist/utils/auth-errors.js +4 -3
  46. package/package.json +41 -16
  47. package/.github/workflows/publish.yml +0 -126
  48. package/DESIGN.md +0 -60
  49. package/WORK_ORDERS.md +0 -148
  50. package/dev/entries.jsx +0 -721
  51. package/dev/fixtures.js +0 -26
  52. package/dev/main.jsx +0 -75
  53. package/dev/mockTransport.jsx +0 -128
  54. package/docs/CHART-LAYOUT.md +0 -157
  55. package/docs/DARK-TOKENS.md +0 -140
  56. package/docs/TYPE-SCALE.md +0 -111
  57. package/docs/messaging-deviations.md +0 -118
  58. package/index.html +0 -12
  59. package/renovate.json +0 -10
  60. package/scripts/chart-api-census.mjs +0 -415
  61. package/src/auth/AuthContext.jsx +0 -158
  62. package/src/auth/ReauthModal.jsx +0 -82
  63. package/src/auth/UserMenu.jsx +0 -121
  64. package/src/auth/apiClient.jsx +0 -232
  65. package/src/auth/authApi.jsx +0 -539
  66. package/src/auth/authConfig.jsx +0 -34
  67. package/src/auth/reauth.js +0 -47
  68. package/src/chat/ChatComposer.jsx +0 -36
  69. package/src/chat/ChatList.jsx +0 -87
  70. package/src/chat/ChatThread.jsx +0 -128
  71. package/src/chat/ChatWorkspace.jsx +0 -244
  72. package/src/chat/MarkdownReply.jsx +0 -22
  73. package/src/chat/ModelPicker.jsx +0 -85
  74. package/src/chat/api.js +0 -18
  75. package/src/chat/useChatSocket.js +0 -32
  76. package/src/chat/wire.js +0 -7
  77. package/src/components/AccessCodeManager.jsx +0 -288
  78. package/src/components/AccessCodeSingleUseToggle.jsx +0 -92
  79. package/src/components/AllowedEmailDomainsManager.jsx +0 -92
  80. package/src/components/AuthFactorRequirementCard.jsx +0 -95
  81. package/src/components/BulkInviteCsvTab.jsx +0 -198
  82. package/src/components/EmptyState.jsx +0 -38
  83. package/src/components/LoginForm.jsx +0 -159
  84. package/src/components/MFAComponent.jsx +0 -350
  85. package/src/components/MfaLoginComponent.jsx +0 -252
  86. package/src/components/MobileBottomNav.jsx +0 -82
  87. package/src/components/PasskeysComponent.jsx +0 -252
  88. package/src/components/PasswordChangeForm.jsx +0 -87
  89. package/src/components/PasswordResetRequestForm.jsx +0 -43
  90. package/src/components/PasswordSetForm.jsx +0 -97
  91. package/src/components/ProfileComponent.jsx +0 -348
  92. package/src/components/QrSignupManager.jsx +0 -404
  93. package/src/components/QrSignupValidityManager.jsx +0 -106
  94. package/src/components/RegistrationMethodsManager.jsx +0 -150
  95. package/src/components/SecurityComponent.jsx +0 -141
  96. package/src/components/SocialLoginButtons.jsx +0 -83
  97. package/src/components/SoftChip.jsx +0 -93
  98. package/src/components/StatTile.jsx +0 -39
  99. package/src/components/SupportRecoveryRequestsTab.jsx +0 -482
  100. package/src/components/TurnstileWidget.jsx +0 -99
  101. package/src/components/UserInviteComponent.jsx +0 -76
  102. package/src/components/UserListComponent.jsx +0 -618
  103. package/src/components/charts/BarChart.jsx +0 -102
  104. package/src/components/charts/ChartFrame.jsx +0 -214
  105. package/src/components/charts/LineChart.jsx +0 -126
  106. package/src/components/charts/ScatterChart.jsx +0 -299
  107. package/src/components/charts/TimeSeriesChart.jsx +0 -300
  108. package/src/components/charts/chartDefaults.js +0 -644
  109. package/src/components/charts/chartLabels.js +0 -36
  110. package/src/components/charts/exportChart.js +0 -258
  111. package/src/components/charts/formatters.js +0 -39
  112. package/src/components/charts/palette.js +0 -33
  113. package/src/components/charts/yearTickInterval.js +0 -7
  114. package/src/i18n/authTranslations.ts +0 -2651
  115. package/src/i18n/chartsTranslations.ts +0 -91
  116. package/src/i18n/chatTranslations.ts +0 -55
  117. package/src/i18n/messagingTranslations.ts +0 -120
  118. package/src/i18n/notificationsTranslations.ts +0 -32
  119. package/src/i18n/onboardingTranslations.ts +0 -29
  120. package/src/i18n/sectionNavTranslations.ts +0 -20
  121. package/src/i18n/uiCoreTranslations.js +0 -29
  122. package/src/i18n/userMenuTranslations.ts +0 -5
  123. package/src/index.js +0 -158
  124. package/src/layout/PageLayout.jsx +0 -36
  125. package/src/layout/SectionNav.jsx +0 -320
  126. package/src/messaging/AttachmentList.jsx +0 -145
  127. package/src/messaging/Composer.jsx +0 -197
  128. package/src/messaging/ConversationLaunchers.jsx +0 -51
  129. package/src/messaging/ConversationList.jsx +0 -109
  130. package/src/messaging/DirectMessageLauncher.jsx +0 -112
  131. package/src/messaging/MessageBubble.jsx +0 -183
  132. package/src/messaging/MessagingProvider.jsx +0 -0
  133. package/src/messaging/MessagingScopeConfig.jsx +0 -24
  134. package/src/messaging/PollCard.jsx +0 -163
  135. package/src/messaging/ReactionBar.jsx +0 -43
  136. package/src/messaging/ReadTicks.jsx +0 -82
  137. package/src/messaging/Thread.jsx +0 -195
  138. package/src/messaging/api.js +0 -48
  139. package/src/messaging/composerImageCompression.js +0 -35
  140. package/src/messaging/linkifyText.jsx +0 -37
  141. package/src/notifications/NotificationBell.jsx +0 -84
  142. package/src/notifications/NotificationSettings.jsx +0 -330
  143. package/src/notifications/NotificationsProvider.jsx +0 -224
  144. package/src/notifications/PopupSurface.jsx +0 -105
  145. package/src/notifications/api.js +0 -55
  146. package/src/notifications/feedApi.js +0 -18
  147. package/src/notifications/realtime.jsx +0 -138
  148. package/src/notifications/serviceWorker/sw.js +0 -50
  149. package/src/onboarding/OnboardingProvider.jsx +0 -326
  150. package/src/onboarding/OnboardingWizard.jsx +0 -61
  151. package/src/onboarding/WizardDialogShell.jsx +0 -51
  152. package/src/onboarding/api.js +0 -13
  153. package/src/onboarding/stepSelection.js +0 -16
  154. package/src/onboarding/steps/BrowserPushStep.jsx +0 -121
  155. package/src/onboarding/steps/CompleteNameStep.jsx +0 -46
  156. package/src/onboarding/steps/CookieConsentStep.jsx +0 -133
  157. package/src/onboarding/steps/PwaInstallStep.jsx +0 -47
  158. package/src/pages/AccountPage.jsx +0 -394
  159. package/src/pages/LoginPage.jsx +0 -343
  160. package/src/pages/PasswordChangePage.jsx +0 -62
  161. package/src/pages/PasswordInvitePage.jsx +0 -177
  162. package/src/pages/PasswordResetRequestPage.jsx +0 -68
  163. package/src/pages/SignUpPage.jsx +0 -268
  164. package/src/pages/SignupConfirmPage.jsx +0 -155
  165. package/src/testing/checkKitIntegration.js +0 -233
  166. package/src/theme/createAppTheme.js +0 -423
  167. package/src/theme/fonts.js +0 -3
  168. package/src/theme/index.js +0 -21
  169. package/src/theme/kitSxRegistry.js +0 -285
  170. package/src/theme/themeCompleteness.js +0 -1045
  171. package/src/theme/tokens.js +0 -478
  172. package/src/utils/auth-errors.js +0 -76
  173. package/src/utils/authService.js +0 -223
  174. package/src/utils/resolveErrorText.js +0 -28
  175. package/src/utils/webauthn.js +0 -51
  176. package/tests/AccountPage.profileStatements.test.jsx +0 -162
  177. package/tests/AccountPage.test.jsx +0 -200
  178. package/tests/AuthContext.test.jsx +0 -129
  179. package/tests/BarChart.test.jsx +0 -112
  180. package/tests/BrowserPushStep.test.jsx +0 -110
  181. package/tests/ChartFrame.test.jsx +0 -336
  182. package/tests/ConversationList.test.jsx +0 -144
  183. package/tests/CookieConsentStep.test.jsx +0 -69
  184. package/tests/EmptyState.test.jsx +0 -62
  185. package/tests/LineChart.test.jsx +0 -80
  186. package/tests/MessagingProvider.test.jsx +0 -50
  187. package/tests/MobileBottomNav.test.jsx +0 -319
  188. package/tests/NotificationBell.test.jsx +0 -60
  189. package/tests/NotificationSettings.test.jsx +0 -276
  190. package/tests/NotificationsProvider.test.jsx +0 -240
  191. package/tests/OnboardingProvider.test.jsx +0 -294
  192. package/tests/OnboardingWizard.test.jsx +0 -143
  193. package/tests/PasswordChangeForm.test.jsx +0 -70
  194. package/tests/PasswordInvitePage.test.jsx +0 -142
  195. package/tests/PasswordSetForm.test.jsx +0 -70
  196. package/tests/PopupSurface.test.jsx +0 -142
  197. package/tests/ProfileComponent.refresh.test.jsx +0 -194
  198. package/tests/QrSignupManager.registrationContext.test.jsx +0 -106
  199. package/tests/QrSignupManagerInfoBox.test.jsx +0 -49
  200. package/tests/ScatterChart.test.jsx +0 -270
  201. package/tests/SectionNav.test.jsx +0 -363
  202. package/tests/SignUpPage.test.jsx +0 -208
  203. package/tests/SoftChip.test.jsx +0 -105
  204. package/tests/StatTile.test.jsx +0 -57
  205. package/tests/Thread.test.jsx +0 -151
  206. package/tests/TimeSeriesChart.test.jsx +0 -367
  207. package/tests/UserListComponent.test.jsx +0 -192
  208. package/tests/UserMenu.test.jsx +0 -171
  209. package/tests/apiClientLanguage.test.js +0 -33
  210. package/tests/apiClientPublicPaths.test.js +0 -178
  211. package/tests/authApiLogin.test.js +0 -42
  212. package/tests/authApiRegistration.test.js +0 -31
  213. package/tests/authErrorCodeRendering.test.jsx +0 -77
  214. package/tests/authErrors.test.js +0 -74
  215. package/tests/authTranslations.test.js +0 -74
  216. package/tests/chart-api-census.test.js +0 -366
  217. package/tests/chartAxisTickBand.test.jsx +0 -95
  218. package/tests/chartDefaults.test.js +0 -902
  219. package/tests/chartLabels.test.js +0 -50
  220. package/tests/chartsPalette.test.js +0 -99
  221. package/tests/chatApi.test.js +0 -48
  222. package/tests/chatDriverNames.test.jsx +0 -71
  223. package/tests/chatExports.test.js +0 -3
  224. package/tests/chatList.test.jsx +0 -84
  225. package/tests/chatPicker.test.jsx +0 -82
  226. package/tests/chatSocket.test.jsx +0 -26
  227. package/tests/chatThread.test.jsx +0 -116
  228. package/tests/chatTranslations.test.js +0 -47
  229. package/tests/chatWorkspace.test.jsx +0 -234
  230. package/tests/checkKitIntegration.test.jsx +0 -219
  231. package/tests/createAppTheme.test.js +0 -132
  232. package/tests/createAppThemeDark.test.js +0 -127
  233. package/tests/createAppThemeLightGuard.test.js +0 -40
  234. package/tests/createAppThemePageContrast.test.js +0 -108
  235. package/tests/createAppThemeTypography.test.js +0 -53
  236. package/tests/errorCallSiteGuard.test.js +0 -32
  237. package/tests/exportChart.test.js +0 -313
  238. package/tests/feedApi.test.js +0 -46
  239. package/tests/fixtures/light-theme-baseline.json +0 -2234
  240. package/tests/i18nAggregate.test.js +0 -120
  241. package/tests/i18nGermanVariant.test.js +0 -65
  242. package/tests/loginPageErrorResolution.test.jsx +0 -102
  243. package/tests/messagingApi.test.js +0 -32
  244. package/tests/messagingChunk6.test.jsx +0 -116
  245. package/tests/messagingCompactBubble.test.jsx +0 -64
  246. package/tests/messagingComposer.test.jsx +0 -136
  247. package/tests/messagingComposerChunk5.test.jsx +0 -113
  248. package/tests/messagingContractConformance.test.js +0 -69
  249. package/tests/messagingDirectMessageLauncher.test.jsx +0 -151
  250. package/tests/messagingExports.test.js +0 -21
  251. package/tests/messagingInteractions.test.jsx +0 -136
  252. package/tests/messagingLastMessagePreview.test.jsx +0 -93
  253. package/tests/messagingLinkify.test.jsx +0 -51
  254. package/tests/messagingMessageActions.test.jsx +0 -163
  255. package/tests/messagingMsg6.test.jsx +0 -105
  256. package/tests/messagingMsg6f.test.jsx +0 -155
  257. package/tests/messagingMsg6g.test.jsx +0 -166
  258. package/tests/messagingMsg6h.test.jsx +0 -136
  259. package/tests/messagingMsg6i.test.jsx +0 -129
  260. package/tests/messagingPollRendering.test.jsx +0 -142
  261. package/tests/messagingReactionMerge.test.jsx +0 -77
  262. package/tests/messagingReadTicksTooltip.test.jsx +0 -36
  263. package/tests/messagingThreadReceipts.test.jsx +0 -178
  264. package/tests/messagingThreadingQuoting.test.jsx +0 -87
  265. package/tests/messagingUnreadLifecycle.test.jsx +0 -78
  266. package/tests/notificationsApi.test.js +0 -41
  267. package/tests/notificationsExports.test.js +0 -34
  268. package/tests/onboardingDescriptors.test.js +0 -132
  269. package/tests/packageTreeShaking.test.js +0 -126
  270. package/tests/realtime.test.jsx +0 -219
  271. package/tests/resolveErrorText.test.js +0 -72
  272. package/tests/stepSelection.test.js +0 -53
  273. package/tests/themeCompleteness.test.js +0 -626
  274. package/tests/timeSeriesLegend.test.js +0 -99
  275. package/tests/userScreenTranslations.test.jsx +0 -218
  276. package/tsconfig.build.json +0 -18
  277. package/vite.config.mjs +0 -6
  278. package/work-orders/AUTH-1.md +0 -74
  279. package/work-orders/AUTH-2.md +0 -74
  280. package/work-orders/AUTH-4.md +0 -183
  281. package/work-orders/AUTH-5.md +0 -154
  282. package/work-orders/AUTH-7.md +0 -181
  283. package/work-orders/AUTH-8.md +0 -184
  284. package/work-orders/CHART-1.md +0 -285
  285. package/work-orders/CHART-2.md +0 -222
  286. package/work-orders/CHART-3.md +0 -163
  287. package/work-orders/CHART-4.md +0 -203
  288. package/work-orders/CHART-5.md +0 -226
  289. package/work-orders/CHART-6.md +0 -428
  290. package/work-orders/CHART-7.md +0 -175
  291. package/work-orders/DX-1.md +0 -169
  292. package/work-orders/DX-2.md +0 -188
  293. package/work-orders/DX-3.md +0 -195
  294. package/work-orders/I18N-1.md +0 -254
  295. package/work-orders/I18N-3.md +0 -207
  296. package/work-orders/MSG-3.md +0 -375
  297. package/work-orders/MSG-3b.md +0 -1002
  298. package/work-orders/MSG-3c.md +0 -378
  299. package/work-orders/MSG-3d.md +0 -268
  300. package/work-orders/MSG-3e.md +0 -164
  301. package/work-orders/MSG-3f.md +0 -391
  302. package/work-orders/MSG-6e.md +0 -308
  303. package/work-orders/MSG-6f.md +0 -214
  304. package/work-orders/MSG-6g.md +0 -244
  305. package/work-orders/MSG-6h.md +0 -238
  306. package/work-orders/MSG-6i.md +0 -271
  307. package/work-orders/MSG-6j.md +0 -117
  308. package/work-orders/NOTIF-12.md +0 -214
  309. package/work-orders/NOTIF-13.md +0 -142
  310. package/work-orders/NOTIF-14.md +0 -151
  311. package/work-orders/PRIM-1.md +0 -177
  312. package/work-orders/SHELL-1.md +0 -255
  313. package/work-orders/SHELL-2.md +0 -197
  314. package/work-orders/SHELL-3.md +0 -359
  315. package/work-orders/SHELL-4.md +0 -351
  316. package/work-orders/SHELL-5.md +0 -345
  317. package/work-orders/SHELL-6.md +0 -210
  318. package/work-orders/THEME-1.md +0 -587
  319. package/work-orders/THEME-10.md +0 -303
  320. package/work-orders/THEME-11.md +0 -208
  321. package/work-orders/THEME-2.md +0 -339
  322. package/work-orders/THEME-3.md +0 -210
  323. package/work-orders/THEME-4.md +0 -271
  324. package/work-orders/THEME-5.md +0 -341
  325. package/work-orders/THEME-6.md +0 -247
  326. package/work-orders/THEME-7.md +0 -82
  327. package/work-orders/THEME-8.md +0 -211
  328. package/work-orders/THEME-9.md +0 -194
  329. package/work-orders/UCM-AUTH-10.md +0 -490
  330. package/work-orders/UCM-AUTH-11.md +0 -185
  331. package/work-orders/UCM-AUTH-12.md +0 -98
  332. package/work-orders/UCM-AUTH-13.md +0 -47
  333. package/work-orders/UCM-AUTH-9.md +0 -207
  334. package/work-orders/UCM-CHART-10.md +0 -150
  335. package/work-orders/UCM-CHART-11.md +0 -132
  336. package/work-orders/UCM-CHART-12.md +0 -348
  337. package/work-orders/UCM-CHART-13.md +0 -122
  338. package/work-orders/UCM-CHART-14.md +0 -198
  339. package/work-orders/UCM-CHART-15.md +0 -187
  340. package/work-orders/UCM-CHART-16.md +0 -169
  341. package/work-orders/UCM-CHART-17.md +0 -195
  342. package/work-orders/UCM-CHART-18.md +0 -200
  343. package/work-orders/UCM-CHART-8.md +0 -147
  344. package/work-orders/UCM-CHART-9.md +0 -265
  345. package/work-orders/UCM-CHAT-1.md +0 -190
  346. package/work-orders/UCM-CHAT-2.md +0 -75
  347. package/work-orders/UCM-DEP-1.md +0 -63
  348. package/work-orders/UCM-I18N-4.md +0 -226
  349. package/work-orders/UCM-I18N-5.md +0 -211
  350. package/work-orders/UCM-MSG-20.md +0 -192
  351. package/work-orders/UCM-PRIM-2.md +0 -114
  352. package/work-orders/UCM-SHELL-7.md +0 -134
  353. package/work-orders/UCM-SHELL-8.md +0 -125
  354. package/work-orders/UCM-TEST-1.md +0 -304
  355. package/work-orders/UCM-THEME-13.md +0 -69
  356. package/work-orders/UCM-THEME-14.md +0 -312
  357. package/work-orders/UCM-THEME-15.md +0 -356
  358. package/work-orders/UCM-THEME-16.md +0 -80
  359. package/work-orders/UCM-THEME-17.md +0 -111
  360. package/work-orders/UCM-THEME-18.md +0 -184
  361. package/work-orders/assets/AUTH-4-user-list-card.html +0 -407
  362. package/work-orders/assets/PRIM-1-dashboard-primitives.html +0 -624
  363. package/work-orders/assets/SHELL-2-account-navigation.html +0 -1159
  364. package/work-orders/assets/THEME-1-baseline-reference-sheet.html +0 -1352
  365. package/work-orders/assets/UCM-CHAT-1-ai-chat.html +0 -447
  366. package/work-orders/assets/UCM-THEME-13-dark-prototype.html +0 -390
  367. package/work-orders/assets/UCM-THEME-17-type-scale.html +0 -391
@@ -1,75 +0,0 @@
1
- # UCM-CHAT-2 — Readable driver names in the chat model picker
2
-
3
- Prepared: 2026-10-15. Target repository: `ui-core-micha` (`main`). Correction to `UCM-CHAT-1`, found at acceptance.
4
-
5
- # A. Envelope — addressed to everyone
6
-
7
- ## Goal and expected outcome
8
-
9
- The model picker of the shared chat surface groups its entries by driver. In the UCM-CHAT-1 implementation, each group heading shows the raw driver id the catalogue returns (`claude_cli`, `anthropic_api`, `openai_api`). The prototype `work-orders/assets/UCM-CHAT-1-ai-chat.html` shows readable names instead.
10
-
11
- Expected outcome: the three drivers that `django-core-micha/DCM-CHAT-1` ships appear under readable, translated names, both in the picker and wherever else ui-core-micha shows a driver. An unknown driver id still appears as its raw id, so a driver added later (`django-core-micha/DCM-CHAT-2`) stays usable before it gets a name.
12
-
13
- ## Scope
14
-
15
- - A mapping from the three driver ids to translated names, registered in ui-core-micha's chat translations:
16
-
17
- | Driver id | en | de | fr | sw |
18
- |---|---|---|---|---|
19
- | `claude_cli` | Claude Code subscription | Claude Code (Abo) | Claude Code (abonnement) | Claude Code (usajili) |
20
- | `anthropic_api` | Anthropic API | Anthropic API | API Anthropic | API ya Anthropic |
21
- | `openai_api` | OpenAI API | OpenAI API | API OpenAI | API ya OpenAI |
22
-
23
- - The picker's group heading and the group's accessible name use the translated name.
24
- - Any other place in the chat surface that shows a driver uses the same name. One example is the model-change divider in the thread.
25
- - Unknown driver ids fall back to the raw id.
26
-
27
- ## Copy list (released with this Envelope)
28
-
29
- The twelve names in the table above, verbatim. No other new text.
30
-
31
- ## Non-goals
32
-
33
- - Any change to the catalogue contract or to django-core-micha. The names live in ui-core-micha.
34
- - Other picker behaviour, layout or styling.
35
- - The post-landing re-review of UCM-CHAT-1's last fix batch. That is UCM-CHAT-1's own follow-up.
36
-
37
- ## Tier
38
-
39
- Tier 3: a change inside shared-core. Small and copy-only in effect.
40
-
41
- ## Risks
42
-
43
- - **Id mismatch:** the ids must match exactly what DCM-CHAT-1 returns (`django_core_micha/assistant/catalogue.py`, `DRIVERS`). A mismatch silently falls back to raw ids. The existing picker test fixture uses `openai`, which is not a real driver id.
44
-
45
- ## Required tests to write
46
-
47
- - Picker: groups for `claude_cli`, `anthropic_api` and `openai_api` show their translated names as heading and accessible name. Fixtures use the real driver ids.
48
- - Unknown driver: an entry with an unknown driver id is grouped under its raw id.
49
- - Translations: the three new keys exist in all four languages.
50
-
51
- # B. Implementation map — addressed to the implementer
52
-
53
- ## Context package
54
-
55
- Tier 3 · tests: picker + translations (see Part A). Work from this package; do not explore broadly. Target working directory: `C:/Users/Micha Bigler/Documents/webapps/ui-core-micha` (never the workspace root).
56
-
57
- - `src/chat/ModelPicker.jsx` — `groupByDriver` groups `entries` by `entry.driver`; the group is rendered at about line 38 as `<Box key={driver} role="group" aria-label={driver}>` with `<Typography variant="overline">{driver}</Typography>`. Both the accessible name and the heading must show the translated name. `t` comes from `useTranslation()` already in the file.
58
- - `src/i18n/chatTranslations.ts` — one `chatTranslations` const, entries `'Chat.xxx': { de, en, fr, sw }`. Add exactly three keys, flat like the existing `Chat.effort.low`: `Chat.driver.claude_cli`, `Chat.driver.anthropic_api`, `Chat.driver.openai_api`, with the Envelope's twelve names verbatim (en/de/fr/sw columns). No other new text.
59
- - A small helper keeps the lookup in one place: export `driverName(t, id)` from `src/chat/ModelPicker.jsx` (or a new `src/chat/driverName.js` if cleaner) returning `t(`Chat.driver.${id}`, { defaultValue: id })`, so an unknown id falls back to the raw id with real i18next. Use it in the picker. The thread's model-change divider (`src/chat/ChatThread.jsx`, `selectionLine`) shows only model and effort, no driver; leave it unchanged. No other place in `src/chat/**` renders a driver id (verify with a search for `driver`).
60
- - Tests: `tests/chatPicker.test.jsx` mocks `react-i18next` with `t: (key) => key`; make the mock return `values.defaultValue` when the key starts with `Chat.driver.` and a `defaultValue` is given and the id is not one of the three known ids, and the key otherwise, so every other assertion keeps expecting keys. Update the fixture entries to the real ids `claude_cli`, `anthropic_api` (replace the fake `openai`), keep one extra fixture with an unknown id (for example `mystery_driver`). Assert: group role name and heading text for each known driver equal the translation KEY `Chat.driver.<id>` (the mocked t returns keys); the unknown id group is named by the raw id. Also assert with the REAL `chatTranslations` that the three keys exist with the Envelope's exact English names, and that each key is non-empty in de/en/fr/sw (add to `tests/chatTranslations.test.js`). `tests/chatWorkspace.test.jsx` uses `openai`/`claude_cli` ids in its catalogue fixture and finds the group by name `openai`: update that lookup to the new key-based name.
61
- - Do not edit: `package.json`, lockfile, CHANGELOG, README, `WORK_ORDERS.md`, anything outside `src/chat/**`, `src/i18n/chatTranslations.ts`, `tests/chat*.test.*`. No catalogue contract change.
62
- - Pitfall: the existing aggregate test `tests/i18nAggregate.test.js` iterates all bundle keys; every value needs all four locales as non-empty strings.
63
-
64
- ## Preamble
65
-
66
- > The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md` — the register row and the review verdicts are the orchestrator's alone.** **Your tools are for editing source and test files and for running the tests you wrote — nothing else.** Do NOT install dependencies, touch a lockfile, run a package manager, or tidy up stray files; if something in the repo state blocks you, stop and report it as `RESULT: BLOCKED <reason>` instead of fixing it. Do NOT `git add`/`commit`/`push` — leave every change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review). The orchestrator re-runs the authoritative set + does the independent review after you finish — those are the gate; your own run does not count as the gate.
67
- >
68
- > Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final `RESULT: DONE|BLOCKED <reason>`.
69
-
70
-
71
- # C. Orchestrator only — not addressed to the implementer
72
-
73
- > **If this WO was dispatched to you as an implementer: STOP here.**
74
-
75
- Gate #1 open until recorded in the register row. Publish as a patch release; cockpit/CP-CHAT-4 pins the release that contains it.
@@ -1,63 +0,0 @@
1
- # UCM-DEP-1 — All open Renovate updates in one change on main, one CI run
2
-
3
- Prepared: 2026-10-15. Target repository: `ui-core-micha` (`main`).
4
-
5
- # A. Envelope — addressed to everyone
6
-
7
- ## Goal and expected outcome
8
-
9
- ui-core-micha's eight open Renovate PRs land as one change on `main`, verified by one CI run. A release follows only if a runtime dependency changed; tooling-only updates need none.
10
-
11
- ## Tier
12
-
13
- Tier 3: dependency changes, majors included.
14
-
15
- ## Operator decisions this Envelope records (2026-10-15)
16
-
17
- 1. The bundle contains these open Renovate PRs' updates, in one change on `main`:
18
-
19
- | PR | Update |
20
- |---|---|
21
- | #17 | npm non-major |
22
- | #18 | github-actions |
23
- | #19 | actions/checkout v7 |
24
- | #20 | actions/setup-node v7 |
25
- | #21 | jsdom v30 (test) |
26
- | #22 | pnpm v12 |
27
- | #23 | typescript v7 |
28
- | #24 | vitest v5 (test) |
29
-
30
- 2. A major that needs more than small adaptations (configuration, a renamed import, a test helper) is taken out of the bundle, left as its PR, and reported with the reason. The bundle does not grow into a migration.
31
- 3. Verification is one CI run of the repository's own CI on the candidate (for an app: a `ci-test/<ID>` ref with the full job set). A red job is fixed within decision 2 and the run repeated; not more than that.
32
- 4. After the push Renovate closes the PRs whose update landed; a PR it rebases instead is an update that did not land and is reported.
33
-
34
- ## Scope
35
-
36
- 1. Dependency manifests and lockfiles, workflow `uses:` pins, image pins the updates touch.
37
- 2. The small adaptations decision 2 allows, with tests where behaviour is touched.
38
- 3. Each update's changelog read for breaking changes before it goes in; a breaking change the code meets is adapted (decision 2) or the update is taken out.
39
- 4. A release per the repository's own publish procedure only when the published package's runtime dependencies changed.
40
-
41
- ## Non-goals
42
-
43
- - No new features, no refactoring beyond decision 2.
44
- - No change to the Renovate configuration.
45
- - No pin bump in any consuming app.
46
-
47
- ## Risks
48
-
49
- - pnpm 12 and TypeScript 7 change the build toolchain; the published bundle must stay byte-compatible in its exports. The CI's build and the kit's own tests are the check.
50
-
51
- ## Required tests to write
52
-
53
- None beyond the adaptations of decision 2. The evidence is the CI run of decision 3.
54
-
55
- # B. Implementation map — addressed to the implementer
56
-
57
- *To be filled by the Orchestrator.*
58
-
59
- # C. Orchestrator only — not addressed to the implementer
60
-
61
- > **If this WO was dispatched to you as an implementer: STOP here.**
62
-
63
- Gate #1 open until recorded in the register row. Part of the PR close-out round of 2026-10-15; stagger the CI run with the other bundles of that round (one heavy run at a time on the shared runner). On 2026-10-15 the working tree carried another session's uncommitted changes to `package.json` and `pnpm-lock.yaml` (likely the dcm/ucm chat migration): the same files this bundle changes. Sequence with that session before starting; never fold its changes into this commit.
@@ -1,226 +0,0 @@
1
- # UCM-I18N-4 — Let a consumer choose informal German, and translate the hard-coded English in the auth and user screens
2
-
3
- # A. Envelope — authored by the Expertenchat
4
-
5
- ## Goal & expected outcome
6
-
7
- - Goal: an app that addresses its users with "du" gets "du" in every ucm screen, and no ucm screen
8
- shows hard-coded English in a German UI.
9
- - Expected outcome:
10
- - The kit's German strings exist in a formal ("Sie", today's default) and an informal ("du")
11
- variant; a consumer picks one when it registers the kit's strings (the single export from
12
- `I18N-1`). Apps that do nothing keep today's formal German.
13
- - `UserListComponent`, the invite panel (`UserInviteComponent`, `BulkInviteCsvTab`) and their
14
- messages use translation keys for every visible string, in all configured locales.
15
-
16
- ## Context — measured 2026-09-29 in jg-ferien's local browser test (ucm 3.5.0 installed there)
17
-
18
- - jg-ferien addresses its users with "du" throughout; ucm's auth screens use "Sie" — login, signup,
19
- reset request, invite and reset pages (`src/i18n/authTranslations.ts`), so the break runs through
20
- one flow (`/signup` "Sie", jg's `/signup/confirm` "du"), and one page mixes both (invite page
21
- heading "Sie", validation "du").
22
- - Hard-coded English in German UI: `UserListComponent.jsx` — "All Users", "Search",
23
- "Search users...", "Rows per page:", "Successful Login", "Are you sure you want to delete this
24
- user?"; invite panel — "Invite a new user", "Bulk Invite via CSV", "Upload a CSV file containing
25
- email addresses. Header "email" is supported.", "Upload CSV", "Send Invites", success "Invitation
26
- sent.".
27
- - **Operator decision 2026-09-29: generic fixes go to ucm, app-specific ones to the app.**
28
-
29
- ## Scope + non-goals
30
-
31
- - In scope: the variant mechanism at registration time; the informal German variant of the auth
32
- bundle; keys for the hard-coded strings above (de/en/fr at least, plus every locale the bundles
33
- already carry).
34
- - Explicit non-goals / do-not-touch:
35
- - Default behaviour for existing consumers stays formal German — no consumer changes wording
36
- without opting in.
37
- - Behavioural fixes of those screens are `UCM-AUTH-9`.
38
-
39
- ## Tier · gates
40
-
41
- - **Tier 3** — change inside shared-core, a new public option on the registration export.
42
- - Reviewer: `reviewer` (all lenses) · `ui_reviewer`.
43
- - **Done means released and jg-ferien's pin bumped with the option set** (separate jg step).
44
-
45
- ## Risks
46
-
47
- - A variant that only covers some keys silently falls back to "Sie" for the rest; a test must prove
48
- key parity between the two German variants.
49
- - Consumers that already override ucm keys locally must keep working (override order unchanged).
50
-
51
- ## Required tests to WRITE (you write them and run YOUR OWN new ones; the orchestrator's run is the gate)
52
-
53
- 1. Registering with the informal option yields "du" strings for the auth pages; without it, today's
54
- strings.
55
- 2. Key parity: formal and informal German cover the same key set.
56
- 3. `UserListComponent` and the invite panel render no hard-coded English (render in `de`, assert the
57
- listed strings are absent and translated keys present).
58
- 4. Four-locale shape test (`I18N-3`) still passes for the new keys.
59
-
60
- ---
61
-
62
- # B. Implementation map — filled by the Orchestrator — ADDRESSED TO THE IMPLEMENTER
63
-
64
- ## Context package — two independent parts
65
-
66
- ### 1. The variant mechanism + the informal auth bundle
67
-
68
- - **What "registers the kit's strings" means today, concretely** (so the mechanism plugs into the
69
- real thing, not a hypothetical): every consuming app's own `i18n/index.js` imports the named
70
- bundle exports (`authTranslations`, `messagingTranslations`, …) or the single aggregate
71
- `uiCoreTranslations` (`src/i18n/uiCoreTranslations.js`, built by `I18N-1`) and spreads them into
72
- its own i18next `resources` object — see `jg-ferien/frontend/i18n/index.js` for the exact pattern
73
- (not this repo; read it for reference only, do not edit it — jg's own pin-bump/adoption is a
74
- separate step, out of this WO). **No app currently imports `uiCoreTranslations` itself** (checked
75
- — only per-feature bundles are imported today), so changing how the aggregate is BUILT carries no
76
- live migration risk.
77
- - **Do not change `uiCoreTranslations`'s existing shape or behaviour** — `tests/i18nAggregate.test.js`
78
- (`I18N-1`/`I18N-3`) asserts it is byte-identical to the plain merge of the 7 per-feature bundles;
79
- breaking that assertion is not this WO's job. Add a NEW function alongside it instead:
80
- ```js
81
- // src/i18n/uiCoreTranslations.js — ADD this export, keep the existing `uiCoreTranslations` export unchanged
82
- export function createUiCoreTranslations({ germanVariant = 'formal' } = {}) {
83
- return Object.fromEntries(
84
- Object.entries(uiCoreTranslations).map(([key, value]) => {
85
- const { de_informal, ...rest } = value;
86
- if (germanVariant === 'informal' && de_informal) return [key, { ...rest, de: de_informal }];
87
- return [key, rest];
88
- }),
89
- );
90
- }
91
- ```
92
- This is "the single export a consumer picks a variant with" (the Envelope's phrase) — a future jg
93
- adoption step calls `createUiCoreTranslations({ germanVariant: 'informal' })` instead of spreading
94
- `uiCoreTranslations` directly; every OTHER existing consumer is completely unaffected (they don't
95
- call this function at all, and `uiCoreTranslations` itself is untouched) — this is what "no
96
- consumer changes wording without opting in" means mechanically.
97
- - **The informal German variant itself** — add a sibling `de_informal` field to the `de` value of
98
- every key in `src/i18n/authTranslations.ts` where the FORMAL wording actually depends on
99
- Sie/Ihr-form address. Do NOT add `de_informal` to a key whose German text has no such dependency
100
- (e.g. "E-Mail-Adresse", "Passwort", "QR-Token" read identically either way) — the function above
101
- already falls back to the formal `de` value when `de_informal` is absent, so omitting it there is
102
- correct, not incomplete.
103
- - Find every Sie-dependent key with a word-boundary scan of each entry's `de` value against
104
- `\bSie\b|\bIhr\b|\bIhre\b|\bIhrem\b|\bIhren\b|\bIhrer\b|\bIhres\b` (covers "Sie", "Ihr(e/em/en/er/es)"
105
- in all inflected forms) — this repo already has one page that MIXES both forms today
106
- (`Auth.MFA_RECOVERY_TITLE`'s description at `authTranslations.ts` uses "du" while
107
- `Auth.PAGE_INVITE_SUBTITLE` uses "Sie" — measured, not hypothetical), so a plain "does the file
108
- already use du sometimes" check is not sufficient; use the regex scan.
109
- - For each matched key, write a natural informal ("du"/"dein"/"dir"/imperative-du) rewording as
110
- `de_informal`, keeping the same meaning, placeholders (`{{email}}` etc. must appear identically),
111
- and punctuation style as the formal version. This is a real translation task — this is a
112
- shared-core kit that already ships a disclosed machine-translated Swahili bundle (`I18N-3`); do
113
- the same here: **disclose in your final `RESULT:` line that the informal wording was machine-
114
- translated by you (the implementing model), not reviewed by a fluent German speaker**, exactly
115
- as `I18N-3` did for Swahili. Do not silently imply human review.
116
- - **Test file:** extend `tests/i18nAggregate.test.js` (it already imports `uiCoreTranslations` and
117
- the per-bundle exports — read it first) or add a new `tests/i18nGermanVariant.test.js`, covering:
118
- 1. For a representative key (e.g. `Auth.PAGE_INVITE_SUBTITLE`),
119
- `createUiCoreTranslations({ germanVariant: 'informal' }).['Auth.PAGE_INVITE_SUBTITLE'].de`
120
- is the informal wording and does NOT match the Sie-form regex; the default call
121
- (`createUiCoreTranslations()`, no argument) returns the SAME `de` value as plain
122
- `uiCoreTranslations['Auth.PAGE_INVITE_SUBTITLE'].de` (today's formal string, unopted-in
123
- consumers see no change).
124
- 2. **The real parity guard the Risk note asks for:** scan `authTranslations` for every key whose
125
- `de` matches the Sie-form regex above, and assert EACH such key has a non-empty `de_informal`
126
- that does NOT itself match the Sie-form regex (proves it was actually rewritten, not copied).
127
- This is the test that would fail if a future key were added with formal wording only and
128
- forgotten — the actual failure mode the Envelope's Risk names, not a generic "same key set"
129
- check (which would be trivially true by construction here and prove nothing).
130
- 3. Four-locale shape test (`I18N-3`, `tests/i18nAggregate.test.js`'s existing
131
- `REQUIRED_LOCALES = ['de','en','fr','sw']` check) still passes — it iterates `uiCoreTranslations`
132
- itself, which is unchanged; run it to confirm, do not edit it.
133
- 4. Existing consumers unaffected: `uiCoreTranslations['Auth.PAGE_INVITE_SUBTITLE']` (the plain,
134
- unchanged export) still equals exactly what it did before this WO — read from
135
- `authTranslations.ts` directly, minus the new `de_informal` field which existing code never
136
- reads.
137
-
138
- ### 2. Hard-coded English in `UserListComponent`, `UserInviteComponent`, `BulkInviteCsvTab`
139
-
140
- - **Every string named in the Envelope's Context already uses `t(key, englishDefault)`** — the
141
- translation KEYS are already referenced in the JSX, they are simply missing from every bundle, so
142
- `t()` silently falls through to the English default regardless of locale. **In almost every case
143
- the fix is adding the bundle entry, not touching the component.** Add these keys to
144
- `src/i18n/authTranslations.ts` (all four locales it already carries: de/en/fr/sw — plain, correct
145
- translations, NOT the informal-German mechanism from part 1, this is unrelated hard-coded-string
146
- work):
147
- - From `src/components/UserListComponent.jsx` (verified against the file, line refs current):
148
- `UserList.DELETE_CONFIRM` (`:93`), `Common.OPERATION_FAILED` (`:278`), `UserList.NEW` (`:313`),
149
- `UserList.SUCCESSFUL_LOGIN` (`:331`), `UserList.ROLE` (`:349`), `Common.ACTIONS` (`:398`),
150
- `UserList.TITLE` (`:503`), `Common.SEARCH` (`:509`), `UserList.SEARCH_PLACEHOLDER` (`:510`),
151
- `UserList.NO_USERS` (`:560`). (`Common.YES`/`Common.NO`/`Common.DELETE`/`Auth.EMAIL_LABEL`/
152
- `Profile.NAME_LABEL` already exist — do not re-add them.)
153
- - **One genuine code change, not just a bundle entry:** the `<TablePagination>` at `:581` has no
154
- localisation props at all — MUI supplies its own English default "Rows per page:" directly, it
155
- is not reachable via `t()` today. Add `labelRowsPerPage={t('UserList.ROWS_PER_PAGE', 'Rows per
156
- page:')}` to that element, plus the new `UserList.ROWS_PER_PAGE` bundle entry.
157
- - From `src/components/UserInviteComponent.jsx`: `Auth.INVITE_SENT_SUCCESS` (`:29`, `:104` in
158
- `BulkInviteCsvTab.jsx` too — shared key), `Auth.INVITE_TITLE` (`:43`). (`Auth.EMAIL_LABEL`,
159
- `Auth.INVITE_BUTTON` already exist.)
160
- - From `src/components/BulkInviteCsvTab.jsx`: `Account.BULK_INVITE_NO_EMAILS` (`:82`),
161
- `Account.BULK_INVITE_PARSE_FAILED` (`:87`), `Account.BULK_INVITE_DONE` (`:117`, has `{{ok}}`/
162
- `{{total}}` interpolation — keep both placeholders in every locale), `Account.BULK_INVITE_TITLE`
163
- (`:129`), `Account.BULK_INVITE_HINT` (`:132-135`, multi-line `t()` call — easy to miss with a
164
- single-line grep, it IS in scope), `Account.BULK_INVITE_UPLOAD` (`:143`),
165
- `Account.BULK_INVITE_SEND` (`:147`), `Account.BULK_INVITE_COUNT` (`:150`, `{{count}}`),
166
- `Common.STATUS` (`:166`), `Common.DETAILS` (`:167`), `Account.BULK_INVITE_PROGRESS` (`:190`,
167
- `{{done}}`/`{{total}}`), `Account.BULK_INVITE_SUCCESS_COUNT` (`:192`, `{{count}}`).
168
- (`Auth.EMAIL_LABEL`, `Common.SUCCESS`, `Common.ERROR` already exist.)
169
- - **`UCM-AUTH-9` already landed** (earlier in this release's sequence) and touched this SAME
170
- file: it added `UserList.ROLE_UPDATE_SUCCESS` (already present, all four locales — do not
171
- re-add it) and, after its own review, reused the pre-existing `Auth.SELF_SIGNUP_DISABLED` key
172
- for the closed-signup message rather than adding a new `Auth.SIGNUP_CLOSED` key (that key does
173
- NOT exist — do not look for it or add it).
174
- - Test file: extend `tests/UserListComponent`/`UserInviteComponent`/`BulkInviteCsvTab` tests if they
175
- exist (grep `tests/`), or add focused new ones:
176
- 1. Render each of the three components with `i18n.language = 'de'` (or however this repo's test
177
- harness sets locale — check an existing test that asserts translated text, e.g.
178
- `tests/authTranslations.test.js`, for the pattern) and assert NONE of the literal English
179
- default strings listed above are present, and the translated (German) text IS present.
180
- 2. Four-locale shape test (`i18nAggregate.test.js`) still passes for every new key.
181
-
182
- ## Do-not-touch / invariants
183
-
184
- - Default behaviour for existing consumers stays formal German — `uiCoreTranslations` itself must
185
- not change; only the new `createUiCoreTranslations` function is variant-aware.
186
- - Behavioural fixes of the auth screens are `UCM-AUTH-9`'s scope, not this one — this WO only adds
187
- strings/keys and the variant mechanism, it does not change component logic (aside from the one
188
- named `labelRowsPerPage` prop addition, which is not a behaviour change).
189
- - No secrets, no dependency changes — everything here is data (translation bundles) plus one small
190
- pure function.
191
-
192
- ## Target repo working directory (absolute)
193
-
194
- `C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`)
195
-
196
- ## Preamble — a REQUIRED block IN this file, not something appended at invocation
197
-
198
- > The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there
199
- > is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the
200
- > app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
201
- > unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md` — the register
202
- > row and the review verdicts are the orchestrator's alone.** **Your tools are for editing source
203
- > and test files and for running the tests you wrote — nothing else.** Do NOT install dependencies,
204
- > touch a lockfile, run a package manager, or tidy up stray files; if something in the repo state
205
- > blocks you, stop and report it as `RESULT: BLOCKED <reason>` instead of fixing it. Do NOT
206
- > `git add`/`commit`/`push` — leave every
207
- > change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests
208
- > the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute
209
- > and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review).
210
- > The orchestrator re-runs the authoritative set + does the independent review after you finish —
211
- > those are the gate; your own run does not count as the gate.
212
- >
213
- > Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
214
- > `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
215
- > completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
216
- > `RESULT: DONE|BLOCKED <reason>`.
217
-
218
- ---
219
-
220
- # C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
221
-
222
- > **If you are the implementer reading this work order as your own specification: STOP at this line.
223
- > Everything below describes what the Orchestrator does AFTER you finish. You do none of it — no
224
- > reviewers, no verification run, no register edit, no commit.**
225
-
226
- *(to be filled by the Orchestrator: execution directive; `reviewer` (all lenses) + `ui_reviewer`; release; jg-ferien pin bump with the informal option; register rows here and in jg (`JG-UX-10`).)*
@@ -1,211 +0,0 @@
1
- # UCM-I18N-5 — User-list pagination range text is hard-coded English
2
-
3
- # A. Envelope — authored by the Expertenchat
4
-
5
- ## Goal & expected outcome
6
-
7
- - Goal: the user list's pagination reads in the user's language.
8
- - Expected outcome: `UserListComponent`'s `TablePagination` renders its "1–4 of 4" text through a
9
- translation key (de/en/fr and every locale the bundles carry), the way `labelRowsPerPage`
10
- already does.
11
-
12
- ## Context — measured 2026-10-01 in jg-ferien's local browser (ucm 3.7.0 installed there)
13
-
14
- - `/account?tab=users` in German: "Zeilen pro Seite: 25 ▾ · **1–4 of 4**". `UserListComponent.jsx`
15
- (~l.589-600) sets `labelRowsPerPage={t('UserList.ROWS_PER_PAGE', …)}` but no
16
- `labelDisplayedRows`, so MUI's English default renders. It is the only `TablePagination` in ucm.
17
- - Follows `UCM-I18N-4` (hard-coded English in the user list).
18
-
19
- ## Scope + non-goals
20
-
21
- - In scope: `labelDisplayedRows` via a key with count interpolation; tests; release.
22
- - Explicit non-goals / do-not-touch: no other change to the user list.
23
-
24
- ## Tier · gates
25
-
26
- - **Tier 3** — change inside shared-core (small).
27
- - Done means released AND jg-ferien's pin bumped.
28
-
29
- ## Risks
30
-
31
- - The "more than" form (`count === -1`) must have a wording too, or it renders "of -1".
32
-
33
- ## Required tests to WRITE (you write them and run YOUR OWN new ones; the orchestrator's run is the gate)
34
-
35
- 1. In `de`, the pagination shows the German range text; in `en` the English one.
36
- 2. Key-parity: every locale bundle has the new key.
37
-
38
- ---
39
-
40
- # B. Implementation map — filled by the Orchestrator — ADDRESSED TO THE IMPLEMENTER
41
-
42
- ## Context package
43
-
44
- ### The call site
45
-
46
- `src/components/UserListComponent.jsx:589-601`:
47
- ```jsx
48
- <TablePagination
49
- component="div"
50
- count={sortedUsers.length}
51
- page={page}
52
- onPageChange={(_, newPage) => setPage(newPage)}
53
- rowsPerPage={pageSize}
54
- onRowsPerPageChange={(event) => {
55
- setPageSize(Number(event.target.value));
56
- setPage(0);
57
- }}
58
- labelRowsPerPage={t('UserList.ROWS_PER_PAGE', 'Rows per page:')}
59
- rowsPerPageOptions={[10, 25, 50, 100]}
60
- />
61
- ```
62
- `t`/`i18n` come from `useTranslation()` (`react-i18next`), already in scope at l.53.
63
-
64
- ### MUI's `labelDisplayedRows` contract
65
-
66
- MUI's own default (`node_modules/@mui/material/TablePagination/TablePagination.js:119-124`,
67
- for reference only — do not import it):
68
- ```js
69
- function defaultLabelDisplayedRows({ from, to, count }) {
70
- return `${from}–${to} of ${count !== -1 ? count : `more than ${to}`}`;
71
- }
72
- ```
73
- The prop signature is `({ from, to, count, page }) => ReactNode`. `count` is `-1` when the total
74
- is unknown/unbounded — this component always passes a real `sortedUsers.length`, but the prop
75
- contract still has to handle `-1` defensively (the Risk note): MUI itself would call the function
76
- with `-1` only if `count={-1}` were passed, which this component doesn't do — handle it anyway
77
- since the function must satisfy the full contract, not just this component's current call site.
78
-
79
- ### The translation bundle has FOUR locales, not three
80
-
81
- `src/i18n/authTranslations.ts` (flat `export const authTranslations = { "Key.NAME": { de, fr, en,
82
- sw }, ... }`) carries `de`/`fr`/`en`/`sw` for every existing key, confirmed by grepping all locale
83
- codes in the file — **sw (Swahili) is real and already translated throughout, not a stub**. "every
84
- locale the bundles carry" in the Envelope means these four, not jg-ferien's usual three. Add the
85
- new key(s) in the same shape, next to `UserList.ROWS_PER_PAGE` (~l.2050-2055) for locality.
86
-
87
- Proposed keys (interpolated, i18next `{{var}}` syntax — do not reserialize the whole file through
88
- `JSON.parse`/`JSON.stringify`, this is a `.ts` module, not JSON; a plain text insert keeps every
89
- other entry byte-identical):
90
- ```ts
91
- "UserList.DISPLAYED_ROWS": {
92
- "de": "{{from}}–{{to}} von {{count}}",
93
- "fr": "{{from}}–{{to}} sur {{count}}",
94
- "en": "{{from}}–{{to}} of {{count}}",
95
- "sw": "{{from}}–{{to}} ya {{count}}"
96
- },
97
- "UserList.DISPLAYED_ROWS_MORE_THAN": {
98
- "de": "{{from}}–{{to}} von mehr als {{to}}",
99
- "fr": "{{from}}–{{to}} sur plus de {{to}}",
100
- "en": "{{from}}–{{to}} of more than {{to}}",
101
- "sw": "{{from}}–{{to}} ya zaidi ya {{to}}"
102
- }
103
- ```
104
- The `sw` wording reuses "ya" for "of"/possessive, already used this way elsewhere in the same file
105
- (e.g. l.57 `"ruhusa ya kutuma mialiko"`, l.114 `"barua pepe ya kuweka upya"`) and "zaidi ya" ("more
106
- than") as a plain compositional phrase — a reasonable best-effort construction, NOT a
107
- native-speaker-verified translation; say so plainly in your own report rather than presenting it as
108
- settled, same as you would for any other claim you can't independently verify.
109
-
110
- Call site becomes:
111
- ```jsx
112
- labelDisplayedRows={({ from, to, count }) =>
113
- count === -1
114
- ? t('UserList.DISPLAYED_ROWS_MORE_THAN', '{{from}}–{{to}} of more than {{to}}', { from, to })
115
- : t('UserList.DISPLAYED_ROWS', '{{from}}–{{to}} of {{count}}', { from, to, count })
116
- }
117
- ```
118
-
119
- ### Existing test harness to extend, not duplicate
120
-
121
- `tests/userScreenTranslations.test.jsx` already renders `UserListComponent` through a REAL
122
- `i18next` instance pinned to German (`withGermanI18n`, ~l.22-30, built from
123
- `authTranslations.*.de`) and asserts rendered German strings plus `expectNoEnglishDefaults()`
124
- (~l.34-39, checks `document.body.textContent` against an `ENGLISH_DEFAULTS` list, ~l.33-46). The
125
- test `'renders UserListComponent in German, including pagination and action feedback'` (~l.97-125)
126
- already fetches exactly 1 user, so the pagination currently renders English "1–1 of 1" — add that
127
- literal string (or your chosen German text) to the existing `for (const german of [...])` loop
128
- (~l.115) to assert the real rendered pagination text, and add the English range phrasing (e.g.
129
- `'of 1'` or similar, whatever actually changes) to `ENGLISH_DEFAULTS` so `expectNoEnglishDefaults()`
130
- (already called at line 124) starts actually catching a regression here — today it does NOT, since
131
- no "of N" string is in that list, which is why this bug shipped unnoticed.
132
-
133
- Required test 1 (German vs English) is naturally satisfied by extending this file: German via the
134
- existing `withGermanI18n` harness, English via a parallel small i18next instance (or reuse the
135
- `en` resources the same way `germanResources` is built from `.de`) rendering the same component and
136
- asserting the English range text.
137
-
138
- Required test 2 (key-parity across all four locales) — check whether a generic "every key has
139
- every locale" structural test already exists in this repo (grep `authTranslations` test files for
140
- something like `Object.values(...).every(...)` or a locale-set check) before writing a new one;
141
- extend it if so, add a small standalone one for just these two new keys if not.
142
-
143
- ## Target repo working directory (absolute)
144
-
145
- `C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`)
146
-
147
- ## Preamble — a REQUIRED block IN this file, not something appended at invocation
148
-
149
- > The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there
150
- > is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the
151
- > app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
152
- > unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md` — the register
153
- > row and the review verdicts are the orchestrator's alone.** **Your tools are for editing source
154
- > and test files and for running the tests you wrote — nothing else.** Do NOT install dependencies,
155
- > touch a lockfile, run a package manager, or tidy up stray files; if something in the repo state
156
- > blocks you, stop and report it as `RESULT: BLOCKED <reason>` instead of fixing it. Do NOT
157
- > `git add`/`commit`/`push` — leave every
158
- > change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests
159
- > the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute
160
- > and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review).
161
- > The orchestrator re-runs the authoritative set + does the independent review after you finish —
162
- > those are the gate; your own run does not count as the gate.
163
- >
164
- > Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
165
- > `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
166
- > completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
167
- > `RESULT: DONE|BLOCKED <reason>`.
168
-
169
- ---
170
-
171
- # C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
172
-
173
- > **If you are the implementer reading this work order as your own specification: STOP at this line.
174
- > Everything below describes what the Orchestrator does AFTER you finish. You do none of it — no
175
- > reviewers, no verification run, no register edit, no commit.**
176
-
177
- **Execution directive:** dispatch via `codex exec --skip-git-repo-check
178
- --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-luna - < work-orders/UCM-I18N-5.md` (today,
179
- 2026-10-02, already recorded `available` in `webapps/.claude/codex-status.md`), cwd =
180
- `C:\Users\biglmi\Documents\webapps\ui-core-micha`. Monitor for `RESULT: DONE|BLOCKED`.
181
-
182
- **Review routing:** Tier 3 (shared-core) — full `reviewer` lens set (`envelope`, `regression`,
183
- `duplication`, `tests`, codex/gpt-5.6-luna, one concurrent batch, diff inline) PLUS `ui_reviewer`
184
- (frontend-adjacent: a rendered component's i18n text). `duplication` should specifically check
185
- whether any OTHER app already patched around this same MUI default locally (a local workaround that
186
- this shared-core fix should make redundant, worth naming even if out of this WO's scope to remove).
187
-
188
- **Tests:** the Orchestrator re-runs `tests/userScreenTranslations.test.jsx` (and any new/renamed
189
- key-parity test file) as the gate — not ucm's full suite (Tier 3 but a small, local-only change;
190
- no cross-app ripple to justify a full run per `AGENTS.md` → Test scope).
191
-
192
- **Release:** patch bump (3.11.0 → 3.11.1) — this extends `UCM-I18N-4`'s existing i18n-gap category
193
- in the same component, not a new capability area, per the project convention (version bump reflects
194
- scope, not mere newness). Update `package.json` + `CHANGELOG.md`, then the repo's normal publish
195
- path (check `.github/workflows/` or `package.json` scripts for how a previous release like
196
- `UCM-THEME-14`/3.11.0 or `UCM-AUTH-11`/3.9.1 actually published, don't assume `npm publish` by
197
- hand — follow the established mechanism).
198
-
199
- **jg-ferien pin bump:** after the release is live, bump `ui-core-micha`'s pin in
200
- `jg-ferien/frontend/package.json`, install, run jg-ferien's own affected tests (anything touching
201
- `UserListComponent` consumption, if jg-ferien renders it at all — check first; if jg-ferien doesn't
202
- use `UserListComponent`, the pin bump itself plus jg-ferien's existing suite staying green is the
203
- evidence), commit + push to jg-ferien's `develop`.
204
-
205
- **Register:** `done` only once BOTH halves land — the release AND the jg-ferien pin bump (the WO's
206
- own Tier line: "Done means released AND jg-ferien's pin bumped"). Row here (ui-core-micha's
207
- `WORK_ORDERS.md`) AND a row in jg-ferien's own `WORK_ORDERS.md` noting the pin bump, per the
208
- Envelope's own closing instruction.
209
-
210
- **Commit:** ui-core-micha lands on `main` (no `develop` branch here, confirmed in `AGENTS.md`'s
211
- branch table). jg-ferien's pin bump lands on `develop` as usual.