@cat-factory/app 0.307.1 → 0.309.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 (255) hide show
  1. package/README.md +21 -0
  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 +3 -2
  6. package/app/components/auth/UserMenu.vue +1 -1
  7. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +15 -15
  8. package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
  9. package/app/components/binaryOutput/StoredAssetView.vue +5 -5
  10. package/app/components/board/AddTaskModal.vue +16 -14
  11. package/app/components/board/AgentFailureCard.vue +9 -9
  12. package/app/components/board/AgentFailureHistory.vue +1 -1
  13. package/app/components/board/CreateInitiativeModal.vue +2 -2
  14. package/app/components/board/FailureDetail.vue +1 -1
  15. package/app/components/board/FailureHistoryList.vue +5 -5
  16. package/app/components/board/RecurringPipelineModal.vue +12 -11
  17. package/app/components/board/ReviewFrictionDialog.vue +4 -3
  18. package/app/components/board/StepExecutionHistory.vue +8 -8
  19. package/app/components/board/nodes/AgentChip.vue +1 -1
  20. package/app/components/board/nodes/BlockNode.vue +8 -9
  21. package/app/components/board/nodes/EpicNode.vue +4 -4
  22. package/app/components/board/nodes/FrameSwimlanes.vue +4 -7
  23. package/app/components/board/nodes/InitiativeCard.vue +4 -4
  24. package/app/components/board/nodes/LaneGroup.vue +3 -5
  25. package/app/components/board/nodes/TaskCard.vue +8 -8
  26. package/app/components/board/nodes/TaskLane.vue +3 -3
  27. package/app/components/board/nodes/TaskPipelineMini.vue +13 -12
  28. package/app/components/bootstrap/AdoptionReviewModal.vue +7 -6
  29. package/app/components/bootstrap/BootstrapModal.vue +11 -10
  30. package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
  31. package/app/components/brainstorm/BrainstormWindow.vue +8 -7
  32. package/app/components/bugFishing/BugFishingWindow.vue +37 -36
  33. package/app/components/clarity/ClarityReviewWindow.vue +8 -7
  34. package/app/components/common/AsyncViewError.vue +1 -1
  35. package/app/components/common/ClarificationItem.vue +6 -6
  36. package/app/components/common/DescriptorFields.vue +1 -1
  37. package/app/components/common/EmptyState.vue +1 -1
  38. package/app/components/common/InterviewGateNotice.vue +4 -4
  39. package/app/components/common/MarkdownProse.vue +8 -2
  40. package/app/components/common/SectionLabel.vue +38 -0
  41. package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
  42. package/app/components/context/ContextAttachmentFields.vue +9 -8
  43. package/app/components/docs/DocInterviewWindow.vue +10 -9
  44. package/app/components/documents/ContextDocumentPicker.vue +10 -12
  45. package/app/components/documents/DocumentImportModal.vue +3 -2
  46. package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
  47. package/app/components/documents/DocumentSyncState.vue +1 -1
  48. package/app/components/documents/DocumentTemplatesModal.vue +5 -4
  49. package/app/components/documents/RepoContextDocPicker.vue +3 -6
  50. package/app/components/documents/StartFromDesignModal.vue +4 -4
  51. package/app/components/documents/TaskContextDocs.vue +1 -1
  52. package/app/components/environments/EnvSetupStepper.vue +3 -3
  53. package/app/components/environments/EnvironmentStatusPanel.vue +11 -10
  54. package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
  55. package/app/components/environments/steps/EnvReviewStep.vue +23 -22
  56. package/app/components/environments/steps/EnvSaveStep.vue +5 -5
  57. package/app/components/focus/BlockFocusView.vue +11 -10
  58. package/app/components/followUp/FollowUpWindow.vue +10 -10
  59. package/app/components/forkDecision/ForkDecisionWindow.vue +23 -26
  60. package/app/components/foundational/FoundationalContractSummary.vue +2 -2
  61. package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -3
  62. package/app/components/foundational/FoundationalServiceRegistry.vue +3 -3
  63. package/app/components/foundational/FoundationalSuppressions.vue +2 -2
  64. package/app/components/fragments/FragmentLibraryManager.vue +3 -3
  65. package/app/components/fragments/FragmentSelector.vue +10 -11
  66. package/app/components/gates/GateFailingCheckList.vue +3 -3
  67. package/app/components/gates/GateResultView.vue +39 -38
  68. package/app/components/github/AddServiceFromRepoModal.vue +5 -4
  69. package/app/components/github/BranchProtectionPreflight.vue +5 -5
  70. package/app/components/github/GitHubConnect.vue +5 -3
  71. package/app/components/github/GitHubPanel.vue +14 -13
  72. package/app/components/github/RepoTreeBrowser.vue +1 -1
  73. package/app/components/humanTest/HumanTestWindow.vue +18 -17
  74. package/app/components/initiative/InitiativePlanNotice.vue +3 -3
  75. package/app/components/initiative/InitiativePlanReview.vue +19 -21
  76. package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
  77. package/app/components/initiative/InitiativeTrackerWindow.vue +54 -53
  78. package/app/components/judge/JudgeResultView.vue +24 -25
  79. package/app/components/kaizen/KaizenPanel.vue +4 -4
  80. package/app/components/kaizen/KaizenStepStatus.vue +7 -6
  81. package/app/components/layout/AccountAuditLog.vue +1 -1
  82. package/app/components/layout/AccountDeploymentSettings.vue +10 -10
  83. package/app/components/layout/AccountFailureKindRules.vue +13 -13
  84. package/app/components/layout/AccountFoundationalSettings.vue +1 -1
  85. package/app/components/layout/AccountFragmentSettings.vue +1 -1
  86. package/app/components/layout/AccountModelPolicySettings.vue +7 -7
  87. package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
  88. package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
  89. package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
  90. package/app/components/layout/AccountSkillSettings.vue +1 -1
  91. package/app/components/layout/AccountTeamSettings.vue +4 -0
  92. package/app/components/layout/AiProvidersBanner.vue +1 -1
  93. package/app/components/layout/AppearanceSwitcher.vue +1 -1
  94. package/app/components/layout/BoardSwitcher.vue +3 -2
  95. package/app/components/layout/BoardToolbar.vue +6 -2
  96. package/app/components/layout/CommandBar.vue +4 -2
  97. package/app/components/layout/DefaultTestEnvBanner.vue +2 -2
  98. package/app/components/layout/IntegrationsHub.vue +4 -3
  99. package/app/components/layout/LanguageSwitcher.vue +1 -1
  100. package/app/components/layout/ModelProvidersHub.vue +6 -4
  101. package/app/components/layout/NotificationsInbox.vue +8 -7
  102. package/app/components/layout/PersonalSetupModal.vue +5 -3
  103. package/app/components/layout/RolePrompt.vue +1 -1
  104. package/app/components/layout/SideBar.vue +3 -5
  105. package/app/components/layout/SpendWarningBanner.vue +3 -3
  106. package/app/components/layout/TranslationWarningBanner.vue +1 -1
  107. package/app/components/layout/UiModeSwitcher.vue +7 -6
  108. package/app/components/layout/UiRoleSwitcher.vue +2 -2
  109. package/app/components/media/ArtifactLightbox.vue +6 -6
  110. package/app/components/media/ImageCompare.vue +16 -16
  111. package/app/components/merge/MergeEffortChips.vue +4 -6
  112. package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
  113. package/app/components/observability/OutcomeFilterChips.vue +1 -1
  114. package/app/components/observability/RunFailureSummary.vue +14 -17
  115. package/app/components/observability/StepMetricsBar.vue +9 -8
  116. package/app/components/observability/StepModelActivity.vue +4 -3
  117. package/app/components/observability/ToolCallList.vue +15 -18
  118. package/app/components/outcome/OutcomeSummaryWindow.vue +43 -42
  119. package/app/components/palettes/AgentPalette.vue +7 -5
  120. package/app/components/palettes/AgentTierSelect.vue +1 -1
  121. package/app/components/palettes/PipelinePurposeSelect.vue +2 -1
  122. package/app/components/panels/AgentStepDetail.vue +27 -30
  123. package/app/components/panels/AttemptEntryHeader.vue +2 -2
  124. package/app/components/panels/DecisionModal.vue +1 -1
  125. package/app/components/panels/GenericStructuredResultView.vue +6 -5
  126. package/app/components/panels/InspectorPanel.vue +15 -13
  127. package/app/components/panels/MergerResultView.vue +10 -9
  128. package/app/components/panels/ObservabilityPanel.vue +66 -76
  129. package/app/components/panels/OperatorDashboardPanel.vue +27 -26
  130. package/app/components/panels/ReportsPanel.vue +26 -25
  131. package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
  132. package/app/components/panels/ResultWindowShell.vue +19 -18
  133. package/app/components/panels/RunDetailLoadState.vue +1 -1
  134. package/app/components/panels/StepContainerStatus.vue +8 -7
  135. package/app/components/panels/StepDelegatedStatus.vue +13 -12
  136. package/app/components/panels/StepEffortReport.vue +12 -17
  137. package/app/components/panels/StepFragmentAdherence.vue +9 -10
  138. package/app/components/panels/StepMetadataCard.vue +41 -43
  139. package/app/components/panels/StepReproductionReport.vue +18 -20
  140. package/app/components/panels/StepRunMeta.vue +27 -26
  141. package/app/components/panels/StepTestReport.vue +16 -15
  142. package/app/components/panels/StepToolServers.vue +7 -8
  143. package/app/components/panels/StepValidationReport.vue +5 -5
  144. package/app/components/panels/inspector/ContainerSummary.vue +4 -4
  145. package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
  146. package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
  147. package/app/components/panels/inspector/EpicChildren.vue +8 -7
  148. package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
  149. package/app/components/panels/inspector/FrontendConfig.vue +26 -34
  150. package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
  151. package/app/components/panels/inspector/InspectorSection.vue +7 -4
  152. package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
  153. package/app/components/panels/inspector/ServiceConnections.vue +2 -2
  154. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
  155. package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
  156. package/app/components/panels/inspector/ServiceTestConfig.vue +41 -45
  157. package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
  158. package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
  159. package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
  160. package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
  161. package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
  162. package/app/components/panels/inspector/TaskDependencies.vue +1 -1
  163. package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
  164. package/app/components/panels/inspector/TaskExecution.vue +13 -12
  165. package/app/components/panels/inspector/TaskRunSettings.vue +35 -38
  166. package/app/components/panels/inspector/TaskStructure.vue +5 -4
  167. package/app/components/pipeline/AgentPromptEditor.vue +15 -14
  168. package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
  169. package/app/components/pipeline/EstimateThresholdFields.vue +2 -2
  170. package/app/components/pipeline/GateConfigFields.vue +6 -6
  171. package/app/components/pipeline/IterationCapPrompt.vue +1 -1
  172. package/app/components/pipeline/PipelineBuilder.vue +28 -27
  173. package/app/components/pipeline/PipelineHealthModal.vue +7 -7
  174. package/app/components/pipeline/PipelinePicker.vue +3 -3
  175. package/app/components/pipeline/PipelinePreview.vue +6 -7
  176. package/app/components/pipeline/PipelineProgress.vue +23 -24
  177. package/app/components/prReview/PrReviewWindow.vue +42 -41
  178. package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
  179. package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
  180. package/app/components/providers/ApiKeysSection.vue +7 -6
  181. package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
  182. package/app/components/providers/VendorCredentialsModal.vue +5 -4
  183. package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
  184. package/app/components/ralph/RalphLoopResultView.vue +25 -26
  185. package/app/components/requirements/RequirementsReviewWindow.vue +13 -12
  186. package/app/components/riskPolicy/RiskPolicyPicker.vue +5 -5
  187. package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
  188. package/app/components/sandbox/SandboxPanel.vue +21 -20
  189. package/app/components/settings/ApiTokensPanel.vue +1 -1
  190. package/app/components/settings/BudgetSettings.vue +18 -17
  191. package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
  192. package/app/components/settings/CloudflareHandlerSection.vue +16 -16
  193. package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
  194. package/app/components/settings/ConnectionTestVerdict.vue +1 -1
  195. package/app/components/settings/ConsensusGroupsSection.vue +21 -20
  196. package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
  197. package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
  198. package/app/components/settings/InfraHandlersConfigurator.vue +14 -15
  199. package/app/components/settings/InfrastructureBackendPicker.vue +2 -2
  200. package/app/components/settings/IssueTrackerPanel.vue +9 -15
  201. package/app/components/settings/KubernetesEngineForm.vue +9 -8
  202. package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
  203. package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
  204. package/app/components/settings/LocalModelEndpointsPanel.vue +10 -9
  205. package/app/components/settings/MergeClassRulesEditor.vue +6 -5
  206. package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
  207. package/app/components/settings/ModelConfigurationPanel.vue +8 -11
  208. package/app/components/settings/ModelPresetHealthModal.vue +3 -3
  209. package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
  210. package/app/components/settings/OpenRouterCatalogPanel.vue +6 -5
  211. package/app/components/settings/PackageRegistriesPanel.vue +4 -4
  212. package/app/components/settings/ProviderConnectionTab.vue +5 -4
  213. package/app/components/settings/ProviderManifestEditor.vue +9 -8
  214. package/app/components/settings/ProviderPreferenceEditor.vue +8 -7
  215. package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
  216. package/app/components/settings/RiskPolicyEditorRow.vue +18 -17
  217. package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
  218. package/app/components/settings/RiskPolicyPanel.vue +11 -13
  219. package/app/components/settings/ServiceFragmentDefaultsPanel.vue +5 -4
  220. package/app/components/settings/SharedStacksPanel.vue +5 -5
  221. package/app/components/settings/TaskSourceCard.vue +2 -2
  222. package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
  223. package/app/components/settings/ToolServerChecklist.vue +22 -22
  224. package/app/components/settings/UsageSettings.vue +13 -13
  225. package/app/components/settings/UserSecretsSection.vue +4 -3
  226. package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
  227. package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
  228. package/app/components/skills/ReviewSkillQueue.vue +8 -7
  229. package/app/components/skills/SkillLibraryManager.vue +2 -2
  230. package/app/components/slack/SlackPanel.vue +8 -7
  231. package/app/components/spec/ServiceSpecWindow.vue +15 -16
  232. package/app/components/tasks/BugHuntModal.vue +1 -1
  233. package/app/components/tasks/ContextIssuePicker.vue +4 -6
  234. package/app/components/tasks/TaskContextIssues.vue +1 -1
  235. package/app/components/tasks/TaskImportModal.vue +3 -2
  236. package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
  237. package/app/components/testing/TestReportWindow.vue +54 -53
  238. package/app/components/tutorial/TutorialNudge.vue +3 -2
  239. package/app/components/tutorial/TutorialOverlay.vue +3 -2
  240. package/app/components/vcs/GitLabConnect.vue +1 -1
  241. package/app/components/visualConfirm/VisualConfirmationWindow.vue +23 -25
  242. package/app/composables/usePipelineErrorToast.ts +2 -0
  243. package/app/utils/catalog.ts +8 -0
  244. package/app/utils/theme/builtins.ts +7 -1
  245. package/i18n/locales/de.json +6 -3
  246. package/i18n/locales/en.json +6 -3
  247. package/i18n/locales/es.json +6 -3
  248. package/i18n/locales/fr.json +6 -3
  249. package/i18n/locales/he.json +6 -3
  250. package/i18n/locales/it.json +6 -3
  251. package/i18n/locales/ja.json +6 -3
  252. package/i18n/locales/pl.json +6 -3
  253. package/i18n/locales/tr.json +6 -3
  254. package/i18n/locales/uk.json +6 -3
  255. package/package.json +2 -2
@@ -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
  {{
@@ -54,7 +54,7 @@ function commit(axis: EstimateAxis, raw: string) {
54
54
 
55
55
  <template>
56
56
  <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])">
57
+ <span class="text-3xs text-dimmed" :title="t(OUTCOME_HINT_KEYS[outcome])">
58
58
  {{ t('pipeline.builder.runWhenAny') }}
59
59
  </span>
60
60
  <template v-for="f in fields" :key="f.axis">
@@ -66,7 +66,7 @@ function commit(axis: EstimateAxis, raw: string) {
66
66
  min="0"
67
67
  max="1"
68
68
  step="0.1"
69
- class="w-14 rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
69
+ class="w-14 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-app-100"
70
70
  @change="commit(f.axis, ($event.target as HTMLInputElement).value)"
71
71
  />
72
72
  </template>
@@ -119,7 +119,7 @@ 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
124
  <label
125
125
  v-for="role in APPROVER_ROLES"
@@ -136,7 +136,7 @@ const gateFieldValues = computed<DescriptorFieldValues>({
136
136
  </label>
137
137
  </div>
138
138
 
139
- <div class="flex flex-wrap items-center gap-2 text-[10px]">
139
+ <div class="flex flex-wrap items-center gap-2 text-3xs">
140
140
  <span class="text-dimmed">{{ t('pipeline.gateConfig.namedApproversLabel') }}</span>
141
141
  <USelectMenu
142
142
  class="w-64"
@@ -151,7 +151,7 @@ const gateFieldValues = computed<DescriptorFieldValues>({
151
151
  />
152
152
  </div>
153
153
 
154
- <div class="flex flex-wrap items-center gap-2 text-[10px]">
154
+ <div class="flex flex-wrap items-center gap-2 text-3xs">
155
155
  <label class="text-dimmed" :title="t('pipeline.gateConfig.requiredApprovalsHint')">
156
156
  {{ t('pipeline.gateConfig.requiredApprovalsLabel') }}
157
157
  </label>
@@ -161,14 +161,14 @@ const gateFieldValues = computed<DescriptorFieldValues>({
161
161
  min="1"
162
162
  :max="MAX_GATE_APPROVALS"
163
163
  step="1"
164
- class="w-14 rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
164
+ class="w-14 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-app-100"
165
165
  data-testid="gate-required-approvals"
166
166
  @change="setRequiredApprovals(($event.target as HTMLInputElement).value)"
167
167
  />
168
168
  <span class="text-dimmed">{{ t('pipeline.gateConfig.requiredApprovalsHint') }}</span>
169
169
  </div>
170
170
 
171
- <p v-if="!config.approvers" class="text-[10px] text-dimmed">
171
+ <p v-if="!config.approvers" class="text-3xs text-dimmed">
172
172
  {{ t('pipeline.gateConfig.anyoneHint') }}
173
173
  </p>
174
174
  </div>
@@ -179,7 +179,7 @@ const gateFieldValues = computed<DescriptorFieldValues>({
179
179
  v-if="gateFields?.length"
180
180
  class="space-y-2 rounded-md border border-default bg-default/40 p-2"
181
181
  >
182
- <p class="text-[10px] text-dimmed">{{ t('pipeline.gateConfig.gateParametersLabel') }}</p>
182
+ <p class="text-3xs text-dimmed">{{ t('pipeline.gateConfig.gateParametersLabel') }}</p>
183
183
  <DescriptorFields
184
184
  v-model="gateFieldValues"
185
185
  :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"
@@ -28,6 +28,7 @@ import {
28
28
  mayCarrySkipAxis,
29
29
  } from '~/utils/catalog'
30
30
  import type { ConsensusStrategy } from '~/types/consensus'
31
+ import SectionLabel from '~/components/common/SectionLabel.vue'
31
32
 
32
33
  type DraftUnit = { index: number; kind: AgentKind; companionIndex: number | null }
33
34
 
@@ -423,9 +424,9 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
423
424
  data-testid="pipeline-builder-palette"
424
425
  >
425
426
  <div class="mb-2 flex shrink-0 items-center justify-between gap-2">
426
- <h3 class="text-xs font-semibold uppercase tracking-wide text-muted">
427
+ <SectionLabel as="h3">
427
428
  {{ t('pipeline.builder.agentPalette') }}
428
- </h3>
429
+ </SectionLabel>
429
430
  <UButton
430
431
  color="primary"
431
432
  variant="soft"
@@ -447,9 +448,9 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
447
448
  data-testid="pipeline-builder-draft"
448
449
  >
449
450
  <div class="mb-2 flex items-center justify-between gap-2">
450
- <h3 class="text-xs font-semibold uppercase tracking-wide text-muted">
451
+ <SectionLabel as="h3">
451
452
  {{ t('pipeline.builder.pipeline') }}
452
- </h3>
453
+ </SectionLabel>
453
454
  <UButton
454
455
  color="neutral"
455
456
  variant="soft"
@@ -497,7 +498,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
497
498
  <input
498
499
  v-model="newLabel"
499
500
  :placeholder="t('pipeline.builder.labelPlaceholder')"
500
- class="w-20 rounded border border-muted bg-default px-1.5 py-0.5 text-[11px] text-default focus:w-28"
501
+ class="w-20 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-2xs text-default focus:w-28"
501
502
  @keydown.enter.prevent="addLabel"
502
503
  @blur="addLabel"
503
504
  />
@@ -508,7 +509,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
508
509
  <p
509
510
  v-for="warning in draftWarnings"
510
511
  :key="warning.key"
511
- class="mb-2 flex items-center gap-1.5 rounded-md border border-app-warning-800/50 bg-app-warning-950/30 px-2 py-1 text-[11px] text-app-warning-300"
512
+ class="mb-2 flex items-center gap-1.5 rounded-md border border-app-warning-800/50 bg-app-warning-950/30 px-2 py-1 text-2xs text-app-warning-300"
512
513
  :data-testid="warning.testId"
513
514
  >
514
515
  <UIcon name="i-lucide-alert-triangle" class="h-3.5 w-3.5 shrink-0" />
@@ -533,7 +534,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
533
534
  :data-gated="pipelines.draftGates[unit.index] === true"
534
535
  >
535
536
  <div class="flex items-center gap-1.5">
536
- <span class="w-4 shrink-0 text-center text-[10px] text-dimmed">{{ vi + 1 }}</span>
537
+ <span class="w-4 shrink-0 text-center text-3xs text-dimmed">{{ vi + 1 }}</span>
537
538
  <AgentKindIcon :kind="unit.kind" icon-class="h-4 w-4" />
538
539
  <span
539
540
  class="min-w-0 flex-1 truncate text-xs text-app-100"
@@ -785,10 +786,10 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
785
786
  :disabled="!skillSelectItems.length"
786
787
  @update:model-value="pipelines.setDraftSkillId(unit.index, $event)"
787
788
  />
788
- <p v-if="!skillSelectItems.length" class="text-[10px] text-dimmed">
789
+ <p v-if="!skillSelectItems.length" class="text-3xs text-dimmed">
789
790
  {{ t('pipeline.builder.skillNoneAvailable') }}
790
791
  </p>
791
- <p v-else-if="skillMissing(unit.index)" class="text-[10px] text-app-warning-400">
792
+ <p v-else-if="skillMissing(unit.index)" class="text-3xs text-app-warning-400">
792
793
  {{ t('pipeline.builder.skillMissing') }}
793
794
  </p>
794
795
  </div>
@@ -801,7 +802,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
801
802
  v-if="showVariantPicker(unit.index, unit.kind)"
802
803
  class="ms-6 flex items-center gap-2"
803
804
  >
804
- <span class="text-[10px] text-dimmed">
805
+ <span class="text-3xs text-dimmed">
805
806
  {{ t('pipeline.builder.variantLabel') }}
806
807
  </span>
807
808
  <USelect
@@ -842,7 +843,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
842
843
  setting (itself an override of the deployment routing default), so it is
843
844
  advanced-only until a value is pinned; empty inherits. -->
844
845
  <div v-if="showOutputBudget(unit.index)" class="ms-6 flex items-center gap-2">
845
- <span class="text-[10px] text-dimmed">
846
+ <span class="text-3xs text-dimmed">
846
847
  {{ t('pipeline.outputBudget.stepLabel') }}
847
848
  </span>
848
849
  <OutputBudgetInput
@@ -934,7 +935,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
934
935
  <UIcon name="i-lucide-layers" class="h-3.5 w-3.5 text-app-success-400" />
935
936
  <span class="text-toned">{{ t('pipeline.builder.consensusGroups') }}</span>
936
937
  </div>
937
- <p class="text-[11px] text-dimmed">
938
+ <p class="text-2xs text-dimmed">
938
939
  {{ t('pipeline.builder.consensusGroupsHint') }}
939
940
  </p>
940
941
  <div class="flex flex-wrap gap-1">
@@ -942,7 +943,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
942
943
  v-for="group in consensusGroups.groups"
943
944
  :key="group.id"
944
945
  type="button"
945
- class="rounded border px-1.5 py-0.5 text-[11px]"
946
+ class="rounded-sm border px-1.5 py-0.5 text-2xs"
946
947
  :class="
947
948
  isGroupSelected(unit.index, group.id)
948
949
  ? 'border-app-success-600 bg-app-success-900/40 text-app-success-200'
@@ -957,7 +958,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
957
958
  </div>
958
959
  </div>
959
960
 
960
- <div v-if="usesGroups(unit.index)" class="text-[11px] text-dimmed">
961
+ <div v-if="usesGroups(unit.index)" class="text-2xs text-dimmed">
961
962
  {{ t('pipeline.builder.consensusGroupsActive') }}
962
963
  </div>
963
964
 
@@ -966,7 +967,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
966
967
  <label class="text-muted">{{ t('pipeline.builder.strategy') }}</label>
967
968
  <select
968
969
  v-model="pipelines.draftConsensus[unit.index]!.strategy"
969
- class="rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
970
+ class="rounded-sm border border-muted bg-default px-1.5 py-0.5 text-app-100"
970
971
  >
971
972
  <option v-for="s in CONSENSUS_STRATEGIES" :key="s.value" :value="s.value">
972
973
  {{ s.label }}
@@ -984,7 +985,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
984
985
  min="1"
985
986
  max="5"
986
987
  placeholder="2"
987
- class="w-12 rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
988
+ class="w-12 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-app-100"
988
989
  />
989
990
  </div>
990
991
 
@@ -998,12 +999,12 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
998
999
  <input
999
1000
  v-model="p.role"
1000
1001
  :placeholder="t('pipeline.builder.rolePlaceholder')"
1001
- class="w-28 rounded border border-muted bg-default px-1.5 py-0.5 text-app-100"
1002
+ class="w-28 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-app-100"
1002
1003
  />
1003
1004
  <input
1004
1005
  v-model="p.modelId"
1005
1006
  :placeholder="t('pipeline.builder.modelIdPlaceholder')"
1006
- class="flex-1 rounded border border-muted bg-default px-1.5 py-0.5 text-toned"
1007
+ class="flex-1 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-toned"
1007
1008
  />
1008
1009
  <UButton
1009
1010
  icon="i-lucide-x"
@@ -1103,9 +1104,9 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
1103
1104
  moved to the task card / inspector when the palettes were removed). -->
1104
1105
  <div v-if="pipelines.pipelines.length" class="flex flex-col lg:min-h-0 lg:overflow-hidden">
1105
1106
  <div class="mb-2 flex shrink-0 items-center justify-between gap-2">
1106
- <h3 class="text-xs font-semibold uppercase tracking-wide text-muted">
1107
+ <SectionLabel as="h3">
1107
1108
  {{ t('pipeline.builder.savedPipelines') }}
1108
- </h3>
1109
+ </SectionLabel>
1109
1110
  <UButton
1110
1111
  v-if="library.archivedInScope"
1111
1112
  :icon="showArchived ? 'i-lucide-archive-restore' : 'i-lucide-archive'"
@@ -1157,7 +1158,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
1157
1158
  narrows and whose every change is saved. -->
1158
1159
  <div
1159
1160
  v-if="browseEveryPurpose || library.hiddenByPurpose"
1160
- class="mb-2 flex shrink-0 flex-wrap items-center gap-x-2 px-1 text-[10px] text-dimmed"
1161
+ class="mb-2 flex shrink-0 flex-wrap items-center gap-x-2 px-1 text-3xs text-dimmed"
1161
1162
  >
1162
1163
  <span>
1163
1164
  {{
@@ -1249,7 +1250,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
1249
1250
  >
1250
1251
  {{ t('pipeline.builder.scopeDefault.unattended') }}
1251
1252
  </UBadge>
1252
- <span class="shrink-0 text-[10px] text-dimmed">
1253
+ <span class="shrink-0 text-3xs text-dimmed">
1253
1254
  {{
1254
1255
  t(
1255
1256
  'pipeline.builder.stepCount',
@@ -1356,7 +1357,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
1356
1357
  p.enabled?.[i] === false ? t('pipeline.builder.disabledStepTooltip') : undefined
1357
1358
  "
1358
1359
  >
1359
- <span class="w-4 shrink-0 text-center text-[10px] text-dimmed">{{ i + 1 }}</span>
1360
+ <span class="w-4 shrink-0 text-center text-3xs text-dimmed">{{ i + 1 }}</span>
1360
1361
  <AgentKindIcon :kind="k" show-label />
1361
1362
  <!-- A step that does not run on every task says so HERE, in the library, because
1362
1363
  this list is what a reader compares two pipelines by: a preset whose testers
@@ -1400,9 +1401,9 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
1400
1401
  <template #body>
1401
1402
  <div class="space-y-3">
1402
1403
  <div>
1403
- <label class="mb-1 block text-[11px] font-semibold uppercase tracking-wide text-muted">
1404
+ <SectionLabel as="label" class="mb-1 block">
1404
1405
  {{ t('pipeline.builder.addAgentModal.name') }}
1405
- </label>
1406
+ </SectionLabel>
1406
1407
  <UInput
1407
1408
  v-model="newAgentName"
1408
1409
  :placeholder="t('pipeline.builder.addAgentModal.namePlaceholder')"
@@ -1411,9 +1412,9 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
1411
1412
  />
1412
1413
  </div>
1413
1414
  <div>
1414
- <label class="mb-1 block text-[11px] font-semibold uppercase tracking-wide text-muted">
1415
+ <SectionLabel as="label" class="mb-1 block">
1415
1416
  {{ t('pipeline.builder.addAgentModal.description') }}
1416
- </label>
1417
+ </SectionLabel>
1417
1418
  <UTextarea
1418
1419
  v-model="newAgentDesc"
1419
1420
  :rows="2"