@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 @@
|
|
|
22
22
|
// self-assessment (see the footer block below), so a window never renders it itself.
|
|
23
23
|
import { computed, ref, watch } from 'vue'
|
|
24
24
|
import { useModalBehavior } from '@modular-vue/core'
|
|
25
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
25
26
|
import StepRestartControl from '~/components/panels/StepRestartControl.vue'
|
|
26
27
|
import RunDetailLoadState from '~/components/panels/RunDetailLoadState.vue'
|
|
27
28
|
import StepEffortReport from '~/components/panels/StepEffortReport.vue'
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
RESULT_WINDOW_WIDTH_CLASS,
|
|
40
41
|
type ResultWindowWidth,
|
|
41
42
|
} from '~/components/panels/ResultWindowShell.logic'
|
|
43
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
42
44
|
|
|
43
45
|
/** A pipeline step reference — passed by step-result windows to surface the shared
|
|
44
46
|
* "restart from here" control. `StepRestartControl` self-hides for an off-path open
|
|
@@ -68,8 +70,8 @@ const props = withDefaults(
|
|
|
68
70
|
* worse, not better.
|
|
69
71
|
*
|
|
70
72
|
* The obligation that comes with it: CONTINUOUS PROSE inside a `full` window carries its
|
|
71
|
-
* own reading measure (`PROSE_MEASURE_CLASS`, the step reader's own, over the same
|
|
72
|
-
* `.reader-prose`), or the width lands as 200-character lines.
|
|
73
|
+
* own reading measure (`PROSE_MEASURE_CLASS`, the step reader's own, over the same
|
|
74
|
+
* `text-sm` `.reader-prose`), or the width lands as 200-character lines.
|
|
73
75
|
*
|
|
74
76
|
* The unit that obligation attaches to is the PARAGRAPH, not the section — which is the
|
|
75
77
|
* distinction to get right, because "a findings list reads better at the full span" is
|
|
@@ -289,7 +291,7 @@ const panelClass = computed(() => [
|
|
|
289
291
|
</span>
|
|
290
292
|
<div class="min-w-0 flex-1">
|
|
291
293
|
<h2 class="truncate text-sm font-semibold text-app-100">{{ title }}</h2>
|
|
292
|
-
<p v-if="subtitle" class="truncate text-
|
|
294
|
+
<p v-if="subtitle" class="truncate text-2xs text-muted">{{ subtitle }}</p>
|
|
293
295
|
</div>
|
|
294
296
|
<!-- Window-specific header content (status badges, counts). -->
|
|
295
297
|
<slot name="header-extras" />
|
|
@@ -299,14 +301,15 @@ const panelClass = computed(() => [
|
|
|
299
301
|
:step-index="stepRef.stepIndex"
|
|
300
302
|
@restarted="requestClose"
|
|
301
303
|
/>
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
+
<IconButton
|
|
305
|
+
icon="i-lucide-x"
|
|
306
|
+
color="neutral"
|
|
307
|
+
variant="ghost"
|
|
308
|
+
size="sm"
|
|
304
309
|
data-testid="result-window-close"
|
|
305
|
-
:
|
|
310
|
+
:label="t('common.close')"
|
|
306
311
|
@click="requestClose"
|
|
307
|
-
|
|
308
|
-
<UIcon name="i-lucide-x" class="h-4 w-4" />
|
|
309
|
-
</button>
|
|
312
|
+
/>
|
|
310
313
|
</header>
|
|
311
314
|
<!-- Whether the whole-run fetch behind this window's prose has landed. -->
|
|
312
315
|
<RunDetailLoadState :instance-id="activeInstanceId" />
|
|
@@ -321,34 +324,37 @@ const panelClass = computed(() => [
|
|
|
321
324
|
class="shrink-0 border-t border-default bg-default/60"
|
|
322
325
|
data-testid="result-window-effort"
|
|
323
326
|
>
|
|
324
|
-
<
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
>
|
|
331
|
-
<UIcon name="i-lucide-gauge" class="h-3.5 w-3.5 shrink-0 text-muted" />
|
|
332
|
-
<span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
333
|
-
{{ t('panels.stepDetail.effort.heading') }}
|
|
334
|
-
</span>
|
|
335
|
-
<span
|
|
336
|
-
class="shrink-0 rounded px-1.5 py-0.5 text-[11px] font-medium tabular-nums"
|
|
337
|
-
:class="chipClass"
|
|
327
|
+
<UCollapsible v-model:open="effortOpen">
|
|
328
|
+
<UButton
|
|
329
|
+
color="neutral"
|
|
330
|
+
variant="ghost"
|
|
331
|
+
class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
|
|
332
|
+
data-testid="result-window-effort-toggle"
|
|
338
333
|
>
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
334
|
+
<UIcon name="i-lucide-gauge" class="h-3.5 w-3.5 shrink-0 text-muted" />
|
|
335
|
+
<SectionLabel as="span">
|
|
336
|
+
{{ t('panels.stepDetail.effort.heading') }}
|
|
337
|
+
</SectionLabel>
|
|
338
|
+
<span
|
|
339
|
+
class="shrink-0 rounded-sm px-1.5 py-0.5 text-2xs font-medium tabular-nums"
|
|
340
|
+
:class="chipClass"
|
|
341
|
+
>
|
|
342
|
+
{{ t('panels.stepDetail.effort.outOfTen', { value: effortReport.difficulty }) }}
|
|
343
|
+
</span>
|
|
344
|
+
<span v-if="hint" class="min-w-0 flex-1 truncate text-xs text-muted">
|
|
345
|
+
{{ hint }}
|
|
346
|
+
</span>
|
|
347
|
+
<UIcon
|
|
348
|
+
:name="effortOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
|
|
349
|
+
class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
|
|
350
|
+
/>
|
|
351
|
+
</UButton>
|
|
352
|
+
<template #content>
|
|
353
|
+
<div class="max-h-56 overflow-y-auto px-5 pb-3">
|
|
354
|
+
<StepEffortReport :report="effortReport" variant="flat" />
|
|
355
|
+
</div>
|
|
356
|
+
</template>
|
|
357
|
+
</UCollapsible>
|
|
352
358
|
</section>
|
|
353
359
|
|
|
354
360
|
<!-- Shared trailing section: the pre-PR validation report (the service's check commands
|
|
@@ -359,51 +365,54 @@ const panelClass = computed(() => [
|
|
|
359
365
|
class="shrink-0 border-t border-default bg-default/60"
|
|
360
366
|
data-testid="result-window-validation"
|
|
361
367
|
>
|
|
362
|
-
<
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
>
|
|
369
|
-
<UIcon
|
|
370
|
-
:name="validationReport.passed ? 'i-lucide-shield-check' : 'i-lucide-shield-alert'"
|
|
371
|
-
class="h-3.5 w-3.5 shrink-0"
|
|
372
|
-
:class="validationReport.passed ? 'text-app-success-400' : 'text-app-error-400'"
|
|
373
|
-
/>
|
|
374
|
-
<span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
375
|
-
{{ t('panels.stepDetail.validation.heading') }}
|
|
376
|
-
</span>
|
|
377
|
-
<span
|
|
378
|
-
class="shrink-0 rounded px-1.5 py-0.5 text-[11px] font-medium tabular-nums"
|
|
379
|
-
:class="
|
|
380
|
-
validationReport.passed
|
|
381
|
-
? 'bg-app-success-500/15 text-app-success-300'
|
|
382
|
-
: 'bg-app-error-500/15 text-app-error-300'
|
|
383
|
-
"
|
|
368
|
+
<UCollapsible v-model:open="validationOpen">
|
|
369
|
+
<UButton
|
|
370
|
+
color="neutral"
|
|
371
|
+
variant="ghost"
|
|
372
|
+
class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
|
|
373
|
+
data-testid="result-window-validation-toggle"
|
|
384
374
|
>
|
|
385
|
-
|
|
386
|
-
validationReport.passed
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
375
|
+
<UIcon
|
|
376
|
+
:name="validationReport.passed ? 'i-lucide-shield-check' : 'i-lucide-shield-alert'"
|
|
377
|
+
class="h-3.5 w-3.5 shrink-0"
|
|
378
|
+
:class="validationReport.passed ? 'text-app-success-400' : 'text-app-error-400'"
|
|
379
|
+
/>
|
|
380
|
+
<SectionLabel as="span">
|
|
381
|
+
{{ t('panels.stepDetail.validation.heading') }}
|
|
382
|
+
</SectionLabel>
|
|
383
|
+
<span
|
|
384
|
+
class="shrink-0 rounded-sm px-1.5 py-0.5 text-2xs font-medium tabular-nums"
|
|
385
|
+
:class="
|
|
386
|
+
validationReport.passed
|
|
387
|
+
? 'bg-app-success-500/15 text-app-success-300'
|
|
388
|
+
: 'bg-app-error-500/15 text-app-error-300'
|
|
389
|
+
"
|
|
390
|
+
>
|
|
391
|
+
{{
|
|
392
|
+
validationReport.passed
|
|
393
|
+
? t('panels.stepDetail.validation.passed')
|
|
394
|
+
: t('panels.stepDetail.validation.failed')
|
|
395
|
+
}}
|
|
396
|
+
</span>
|
|
397
|
+
<span class="min-w-0 flex-1 truncate text-xs text-muted">
|
|
398
|
+
{{
|
|
399
|
+
t('panels.stepDetail.validation.attempts', {
|
|
400
|
+
attempts: validationReport.attempts,
|
|
401
|
+
maxAttempts: validationReport.maxAttempts,
|
|
402
|
+
})
|
|
403
|
+
}}
|
|
404
|
+
</span>
|
|
405
|
+
<UIcon
|
|
406
|
+
:name="validationOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
|
|
407
|
+
class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
|
|
408
|
+
/>
|
|
409
|
+
</UButton>
|
|
410
|
+
<template #content>
|
|
411
|
+
<div class="max-h-72 overflow-y-auto px-5 pb-3">
|
|
412
|
+
<StepValidationReport :report="validationReport" />
|
|
413
|
+
</div>
|
|
414
|
+
</template>
|
|
415
|
+
</UCollapsible>
|
|
407
416
|
</section>
|
|
408
417
|
|
|
409
418
|
<!-- Shared trailing section: the bugfix reproduction proof (the declared check run against
|
|
@@ -415,42 +424,45 @@ const panelClass = computed(() => [
|
|
|
415
424
|
class="shrink-0 border-t border-default bg-default/60"
|
|
416
425
|
data-testid="result-window-reproduction"
|
|
417
426
|
>
|
|
418
|
-
<
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
>
|
|
425
|
-
<UIcon
|
|
426
|
-
:name="reproductionKeys!.icon"
|
|
427
|
-
class="h-3.5 w-3.5 shrink-0"
|
|
428
|
-
:class="reproductionKeys!.proven ? 'text-app-success-400' : 'text-app-warning-400'"
|
|
429
|
-
/>
|
|
430
|
-
<span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
431
|
-
{{ t('panels.stepDetail.reproduction.heading') }}
|
|
432
|
-
</span>
|
|
433
|
-
<span
|
|
434
|
-
class="shrink-0 rounded px-1.5 py-0.5 text-[11px] font-medium"
|
|
435
|
-
:class="
|
|
436
|
-
reproductionKeys!.proven
|
|
437
|
-
? 'bg-app-success-500/15 text-app-success-300'
|
|
438
|
-
: 'bg-app-warning-500/15 text-app-warning-300'
|
|
439
|
-
"
|
|
427
|
+
<UCollapsible v-model:open="reproductionOpen">
|
|
428
|
+
<UButton
|
|
429
|
+
color="neutral"
|
|
430
|
+
variant="ghost"
|
|
431
|
+
class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
|
|
432
|
+
data-testid="result-window-reproduction-toggle"
|
|
440
433
|
>
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
434
|
+
<UIcon
|
|
435
|
+
:name="reproductionKeys!.icon"
|
|
436
|
+
class="h-3.5 w-3.5 shrink-0"
|
|
437
|
+
:class="reproductionKeys!.proven ? 'text-app-success-400' : 'text-app-warning-400'"
|
|
438
|
+
/>
|
|
439
|
+
<SectionLabel as="span">
|
|
440
|
+
{{ t('panels.stepDetail.reproduction.heading') }}
|
|
441
|
+
</SectionLabel>
|
|
442
|
+
<span
|
|
443
|
+
class="shrink-0 rounded-sm px-1.5 py-0.5 text-2xs font-medium"
|
|
444
|
+
:class="
|
|
445
|
+
reproductionKeys!.proven
|
|
446
|
+
? 'bg-app-success-500/15 text-app-success-300'
|
|
447
|
+
: 'bg-app-warning-500/15 text-app-warning-300'
|
|
448
|
+
"
|
|
449
|
+
>
|
|
450
|
+
{{ t(reproductionKeys!.chip) }}
|
|
451
|
+
</span>
|
|
452
|
+
<span class="min-w-0 flex-1 truncate text-xs text-muted">
|
|
453
|
+
{{ t(reproductionKeys!.verdict) }}
|
|
454
|
+
</span>
|
|
455
|
+
<UIcon
|
|
456
|
+
:name="reproductionOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
|
|
457
|
+
class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
|
|
458
|
+
/>
|
|
459
|
+
</UButton>
|
|
460
|
+
<template #content>
|
|
461
|
+
<div class="max-h-72 overflow-y-auto px-5 pb-3">
|
|
462
|
+
<StepReproductionReport :report="reproductionReport" />
|
|
463
|
+
</div>
|
|
464
|
+
</template>
|
|
465
|
+
</UCollapsible>
|
|
454
466
|
</section>
|
|
455
467
|
|
|
456
468
|
<!-- Shared trailing section: what this step's agent declared it stored through a
|
|
@@ -463,28 +475,31 @@ const panelClass = computed(() => [
|
|
|
463
475
|
class="shrink-0 border-t border-default bg-default/60"
|
|
464
476
|
data-testid="result-window-binary-outputs"
|
|
465
477
|
>
|
|
466
|
-
<
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
478
|
+
<UCollapsible v-model:open="binaryOutputsOpen">
|
|
479
|
+
<UButton
|
|
480
|
+
color="neutral"
|
|
481
|
+
variant="ghost"
|
|
482
|
+
class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
|
|
483
|
+
data-testid="result-window-binary-outputs-toggle"
|
|
484
|
+
>
|
|
485
|
+
<UIcon name="i-lucide-image" class="h-3.5 w-3.5 shrink-0 text-muted" />
|
|
486
|
+
<SectionLabel as="span">
|
|
487
|
+
{{ t('binaryOutput.heading') }}
|
|
488
|
+
</SectionLabel>
|
|
489
|
+
<span class="min-w-0 flex-1 truncate text-xs text-muted">
|
|
490
|
+
{{ binaryOutputSummary }}
|
|
491
|
+
</span>
|
|
492
|
+
<UIcon
|
|
493
|
+
:name="binaryOutputsOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
|
|
494
|
+
class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
|
|
495
|
+
/>
|
|
496
|
+
</UButton>
|
|
497
|
+
<template #content>
|
|
498
|
+
<div v-if="activeStep" class="max-h-72 overflow-y-auto px-5 pb-3">
|
|
499
|
+
<BinaryOutputReport :step="activeStep" />
|
|
500
|
+
</div>
|
|
501
|
+
</template>
|
|
502
|
+
</UCollapsible>
|
|
488
503
|
</section>
|
|
489
504
|
</div>
|
|
490
505
|
</div>
|
|
@@ -25,7 +25,7 @@ const error = computed(() => execution.fullError(props.instanceId))
|
|
|
25
25
|
<template>
|
|
26
26
|
<div
|
|
27
27
|
v-if="loading || error"
|
|
28
|
-
class="flex items-center gap-2 border-b border-default px-4 py-2 text-
|
|
28
|
+
class="flex items-center gap-2 border-b border-default px-4 py-2 text-2xs"
|
|
29
29
|
:class="error ? 'text-app-error-300' : 'text-muted'"
|
|
30
30
|
data-testid="run-detail-load-state"
|
|
31
31
|
>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import type { PipelineStep, RunContainerStatus } from '~/types/execution'
|
|
4
4
|
import { containerPhaseLabel } from '~/utils/pipelineRender'
|
|
5
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
6
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
5
7
|
|
|
6
8
|
// The per-run container lifecycle for a container-backed step: its status (spinning up /
|
|
7
9
|
// running / errored / reclaimed), the live phase (preparing the checkout vs the agent
|
|
@@ -94,7 +96,7 @@ const { copy: copyText } = useCopyToClipboard()
|
|
|
94
96
|
live phase (preparing the checkout vs the agent making calls), and the
|
|
95
97
|
container's id + reachable URL once up. -->
|
|
96
98
|
<div
|
|
97
|
-
class="rounded-lg border px-3 py-2 text-
|
|
99
|
+
class="rounded-lg border px-3 py-2 text-xs"
|
|
98
100
|
:class="CONTAINER_STATUS_META[containerStatus].cls"
|
|
99
101
|
>
|
|
100
102
|
<div class="flex items-center gap-2">
|
|
@@ -111,45 +113,44 @@ const { copy: copyText } = useCopyToClipboard()
|
|
|
111
113
|
</div>
|
|
112
114
|
<dl v-if="step.container?.id || step.container?.url" class="mt-2 space-y-1">
|
|
113
115
|
<div v-if="step.container?.id" class="flex items-center gap-2">
|
|
114
|
-
<dt class="shrink-0
|
|
116
|
+
<SectionLabel as="dt" class="shrink-0">
|
|
115
117
|
{{ t('panels.stepMeta.container.id') }}
|
|
116
|
-
</
|
|
117
|
-
<dd class="truncate font-mono text-
|
|
118
|
+
</SectionLabel>
|
|
119
|
+
<dd class="truncate font-mono text-2xs text-toned" :title="step.container.id">
|
|
118
120
|
{{ step.container.id }}
|
|
119
121
|
</dd>
|
|
120
|
-
<
|
|
122
|
+
<IconButton
|
|
121
123
|
icon="i-lucide-copy"
|
|
122
124
|
color="neutral"
|
|
123
125
|
variant="ghost"
|
|
124
126
|
size="xs"
|
|
125
127
|
class="ms-auto shrink-0"
|
|
126
|
-
:
|
|
127
|
-
:aria-label="t('panels.stepMeta.container.copyId')"
|
|
128
|
+
:label="t('panels.stepMeta.container.copyId')"
|
|
128
129
|
@click="copyText(step.container.id)"
|
|
129
130
|
/>
|
|
130
131
|
</div>
|
|
131
132
|
<div v-if="step.container?.url" class="flex items-center gap-2">
|
|
132
|
-
<dt class="shrink-0
|
|
133
|
+
<SectionLabel as="dt" class="shrink-0">
|
|
133
134
|
{{ t('panels.stepMeta.container.url') }}
|
|
134
|
-
</
|
|
135
|
-
<dd class="truncate font-mono text-
|
|
136
|
-
<
|
|
137
|
-
|
|
135
|
+
</SectionLabel>
|
|
136
|
+
<dd class="truncate font-mono text-2xs text-toned">
|
|
137
|
+
<ULink
|
|
138
|
+
raw
|
|
139
|
+
:to="step.container.url"
|
|
138
140
|
target="_blank"
|
|
139
141
|
rel="noopener noreferrer"
|
|
140
142
|
class="hover:underline"
|
|
141
143
|
>
|
|
142
144
|
{{ step.container.url }}
|
|
143
|
-
</
|
|
145
|
+
</ULink>
|
|
144
146
|
</dd>
|
|
145
|
-
<
|
|
147
|
+
<IconButton
|
|
146
148
|
icon="i-lucide-copy"
|
|
147
149
|
color="neutral"
|
|
148
150
|
variant="ghost"
|
|
149
151
|
size="xs"
|
|
150
152
|
class="ms-auto shrink-0"
|
|
151
|
-
:
|
|
152
|
-
:aria-label="t('panels.stepMeta.container.copyUrl')"
|
|
153
|
+
:label="t('panels.stepMeta.container.copyUrl')"
|
|
153
154
|
@click="copyText(step.container.url)"
|
|
154
155
|
/>
|
|
155
156
|
</div>
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
externalRunHref,
|
|
7
7
|
} from './StepDelegatedStatus.logic'
|
|
8
8
|
import type { PipelineStep } from '~/types/execution'
|
|
9
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
10
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
9
11
|
|
|
10
12
|
// The EXTERNAL work a delegated step dispatched: which registered executor is running it, what it
|
|
11
13
|
// is doing, and the link to that system's own logs, which is the affordance everything else here
|
|
@@ -77,7 +79,7 @@ const { copy: copyText } = useCopyToClipboard()
|
|
|
77
79
|
<!-- Single conditional root so a passed-through `class` (e.g. layout margin) applies cleanly.
|
|
78
80
|
Renders nothing for a step that dispatched nowhere external. -->
|
|
79
81
|
<div v-if="record" data-testid="step-delegated-status">
|
|
80
|
-
<div class="rounded-lg border px-3 py-2 text-
|
|
82
|
+
<div class="rounded-lg border px-3 py-2 text-xs" :class="statusView.meta.cls">
|
|
81
83
|
<div class="flex items-center gap-2">
|
|
82
84
|
<UIcon
|
|
83
85
|
:name="statusView.meta.icon"
|
|
@@ -98,32 +100,32 @@ const { copy: copyText } = useCopyToClipboard()
|
|
|
98
100
|
<!-- The PRIMARY affordance: the executor's own logs. It is the only place the detail of
|
|
99
101
|
what happened exists, which is why a failed delegated step without it is a dead end. -->
|
|
100
102
|
<div v-if="record.url" class="mt-2 flex items-center gap-2">
|
|
101
|
-
<dt class="shrink-0
|
|
103
|
+
<SectionLabel as="dt" class="shrink-0">
|
|
102
104
|
{{ t('panels.stepMeta.delegated.run') }}
|
|
103
|
-
</
|
|
105
|
+
</SectionLabel>
|
|
104
106
|
<!-- Linked only when the executor's URL is `http(s)`. Anything else is shown as the text
|
|
105
107
|
it is: refusing to follow it is right, and hiding it would report a run that named
|
|
106
108
|
no link at all. -->
|
|
107
|
-
<dd class="truncate font-mono text-
|
|
108
|
-
<
|
|
109
|
+
<dd class="truncate font-mono text-2xs text-toned">
|
|
110
|
+
<ULink
|
|
111
|
+
raw
|
|
109
112
|
v-if="runHref"
|
|
110
|
-
:
|
|
113
|
+
:to="runHref"
|
|
111
114
|
target="_blank"
|
|
112
115
|
rel="noopener noreferrer"
|
|
113
116
|
class="hover:underline"
|
|
114
117
|
>
|
|
115
118
|
{{ record.url }}
|
|
116
|
-
</
|
|
119
|
+
</ULink>
|
|
117
120
|
<span v-else>{{ record.url }}</span>
|
|
118
121
|
</dd>
|
|
119
|
-
<
|
|
122
|
+
<IconButton
|
|
120
123
|
icon="i-lucide-copy"
|
|
121
124
|
color="neutral"
|
|
122
125
|
variant="ghost"
|
|
123
126
|
size="xs"
|
|
124
127
|
class="ms-auto shrink-0"
|
|
125
|
-
:
|
|
126
|
-
:aria-label="t('panels.stepMeta.delegated.copyUrl')"
|
|
128
|
+
:label="t('panels.stepMeta.delegated.copyUrl')"
|
|
127
129
|
@click="copyText(record.url)"
|
|
128
130
|
/>
|
|
129
131
|
</div>
|
|
@@ -132,48 +134,49 @@ const { copy: copyText } = useCopyToClipboard()
|
|
|
132
134
|
request. Rendered here because the platform holds nothing else about that run's
|
|
133
135
|
product. -->
|
|
134
136
|
<div v-if="landedBranch" class="mt-2 flex items-center gap-2">
|
|
135
|
-
<dt class="shrink-0
|
|
137
|
+
<SectionLabel as="dt" class="shrink-0">
|
|
136
138
|
{{ t('panels.stepMeta.delegated.branch') }}
|
|
137
|
-
</
|
|
138
|
-
<dd class="truncate font-mono text-
|
|
139
|
+
</SectionLabel>
|
|
140
|
+
<dd class="truncate font-mono text-2xs text-toned">{{ landedBranch }}</dd>
|
|
139
141
|
</div>
|
|
140
142
|
|
|
141
143
|
<!-- What the platform could not do, stated rather than left to read as a clean outcome:
|
|
142
144
|
a cancelled run whose executor declares no cancel is still going. -->
|
|
143
|
-
<p v-if="record.note" class="mt-2 text-
|
|
145
|
+
<p v-if="record.note" class="mt-2 text-2xs text-toned">{{ record.note }}</p>
|
|
144
146
|
</div>
|
|
145
147
|
|
|
146
148
|
<!-- "Absent" and "zero" must never render the same. Without this line a delegated step shows
|
|
147
149
|
no tokens beside a container step that shows some, and the only available reading is that
|
|
148
150
|
it was free. -->
|
|
149
|
-
<p v-if="usageUnreported" class="mt-2 text-
|
|
151
|
+
<p v-if="usageUnreported" class="mt-2 text-2xs text-dimmed">
|
|
150
152
|
{{ t('panels.stepMeta.delegated.usageNotReported', { executor: executorName }) }}
|
|
151
153
|
</p>
|
|
152
154
|
|
|
153
155
|
<!-- Earlier attempts. Kept across a re-run on purpose: the previous run's logs are the
|
|
154
156
|
evidence for why this step is being run again, and the platform holds nothing else. -->
|
|
155
157
|
<div v-if="priorAttempts.length" class="mt-3">
|
|
156
|
-
<
|
|
158
|
+
<SectionLabel>
|
|
157
159
|
{{ t('panels.stepMeta.delegated.earlierAttempts') }}
|
|
158
|
-
</
|
|
160
|
+
</SectionLabel>
|
|
159
161
|
<ul class="mt-1 space-y-1">
|
|
160
162
|
<li
|
|
161
163
|
v-for="(attempt, index) in priorAttempts"
|
|
162
164
|
:key="`${attempt.startedAt}-${index}`"
|
|
163
|
-
class="flex items-center gap-2 text-
|
|
165
|
+
class="flex items-center gap-2 text-2xs text-muted"
|
|
164
166
|
>
|
|
165
167
|
<span class="truncate">{{
|
|
166
168
|
attempt.outcome || t('panels.stepMeta.delegated.noOutcome')
|
|
167
169
|
}}</span>
|
|
168
|
-
<
|
|
170
|
+
<ULink
|
|
171
|
+
raw
|
|
169
172
|
v-if="externalRunHref(attempt.url)"
|
|
170
|
-
:
|
|
173
|
+
:to="externalRunHref(attempt.url)!"
|
|
171
174
|
target="_blank"
|
|
172
175
|
rel="noopener noreferrer"
|
|
173
176
|
class="ms-auto shrink-0 font-mono hover:underline"
|
|
174
177
|
>
|
|
175
178
|
{{ t('panels.stepMeta.delegated.openRun') }}
|
|
176
|
-
</
|
|
179
|
+
</ULink>
|
|
177
180
|
</li>
|
|
178
181
|
</ul>
|
|
179
182
|
</div>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// second one plus a nested border would just be chrome inside chrome.
|
|
11
11
|
import type { AgentEffortReport } from '~/types/execution'
|
|
12
12
|
import { effortBand } from '~/utils/effort'
|
|
13
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
13
14
|
|
|
14
15
|
const props = withDefaults(
|
|
15
16
|
defineProps<{ report: AgentEffortReport; variant?: 'card' | 'flat' }>(),
|
|
@@ -37,16 +38,13 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
|
|
|
37
38
|
variant === 'card' ? 'scroll-mt-4 rounded-xl border border-default bg-default/50 p-4' : ''
|
|
38
39
|
"
|
|
39
40
|
>
|
|
40
|
-
<
|
|
41
|
-
v-if="variant === 'card'"
|
|
42
|
-
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
|
|
43
|
-
>
|
|
41
|
+
<SectionLabel v-if="variant === 'card'" class="mb-2 flex items-center gap-1.5">
|
|
44
42
|
<UIcon name="i-lucide-gauge" class="h-3.5 w-3.5" />
|
|
45
43
|
<span>{{ t('panels.stepDetail.effort.heading') }}</span>
|
|
46
|
-
</
|
|
44
|
+
</SectionLabel>
|
|
47
45
|
|
|
48
46
|
<div class="flex items-center gap-2">
|
|
49
|
-
<span class="text-
|
|
47
|
+
<span class="text-xs text-toned" :title="t('panels.stepDetail.effort.difficultyHint')">
|
|
50
48
|
{{ t('panels.stepDetail.effort.difficulty') }}
|
|
51
49
|
</span>
|
|
52
50
|
<div class="h-1.5 flex-1 overflow-hidden rounded-full bg-accented/60">
|
|
@@ -58,38 +56,35 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
|
|
|
58
56
|
</div>
|
|
59
57
|
<span
|
|
60
58
|
data-testid="step-effort-difficulty"
|
|
61
|
-
class="text-
|
|
59
|
+
class="text-xs font-medium text-default"
|
|
62
60
|
:title="t('panels.stepDetail.effort.difficultyHint')"
|
|
63
61
|
>
|
|
64
62
|
{{ t('panels.stepDetail.effort.outOfTen', { value: report.difficulty }) }}
|
|
65
63
|
</span>
|
|
66
64
|
</div>
|
|
67
65
|
|
|
68
|
-
<p
|
|
69
|
-
v-if="report.summary"
|
|
70
|
-
class="mt-2 whitespace-pre-wrap text-[13px] leading-relaxed text-toned"
|
|
71
|
-
>
|
|
66
|
+
<p v-if="report.summary" class="mt-2 whitespace-pre-wrap text-sm leading-relaxed text-toned">
|
|
72
67
|
{{ report.summary }}
|
|
73
68
|
</p>
|
|
74
69
|
|
|
75
70
|
<div v-if="report.reducedEffectiveness" class="mt-3">
|
|
76
|
-
<
|
|
71
|
+
<SectionLabel as="p">
|
|
77
72
|
{{ t('panels.stepDetail.effort.reduced') }}
|
|
78
|
-
</
|
|
79
|
-
<p class="mt-0.5 whitespace-pre-wrap text-
|
|
73
|
+
</SectionLabel>
|
|
74
|
+
<p class="mt-0.5 whitespace-pre-wrap text-xs text-toned">
|
|
80
75
|
{{ report.reducedEffectiveness }}
|
|
81
76
|
</p>
|
|
82
77
|
</div>
|
|
83
78
|
|
|
84
79
|
<div v-if="report.obstacles?.length" class="mt-3">
|
|
85
|
-
<
|
|
80
|
+
<SectionLabel as="p">
|
|
86
81
|
{{ t('panels.stepDetail.effort.obstacles') }}
|
|
87
|
-
</
|
|
82
|
+
</SectionLabel>
|
|
88
83
|
<ul class="mt-0.5 space-y-1">
|
|
89
84
|
<li
|
|
90
85
|
v-for="(obstacle, i) in report.obstacles"
|
|
91
86
|
:key="i"
|
|
92
|
-
class="flex items-start gap-1.5 text-
|
|
87
|
+
class="flex items-start gap-1.5 text-xs text-toned"
|
|
93
88
|
>
|
|
94
89
|
<UIcon
|
|
95
90
|
name="i-lucide-alert-triangle"
|