@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
@@ -22,6 +22,7 @@ import type {
22
22
  ProvisioningOutcome,
23
23
  ProvisioningSubsystem,
24
24
  } from '~/types/provisioningLogs'
25
+ import SectionLabel from '~/components/common/SectionLabel.vue'
25
26
 
26
27
  const props = defineProps<{
27
28
  subsystem?: ProvisioningSubsystem
@@ -115,9 +116,9 @@ function when(epochMs: number): string {
115
116
  <template>
116
117
  <div class="rounded-lg border border-muted bg-default/50">
117
118
  <div class="flex items-center justify-between border-b border-default px-3 py-2">
118
- <p class="text-[11px] font-semibold uppercase tracking-wide text-muted">
119
+ <SectionLabel as="p">
119
120
  {{ t('provisioning.title') }}
120
- </p>
121
+ </SectionLabel>
121
122
  <UButton
122
123
  icon="i-lucide-rotate-ccw"
123
124
  variant="ghost"
@@ -129,17 +130,17 @@ function when(epochMs: number): string {
129
130
  </UButton>
130
131
  </div>
131
132
 
132
- <p v-if="state.error" class="px-3 py-2 text-[12px] text-app-error-300">{{ state.error }}</p>
133
+ <p v-if="state.error" class="px-3 py-2 text-xs text-app-error-300">{{ state.error }}</p>
133
134
  <p
134
135
  v-else-if="!state.loading && state.entries.length === 0"
135
- class="px-3 py-3 text-[12px] text-dimmed"
136
+ class="px-3 py-3 text-xs text-dimmed"
136
137
  >
137
138
  {{ t('provisioning.empty') }}
138
139
  </p>
139
140
 
140
141
  <ul v-else class="max-h-80 divide-y divide-default overflow-auto">
141
142
  <li v-for="entry in state.entries" :key="entry.id" class="px-3 py-2">
142
- <div class="flex items-center gap-2 text-[12px]">
143
+ <div class="flex items-center gap-2 text-xs">
143
144
  <UIcon
144
145
  :name="entry.outcome === 'success' ? 'i-lucide-check-circle' : 'i-lucide-x-circle'"
145
146
  class="h-3.5 w-3.5 shrink-0"
@@ -147,7 +148,7 @@ function when(epochMs: number): string {
147
148
  />
148
149
  <span class="font-medium text-default">{{ OPERATION_LABEL[entry.operation] }}</span>
149
150
  <span
150
- class="rounded px-1.5 py-0.5 text-[10px] uppercase tracking-wide"
151
+ class="rounded-sm px-1.5 py-0.5 text-3xs uppercase tracking-wide"
151
152
  :class="
152
153
  entry.outcome === 'success'
153
154
  ? 'bg-app-success-950/60 text-app-success-300'
@@ -155,15 +156,15 @@ function when(epochMs: number): string {
155
156
  "
156
157
  >{{ OUTCOME_LABEL[entry.outcome] }}</span
157
158
  >
158
- <span class="ms-auto text-[11px] text-dimmed">{{ when(entry.createdAt) }}</span>
159
+ <span class="ms-auto text-2xs text-dimmed">{{ when(entry.createdAt) }}</span>
159
160
  </div>
160
- <div v-if="entry.targetId" class="mt-0.5 text-[11px] text-dimmed">
161
+ <div v-if="entry.targetId" class="mt-0.5 text-2xs text-dimmed">
161
162
  {{ entry.providerId ? `${entry.providerId} · ` : '' }}{{ entry.targetId }}
162
163
  </div>
163
164
  <!-- The verbatim provider/runtime error on a failed attempt. -->
164
165
  <pre
165
166
  v-if="entry.error"
166
- class="mt-1 max-h-28 overflow-auto whitespace-pre-wrap rounded border border-app-error-900/50 bg-app-error-950/30 p-1.5 text-[11px] text-app-error-200/90"
167
+ class="mt-1 max-h-28 overflow-auto whitespace-pre-wrap rounded-sm border border-app-error-900/50 bg-app-error-950/30 p-1.5 text-2xs text-app-error-200/90"
167
168
  >{{ entry.error }}</pre>
168
169
  </li>
169
170
  </ul>
@@ -10,6 +10,7 @@ import type { RalphStepState } from '~/types/execution'
10
10
  import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
11
11
  import StepRunMeta from '~/components/panels/StepRunMeta.vue'
12
12
  import CopyButton from '~/components/common/CopyButton.vue'
13
+ import SectionLabel from '~/components/common/SectionLabel.vue'
13
14
 
14
15
  const board = useBoardStore()
15
16
  const execution = useExecutionStore()
@@ -145,45 +146,46 @@ const STATUS_META = computed<
145
146
 
146
147
  <template v-else>
147
148
  <!-- The completion criterion. -->
148
- <h3 class="mb-1.5 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
149
+ <SectionLabel as="h3" class="mb-1.5">
149
150
  {{ t('ralph.validationCommand') }}
150
- </h3>
151
+ </SectionLabel>
151
152
  <div class="relative rounded-md border border-default bg-app-950/60 px-3 py-2">
152
153
  <CopyButton :text="ralph.validationCommand" class="absolute end-1 top-1" />
153
- <code class="block whitespace-pre-wrap pe-8 font-mono text-[12px] text-default">{{
154
+ <code class="block whitespace-pre-wrap pe-8 font-mono text-xs text-default">{{
154
155
  ralph.validationCommand
155
156
  }}</code>
156
157
  </div>
157
158
 
158
159
  <!-- The most recent validation output. -->
159
160
  <template v-if="ralph.lastValidationTail">
160
- <h3 class="mb-1.5 mt-4 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
161
+ <SectionLabel as="h3" class="mb-1.5 mt-4">
161
162
  {{ t('ralph.lastOutput', { exit: ralph.lastExitCode ?? '?' }) }}
162
- </h3>
163
+ </SectionLabel>
163
164
  <div class="relative rounded-md border border-default bg-app-950/60 px-3 py-2">
164
165
  <CopyButton :text="ralph.lastValidationTail" class="absolute end-1 top-1" />
165
- <pre
166
- class="whitespace-pre-wrap pe-8 font-mono text-[11px] leading-relaxed text-muted"
167
- >{{ ralph.lastValidationTail }}</pre>
166
+ <pre class="whitespace-pre-wrap pe-8 font-mono text-2xs leading-relaxed text-muted">{{
167
+ ralph.lastValidationTail
168
+ }}</pre>
168
169
  </div>
169
170
  </template>
170
171
 
171
- <a
172
+ <ULink
173
+ raw
172
174
  v-if="prUrl"
173
- :href="prUrl"
175
+ :to="prUrl"
174
176
  target="_blank"
175
177
  rel="noopener"
176
- class="mt-3 inline-flex items-center gap-1 text-[12px] text-app-info-300 hover:text-app-info-200 hover:underline"
178
+ class="mt-3 inline-flex items-center gap-1 text-xs text-app-info-300 hover:text-app-info-200 hover:underline"
177
179
  >
178
180
  {{ t('ralph.viewPr') }}
179
181
  <UIcon name="i-lucide-external-link" class="h-3 w-3" />
180
- </a>
182
+ </ULink>
181
183
 
182
184
  <!-- Why a loop that stopped short of its budget stopped: without this the count in
183
185
  the sidebar (e.g. "3 of 20") reads as an unexplained abandonment. -->
184
186
  <p
185
187
  v-if="status === 'stalled'"
186
- class="mt-3 rounded-md border border-app-error-900/60 bg-app-error-950/30 px-3 py-2 text-[12px] leading-relaxed text-app-error-200"
188
+ class="mt-3 rounded-md border border-app-error-900/60 bg-app-error-950/30 px-3 py-2 text-xs leading-relaxed text-app-error-200"
187
189
  data-testid="ralph-stalled-note"
188
190
  >
189
191
  {{ t('ralph.stalledNote') }}
@@ -191,14 +193,14 @@ const STATUS_META = computed<
191
193
 
192
194
  <!-- Iteration history: what each pass produced and whether its validation passed. -->
193
195
  <section v-if="attempts.length" class="mt-5">
194
- <h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
196
+ <SectionLabel as="h3" class="mb-2">
195
197
  {{ t('ralph.iterationsHeading') }}
196
- </h3>
198
+ </SectionLabel>
197
199
  <!-- The log is capped (it rides the run's detail blob); say so rather than letting a
198
200
  long loop's partial history read as if those iterations never ran. -->
199
201
  <p
200
202
  v-if="droppedAttempts"
201
- class="mb-2 text-[11px] text-dimmed"
203
+ class="mb-2 text-2xs text-dimmed"
202
204
  data-testid="ralph-iterations-truncated"
203
205
  >
204
206
  {{ t('ralph.iterationsTruncated', { count: droppedAttempts }, droppedAttempts) }}
@@ -216,23 +218,21 @@ const STATUS_META = computed<
216
218
  class="h-3.5 w-3.5"
217
219
  :class="a.validationPassed ? 'text-app-success-400' : 'text-app-error-400'"
218
220
  />
219
- <span class="text-[12px] font-medium text-default">
221
+ <span class="text-xs font-medium text-default">
220
222
  {{ t('ralph.iteration', { number: a.attempt }) }}
221
223
  </span>
222
- <span class="text-[11px] text-dimmed">
224
+ <span class="text-2xs text-dimmed">
223
225
  {{
224
226
  a.validationPassed
225
227
  ? t('ralph.iterationPassed')
226
228
  : t('ralph.iterationFailed', { exit: a.exitCode ?? '?' })
227
229
  }}
228
230
  </span>
229
- <span class="ms-auto text-[10px] text-app-600">{{
230
- d(new Date(a.at), 'long')
231
- }}</span>
231
+ <span class="ms-auto text-3xs text-app-600">{{ d(new Date(a.at), 'long') }}</span>
232
232
  </div>
233
233
  <p
234
234
  v-if="a.summary"
235
- class="mt-1 whitespace-pre-wrap text-[12px] leading-relaxed text-muted"
235
+ class="mt-1 whitespace-pre-wrap text-xs leading-relaxed text-muted"
236
236
  >
237
237
  {{ a.summary }}
238
238
  </p>
@@ -246,10 +246,10 @@ const STATUS_META = computed<
246
246
  class="hidden w-60 shrink-0 flex-col gap-4 border-s border-default bg-default/50 px-4 py-4 lg:flex"
247
247
  >
248
248
  <div v-if="ralph">
249
- <h4 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
249
+ <SectionLabel as="h4" class="mb-2">
250
250
  {{ t('ralph.sidebar.state') }}
251
- </h4>
252
- <div class="flex items-center gap-2 text-[13px]">
251
+ </SectionLabel>
252
+ <div class="flex items-center gap-2 text-sm">
253
253
  <UIcon
254
254
  :name="STATUS_META[status].icon"
255
255
  class="h-4 w-4"
@@ -259,10 +259,10 @@ const STATUS_META = computed<
259
259
  </div>
260
260
  </div>
261
261
  <div v-if="ralph">
262
- <h4 class="mb-1 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
262
+ <SectionLabel as="h4" class="mb-1">
263
263
  {{ t('ralph.sidebar.iterations') }}
264
- </h4>
265
- <p class="text-[12px] text-toned" data-testid="ralph-iteration-count">
264
+ </SectionLabel>
265
+ <p class="text-xs text-toned" data-testid="ralph-iteration-count">
266
266
  {{ t('ralph.sidebar.count', { attempts: ralph.attempts, max: ralph.maxIterations }) }}
267
267
  </p>
268
268
  </div>
@@ -275,7 +275,7 @@ const STATUS_META = computed<
275
275
  :run-failed="instance?.status === 'failed'"
276
276
  :failure-at="instance?.failure?.occurredAt"
277
277
  />
278
- <p class="mt-auto text-[10px] leading-relaxed text-app-600">
278
+ <p class="mt-auto text-3xs leading-relaxed text-app-600">
279
279
  {{ t('ralph.sidebar.footer') }}
280
280
  </p>
281
281
  </aside>
@@ -28,6 +28,7 @@ import type {
28
28
  ReviewItemSeverity,
29
29
  ReviewItemStatus,
30
30
  } from '~/types/requirements'
31
+ import SectionLabel from '~/components/common/SectionLabel.vue'
31
32
 
32
33
  const board = useBoardStore()
33
34
  const requirements = useRequirementsStore()
@@ -806,11 +807,11 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
806
807
  </span>
807
808
  <span class="h-px flex-1 bg-accented" />
808
809
  </div>
809
- <p class="mt-0.5 text-[11px] text-dimmed">{{ CLASS_HINTS[group] }}</p>
810
+ <p class="mt-0.5 text-2xs text-dimmed">{{ CLASS_HINTS[group] }}</p>
810
811
  </div>
811
812
  <div v-if="startsAttentionGroup(index)" class="flex items-center gap-2 pt-1">
812
813
  <span
813
- class="text-[11px] font-semibold uppercase tracking-wide"
814
+ class="text-2xs font-semibold uppercase tracking-wide"
814
815
  :class="ATTENTION_LABEL_COLOR[attention]"
815
816
  >
816
817
  {{ ATTENTION_LABELS[attention] }}
@@ -873,9 +874,9 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
873
874
  v-if="item.reply && item.status !== 'open' && item.status !== 'answered'"
874
875
  class="mt-2 max-w-3xl rounded-md border-s-2 border-muted bg-app-950/40 px-3 py-1.5 text-sm text-toned"
875
876
  >
876
- <span class="text-[10px] uppercase tracking-wide text-dimmed">
877
+ <SectionLabel as="span">
877
878
  {{ t('requirements.answerLabel') }}
878
- </span>
879
+ </SectionLabel>
879
880
  <p class="whitespace-pre-line">{{ item.reply }}</p>
880
881
  </div>
881
882
 
@@ -964,7 +965,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
964
965
  />
965
966
  <p
966
967
  v-if="isUserAnswered(item)"
967
- class="mt-1 flex items-center gap-1 text-[11px] text-app-success-400"
968
+ class="mt-1 flex items-center gap-1 text-2xs text-app-success-400"
968
969
  >
969
970
  <UIcon name="i-lucide-check" class="h-3 w-3 shrink-0" />
970
971
  {{ t('requirements.userAnswered') }}
@@ -1093,7 +1094,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1093
1094
  :placeholder="t('requirements.guidancePlaceholder')"
1094
1095
  :disabled="frozen"
1095
1096
  />
1096
- <p class="mt-1 flex items-center gap-1 text-[11px] text-primary/80">
1097
+ <p class="mt-1 flex items-center gap-1 text-2xs text-primary/80">
1097
1098
  <UIcon name="i-lucide-wand-2" class="h-3 w-3 shrink-0" />
1098
1099
  {{ t('requirements.guidanceHint') }}
1099
1100
  </p>
@@ -1101,7 +1102,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1101
1102
  </template>
1102
1103
 
1103
1104
  <!-- DISMISS: nothing to fill in — a short note explains the effect -->
1104
- <p v-else class="mt-2 text-[11px] text-dimmed">
1105
+ <p v-else class="mt-2 text-2xs text-dimmed">
1105
1106
  {{ t('requirements.dismissedHint') }}
1106
1107
  </p>
1107
1108
  </template>
@@ -1115,8 +1116,10 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1115
1116
  collapses as a unit (a long doc otherwise pushes the findings/recommendations
1116
1117
  off-screen); the per-heading toggles below still work when it's expanded. -->
1117
1118
  <section v-if="outline" class="mt-6 border-t border-default pt-5">
1118
- <button
1119
- class="mb-3 flex w-full items-center gap-1.5 text-[11px] text-app-success-400"
1119
+ <UButton
1120
+ color="neutral"
1121
+ variant="ghost"
1122
+ class="mb-3 flex w-full items-center gap-1.5 p-0 text-2xs text-app-success-400 hover:bg-transparent"
1120
1123
  @click="toggleDoc"
1121
1124
  >
1122
1125
  <UIcon
@@ -1132,16 +1135,18 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1132
1135
  : t('requirements.incorporatedDraft')
1133
1136
  }}
1134
1137
  </span>
1135
- </button>
1138
+ </UButton>
1136
1139
  <!-- The same reading measure the findings' own prose takes above (see the shell's
1137
1140
  `width` prop): the window is `full`-width now, and this is continuous prose that
1138
1141
  would otherwise run to 200-character lines. Left-aligned rather than centred, so
1139
1142
  it starts where every finding above it starts. -->
1140
1143
  <div v-show="!docCollapsed" class="max-w-3xl">
1141
1144
  <div v-for="s in outline.sections" :key="s.id" class="mb-2">
1142
- <button
1145
+ <UButton
1146
+ color="neutral"
1147
+ variant="ghost"
1143
1148
  v-if="s.title"
1144
- class="group flex w-full items-center gap-2 text-start"
1149
+ class="group flex w-full items-center gap-2 p-0 text-start hover:bg-transparent"
1145
1150
  @click="toggle(s.id)"
1146
1151
  >
1147
1152
  <UIcon
@@ -1154,10 +1159,10 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1154
1159
  :class="s.depth <= 1 ? 'text-base' : s.depth === 2 ? 'text-sm' : 'text-xs'"
1155
1160
  v-html="s.titleHtml"
1156
1161
  />
1157
- </button>
1162
+ </UButton>
1158
1163
  <div
1159
1164
  v-show="!s.title || !collapsed[s.id]"
1160
- class="reader-prose mt-1 ps-5.5 text-[13px] leading-relaxed text-toned"
1165
+ class="reader-prose mt-1 ps-5.5 text-sm leading-relaxed text-toned"
1161
1166
  v-html="s.bodyHtml"
1162
1167
  />
1163
1168
  </div>
@@ -1277,7 +1282,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1277
1282
  >
1278
1283
  {{ t('requirements.actions.incorporateAnswers') }}
1279
1284
  </UButton>
1280
- <p class="text-[11px] leading-relaxed text-dimmed">
1285
+ <p class="text-2xs leading-relaxed text-dimmed">
1281
1286
  <template v-if="canProceed">
1282
1287
  {{ t('requirements.help.canProceed') }}
1283
1288
  </template>
@@ -1341,14 +1346,14 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
1341
1346
  {{ t('requirements.actions.redoWithDirection') }}
1342
1347
  </UButton>
1343
1348
  </div>
1344
- <p class="text-[11px] leading-relaxed text-dimmed">
1349
+ <p class="text-2xs leading-relaxed text-dimmed">
1345
1350
  {{ t('requirements.help.merged') }}
1346
1351
  </p>
1347
1352
  </div>
1348
1353
 
1349
1354
  <div
1350
1355
  v-if="review && incorporated"
1351
- class="border-t border-default pt-4 text-[11px] leading-relaxed text-dimmed"
1356
+ class="border-t border-default pt-4 text-2xs leading-relaxed text-dimmed"
1352
1357
  >
1353
1358
  {{ t('requirements.settledFooter') }}
1354
1359
  </div>
@@ -140,9 +140,10 @@ function choose(id: string) {
140
140
  <!-- left: selectable options, NAME ONLY -->
141
141
  <ul class="w-1/2 shrink-0 overflow-y-auto border-e border-default p-1">
142
142
  <li>
143
- <button
144
- type="button"
145
- class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm"
143
+ <UButton
144
+ color="neutral"
145
+ variant="ghost"
146
+ class="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-start text-sm"
146
147
  :class="[
147
148
  refused.has('') ? 'cursor-not-allowed opacity-50' : 'hover:bg-elevated/60',
148
149
  modelValue ? 'text-toned' : 'text-app-100',
@@ -164,12 +165,13 @@ function choose(id: string) {
164
165
  name="i-lucide-check"
165
166
  class="h-4 w-4 shrink-0 text-primary"
166
167
  />
167
- </button>
168
+ </UButton>
168
169
  </li>
169
170
  <li v-for="p in options" :key="p.id">
170
- <button
171
- type="button"
172
- class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm"
171
+ <UButton
172
+ color="neutral"
173
+ variant="ghost"
174
+ class="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-start text-sm"
173
175
  :class="[
174
176
  refused.has(p.id) ? 'cursor-not-allowed opacity-50' : 'hover:bg-elevated/60',
175
177
  modelValue === p.id ? 'text-app-100' : 'text-toned',
@@ -191,7 +193,7 @@ function choose(id: string) {
191
193
  name="i-lucide-check"
192
194
  class="h-4 w-4 shrink-0 text-primary"
193
195
  />
194
- </button>
196
+ </UButton>
195
197
  </li>
196
198
  </ul>
197
199
 
@@ -200,17 +202,17 @@ function choose(id: string) {
200
202
  <template v-if="preview.policy">
201
203
  <p
202
204
  v-if="previewRefusal"
203
- class="mb-2 text-[11px] leading-snug text-app-warning-400"
205
+ class="mb-2 text-2xs leading-snug text-app-warning-400"
204
206
  data-testid="risk-policy-refusal"
205
207
  >
206
208
  {{ t(`riskPolicy.picker.refused.${previewRefusal}`) }}
207
209
  </p>
208
- <p v-if="preview.viaWorkspaceDefault" class="mb-2 text-[11px] leading-snug text-dimmed">
210
+ <p v-if="preview.viaWorkspaceDefault" class="mb-2 text-2xs leading-snug text-dimmed">
209
211
  {{ t('riskPolicy.picker.workspaceDefaultCaption') }}
210
212
  </p>
211
213
  <RiskPolicyPreview :policy="preview.policy" />
212
214
  </template>
213
- <div v-else class="text-[12px] leading-snug text-dimmed">
215
+ <div v-else class="text-xs leading-snug text-dimmed">
214
216
  {{ t('riskPolicy.picker.noneHint') }}
215
217
  </div>
216
218
  </div>
@@ -10,6 +10,7 @@
10
10
  import { computed } from 'vue'
11
11
  import type { RiskPolicy, WorkspaceRole } from '~/types/merge'
12
12
  import { riskPolicyCeilings, rolePolicySummary, type RiskPolicyAxis } from '~/utils/riskPolicy'
13
+ import SectionLabel from '~/components/common/SectionLabel.vue'
13
14
 
14
15
  const props = defineProps<{ policy: RiskPolicy }>()
15
16
  const { t, n } = useI18n()
@@ -56,15 +57,15 @@ const ceilings = computed(() =>
56
57
 
57
58
  <!-- the three ceilings, grouped under one heading that names what they are -->
58
59
  <div v-if="policy.autoMergeEnabled">
59
- <div class="mb-1 flex items-center gap-1 text-[10px] uppercase tracking-wide text-dimmed">
60
+ <SectionLabel class="mb-1 flex items-center gap-1">
60
61
  <UIcon name="i-lucide-git-merge" class="h-3 w-3" />
61
62
  {{ t('riskPolicy.preview.autoMergeHeading') }}
62
- </div>
63
+ </SectionLabel>
63
64
  <dl class="space-y-1">
64
65
  <div
65
66
  v-for="c in ceilings"
66
67
  :key="c.axis"
67
- class="flex items-baseline justify-between gap-3 rounded bg-elevated/70 px-1.5 py-0.5 text-[12px]"
68
+ class="flex items-baseline justify-between gap-3 rounded-sm bg-elevated/70 px-1.5 py-0.5 text-xs"
68
69
  >
69
70
  <dt class="text-toned">{{ c.label }}</dt>
70
71
  <dd class="tabular-nums text-app-100">
@@ -72,43 +73,43 @@ const ceilings = computed(() =>
72
73
  </dd>
73
74
  </div>
74
75
  </dl>
75
- <p class="mt-1.5 text-[12px] leading-snug text-muted">
76
+ <p class="mt-1.5 text-xs leading-snug text-muted">
76
77
  {{ t('riskPolicy.preview.autoMergeExplainer') }}
77
78
  </p>
78
79
  </div>
79
80
  <div v-else>
80
- <div class="mb-1 flex items-center gap-1 text-[10px] uppercase tracking-wide text-dimmed">
81
+ <SectionLabel class="mb-1 flex items-center gap-1">
81
82
  <UIcon name="i-lucide-user-check" class="h-3 w-3" />
82
83
  {{ t('riskPolicy.preview.manualHeading') }}
83
- </div>
84
- <p class="text-[12px] leading-snug text-muted">
84
+ </SectionLabel>
85
+ <p class="text-xs leading-snug text-muted">
85
86
  {{ t('riskPolicy.preview.manualExplainer') }}
86
87
  </p>
87
88
  </div>
88
89
 
89
90
  <!-- Who started the run changes what may land, on a policy that says so. -->
90
91
  <div v-if="roleLayer.any" data-testid="risk-policy-preview-roles">
91
- <div class="mb-1 flex items-center gap-1 text-[10px] uppercase tracking-wide text-dimmed">
92
+ <SectionLabel class="mb-1 flex items-center gap-1">
92
93
  <UIcon name="i-lucide-users" class="h-3 w-3" />
93
94
  {{ t('riskPolicy.preview.roleHeading') }}
94
- </div>
95
- <p v-if="roleLayer.sandboxed" class="text-[12px] leading-snug text-muted">
95
+ </SectionLabel>
96
+ <p v-if="roleLayer.sandboxed" class="text-xs leading-snug text-muted">
96
97
  {{ t('riskPolicy.preview.roleSandboxed', { roles: roleLayer.sandboxed }) }}
97
98
  </p>
98
- <p v-if="roleLayer.scoped" class="text-[12px] leading-snug text-muted">
99
+ <p v-if="roleLayer.scoped" class="text-xs leading-snug text-muted">
99
100
  {{ t('riskPolicy.preview.roleScoped', { roles: roleLayer.scoped }) }}
100
101
  </p>
101
- <p v-if="roleLayer.narrowed" class="text-[12px] leading-snug text-muted">
102
+ <p v-if="roleLayer.narrowed" class="text-xs leading-snug text-muted">
102
103
  {{ t('riskPolicy.preview.roleNarrowed', { roles: roleLayer.narrowed }) }}
103
104
  </p>
104
105
  </div>
105
106
 
106
107
  <div>
107
- <div class="mb-1 flex items-center gap-1 text-[10px] uppercase tracking-wide text-dimmed">
108
+ <SectionLabel class="mb-1 flex items-center gap-1">
108
109
  <UIcon name="i-lucide-wrench" class="h-3 w-3" />
109
110
  {{ t('riskPolicy.preview.ciHeading') }}
110
- </div>
111
- <p class="text-[12px] leading-snug text-muted">
111
+ </SectionLabel>
112
+ <p class="text-xs leading-snug text-muted">
112
113
  {{
113
114
  t('riskPolicy.preview.ciAttempts', { count: policy.ciMaxAttempts }, policy.ciMaxAttempts)
114
115
  }}