@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
@@ -6,6 +6,7 @@ import AgentTierSelect from '~/components/palettes/AgentTierSelect.vue'
6
6
  import PipelinePurposeSelect from '~/components/palettes/PipelinePurposeSelect.vue'
7
7
  import { groupAgentPalette, narrowAgentPalette } from '~/utils/agentPalette'
8
8
  import { AGENT_CATEGORIES, OBSERVABILITY_GATE_ARCHETYPE } from '~/utils/catalog'
9
+ import SectionLabel from '~/components/common/SectionLabel.vue'
9
10
 
10
11
  const { t } = useI18n()
11
12
  const agents = useAgentsStore()
@@ -57,7 +58,7 @@ function toggle(id: string) {
57
58
 
58
59
  <template>
59
60
  <div class="space-y-2">
60
- <p class="px-1 text-[11px] text-dimmed">{{ t('palette.hint') }}</p>
61
+ <p class="px-1 text-2xs text-dimmed">{{ t('palette.hint') }}</p>
61
62
  <!-- The two catalog dials, one above the other: what this pipeline is for, and how deep into
62
63
  the agent catalog to look. Both narrow the sections below, and each states its own count.
63
64
  Stacked rather than side by side because the palette column is a third of the slideover:
@@ -73,9 +74,10 @@ function toggle(id: string) {
73
74
  </div>
74
75
  <div class="space-y-2">
75
76
  <section v-for="g in groups" :key="g.id">
76
- <button
77
+ <SectionLabel
78
+ as="button"
77
79
  type="button"
78
- class="flex w-full items-center gap-1.5 rounded px-1 py-1 text-start text-[11px] font-semibold uppercase tracking-wide text-muted transition hover:text-default"
80
+ class="flex w-full items-center gap-1.5 rounded-sm px-1 py-1 text-start transition hover:text-default"
79
81
  @click="toggle(g.id)"
80
82
  >
81
83
  <UIcon
@@ -84,7 +86,7 @@ function toggle(id: string) {
84
86
  />
85
87
  <span>{{ g.label }}</span>
86
88
  <span class="ms-auto text-app-600">{{ g.agents.length }}</span>
87
- </button>
89
+ </SectionLabel>
88
90
  <div v-if="!isCollapsed(g.id)" class="mt-1 space-y-1.5">
89
91
  <button
90
92
  v-for="a in g.agents"
@@ -103,7 +105,7 @@ function toggle(id: string) {
103
105
  </div>
104
106
  <div class="min-w-0">
105
107
  <div class="text-xs font-semibold text-app-100">{{ a.label }}</div>
106
- <div class="truncate text-[10px] text-muted">{{ a.description }}</div>
108
+ <div class="truncate text-3xs text-muted">{{ a.description }}</div>
107
109
  </div>
108
110
  <UIcon name="i-lucide-plus" class="ms-auto h-4 w-4 shrink-0 text-dimmed" />
109
111
  </button>
@@ -60,7 +60,7 @@ const items = computed(() => [
60
60
  </span>
61
61
  </UButton>
62
62
  </UDropdownMenu>
63
- <p v-if="props.hiddenCount" class="px-1 text-[10px] text-dimmed">
63
+ <p v-if="props.hiddenCount" class="px-1 text-3xs text-dimmed">
64
64
  {{ t('agentTier.hidden', { count: props.hiddenCount }, props.hiddenCount) }}
65
65
  </p>
66
66
  </div>
@@ -31,6 +31,7 @@ const PURPOSE_LABELS = computed<Record<PipelinePurpose, string>>(() => ({
31
31
  research: t('pipeline.builder.purposeOption.research'),
32
32
  planning: t('pipeline.builder.purposeOption.planning'),
33
33
  media: t('pipeline.builder.purposeOption.media'),
34
+ maintenance: t('pipeline.builder.purposeOption.maintenance'),
34
35
  }))
35
36
 
36
37
  // The button text. A stored purpose this build has no label for is NAMED as unrecognised and
@@ -71,7 +72,7 @@ const items = computed(() => [
71
72
  <span class="truncate"> {{ t('pipeline.builder.purposeLabel') }}: {{ current }} </span>
72
73
  </UButton>
73
74
  </UDropdownMenu>
74
- <p v-if="props.hiddenCount" class="px-1 text-[10px] text-dimmed">
75
+ <p v-if="props.hiddenCount" class="px-1 text-3xs text-dimmed">
75
76
  {{ t('palette.purposeHidden', { count: props.hiddenCount }, props.hiddenCount) }}
76
77
  </p>
77
78
  </div>
@@ -29,6 +29,7 @@ import {
29
29
  } from '~/utils/pipelineRender'
30
30
  import InputGateNotice from '~/components/inputGate/InputGateNotice.vue'
31
31
  import RunDetailLoadState from '~/components/panels/RunDetailLoadState.vue'
32
+ import SectionLabel from '~/components/common/SectionLabel.vue'
32
33
 
33
34
  // Detail overlay for a single pipeline step. Opened by clicking an agent in the
34
35
  // inspector list (TaskExecution) or the focus-view pipeline (PipelineProgress) via
@@ -402,13 +403,13 @@ async function copyOutput() {
402
403
  class="hidden w-72 shrink-0 flex-col border-e border-default bg-default/60 md:flex"
403
404
  >
404
405
  <div class="border-b border-default px-4 py-3">
405
- <div class="text-[11px] font-semibold uppercase tracking-wide text-dimmed">
406
+ <SectionLabel>
406
407
  {{ t('panels.stepDetail.contents') }}
407
- </div>
408
+ </SectionLabel>
408
409
  </div>
409
410
  <nav class="flex-1 space-y-0.5 overflow-auto px-2 py-3">
410
411
  <button
411
- class="block w-full truncate rounded-md px-2 py-1 text-start text-[13px] transition"
412
+ class="block w-full truncate rounded-md px-2 py-1 text-start text-sm transition"
412
413
  :class="
413
414
  activeId === 'step-details'
414
415
  ? 'bg-primary/15 font-medium text-primary'
@@ -421,7 +422,7 @@ async function copyOutput() {
421
422
  <button
422
423
  v-for="s in tocSections"
423
424
  :key="s.id"
424
- class="block w-full truncate rounded-md px-2 py-1 text-start text-[13px] transition"
425
+ class="block w-full truncate rounded-md px-2 py-1 text-start text-sm transition"
425
426
  :class="
426
427
  activeId === s.id
427
428
  ? 'bg-primary/15 font-medium text-primary'
@@ -603,7 +604,7 @@ async function copyOutput() {
603
604
  data-testid="dedicated-park-redirect"
604
605
  :data-park="dedicatedPark"
605
606
  >
606
- <p class="text-[13px] leading-relaxed text-app-warning-200/90">
607
+ <p class="text-sm leading-relaxed text-app-warning-200/90">
607
608
  {{ t(parkPresentation.noticeKey) }}
608
609
  </p>
609
610
  <UButton
@@ -640,7 +641,7 @@ async function copyOutput() {
640
641
  <li
641
642
  v-for="(note, i) in runNotes"
642
643
  :key="i"
643
- class="flex items-start gap-1.5 text-[11px] leading-snug text-app-warning-300/80"
644
+ class="flex items-start gap-1.5 text-2xs leading-snug text-app-warning-300/80"
644
645
  >
645
646
  <UIcon name="i-lucide-info" class="mt-0.5 h-3.5 w-3.5 shrink-0" />
646
647
  <span>{{ note }}</span>
@@ -755,7 +756,7 @@ async function copyOutput() {
755
756
  <!-- edit-then-approve: a direct editor over the raw conclusions; the
756
757
  edits become the approved proposal that flows to the next step -->
757
758
  <section v-if="editing" class="scroll-mt-4">
758
- <div class="mb-2 flex items-center gap-1.5 text-[11px] text-app-warning-400">
759
+ <div class="mb-2 flex items-center gap-1.5 text-2xs text-app-warning-400">
759
760
  <UIcon name="i-lucide-pencil" class="h-3.5 w-3.5" />
760
761
  <span class="font-semibold uppercase tracking-wide">{{
761
762
  t('panels.stepDetail.editingConclusions')
@@ -767,7 +768,7 @@ async function copyOutput() {
767
768
  autoresize
768
769
  size="sm"
769
770
  class="w-full"
770
- :ui="{ base: 'font-mono text-[12px] leading-relaxed' }"
771
+ :ui="{ base: 'font-mono text-xs leading-relaxed' }"
771
772
  :placeholder="t('panels.stepDetail.editConclusionsPlaceholder')"
772
773
  />
773
774
  </section>
@@ -800,7 +801,7 @@ async function copyOutput() {
800
801
  <!-- eslint-disable-next-line vue/no-v-html -->
801
802
  <div
802
803
  v-show="!collapsed[s.id]"
803
- class="reader-prose mt-1 text-[13px] leading-relaxed text-toned"
804
+ class="reader-prose mt-1 text-sm leading-relaxed text-toned"
804
805
  :class="[
805
806
  s.depth > 0 ? 'ps-6' : '',
806
807
  genericApprovalPending && !editing ? 'review-mode' : '',
@@ -829,25 +830,21 @@ async function copyOutput() {
829
830
  class="absolute inset-x-0 bottom-0 z-10 flex max-h-[70dvh] flex-col rounded-t-2xl border-t border-muted bg-default/95 shadow-2xl backdrop-blur lg:static lg:inset-auto lg:z-auto lg:max-h-none lg:w-96 lg:shrink-0 lg:rounded-none lg:border-s lg:border-t-0 lg:border-default lg:bg-default/60 lg:shadow-none lg:backdrop-blur-none"
830
831
  >
831
832
  <div class="border-b border-default px-4 py-3">
832
- <div class="text-[11px] font-semibold uppercase tracking-wide text-app-warning-400">
833
+ <div class="text-2xs font-semibold uppercase tracking-wide text-app-warning-400">
833
834
  {{
834
835
  editing
835
836
  ? t('panels.stepDetail.approveWithCorrections')
836
837
  : t('panels.stepDetail.reviewAndApprove')
837
838
  }}
838
839
  </div>
839
- <p class="mt-1 text-[12px] text-muted">
840
+ <p class="mt-1 text-xs text-muted">
840
841
  {{ editing ? t('panels.stepDetail.editHint') : t('panels.stepDetail.reviewHint') }}
841
842
  </p>
842
843
  <!-- The gate's configured POLICY, when it has one. Both lines exist because an
843
844
  approve on such a gate legitimately may not advance the run: without the tally, a
844
845
  correctly-recorded approval is indistinguishable from a call that failed, and
845
846
  without the refusal a person would press a button the server answers 403. -->
846
- <p
847
- v-if="gateQuorum"
848
- class="mt-1 text-[12px] text-app-warning-300/90"
849
- data-testid="gate-quorum"
850
- >
847
+ <p v-if="gateQuorum" class="mt-1 text-xs text-app-warning-300/90" data-testid="gate-quorum">
851
848
  {{
852
849
  t('panels.stepDetail.quorumProgress', {
853
850
  recorded: gateQuorum.recorded,
@@ -856,7 +853,7 @@ async function copyOutput() {
856
853
  }}
857
854
  <span v-if="viewerHasApproved">{{ t('panels.stepDetail.quorumYours') }}</span>
858
855
  </p>
859
- <p v-if="gateRefusal" class="mt-1 text-[12px] text-muted" data-testid="gate-not-approver">
856
+ <p v-if="gateRefusal" class="mt-1 text-xs text-muted" data-testid="gate-not-approver">
860
857
  {{ t(GATE_REFUSAL_KEYS[gateRefusal]) }}
861
858
  </p>
862
859
  </div>
@@ -864,7 +861,7 @@ async function copyOutput() {
864
861
  <div class="flex-1 space-y-3 overflow-auto overscroll-contain px-4 py-3">
865
862
  <p
866
863
  v-if="editing"
867
- class="rounded-lg border border-app-warning-500/30 bg-app-warning-500/5 p-3 text-[12px] leading-relaxed text-app-warning-200/90"
864
+ class="rounded-lg border border-app-warning-500/30 bg-app-warning-500/5 p-3 text-xs leading-relaxed text-app-warning-200/90"
868
865
  >
869
866
  {{ t('panels.stepDetail.editingNotice') }}
870
867
  </p>
@@ -875,11 +872,11 @@ async function copyOutput() {
875
872
  data-testid="step-review-composer"
876
873
  class="rounded-lg border border-primary/40 bg-primary/5 p-3"
877
874
  >
878
- <div class="mb-1 text-[10px] uppercase tracking-wide text-primary">
875
+ <div class="mb-1 text-3xs uppercase tracking-wide text-primary">
879
876
  {{ t('panels.stepDetail.commentingOn') }}
880
877
  </div>
881
878
  <pre
882
- class="mb-2 max-h-24 overflow-auto whitespace-pre-wrap rounded bg-app-950/60 p-2 text-[11px] text-toned"
879
+ class="mb-2 max-h-24 overflow-auto whitespace-pre-wrap rounded-sm bg-app-950/60 p-2 text-2xs text-toned"
883
880
  >{{ draftTarget.quotedSource }}</pre>
884
881
  <UTextarea
885
882
  v-model="draftBody"
@@ -914,9 +911,9 @@ async function copyOutput() {
914
911
  class="rounded-lg border border-default bg-default/50 p-3"
915
912
  >
916
913
  <div class="mb-1 flex items-start justify-between gap-2">
917
- <div class="text-[10px] uppercase tracking-wide text-dimmed">
914
+ <SectionLabel>
918
915
  {{ t('panels.stepDetail.commentN', { number: idx + 1 }) }}
919
- </div>
916
+ </SectionLabel>
920
917
  <button
921
918
  class="text-dimmed transition hover:text-app-error-400"
922
919
  :title="t('panels.stepDetail.removeComment')"
@@ -926,15 +923,15 @@ async function copyOutput() {
926
923
  </button>
927
924
  </div>
928
925
  <pre
929
- class="mb-1 max-h-20 overflow-auto whitespace-pre-wrap rounded bg-app-950/50 p-1.5 text-[10px] text-muted"
926
+ class="mb-1 max-h-20 overflow-auto whitespace-pre-wrap rounded-sm bg-app-950/50 p-1.5 text-3xs text-muted"
930
927
  >{{ c.quotedSource }}</pre>
931
- <p class="text-[12px] text-default">{{ c.body }}</p>
928
+ <p class="text-xs text-default">{{ c.body }}</p>
932
929
  </div>
933
930
 
934
931
  <div>
935
- <label class="mb-1 block text-[11px] font-semibold uppercase tracking-wide text-muted">
932
+ <SectionLabel as="label" class="mb-1 block">
936
933
  {{ t('panels.stepDetail.overallFeedback') }}
937
- </label>
934
+ </SectionLabel>
938
935
  <UTextarea
939
936
  v-model="feedback"
940
937
  data-testid="step-review-feedback"
@@ -1005,14 +1002,14 @@ async function copyOutput() {
1005
1002
  </UButton>
1006
1003
  <p
1007
1004
  v-else-if="!proposalEditable"
1008
- class="text-[10px] text-dimmed"
1005
+ class="text-3xs text-dimmed"
1009
1006
  data-testid="step-rendered-output-note"
1010
1007
  >
1011
1008
  {{ t('panels.stepDetail.renderedOutputNote') }}
1012
1009
  </p>
1013
1010
  <!-- Withheld only until the quorum is one approval away, so it says so rather than
1014
1011
  leaving a reviewer to wonder where the affordance went. -->
1015
- <p v-else class="text-[10px] text-dimmed" data-testid="step-quorum-edit-locked">
1012
+ <p v-else class="text-3xs text-dimmed" data-testid="step-quorum-edit-locked">
1016
1013
  {{ t('panels.stepDetail.quorumEditLocked') }}
1017
1014
  </p>
1018
1015
 
@@ -1021,7 +1018,7 @@ async function copyOutput() {
1021
1018
  v-if="rejectArmed"
1022
1019
  class="rounded-lg border border-app-error-500/40 bg-app-error-500/5 p-2.5"
1023
1020
  >
1024
- <p class="mb-2 text-[11px] text-app-error-200">
1021
+ <p class="mb-2 text-2xs text-app-error-200">
1025
1022
  {{ t('panels.stepDetail.rejectConfirmPrompt') }}
1026
1023
  </p>
1027
1024
  <div class="flex gap-2">
@@ -1073,7 +1070,7 @@ async function copyOutput() {
1073
1070
  {{ t('panels.stepDetail.reject') }}
1074
1071
  </UButton>
1075
1072
  </div>
1076
- <p class="text-[10px] text-dimmed">
1073
+ <p class="text-3xs text-dimmed">
1077
1074
  {{ t('panels.stepDetail.requestChangesHint') }}
1078
1075
  </p>
1079
1076
  </div>
@@ -23,11 +23,11 @@ function formatClock(ms: number | null | undefined, fmt: 'short' | 'long'): stri
23
23
  <template>
24
24
  <div class="flex items-center gap-2">
25
25
  <UIcon v-if="icon" :name="icon" class="h-3.5 w-3.5 shrink-0" :class="iconClass" />
26
- <span class="text-[13px] font-medium text-default">{{ label }}</span>
26
+ <span class="text-sm font-medium text-default">{{ label }}</span>
27
27
  <UBadge :color="outcome === 'failed' ? 'error' : 'neutral'" variant="subtle" size="sm">{{
28
28
  outcomeLabel
29
29
  }}</UBadge>
30
- <span v-if="formatClock(at, dateFormat ?? 'short')" class="ms-auto text-[11px] text-dimmed">{{
30
+ <span v-if="formatClock(at, dateFormat ?? 'short')" class="ms-auto text-2xs text-dimmed">{{
31
31
  formatClock(at, dateFormat ?? 'short')
32
32
  }}</span>
33
33
  </div>
@@ -93,7 +93,7 @@ async function choose(option: string) {
93
93
  {{ opt }}
94
94
  </UButton>
95
95
  </div>
96
- <p class="text-[11px] text-dimmed">
96
+ <p class="text-2xs text-dimmed">
97
97
  {{ t('panels.decision.visualizationHint') }}
98
98
  </p>
99
99
  </div>
@@ -11,6 +11,7 @@ import StepRunMeta from '~/components/panels/StepRunMeta.vue'
11
11
  import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
12
12
  import MarkdownProse from '~/components/common/MarkdownProse.vue'
13
13
  import CopyButton from '~/components/common/CopyButton.vue'
14
+ import SectionLabel from '~/components/common/SectionLabel.vue'
14
15
 
15
16
  const board = useBoardStore()
16
17
  const execution = useExecutionStore()
@@ -71,18 +72,18 @@ const customJson = computed<string | null>(() => {
71
72
  <MarkdownProse
72
73
  v-if="step?.output"
73
74
  :text="step.output"
74
- class="mb-4 text-[13px] leading-relaxed text-toned"
75
+ class="mb-4 text-sm leading-relaxed text-toned"
75
76
  />
76
77
 
77
78
  <template v-if="customJson">
78
79
  <div class="mb-2 flex items-center gap-2">
79
- <h3 class="text-[11px] font-semibold uppercase tracking-wide text-dimmed">
80
+ <SectionLabel as="h3">
80
81
  {{ t('panels.structuredResult.structuredOutput') }}
81
- </h3>
82
+ </SectionLabel>
82
83
  <CopyButton :text="customJson" class="-my-1" />
83
84
  </div>
84
85
  <pre
85
- class="overflow-x-auto rounded-lg border border-default bg-app-950/60 p-3 text-[12px] leading-relaxed text-default"
86
+ class="overflow-x-auto rounded-lg border border-default bg-app-950/60 p-3 text-xs leading-relaxed text-default"
86
87
  ><code>{{ customJson }}</code></pre>
87
88
  </template>
88
89
 
@@ -92,7 +93,7 @@ const customJson = computed<string | null>(() => {
92
93
  >
93
94
  <UIcon name="i-lucide-braces" class="h-8 w-8 opacity-40" />
94
95
  <p class="text-sm">{{ t('panels.structuredResult.noResult') }}</p>
95
- <p class="max-w-sm text-[11px] text-dimmed">
96
+ <p class="max-w-sm text-2xs text-dimmed">
96
97
  {{ t('panels.structuredResult.noResultHint') }}
97
98
  </p>
98
99
  </div>
@@ -10,6 +10,7 @@ import AgentStopButton from '~/components/board/AgentStopButton.vue'
10
10
  import BootstrapRunSteps from '~/components/bootstrap/BootstrapRunSteps.vue'
11
11
  import { BLUEPRINT_AGENT_KIND } from '@cat-factory/contracts'
12
12
  import { VCS_PROVIDER_ICONS } from '~/utils/vcs'
13
+ import SectionLabel from '~/components/common/SectionLabel.vue'
13
14
 
14
15
  const board = useBoardStore()
15
16
  const pipelines = usePipelinesStore()
@@ -368,7 +369,10 @@ const showOriginalDescription = ref(false)
368
369
  <UBadge :color="statusMeta.chip" variant="subtle" size="sm">
369
370
  {{ statusLabel }}
370
371
  </UBadge>
371
- <span class="text-[10px] uppercase tracking-wide text-dimmed">{{ level }}</span>
372
+ <!-- The block's LEVEL, beside its status chip: a category this block is in, not a
373
+ heading over what follows, so it keeps its own classes rather than adopting the
374
+ eyebrow recipe (`common/SectionLabel.vue`). -->
375
+ <span class="text-3xs uppercase tracking-wide text-dimmed">{{ level }}</span>
372
376
  </div>
373
377
  </div>
374
378
  </div>
@@ -403,16 +407,16 @@ const showOriginalDescription = ref(false)
403
407
  <template v-if="frozenByRework">
404
408
  <div class="rounded-lg border border-app-success-900/60 bg-app-success-950/20 p-3">
405
409
  <div
406
- class="mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-app-success-400"
410
+ class="mb-1.5 flex items-center gap-1.5 text-2xs font-semibold uppercase tracking-wide text-app-success-400"
407
411
  >
408
412
  <UIcon name="i-lucide-file-check-2" class="h-3.5 w-3.5" />
409
413
  {{ t('panels.inspector.reworkedRequirements') }}
410
414
  </div>
411
- <p class="line-clamp-5 whitespace-pre-line text-[13px] leading-relaxed text-toned">
415
+ <p class="line-clamp-5 whitespace-pre-line text-sm leading-relaxed text-toned">
412
416
  {{ reqReworkedText }}
413
417
  </p>
414
418
  <div class="mt-2 flex items-center justify-between gap-2">
415
- <p class="text-[11px] text-dimmed">
419
+ <p class="text-2xs text-dimmed">
416
420
  {{ t('panels.inspector.agentStepsUseDocument') }}
417
421
  </p>
418
422
  <UButton
@@ -464,23 +468,21 @@ const showOriginalDescription = ref(false)
464
468
  @change="saveDescription"
465
469
  @blur="saveDescription"
466
470
  />
467
- <p v-if="isTask && !editable" class="flex items-center gap-1 text-[11px] text-dimmed">
471
+ <p v-if="isTask && !editable" class="flex items-center gap-1 text-2xs text-dimmed">
468
472
  <UIcon name="i-lucide-lock" class="h-3 w-3" />
469
473
  {{ t('panels.inspector.taskStartedLocked') }}
470
474
  </p>
471
475
 
472
476
  <!-- prior incorporated requirements kept as a base after a review-driven reset -->
473
477
  <div v-if="reqHasPriorDoc" class="rounded-lg border border-muted bg-elevated/40 p-3">
474
- <div
475
- class="mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
476
- >
478
+ <SectionLabel class="mb-1.5 flex items-center gap-1.5">
477
479
  <UIcon name="i-lucide-history" class="h-3.5 w-3.5" />
478
480
  {{ t('panels.inspector.lastIncorporatedRequirements') }}
479
- </div>
480
- <p class="line-clamp-5 whitespace-pre-line text-[13px] leading-relaxed text-toned">
481
+ </SectionLabel>
482
+ <p class="line-clamp-5 whitespace-pre-line text-sm leading-relaxed text-toned">
481
483
  {{ reqReworkedText }}
482
484
  </p>
483
- <p class="mt-2 text-[11px] text-dimmed">
485
+ <p class="mt-2 text-2xs text-dimmed">
484
486
  {{ t('panels.inspector.priorDocHint') }}
485
487
  </p>
486
488
  </div>
@@ -586,7 +588,7 @@ const showOriginalDescription = ref(false)
586
588
  >
587
589
  {{ t('panels.inspector.mapService') }}
588
590
  </UButton>
589
- <p v-if="isFrame && !serviceRepo" class="text-[11px] text-dimmed">
591
+ <p v-if="isFrame && !serviceRepo" class="text-2xs text-dimmed">
590
592
  {{ t('panels.inspector.mapServiceNoRepo') }}
591
593
  </p>
592
594
 
@@ -613,7 +615,7 @@ const showOriginalDescription = ref(false)
613
615
  on a disabled button doesn't fire hover events. -->
614
616
  <p
615
617
  v-if="isTask && runBlockedReason"
616
- class="flex items-start gap-1.5 text-[11px] text-app-warning-300/90"
618
+ class="flex items-start gap-1.5 text-2xs text-app-warning-300/90"
617
619
  data-testid="run-blocked-reason"
618
620
  >
619
621
  <UIcon name="i-lucide-lock" class="mt-px h-3 w-3 shrink-0" />
@@ -11,6 +11,7 @@ import type { ChangeClass, MergeAxis, MergeDecision, WorkspaceRole } from '@cat-
11
11
  import StepRunMeta from '~/components/panels/StepRunMeta.vue'
12
12
  import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
13
13
  import MarkdownProse from '~/components/common/MarkdownProse.vue'
14
+ import SectionLabel from '~/components/common/SectionLabel.vue'
14
15
 
15
16
  const board = useBoardStore()
16
17
  const execution = useExecutionStore()
@@ -217,15 +218,15 @@ const reasonText = computed(() => {
217
218
  {{ changeClassLabel }}
218
219
  </UBadge>
219
220
  </div>
220
- <p class="mt-0.5 text-[13px] leading-relaxed text-toned">{{ reasonText }}</p>
221
+ <p class="mt-0.5 text-sm leading-relaxed text-toned">{{ reasonText }}</p>
221
222
  </div>
222
223
  </div>
223
224
 
224
225
  <!-- Scores vs the resolved preset's ceilings. -->
225
226
  <template v-if="axes.length">
226
- <h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
227
+ <SectionLabel as="h3" class="mb-2">
227
228
  {{ t('panels.mergerResult.scores') }}
228
- </h3>
229
+ </SectionLabel>
229
230
  <div class="space-y-2 rounded-lg border border-default bg-app-950/40 p-3">
230
231
  <div v-for="axis in axes" :key="axis.key" class="flex items-center gap-2">
231
232
  <span class="w-20 shrink-0 text-xs text-muted">{{ axis.label }}</span>
@@ -242,7 +243,7 @@ const reasonText = computed(() => {
242
243
  >
243
244
  {{ n(axis.score, { key: 'percent' }) }}
244
245
  </span>
245
- <span class="w-24 shrink-0 text-end text-[10px] tabular-nums text-dimmed">
246
+ <span class="w-24 shrink-0 text-end text-3xs tabular-nums text-dimmed">
246
247
  {{
247
248
  t('panels.mergerResult.ceiling', {
248
249
  value: n(axis.ceiling, { key: 'percent' }),
@@ -255,15 +256,15 @@ const reasonText = computed(() => {
255
256
 
256
257
  <!-- The agent's prose justification. -->
257
258
  <template v-if="decision.assessment?.rationale">
258
- <h3 class="mb-2 mt-4 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
259
+ <SectionLabel as="h3" class="mb-2 mt-4">
259
260
  {{ t('panels.mergerResult.rationale') }}
260
- </h3>
261
+ </SectionLabel>
261
262
  <MarkdownProse
262
263
  :text="decision.assessment.rationale"
263
- class="text-[13px] leading-relaxed text-toned"
264
+ class="text-sm leading-relaxed text-toned"
264
265
  />
265
266
  </template>
266
- <p v-else class="text-[13px] italic leading-relaxed text-dimmed">
267
+ <p v-else class="text-sm italic leading-relaxed text-dimmed">
267
268
  {{ t('panels.mergerResult.noAssessment') }}
268
269
  </p>
269
270
  </template>
@@ -272,7 +273,7 @@ const reasonText = computed(() => {
272
273
  <MarkdownProse
273
274
  v-else-if="step?.output"
274
275
  :text="step.output"
275
- class="text-[13px] leading-relaxed text-toned"
276
+ class="text-sm leading-relaxed text-toned"
276
277
  />
277
278
  <div
278
279
  v-else