@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.
- package/README.md +32 -2
- package/app/assets/css/main.css +22 -0
- package/app/assets/css/prose.css +4 -4
- package/app/assets/css/type.css +24 -0
- package/app/components/assistant/AssistantModal.vue +8 -6
- package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
- package/app/components/auth/LoginScreen.vue +40 -26
- package/app/components/auth/ResetPasswordScreen.vue +9 -4
- package/app/components/auth/UserMenu.vue +5 -4
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +48 -37
- package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
- package/app/components/binaryOutput/StoredAssetView.vue +13 -11
- package/app/components/board/AddTaskModal.vue +30 -27
- package/app/components/board/AgentFailureCard.vue +21 -18
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +7 -6
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/FailureHistoryList.vue +5 -5
- package/app/components/board/RecurringPipelineModal.vue +12 -11
- package/app/components/board/ReviewFrictionDialog.vue +8 -6
- package/app/components/board/StepExecutionHistory.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +1 -1
- package/app/components/board/nodes/BlockNode.vue +25 -24
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/EpicNode.vue +4 -4
- package/app/components/board/nodes/FrameSwimlanes.vue +8 -10
- package/app/components/board/nodes/InitiativeCard.vue +4 -4
- package/app/components/board/nodes/LaneGroup.vue +3 -5
- package/app/components/board/nodes/TaskCard.vue +20 -15
- package/app/components/board/nodes/TaskLane.vue +3 -3
- package/app/components/board/nodes/TaskPipelineMini.vue +21 -18
- package/app/components/bootstrap/AdoptionReviewModal.vue +36 -26
- package/app/components/bootstrap/BootstrapModal.vue +14 -13
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +13 -10
- package/app/components/bugFishing/BugFishingWindow.vue +81 -58
- package/app/components/clarity/ClarityReviewWindow.vue +13 -10
- package/app/components/common/AsyncViewError.vue +1 -1
- package/app/components/common/ClarificationItem.vue +6 -6
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +1 -1
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/common/InterviewGateNotice.vue +4 -4
- package/app/components/common/MarkdownProse.vue +8 -2
- package/app/components/common/SectionLabel.vue +38 -0
- package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
- package/app/components/context/ContextAttachmentFields.vue +32 -20
- package/app/components/docs/DocInterviewWindow.vue +10 -9
- package/app/components/documents/ContextDocumentPicker.vue +22 -21
- package/app/components/documents/DocumentImportModal.vue +7 -5
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
- package/app/components/documents/DocumentSyncState.vue +4 -4
- package/app/components/documents/DocumentTemplatesModal.vue +5 -4
- package/app/components/documents/RepoContextDocPicker.vue +7 -9
- package/app/components/documents/StartFromDesignModal.vue +4 -4
- package/app/components/documents/TaskContextDocs.vue +1 -1
- package/app/components/environments/EnvSetupStepper.vue +3 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +15 -13
- package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
- package/app/components/environments/steps/EnvReviewStep.vue +23 -22
- package/app/components/environments/steps/EnvSaveStep.vue +5 -5
- package/app/components/focus/BlockFocusView.vue +11 -10
- package/app/components/followUp/FollowUpWindow.vue +18 -15
- package/app/components/forkDecision/ForkDecisionWindow.vue +85 -97
- package/app/components/foundational/FoundationalContractSummary.vue +2 -2
- package/app/components/foundational/FoundationalServiceCatalogList.vue +6 -5
- package/app/components/foundational/FoundationalServiceRegistry.vue +10 -9
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/foundational/FoundationalSuppressions.vue +2 -2
- package/app/components/fragments/FragmentLibraryManager.vue +8 -7
- package/app/components/fragments/FragmentSelector.vue +22 -20
- package/app/components/gates/GateFailingCheckList.vue +7 -6
- package/app/components/gates/GateResultView.vue +55 -49
- package/app/components/github/AddServiceFromRepoModal.vue +16 -11
- package/app/components/github/BranchProtectionPreflight.vue +5 -5
- package/app/components/github/GitHubConnect.vue +5 -3
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +23 -19
- package/app/components/github/RepoTreeBrowser.vue +16 -13
- package/app/components/humanTest/HumanTestWindow.vue +29 -24
- package/app/components/initiative/InitiativePlanNotice.vue +3 -3
- package/app/components/initiative/InitiativePlanReview.vue +46 -38
- package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
- package/app/components/initiative/InitiativeTrackerWindow.vue +213 -165
- package/app/components/judge/JudgeResultView.vue +28 -27
- package/app/components/kaizen/KaizenPanel.vue +70 -56
- package/app/components/kaizen/KaizenStepStatus.vue +7 -6
- package/app/components/layout/AccountAuditLog.vue +1 -1
- package/app/components/layout/AccountDeploymentSettings.vue +10 -10
- package/app/components/layout/AccountFailureKindRules.vue +13 -13
- package/app/components/layout/AccountFoundationalSettings.vue +1 -1
- package/app/components/layout/AccountFragmentSettings.vue +1 -1
- package/app/components/layout/AccountModelPolicySettings.vue +7 -7
- package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
- package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
- package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
- package/app/components/layout/AccountSkillSettings.vue +1 -1
- package/app/components/layout/AccountTeamSettings.vue +13 -9
- package/app/components/layout/AiProvidersBanner.vue +1 -1
- package/app/components/layout/AppearanceSwitcher.vue +5 -4
- package/app/components/layout/BoardSwitcher.vue +13 -10
- package/app/components/layout/BoardToolbar.vue +10 -5
- package/app/components/layout/CommandBar.vue +8 -5
- package/app/components/layout/DefaultTestEnvBanner.vue +6 -5
- package/app/components/layout/IntegrationsHub.vue +12 -9
- package/app/components/layout/LanguageSwitcher.vue +5 -4
- package/app/components/layout/ModelProvidersHub.vue +10 -7
- package/app/components/layout/NotificationsInbox.vue +47 -36
- package/app/components/layout/PersonalSetupModal.vue +9 -6
- package/app/components/layout/RolePrompt.vue +5 -4
- package/app/components/layout/SideBar.vue +7 -8
- package/app/components/layout/SpendWarningBanner.vue +3 -3
- package/app/components/layout/TranslationWarningBanner.vue +5 -4
- package/app/components/layout/UiModeSwitcher.vue +15 -12
- package/app/components/layout/UiRoleSwitcher.vue +10 -8
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +74 -44
- package/app/components/media/ImageCompare.vue +80 -85
- package/app/components/merge/MergeEffortChips.vue +4 -6
- package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
- package/app/components/observability/OutcomeFilterChips.vue +6 -5
- package/app/components/observability/RunFailureSummary.vue +22 -23
- package/app/components/observability/StepMetricsBar.vue +9 -8
- package/app/components/observability/StepModelActivity.vue +8 -5
- package/app/components/observability/ToolCallList.vue +19 -20
- package/app/components/outcome/OutcomeSummaryWindow.vue +48 -46
- package/app/components/palettes/AgentPalette.vue +21 -15
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +57 -49
- package/app/components/panels/AttemptEntryHeader.vue +2 -2
- package/app/components/panels/DecisionModal.vue +1 -1
- package/app/components/panels/GenericStructuredResultView.vue +6 -5
- package/app/components/panels/InspectorPanel.vue +15 -13
- package/app/components/panels/MergerResultView.vue +10 -9
- package/app/components/panels/ObservabilityPanel.vue +211 -186
- package/app/components/panels/OperatorDashboardPanel.vue +124 -115
- package/app/components/panels/ReportsPanel.vue +87 -83
- package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
- package/app/components/panels/ResultWindowShell.vue +152 -137
- package/app/components/panels/RunDetailLoadState.vue +1 -1
- package/app/components/panels/StepContainerStatus.vue +17 -16
- package/app/components/panels/StepDelegatedStatus.vue +24 -21
- package/app/components/panels/StepEffortReport.vue +12 -17
- package/app/components/panels/StepFragmentAdherence.vue +9 -10
- package/app/components/panels/StepMetadataCard.vue +41 -43
- package/app/components/panels/StepReproductionReport.vue +18 -20
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/StepRunMeta.vue +27 -26
- package/app/components/panels/StepTestReport.vue +16 -15
- package/app/components/panels/StepToolServers.vue +7 -8
- package/app/components/panels/StepValidationReport.vue +5 -5
- package/app/components/panels/inspector/ContainerSummary.vue +4 -4
- package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
- package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
- package/app/components/panels/inspector/EpicChildren.vue +12 -10
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
- package/app/components/panels/inspector/FrontendConfig.vue +29 -36
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +25 -17
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
- package/app/components/panels/inspector/ServiceConnections.vue +5 -4
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
- package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
- package/app/components/panels/inspector/ServiceTestConfig.vue +46 -49
- package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
- package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
- package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
- package/app/components/panels/inspector/TaskExecution.vue +18 -16
- package/app/components/panels/inspector/TaskRunSettings.vue +45 -44
- package/app/components/panels/inspector/TaskStructure.vue +5 -4
- package/app/components/pipeline/AgentPromptEditor.vue +15 -14
- package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
- package/app/components/pipeline/EstimateThresholdFields.vue +14 -11
- package/app/components/pipeline/GateConfigFields.vue +19 -23
- package/app/components/pipeline/IterationCapPrompt.vue +1 -1
- package/app/components/pipeline/PipelineBuilder.vue +113 -99
- package/app/components/pipeline/PipelineHealthModal.vue +7 -7
- package/app/components/pipeline/PipelinePicker.vue +11 -9
- package/app/components/pipeline/PipelinePreview.vue +6 -7
- package/app/components/pipeline/PipelineProgress.vue +49 -45
- package/app/components/prReview/PrReviewWindow.vue +87 -65
- package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
- package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
- package/app/components/providers/ApiKeysSection.vue +11 -9
- package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
- package/app/components/providers/VendorCredentialsModal.vue +5 -4
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
- package/app/components/ralph/RalphLoopResultView.vue +29 -29
- package/app/components/requirements/RequirementsReviewWindow.vue +22 -17
- package/app/components/riskPolicy/RiskPolicyPicker.vue +13 -11
- package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
- package/app/components/sandbox/SandboxPanel.vue +93 -73
- package/app/components/settings/ApiTokensPanel.vue +1 -1
- package/app/components/settings/BudgetSettings.vue +18 -17
- package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
- package/app/components/settings/CloudflareHandlerSection.vue +44 -41
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
- package/app/components/settings/ConnectionTestVerdict.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +58 -47
- package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
- package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
- package/app/components/settings/InfraHandlersConfigurator.vue +26 -24
- package/app/components/settings/InfrastructureBackendPicker.vue +18 -18
- package/app/components/settings/IssueTrackerPanel.vue +30 -21
- package/app/components/settings/KubernetesEngineForm.vue +9 -8
- package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
- package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
- package/app/components/settings/LocalModelEndpointsPanel.vue +13 -11
- package/app/components/settings/MergeClassRulesEditor.vue +6 -5
- package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
- package/app/components/settings/ModelConfigurationPanel.vue +17 -19
- package/app/components/settings/ModelPresetHealthModal.vue +3 -3
- package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
- package/app/components/settings/OpenRouterCatalogPanel.vue +10 -8
- package/app/components/settings/PackageRegistriesPanel.vue +4 -4
- package/app/components/settings/ProviderConnectionTab.vue +5 -4
- package/app/components/settings/ProviderManifestEditor.vue +9 -8
- package/app/components/settings/ProviderPreferenceEditor.vue +13 -13
- package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
- package/app/components/settings/RiskPolicyEditorRow.vue +21 -19
- package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
- package/app/components/settings/RiskPolicyPanel.vue +11 -13
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +15 -12
- package/app/components/settings/SharedStacksPanel.vue +5 -5
- package/app/components/settings/TaskSourceCard.vue +2 -2
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
- package/app/components/settings/ToolServerChecklist.vue +22 -22
- package/app/components/settings/UsageSettings.vue +13 -13
- package/app/components/settings/UserSecretsSection.vue +4 -3
- package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
- package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
- package/app/components/skills/ReviewSkillQueue.vue +12 -10
- package/app/components/skills/SkillLibraryManager.vue +9 -8
- package/app/components/slack/SlackPanel.vue +17 -12
- package/app/components/spec/ServiceSpecWindow.vue +19 -19
- package/app/components/tasks/BugHuntModal.vue +1 -1
- package/app/components/tasks/ContextIssuePicker.vue +16 -15
- package/app/components/tasks/TaskContextIssues.vue +5 -4
- package/app/components/tasks/TaskImportModal.vue +3 -2
- package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
- package/app/components/testing/TestReportWindow.vue +67 -60
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/tutorial/TutorialNudge.vue +3 -2
- package/app/components/tutorial/TutorialOverlay.vue +3 -2
- package/app/components/vcs/GitLabConnect.vue +1 -1
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +79 -54
- package/app/utils/theme/builtins.ts +7 -1
- package/i18n/locales/de.json +7 -3
- package/i18n/locales/en.json +7 -3
- package/i18n/locales/es.json +7 -3
- package/i18n/locales/fr.json +7 -3
- package/i18n/locales/he.json +7 -3
- package/i18n/locales/it.json +7 -3
- package/i18n/locales/ja.json +7 -3
- package/i18n/locales/pl.json +7 -3
- package/i18n/locales/tr.json +7 -3
- package/i18n/locales/uk.json +7 -3
- 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
|
-
<
|
|
119
|
+
<SectionLabel as="p">
|
|
119
120
|
{{ t('provisioning.title') }}
|
|
120
|
-
</
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
149
|
+
<SectionLabel as="h3" class="mb-1.5">
|
|
149
150
|
{{ t('ralph.validationCommand') }}
|
|
150
|
-
</
|
|
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-
|
|
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
|
|
161
|
+
<SectionLabel as="h3" class="mb-1.5 mt-4">
|
|
161
162
|
{{ t('ralph.lastOutput', { exit: ralph.lastExitCode ?? '?' }) }}
|
|
162
|
-
</
|
|
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
|
-
|
|
167
|
-
|
|
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
|
-
<
|
|
172
|
+
<ULink
|
|
173
|
+
raw
|
|
172
174
|
v-if="prUrl"
|
|
173
|
-
:
|
|
175
|
+
:to="prUrl"
|
|
174
176
|
target="_blank"
|
|
175
177
|
rel="noopener"
|
|
176
|
-
class="mt-3 inline-flex items-center gap-1 text-
|
|
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
|
-
</
|
|
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-
|
|
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
|
|
196
|
+
<SectionLabel as="h3" class="mb-2">
|
|
195
197
|
{{ t('ralph.iterationsHeading') }}
|
|
196
|
-
</
|
|
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-
|
|
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-
|
|
221
|
+
<span class="text-xs font-medium text-default">
|
|
220
222
|
{{ t('ralph.iteration', { number: a.attempt }) }}
|
|
221
223
|
</span>
|
|
222
|
-
<span class="text-
|
|
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-
|
|
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-
|
|
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
|
|
249
|
+
<SectionLabel as="h4" class="mb-2">
|
|
250
250
|
{{ t('ralph.sidebar.state') }}
|
|
251
|
-
</
|
|
252
|
-
<div class="flex items-center gap-2 text-
|
|
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
|
|
262
|
+
<SectionLabel as="h4" class="mb-1">
|
|
263
263
|
{{ t('ralph.sidebar.iterations') }}
|
|
264
|
-
</
|
|
265
|
-
<p class="text-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
<
|
|
877
|
+
<SectionLabel as="span">
|
|
877
878
|
{{ t('requirements.answerLabel') }}
|
|
878
|
-
</
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
<
|
|
1119
|
-
|
|
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
|
-
</
|
|
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
|
-
<
|
|
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
|
-
</
|
|
1162
|
+
</UButton>
|
|
1158
1163
|
<div
|
|
1159
1164
|
v-show="!s.title || !collapsed[s.id]"
|
|
1160
|
-
class="reader-prose mt-1 ps-5.5 text-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
</
|
|
168
|
+
</UButton>
|
|
168
169
|
</li>
|
|
169
170
|
<li v-for="p in options" :key="p.id">
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
</
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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-
|
|
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-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
84
|
-
<p class="text-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
95
|
-
<p v-if="roleLayer.sandboxed" class="text-
|
|
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-
|
|
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-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
111
|
-
<p class="text-
|
|
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
|
}}
|