@micha.bigler/ui-core-micha 3.14.4 → 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 (341) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +7 -0
  3. package/dist/chat/kitSxRegistry.js +9 -0
  4. package/dist/components/charts/kitSxRegistry.js +6 -0
  5. package/dist/entries/charts.js +6 -0
  6. package/dist/entries/chat.js +8 -0
  7. package/dist/entries/markdown.js +1 -0
  8. package/dist/index.js +0 -14
  9. package/dist/pages/AccountPage.js +1 -2
  10. package/dist/pages/LoginPage.js +1 -2
  11. package/dist/pages/PasswordChangePage.js +1 -2
  12. package/dist/pages/PasswordInvitePage.js +1 -2
  13. package/dist/pages/PasswordResetRequestPage.js +1 -2
  14. package/dist/pages/SignUpPage.js +1 -2
  15. package/dist/pages/SignupConfirmPage.js +1 -2
  16. package/dist/theme/kitSxEntry.js +11 -0
  17. package/dist/theme/kitSxRegistry.js +2 -15
  18. package/package.json +32 -7
  19. package/.github/workflows/ci.yml +0 -35
  20. package/.github/workflows/publish.yml +0 -126
  21. package/DESIGN.md +0 -60
  22. package/WORK_ORDERS.md +0 -150
  23. package/dev/entries.jsx +0 -721
  24. package/dev/fixtures.js +0 -26
  25. package/dev/main.jsx +0 -75
  26. package/dev/mockTransport.jsx +0 -128
  27. package/docs/CHART-LAYOUT.md +0 -157
  28. package/docs/DARK-TOKENS.md +0 -140
  29. package/docs/TYPE-SCALE.md +0 -111
  30. package/docs/messaging-deviations.md +0 -118
  31. package/index.html +0 -12
  32. package/renovate.json +0 -10
  33. package/scripts/chart-api-census.mjs +0 -415
  34. package/src/auth/AuthContext.jsx +0 -158
  35. package/src/auth/ReauthModal.jsx +0 -82
  36. package/src/auth/UserMenu.jsx +0 -121
  37. package/src/auth/apiClient.jsx +0 -232
  38. package/src/auth/authApi.jsx +0 -539
  39. package/src/auth/authConfig.jsx +0 -34
  40. package/src/auth/reauth.js +0 -47
  41. package/src/chat/ChatComposer.jsx +0 -36
  42. package/src/chat/ChatList.jsx +0 -87
  43. package/src/chat/ChatThread.jsx +0 -128
  44. package/src/chat/ChatWorkspace.jsx +0 -244
  45. package/src/chat/MarkdownReply.jsx +0 -22
  46. package/src/chat/ModelPicker.jsx +0 -85
  47. package/src/chat/api.js +0 -18
  48. package/src/chat/useChatSocket.js +0 -32
  49. package/src/chat/wire.js +0 -7
  50. package/src/components/AccessCodeManager.jsx +0 -288
  51. package/src/components/AccessCodeSingleUseToggle.jsx +0 -92
  52. package/src/components/AllowedEmailDomainsManager.jsx +0 -92
  53. package/src/components/AuthFactorRequirementCard.jsx +0 -95
  54. package/src/components/BulkInviteCsvTab.jsx +0 -198
  55. package/src/components/EmptyState.jsx +0 -38
  56. package/src/components/LoginForm.jsx +0 -159
  57. package/src/components/MFAComponent.jsx +0 -350
  58. package/src/components/MfaLoginComponent.jsx +0 -252
  59. package/src/components/MobileBottomNav.jsx +0 -82
  60. package/src/components/PasskeysComponent.jsx +0 -252
  61. package/src/components/PasswordChangeForm.jsx +0 -87
  62. package/src/components/PasswordResetRequestForm.jsx +0 -43
  63. package/src/components/PasswordSetForm.jsx +0 -97
  64. package/src/components/ProfileComponent.jsx +0 -348
  65. package/src/components/QrSignupManager.jsx +0 -404
  66. package/src/components/QrSignupValidityManager.jsx +0 -106
  67. package/src/components/RegistrationMethodsManager.jsx +0 -150
  68. package/src/components/SecurityComponent.jsx +0 -141
  69. package/src/components/SocialLoginButtons.jsx +0 -83
  70. package/src/components/SoftChip.jsx +0 -93
  71. package/src/components/StatTile.jsx +0 -39
  72. package/src/components/SupportRecoveryRequestsTab.jsx +0 -482
  73. package/src/components/TurnstileWidget.jsx +0 -99
  74. package/src/components/UserInviteComponent.jsx +0 -76
  75. package/src/components/UserListComponent.jsx +0 -618
  76. package/src/components/charts/BarChart.jsx +0 -102
  77. package/src/components/charts/ChartFrame.jsx +0 -214
  78. package/src/components/charts/LineChart.jsx +0 -126
  79. package/src/components/charts/ScatterChart.jsx +0 -299
  80. package/src/components/charts/TimeSeriesChart.jsx +0 -300
  81. package/src/components/charts/chartDefaults.js +0 -644
  82. package/src/components/charts/chartLabels.js +0 -36
  83. package/src/components/charts/exportChart.js +0 -258
  84. package/src/components/charts/formatters.js +0 -39
  85. package/src/components/charts/palette.js +0 -33
  86. package/src/components/charts/yearTickInterval.js +0 -7
  87. package/src/i18n/authTranslations.ts +0 -2651
  88. package/src/i18n/chartsTranslations.ts +0 -91
  89. package/src/i18n/chatTranslations.ts +0 -55
  90. package/src/i18n/messagingTranslations.ts +0 -120
  91. package/src/i18n/notificationsTranslations.ts +0 -32
  92. package/src/i18n/onboardingTranslations.ts +0 -29
  93. package/src/i18n/sectionNavTranslations.ts +0 -20
  94. package/src/i18n/uiCoreTranslations.js +0 -29
  95. package/src/i18n/userMenuTranslations.ts +0 -5
  96. package/src/index.js +0 -158
  97. package/src/layout/PageLayout.jsx +0 -36
  98. package/src/layout/SectionNav.jsx +0 -320
  99. package/src/messaging/AttachmentList.jsx +0 -145
  100. package/src/messaging/Composer.jsx +0 -197
  101. package/src/messaging/ConversationLaunchers.jsx +0 -51
  102. package/src/messaging/ConversationList.jsx +0 -109
  103. package/src/messaging/DirectMessageLauncher.jsx +0 -112
  104. package/src/messaging/MessageBubble.jsx +0 -183
  105. package/src/messaging/MessagingProvider.jsx +0 -0
  106. package/src/messaging/MessagingScopeConfig.jsx +0 -24
  107. package/src/messaging/PollCard.jsx +0 -163
  108. package/src/messaging/ReactionBar.jsx +0 -43
  109. package/src/messaging/ReadTicks.jsx +0 -82
  110. package/src/messaging/Thread.jsx +0 -195
  111. package/src/messaging/api.js +0 -48
  112. package/src/messaging/composerImageCompression.js +0 -35
  113. package/src/messaging/linkifyText.jsx +0 -37
  114. package/src/notifications/NotificationBell.jsx +0 -84
  115. package/src/notifications/NotificationSettings.jsx +0 -330
  116. package/src/notifications/NotificationsProvider.jsx +0 -224
  117. package/src/notifications/PopupSurface.jsx +0 -105
  118. package/src/notifications/api.js +0 -55
  119. package/src/notifications/feedApi.js +0 -18
  120. package/src/notifications/realtime.jsx +0 -138
  121. package/src/notifications/serviceWorker/sw.js +0 -50
  122. package/src/onboarding/OnboardingProvider.jsx +0 -326
  123. package/src/onboarding/OnboardingWizard.jsx +0 -61
  124. package/src/onboarding/WizardDialogShell.jsx +0 -51
  125. package/src/onboarding/api.js +0 -13
  126. package/src/onboarding/stepSelection.js +0 -16
  127. package/src/onboarding/steps/BrowserPushStep.jsx +0 -121
  128. package/src/onboarding/steps/CompleteNameStep.jsx +0 -46
  129. package/src/onboarding/steps/CookieConsentStep.jsx +0 -133
  130. package/src/onboarding/steps/PwaInstallStep.jsx +0 -47
  131. package/src/pages/AccountPage.jsx +0 -394
  132. package/src/pages/LoginPage.jsx +0 -343
  133. package/src/pages/PasswordChangePage.jsx +0 -62
  134. package/src/pages/PasswordInvitePage.jsx +0 -177
  135. package/src/pages/PasswordResetRequestPage.jsx +0 -68
  136. package/src/pages/SignUpPage.jsx +0 -268
  137. package/src/pages/SignupConfirmPage.jsx +0 -155
  138. package/src/testing/checkKitIntegration.js +0 -233
  139. package/src/theme/createAppTheme.js +0 -423
  140. package/src/theme/fonts.js +0 -3
  141. package/src/theme/index.js +0 -21
  142. package/src/theme/kitSxRegistry.js +0 -285
  143. package/src/theme/themeCompleteness.js +0 -1045
  144. package/src/theme/tokens.js +0 -478
  145. package/src/utils/auth-errors.js +0 -76
  146. package/src/utils/authService.js +0 -223
  147. package/src/utils/resolveErrorText.js +0 -28
  148. package/src/utils/webauthn.js +0 -51
  149. package/tests/AccountPage.profileStatements.test.jsx +0 -162
  150. package/tests/AccountPage.test.jsx +0 -200
  151. package/tests/AuthContext.test.jsx +0 -129
  152. package/tests/BarChart.test.jsx +0 -112
  153. package/tests/BrowserPushStep.test.jsx +0 -110
  154. package/tests/ChartFrame.test.jsx +0 -336
  155. package/tests/ConversationList.test.jsx +0 -144
  156. package/tests/CookieConsentStep.test.jsx +0 -69
  157. package/tests/EmptyState.test.jsx +0 -62
  158. package/tests/LineChart.test.jsx +0 -80
  159. package/tests/MessagingProvider.test.jsx +0 -50
  160. package/tests/MobileBottomNav.test.jsx +0 -319
  161. package/tests/NotificationBell.test.jsx +0 -60
  162. package/tests/NotificationSettings.test.jsx +0 -276
  163. package/tests/NotificationsProvider.test.jsx +0 -240
  164. package/tests/OnboardingProvider.test.jsx +0 -294
  165. package/tests/OnboardingWizard.test.jsx +0 -143
  166. package/tests/PasswordChangeForm.test.jsx +0 -70
  167. package/tests/PasswordInvitePage.test.jsx +0 -142
  168. package/tests/PasswordSetForm.test.jsx +0 -70
  169. package/tests/PopupSurface.test.jsx +0 -142
  170. package/tests/ProfileComponent.refresh.test.jsx +0 -194
  171. package/tests/QrSignupManager.registrationContext.test.jsx +0 -106
  172. package/tests/QrSignupManagerInfoBox.test.jsx +0 -49
  173. package/tests/ScatterChart.test.jsx +0 -270
  174. package/tests/SectionNav.test.jsx +0 -363
  175. package/tests/SignUpPage.test.jsx +0 -208
  176. package/tests/SoftChip.test.jsx +0 -105
  177. package/tests/StatTile.test.jsx +0 -57
  178. package/tests/Thread.test.jsx +0 -151
  179. package/tests/TimeSeriesChart.test.jsx +0 -367
  180. package/tests/UserListComponent.test.jsx +0 -192
  181. package/tests/UserMenu.test.jsx +0 -171
  182. package/tests/apiClientLanguage.test.js +0 -33
  183. package/tests/apiClientPublicPaths.test.js +0 -178
  184. package/tests/authApiLogin.test.js +0 -42
  185. package/tests/authApiRegistration.test.js +0 -31
  186. package/tests/authErrorCodeRendering.test.jsx +0 -77
  187. package/tests/authErrors.test.js +0 -74
  188. package/tests/authTranslations.test.js +0 -74
  189. package/tests/chart-api-census.test.js +0 -366
  190. package/tests/chartAxisTickBand.test.jsx +0 -95
  191. package/tests/chartDefaults.test.js +0 -902
  192. package/tests/chartLabels.test.js +0 -50
  193. package/tests/chartsPalette.test.js +0 -99
  194. package/tests/chatApi.test.js +0 -48
  195. package/tests/chatDriverNames.test.jsx +0 -71
  196. package/tests/chatExports.test.js +0 -3
  197. package/tests/chatList.test.jsx +0 -84
  198. package/tests/chatPicker.test.jsx +0 -82
  199. package/tests/chatSocket.test.jsx +0 -26
  200. package/tests/chatThread.test.jsx +0 -116
  201. package/tests/chatTranslations.test.js +0 -47
  202. package/tests/chatWorkspace.test.jsx +0 -234
  203. package/tests/checkKitIntegration.test.jsx +0 -219
  204. package/tests/createAppTheme.test.js +0 -132
  205. package/tests/createAppThemeDark.test.js +0 -127
  206. package/tests/createAppThemeLightGuard.test.js +0 -40
  207. package/tests/createAppThemePageContrast.test.js +0 -108
  208. package/tests/createAppThemeTypography.test.js +0 -53
  209. package/tests/errorCallSiteGuard.test.js +0 -32
  210. package/tests/exportChart.test.js +0 -313
  211. package/tests/feedApi.test.js +0 -46
  212. package/tests/fixtures/light-theme-baseline.json +0 -2234
  213. package/tests/i18nAggregate.test.js +0 -120
  214. package/tests/i18nGermanVariant.test.js +0 -65
  215. package/tests/loginPageErrorResolution.test.jsx +0 -102
  216. package/tests/messagingApi.test.js +0 -32
  217. package/tests/messagingChunk6.test.jsx +0 -116
  218. package/tests/messagingCompactBubble.test.jsx +0 -64
  219. package/tests/messagingComposer.test.jsx +0 -136
  220. package/tests/messagingComposerChunk5.test.jsx +0 -113
  221. package/tests/messagingContractConformance.test.js +0 -69
  222. package/tests/messagingDirectMessageLauncher.test.jsx +0 -151
  223. package/tests/messagingExports.test.js +0 -21
  224. package/tests/messagingInteractions.test.jsx +0 -136
  225. package/tests/messagingLastMessagePreview.test.jsx +0 -93
  226. package/tests/messagingLinkify.test.jsx +0 -51
  227. package/tests/messagingMessageActions.test.jsx +0 -163
  228. package/tests/messagingMsg6.test.jsx +0 -105
  229. package/tests/messagingMsg6f.test.jsx +0 -155
  230. package/tests/messagingMsg6g.test.jsx +0 -166
  231. package/tests/messagingMsg6h.test.jsx +0 -136
  232. package/tests/messagingMsg6i.test.jsx +0 -129
  233. package/tests/messagingPollRendering.test.jsx +0 -142
  234. package/tests/messagingReactionMerge.test.jsx +0 -77
  235. package/tests/messagingReadTicksTooltip.test.jsx +0 -36
  236. package/tests/messagingThreadReceipts.test.jsx +0 -178
  237. package/tests/messagingThreadingQuoting.test.jsx +0 -87
  238. package/tests/messagingUnreadLifecycle.test.jsx +0 -78
  239. package/tests/notificationsApi.test.js +0 -41
  240. package/tests/notificationsExports.test.js +0 -34
  241. package/tests/onboardingDescriptors.test.js +0 -132
  242. package/tests/packageTreeShaking.test.js +0 -126
  243. package/tests/realtime.test.jsx +0 -219
  244. package/tests/resolveErrorText.test.js +0 -72
  245. package/tests/stepSelection.test.js +0 -53
  246. package/tests/themeCompleteness.test.js +0 -626
  247. package/tests/timeSeriesLegend.test.js +0 -99
  248. package/tests/userScreenTranslations.test.jsx +0 -218
  249. package/tsconfig.build.json +0 -18
  250. package/vite.config.mjs +0 -6
  251. package/work-orders/AUTH-1.md +0 -74
  252. package/work-orders/AUTH-2.md +0 -74
  253. package/work-orders/AUTH-4.md +0 -183
  254. package/work-orders/AUTH-5.md +0 -154
  255. package/work-orders/AUTH-7.md +0 -181
  256. package/work-orders/AUTH-8.md +0 -184
  257. package/work-orders/CHART-1.md +0 -285
  258. package/work-orders/CHART-2.md +0 -222
  259. package/work-orders/CHART-3.md +0 -163
  260. package/work-orders/CHART-4.md +0 -203
  261. package/work-orders/CHART-5.md +0 -226
  262. package/work-orders/CHART-6.md +0 -428
  263. package/work-orders/CHART-7.md +0 -175
  264. package/work-orders/DX-1.md +0 -169
  265. package/work-orders/DX-2.md +0 -188
  266. package/work-orders/DX-3.md +0 -195
  267. package/work-orders/I18N-1.md +0 -254
  268. package/work-orders/I18N-3.md +0 -207
  269. package/work-orders/MSG-3.md +0 -375
  270. package/work-orders/MSG-3b.md +0 -1002
  271. package/work-orders/MSG-3c.md +0 -378
  272. package/work-orders/MSG-3d.md +0 -268
  273. package/work-orders/MSG-3e.md +0 -164
  274. package/work-orders/MSG-3f.md +0 -391
  275. package/work-orders/MSG-6e.md +0 -308
  276. package/work-orders/MSG-6f.md +0 -214
  277. package/work-orders/MSG-6g.md +0 -244
  278. package/work-orders/MSG-6h.md +0 -238
  279. package/work-orders/MSG-6i.md +0 -271
  280. package/work-orders/MSG-6j.md +0 -117
  281. package/work-orders/NOTIF-12.md +0 -214
  282. package/work-orders/NOTIF-13.md +0 -142
  283. package/work-orders/NOTIF-14.md +0 -151
  284. package/work-orders/PRIM-1.md +0 -177
  285. package/work-orders/SHELL-1.md +0 -255
  286. package/work-orders/SHELL-2.md +0 -197
  287. package/work-orders/SHELL-3.md +0 -359
  288. package/work-orders/SHELL-4.md +0 -351
  289. package/work-orders/SHELL-5.md +0 -345
  290. package/work-orders/SHELL-6.md +0 -210
  291. package/work-orders/THEME-1.md +0 -587
  292. package/work-orders/THEME-10.md +0 -303
  293. package/work-orders/THEME-11.md +0 -208
  294. package/work-orders/THEME-2.md +0 -339
  295. package/work-orders/THEME-3.md +0 -210
  296. package/work-orders/THEME-4.md +0 -271
  297. package/work-orders/THEME-5.md +0 -341
  298. package/work-orders/THEME-6.md +0 -247
  299. package/work-orders/THEME-7.md +0 -82
  300. package/work-orders/THEME-8.md +0 -211
  301. package/work-orders/THEME-9.md +0 -194
  302. package/work-orders/UCM-AUTH-10.md +0 -490
  303. package/work-orders/UCM-AUTH-11.md +0 -185
  304. package/work-orders/UCM-AUTH-12.md +0 -98
  305. package/work-orders/UCM-AUTH-13.md +0 -47
  306. package/work-orders/UCM-AUTH-9.md +0 -207
  307. package/work-orders/UCM-CHART-10.md +0 -150
  308. package/work-orders/UCM-CHART-11.md +0 -132
  309. package/work-orders/UCM-CHART-12.md +0 -348
  310. package/work-orders/UCM-CHART-13.md +0 -122
  311. package/work-orders/UCM-CHART-14.md +0 -198
  312. package/work-orders/UCM-CHART-15.md +0 -187
  313. package/work-orders/UCM-CHART-16.md +0 -169
  314. package/work-orders/UCM-CHART-17.md +0 -195
  315. package/work-orders/UCM-CHART-18.md +0 -200
  316. package/work-orders/UCM-CHART-8.md +0 -147
  317. package/work-orders/UCM-CHART-9.md +0 -265
  318. package/work-orders/UCM-CHAT-1.md +0 -190
  319. package/work-orders/UCM-CHAT-2.md +0 -75
  320. package/work-orders/UCM-CI-1.md +0 -65
  321. package/work-orders/UCM-DEP-1.md +0 -63
  322. package/work-orders/UCM-I18N-4.md +0 -226
  323. package/work-orders/UCM-I18N-5.md +0 -211
  324. package/work-orders/UCM-MSG-20.md +0 -192
  325. package/work-orders/UCM-PRIM-2.md +0 -114
  326. package/work-orders/UCM-SHELL-7.md +0 -134
  327. package/work-orders/UCM-SHELL-8.md +0 -125
  328. package/work-orders/UCM-TEST-1.md +0 -304
  329. package/work-orders/UCM-THEME-13.md +0 -69
  330. package/work-orders/UCM-THEME-14.md +0 -312
  331. package/work-orders/UCM-THEME-15.md +0 -356
  332. package/work-orders/UCM-THEME-16.md +0 -80
  333. package/work-orders/UCM-THEME-17.md +0 -111
  334. package/work-orders/UCM-THEME-18.md +0 -184
  335. package/work-orders/assets/AUTH-4-user-list-card.html +0 -407
  336. package/work-orders/assets/PRIM-1-dashboard-primitives.html +0 -624
  337. package/work-orders/assets/SHELL-2-account-navigation.html +0 -1159
  338. package/work-orders/assets/THEME-1-baseline-reference-sheet.html +0 -1352
  339. package/work-orders/assets/UCM-CHAT-1-ai-chat.html +0 -447
  340. package/work-orders/assets/UCM-THEME-13-dark-prototype.html +0 -390
  341. package/work-orders/assets/UCM-THEME-17-type-scale.html +0 -391
@@ -1,339 +0,0 @@
1
- # THEME-2 — Two defects from the THEME-1/CHART-6 landings: `warning.main` contrast, and `grid` replacing instead of merging
2
-
3
- **Target repo:** `ui-core-micha` (branch `main` — this repo has no `develop`)
4
- **Tier:** 2 (shared core — `ui-core-micha` is named in AGENTS.md's Tier-2 forcing list)
5
- **Review:** independent `reviewer` **and** `ui_reviewer` — spawned concurrently, both mandatory before commit
6
- **Version target:** `2.31.1` (patch — one palette value corrected, one merge bug fixed, one assertion rule added; no API change)
7
- **Decision record:** `webapp-management/DESIGN_SYSTEM_PROGRAM.md` → "Open follow-ups from the two landings"
8
-
9
- Short-form WO: both defects are fully diagnosed and measured. There is no design question in either.
10
-
11
- ---
12
-
13
- ## A. Envelope
14
-
15
- ### Goal
16
-
17
- Fix the two defects found after `THEME-1` (`96992cf`) and `CHART-6` (`6dedc62`) landed, and in each
18
- case close the **mechanism** rather than only the instance — both are the same failure class as
19
- something already fixed, which is why they recurred.
20
-
21
- ### Defect 1 — `warning.main` fails AA as a foreground
22
-
23
- THEME-1's R1 fix gave every status channel an explicit `main`/`light`/`dark`/`contrastText` (correct
24
- — MUI was otherwise filling its stock hues for `color="success"` and friends). It put the **fill**
25
- tone in `main`. Measured against `#FFFFFF`:
26
-
27
- | Channel | `main` | as foreground | |
28
- |---|---|---|---|
29
- | success | `#1B8038` | 5.010 | passes |
30
- | error | `#BF3227` | 5.674 | passes |
31
- | **warning** | `#C08A2C` | **3.038** | **fails AA (4.5)** |
32
-
33
- `main`/`contrastText` pairs are all fine (warning 5.078 with dark ink). The failure is only when
34
- `main` is used as a **foreground on a light surface** — `<Typography color="warning.main">`,
35
- `color="warning"` on an icon, and an outlined warning chip, whose border and label both come from
36
- `main`.
37
-
38
- **Why warning specifically, and why this is not carelessness:** green and red can serve both roles
39
- with one value. Amber cannot. A legible amber **fill** needs dark text on it and must therefore stay
40
- light; a legible amber **text** must be dark. The two requirements pull in opposite directions.
41
- Warning is the one channel where "one hex for both roles" is impossible in principle — so the
42
- pattern that works for success and error had to break here.
43
-
44
- **Fix:** `warning.main` = `#976100` (the text tone already in the same token block, 5.216 on white),
45
- `contrastText` = `#FFFFFF`. The light amber stays available as `warning.fill` for deliberate fill
46
- use, unchanged.
47
-
48
- **Accepted visual consequence, stated so nobody treats it as a regression:** a filled
49
- `color="warning"` Button/Chip becomes a darker brown with white text instead of a lighter amber with
50
- dark text. That is the price of one token serving MUI's `main` contract, and it is the operator's
51
- call already recorded in the programme doc.
52
-
53
- **Close the mechanism, not just the value:** add an assertion rule that checks **every** status
54
- channel's `main` against `#FFFFFF` and `background.default` at 4.5:1. Without it the next channel
55
- added repeats this exactly — the existing contrast checks were designed before R1 introduced `main`,
56
- which is why they did not catch it.
57
-
58
- ### Defect 2 — `grid` is replaced, not merged
59
-
60
- `LineChart` and `BarChart` declare `grid = { horizontal: true }` as a plain default parameter and
61
- pass it straight through. A caller writing `grid={{ vertical: true }}` — intending to *add* vertical
62
- lines — silently loses the horizontal ones.
63
-
64
- This is the same class as the `scaleType` bug the rendered gate caught during CHART-6: **a partial
65
- caller object erases a default.** `xAxis`, `yAxis`, `margin` and `slotProps` all go through merge
66
- helpers; `grid` alone does not.
67
-
68
- **Fix:** merge `grid` with the default the way the sibling props already do, so a caller adds to it
69
- rather than replacing it.
70
-
71
- **Close the mechanism:** audit the remaining object-valued props the wrappers default or forward
72
- (`slots`, `tickLabelStyle` and anything CHART-6 introduced) for the same replace-instead-of-merge
73
- shape, and state the result — either "all others already merge" or a named list. **Audit and report;
74
- do not refactor beyond `grid`** unless the audit finds another live instance, in which case fix that
75
- too and say so.
76
-
77
- ### Non-goals / do not touch
78
-
79
- - The other status channels' `main` values — success and error measure fine and stay.
80
- - `warning.fill` / `warning.text` / `warning.bg` — unchanged.
81
- - The reference sheet's committed HTML artifact. It is the frozen spec of the accepted baseline;
82
- `warning.main` is a channel the sheet never depicted (see Verification).
83
- - Anything in `CHART-6`'s scope beyond the `grid` merge and the audit.
84
- - No behaviour, permission or data-contract change.
85
-
86
- ### Risks
87
-
88
- - **A palette value change is visible.** Any app already using `color="warning"` sees a darker
89
- filled control. No app has an adoption WO yet, so the blast radius today is ucm's own harness — but
90
- say it in the release note rather than let someone find it.
91
- - **Adding an assertion rule can turn a green suite red.** Safe today by the ratchet: the
92
- completeness check is a hard failure only for an app whose adoption WO has landed, and none has.
93
- It must stay that way — the new rule must not become hard for non-adopters.
94
- - **No staging net.** A push to `main` touching `src/**` publishes to npm at once; the independent
95
- review is the only gate and is not back-fillable.
96
- - **The `grid` merge changes behaviour for any caller who passes a partial `grid` today.** That is
97
- the point, but it means the rendered check should look at a chart that passes `grid` explicitly if
98
- one exists.
99
-
100
- ### Required tests to WRITE
101
-
102
- Narrow. Extend the existing files rather than adding new ones.
103
-
104
- **`tests/themeCompleteness.test.js`**
105
-
106
- 1. Every status channel's `main` clears 4.5:1 against `#FFFFFF` **and** against
107
- `background.default`. **Prove non-vacuity** by restoring `warning.main` to `#C08A2C` and
108
- confirming this test fails — that is the whole point of the rule.
109
- 2. The new rule reports, and does not hard-fail, for a theme belonging to an app without a landed
110
- adoption WO (the ratchet stays intact).
111
-
112
- **`tests/chartDefaults.test.js`**
113
-
114
- 3. A caller passing `grid={{ vertical: true }}` receives **both** `vertical: true` and the default
115
- `horizontal: true`. **Prove non-vacuity** by reverting to the plain default parameter and
116
- confirming the test fails.
117
- 4. A caller passing `grid={false}` (or the documented way to switch the grid off entirely) still
118
- gets no grid — merging must not make the default un-removable.
119
-
120
- Plus `tsc -p tsconfig.build.json --noEmit` clean.
121
-
122
- **No full-suite run.** Affected-areas set is the two test files above.
123
-
124
- ### Verification
125
-
126
- - The rendered two-width side-by-side per DS-1, **and this time it must cover what changed**: the
127
- harness needs a specimen row rendering `color="success|warning|error|info"` on **Button, Chip and
128
- Alert** — the components where `main` actually resolves. It has none today, which is precisely why
129
- the gate could not catch defect 1 the first time. Adding that row is part of this WO.
130
- - A chart specimen that passes a partial `grid`, to show the merge.
131
-
132
- ### Preconditions
133
-
134
- - `THEME-1` (`2.30.0`) and `CHART-6` (`2.31.0`) landed and published.
135
-
136
- ### Parity guardrail
137
-
138
- No behaviour, permission or data-contract change. One palette value moves deliberately and visibly;
139
- everything else must render identically.
140
-
141
- ---
142
-
143
- ## B. Implementation map
144
-
145
- *Filled by the Orchestrator on `git pull` — see AGENTS.md → "Work Order".*
146
-
147
- ### Execution directive (read this first)
148
-
149
- > **If you are the implementer reading this work order as your own specification: this section is
150
- > NOT addressed to you.** It tells the Orchestrator how to invoke you. **You ARE that invocation —
151
- > do NOT shell out to `codex exec`.**
152
- >
153
- > Implement through `codex exec` in the background — invoked directly via Bash (never the
154
- > `debugger`/`*_coder` Agent wrappers) with BOTH flags `--skip-git-repo-check` and
155
- > `--dangerously-bypass-approvals-and-sandbox`. **Pass the WO via stdin, not as a positional
156
- > argument** — `cat work-orders/THEME-2.md | codex exec --skip-git-repo-check
157
- > --dangerously-bypass-approvals-and-sandbox -` (a positional arg hits Windows' command-line length
158
- > limit on a WO this size — proven on THEME-1/CHART-6). Fallback to direct Claude implementation
159
- > only on Codex quota/rate-limit/non-zero exit.
160
-
161
- ### Context package
162
-
163
- **Preconditions verified 2026-08-10:** `THEME-1` (`96992cf`) and `CHART-6` (`6dedc62`) are both
164
- landed on `main` and published (`2.30.0`, `2.31.0`).
165
-
166
- **Defect 1 — exact current state, verified in `src/theme/tokens.js:81-87`:**
167
- ```js
168
- warning: {
169
- ...withMainShades('#C08A2C', '#212529'),
170
- text: '#976100',
171
- fill: '#C08A2C',
172
- fillText: '#212529',
173
- bg: '#FBF0DC',
174
- },
175
- ```
176
- `withMainShades(main, contrastText)` (defined near the top of `tokens.js`) sets `main`/`light`/`dark`/
177
- `contrastText` via MUI's own `lighten`/`darken` at 0.2/0.3 tonal offsets. **Fix:** change the call to
178
- `withMainShades('#976100', '#FFFFFF')` — reusing the existing `text` value as the new `main`, and
179
- `'#FFFFFF'` as `contrastText` (verify this actually clears 4.5:1 — the WO states 5.216 on white
180
- already for `#976100`, and `contrastText` white-on-`#976100` is the same ratio by symmetry). Leave
181
- `text`/`fill`/`fillText`/`bg` untouched — `fill` stays the lighter amber for deliberate fill use
182
- (THEME-1's own `MuiAlert` `standardWarning` styleOverride already reads `palette.warning.text`/`.bg`,
183
- NOT `.main`, so that specimen is unaffected by this change — see the harness note below for why a
184
- NEW specimen is needed to actually exercise `.main`).
185
-
186
- **Defect 1's assertion rule — add to `src/theme/themeCompleteness.js`'s `contrastFindings(theme)`
187
- function (~line 249).** Alongside the existing per-status `text`-vs-`bg` and `fillText`-vs-`fill`
188
- loops, add a third: for each `status` in `STATUS_KEYS` (`['success','warning','error','info',
189
- 'stale']`, from `tokens.js`) that HAS a `.main` property (**`stale` does not** — it's a custom
190
- augmented namespace, never passed through MUI's `createPalette`/`augmentColor`, so
191
- `theme.palette.stale.main` is `undefined` — skip it, don't push a spurious finding for a channel
192
- that was never supposed to have one), check `calculateContrastRatio(tokens.main, '#FFFFFF')` and
193
- `calculateContrastRatio(tokens.main, theme.palette.background.default)`, both `>= 4.5`, pushing a
194
- `contrast.<status>.main-on-<white|page>` finding (matching the existing naming convention,
195
- `contrast.controlBorder.<state>-on-<surface>`) on failure. This is a REPORT via the existing
196
- `findings` array — `assertThemeComplete` never throws or hard-fails on its own (confirm this by
197
- reading the function; the "ratchet stays a report, not a hard fail for non-adopters" is structural
198
- here, not a flag to add — a consuming app's OWN test suite decides whether to assert
199
- `findings.length === 0`, ucm's export just returns data either way).
200
-
201
- **Defect 2 — exact current state, verified in `src/components/charts/BarChart.jsx:26` and
202
- `LineChart.jsx:43`:** `grid = { horizontal: true }` as a bare JS default parameter, then
203
- `grid={grid}` passed straight through (`BarChart.jsx:65`, `LineChart.jsx:88`) — a caller-supplied
204
- `grid` object REPLACES the default wholesale rather than merging per-key, unlike every sibling prop
205
- in this file (compare `withAxisDefaults`'s `tickLabelStyle` merge, `withChartSlotDefaults`'s
206
- `tooltip`/`legend` merge — both spread the default first, caller second, so the caller only
207
- overrides the keys it actually sets). **Fix:** add a `withGridDefaults(grid)` helper to
208
- `src/components/charts/chartDefaults.js` following the SAME pattern (`{ horizontal: true, ...grid }`
209
- — MUI's `grid` prop type is `Pick<ChartsGridProps, 'vertical'|'horizontal'>`, plain optional
210
- booleans, no special `false`/`true` shorthand at the type level, so spreading a caller's object
211
- after the default is sufficient: a caller wanting no grid at all passes
212
- `grid={{ horizontal: false, vertical: false }}` explicitly, which the spread correctly honours since
213
- it's a later key overriding an earlier one — do not add special-casing for a literal `grid={false}`
214
- unless you find MUI's actual runtime prop handling treats a boolean differently from the declared
215
- type, which the WO's own phrasing ("or the documented way to switch the grid off entirely") already
216
- anticipates might not be a literal `false`). Wire it into both `BarChart.jsx` and `LineChart.jsx`
217
- the same way the other `chartDefaults.js` helpers are used.
218
-
219
- **Defect 2's audit — read `src/components/charts/chartDefaults.js` in full and check each
220
- object-valued prop the wrappers default or forward against the same replace-vs-merge question:**
221
- - `withAxisDefaults`'s `tickLabelStyle: { fontSize: tickFontSize, ...axis.tickLabelStyle }` —
222
- ALREADY merges correctly (default first, caller's own `tickLabelStyle` fields win per-key).
223
- - `withChartSlotDefaults`'s `{ ...slotProps, tooltip: {...}, legend: {...} }` — the outer
224
- `...slotProps` spread preserves any OTHER slot key a caller sets (e.g. `slotProps.axisHighlight`),
225
- and the `tooltip`/`legend` sub-objects are themselves merged default-first. ALREADY correct.
226
- - `LineChart.jsx`'s `slots={{ mark: FilledMarkElement, ...slots }}` — default first, caller's own
227
- `slots` spread after, so a caller's own `slots.mark` wins and other slot keys survive. ALREADY
228
- correct.
229
- - `spaceForRotatedTicks`'s `margin` handling is NOT a "default object caller can partially override"
230
- shape at all (it only computes `margin.bottom` when rotation is detected AND the caller hasn't set
231
- one) — not the same bug class, nothing to fix there, but confirm this reading is right by re-reading
232
- the function rather than trusting this summary.
233
- **Verify each of these four independently rather than trusting this list — this map is a starting
234
- point for the audit, not a substitute for it.** If the audit finds anything actually broken beyond
235
- `grid`, fix it and say so explicitly in the PR/commit, per the WO's "fix that too and say so." If the
236
- audit confirms all four are already correct, state that explicitly too — "audited and confirmed
237
- correct" is a valid, expected outcome per the WO ("either... or a named list").
238
-
239
- **Harness — why a new specimen row is required, not optional (verified 2026-08-10):** the current
240
- `ThemeBaselineEntry` (`dev/entries.jsx`) has TWO status-colour specimens today, and NEITHER exercises
241
- `palette.<status>.main`:
242
- 1. `StatusChip` (`dev/entries.jsx:71-78`) sets `sx={{ bgcolor: '${tone}.fill', color:
243
- '${tone}.fillText' }}` directly — bypasses `.main` entirely by design.
244
- 2. `<Alert severity="warning">` etc. (`dev/entries.jsx:136-140`) — THEME-1's `MuiAlert`
245
- `styleOverrides.standardWarning` (`src/theme/createAppTheme.js`'s `createPaletteAwareComponents`)
246
- already overrides the STANDARD variant's `color`/`backgroundColor` to `palette.warning.text`/
247
- `.bg` directly, NOT `.main` — so this existing Alert row was already immune to defect 1 and would
248
- not have caught it even now.
249
- Add: a row of `<Button color="success|warning|error|info" variant="contained">` (MUI's contained
250
- Button reads `palette[color].main` for its background and `.contrastText` for its label — this is
251
- the most direct `.main` exposure in the kit), a row of native `<Chip color="warning">` (not
252
- `StatusChip` — MUI's own `color` prop on `Chip`, filled variant, also reads `.main`/
253
- `.contrastText` directly), and an `<Alert severity="warning" variant="filled">` (MUI's `filled`
254
- Alert variant is NOT covered by THEME-1's `standardWarning`-only override, so it still resolves
255
- `.main` — confirm this by checking `createPaletteAwareComponents`'s `alertStyles` only sets
256
- `standard${Status}` keys, never `filled${Status}` or `outlined${Status}`). These three together
257
- are what the WO's Verification section means by "Button, Chip and Alert — the components where
258
- `main` actually resolves."
259
-
260
- **Chart specimen for the `grid` merge:** the existing "Caller overrides" `LineChart` specimen
261
- (`dev/entries.jsx`, added in CHART-6) already sets `grid={{ horizontal: true, vertical: true }}` — a
262
- COMPLETE object, which happens to already include `horizontal: true`, so it would not visibly
263
- demonstrate the bug even pre-fix. Change it to a genuinely PARTIAL grid, e.g. `grid={{ vertical:
264
- true }}` alone — pre-fix this would have shown ONLY vertical lines (losing the horizontal default);
265
- post-fix it must show both. This is the specimen the WO's Verification section calls for ("A chart
266
- specimen that passes a partial `grid`, to show the merge").
267
-
268
- ### Named files to change
269
-
270
- - `src/theme/tokens.js` — the `warning` entry's `withMainShades(...)` call (line 82).
271
- - `src/theme/themeCompleteness.js` — `contrastFindings` (~line 249), add the `main`-vs-white/page
272
- loop, skipping any `STATUS_KEYS` entry without a `.main`.
273
- - `src/components/charts/chartDefaults.js` — new `withGridDefaults` export.
274
- - `src/components/charts/BarChart.jsx:26,65`, `src/components/charts/LineChart.jsx:43,88` — wire in
275
- `withGridDefaults`.
276
- - `dev/entries.jsx` — new Button/Chip/Alert `.main`-exercising specimen row; fix the existing
277
- "Caller overrides" LineChart's `grid` prop to a genuinely partial object.
278
- - `package.json` — version `2.31.0` → `2.31.1` (patch).
279
- - `tests/themeCompleteness.test.js` — extend with the 2 required tests (main contrast + non-vacuity
280
- proof by temporarily reverting `warning.main`; ratchet/report-not-hard-fail confirmation).
281
- - `tests/chartDefaults.test.js` — extend with the 2 required tests (partial-grid merge + non-vacuity
282
- proof by temporarily reverting to the bare default parameter; grid-off-via-explicit-false-object
283
- still works).
284
-
285
- ### Do-not-touch / invariants
286
-
287
- - `success`/`error`/`info`/`stale` palette values — untouched, they measure fine.
288
- - `warning.fill`/`.text`/`.bg` — untouched.
289
- - The committed reference-sheet HTML artifact (`work-orders/assets/THEME-1-baseline-reference-sheet.html`)
290
- — frozen spec, never depicted `warning.main` as a foreground, not touched by this WO.
291
- - Anything in CHART-6's scope beyond the `grid` merge and the audit — no new chart-chrome feature
292
- work here.
293
- - No behaviour, permission, or data-contract change.
294
-
295
- ### Pitfalls (verified against landed code 2026-08-10)
296
-
297
- - `withMainShades` is defined once near the top of `tokens.js` and used for
298
- `success`/`warning`/`error`/`info` — changing ONLY the `warning` call site, not the helper itself
299
- (the helper's `lighten`/`darken` derivation logic is correct and unrelated to this bug).
300
- - `STATUS_KEYS` includes `'stale'`, which has no MUI-augmented `.main` — a naive loop over all
301
- `STATUS_KEYS` reading `tokens.main` will hit `undefined` for `stale`; guard it (`if (!tokens?.main)
302
- continue`, matching the existing loop's `if (!tokens) continue` pattern one function up).
303
- - Don't confuse this WO's `contrastFindings` addition with `THEME_COMPLETENESS_SURFACES`'s existing
304
- `STATUS_SURFACES` (`text`/`fill`/`fillText`/`bg` presence-vs-default check) — the new rule is a
305
- CONTRAST check (numeric ratio), same family as the existing `contrast.<status>.text-on-bg` /
306
- `contrast.controlBorder.*` findings, not a "surface is deliberately defined" presence check.
307
-
308
- ### Target repo working directory (absolute)
309
-
310
- `C:\Users\biglmi\Documents\webapps\ui-core-micha`
311
-
312
- ### Required tests to WRITE (Codex writes them; the Orchestrator runs them)
313
-
314
- Exactly the 4 tests enumerated in Envelope § "Required tests to WRITE" above, extending
315
- `tests/themeCompleteness.test.js` and `tests/chartDefaults.test.js` (no new files), plus
316
- `tsc -p tsconfig.build.json --noEmit` clean. Do not add more, do not run the full suite. Affected-areas
317
- set is exactly those two files.
318
-
319
- ### Preamble (append verbatim)
320
-
321
- > The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there
322
- > is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the
323
- > app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
324
- > unless the spec says so; do not update `MEMORY.md`. Do NOT `git add`/`commit`/`push` — leave every
325
- > change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests
326
- > the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute
327
- > and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review).
328
- > The orchestrator re-runs the authoritative set + does the independent review after you finish —
329
- > those are the gate; your own run does not count as the gate.
330
- >
331
- > Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
332
- > `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
333
- > completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
334
- > `RESULT: DONE|BLOCKED <reason>`.
335
-
336
- ### Mini-handover
337
-
338
- Repo: `ui-core-micha` (`C:\Users\biglmi\Documents\webapps\ui-core-micha`), branch `main`. WO:
339
- `work-orders/THEME-2.md`. Follow `orchestrate-codex`.
@@ -1,210 +0,0 @@
1
- # THEME-3 — Add the missing "subtle surface" baseline token
2
-
3
- **Target repo:** `ui-core-micha` (branch `main` — this repo has no `develop`; a push touching
4
- `src/**`/`package.json` publishes to npm immediately via `publish.yml`)
5
- **Tier:** 3 — shared-core theme baseline, consumed by every `createAppTheme` adopter.
6
- **Review:** independent `reviewer` **and** `ui_reviewer`, concurrently, both mandatory before commit
7
- (no staging net in this repo — the independent review is the only gate and is not back-fillable).
8
- **Found by:** `cockpit/UI-6` (adopting `createAppTheme` with the frozen `UI-4` token table). The
9
- sheet's canonical token table (section 8, "what cockpit stops owning") lists an *inset surface*
10
- `#F4F5F6` as a baseline-supplied value, replacing `cockpit.surface2` (16 of 195 token reads in that
11
- WO). It does not exist anywhere in the shipped package — confirmed by grepping
12
- `src/theme/tokens.js`/`themeCompleteness.js` for the hex and for any "surface"/"inset" key. The value
13
- was one of the design-language instrument's *own* internal comparison-stack entries
14
- (`cockpit/work-orders/assets/UI-4-design-language.html:681`), never actually wired into
15
- `createAppTheme`. Per this estate's own rule ("a gap in the shared kit discovered mid-adoption is a
16
- `ui-core-micha` work order and cockpit's item waits — not a local workaround"), `UI-6` is blocked on
17
- this landing and publishing first.
18
-
19
- ---
20
-
21
- ## A. Envelope
22
-
23
- ### Goal
24
-
25
- Add a third baseline background tier — `palette.background.subtle` — to `createAppTheme`'s shared
26
- palette, for panels/table stripes/excerpt boxes that need to read as slightly recessed from
27
- `background.paper` without a bespoke per-app colour. Register it in the completeness-assertion
28
- surface inventory so every adopter (present and future) gets the same guarantee the other baseline
29
- surfaces already have.
30
-
31
- ### Scope
32
-
33
- 1. **`src/theme/tokens.js`** — add `background.subtle: '#F4F5F6'` to `BASELINE_PALETTE.background`
34
- (alongside the existing `default`/`paper`). This is a **fixed baseline constant**, not
35
- accent-derived — the same treatment as `default`/`paper`, not the accent-tint derivation used for
36
- `cockpit.accentTint`.
37
- 2. **`src/theme/themeCompleteness.js`** — add `pathSurface('palette.background.subtle')` to
38
- `THEME_COMPLETENESS_SURFACES`.
39
- 3. **Recompute the contrast claim independently** — the frozen sheet's "muted ink on it: 4.81" was
40
- computed on the sheet's own static comparison canvas, not via this package's
41
- `calculateContrastRatio`. Recompute `calculateContrastRatio('#5B6670', '#F4F5F6')` (baseline
42
- `ink.secondary`, the tone most likely to sit on this surface) directly against the shipped
43
- function before treating the sheet's number as confirmed.
44
- 4. Publish (version bump — see Risks for the semver call).
45
-
46
- ### Non-goals / do not touch
47
-
48
- - Renaming or removing any existing palette token.
49
- - `CHART-*`/`SHELL-*`/`AUTH-*` surfaces — unrelated to this addition.
50
- - `fitness-monitor` or any other consuming app's own repo — this WO lands and publishes the token
51
- only; `cockpit/UI-6` consumes it afterward, in its own repo, as a separate step.
52
- - Any accent-derived tint/shade math — this token is a fixed baseline value, structurally unlike
53
- `cockpit.accentTint`/`accentLight`/`accentDark`.
54
-
55
- ### Risks
56
-
57
- - **`fitness-monitor` is a real, already-shipped adopter** (`frontend/src/theme.js` +
58
- `frontend/src/theme.test.js`) that hard-asserts `assertThemeComplete(theme).findings` equals `[]`.
59
- A new *required* completeness surface must resolve automatically for every adopter with zero
60
- app-level action — the same guarantee `background.default`/`background.paper` already give,
61
- **not** an opt-in the app must declare. Concretely: the new key must come from
62
- `BASELINE_PALETTE` so every real `createAppTheme(...)` output has it defined, and MUI's own
63
- default theme must never define `background.subtle` itself (a novel key — verify this, don't
64
- assume it), so `descriptor.get(MUI_DEFAULT_THEME)` returns `undefined` and the "still equals MUI's
65
- untouched default" branch never fires. If either assumption is wrong, `fitness-monitor`'s CI
66
- breaks on its next pin bump and this WO must not ship that way.
67
- - **Semver classification** — additive to the factory's *output* (no adopter passes anything new to
68
- get it), which argues for a patch, mirroring `SHELL-4`'s "narrows the contract, cannot turn
69
- cockpit red" precedent in the opposite direction (widens the contract, but resolves automatically,
70
- so it also cannot turn an adopter red). Confirm no adopter needs a code change before treating
71
- this as settled rather than asserting it.
72
- - **Do not silently rename cockpit's `surface2` in this repo** — this WO adds the baseline token;
73
- cockpit's own re-point of 16 call sites from `cockpit.surface2` to the new baseline token is
74
- `UI-6`'s job, in cockpit's repo, not this one's.
75
-
76
- ### Required tests to WRITE
77
-
78
- 1. `assertThemeComplete` stays empty-findings for a minimal adopter call —
79
- `createAppTheme({ palette: { primary: { main: '#0F62FE' } } })` (mirroring `fitness-monitor`'s
80
- real usage) — proving the new surface resolves with zero adopter action, not just for a theme
81
- that happens to declare it.
82
- 2. `theme.palette.background.subtle` equals `'#F4F5F6'` on an unconfigured `createAppTheme(...)`
83
- call.
84
- 3. `calculateContrastRatio('#5B6670', '#F4F5F6')` (baseline `ink.secondary` on the new surface)
85
- passes AA (≥ 4.5:1) — computed via the shipped function, not asserted from the sheet's number.
86
- 4. Existing `tests/createAppTheme.test.js` and `tests/themeCompleteness.test.js` stay green
87
- unmodified in intent (only extended where the new surface must appear in an enumeration they
88
- already assert against, e.g. a surface-count or key-list check if one exists).
89
-
90
- ### Verification
91
-
92
- No visual/prototype gate — this is a token-level palette addition with no rendered specimen of its
93
- own in this repo. The rendered check for what this token actually looks like on real cockpit
94
- surfaces happens downstream, in `cockpit/UI-6`'s own two-width verification.
95
-
96
- ---
97
-
98
- ## B. Implementation map
99
-
100
- *Filled by the Orchestrator on `git pull` — see `AGENTS.md` → "Work Order".*
101
-
102
- ### Context package
103
-
104
- - **`src/theme/tokens.js`** — `BASELINE_PALETTE.background` currently reads:
105
- ```js
106
- background: {
107
- default: '#FAFAFA',
108
- paper: '#FFFFFF',
109
- },
110
- ```
111
- Add `subtle: '#F4F5F6'` as a third key. This is the ONLY change needed in this file for the new
112
- value itself — do not touch `SERIES_COLOURS`, `STATUS_KEYS`, `BASELINE_STATIC`, or the exemptions
113
- list.
114
- - **`src/theme/themeCompleteness.js`** — `THEME_COMPLETENESS_SURFACES` (around line 155-192) already
115
- has `pathSurface('palette.background.default')` and `pathSurface('palette.background.paper')` in
116
- its list. Add `pathSurface('palette.background.subtle')` immediately next to them — same helper,
117
- same pattern, no new machinery needed.
118
- - **Why this can't collide with an existing adopter (verified, not assumed):** `MUI_DEFAULT_THEME =
119
- createTheme()` (line 5 of `themeCompleteness.js`) is vanilla MUI with no `background.subtle` key —
120
- MUI's own palette only ever defines `background.default`/`.paper`. So for every real
121
- `createAppTheme(...)` output, `descriptor.get(theme)` resolves to `'#F4F5F6'` (defined) while
122
- `descriptor.get(MUI_DEFAULT_THEME)` resolves to `undefined` — the `sameValue` check in
123
- `assertThemeComplete` (around line 354) therefore never flags it, with no exemption required. This
124
- is exactly why `background.default` needs no exemption today; `background.subtle` gets the same
125
- treatment. `background.paper` is the one that DOES need an exemption, because MUI's own default
126
- theme also happens to be white — do not copy that exemption pattern here, it does not apply.
127
- - **`calculateContrastRatio` is already exported** from `src/theme/themeCompleteness.js` and
128
- re-exported from `src/theme/index.js` — use it directly for the required contrast test, do not
129
- reimplement contrast math.
130
- - **Test file conventions** (read `tests/themeCompleteness.test.js` and
131
- `tests/createAppTheme.test.js` for the existing style before writing new assertions — minimal
132
- `createAppTheme({ palette: { primary: { main: '#0F62FE' } } })` is the repo's own established
133
- "minimal adopter" fixture, already used in both files; reuse it rather than inventing a new one).
134
- - Directive: work from this package; do not explore broadly from scratch; open only the two named
135
- source files plus the two named test files to verify. If you must dig deeper, delegate to a
136
- read-only Explore sub-agent (Haiku).
137
-
138
- ### Target repo working directory (absolute)
139
-
140
- `C:\Users\biglmi\Documents\webapps\ui-core-micha`
141
-
142
- ### Preamble
143
-
144
- > The text of this whole file is the COMPLETE spec — not a plan to refine; there is no separate plan
145
- > file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and this repo's
146
- > own `DESIGN.md`/conventions ONLY for conventions. Stay in scope; do not touch
147
- > `CHART-*`/`SHELL-*`/`AUTH-*` surfaces or any file outside `src/theme/` and `tests/` unless this
148
- > spec says so; do not update any `MEMORY.md`. Do NOT `git add` / `commit` / `push` — leave every
149
- > change uncommitted in the working tree for the orchestrator's independent review; do NOT bump
150
- > `package.json`'s version yourself — the Orchestrator decides and applies the semver bump after
151
- > review, per the Risks section's still-open patch/minor question. WRITE the tests the "Required
152
- > tests to WRITE" section calls for AND **RUN the tests you just wrote** (plus the two named existing
153
- > spec files, to confirm no regression) to confirm they execute and pass — that is the ONLY test run
154
- > you do (NOT this repo's full suite, NOT any review). The orchestrator re-runs the authoritative set
155
- > + does the independent review after you finish — those are the gate; your own run does not count
156
- > as the gate.
157
- >
158
- > Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
159
- > `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
160
- > completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
161
- > `RESULT: DONE|BLOCKED <reason>`.
162
-
163
- ---
164
-
165
- ## C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
166
-
167
- > **If you are the implementer reading this work order as your own specification: STOP at this line.
168
- > Everything below describes what the Orchestrator does AFTER you finish. You do none of it — no
169
- > reviewers, no verification run, no register edit, no commit.** You ARE the invocation described
170
- > below; do NOT shell out to `codex exec`.
171
-
172
- ### Execution directive
173
-
174
- Implement through `codex exec` in the background — invoked directly via Bash (never the
175
- `debugger`/`*_coder` Agent wrappers) with BOTH flags `--skip-git-repo-check` and
176
- `--dangerously-bypass-approvals-and-sandbox`. **Pass the work order via stdin, not as a positional
177
- argument** (this repo's own `THEME-1` row already documents the Windows command-line length limit
178
- hitting this via the npm shim). Fallback to direct Claude implementation only on Codex
179
- quota/rate-limit/non-zero exit — the fallback flips authorship, so both reviewers stay mandatory
180
- either way.
181
-
182
- ### Review routing
183
-
184
- Tier 3: `reviewer` (Sonnet) + `ui_reviewer` (Sonnet), concurrent, same background batch, before
185
- commit. No `sec_reviewer` — no auth/security surface in scope. `ui_reviewer`'s job here is narrow
186
- (no rendered surface to review) — focus it on the completeness-contract and adopter-safety question
187
- rather than visual design.
188
-
189
- ### Verification
190
-
191
- No rendered two-width check — token-only change with no specimen in this repo (per the Envelope).
192
- The authoritative check is: the two new/extended test files pass, `tests/createAppTheme.test.js` +
193
- `tests/themeCompleteness.test.js` stay green, and a direct read of `fitness-monitor`'s
194
- `frontend/src/theme.test.js` assertion confirms it would still pass unmodified against the new
195
- package version (do not just reason about it — actually run `fitness-monitor`'s own scoped theme
196
- test against the locally-built `ui-core-micha` if practical, or explain why not).
197
-
198
- ### Register + commit
199
-
200
- Decide and apply the semver bump (patch, per the Risks section's reasoning, unless the
201
- implementation reveals an adopter needs a code change — then escalate to minor and say why). Update
202
- the `WORK_ORDERS.md` THEME-3 row to `done` with the named review verdicts and version, then commit +
203
- push to `main` on green (this push publishes to npm — confirm everything is green first, there is no
204
- staging net here).
205
-
206
- ### Mini-handover
207
-
208
- Repo: `ui-core-micha` (`C:\Users\biglmi\Documents\webapps\ui-core-micha`), branch `main`.
209
- WO: `work-orders/THEME-3.md`. **Ready to run** — no preconditions, small well-bounded addition.
210
- Follow `orchestrate-codex`.