@cat-factory/app 0.308.0 → 0.310.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 (265) hide show
  1. package/README.md +32 -2
  2. package/app/assets/css/main.css +22 -0
  3. package/app/assets/css/prose.css +4 -4
  4. package/app/assets/css/type.css +24 -0
  5. package/app/components/assistant/AssistantModal.vue +8 -6
  6. package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
  7. package/app/components/auth/LoginScreen.vue +40 -26
  8. package/app/components/auth/ResetPasswordScreen.vue +9 -4
  9. package/app/components/auth/UserMenu.vue +5 -4
  10. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +48 -37
  11. package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
  12. package/app/components/binaryOutput/StoredAssetView.vue +13 -11
  13. package/app/components/board/AddTaskModal.vue +30 -27
  14. package/app/components/board/AgentFailureCard.vue +21 -18
  15. package/app/components/board/AgentFailureHistory.vue +18 -9
  16. package/app/components/board/CreateInitiativeModal.vue +7 -6
  17. package/app/components/board/FailureDetail.vue +22 -12
  18. package/app/components/board/FailureHistoryList.vue +5 -5
  19. package/app/components/board/RecurringPipelineModal.vue +12 -11
  20. package/app/components/board/ReviewFrictionDialog.vue +8 -6
  21. package/app/components/board/StepExecutionHistory.vue +8 -8
  22. package/app/components/board/nodes/AgentChip.vue +1 -1
  23. package/app/components/board/nodes/BlockNode.vue +25 -24
  24. package/app/components/board/nodes/DecisionBadge.vue +4 -3
  25. package/app/components/board/nodes/EpicNode.vue +4 -4
  26. package/app/components/board/nodes/FrameSwimlanes.vue +8 -10
  27. package/app/components/board/nodes/InitiativeCard.vue +4 -4
  28. package/app/components/board/nodes/LaneGroup.vue +3 -5
  29. package/app/components/board/nodes/TaskCard.vue +20 -15
  30. package/app/components/board/nodes/TaskLane.vue +3 -3
  31. package/app/components/board/nodes/TaskPipelineMini.vue +21 -18
  32. package/app/components/bootstrap/AdoptionReviewModal.vue +36 -26
  33. package/app/components/bootstrap/BootstrapModal.vue +14 -13
  34. package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
  35. package/app/components/brainstorm/BrainstormWindow.vue +13 -10
  36. package/app/components/bugFishing/BugFishingWindow.vue +81 -58
  37. package/app/components/clarity/ClarityReviewWindow.vue +13 -10
  38. package/app/components/common/AsyncViewError.vue +1 -1
  39. package/app/components/common/ClarificationItem.vue +6 -6
  40. package/app/components/common/CopyButton.vue +12 -11
  41. package/app/components/common/DescriptorFields.vue +1 -1
  42. package/app/components/common/EmptyState.vue +1 -1
  43. package/app/components/common/IconButton.vue +34 -9
  44. package/app/components/common/InterviewGateNotice.vue +4 -4
  45. package/app/components/common/MarkdownProse.vue +8 -2
  46. package/app/components/common/SectionLabel.vue +38 -0
  47. package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
  48. package/app/components/context/ContextAttachmentFields.vue +32 -20
  49. package/app/components/docs/DocInterviewWindow.vue +10 -9
  50. package/app/components/documents/ContextDocumentPicker.vue +22 -21
  51. package/app/components/documents/DocumentImportModal.vue +7 -5
  52. package/app/components/documents/DocumentOriginLink.vue +12 -9
  53. package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
  54. package/app/components/documents/DocumentSyncState.vue +4 -4
  55. package/app/components/documents/DocumentTemplatesModal.vue +5 -4
  56. package/app/components/documents/RepoContextDocPicker.vue +7 -9
  57. package/app/components/documents/StartFromDesignModal.vue +4 -4
  58. package/app/components/documents/TaskContextDocs.vue +1 -1
  59. package/app/components/environments/EnvSetupStepper.vue +3 -3
  60. package/app/components/environments/EnvironmentStatusPanel.vue +15 -13
  61. package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
  62. package/app/components/environments/steps/EnvReviewStep.vue +23 -22
  63. package/app/components/environments/steps/EnvSaveStep.vue +5 -5
  64. package/app/components/focus/BlockFocusView.vue +11 -10
  65. package/app/components/followUp/FollowUpWindow.vue +18 -15
  66. package/app/components/forkDecision/ForkDecisionWindow.vue +85 -97
  67. package/app/components/foundational/FoundationalContractSummary.vue +2 -2
  68. package/app/components/foundational/FoundationalServiceCatalogList.vue +6 -5
  69. package/app/components/foundational/FoundationalServiceRegistry.vue +10 -9
  70. package/app/components/foundational/FoundationalServiceSources.vue +7 -6
  71. package/app/components/foundational/FoundationalSuppressions.vue +2 -2
  72. package/app/components/fragments/FragmentLibraryManager.vue +8 -7
  73. package/app/components/fragments/FragmentSelector.vue +22 -20
  74. package/app/components/gates/GateFailingCheckList.vue +7 -6
  75. package/app/components/gates/GateResultView.vue +55 -49
  76. package/app/components/github/AddServiceFromRepoModal.vue +16 -11
  77. package/app/components/github/BranchProtectionPreflight.vue +5 -5
  78. package/app/components/github/GitHubConnect.vue +5 -3
  79. package/app/components/github/GitHubOnboarding.vue +7 -2
  80. package/app/components/github/GitHubPanel.vue +23 -19
  81. package/app/components/github/RepoTreeBrowser.vue +16 -13
  82. package/app/components/humanTest/HumanTestWindow.vue +29 -24
  83. package/app/components/initiative/InitiativePlanNotice.vue +3 -3
  84. package/app/components/initiative/InitiativePlanReview.vue +46 -38
  85. package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
  86. package/app/components/initiative/InitiativeTrackerWindow.vue +213 -165
  87. package/app/components/judge/JudgeResultView.vue +28 -27
  88. package/app/components/kaizen/KaizenPanel.vue +70 -56
  89. package/app/components/kaizen/KaizenStepStatus.vue +7 -6
  90. package/app/components/layout/AccountAuditLog.vue +1 -1
  91. package/app/components/layout/AccountDeploymentSettings.vue +10 -10
  92. package/app/components/layout/AccountFailureKindRules.vue +13 -13
  93. package/app/components/layout/AccountFoundationalSettings.vue +1 -1
  94. package/app/components/layout/AccountFragmentSettings.vue +1 -1
  95. package/app/components/layout/AccountModelPolicySettings.vue +7 -7
  96. package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
  97. package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
  98. package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
  99. package/app/components/layout/AccountSkillSettings.vue +1 -1
  100. package/app/components/layout/AccountTeamSettings.vue +13 -9
  101. package/app/components/layout/AiProvidersBanner.vue +1 -1
  102. package/app/components/layout/AppearanceSwitcher.vue +5 -4
  103. package/app/components/layout/BoardSwitcher.vue +13 -10
  104. package/app/components/layout/BoardToolbar.vue +10 -5
  105. package/app/components/layout/CommandBar.vue +8 -5
  106. package/app/components/layout/DefaultTestEnvBanner.vue +6 -5
  107. package/app/components/layout/IntegrationsHub.vue +12 -9
  108. package/app/components/layout/LanguageSwitcher.vue +5 -4
  109. package/app/components/layout/ModelProvidersHub.vue +10 -7
  110. package/app/components/layout/NotificationsInbox.vue +47 -36
  111. package/app/components/layout/PersonalSetupModal.vue +9 -6
  112. package/app/components/layout/RolePrompt.vue +5 -4
  113. package/app/components/layout/SideBar.vue +7 -8
  114. package/app/components/layout/SpendWarningBanner.vue +3 -3
  115. package/app/components/layout/TranslationWarningBanner.vue +5 -4
  116. package/app/components/layout/UiModeSwitcher.vue +15 -12
  117. package/app/components/layout/UiRoleSwitcher.vue +10 -8
  118. package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
  119. package/app/components/media/ArtifactLightbox.vue +74 -44
  120. package/app/components/media/ImageCompare.vue +80 -85
  121. package/app/components/merge/MergeEffortChips.vue +4 -6
  122. package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
  123. package/app/components/observability/OutcomeFilterChips.vue +6 -5
  124. package/app/components/observability/RunFailureSummary.vue +22 -23
  125. package/app/components/observability/StepMetricsBar.vue +9 -8
  126. package/app/components/observability/StepModelActivity.vue +8 -5
  127. package/app/components/observability/ToolCallList.vue +19 -20
  128. package/app/components/outcome/OutcomeSummaryWindow.vue +48 -46
  129. package/app/components/palettes/AgentPalette.vue +21 -15
  130. package/app/components/palettes/AgentTierSelect.vue +1 -1
  131. package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
  132. package/app/components/panels/AgentStepDetail.vue +57 -49
  133. package/app/components/panels/AttemptEntryHeader.vue +2 -2
  134. package/app/components/panels/DecisionModal.vue +1 -1
  135. package/app/components/panels/GenericStructuredResultView.vue +6 -5
  136. package/app/components/panels/InspectorPanel.vue +15 -13
  137. package/app/components/panels/MergerResultView.vue +10 -9
  138. package/app/components/panels/ObservabilityPanel.vue +211 -186
  139. package/app/components/panels/OperatorDashboardPanel.vue +124 -115
  140. package/app/components/panels/ReportsPanel.vue +87 -83
  141. package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
  142. package/app/components/panels/ResultWindowShell.vue +152 -137
  143. package/app/components/panels/RunDetailLoadState.vue +1 -1
  144. package/app/components/panels/StepContainerStatus.vue +17 -16
  145. package/app/components/panels/StepDelegatedStatus.vue +24 -21
  146. package/app/components/panels/StepEffortReport.vue +12 -17
  147. package/app/components/panels/StepFragmentAdherence.vue +9 -10
  148. package/app/components/panels/StepMetadataCard.vue +41 -43
  149. package/app/components/panels/StepReproductionReport.vue +18 -20
  150. package/app/components/panels/StepRestartControl.vue +3 -2
  151. package/app/components/panels/StepRunMeta.vue +27 -26
  152. package/app/components/panels/StepTestReport.vue +16 -15
  153. package/app/components/panels/StepToolServers.vue +7 -8
  154. package/app/components/panels/StepValidationReport.vue +5 -5
  155. package/app/components/panels/inspector/ContainerSummary.vue +4 -4
  156. package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
  157. package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
  158. package/app/components/panels/inspector/EpicChildren.vue +12 -10
  159. package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
  160. package/app/components/panels/inspector/FrontendConfig.vue +29 -36
  161. package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
  162. package/app/components/panels/inspector/InspectorSection.vue +25 -17
  163. package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
  164. package/app/components/panels/inspector/ServiceConnections.vue +5 -4
  165. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
  166. package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
  167. package/app/components/panels/inspector/ServiceTestConfig.vue +46 -49
  168. package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
  169. package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
  170. package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
  171. package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
  172. package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
  173. package/app/components/panels/inspector/TaskDependencies.vue +1 -1
  174. package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
  175. package/app/components/panels/inspector/TaskExecution.vue +18 -16
  176. package/app/components/panels/inspector/TaskRunSettings.vue +45 -44
  177. package/app/components/panels/inspector/TaskStructure.vue +5 -4
  178. package/app/components/pipeline/AgentPromptEditor.vue +15 -14
  179. package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
  180. package/app/components/pipeline/EstimateThresholdFields.vue +14 -11
  181. package/app/components/pipeline/GateConfigFields.vue +19 -23
  182. package/app/components/pipeline/IterationCapPrompt.vue +1 -1
  183. package/app/components/pipeline/PipelineBuilder.vue +113 -99
  184. package/app/components/pipeline/PipelineHealthModal.vue +7 -7
  185. package/app/components/pipeline/PipelinePicker.vue +11 -9
  186. package/app/components/pipeline/PipelinePreview.vue +6 -7
  187. package/app/components/pipeline/PipelineProgress.vue +49 -45
  188. package/app/components/prReview/PrReviewWindow.vue +87 -65
  189. package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
  190. package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
  191. package/app/components/providers/ApiKeysSection.vue +11 -9
  192. package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
  193. package/app/components/providers/VendorCredentialsModal.vue +5 -4
  194. package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
  195. package/app/components/ralph/RalphLoopResultView.vue +29 -29
  196. package/app/components/requirements/RequirementsReviewWindow.vue +22 -17
  197. package/app/components/riskPolicy/RiskPolicyPicker.vue +13 -11
  198. package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
  199. package/app/components/sandbox/SandboxPanel.vue +93 -73
  200. package/app/components/settings/ApiTokensPanel.vue +1 -1
  201. package/app/components/settings/BudgetSettings.vue +18 -17
  202. package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
  203. package/app/components/settings/CloudflareHandlerSection.vue +44 -41
  204. package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
  205. package/app/components/settings/ConnectionTestVerdict.vue +1 -1
  206. package/app/components/settings/ConsensusGroupsSection.vue +58 -47
  207. package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
  208. package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
  209. package/app/components/settings/InfraHandlersConfigurator.vue +26 -24
  210. package/app/components/settings/InfrastructureBackendPicker.vue +18 -18
  211. package/app/components/settings/IssueTrackerPanel.vue +30 -21
  212. package/app/components/settings/KubernetesEngineForm.vue +9 -8
  213. package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
  214. package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
  215. package/app/components/settings/LocalModelEndpointsPanel.vue +13 -11
  216. package/app/components/settings/MergeClassRulesEditor.vue +6 -5
  217. package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
  218. package/app/components/settings/ModelConfigurationPanel.vue +17 -19
  219. package/app/components/settings/ModelPresetHealthModal.vue +3 -3
  220. package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
  221. package/app/components/settings/OpenRouterCatalogPanel.vue +10 -8
  222. package/app/components/settings/PackageRegistriesPanel.vue +4 -4
  223. package/app/components/settings/ProviderConnectionTab.vue +5 -4
  224. package/app/components/settings/ProviderManifestEditor.vue +9 -8
  225. package/app/components/settings/ProviderPreferenceEditor.vue +13 -13
  226. package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
  227. package/app/components/settings/RiskPolicyEditorRow.vue +21 -19
  228. package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
  229. package/app/components/settings/RiskPolicyPanel.vue +11 -13
  230. package/app/components/settings/ServiceFragmentDefaultsPanel.vue +15 -12
  231. package/app/components/settings/SharedStacksPanel.vue +5 -5
  232. package/app/components/settings/TaskSourceCard.vue +2 -2
  233. package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
  234. package/app/components/settings/ToolServerChecklist.vue +22 -22
  235. package/app/components/settings/UsageSettings.vue +13 -13
  236. package/app/components/settings/UserSecretsSection.vue +4 -3
  237. package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
  238. package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
  239. package/app/components/skills/ReviewSkillQueue.vue +12 -10
  240. package/app/components/skills/SkillLibraryManager.vue +9 -8
  241. package/app/components/slack/SlackPanel.vue +17 -12
  242. package/app/components/spec/ServiceSpecWindow.vue +19 -19
  243. package/app/components/tasks/BugHuntModal.vue +1 -1
  244. package/app/components/tasks/ContextIssuePicker.vue +16 -15
  245. package/app/components/tasks/TaskContextIssues.vue +5 -4
  246. package/app/components/tasks/TaskImportModal.vue +3 -2
  247. package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
  248. package/app/components/testing/TestReportWindow.vue +67 -60
  249. package/app/components/theme/ThemeImportModal.vue +2 -2
  250. package/app/components/tutorial/TutorialNudge.vue +3 -2
  251. package/app/components/tutorial/TutorialOverlay.vue +3 -2
  252. package/app/components/vcs/GitLabConnect.vue +1 -1
  253. package/app/components/visualConfirm/VisualConfirmationWindow.vue +79 -54
  254. package/app/utils/theme/builtins.ts +7 -1
  255. package/i18n/locales/de.json +7 -3
  256. package/i18n/locales/en.json +7 -3
  257. package/i18n/locales/es.json +7 -3
  258. package/i18n/locales/fr.json +7 -3
  259. package/i18n/locales/he.json +7 -3
  260. package/i18n/locales/it.json +7 -3
  261. package/i18n/locales/ja.json +7 -3
  262. package/i18n/locales/pl.json +7 -3
  263. package/i18n/locales/tr.json +7 -3
  264. package/i18n/locales/uk.json +7 -3
  265. package/package.json +1 -1
@@ -473,7 +473,7 @@ const declaredFormats = computed(() => {
473
473
  <template>
474
474
  <div class="ms-6 flex flex-col gap-1.5" data-testid="binary-output-picker">
475
475
  <div class="flex items-center gap-2">
476
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryOutputStorage') }}</span>
476
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryOutputStorage') }}</span>
477
477
  <USelect
478
478
  class="w-56"
479
479
  :model-value="config?.storageServiceId ?? ''"
@@ -488,7 +488,7 @@ const declaredFormats = computed(() => {
488
488
  </div>
489
489
 
490
490
  <div v-if="config?.storageServiceId" class="flex items-center gap-2">
491
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryOutputContext') }}</span>
491
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryOutputContext') }}</span>
492
492
  <USelectMenu
493
493
  class="w-56"
494
494
  multiple
@@ -503,9 +503,7 @@ const declaredFormats = computed(() => {
503
503
  </div>
504
504
 
505
505
  <div v-if="config?.storageServiceId" class="flex items-center gap-2">
506
- <span class="text-[10px] text-dimmed">{{
507
- t('pipeline.builder.binaryOutputGenerators')
508
- }}</span>
506
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryOutputGenerators') }}</span>
509
507
  <USelectMenu
510
508
  class="w-56"
511
509
  multiple
@@ -521,9 +519,7 @@ const declaredFormats = computed(() => {
521
519
  </div>
522
520
 
523
521
  <div v-if="config?.storageServiceId" class="flex items-center gap-2">
524
- <span class="text-[10px] text-dimmed">{{
525
- t('pipeline.builder.binaryOutputModalities')
526
- }}</span>
522
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryOutputModalities') }}</span>
527
523
  <USelectMenu
528
524
  class="w-56"
529
525
  multiple
@@ -541,9 +537,7 @@ const declaredFormats = computed(() => {
541
537
  under them. Both tiers: like the rest of this picker it is not an override of a default —
542
538
  a format nobody stated is a format the run does not check. -->
543
539
  <div v-if="config?.storageServiceId" class="flex items-center gap-2">
544
- <span class="text-[10px] text-dimmed">{{
545
- t('pipeline.builder.binaryOutputMediaTypes')
546
- }}</span>
540
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryOutputMediaTypes') }}</span>
547
541
  <UInput
548
542
  class="w-56"
549
543
  :model-value="mediaTypeText"
@@ -556,7 +550,7 @@ const declaredFormats = computed(() => {
556
550
  </div>
557
551
  <p
558
552
  v-if="config?.storageServiceId && declaredFormats.length"
559
- class="ms-1 text-[10px] text-dimmed"
553
+ class="ms-1 text-3xs text-dimmed"
560
554
  data-testid="binary-output-declared-formats"
561
555
  >
562
556
  {{
@@ -572,7 +566,7 @@ const declaredFormats = computed(() => {
572
566
  option nobody stated is an option the run does not apply. -->
573
567
  <template v-if="config?.storageServiceId">
574
568
  <div v-if="offers('reference-image')" class="flex items-start gap-2">
575
- <span class="mt-1 text-[10px] text-dimmed">{{
569
+ <span class="mt-1 text-3xs text-dimmed">{{
576
570
  t('pipeline.builder.binaryReferenceImages')
577
571
  }}</span>
578
572
  <UTextarea
@@ -588,7 +582,7 @@ const declaredFormats = computed(() => {
588
582
  </div>
589
583
  <p
590
584
  v-if="unusableReferences.length"
591
- class="ms-1 text-[10px] text-app-warning-400"
585
+ class="ms-1 text-3xs text-app-warning-400"
592
586
  data-testid="binary-output-reference-unusable"
593
587
  >
594
588
  {{
@@ -599,7 +593,7 @@ const declaredFormats = computed(() => {
599
593
  </p>
600
594
 
601
595
  <div v-if="offers('instruction-edit') || offers('mask-edit')" class="flex items-center gap-2">
602
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryEditMode') }}</span>
596
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryEditMode') }}</span>
603
597
  <USelect
604
598
  class="w-56"
605
599
  size="xs"
@@ -618,9 +612,7 @@ const declaredFormats = computed(() => {
618
612
  />
619
613
  </div>
620
614
  <div v-if="generation.edit" class="flex items-center gap-2">
621
- <span class="text-[10px] text-dimmed">{{
622
- t('pipeline.builder.binaryEditInstruction')
623
- }}</span>
615
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryEditInstruction') }}</span>
624
616
  <UInput
625
617
  class="w-56"
626
618
  size="xs"
@@ -636,9 +628,7 @@ const declaredFormats = computed(() => {
636
628
  </div>
637
629
 
638
630
  <div v-if="offers('negative-prompt')" class="flex items-center gap-2">
639
- <span class="text-[10px] text-dimmed">{{
640
- t('pipeline.builder.binaryNegativePrompt')
641
- }}</span>
631
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryNegativePrompt') }}</span>
642
632
  <UInput
643
633
  class="w-56"
644
634
  size="xs"
@@ -652,7 +642,7 @@ const declaredFormats = computed(() => {
652
642
  </div>
653
643
 
654
644
  <div v-if="offers('aspect-ratio')" class="flex items-center gap-2">
655
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryAspectRatio') }}</span>
645
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryAspectRatio') }}</span>
656
646
  <UInput
657
647
  class="w-56"
658
648
  size="xs"
@@ -670,7 +660,7 @@ const declaredFormats = computed(() => {
670
660
  exists to remove. -->
671
661
  <div v-if="offers('exact-size')" class="flex flex-col gap-1">
672
662
  <div class="flex items-center gap-2">
673
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryOutputSize') }}</span>
663
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryOutputSize') }}</span>
674
664
  <UInput
675
665
  class="w-24"
676
666
  type="number"
@@ -680,7 +670,7 @@ const declaredFormats = computed(() => {
680
670
  data-testid="binary-output-size-width"
681
671
  @change="setOutputSize('width', ($event.target as HTMLInputElement).value)"
682
672
  />
683
- <span class="text-[10px] text-dimmed">×</span>
673
+ <span class="text-3xs text-dimmed">×</span>
684
674
  <UInput
685
675
  class="w-24"
686
676
  type="number"
@@ -696,7 +686,7 @@ const declaredFormats = computed(() => {
696
686
  that does not carry the requirement. -->
697
687
  <p
698
688
  v-if="outputSizeIncomplete"
699
- class="text-[10px] text-app-warning-400"
689
+ class="text-3xs text-app-warning-400"
700
690
  data-testid="binary-output-size-incomplete"
701
691
  >
702
692
  {{ t('pipeline.builder.binaryOutputSizeIncomplete') }}
@@ -704,7 +694,7 @@ const declaredFormats = computed(() => {
704
694
  </div>
705
695
 
706
696
  <div v-if="offers('seed')" class="flex items-center gap-2">
707
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binarySeed') }}</span>
697
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binarySeed') }}</span>
708
698
  <UInput
709
699
  class="w-56"
710
700
  type="number"
@@ -731,7 +721,7 @@ const declaredFormats = computed(() => {
731
721
  setGeneration({ transparentBackground: $event ? true : undefined })
732
722
  "
733
723
  />
734
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryTransparent') }}</span>
724
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryTransparent') }}</span>
735
725
  </label>
736
726
  <label v-if="offers('tileable')" class="flex items-center gap-1.5">
737
727
  <UCheckbox
@@ -739,7 +729,7 @@ const declaredFormats = computed(() => {
739
729
  data-testid="binary-output-tileable"
740
730
  @update:model-value="setGeneration({ tileable: $event ? true : undefined })"
741
731
  />
742
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryTileable') }}</span>
732
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryTileable') }}</span>
743
733
  </label>
744
734
  <label v-if="offers('upscale')" class="flex items-center gap-1.5">
745
735
  <UCheckbox
@@ -747,7 +737,7 @@ const declaredFormats = computed(() => {
747
737
  data-testid="binary-output-upscale"
748
738
  @update:model-value="setGeneration({ upscale: $event ? 2 : undefined })"
749
739
  />
750
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryUpscale') }}</span>
740
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryUpscale') }}</span>
751
741
  </label>
752
742
  </div>
753
743
 
@@ -759,10 +749,10 @@ const declaredFormats = computed(() => {
759
749
  data-testid="binary-output-comparison"
760
750
  @update:model-value="setComparison($event === true)"
761
751
  />
762
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryComparison') }}</span>
752
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryComparison') }}</span>
763
753
  </label>
764
754
  <div v-if="config.comparison" class="ms-6 flex flex-wrap items-center gap-3">
765
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryPerGenerator') }}</span>
755
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryPerGenerator') }}</span>
766
756
  <USelect
767
757
  class="w-20"
768
758
  size="xs"
@@ -777,12 +767,12 @@ const declaredFormats = computed(() => {
777
767
  data-testid="binary-output-multi-select"
778
768
  @update:model-value="setMultiSelect($event === true)"
779
769
  />
780
- <span class="text-[10px] text-dimmed">{{ t('pipeline.builder.binaryMultiSelect') }}</span>
770
+ <span class="text-3xs text-dimmed">{{ t('pipeline.builder.binaryMultiSelect') }}</span>
781
771
  </label>
782
772
  </div>
783
773
  <p
784
774
  v-if="comparisonUnreachable"
785
- class="text-[10px] text-app-warning-400"
775
+ class="text-3xs text-app-warning-400"
786
776
  data-testid="binary-output-comparison-unreachable"
787
777
  >
788
778
  {{ t('pipeline.builder.binaryComparisonUnreachable') }}
@@ -794,25 +784,25 @@ const declaredFormats = computed(() => {
794
784
  an untagged one, and a lost CONTEXT service is not a lost storage target. -->
795
785
  <p
796
786
  v-if="has('catalog_unavailable')"
797
- class="text-[10px] text-app-warning-400"
787
+ class="text-3xs text-app-warning-400"
798
788
  data-testid="binary-output-unavailable"
799
789
  >
800
790
  {{ t('pipeline.builder.binaryOutputUnavailable') }}
801
791
  </p>
802
792
  <p
803
793
  v-else-if="has('no_storage_service')"
804
- class="text-[10px] text-app-warning-400"
794
+ class="text-3xs text-app-warning-400"
805
795
  data-testid="binary-output-no-storage"
806
796
  >
807
797
  {{ t('pipeline.builder.binaryOutputNoStorage', { capability: ASSET_STORAGE_CAPABILITY }) }}
808
798
  </p>
809
- <p v-if="has('unknown_service')" class="text-[10px] text-app-warning-400">
799
+ <p v-if="has('unknown_service')" class="text-3xs text-app-warning-400">
810
800
  {{ t('pipeline.builder.binaryOutputMissing') }}
811
801
  </p>
812
- <p v-if="has('not_storage_capable')" class="text-[10px] text-app-warning-400">
802
+ <p v-if="has('not_storage_capable')" class="text-3xs text-app-warning-400">
813
803
  {{ t('pipeline.builder.binaryOutputNotStorage', { capability: ASSET_STORAGE_CAPABILITY }) }}
814
804
  </p>
815
- <p v-if="has('unknown_context_service')" class="text-[10px] text-app-warning-400">
805
+ <p v-if="has('unknown_context_service')" class="text-3xs text-app-warning-400">
816
806
  {{
817
807
  t('pipeline.builder.binaryOutputContextMissing', {
818
808
  ids: pick.unknownContextIds.join(', '),
@@ -826,14 +816,14 @@ const declaredFormats = computed(() => {
826
816
  it says so and stops, exactly as run admission does. -->
827
817
  <p
828
818
  v-if="has('generators_unavailable')"
829
- class="text-[10px] text-app-warning-400"
819
+ class="text-3xs text-app-warning-400"
830
820
  data-testid="binary-output-generators-unavailable"
831
821
  >
832
822
  {{ t('pipeline.builder.binaryOutputGeneratorsUnavailable') }}
833
823
  </p>
834
824
  <p
835
825
  v-if="has('unknown_generator')"
836
- class="text-[10px] text-app-warning-400"
826
+ class="text-3xs text-app-warning-400"
837
827
  data-testid="binary-output-unknown-generator"
838
828
  >
839
829
  {{
@@ -844,7 +834,7 @@ const declaredFormats = computed(() => {
844
834
  </p>
845
835
  <p
846
836
  v-if="has('modality_uncovered')"
847
- class="text-[10px] text-app-warning-400"
837
+ class="text-3xs text-app-warning-400"
848
838
  data-testid="binary-output-modality-uncovered"
849
839
  >
850
840
  {{
@@ -855,7 +845,7 @@ const declaredFormats = computed(() => {
855
845
  </p>
856
846
  <p
857
847
  v-if="has('media_type_uncovered')"
858
- class="text-[10px] text-app-warning-400"
848
+ class="text-3xs text-app-warning-400"
859
849
  data-testid="binary-output-media-type-uncovered"
860
850
  >
861
851
  {{
@@ -870,7 +860,7 @@ const declaredFormats = computed(() => {
870
860
  would send someone editing a selection that is fine. -->
871
861
  <p
872
862
  v-if="has('media_type_unverifiable')"
873
- class="text-[10px] text-dimmed"
863
+ class="text-3xs text-dimmed"
874
864
  data-testid="binary-output-media-type-unverifiable"
875
865
  >
876
866
  {{
@@ -886,7 +876,7 @@ const declaredFormats = computed(() => {
886
876
  mismatch. Silence here is what turned it into a surprise at the door. -->
887
877
  <p
888
878
  v-if="has('generator_harness_required')"
889
- class="text-[10px] text-dimmed"
879
+ class="text-3xs text-dimmed"
890
880
  data-testid="binary-output-generator-harness"
891
881
  >
892
882
  {{ t('pipeline.builder.binaryOutputGeneratorHarness', { generators: harnessServedSummary }) }}
@@ -897,14 +887,14 @@ const declaredFormats = computed(() => {
897
887
  line carries is the step's own prompt, which is the field right beside it. -->
898
888
  <p
899
889
  v-if="has('generator_overlap')"
900
- class="text-[10px] text-dimmed"
890
+ class="text-3xs text-dimmed"
901
891
  data-testid="binary-output-generator-overlap"
902
892
  >
903
893
  {{ t('pipeline.builder.binaryOutputGeneratorOverlap', { overlaps: overlapSummary }) }}
904
894
  </p>
905
895
  <p
906
896
  v-if="has('capability_unsupported')"
907
- class="text-[10px] text-app-warning-400"
897
+ class="text-3xs text-app-warning-400"
908
898
  data-testid="binary-output-capability-unsupported"
909
899
  >
910
900
  {{
@@ -919,7 +909,7 @@ const declaredFormats = computed(() => {
919
909
  <p
920
910
  v-for="value in pick.unacceptedValues"
921
911
  :key="value.option"
922
- class="text-[10px] text-app-warning-400"
912
+ class="text-3xs text-app-warning-400"
923
913
  data-testid="binary-output-value-unaccepted"
924
914
  >
925
915
  {{
@@ -935,7 +925,7 @@ const declaredFormats = computed(() => {
935
925
  two values on this form. -->
936
926
  <p
937
927
  v-if="has('output_size_ambiguous')"
938
- class="text-[10px] text-app-warning-400"
928
+ class="text-3xs text-app-warning-400"
939
929
  data-testid="binary-output-size-ambiguous"
940
930
  >
941
931
  {{
@@ -950,7 +940,7 @@ const declaredFormats = computed(() => {
950
940
  selections in the product. -->
951
941
  <p
952
942
  v-if="has('capability_unverifiable')"
953
- class="text-[10px] text-dimmed"
943
+ class="text-3xs text-dimmed"
954
944
  data-testid="binary-output-capability-unverifiable"
955
945
  >
956
946
  {{
@@ -965,7 +955,7 @@ const declaredFormats = computed(() => {
965
955
  <p
966
956
  v-for="value in pick.partiallyAcceptedValues"
967
957
  :key="value.option"
968
- class="text-[10px] text-dimmed"
958
+ class="text-3xs text-dimmed"
969
959
  data-testid="binary-output-value-partial"
970
960
  >
971
961
  {{
@@ -980,7 +970,7 @@ const declaredFormats = computed(() => {
980
970
  another has not said what it takes, so the step starts and is served by the second. -->
981
971
  <p
982
972
  v-if="has('option_value_unverifiable')"
983
- class="text-[10px] text-dimmed"
973
+ class="text-3xs text-dimmed"
984
974
  data-testid="binary-output-value-unverifiable"
985
975
  >
986
976
  {{
@@ -991,7 +981,7 @@ const declaredFormats = computed(() => {
991
981
  </p>
992
982
  <p
993
983
  v-if="unusableMediaTypes.length"
994
- class="text-[10px] text-app-warning-400"
984
+ class="text-3xs text-app-warning-400"
995
985
  data-testid="binary-output-media-type-unusable"
996
986
  >
997
987
  {{
@@ -47,27 +47,30 @@ const fields = computed(() =>
47
47
  })),
48
48
  )
49
49
 
50
- function commit(axis: EstimateAxis, raw: string) {
51
- emit('update', axis, parseAxisThreshold(raw))
50
+ // The control hands back a number (or nothing when cleared); the shared parser still owns the
51
+ // clamping, so the value that leaves here is the same one the text input used to produce.
52
+ function commit(axis: EstimateAxis, raw: number | undefined) {
53
+ emit('update', axis, raw == null ? undefined : parseAxisThreshold(String(raw)))
52
54
  }
53
55
  </script>
54
56
 
55
57
  <template>
56
58
  <div class="flex flex-wrap items-center gap-2 border-t border-default pt-2">
57
- <span class="text-[10px] text-dimmed" :title="t(OUTCOME_HINT_KEYS[outcome])">
59
+ <span class="text-3xs text-dimmed" :title="t(OUTCOME_HINT_KEYS[outcome])">
58
60
  {{ t('pipeline.builder.runWhenAny') }}
59
61
  </span>
60
62
  <template v-for="f in fields" :key="f.axis">
61
63
  <label class="text-muted" :title="f.hint">{{ f.label }}</label>
62
- <input
63
- :value="f.value"
64
+ <UInputNumber
65
+ :model-value="f.value"
64
66
  :title="f.hint"
65
- type="number"
66
- min="0"
67
- max="1"
68
- step="0.1"
69
- class="w-14 rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
70
- @change="commit(f.axis, ($event.target as HTMLInputElement).value)"
67
+ :min="0"
68
+ :max="1"
69
+ :step="0.1"
70
+ :step-snapping="false"
71
+ size="xs"
72
+ class="w-28"
73
+ @update:model-value="commit(f.axis, $event ?? undefined)"
71
74
  />
72
75
  </template>
73
76
  </div>
@@ -119,24 +119,20 @@ const gateFieldValues = computed<DescriptorFieldValues>({
119
119
  v-if="gated"
120
120
  class="space-y-2 rounded-md border border-app-warning-800/40 bg-app-warning-950/10 p-2"
121
121
  >
122
- <div class="flex flex-wrap items-center gap-2 text-[10px]">
122
+ <div class="flex flex-wrap items-center gap-2 text-3xs">
123
123
  <span class="text-dimmed">{{ t('pipeline.gateConfig.approversLabel') }}</span>
124
- <label
124
+ <UCheckbox
125
125
  v-for="role in APPROVER_ROLES"
126
126
  :key="role"
127
- class="flex items-center gap-1 text-muted"
128
- >
129
- <input
130
- type="checkbox"
131
- :checked="config.approvers?.roles?.includes(role) ?? false"
132
- :data-testid="`gate-approver-role-${role}`"
133
- @change="toggleRole(role, ($event.target as HTMLInputElement).checked)"
134
- />
135
- {{ t(ROLE_LABEL_KEYS[role as 'admin' | 'member']) }}
136
- </label>
127
+ size="xs"
128
+ :model-value="config.approvers?.roles?.includes(role) ?? false"
129
+ :label="t(ROLE_LABEL_KEYS[role as 'admin' | 'member'])"
130
+ :data-testid="`gate-approver-role-${role}`"
131
+ @update:model-value="toggleRole(role, $event === true)"
132
+ />
137
133
  </div>
138
134
 
139
- <div class="flex flex-wrap items-center gap-2 text-[10px]">
135
+ <div class="flex flex-wrap items-center gap-2 text-3xs">
140
136
  <span class="text-dimmed">{{ t('pipeline.gateConfig.namedApproversLabel') }}</span>
141
137
  <USelectMenu
142
138
  class="w-64"
@@ -151,24 +147,24 @@ const gateFieldValues = computed<DescriptorFieldValues>({
151
147
  />
152
148
  </div>
153
149
 
154
- <div class="flex flex-wrap items-center gap-2 text-[10px]">
150
+ <div class="flex flex-wrap items-center gap-2 text-3xs">
155
151
  <label class="text-dimmed" :title="t('pipeline.gateConfig.requiredApprovalsHint')">
156
152
  {{ t('pipeline.gateConfig.requiredApprovalsLabel') }}
157
153
  </label>
158
- <input
159
- :value="requiredApprovals"
160
- type="number"
161
- min="1"
154
+ <UInputNumber
155
+ :model-value="Number(requiredApprovals)"
156
+ :min="1"
162
157
  :max="MAX_GATE_APPROVALS"
163
- step="1"
164
- class="w-14 rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
158
+ :step="1"
159
+ size="xs"
160
+ class="w-24"
165
161
  data-testid="gate-required-approvals"
166
- @change="setRequiredApprovals(($event.target as HTMLInputElement).value)"
162
+ @update:model-value="setRequiredApprovals(String($event ?? ''))"
167
163
  />
168
164
  <span class="text-dimmed">{{ t('pipeline.gateConfig.requiredApprovalsHint') }}</span>
169
165
  </div>
170
166
 
171
- <p v-if="!config.approvers" class="text-[10px] text-dimmed">
167
+ <p v-if="!config.approvers" class="text-3xs text-dimmed">
172
168
  {{ t('pipeline.gateConfig.anyoneHint') }}
173
169
  </p>
174
170
  </div>
@@ -179,7 +175,7 @@ const gateFieldValues = computed<DescriptorFieldValues>({
179
175
  v-if="gateFields?.length"
180
176
  class="space-y-2 rounded-md border border-default bg-default/40 p-2"
181
177
  >
182
- <p class="text-[10px] text-dimmed">{{ t('pipeline.gateConfig.gateParametersLabel') }}</p>
178
+ <p class="text-3xs text-dimmed">{{ t('pipeline.gateConfig.gateParametersLabel') }}</p>
183
179
  <DescriptorFields
184
180
  v-model="gateFieldValues"
185
181
  :fields="gateFields"
@@ -38,7 +38,7 @@ const emit = defineEmits<{ resolve: [choice: IterationCapChoice] }>()
38
38
  <UIcon name="i-lucide-alert-triangle" class="h-5 w-5 shrink-0" />
39
39
  {{ heading }}
40
40
  </div>
41
- <p class="mt-1 text-[12px] text-app-warning-200/80">{{ detail }}</p>
41
+ <p class="mt-1 text-xs text-app-warning-200/80">{{ detail }}</p>
42
42
  <div class="mt-3 flex flex-wrap gap-2">
43
43
  <UButton
44
44
  color="primary"