@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.
- package/CHANGELOG.md +25 -0
- package/README.md +7 -0
- package/dist/chat/kitSxRegistry.js +9 -0
- package/dist/components/charts/kitSxRegistry.js +6 -0
- package/dist/entries/charts.js +6 -0
- package/dist/entries/chat.js +8 -0
- package/dist/entries/markdown.js +1 -0
- package/dist/index.js +0 -14
- package/dist/pages/AccountPage.js +1 -2
- package/dist/pages/LoginPage.js +1 -2
- package/dist/pages/PasswordChangePage.js +1 -2
- package/dist/pages/PasswordInvitePage.js +1 -2
- package/dist/pages/PasswordResetRequestPage.js +1 -2
- package/dist/pages/SignUpPage.js +1 -2
- package/dist/pages/SignupConfirmPage.js +1 -2
- package/dist/theme/kitSxEntry.js +11 -0
- package/dist/theme/kitSxRegistry.js +2 -15
- package/package.json +32 -7
- package/.github/workflows/ci.yml +0 -35
- package/.github/workflows/publish.yml +0 -126
- package/DESIGN.md +0 -60
- package/WORK_ORDERS.md +0 -150
- package/dev/entries.jsx +0 -721
- package/dev/fixtures.js +0 -26
- package/dev/main.jsx +0 -75
- package/dev/mockTransport.jsx +0 -128
- package/docs/CHART-LAYOUT.md +0 -157
- package/docs/DARK-TOKENS.md +0 -140
- package/docs/TYPE-SCALE.md +0 -111
- package/docs/messaging-deviations.md +0 -118
- package/index.html +0 -12
- package/renovate.json +0 -10
- package/scripts/chart-api-census.mjs +0 -415
- package/src/auth/AuthContext.jsx +0 -158
- package/src/auth/ReauthModal.jsx +0 -82
- package/src/auth/UserMenu.jsx +0 -121
- package/src/auth/apiClient.jsx +0 -232
- package/src/auth/authApi.jsx +0 -539
- package/src/auth/authConfig.jsx +0 -34
- package/src/auth/reauth.js +0 -47
- package/src/chat/ChatComposer.jsx +0 -36
- package/src/chat/ChatList.jsx +0 -87
- package/src/chat/ChatThread.jsx +0 -128
- package/src/chat/ChatWorkspace.jsx +0 -244
- package/src/chat/MarkdownReply.jsx +0 -22
- package/src/chat/ModelPicker.jsx +0 -85
- package/src/chat/api.js +0 -18
- package/src/chat/useChatSocket.js +0 -32
- package/src/chat/wire.js +0 -7
- package/src/components/AccessCodeManager.jsx +0 -288
- package/src/components/AccessCodeSingleUseToggle.jsx +0 -92
- package/src/components/AllowedEmailDomainsManager.jsx +0 -92
- package/src/components/AuthFactorRequirementCard.jsx +0 -95
- package/src/components/BulkInviteCsvTab.jsx +0 -198
- package/src/components/EmptyState.jsx +0 -38
- package/src/components/LoginForm.jsx +0 -159
- package/src/components/MFAComponent.jsx +0 -350
- package/src/components/MfaLoginComponent.jsx +0 -252
- package/src/components/MobileBottomNav.jsx +0 -82
- package/src/components/PasskeysComponent.jsx +0 -252
- package/src/components/PasswordChangeForm.jsx +0 -87
- package/src/components/PasswordResetRequestForm.jsx +0 -43
- package/src/components/PasswordSetForm.jsx +0 -97
- package/src/components/ProfileComponent.jsx +0 -348
- package/src/components/QrSignupManager.jsx +0 -404
- package/src/components/QrSignupValidityManager.jsx +0 -106
- package/src/components/RegistrationMethodsManager.jsx +0 -150
- package/src/components/SecurityComponent.jsx +0 -141
- package/src/components/SocialLoginButtons.jsx +0 -83
- package/src/components/SoftChip.jsx +0 -93
- package/src/components/StatTile.jsx +0 -39
- package/src/components/SupportRecoveryRequestsTab.jsx +0 -482
- package/src/components/TurnstileWidget.jsx +0 -99
- package/src/components/UserInviteComponent.jsx +0 -76
- package/src/components/UserListComponent.jsx +0 -618
- package/src/components/charts/BarChart.jsx +0 -102
- package/src/components/charts/ChartFrame.jsx +0 -214
- package/src/components/charts/LineChart.jsx +0 -126
- package/src/components/charts/ScatterChart.jsx +0 -299
- package/src/components/charts/TimeSeriesChart.jsx +0 -300
- package/src/components/charts/chartDefaults.js +0 -644
- package/src/components/charts/chartLabels.js +0 -36
- package/src/components/charts/exportChart.js +0 -258
- package/src/components/charts/formatters.js +0 -39
- package/src/components/charts/palette.js +0 -33
- package/src/components/charts/yearTickInterval.js +0 -7
- package/src/i18n/authTranslations.ts +0 -2651
- package/src/i18n/chartsTranslations.ts +0 -91
- package/src/i18n/chatTranslations.ts +0 -55
- package/src/i18n/messagingTranslations.ts +0 -120
- package/src/i18n/notificationsTranslations.ts +0 -32
- package/src/i18n/onboardingTranslations.ts +0 -29
- package/src/i18n/sectionNavTranslations.ts +0 -20
- package/src/i18n/uiCoreTranslations.js +0 -29
- package/src/i18n/userMenuTranslations.ts +0 -5
- package/src/index.js +0 -158
- package/src/layout/PageLayout.jsx +0 -36
- package/src/layout/SectionNav.jsx +0 -320
- package/src/messaging/AttachmentList.jsx +0 -145
- package/src/messaging/Composer.jsx +0 -197
- package/src/messaging/ConversationLaunchers.jsx +0 -51
- package/src/messaging/ConversationList.jsx +0 -109
- package/src/messaging/DirectMessageLauncher.jsx +0 -112
- package/src/messaging/MessageBubble.jsx +0 -183
- package/src/messaging/MessagingProvider.jsx +0 -0
- package/src/messaging/MessagingScopeConfig.jsx +0 -24
- package/src/messaging/PollCard.jsx +0 -163
- package/src/messaging/ReactionBar.jsx +0 -43
- package/src/messaging/ReadTicks.jsx +0 -82
- package/src/messaging/Thread.jsx +0 -195
- package/src/messaging/api.js +0 -48
- package/src/messaging/composerImageCompression.js +0 -35
- package/src/messaging/linkifyText.jsx +0 -37
- package/src/notifications/NotificationBell.jsx +0 -84
- package/src/notifications/NotificationSettings.jsx +0 -330
- package/src/notifications/NotificationsProvider.jsx +0 -224
- package/src/notifications/PopupSurface.jsx +0 -105
- package/src/notifications/api.js +0 -55
- package/src/notifications/feedApi.js +0 -18
- package/src/notifications/realtime.jsx +0 -138
- package/src/notifications/serviceWorker/sw.js +0 -50
- package/src/onboarding/OnboardingProvider.jsx +0 -326
- package/src/onboarding/OnboardingWizard.jsx +0 -61
- package/src/onboarding/WizardDialogShell.jsx +0 -51
- package/src/onboarding/api.js +0 -13
- package/src/onboarding/stepSelection.js +0 -16
- package/src/onboarding/steps/BrowserPushStep.jsx +0 -121
- package/src/onboarding/steps/CompleteNameStep.jsx +0 -46
- package/src/onboarding/steps/CookieConsentStep.jsx +0 -133
- package/src/onboarding/steps/PwaInstallStep.jsx +0 -47
- package/src/pages/AccountPage.jsx +0 -394
- package/src/pages/LoginPage.jsx +0 -343
- package/src/pages/PasswordChangePage.jsx +0 -62
- package/src/pages/PasswordInvitePage.jsx +0 -177
- package/src/pages/PasswordResetRequestPage.jsx +0 -68
- package/src/pages/SignUpPage.jsx +0 -268
- package/src/pages/SignupConfirmPage.jsx +0 -155
- package/src/testing/checkKitIntegration.js +0 -233
- package/src/theme/createAppTheme.js +0 -423
- package/src/theme/fonts.js +0 -3
- package/src/theme/index.js +0 -21
- package/src/theme/kitSxRegistry.js +0 -285
- package/src/theme/themeCompleteness.js +0 -1045
- package/src/theme/tokens.js +0 -478
- package/src/utils/auth-errors.js +0 -76
- package/src/utils/authService.js +0 -223
- package/src/utils/resolveErrorText.js +0 -28
- package/src/utils/webauthn.js +0 -51
- package/tests/AccountPage.profileStatements.test.jsx +0 -162
- package/tests/AccountPage.test.jsx +0 -200
- package/tests/AuthContext.test.jsx +0 -129
- package/tests/BarChart.test.jsx +0 -112
- package/tests/BrowserPushStep.test.jsx +0 -110
- package/tests/ChartFrame.test.jsx +0 -336
- package/tests/ConversationList.test.jsx +0 -144
- package/tests/CookieConsentStep.test.jsx +0 -69
- package/tests/EmptyState.test.jsx +0 -62
- package/tests/LineChart.test.jsx +0 -80
- package/tests/MessagingProvider.test.jsx +0 -50
- package/tests/MobileBottomNav.test.jsx +0 -319
- package/tests/NotificationBell.test.jsx +0 -60
- package/tests/NotificationSettings.test.jsx +0 -276
- package/tests/NotificationsProvider.test.jsx +0 -240
- package/tests/OnboardingProvider.test.jsx +0 -294
- package/tests/OnboardingWizard.test.jsx +0 -143
- package/tests/PasswordChangeForm.test.jsx +0 -70
- package/tests/PasswordInvitePage.test.jsx +0 -142
- package/tests/PasswordSetForm.test.jsx +0 -70
- package/tests/PopupSurface.test.jsx +0 -142
- package/tests/ProfileComponent.refresh.test.jsx +0 -194
- package/tests/QrSignupManager.registrationContext.test.jsx +0 -106
- package/tests/QrSignupManagerInfoBox.test.jsx +0 -49
- package/tests/ScatterChart.test.jsx +0 -270
- package/tests/SectionNav.test.jsx +0 -363
- package/tests/SignUpPage.test.jsx +0 -208
- package/tests/SoftChip.test.jsx +0 -105
- package/tests/StatTile.test.jsx +0 -57
- package/tests/Thread.test.jsx +0 -151
- package/tests/TimeSeriesChart.test.jsx +0 -367
- package/tests/UserListComponent.test.jsx +0 -192
- package/tests/UserMenu.test.jsx +0 -171
- package/tests/apiClientLanguage.test.js +0 -33
- package/tests/apiClientPublicPaths.test.js +0 -178
- package/tests/authApiLogin.test.js +0 -42
- package/tests/authApiRegistration.test.js +0 -31
- package/tests/authErrorCodeRendering.test.jsx +0 -77
- package/tests/authErrors.test.js +0 -74
- package/tests/authTranslations.test.js +0 -74
- package/tests/chart-api-census.test.js +0 -366
- package/tests/chartAxisTickBand.test.jsx +0 -95
- package/tests/chartDefaults.test.js +0 -902
- package/tests/chartLabels.test.js +0 -50
- package/tests/chartsPalette.test.js +0 -99
- package/tests/chatApi.test.js +0 -48
- package/tests/chatDriverNames.test.jsx +0 -71
- package/tests/chatExports.test.js +0 -3
- package/tests/chatList.test.jsx +0 -84
- package/tests/chatPicker.test.jsx +0 -82
- package/tests/chatSocket.test.jsx +0 -26
- package/tests/chatThread.test.jsx +0 -116
- package/tests/chatTranslations.test.js +0 -47
- package/tests/chatWorkspace.test.jsx +0 -234
- package/tests/checkKitIntegration.test.jsx +0 -219
- package/tests/createAppTheme.test.js +0 -132
- package/tests/createAppThemeDark.test.js +0 -127
- package/tests/createAppThemeLightGuard.test.js +0 -40
- package/tests/createAppThemePageContrast.test.js +0 -108
- package/tests/createAppThemeTypography.test.js +0 -53
- package/tests/errorCallSiteGuard.test.js +0 -32
- package/tests/exportChart.test.js +0 -313
- package/tests/feedApi.test.js +0 -46
- package/tests/fixtures/light-theme-baseline.json +0 -2234
- package/tests/i18nAggregate.test.js +0 -120
- package/tests/i18nGermanVariant.test.js +0 -65
- package/tests/loginPageErrorResolution.test.jsx +0 -102
- package/tests/messagingApi.test.js +0 -32
- package/tests/messagingChunk6.test.jsx +0 -116
- package/tests/messagingCompactBubble.test.jsx +0 -64
- package/tests/messagingComposer.test.jsx +0 -136
- package/tests/messagingComposerChunk5.test.jsx +0 -113
- package/tests/messagingContractConformance.test.js +0 -69
- package/tests/messagingDirectMessageLauncher.test.jsx +0 -151
- package/tests/messagingExports.test.js +0 -21
- package/tests/messagingInteractions.test.jsx +0 -136
- package/tests/messagingLastMessagePreview.test.jsx +0 -93
- package/tests/messagingLinkify.test.jsx +0 -51
- package/tests/messagingMessageActions.test.jsx +0 -163
- package/tests/messagingMsg6.test.jsx +0 -105
- package/tests/messagingMsg6f.test.jsx +0 -155
- package/tests/messagingMsg6g.test.jsx +0 -166
- package/tests/messagingMsg6h.test.jsx +0 -136
- package/tests/messagingMsg6i.test.jsx +0 -129
- package/tests/messagingPollRendering.test.jsx +0 -142
- package/tests/messagingReactionMerge.test.jsx +0 -77
- package/tests/messagingReadTicksTooltip.test.jsx +0 -36
- package/tests/messagingThreadReceipts.test.jsx +0 -178
- package/tests/messagingThreadingQuoting.test.jsx +0 -87
- package/tests/messagingUnreadLifecycle.test.jsx +0 -78
- package/tests/notificationsApi.test.js +0 -41
- package/tests/notificationsExports.test.js +0 -34
- package/tests/onboardingDescriptors.test.js +0 -132
- package/tests/packageTreeShaking.test.js +0 -126
- package/tests/realtime.test.jsx +0 -219
- package/tests/resolveErrorText.test.js +0 -72
- package/tests/stepSelection.test.js +0 -53
- package/tests/themeCompleteness.test.js +0 -626
- package/tests/timeSeriesLegend.test.js +0 -99
- package/tests/userScreenTranslations.test.jsx +0 -218
- package/tsconfig.build.json +0 -18
- package/vite.config.mjs +0 -6
- package/work-orders/AUTH-1.md +0 -74
- package/work-orders/AUTH-2.md +0 -74
- package/work-orders/AUTH-4.md +0 -183
- package/work-orders/AUTH-5.md +0 -154
- package/work-orders/AUTH-7.md +0 -181
- package/work-orders/AUTH-8.md +0 -184
- package/work-orders/CHART-1.md +0 -285
- package/work-orders/CHART-2.md +0 -222
- package/work-orders/CHART-3.md +0 -163
- package/work-orders/CHART-4.md +0 -203
- package/work-orders/CHART-5.md +0 -226
- package/work-orders/CHART-6.md +0 -428
- package/work-orders/CHART-7.md +0 -175
- package/work-orders/DX-1.md +0 -169
- package/work-orders/DX-2.md +0 -188
- package/work-orders/DX-3.md +0 -195
- package/work-orders/I18N-1.md +0 -254
- package/work-orders/I18N-3.md +0 -207
- package/work-orders/MSG-3.md +0 -375
- package/work-orders/MSG-3b.md +0 -1002
- package/work-orders/MSG-3c.md +0 -378
- package/work-orders/MSG-3d.md +0 -268
- package/work-orders/MSG-3e.md +0 -164
- package/work-orders/MSG-3f.md +0 -391
- package/work-orders/MSG-6e.md +0 -308
- package/work-orders/MSG-6f.md +0 -214
- package/work-orders/MSG-6g.md +0 -244
- package/work-orders/MSG-6h.md +0 -238
- package/work-orders/MSG-6i.md +0 -271
- package/work-orders/MSG-6j.md +0 -117
- package/work-orders/NOTIF-12.md +0 -214
- package/work-orders/NOTIF-13.md +0 -142
- package/work-orders/NOTIF-14.md +0 -151
- package/work-orders/PRIM-1.md +0 -177
- package/work-orders/SHELL-1.md +0 -255
- package/work-orders/SHELL-2.md +0 -197
- package/work-orders/SHELL-3.md +0 -359
- package/work-orders/SHELL-4.md +0 -351
- package/work-orders/SHELL-5.md +0 -345
- package/work-orders/SHELL-6.md +0 -210
- package/work-orders/THEME-1.md +0 -587
- package/work-orders/THEME-10.md +0 -303
- package/work-orders/THEME-11.md +0 -208
- package/work-orders/THEME-2.md +0 -339
- package/work-orders/THEME-3.md +0 -210
- package/work-orders/THEME-4.md +0 -271
- package/work-orders/THEME-5.md +0 -341
- package/work-orders/THEME-6.md +0 -247
- package/work-orders/THEME-7.md +0 -82
- package/work-orders/THEME-8.md +0 -211
- package/work-orders/THEME-9.md +0 -194
- package/work-orders/UCM-AUTH-10.md +0 -490
- package/work-orders/UCM-AUTH-11.md +0 -185
- package/work-orders/UCM-AUTH-12.md +0 -98
- package/work-orders/UCM-AUTH-13.md +0 -47
- package/work-orders/UCM-AUTH-9.md +0 -207
- package/work-orders/UCM-CHART-10.md +0 -150
- package/work-orders/UCM-CHART-11.md +0 -132
- package/work-orders/UCM-CHART-12.md +0 -348
- package/work-orders/UCM-CHART-13.md +0 -122
- package/work-orders/UCM-CHART-14.md +0 -198
- package/work-orders/UCM-CHART-15.md +0 -187
- package/work-orders/UCM-CHART-16.md +0 -169
- package/work-orders/UCM-CHART-17.md +0 -195
- package/work-orders/UCM-CHART-18.md +0 -200
- package/work-orders/UCM-CHART-8.md +0 -147
- package/work-orders/UCM-CHART-9.md +0 -265
- package/work-orders/UCM-CHAT-1.md +0 -190
- package/work-orders/UCM-CHAT-2.md +0 -75
- package/work-orders/UCM-CI-1.md +0 -65
- package/work-orders/UCM-DEP-1.md +0 -63
- package/work-orders/UCM-I18N-4.md +0 -226
- package/work-orders/UCM-I18N-5.md +0 -211
- package/work-orders/UCM-MSG-20.md +0 -192
- package/work-orders/UCM-PRIM-2.md +0 -114
- package/work-orders/UCM-SHELL-7.md +0 -134
- package/work-orders/UCM-SHELL-8.md +0 -125
- package/work-orders/UCM-TEST-1.md +0 -304
- package/work-orders/UCM-THEME-13.md +0 -69
- package/work-orders/UCM-THEME-14.md +0 -312
- package/work-orders/UCM-THEME-15.md +0 -356
- package/work-orders/UCM-THEME-16.md +0 -80
- package/work-orders/UCM-THEME-17.md +0 -111
- package/work-orders/UCM-THEME-18.md +0 -184
- package/work-orders/assets/AUTH-4-user-list-card.html +0 -407
- package/work-orders/assets/PRIM-1-dashboard-primitives.html +0 -624
- package/work-orders/assets/SHELL-2-account-navigation.html +0 -1159
- package/work-orders/assets/THEME-1-baseline-reference-sheet.html +0 -1352
- package/work-orders/assets/UCM-CHAT-1-ai-chat.html +0 -447
- package/work-orders/assets/UCM-THEME-13-dark-prototype.html +0 -390
- package/work-orders/assets/UCM-THEME-17-type-scale.html +0 -391
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# UCM-CHART-8 — Make the chart presets stop producing dead space below the chart
|
|
2
|
-
|
|
3
|
-
- **Repo:** `ui-core-micha`, branch `main` (shared-core; publishes from `main` without a staging step)
|
|
4
|
-
- **Tier:** 3 — shared-core. Every consuming app inherits the behaviour change.
|
|
5
|
-
- **Status:** planned
|
|
6
|
-
- **Workstream:** `CHART-*` (chart presets)
|
|
7
|
-
- **Files:** `src/components/charts/ScatterChart.jsx`, `BarChart.jsx`, `LineChart.jsx`,
|
|
8
|
-
`TimeSeriesChart.jsx`, **`ChartFrame.jsx`** — all five destructure `minHeight` **and** `aspect`
|
|
9
|
-
(verified 2026-08-21) — plus their tests. **Note for the implementer: only `ScatterChart` and
|
|
10
|
-
`TimeSeriesChart` reference `height` at all.** `BarChart`, `LineChart` and `ChartFrame` never
|
|
11
|
-
destructure it, so for them the incoherent "pair" exists only via the rest spread into the MUI
|
|
12
|
-
chart. Do not go looking for a declared `height` prop there.
|
|
13
|
-
|
|
14
|
-
> **Why.** `minHeight` and `height` are two different things on these presets, and the API lets a
|
|
15
|
-
> caller pass both. `minHeight` lands on the **wrapper `Box`** —
|
|
16
|
-
> `sx={{ width: '100%', minHeight, aspectRatio: aspect }}` (`ScatterChart.jsx:260`, same
|
|
17
|
-
> construction in `BarChart.jsx`) — while `height` sizes the **chart**. When `minHeight > height`,
|
|
18
|
-
> the difference is dead space **below the chart**.
|
|
19
|
-
>
|
|
20
|
-
> Measured in `hram` on 2026-08-20:
|
|
21
|
-
>
|
|
22
|
-
> | panel | `minHeight` | `height` | dead space |
|
|
23
|
-
> |---|---|---|---|
|
|
24
|
-
> | `StructuralReachabilityPanel` | 420 | 380 | 40 px |
|
|
25
|
-
> | `ExpertTimelinePanel` | 340 | 280 (×2) | 60 px |
|
|
26
|
-
> | `ResultsTimelinePanel` | 320 | 280 | 40 px |
|
|
27
|
-
> | `GroupMetricsPanel` | 300 | **none** | the whole chart is unsized |
|
|
28
|
-
> | Cost, Ratio, Accessibility, Referral, Total | equal | equal | 0 |
|
|
29
|
-
>
|
|
30
|
-
> **The equal-value majority is why this survived.** Passing both looks like harmless
|
|
31
|
-
> belt-and-braces and costs nothing when the numbers match, so the pattern spread by copy-paste and
|
|
32
|
-
> nobody noticed the cases where they diverge. It has been diagnosed and fixed **pointwise twice**
|
|
33
|
-
> in hram (`AllocationPerformancePanel.jsx:462-478`, `OptimizationResultsPanel.jsx:928-940`, both to
|
|
34
|
-
> `height={420}`) — with the explanation written as a comment **inside those two files**, where no
|
|
35
|
-
> new panel will ever read it.
|
|
36
|
-
>
|
|
37
|
-
> This is not N panel bugs. It is one shared API that permits an incoherent pair, and it will keep
|
|
38
|
-
> recurring for as long as it does. Fixing it here fixes every consumer at once, including the ones
|
|
39
|
-
> nobody sweeps.
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Part A — Envelope (authoritative WHAT/WHY)
|
|
44
|
-
|
|
45
|
-
### Goal
|
|
46
|
-
|
|
47
|
-
A caller can no longer produce dead space by passing `minHeight`. The presets resolve the pair
|
|
48
|
-
themselves, and the incoherent combination becomes impossible rather than merely discouraged.
|
|
49
|
-
|
|
50
|
-
### Definition of Done
|
|
51
|
-
|
|
52
|
-
- [ ] **The resolution is three-way, not two-way — `aspect` is the third input and it changes the
|
|
53
|
-
answer.** Amended 2026-08-21; the original two-way rule would have broken four live call sites.
|
|
54
|
-
- **`height` present** → it sizes the chart, and the wrapper reserves no more than that.
|
|
55
|
-
- **No `height`, no `aspect`** → **`minHeight` sizes the chart**, not merely the wrapper.
|
|
56
|
-
This is what a caller in that shape meant (`GroupMetricsPanel`: `minHeight={300}`, no
|
|
57
|
-
`height`, no `aspect` — chart unsized today).
|
|
58
|
-
- **No `height`, but `aspect` present** → **today's behaviour is correct and must not change.**
|
|
59
|
-
The wrapper is `width: 100%` with `aspectRatio`, so its height derives from its width, and
|
|
60
|
-
`minHeight` is the floor that stops it collapsing on a narrow viewport. Here `minHeight`
|
|
61
|
-
means exactly what its name says.
|
|
62
|
-
|
|
63
|
-
**Same prop shape, opposite intent** — which is why the rule cannot be stated on
|
|
64
|
-
`minHeight`/`height` alone.
|
|
65
|
-
- [ ] **`minHeight > height` produces no wrapper padding.** The chart is sized by `height` and the
|
|
66
|
-
wrapper does not reserve more than the chart occupies. The extra space was never intentional.
|
|
67
|
-
- [ ] **Equal values behave exactly as today** — that is the majority of call sites and they must
|
|
68
|
-
not shift by a pixel.
|
|
69
|
-
- [ ] **A dev-mode warning names the offending call site** when both are passed and they disagree.
|
|
70
|
-
Not a throw: a shared package that throws on a prop combination in production breaks a
|
|
71
|
-
consumer's page over a layout nit.
|
|
72
|
-
- [ ] **JSDoc on every preset that takes it** states in one line what `minHeight` now does, so the
|
|
73
|
-
next caller does not have to infer it from a comment in a consumer app.
|
|
74
|
-
|
|
75
|
-
### Deliberately NOT done
|
|
76
|
-
|
|
77
|
-
- **`minHeight` is not removed from the API.** Removing it is a breaking change to a shared package,
|
|
78
|
-
which would make every consumer's pin bump a Tier-3 change with a real chance of unnoticed layout
|
|
79
|
-
regressions — a worse outcome than the defect. Deprecate in the docstring, coerce in the code.
|
|
80
|
-
- No change to chart internals, palettes, axis defaults or `aspect`.
|
|
81
|
-
- No consumer-side sweep in this WO. hram's call-site cleanup is its own follow-up, gated on the pin
|
|
82
|
-
bump — see below.
|
|
83
|
-
|
|
84
|
-
### Preconditions and ordering
|
|
85
|
-
|
|
86
|
-
The fix only reaches hram after **(a)** this lands and publishes and **(b)** hram bumps its
|
|
87
|
-
`@micha.bigler/ui-core-micha` pin. Verify the published version is actually live before the consumer
|
|
88
|
-
bump — this package publishes from `main` with no staging step, so a failed publish is silent until
|
|
89
|
-
a consumer installs it.
|
|
90
|
-
|
|
91
|
-
### Risks
|
|
92
|
-
|
|
93
|
-
- **The consumer check is done, and it found something — 2026-08-21.** It was written here as a
|
|
94
|
-
hypothetical ("a consumer may be relying on the padding as spacing"); the real finding is
|
|
95
|
-
different and larger. **Four live call sites pass `aspect` together with `minHeight` and no
|
|
96
|
-
`height`:**
|
|
97
|
-
|
|
98
|
-
| call site | props |
|
|
99
|
-
|---|---|
|
|
100
|
-
| `hram/AccessGapScatterPanel.jsx:182` | `aspect={1.8}` + `minHeight={320}` |
|
|
101
|
-
| `fitness-monitor/BodyHistoryPage.jsx:~328` | `aspect="960 / 380"` + `minHeight={320}` |
|
|
102
|
-
| `fitness-monitor/BodyHistoryPage.jsx:~355` | `aspect="960 / 380"` + `minHeight={320}` |
|
|
103
|
-
| `fitness-monitor/BodyHistoryPage.jsx:~450` | `aspect="400 / 220"` + `minHeight={220}` |
|
|
104
|
-
|
|
105
|
-
These are not relying on padding-as-spacing. They are using `minHeight` **as a floor under an
|
|
106
|
-
aspect-derived height**, which is legitimate and is what the name promises. The original
|
|
107
|
-
Definition of Done would have turned all four into fixed-height charts and removed their
|
|
108
|
-
responsive behaviour. **That is the reason for the three-way rule above**, and it is the case to
|
|
109
|
-
hold onto when reading the rest of this order.
|
|
110
|
-
|
|
111
|
-
Scope note: `survey-renderer` is named above as a consumer to check. **The standalone repo is
|
|
112
|
-
retired** (2026-07-31); the widget now lives at `survey_app/frontend/packages/survey-renderer`,
|
|
113
|
-
and neither it nor `cockpit` or `jg-ferien` passes `aspect` to a chart preset. jg's one `aspect=`
|
|
114
|
-
hit is an `ImageCropDialog`, unrelated.
|
|
115
|
-
- The dev warning must not fire on the equal-value majority, or it becomes noise that trains people
|
|
116
|
-
to ignore it.
|
|
117
|
-
|
|
118
|
-
### Tests to WRITE — narrow
|
|
119
|
-
|
|
120
|
-
- `minHeight` alone, **no `aspect`** → the chart receives that height.
|
|
121
|
-
- **`minHeight` + `aspect`, no `height` → unchanged from today**: the wrapper keeps its
|
|
122
|
-
`aspectRatio` and `minHeight` stays a floor, and the chart is **not** given a fixed height. This is
|
|
123
|
-
the four-call-site case in Risks and the one a two-way rule would have broken — **it is the test
|
|
124
|
-
that has to fail if someone later re-simplifies the resolution.**
|
|
125
|
-
- `minHeight > height` → the chart receives `height` and the wrapper reserves no more than that.
|
|
126
|
-
- `minHeight === height` → byte-identical to the current output.
|
|
127
|
-
- `height` alone → unchanged.
|
|
128
|
-
- The dev warning fires only on the disagreeing pair, and names the values. It must **not** fire on
|
|
129
|
-
`minHeight` + `aspect` without `height`, which is a legitimate combination.
|
|
130
|
-
|
|
131
|
-
No full suite.
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## Part B — Implementation map
|
|
136
|
-
|
|
137
|
-
> **TO BE FILLED BY THE ORCHESTRATOR** on `git pull`. Must carry the preset files with `path:line`
|
|
138
|
-
> anchors (`ScatterChart.jsx:173-174, :260` and the equivalents), the absolute working directory,
|
|
139
|
-
> the progress contract, and the preamble. **Do not dispatch while this placeholder stands.**
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## Part C — Orchestrator-only
|
|
144
|
-
|
|
145
|
-
> **TO BE FILLED BY THE ORCHESTRATOR.** Review routing (`reviewer` + `ui_reviewer`, full context —
|
|
146
|
-
> Tier 3 shared-core), verification, register maintenance, commit, publish check, and the execution
|
|
147
|
-
> directive with its self-address guard.
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
# UCM-CHART-9 — `ChartFrame` is a card, not a chart: it must never take a fixed height
|
|
2
|
-
|
|
3
|
-
- **Repo:** `ui-core-micha`, branch `main` (shared-core; publishes from `main`, no staging step)
|
|
4
|
-
- **Tier:** 3 — shared-core, and this is a **live layout regression in a published version**.
|
|
5
|
-
- **Status:** planned
|
|
6
|
-
- **Workstream:** `CHART-*`
|
|
7
|
-
- **Files:** `src/components/charts/ChartFrame.jsx` and its tests. `chartDefaults.js` only if the
|
|
8
|
-
resolver needs a second shape — see below; the preset behaviour is correct and must not change.
|
|
9
|
-
|
|
10
|
-
> **Why — regression, observed on staging after hram bumped to 2.42.0.** `UCM-CHART-8` wired
|
|
11
|
-
> `resolveChartHeight()` through the four chart presets **and through `ChartFrame`**. For the
|
|
12
|
-
> presets that is right. For `ChartFrame` it is not, and the difference is what the box contains.
|
|
13
|
-
>
|
|
14
|
-
> In the `minHeight` alone / no `height` / no `aspect` branch, `resolveChartHeight` returns
|
|
15
|
-
> `chartHeight = minHeight`, and `ChartFrame` now applies it:
|
|
16
|
-
>
|
|
17
|
-
> ```diff
|
|
18
|
-
> - minHeight,
|
|
19
|
-
> + minHeight: wrapperMinHeight,
|
|
20
|
-
> + height: chartHeight,
|
|
21
|
-
> ```
|
|
22
|
-
>
|
|
23
|
-
> **A chart preset's box contains exactly one chart. `ChartFrame`'s box contains a whole card** —
|
|
24
|
-
> title, toolbar, the chart, a legend, footnotes, export links. Turning its `minHeight` floor into a
|
|
25
|
-
> fixed `height` makes the box shorter than its content, the content overflows, and **adjacent cards
|
|
26
|
-
> visibly overlap**: the operator's screenshot shows a card title rendered over the chart of the card
|
|
27
|
-
> above it and three sets of "Export SVG / Export PNG" stacked at different offsets.
|
|
28
|
-
>
|
|
29
|
-
> `UCM-CHART-8`'s own Files note recorded that `ChartFrame` "never destructures `height`" — and the
|
|
30
|
-
> implementation then gave it one. The rule was written for presets and applied to a frame.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Part A — Envelope (authoritative WHAT/WHY)
|
|
35
|
-
|
|
36
|
-
### Goal
|
|
37
|
-
|
|
38
|
-
`ChartFrame` stops setting a fixed `height` on its content box. Its `minHeight` goes back to meaning
|
|
39
|
-
what its name says — a floor that content can exceed. The four chart presets keep `UCM-CHART-8`'s
|
|
40
|
-
three-way resolution unchanged.
|
|
41
|
-
|
|
42
|
-
### Definition of Done
|
|
43
|
-
|
|
44
|
-
- [ ] **`ChartFrame` never applies `chartHeight` to its content box.** Its box takes `minHeight` as a
|
|
45
|
-
floor, as it did before 2.42.0. Whether that is done by not calling `resolveChartHeight` at
|
|
46
|
-
all, or by giving the resolver an explicit frame shape, is the implementer's call — but
|
|
47
|
-
`ChartFrame` must not end up with a fixed `height` in any branch.
|
|
48
|
-
- [ ] **A `ChartFrame` whose content exceeds `minHeight` grows.** This is the regression, stated as
|
|
49
|
-
the acceptance criterion: content taller than the floor must extend the box, never overflow it.
|
|
50
|
-
- [ ] **The four presets are untouched.** `ScatterChart`, `BarChart`, `LineChart`, `TimeSeriesChart`
|
|
51
|
-
keep `UCM-CHART-8` exactly as it landed — including the `aspect` branch that four live call
|
|
52
|
-
sites depend on. This WO narrows one consumer of the resolver; it does not revisit the rule.
|
|
53
|
-
- [ ] **`ChartFrame`'s JSDoc is corrected.** 2.42.0 added a paragraph claiming `minHeight`
|
|
54
|
-
"sizes the content box itself" when there is no `height`/`aspect`. That sentence is the bug in
|
|
55
|
-
prose form and must go.
|
|
56
|
-
- [ ] **`warnOnHeightMismatch` stays** on `ChartFrame` — a caller passing both is still worth a
|
|
57
|
-
dev-mode note, even though the frame no longer acts on `height`.
|
|
58
|
-
|
|
59
|
-
### Non-goals
|
|
60
|
-
|
|
61
|
-
- Do **not** revert `UCM-CHART-8`. Its preset behaviour is correct and is the fix hram needs; only
|
|
62
|
-
the frame's participation was wrong.
|
|
63
|
-
- Do not change `resolveChartHeight`'s three-way rule for presets.
|
|
64
|
-
- No consumer-side change in this WO.
|
|
65
|
-
|
|
66
|
-
### Risks
|
|
67
|
-
|
|
68
|
-
- **`ChartFrame` is used by every Research card in hram and by other consumers.** The change restores
|
|
69
|
-
pre-2.42.0 behaviour for it, so the risk is low in direction — but it is still a shared-core
|
|
70
|
-
publish, and the rendered check below is what proves it.
|
|
71
|
-
- 2.42.0 is `latest` on the registry and carries this regression. Publish 2.42.1 promptly; note in
|
|
72
|
-
the register that 2.42.0 should not be adopted by a new consumer.
|
|
73
|
-
- **hram's Detailed Results tab is fixed as of 2.42.0** (operator-confirmed, 2026-08-21) — it
|
|
74
|
-
crashed with React #185 before the bump (`HRAM-RES-29` item 1) and does not any more. What is
|
|
75
|
-
**not** established is *why*: the plausible mechanism is that deterministic sizing removed a
|
|
76
|
-
resize-driven `setState` loop, but nobody has traced it.
|
|
77
|
-
**Consequence for this WO, and the only reason it is mentioned here:** since we do not know what
|
|
78
|
-
fixed it, we cannot know whether moving `ChartFrame` back toward a floor disturbs it. Re-check the
|
|
79
|
-
tab after this lands. If the crash returns, that is a finding for `HRAM-RES-29` and a sizing
|
|
80
|
-
dependency worth understanding — not a reason to undo this fix.
|
|
81
|
-
|
|
82
|
-
### Tests to WRITE — narrow
|
|
83
|
-
|
|
84
|
-
- **The regression test:** a `ChartFrame` with `minHeight` and no `height`/`aspect`, containing
|
|
85
|
-
content taller than `minHeight`, does **not** receive a fixed `height` on its content box.
|
|
86
|
-
- `ChartFrame` with `height` explicitly passed: `height` is still not applied as a fixed box height
|
|
87
|
-
(the frame is not a chart), and no exception is thrown.
|
|
88
|
-
- The four presets' existing `UCM-CHART-8` tests stay green **unchanged** — if one of them has to be
|
|
89
|
-
edited, the change has leaked out of `ChartFrame` and that is a stop-and-report.
|
|
90
|
-
|
|
91
|
-
**Rendered check before the hram pin bump — mandatory, and the reason this WO exists.** The unit
|
|
92
|
-
tests for 2.42.0 were 188 green and said nothing about layout, because they cannot. Before hram's pin
|
|
93
|
-
moves again, the affected cards are checked rendered at 375 px and 1280 px: Sensitivity, Access,
|
|
94
|
-
Access Ladder, Allocation, Optimization. Named in the register note, with the substitution declared
|
|
95
|
-
if capture is unavailable.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Part B — Implementation map — ADDRESSED TO THE IMPLEMENTER
|
|
100
|
-
|
|
101
|
-
### Context package
|
|
102
|
-
|
|
103
|
-
**Named files to change:**
|
|
104
|
-
- `src/components/charts/ChartFrame.jsx` — the fix (below).
|
|
105
|
-
- `tests/ChartFrame.test.jsx:215-256` — the `describe('minHeight/height resolution (CHART-8)', …)`
|
|
106
|
-
block. It currently **asserts the bug as correct behaviour** (e.g. `minHeight` alone →
|
|
107
|
-
`style.height` toBe `'300px'`). Rewrite it to assert the fixed behaviour; rename the block to
|
|
108
|
-
`(CHART-9)`.
|
|
109
|
-
|
|
110
|
-
**Do NOT touch (verified against the landed code):**
|
|
111
|
-
- `src/components/charts/chartDefaults.js` — `resolveChartHeight` (lines ~289-298) and
|
|
112
|
-
`warnOnHeightMismatch` (lines ~306-315) keep their exact current contract. If the fix seems to need
|
|
113
|
-
a change here, that means the change has leaked out of `ChartFrame` — stop and report, don't edit.
|
|
114
|
-
- `src/components/charts/{BarChart,LineChart,ScatterChart,TimeSeriesChart}.jsx` — all four still call
|
|
115
|
-
`resolveChartHeight({ minHeight, height, aspect })` for their OWN box, unchanged.
|
|
116
|
-
- `tests/chartDefaults.test.js:441+` (`describe('resolveChartHeight (CHART-8)', …)`) and the four
|
|
117
|
-
presets' own test files — must stay green **unchanged**. If one needs an edit, stop and report.
|
|
118
|
-
|
|
119
|
-
**The bug, exactly:** `ChartFrame.jsx:61-62` calls `resolveChartHeight({ minHeight, height, aspect })`
|
|
120
|
-
and applies the result to its content box at `:109-125`:
|
|
121
|
-
```jsx
|
|
122
|
-
sx={{
|
|
123
|
-
width: '100%',
|
|
124
|
-
minHeight: wrapperMinHeight,
|
|
125
|
-
height: chartHeight,
|
|
126
|
-
aspectRatio: aspect,
|
|
127
|
-
...
|
|
128
|
-
}}
|
|
129
|
-
```
|
|
130
|
-
In the "no `height`, no `aspect`" branch, `resolveChartHeight` returns `chartHeight = minHeight` —
|
|
131
|
-
correct for a preset's box (which holds exactly one chart) but wrong for `ChartFrame`'s box (which
|
|
132
|
-
holds a whole card: title, toolbar, chart, legend, footnotes, export links). A fixed `height` there
|
|
133
|
-
makes the box shorter than its content, and the content overflows into the next card.
|
|
134
|
-
|
|
135
|
-
**What "restore pre-2.42.0 behaviour" means concretely** — before `UCM-CHART-8` (commit `11d362c`),
|
|
136
|
-
`ChartFrame` had no `height` prop at all and its content box was:
|
|
137
|
-
```jsx
|
|
138
|
-
sx={{
|
|
139
|
-
width: '100%',
|
|
140
|
-
minHeight,
|
|
141
|
-
aspectRatio: aspect,
|
|
142
|
-
display: 'flex',
|
|
143
|
-
alignItems: 'center',
|
|
144
|
-
justifyContent: 'center',
|
|
145
|
-
}}
|
|
146
|
-
```
|
|
147
|
-
i.e. `minHeight` applied raw, straight from props, never touched by any resolver; no `height` was
|
|
148
|
-
ever set on the box.
|
|
149
|
-
|
|
150
|
-
**The fix:** `ChartFrame`'s content box must end up equivalent to that — `minHeight` (raw, from
|
|
151
|
-
props) as the box's only height-related sx property besides `aspectRatio`, and nothing ever sets
|
|
152
|
-
`height` on the box. The `height` prop stays in `ChartFrame`'s signature (do not remove it — it is
|
|
153
|
-
still a documented prop and `warnOnHeightMismatch('ChartFrame', { minHeight, height })` at line 61
|
|
154
|
-
must keep firing on a caller passing both `minHeight` and a disagreeing `height`), it is simply no
|
|
155
|
-
longer used to size the box. Whether you implement this by dropping the `resolveChartHeight` call
|
|
156
|
-
from `ChartFrame` entirely (simplest — matches the pre-2.42.0 shape exactly) or by giving the
|
|
157
|
-
resolver a second, frame-specific shape in `chartDefaults.js` that never returns a `chartHeight` is
|
|
158
|
-
your call — but per the non-goals below, the existing `resolveChartHeight` export and its three-way
|
|
159
|
-
preset contract must not change.
|
|
160
|
-
|
|
161
|
-
**JSDoc fix:** `ChartFrame.jsx:19-26`'s docblock currently states: *"otherwise (no `height`, no
|
|
162
|
-
`aspect`) it sizes the content box itself. Once `height` is set, `height` sizes the box…"* — that
|
|
163
|
-
sentence describes the bug as intended behaviour and must be corrected to state that `minHeight` is
|
|
164
|
-
always a floor on `ChartFrame`'s box and `height` is never applied to it (only used for the
|
|
165
|
-
dev-mode mismatch warning).
|
|
166
|
-
|
|
167
|
-
**Regression check while you're in there:** hram's Detailed Results tab crashed with React #185
|
|
168
|
-
before the 2.42.0 bump and stopped crashing after it (`HRAM-RES-29` item 1, unconfirmed hypothesis:
|
|
169
|
-
deterministic sizing removed a resize-driven `setState` loop). This fix moves `ChartFrame` back
|
|
170
|
-
toward non-deterministic sizing for that one prop. You are not expected to reproduce or verify the
|
|
171
|
-
hram-side crash — the Orchestrator does that separately after your diff lands — but do not add any
|
|
172
|
-
new resize-driven effect to `ChartFrame` while touching this code.
|
|
173
|
-
|
|
174
|
-
Work from this package; do not explore broadly from scratch — open only the named files to verify.
|
|
175
|
-
If you must dig deeper, delegate to a read-only Explore sub-agent (Haiku).
|
|
176
|
-
|
|
177
|
-
### Target repo working directory (absolute)
|
|
178
|
-
|
|
179
|
-
`C:\Users\Micha Bigler\Documents\webapps\ui-core-micha`
|
|
180
|
-
|
|
181
|
-
### Preamble — binding, read before doing anything else
|
|
182
|
-
|
|
183
|
-
The text in this file is the COMPLETE spec — the committed WO content, not a plan to refine; there
|
|
184
|
-
is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`,
|
|
185
|
-
and this repo's own `MEMORY.md` ONLY for conventions. Stay in scope; do not touch
|
|
186
|
-
auth/permissions/deps/schema/CI unless this spec says so; do not update `MEMORY.md`. **Do NOT edit
|
|
187
|
-
`WORK_ORDERS.md`** — the register row and the review verdicts are the orchestrator's alone. Do NOT
|
|
188
|
-
`git add`/`commit`/`push` — leave every change uncommitted in the working tree for the orchestrator's
|
|
189
|
-
independent review. WRITE the tests the "Required tests to WRITE" section (Part A) calls for AND
|
|
190
|
-
**RUN the tests you just wrote** to confirm they execute and pass — that is the ONLY test run you do
|
|
191
|
-
(NOT the app's affected/full suite, NOT any review). The orchestrator re-runs the authoritative set
|
|
192
|
-
and does the independent review after you finish — those are the gate; your own run does not count
|
|
193
|
-
as the gate.
|
|
194
|
-
|
|
195
|
-
Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
|
|
196
|
-
`PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
|
|
197
|
-
completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
|
|
198
|
-
`RESULT: DONE|BLOCKED <reason>`.
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
## Part C — Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
|
|
203
|
-
|
|
204
|
-
> **If you are the implementer reading this work order as your own specification: STOP at this
|
|
205
|
-
> line.** Everything below describes what the Orchestrator does AFTER you finish. You do none of it
|
|
206
|
-
> — no reviewers, no verification run, no register edit, no commit. You ARE the invocation described
|
|
207
|
-
> below; do NOT shell out to `codex exec`.
|
|
208
|
-
|
|
209
|
-
### Execution directive
|
|
210
|
-
|
|
211
|
-
Implement through `codex exec` in the background — invoked directly via Bash (never the
|
|
212
|
-
`debugger`/`*_coder` Agent wrappers) with BOTH flags `--skip-git-repo-check` and
|
|
213
|
-
`--dangerously-bypass-approvals-and-sandbox`, `cwd` = the working directory above (never
|
|
214
|
-
`…\webapps`). Fallback to direct Claude implementation only on Codex quota/rate-limit/non-zero exit —
|
|
215
|
-
check `.claude/codex-status.md` first per its own rule (no line for 2026-08-22 → use Codex). The
|
|
216
|
-
fallback flips authorship, making an independent `reviewer` mandatory even if it already was.
|
|
217
|
-
|
|
218
|
-
### Review routing (Tier 3, shared-core)
|
|
219
|
-
|
|
220
|
-
- `reviewer`: **yes**, full context, Sonnet-pinned, background.
|
|
221
|
-
- `ui_reviewer`: **yes** (diff touches frontend), full context, background, same batch as `reviewer`.
|
|
222
|
-
- `sec_reviewer`: not required — no auth/security surface in this diff.
|
|
223
|
-
- Both run concurrently; neither is skippable; commit waits for both clean.
|
|
224
|
-
|
|
225
|
-
### Verification (the authoritative run — Codex's own run is not the gate)
|
|
226
|
-
|
|
227
|
-
1. **Test gate:** `npx vitest run tests/ChartFrame.test.jsx tests/chartDefaults.test.js
|
|
228
|
-
tests/BarChart.test.jsx tests/LineChart.test.jsx tests/ScatterChart.test.jsx
|
|
229
|
-
tests/TimeSeriesChart.test.jsx` (adjust filenames to whatever actually exists — the affected-area
|
|
230
|
-
set per AGENTS.md "Test scope": `ChartFrame` itself plus every consumer of `resolveChartHeight`).
|
|
231
|
-
All must pass; the four presets' pre-existing assertions must be **byte-identical**, not just
|
|
232
|
-
green — a changed preset assertion means the fix leaked scope.
|
|
233
|
-
2. **Rendered check — this WO's own commit gate, scoped to what this repo can render.** This repo
|
|
234
|
-
has no prototype artifact, so the generic prototype side-by-side gate does not apply; this WO's
|
|
235
|
-
own Envelope names a rendered check instead, and it is honoured here at the scope this repo can
|
|
236
|
-
actually reach:
|
|
237
|
-
- Run `npm run dev` (Vite) and open the dev harness at 375 px and 1280 px. It already contains
|
|
238
|
-
`ChartFrame` "shape check" stories that mirror three of the five named hram cards — "Allocation
|
|
239
|
-
performance", "Access gap", "Optimization results" (`dev/entries.jsx`, search `shape check`).
|
|
240
|
-
Confirm none of them, nor any neighbouring card, show overlapping title/content/export rows at
|
|
241
|
-
either width.
|
|
242
|
-
- Additionally render (ad hoc, in the same dev session — e.g. a temporary story or by editing an
|
|
243
|
-
existing one's children) a `ChartFrame` with a `minHeight` smaller than its actual content, to
|
|
244
|
-
directly exercise the Definition of Done's acceptance criterion: the box must grow to fit the
|
|
245
|
-
content, not overflow it. Revert any temporary dev-harness edit before commit (or keep it only
|
|
246
|
-
if it's a genuine permanent addition worth keeping — your call, but say which in the Notiz).
|
|
247
|
-
- This repo's harness has no "Sensitivity" or "Access Ladder" story, so the **full five-card
|
|
248
|
-
rendered check the Envelope describes ("before hram's pin moves again") is NOT done by this WO**
|
|
249
|
-
— it cannot be, without linking a built `ui-core-micha` into a running hram dev server. Declare
|
|
250
|
-
this explicitly in the register Notiz as a carried-forward precondition on whichever WO next
|
|
251
|
-
bumps hram's pin past 2.42.0, not a silently dropped gate.
|
|
252
|
-
- Declare screenshots-vs-DOM-inspection substitution explicitly if real screenshots aren't taken.
|
|
253
|
-
|
|
254
|
-
### Register + commit
|
|
255
|
-
|
|
256
|
-
- `WORK_ORDERS.md` row → `done`, with: the named review verdicts (`reviewer` + `ui_reviewer`, no
|
|
257
|
-
open findings — or the findings and their resolution), the test gate result, the rendered-check
|
|
258
|
-
scope actually achieved (dev harness only, full hram five-card check carried forward), and which
|
|
259
|
-
evidence from `.claude/codex-status.md` was used (or that no fallback was needed).
|
|
260
|
-
- Note in the Notiz: **publish 2.42.1 promptly after commit** (per Part A Risks — 2.42.0 is `latest`
|
|
261
|
-
on the registry and carries this regression) and confirm the version bump lands in the same commit
|
|
262
|
-
or a clearly-linked follow-up; the register row must name whichever it was.
|
|
263
|
-
- Commit message: single concise English subject line (e.g. `fix(ChartFrame): stop applying a fixed
|
|
264
|
-
height to the card box (CHART-9)`). Push to `main` (this repo publishes from `main`, no `develop`
|
|
265
|
-
step) once review + tests are clean.
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# UCM-CHAT-1 — Shared AI chat surface: chat list, streaming thread, sources, model and effort picker
|
|
2
|
-
|
|
3
|
-
Prepared: 2026-10-15. Target repository: `ui-core-micha` (`main`). Backend counterpart and transport contract: `django-core-micha/DCM-CHAT-1`. First consumer: `cockpit/CP-CHAT-4`.
|
|
4
|
-
|
|
5
|
-
# A. Envelope — addressed to everyone
|
|
6
|
-
|
|
7
|
-
## Goal and expected outcome
|
|
8
|
-
|
|
9
|
-
`django-core-micha/DCM-CHAT-1` adds a shared AI chat core with a fixed WebSocket and REST contract. This order adds the matching surface to ui-core-micha, so that an app shows a complete chat by mounting one component. maana's chat UI (`maana/frontend/src/qda/assistant/`) is the functional template, without its proposals, grants and plan views.
|
|
10
|
-
|
|
11
|
-
Expected outcome: ui-core-micha exports a chat workspace that lists the user's chats (with archive), streams answers into a thread, renders Markdown safely, shows the sources each answer used, and lets the user pick model and effort per chat. The parts are also exported individually so that an app can arrange them differently.
|
|
12
|
-
|
|
13
|
-
## Visual spec
|
|
14
|
-
|
|
15
|
-
Prototype: [`work-orders/assets/UCM-CHAT-1-ai-chat.html`](assets/UCM-CHAT-1-ai-chat.html), drawn in cockpit's theme as the first consumer. It shows:
|
|
16
|
-
- at 1280 px, the main working state;
|
|
17
|
-
- at 375 px, the thread, the chat list drawer and the model picker sheet;
|
|
18
|
-
- a 1280 px gallery of the edge states.
|
|
19
|
-
|
|
20
|
-
The prototype declares its coverage at the top. The built components take every colour, type and radius from the consuming app's MUI theme, never from literals.
|
|
21
|
-
|
|
22
|
-
**Parity guardrail:** the prototype governs the look and the interaction only. Behaviour, permissions and the data contract come from `DCM-CHAT-1` and are not changed by anything drawn here.
|
|
23
|
-
|
|
24
|
-
## Operator decisions this Envelope records (2026-10-15)
|
|
25
|
-
|
|
26
|
-
- Several persistent chats per user, in a list. Each chat can be renamed, archived and deleted. Archived chats sit behind an "Archived" entry with a count, open read-only, and can be restored.
|
|
27
|
-
- Model and effort are chosen per chat, from the app's catalogue. The picker groups the entries by driver and marks pay-per-use entries. A change applies from the next turn, and the thread marks where the model changed.
|
|
28
|
-
- The sources of each answer appear as chips under it. A chip shows the source's short label, and the full reference appears on hover.
|
|
29
|
-
- A prototype was requested and is the visual spec.
|
|
30
|
-
|
|
31
|
-
## Scope
|
|
32
|
-
|
|
33
|
-
- **Workspace component.** At wide widths it has a list column and a thread column. At narrow widths the list becomes a drawer and the picker a bottom sheet; the prototype shows the 375 px arrangement.
|
|
34
|
-
- **Chat list:**
|
|
35
|
-
- new chat;
|
|
36
|
-
- select a chat;
|
|
37
|
-
- per-row overflow menu with Rename, Archive and Delete;
|
|
38
|
-
- Delete asks for confirmation inside the UI;
|
|
39
|
-
- the archived section with its count;
|
|
40
|
-
- restore an archived chat.
|
|
41
|
-
- **Thread:**
|
|
42
|
-
- user messages;
|
|
43
|
-
- assistant answers rendered as Markdown, streamed live from `delta` frames;
|
|
44
|
-
- a typing indicator before the first delta;
|
|
45
|
-
- a tool-activity chip while a tool runs, labelled with the tool's own label from the `tool` frame;
|
|
46
|
-
- source chips once the turn completes;
|
|
47
|
-
- a quiet model and effort line under each answer;
|
|
48
|
-
- a divider where the model changed between turns;
|
|
49
|
-
- older turns loaded by cursor when scrolling up.
|
|
50
|
-
- **Composer:** a multi-line input and Send. Stop appears next to Send while a turn runs. Send stays disabled while a turn runs, while the chat is archived, and while the connection is down.
|
|
51
|
-
- **Model and effort picker:** a popover at wide widths and a bottom sheet at narrow widths.
|
|
52
|
-
- Entries come from the catalogue endpoint, grouped by driver, with the billing tag on pay-per-use entries.
|
|
53
|
-
- Effort is a segmented control with the four normalised levels. Levels the selected entry does not allow are disabled.
|
|
54
|
-
- The current selection shows in the thread bar as "model · effort".
|
|
55
|
-
- **Edge states, as drawn:**
|
|
56
|
-
- a new chat with no messages;
|
|
57
|
-
- the usage limit reached, with "Change model";
|
|
58
|
-
- an interrupted answer with an "Interrupted" chip and Retry;
|
|
59
|
-
- connection lost, with a "Reconnecting" chip;
|
|
60
|
-
- no model configured on this server;
|
|
61
|
-
- an archived chat opened.
|
|
62
|
-
- **Socket hook:** one WebSocket per open chat, reconnecting with backoff and no automatic resend. It parses the frames listed in `DCM-CHAT-1`, and on close codes 4401, 4403 and 4429 it stops reconnecting and surfaces the matching state.
|
|
63
|
-
- **API client:** a default implementation of every REST call in `DCM-CHAT-1`. The default set is exported, and a consumer can override single functions while the others keep their defaults.
|
|
64
|
-
- This avoids the `MessagingProvider` limitation described in `webapp-management/SHARED_CAPABILITIES.md`: there, passing any `api` prop replaces the whole default set.
|
|
65
|
-
- **Markdown rendering** uses `react-markdown` with `remark-gfm`, configured like maana's `MarkdownReply.jsx`: no raw HTML, no images, and links rendered as text. Both packages are new dependencies of this repository. They are approved with this order.
|
|
66
|
-
- **Strings:** all strings are registered through ui-core-micha's i18n contract in a new translations module, in German, English, French and Swahili like the existing modules.
|
|
67
|
-
- **Documentation:** a row in `webapp-management/SHARED_CAPABILITIES.md` for the chat surface, as a small companion change in that repository.
|
|
68
|
-
|
|
69
|
-
## Copy list (released with this Envelope)
|
|
70
|
-
|
|
71
|
-
Hint and state texts beyond control labels, verbatim from the prototype:
|
|
72
|
-
- "Usage limit reached for {model}. Choose another model or try again later."
|
|
73
|
-
- "The answer could not be completed."
|
|
74
|
-
- "Chat is not available"
|
|
75
|
-
- "No language model is configured on this server."
|
|
76
|
-
- "pay per use" (catalogue billing tag)
|
|
77
|
-
- Chips: "Interrupted", "Reconnecting", "Archived".
|
|
78
|
-
|
|
79
|
-
The tool-activity text, for example "Searching the knowledge base", is not ui-core-micha copy. It is the label each app gives its tool.
|
|
80
|
-
|
|
81
|
-
## Token delta list
|
|
82
|
-
|
|
83
|
-
None. Drawn from the theme.
|
|
84
|
-
|
|
85
|
-
## Replaces / removes
|
|
86
|
-
|
|
87
|
-
Nothing. This is a new surface. The existing `messaging` components stay unchanged.
|
|
88
|
-
|
|
89
|
-
## Non-goals
|
|
90
|
-
|
|
91
|
-
- Proposals, plans, grants, context inspection, or anything else from maana's domain UI.
|
|
92
|
-
- Credential entry for own logins or API keys (stage 4, `django-core-micha/DCM-CHAT-3`).
|
|
93
|
-
- Search across chats, sharing, attachments, voice input.
|
|
94
|
-
- Mounting the surface in any app. cockpit does that in `CP-CHAT-4`.
|
|
95
|
-
- Changes to `messaging/`, `notifications/` or the theme factory.
|
|
96
|
-
|
|
97
|
-
## Tier
|
|
98
|
-
|
|
99
|
-
Tier 3: a new shared-core surface with new dependencies.
|
|
100
|
-
|
|
101
|
-
## Risks
|
|
102
|
-
|
|
103
|
-
- **Markdown as an injection path:** answers can echo text from retrieved documents. The renderer must never interpret raw HTML or load images or links automatically. The allow-list configuration above is the control.
|
|
104
|
-
- **Contract drift:** the component is built against the transport contract of `DCM-CHAT-1` before that module is published. Any deviation found later is a change to that contract, not a local adaptation here.
|
|
105
|
-
- **Theme coupling:** literal colours copied from the prototype would make the component look like cockpit in every app. Colours must come from the theme.
|
|
106
|
-
|
|
107
|
-
## Required tests to write
|
|
108
|
-
|
|
109
|
-
- Socket hook:
|
|
110
|
-
- deltas append to the streaming answer;
|
|
111
|
-
- the `turn` frame replaces it with the final text and sources;
|
|
112
|
-
- reconnect without resending;
|
|
113
|
-
- 4401, 4403 and 4429 stop reconnecting and show their state.
|
|
114
|
-
- Thread:
|
|
115
|
-
- Markdown renders a list and a table;
|
|
116
|
-
- raw HTML in an answer is shown as text and not executed;
|
|
117
|
-
- an image reference is not loaded;
|
|
118
|
-
- source chips show the label, with the reference on hover;
|
|
119
|
-
- the model-change divider appears between turns with different selections.
|
|
120
|
-
- Picker:
|
|
121
|
-
- entries are grouped by driver;
|
|
122
|
-
- a pay-per-use entry shows its tag;
|
|
123
|
-
- effort levels the entry does not allow are disabled;
|
|
124
|
-
- a change calls the update-selection endpoint.
|
|
125
|
-
- Chat list:
|
|
126
|
-
- rename, archive, restore and delete call their endpoints;
|
|
127
|
-
- delete asks for confirmation first;
|
|
128
|
-
- an archived chat disables Send.
|
|
129
|
-
- Edge states: the usage-limit, interrupted and not-configured states render from their error codes.
|
|
130
|
-
- API client: overriding one function keeps the defaults for all others.
|
|
131
|
-
- Translations: every key of the new module exists in all four languages.
|
|
132
|
-
|
|
133
|
-
# B. Implementation map — addressed to the implementer
|
|
134
|
-
|
|
135
|
-
## Context package
|
|
136
|
-
|
|
137
|
-
Work from this package; do not explore broadly. Open only the files named here to verify. Target working directory: `C:/Users/Micha Bigler/Documents/webapps/ui-core-micha` (never the workspace root). Dependencies `react-markdown` 10.1.0 and `remark-gfm` 4.0.1 are already installed in `package.json` and the lockfile; do not touch either.
|
|
138
|
-
|
|
139
|
-
**Templates to read (maana, read-only, do not edit):** `maana/frontend/src/qda/assistant/` (sibling directory of this repo under the workspace root) — `useAssistantSocket.js` (reconnect with backoff, per-chat socket, close-code mapping), `MarkdownReply.jsx` (the allow-list renderer: copy its approach, but take the table/code region labels from this repo's i18n and colours only from the theme), `ChatThread.jsx`, `ChatList.jsx`, `ChatComposer.jsx`, `ChatWorkspace.jsx` (frame handling around line 118), `assistantApi.js`. Take the structure, not maana's proposals, grants, plans, context dialog or project id. Visual spec: `work-orders/assets/UCM-CHAT-1-ai-chat.html` — read it first; it governs look and interaction, with every colour, radius and type size taken from the MUI theme (palette tokens such as `primary.main`, `text.secondary`, `divider`, `action.hover`, `success/warning/error`), never a literal.
|
|
140
|
-
|
|
141
|
-
**Repo conventions to match (verify in place):**
|
|
142
|
-
- Source is `.jsx`/`.js` under `src/`, tests in `tests/*.test.jsx` (vitest + @testing-library/react + jsdom); look at `tests/Thread.test.jsx`, `tests/ConversationList.test.jsx` and `tests/MessagingProvider.test.jsx` for how a component is tested here (MUI icons are `vi.mock`ed per test file).
|
|
143
|
-
- HTTP goes through `src/auth/apiClient` exactly like `src/messaging/api.js` (default export `apiClient`, each function returns `response.data`).
|
|
144
|
-
- Strings: `useTranslation()` with keys in a new bundle `src/i18n/chatTranslations.ts` that exports exactly one const `chatTranslations`, entries `{ de, en, fr, sw }`, key prefix `Chat.` (check no key collides with another bundle). Register it in three places: `src/i18n/uiCoreTranslations.js` (spread), `src/index.js` (public export next to `messagingTranslations`), and `tests/i18nAggregate.test.js` (`PUBLIC_BUNDLES` plus its import list). German uses the formal variant.
|
|
145
|
-
- Public exports are added to `src/index.js` in a block next to the messaging block (line ~113). Do not edit `src/messaging/**`, `src/notifications/**` or `src/theme/**`.
|
|
146
|
-
|
|
147
|
-
## Wire shape (binding on this order; the Orchestrator pinned it from maana's implementation because DCM-CHAT-1 is not published yet)
|
|
148
|
-
|
|
149
|
-
The Envelope fixes WHICH frames and endpoints exist; the field names below are the working assumption and must be isolated in ONE module (`src/chat/wire.js`: URL builders, frame/field names, the three close codes) so a later contract change touches one file.
|
|
150
|
-
|
|
151
|
-
- **WebSocket** per chat: URL from a `wsUrl(chatId)` option, default `${ws|wss}://${location.host}/ws/assistant/chats/${chatId}/`. Client frames `{type:"send", message}` and `{type:"stop"}`. Server frames: `{type:"history", turns:[turn…]}` on connect; `{type:"delta", text}`; `{type:"tool", phase:"start"|"end", name, label, sources:[{label, reference}]}`; `{type:"turn", turn}`; `{type:"notice", code, text?}`; `{type:"error", code}` with `code` one of `quota_exceeded`, `provider_error`, `timeout`, `prompt_too_long`, `invalid_output`, `security_violation`, `not_configured`, `rate_limited`, `invalid_selection`, `archived`, `turn_active`, `invalid_frame`. Close codes 4401 -> `session_ended`, 4403 -> `access_lost`, 4429 -> `rate_limited`: no reconnect, state surfaced. Any other close -> reconnect with backoff (1 s, 2 s, 4 s, then stop and show the "connection lost" state with a manual Retry), **never resend a message automatically**; ignore malformed JSON frames.
|
|
152
|
-
- **REST**, base path from an `apiBase` option (default `/api/assistant/`): `GET catalogue/` -> `{entries:[{id, driver, model, label, efforts:["low"|"medium"|"high"|"max"…], billing:"subscription"|"pay_per_use"}], default:{entry, effort}}`; `GET chats/?archived=<bool>&cursor=` -> `{results:[chat…], next}`; `POST chats/` body `{scope?}` -> chat; `PATCH chats/{id}/` body any of `{title, archived, selection:{entry, effort}}` -> chat; `DELETE chats/{id}/`; `GET chats/{id}/turns/?cursor=` -> `{results:[turn…], next}` (newest page first, `next` = cursor for older); `GET status/` -> `{status:"available"|"not_configured"}`.
|
|
153
|
-
- **chat** = `{id, title, archived_at|null, selection:{entry, effort}, updated_at}`. **turn** = `{id, seq, user_text, assistant_text, state:"generating"|"completed"|"failed"|"cancelled"|"interrupted", sources:[{label, reference}], driver, model, effort, error_code|null}`.
|
|
154
|
-
|
|
155
|
-
## Named files to create (all new; owns `src/chat/**`, `src/i18n/chatTranslations.ts`, `tests/chat*.test.*`, and the three registration edits above)
|
|
156
|
-
|
|
157
|
-
- `src/chat/wire.js` — constants and URL builders above.
|
|
158
|
-
- `src/chat/api.js` — `createChatApi(overrides = {}, { apiBase })` and the exported `defaultChatApi`: one function per REST call (`getCatalogue, listChats, createChat, updateChat, deleteChat, listTurns, getStatus`) returning `response.data`; `{...defaults, ...overrides}` so overriding one function keeps every other default (the point of this design; contrast `MessagingProvider`).
|
|
159
|
-
- `src/chat/useChatSocket.js` — the hook: `(chatId, {wsUrl, onFrame, onOpen, onClose})` -> `{status, connected, send, reconnect}`. State machine as above. Pass the chat id with every delivered frame so a late frame of a left chat is never applied (maana does this).
|
|
160
|
-
- `src/chat/MarkdownReply.jsx` — allow-list renderer. Allowed elements as maana, `unwrapDisallowed`, links render as text (label plus address when different), images never fetched (alt text or address as text), raw HTML shown as text (no rehype-raw), tables and code in focusable scroll regions, a very long reply falls back to plain text (constant `MARKDOWN_LIMIT`). Styling through `sx` with theme tokens only.
|
|
161
|
-
- `src/chat/ChatThread.jsx` — turns, streaming answer, typing indicator before first delta, tool-activity chip (label from the `tool` frame), source chips (short `label`, full `reference` as tooltip), the quiet "model · effort" line under each answer, a divider between turns whose driver/model/effort differ, older turns loaded by cursor on scroll up/"load older", state chips ("Interrupted" + Retry, "Reconnecting"), and the error states.
|
|
162
|
-
- `src/chat/ChatList.jsx` — new chat, select, per-row overflow menu (Rename, Archive, Delete), Delete confirmation inside a MUI Dialog, "Archived" entry with count, restore of an archived chat, load more.
|
|
163
|
-
- `src/chat/ChatComposer.jsx` — multi-line input, Send, Stop while a turn runs; Send disabled while a turn runs, while the chat is archived, and while the connection is down. Enter sends, Shift+Enter newline.
|
|
164
|
-
- `src/chat/ModelPicker.jsx` — popover (wide) / bottom `Drawer` sheet (narrow, via `useMediaQuery(theme.breakpoints.down('md'))`), entries grouped by driver, "pay per use" tag, effort `ToggleButtonGroup` with levels the entry does not allow disabled; a change calls `updateChat(id, {selection})`; the thread bar shows "model · effort".
|
|
165
|
-
- `src/chat/ChatWorkspace.jsx` — composes list + thread + composer + picker. Props: `apiBase`, `wsUrl`, `api` (partial overrides, merged), `scope`, `sx`. Wide: two columns. Narrow: list in a `Drawer`. Loads status/catalogue, owns the active chat, the streaming state and the edge states: new chat empty state, usage limit (`quota_exceeded` -> "Usage limit reached for {model}. Choose another model or try again later." + "Change model"), interrupted/failed ("The answer could not be completed." + Retry, which re-sends that turn's `user_text` as a new `send` only on the user's click), connection lost ("Reconnecting" chip), `not_configured` ("Chat is not available" / "No language model is configured on this server."), archived (read-only, "Archived" chip, Restore).
|
|
166
|
-
- No `src/chat/index.js`; export from `src/index.js`: `ChatWorkspace, ChatList, ChatThread, ChatComposer, ModelPicker, MarkdownReply, useChatSocket, createChatApi, defaultChatApi, chatTranslations`.
|
|
167
|
-
- `src/i18n/chatTranslations.ts` — every string of the Envelope's copy list verbatim in English, plus control labels, aria-labels and the Markdown region labels; all four languages.
|
|
168
|
-
- Tests (names are guidance): `tests/chatSocket.test.jsx`, `tests/chatThread.test.jsx`, `tests/chatPicker.test.jsx`, `tests/chatList.test.jsx`, `tests/chatEdgeStates.test.jsx`, `tests/chatApi.test.js`, `tests/chatTranslations.test.js`, plus a one-line export check in the style of `tests/messagingExports.test.js`. The socket tests use a fake `WebSocket` class and fake timers.
|
|
169
|
-
|
|
170
|
-
## Invariants, pitfalls, do-not-touch
|
|
171
|
-
|
|
172
|
-
- No raw HTML, no image fetch, no auto-loading links anywhere in answers; no `dangerouslySetInnerHTML`. User message text is rendered as plain text.
|
|
173
|
-
- No literal colours, radii or font sizes copied from the prototype; theme tokens and spacing units only. Light and dark themes must both work.
|
|
174
|
-
- Accessibility: the streaming answer sits in a polite live region that is not re-announced on every delta (`aria-busy` while generating), icon buttons have aria-labels, the picker and menus are keyboard operable, touch targets at least 40 px at narrow width.
|
|
175
|
-
- Do not edit `src/messaging/**`, `src/notifications/**`, `src/theme/**`, `package.json`, the lockfile, `README.md`, `CHANGELOG.md` or the register. Docs and the version bump are the Orchestrator's.
|
|
176
|
-
- Package build is `tsc -p tsconfig.build.json` (allowJs, `src` only): new files must compile; `tests/packageTreeShaking.test.js` and `tests/checkKitIntegration.test.jsx` exist: do not introduce a top-level side effect in the new modules.
|
|
177
|
-
- The working tree contains unrelated foreign changes (`WORK_ORDERS.md`, `work-orders/UCM-DEP-1.md`, `package.json`, `pnpm-lock.yaml`): leave them alone.
|
|
178
|
-
|
|
179
|
-
## Preamble
|
|
180
|
-
|
|
181
|
-
> 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.
|
|
182
|
-
>
|
|
183
|
-
> 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>`.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
# C. Orchestrator only — not addressed to the implementer
|
|
187
|
-
|
|
188
|
-
> **If this WO was dispatched to you as an implementer: STOP here.**
|
|
189
|
-
|
|
190
|
-
Gate #1 open until recorded in the register row. Can start against the `DCM-CHAT-1` contract in parallel; publish as a new minor version. Prototype in scope: ucm has no host app of its own, so the rendered side-by-side at 375 px and 1280 px runs where the surface is first mounted, in `cockpit/CP-CHAT-4`, and is that order's commit gate; a deviation it finds in the shared components is fixed here and republished.
|