@cat-factory/app 0.302.1 → 0.303.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 +16 -0
- package/app/app.config.ts +19 -10
- package/app/assets/css/main.css +13 -13
- package/app/assets/css/prose.css +22 -22
- package/app/assets/css/tokens.css +298 -0
- package/app/components/assistant/AssistantModal.vue +22 -22
- package/app/components/auth/AuthGate.vue +1 -1
- package/app/components/auth/BackendMisconfiguredScreen.vue +10 -10
- package/app/components/auth/LoginScreen.vue +34 -36
- package/app/components/auth/ResetPasswordScreen.vue +12 -12
- package/app/components/auth/UserMenu.vue +4 -4
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +27 -25
- package/app/components/binaryOutput/BinaryOutputReport.vue +15 -15
- package/app/components/binaryOutput/StoredAssetView.vue +5 -5
- package/app/components/board/AddTaskModal.vue +17 -20
- package/app/components/board/AgentFailureCard.vue +11 -11
- package/app/components/board/AgentFailureHistory.vue +2 -2
- package/app/components/board/BoardCanvas.vue +6 -5
- package/app/components/board/CreateInitiativeModal.vue +8 -10
- package/app/components/board/DependencyConnectOverlay.vue +1 -1
- package/app/components/board/FailureHistoryList.vue +7 -7
- package/app/components/board/RecurringPipelineModal.vue +17 -17
- package/app/components/board/ReviewFrictionDialog.vue +6 -6
- package/app/components/board/StepExecutionHistory.vue +13 -13
- package/app/components/board/TaskDependencyEdges.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +10 -10
- package/app/components/board/nodes/BlockNode.vue +29 -29
- package/app/components/board/nodes/DecisionBadge.vue +2 -2
- package/app/components/board/nodes/EpicNode.vue +14 -10
- package/app/components/board/nodes/FrameSwimlanes.vue +7 -9
- package/app/components/board/nodes/InitiativeCard.vue +8 -8
- package/app/components/board/nodes/LaneGroup.vue +1 -1
- package/app/components/board/nodes/LaneTask.vue +2 -2
- package/app/components/board/nodes/ResizeGrips.vue +4 -4
- package/app/components/board/nodes/TaskCard.vue +18 -18
- package/app/components/board/nodes/TaskLane.vue +5 -5
- package/app/components/board/nodes/TaskPipelineMini.vue +18 -18
- package/app/components/bootstrap/AdoptionReviewModal.vue +29 -26
- package/app/components/bootstrap/BootstrapModal.vue +21 -23
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +30 -33
- package/app/components/bugFishing/BugFishingWindow.vue +49 -49
- package/app/components/clarity/ClarityReviewWindow.vue +30 -30
- package/app/components/common/AsyncViewError.vue +5 -5
- package/app/components/common/ClarificationItem.vue +8 -13
- package/app/components/common/ConfirmDialog.vue +4 -2
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +3 -3
- package/app/components/common/InterviewGateNotice.vue +7 -7
- package/app/components/common/KeyboardShortcutsHelp.vue +1 -1
- package/app/components/common/MarkdownProse.vue +14 -13
- package/app/components/consensus/ConsensusSessionWindow.vue +26 -26
- package/app/components/context/ContextAttachmentFields.vue +17 -17
- package/app/components/docs/DocInterviewWindow.vue +14 -14
- package/app/components/documents/ContextDocumentPicker.vue +17 -17
- package/app/components/documents/DocumentImportModal.vue +7 -7
- package/app/components/documents/DocumentSourceConnectModal.vue +3 -3
- package/app/components/documents/DocumentSyncState.vue +5 -5
- package/app/components/documents/DocumentTemplatesModal.vue +15 -15
- package/app/components/documents/RepoContextDocPicker.vue +5 -5
- package/app/components/documents/SpawnPreviewModal.vue +12 -12
- package/app/components/documents/StartFromDesignModal.vue +11 -11
- package/app/components/documents/TaskContextDocs.vue +5 -5
- package/app/components/environments/EnvSetupStepper.vue +6 -6
- package/app/components/environments/EnvironmentStatusPanel.vue +17 -17
- package/app/components/environments/steps/EnvPickStep.vue +3 -3
- package/app/components/environments/steps/EnvPreflightStep.vue +9 -9
- package/app/components/environments/steps/EnvReviewStep.vue +25 -22
- package/app/components/environments/steps/EnvSaveStep.vue +7 -5
- package/app/components/environments/steps/JourneyStepNav.vue +1 -1
- package/app/components/focus/BlockFocusView.vue +17 -19
- package/app/components/followUp/FollowUpWindow.vue +23 -23
- package/app/components/forkDecision/ForkDecisionWindow.vue +37 -39
- package/app/components/foundational/FoundationalContractSummary.vue +7 -7
- package/app/components/foundational/FoundationalServiceCatalogList.vue +11 -11
- package/app/components/foundational/FoundationalServiceManager.vue +1 -1
- package/app/components/foundational/FoundationalServiceRegistry.vue +13 -13
- package/app/components/foundational/FoundationalServiceSources.vue +13 -13
- package/app/components/foundational/FoundationalSuppressions.vue +7 -7
- package/app/components/foundational/ServiceCatalogConnection.vue +10 -10
- package/app/components/fragments/FragmentLibraryManager.vue +41 -44
- package/app/components/fragments/FragmentSelector.vue +13 -13
- package/app/components/fragments/GitHubDocUrlImport.vue +1 -1
- package/app/components/gates/GateFailingCheckList.vue +5 -5
- package/app/components/gates/GateResultView.vue +50 -47
- package/app/components/github/AddServiceFromRepoModal.vue +14 -14
- package/app/components/github/BranchProtectionPreflight.vue +13 -13
- package/app/components/github/GitHubConnect.vue +7 -7
- package/app/components/github/GitHubOnboarding.vue +7 -7
- package/app/components/github/GitHubPanel.vue +37 -40
- package/app/components/github/RepoTreeBrowser.vue +18 -18
- package/app/components/humanTest/HumanTestWindow.vue +30 -33
- package/app/components/initiative/InitiativePlanNotice.vue +5 -5
- package/app/components/initiative/InitiativePlanReview.vue +27 -29
- package/app/components/initiative/InitiativePlanningWindow.vue +10 -10
- package/app/components/initiative/InitiativeTrackerWindow.vue +71 -65
- package/app/components/inputGate/InputGateNotice.vue +2 -4
- package/app/components/judge/JudgeResultView.vue +30 -32
- package/app/components/kaizen/KaizenPanel.vue +40 -36
- package/app/components/kaizen/KaizenStepStatus.vue +21 -21
- package/app/components/layout/AccountAuditLog.vue +10 -10
- package/app/components/layout/AccountDeploymentSettings.vue +20 -20
- 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 +9 -9
- package/app/components/layout/AccountPlatformAlertSettings.vue +11 -11
- package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
- package/app/components/layout/AccountRunCredentialSettings.vue +5 -5
- package/app/components/layout/AccountSkillSettings.vue +1 -1
- package/app/components/layout/AccountTeamSettings.vue +23 -15
- package/app/components/layout/AiProvidersBanner.vue +11 -8
- package/app/components/layout/AppearanceSwitcher.vue +108 -0
- package/app/components/layout/BoardSwitcher.vue +8 -11
- package/app/components/layout/BoardToolbar.vue +3 -3
- package/app/components/layout/CommandBar.vue +7 -9
- package/app/components/layout/ConnectionStatusBanner.vue +2 -2
- package/app/components/layout/DefaultTestEnvBanner.vue +5 -5
- package/app/components/layout/GitHubPatBanner.vue +5 -5
- package/app/components/layout/GitHubPatPermissionsBanner.vue +16 -10
- package/app/components/layout/InfraSetupBanner.vue +6 -6
- package/app/components/layout/IntegrationsHub.vue +15 -15
- package/app/components/layout/LanguageSwitcher.vue +5 -5
- package/app/components/layout/ModelProvidersHub.vue +13 -16
- package/app/components/layout/NotificationsInbox.vue +10 -10
- package/app/components/layout/PersonalSetupModal.vue +8 -8
- package/app/components/layout/ProviderConfigBanner.vue +4 -4
- package/app/components/layout/RolePrompt.vue +7 -7
- package/app/components/layout/SideBar.vue +6 -4
- package/app/components/layout/SpendWarningBanner.vue +17 -14
- package/app/components/layout/TranslationWarningBanner.vue +4 -4
- package/app/components/layout/UiModeSwitcher.vue +13 -13
- package/app/components/layout/UiRoleSwitcher.vue +8 -8
- package/app/components/layout/WorkspaceMembersSettings.vue +15 -11
- package/app/components/media/ArtifactLightbox.vue +13 -13
- package/app/components/media/ImageCompare.vue +31 -24
- package/app/components/merge/MergeEffortChips.vue +2 -2
- package/app/components/notifications/NotificationSettingsPanel.vue +14 -12
- package/app/components/observability/OutcomeFilterChips.vue +6 -6
- package/app/components/observability/RunFailureSummary.vue +28 -25
- package/app/components/observability/StepMetricsBar.vue +26 -28
- package/app/components/observability/StepModelActivity.vue +2 -2
- package/app/components/observability/ToolCallList.vue +24 -24
- package/app/components/outcome/OutcomeSummaryWindow.vue +47 -47
- package/app/components/palettes/AgentPalette.vue +8 -8
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +52 -51
- package/app/components/panels/AttemptEntryHeader.vue +4 -6
- package/app/components/panels/DecisionModal.vue +7 -7
- package/app/components/panels/GenericStructuredResultView.vue +7 -7
- package/app/components/panels/InspectorPanel.vue +17 -17
- package/app/components/panels/MergerResultView.vue +19 -19
- package/app/components/panels/ObservabilityPanel.vue +115 -123
- package/app/components/panels/OperatorDashboardPanel.vue +89 -97
- package/app/components/panels/ReportsPanel.vue +69 -66
- package/app/components/panels/ReportsSpendBreakdown.vue +9 -9
- package/app/components/panels/ResultWindowShell.vue +38 -38
- package/app/components/panels/RunDetailLoadState.vue +2 -2
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.logic.spec.ts +135 -0
- package/app/components/panels/StepDelegatedStatus.logic.ts +160 -0
- package/app/components/panels/StepDelegatedStatus.vue +181 -0
- package/app/components/panels/StepEffortReport.vue +16 -15
- package/app/components/panels/StepFragmentAdherence.vue +14 -10
- package/app/components/panels/StepMetadataCard.vue +74 -45
- package/app/components/panels/StepReproductionReport.vue +25 -21
- package/app/components/panels/StepRunMeta.vue +20 -20
- package/app/components/panels/StepTestReport.logic.spec.ts +8 -3
- package/app/components/panels/StepTestReport.logic.ts +4 -4
- package/app/components/panels/StepTestReport.vue +28 -28
- package/app/components/panels/StepToolServers.vue +14 -11
- package/app/components/panels/StepValidationReport.vue +7 -7
- package/app/components/panels/inspector/ContainerSummary.vue +9 -9
- package/app/components/panels/inspector/DocReferenceRepos.vue +3 -3
- package/app/components/panels/inspector/EnvProbeReport.vue +24 -27
- package/app/components/panels/inspector/EpicChildren.vue +8 -12
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +11 -11
- package/app/components/panels/inspector/FrontendConfig.vue +37 -41
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +6 -6
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +16 -19
- package/app/components/panels/inspector/ServiceConnections.vue +2 -2
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
- package/app/components/panels/inspector/ServiceSelfTests.vue +21 -17
- package/app/components/panels/inspector/ServiceTestConfig.vue +51 -59
- package/app/components/panels/inspector/ServiceTestSecrets.vue +5 -5
- package/app/components/panels/inspector/ServiceTestingContext.vue +3 -3
- package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAgentConfig.vue +3 -3
- package/app/components/panels/inspector/TaskAprioriBranches.vue +8 -5
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +11 -11
- package/app/components/panels/inspector/TaskExecution.vue +17 -17
- package/app/components/panels/inspector/TaskReviewTarget.vue +2 -2
- package/app/components/panels/inspector/TaskRunSettings.vue +35 -37
- package/app/components/panels/inspector/TaskStructure.vue +3 -3
- package/app/components/pipeline/AgentKindIcon.vue +1 -1
- package/app/components/pipeline/AgentPromptEditor.vue +17 -17
- package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -56
- package/app/components/pipeline/EstimateThresholdFields.vue +4 -4
- package/app/components/pipeline/GateConfigFields.vue +13 -10
- package/app/components/pipeline/IterationCapPrompt.vue +4 -2
- package/app/components/pipeline/PipelineBuilder.vue +47 -55
- package/app/components/pipeline/PipelineHealthModal.vue +27 -29
- package/app/components/pipeline/PipelinePicker.vue +10 -10
- package/app/components/pipeline/PipelinePreview.vue +10 -10
- package/app/components/pipeline/PipelineProgress.vue +64 -67
- package/app/components/prReview/PrReviewPhaseBadge.vue +7 -7
- package/app/components/prReview/PrReviewWindow.vue +75 -77
- package/app/components/providers/AiPresetMismatchDialog.vue +5 -5
- package/app/components/providers/AiProviderOnboardingModal.vue +9 -9
- package/app/components/providers/ApiKeysSection.vue +13 -13
- package/app/components/providers/PersonalCredentialModal.vue +2 -2
- package/app/components/providers/PersonalSubscriptionSection.vue +10 -10
- package/app/components/providers/SignInRequiredNotice.vue +1 -1
- package/app/components/providers/VendorCredentialsModal.vue +10 -10
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +13 -13
- package/app/components/ralph/RalphLoopResultView.vue +28 -30
- package/app/components/recurring/RecurrenceEditor.vue +2 -2
- package/app/components/requirements/RequirementsReviewWindow.vue +51 -58
- package/app/components/riskPolicy/RiskPolicyPicker.vue +12 -15
- package/app/components/riskPolicy/RiskPolicyPreview.vue +14 -14
- package/app/components/sandbox/SandboxPanel.vue +58 -59
- package/app/components/settings/AccountSettingsPanel.vue +1 -1
- package/app/components/settings/ApiTokensPanel.vue +10 -10
- package/app/components/settings/BudgetSettings.vue +18 -22
- package/app/components/settings/CapabilityCredentialsPanel.vue +15 -15
- package/app/components/settings/CloudflareHandlerSection.vue +20 -20
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +13 -13
- package/app/components/settings/ConnectionTestVerdict.vue +3 -3
- package/app/components/settings/ConnectionWarnings.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +27 -35
- package/app/components/settings/CustomManifestTypeEditor.vue +10 -10
- package/app/components/settings/DefaultProvisionTypeSection.vue +6 -6
- package/app/components/settings/InfraHandlersConfigurator.vue +24 -22
- package/app/components/settings/InfrastructureBackendPicker.vue +6 -6
- package/app/components/settings/InfrastructureWindow.vue +5 -5
- package/app/components/settings/IssueTrackerPanel.vue +29 -23
- package/app/components/settings/KubernetesEngineForm.vue +11 -11
- package/app/components/settings/KubernetesEnvironmentForm.vue +4 -4
- package/app/components/settings/LocalContainerPoolSettings.vue +6 -11
- package/app/components/settings/LocalModelEndpointsPanel.vue +20 -18
- package/app/components/settings/McpAuthorizeScreen.vue +13 -15
- package/app/components/settings/McpOAuthCallbackScreen.vue +16 -10
- package/app/components/settings/MergeClassRulesEditor.vue +6 -9
- package/app/components/settings/MergeRolePolicyEditor.vue +16 -16
- package/app/components/settings/ModelConfigurationPanel.vue +23 -30
- package/app/components/settings/ModelPresetHealthModal.vue +15 -13
- package/app/components/settings/ObservabilityConnectionPanel.vue +4 -4
- package/app/components/settings/OpenRouterCatalogPanel.vue +23 -19
- package/app/components/settings/PackageRegistriesPanel.vue +8 -8
- package/app/components/settings/ProviderConnectionTab.vue +8 -11
- package/app/components/settings/ProviderManifestEditor.vue +9 -9
- package/app/components/settings/ProviderPreferenceEditor.vue +8 -8
- package/app/components/settings/RiskPolicyCreateForm.vue +10 -10
- package/app/components/settings/RiskPolicyEditorRow.vue +14 -14
- package/app/components/settings/RiskPolicyHealthModal.vue +15 -13
- package/app/components/settings/RiskPolicyInheritedRow.vue +1 -1
- package/app/components/settings/RiskPolicyPanel.vue +10 -15
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +7 -7
- package/app/components/settings/SharedStacksPanel.vue +9 -12
- package/app/components/settings/TaskSourceCard.vue +4 -4
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +6 -6
- package/app/components/settings/ToolServerChecklist.vue +36 -29
- package/app/components/settings/UsageSettings.vue +15 -15
- package/app/components/settings/UserSecretsSection.vue +9 -12
- package/app/components/settings/WorkspaceMetadataSettings.vue +5 -5
- package/app/components/settings/WorkspaceSettingsPanel.vue +47 -47
- package/app/components/skills/ReviewSkillQueue.vue +10 -10
- package/app/components/skills/SkillLibraryManager.vue +23 -20
- package/app/components/slack/SlackPanel.vue +13 -17
- package/app/components/spec/ServiceSpecWindow.vue +45 -42
- package/app/components/tasks/BugHuntModal.vue +24 -27
- package/app/components/tasks/ContextIssuePicker.vue +11 -11
- package/app/components/tasks/TaskContextIssues.vue +3 -3
- package/app/components/tasks/TaskImportModal.vue +7 -7
- package/app/components/tasks/TaskSourceConnectModal.vue +10 -8
- package/app/components/testing/TestReportWindow.vue +99 -82
- package/app/components/theme/ThemeImportModal.vue +115 -0
- package/app/components/tutorial/TutorialCatalogue.vue +9 -9
- package/app/components/tutorial/TutorialNudge.vue +5 -5
- package/app/components/tutorial/TutorialOverlay.vue +12 -12
- package/app/components/tutorial/TutorialPrompt.vue +6 -9
- package/app/components/vcs/GitLabConnect.vue +4 -4
- package/app/components/vcs/VcsConnectSurfaces.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +36 -36
- package/app/composables/api/client.ts +6 -1
- package/app/composables/usePipelineErrorToast.ts +17 -0
- package/app/modular/agent-kinds.ts +24 -0
- package/app/pages/index.vue +5 -5
- package/app/plugins/theme.client.ts +125 -0
- package/app/spa-loading-template.html +52 -14
- package/app/stores/agents.ts +1 -1
- package/app/stores/theme.spec.ts +56 -0
- package/app/stores/theme.ts +87 -0
- package/app/types/domain.ts +19 -0
- package/app/types/execution.ts +4 -0
- package/app/utils/agentOutput.ts +1 -1
- package/app/utils/binaryOutput.ts +6 -6
- package/app/utils/bootstrapSteps.ts +14 -14
- package/app/utils/catalog.ts +87 -83
- package/app/utils/colorTint.ts +10 -0
- package/app/utils/failureKinds.ts +1 -0
- package/app/utils/observability.ts +3 -3
- package/app/utils/pipelineRender.ts +13 -17
- package/app/utils/swimlanes.ts +4 -4
- package/app/utils/theme/bootPalette.spec.ts +54 -0
- package/app/utils/theme/bootPalette.ts +108 -0
- package/app/utils/theme/builtins.spec.ts +38 -0
- package/app/utils/theme/builtins.ts +55 -0
- package/app/utils/theme/css.ts +162 -0
- package/app/utils/theme/doc.ts +353 -0
- package/app/utils/theme/link.ts +93 -0
- package/app/utils/theme/presets.ts +509 -0
- package/app/utils/theme/theme.spec.ts +224 -0
- package/i18n/locales/de.json +61 -4
- package/i18n/locales/en.json +70 -4
- package/i18n/locales/es.json +61 -4
- package/i18n/locales/fr.json +61 -4
- package/i18n/locales/he.json +61 -4
- package/i18n/locales/it.json +61 -4
- package/i18n/locales/ja.json +61 -4
- package/i18n/locales/pl.json +61 -4
- package/i18n/locales/tr.json +61 -4
- package/i18n/locales/uk.json +61 -4
- package/nuxt.config.ts +37 -11
- package/package.json +10 -9
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
delegatedUsageUnreported,
|
|
5
|
+
delegationStatusView,
|
|
6
|
+
externalRunHref,
|
|
7
|
+
} from './StepDelegatedStatus.logic'
|
|
8
|
+
import type { PipelineStep } from '~/types/execution'
|
|
9
|
+
|
|
10
|
+
// The EXTERNAL work a delegated step dispatched: which registered executor is running it, what it
|
|
11
|
+
// is doing, and the link to that system's own logs, which is the affordance everything else here
|
|
12
|
+
// exists to frame.
|
|
13
|
+
//
|
|
14
|
+
// The sibling of `StepContainerStatus`, and deliberately not the same component. A container step
|
|
15
|
+
// reports a phase, an id and a reachable address, all of which the platform observes directly; a
|
|
16
|
+
// delegated step reports whatever an external system chose to tell us, which is usually a status
|
|
17
|
+
// and a URL. Rendering the second through the first would put empty rows labelled "Container" and
|
|
18
|
+
// "Address" on every delegated step, and would claim a container the platform never started.
|
|
19
|
+
//
|
|
20
|
+
// The second thing it says is what the platform CANNOT see. A delegated step's model calls never
|
|
21
|
+
// touch this deployment's proxy or recorder, so its tokens are in no total on this page, and a
|
|
22
|
+
// missing number is invisible. See `delegatedUsageUnreported`, which answers a settled step from
|
|
23
|
+
// contracts' own rule, the one the backend's gap fold reads, so the card and the debug overview
|
|
24
|
+
// cannot disagree about one step.
|
|
25
|
+
const props = defineProps<{
|
|
26
|
+
step: PipelineStep
|
|
27
|
+
/**
|
|
28
|
+
* The registered executor's presentation, when this build still registers it. ABSENT is a real
|
|
29
|
+
* state rather than a loading one: a deployment can stop registering an executor while runs that
|
|
30
|
+
* used it are still on the board, and the card then names the id instead of pretending to a
|
|
31
|
+
* label it does not have.
|
|
32
|
+
*/
|
|
33
|
+
executor?: { label: string; description: string; telemetry: 'not-reported' | 'self-reported' }
|
|
34
|
+
}>()
|
|
35
|
+
|
|
36
|
+
const { t } = useI18n()
|
|
37
|
+
|
|
38
|
+
const record = computed(() => props.step.delegated ?? null)
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Everything the card renders for this record's status, narrowed against the vocabulary this build
|
|
42
|
+
* ships. See `StepDelegatedStatus.logic` for why a bare `Record` lookup cannot be used here.
|
|
43
|
+
*/
|
|
44
|
+
const statusView = computed(() => delegationStatusView(record.value?.status))
|
|
45
|
+
|
|
46
|
+
/** The executor's own label when this build registers it, else the persisted id. */
|
|
47
|
+
const executorName = computed(() => props.executor?.label || record.value?.executor || '')
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The branch the work LANDED on, shown only when there is no pull request to show instead.
|
|
51
|
+
*
|
|
52
|
+
* An executor that pushes and lets a later step open the PR is a case the port names as
|
|
53
|
+
* legitimate, and then this is the run's entire product: without it the card reports a completed
|
|
54
|
+
* external run with nothing to point at.
|
|
55
|
+
*/
|
|
56
|
+
const landedBranch = computed(() => record.value?.branch ?? null)
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The run link, only when it is one this SPA may follow. The value comes from an external
|
|
60
|
+
* system's API, and this is the card's primary affordance; see {@link externalRunHref}.
|
|
61
|
+
*/
|
|
62
|
+
const runHref = computed(() => externalRunHref(record.value?.url))
|
|
63
|
+
|
|
64
|
+
/** Whether to say the platform is not measuring this step's spend; see the logic sibling. */
|
|
65
|
+
const usageUnreported = computed(() => delegatedUsageUnreported(props.step, props.executor))
|
|
66
|
+
|
|
67
|
+
/** Earlier attempts, newest last, shown only once there is more than the current one. */
|
|
68
|
+
const priorAttempts = computed(() => {
|
|
69
|
+
const attempts = record.value?.attempts ?? []
|
|
70
|
+
return attempts.length > 1 ? attempts.slice(0, -1) : []
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const { copy: copyText } = useCopyToClipboard()
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<!-- Single conditional root so a passed-through `class` (e.g. layout margin) applies cleanly.
|
|
78
|
+
Renders nothing for a step that dispatched nowhere external. -->
|
|
79
|
+
<div v-if="record" data-testid="step-delegated-status">
|
|
80
|
+
<div class="rounded-lg border px-3 py-2 text-[12px]" :class="statusView.meta.cls">
|
|
81
|
+
<div class="flex items-center gap-2">
|
|
82
|
+
<UIcon
|
|
83
|
+
:name="statusView.meta.icon"
|
|
84
|
+
class="h-4 w-4 shrink-0"
|
|
85
|
+
:class="statusView.meta.spin ? 'animate-spin' : ''"
|
|
86
|
+
/>
|
|
87
|
+
<!-- A status this build does not know is NAMED as unrecognised, carrying the stored value,
|
|
88
|
+
rather than guessed onto a current one or silently dropped. -->
|
|
89
|
+
<span class="font-medium">{{ t(statusView.labelKey, statusView.labelParams) }}</span>
|
|
90
|
+
<span class="text-dimmed">·</span>
|
|
91
|
+
<span class="truncate" :title="executor?.description">{{ executorName }}</span>
|
|
92
|
+
<template v-if="record.phase && statusView.status === 'running'">
|
|
93
|
+
<span class="text-dimmed">·</span>
|
|
94
|
+
<span>{{ record.phase }}</span>
|
|
95
|
+
</template>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<!-- The PRIMARY affordance: the executor's own logs. It is the only place the detail of
|
|
99
|
+
what happened exists, which is why a failed delegated step without it is a dead end. -->
|
|
100
|
+
<div v-if="record.url" class="mt-2 flex items-center gap-2">
|
|
101
|
+
<dt class="shrink-0 text-[11px] uppercase tracking-wide text-dimmed">
|
|
102
|
+
{{ t('panels.stepMeta.delegated.run') }}
|
|
103
|
+
</dt>
|
|
104
|
+
<!-- Linked only when the executor's URL is `http(s)`. Anything else is shown as the text
|
|
105
|
+
it is: refusing to follow it is right, and hiding it would report a run that named
|
|
106
|
+
no link at all. -->
|
|
107
|
+
<dd class="truncate font-mono text-[11px] text-toned">
|
|
108
|
+
<a
|
|
109
|
+
v-if="runHref"
|
|
110
|
+
:href="runHref"
|
|
111
|
+
target="_blank"
|
|
112
|
+
rel="noopener noreferrer"
|
|
113
|
+
class="hover:underline"
|
|
114
|
+
>
|
|
115
|
+
{{ record.url }}
|
|
116
|
+
</a>
|
|
117
|
+
<span v-else>{{ record.url }}</span>
|
|
118
|
+
</dd>
|
|
119
|
+
<UButton
|
|
120
|
+
icon="i-lucide-copy"
|
|
121
|
+
color="neutral"
|
|
122
|
+
variant="ghost"
|
|
123
|
+
size="xs"
|
|
124
|
+
class="ms-auto shrink-0"
|
|
125
|
+
:title="t('panels.stepMeta.delegated.copyUrl')"
|
|
126
|
+
:aria-label="t('panels.stepMeta.delegated.copyUrl')"
|
|
127
|
+
@click="copyText(record.url)"
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<!-- The branch the work landed on, for an executor that pushed without opening a pull
|
|
132
|
+
request. Rendered here because the platform holds nothing else about that run's
|
|
133
|
+
product. -->
|
|
134
|
+
<div v-if="landedBranch" class="mt-2 flex items-center gap-2">
|
|
135
|
+
<dt class="shrink-0 text-[11px] uppercase tracking-wide text-dimmed">
|
|
136
|
+
{{ t('panels.stepMeta.delegated.branch') }}
|
|
137
|
+
</dt>
|
|
138
|
+
<dd class="truncate font-mono text-[11px] text-toned">{{ landedBranch }}</dd>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<!-- What the platform could not do, stated rather than left to read as a clean outcome:
|
|
142
|
+
a cancelled run whose executor declares no cancel is still going. -->
|
|
143
|
+
<p v-if="record.note" class="mt-2 text-[11px] text-toned">{{ record.note }}</p>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<!-- "Absent" and "zero" must never render the same. Without this line a delegated step shows
|
|
147
|
+
no tokens beside a container step that shows some, and the only available reading is that
|
|
148
|
+
it was free. -->
|
|
149
|
+
<p v-if="usageUnreported" class="mt-2 text-[11px] text-dimmed">
|
|
150
|
+
{{ t('panels.stepMeta.delegated.usageNotReported', { executor: executorName }) }}
|
|
151
|
+
</p>
|
|
152
|
+
|
|
153
|
+
<!-- Earlier attempts. Kept across a re-run on purpose: the previous run's logs are the
|
|
154
|
+
evidence for why this step is being run again, and the platform holds nothing else. -->
|
|
155
|
+
<div v-if="priorAttempts.length" class="mt-3">
|
|
156
|
+
<div class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
157
|
+
{{ t('panels.stepMeta.delegated.earlierAttempts') }}
|
|
158
|
+
</div>
|
|
159
|
+
<ul class="mt-1 space-y-1">
|
|
160
|
+
<li
|
|
161
|
+
v-for="(attempt, index) in priorAttempts"
|
|
162
|
+
:key="`${attempt.startedAt}-${index}`"
|
|
163
|
+
class="flex items-center gap-2 text-[11px] text-muted"
|
|
164
|
+
>
|
|
165
|
+
<span class="truncate">{{
|
|
166
|
+
attempt.outcome || t('panels.stepMeta.delegated.noOutcome')
|
|
167
|
+
}}</span>
|
|
168
|
+
<a
|
|
169
|
+
v-if="externalRunHref(attempt.url)"
|
|
170
|
+
:href="externalRunHref(attempt.url)!"
|
|
171
|
+
target="_blank"
|
|
172
|
+
rel="noopener noreferrer"
|
|
173
|
+
class="ms-auto shrink-0 font-mono hover:underline"
|
|
174
|
+
>
|
|
175
|
+
{{ t('panels.stepMeta.delegated.openRun') }}
|
|
176
|
+
</a>
|
|
177
|
+
</li>
|
|
178
|
+
</ul>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</template>
|
|
@@ -22,7 +22,11 @@ const difficultyPct = computed(() =>
|
|
|
22
22
|
Math.min(100, Math.max(0, (props.report.difficulty / 10) * 100)),
|
|
23
23
|
)
|
|
24
24
|
// Colour the difficulty by band: easy (emerald) → moderate (amber) → hard (rose).
|
|
25
|
-
const BAR_CLASS = {
|
|
25
|
+
const BAR_CLASS = {
|
|
26
|
+
easy: 'bg-app-success-400',
|
|
27
|
+
moderate: 'bg-app-warning-400',
|
|
28
|
+
hard: 'bg-app-error-400',
|
|
29
|
+
} as const
|
|
26
30
|
const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficulty)])
|
|
27
31
|
</script>
|
|
28
32
|
|
|
@@ -30,25 +34,22 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
|
|
|
30
34
|
<section
|
|
31
35
|
data-testid="step-effort-report"
|
|
32
36
|
:class="
|
|
33
|
-
variant === 'card' ? 'scroll-mt-4 rounded-xl border border-
|
|
37
|
+
variant === 'card' ? 'scroll-mt-4 rounded-xl border border-default bg-default/50 p-4' : ''
|
|
34
38
|
"
|
|
35
39
|
>
|
|
36
40
|
<div
|
|
37
41
|
v-if="variant === 'card'"
|
|
38
|
-
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-
|
|
42
|
+
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
|
|
39
43
|
>
|
|
40
44
|
<UIcon name="i-lucide-gauge" class="h-3.5 w-3.5" />
|
|
41
45
|
<span>{{ t('panels.stepDetail.effort.heading') }}</span>
|
|
42
46
|
</div>
|
|
43
47
|
|
|
44
48
|
<div class="flex items-center gap-2">
|
|
45
|
-
<span
|
|
46
|
-
class="text-[12px] text-slate-300"
|
|
47
|
-
:title="t('panels.stepDetail.effort.difficultyHint')"
|
|
48
|
-
>
|
|
49
|
+
<span class="text-[12px] text-toned" :title="t('panels.stepDetail.effort.difficultyHint')">
|
|
49
50
|
{{ t('panels.stepDetail.effort.difficulty') }}
|
|
50
51
|
</span>
|
|
51
|
-
<div class="h-1.5 flex-1 overflow-hidden rounded-full bg-
|
|
52
|
+
<div class="h-1.5 flex-1 overflow-hidden rounded-full bg-accented/60">
|
|
52
53
|
<div
|
|
53
54
|
class="h-full rounded-full"
|
|
54
55
|
:class="difficultyClass"
|
|
@@ -57,7 +58,7 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
|
|
|
57
58
|
</div>
|
|
58
59
|
<span
|
|
59
60
|
data-testid="step-effort-difficulty"
|
|
60
|
-
class="text-[12px] font-medium text-
|
|
61
|
+
class="text-[12px] font-medium text-default"
|
|
61
62
|
:title="t('panels.stepDetail.effort.difficultyHint')"
|
|
62
63
|
>
|
|
63
64
|
{{ t('panels.stepDetail.effort.outOfTen', { value: report.difficulty }) }}
|
|
@@ -66,33 +67,33 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
|
|
|
66
67
|
|
|
67
68
|
<p
|
|
68
69
|
v-if="report.summary"
|
|
69
|
-
class="mt-2 whitespace-pre-wrap text-[13px] leading-relaxed text-
|
|
70
|
+
class="mt-2 whitespace-pre-wrap text-[13px] leading-relaxed text-toned"
|
|
70
71
|
>
|
|
71
72
|
{{ report.summary }}
|
|
72
73
|
</p>
|
|
73
74
|
|
|
74
75
|
<div v-if="report.reducedEffectiveness" class="mt-3">
|
|
75
|
-
<p class="text-[11px] font-semibold uppercase tracking-wide text-
|
|
76
|
+
<p class="text-[11px] font-semibold uppercase tracking-wide text-dimmed">
|
|
76
77
|
{{ t('panels.stepDetail.effort.reduced') }}
|
|
77
78
|
</p>
|
|
78
|
-
<p class="mt-0.5 whitespace-pre-wrap text-[12px] text-
|
|
79
|
+
<p class="mt-0.5 whitespace-pre-wrap text-[12px] text-toned">
|
|
79
80
|
{{ report.reducedEffectiveness }}
|
|
80
81
|
</p>
|
|
81
82
|
</div>
|
|
82
83
|
|
|
83
84
|
<div v-if="report.obstacles?.length" class="mt-3">
|
|
84
|
-
<p class="text-[11px] font-semibold uppercase tracking-wide text-
|
|
85
|
+
<p class="text-[11px] font-semibold uppercase tracking-wide text-dimmed">
|
|
85
86
|
{{ t('panels.stepDetail.effort.obstacles') }}
|
|
86
87
|
</p>
|
|
87
88
|
<ul class="mt-0.5 space-y-1">
|
|
88
89
|
<li
|
|
89
90
|
v-for="(obstacle, i) in report.obstacles"
|
|
90
91
|
:key="i"
|
|
91
|
-
class="flex items-start gap-1.5 text-[12px] text-
|
|
92
|
+
class="flex items-start gap-1.5 text-[12px] text-toned"
|
|
92
93
|
>
|
|
93
94
|
<UIcon
|
|
94
95
|
name="i-lucide-alert-triangle"
|
|
95
|
-
class="mt-0.5 h-3.5 w-3.5 shrink-0 text-
|
|
96
|
+
class="mt-0.5 h-3.5 w-3.5 shrink-0 text-app-warning-400/80"
|
|
96
97
|
/>
|
|
97
98
|
<span>{{ obstacle }}</span>
|
|
98
99
|
</li>
|
|
@@ -13,7 +13,11 @@ const { t } = useI18n()
|
|
|
13
13
|
|
|
14
14
|
/** Rating band → bar colour: poor adherence (rose) → partial (amber) → strong (emerald). */
|
|
15
15
|
function ratingClass(rating: number): string {
|
|
16
|
-
return rating >= 8
|
|
16
|
+
return rating >= 8
|
|
17
|
+
? 'bg-app-success-400'
|
|
18
|
+
: rating >= 5
|
|
19
|
+
? 'bg-app-warning-400'
|
|
20
|
+
: 'bg-app-error-400'
|
|
17
21
|
}
|
|
18
22
|
function ratingPct(rating: number): number {
|
|
19
23
|
return Math.min(100, Math.max(0, (rating / 10) * 100))
|
|
@@ -28,10 +32,10 @@ function label(item: FragmentAdherence[number]): string {
|
|
|
28
32
|
<section
|
|
29
33
|
v-if="items.length"
|
|
30
34
|
data-testid="step-fragment-adherence"
|
|
31
|
-
class="scroll-mt-4 rounded-xl border border-
|
|
35
|
+
class="scroll-mt-4 rounded-xl border border-default bg-default/50 p-4"
|
|
32
36
|
>
|
|
33
37
|
<div
|
|
34
|
-
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-
|
|
38
|
+
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
|
|
35
39
|
>
|
|
36
40
|
<UIcon name="i-lucide-clipboard-check" class="h-3.5 w-3.5" />
|
|
37
41
|
<span :title="t('panels.stepDetail.adherence.headingHint')">
|
|
@@ -44,13 +48,13 @@ function label(item: FragmentAdherence[number]): string {
|
|
|
44
48
|
v-for="(item, i) in items"
|
|
45
49
|
:key="item.fragmentId ?? i"
|
|
46
50
|
data-testid="step-fragment-adherence-item"
|
|
47
|
-
class="rounded-lg border border-
|
|
51
|
+
class="rounded-lg border border-default bg-default/60 px-3 py-2"
|
|
48
52
|
>
|
|
49
53
|
<div class="flex items-center gap-2">
|
|
50
|
-
<span class="min-w-0 flex-1 truncate text-[13px] font-medium text-
|
|
54
|
+
<span class="min-w-0 flex-1 truncate text-[13px] font-medium text-app-100">{{
|
|
51
55
|
label(item)
|
|
52
56
|
}}</span>
|
|
53
|
-
<div class="h-1.5 w-16 shrink-0 overflow-hidden rounded-full bg-
|
|
57
|
+
<div class="h-1.5 w-16 shrink-0 overflow-hidden rounded-full bg-accented/60">
|
|
54
58
|
<div
|
|
55
59
|
class="h-full rounded-full"
|
|
56
60
|
:class="ratingClass(item.rating)"
|
|
@@ -58,7 +62,7 @@ function label(item: FragmentAdherence[number]): string {
|
|
|
58
62
|
/>
|
|
59
63
|
</div>
|
|
60
64
|
<span
|
|
61
|
-
class="shrink-0 text-[12px] font-medium text-
|
|
65
|
+
class="shrink-0 text-[12px] font-medium text-default"
|
|
62
66
|
:title="t('panels.stepDetail.adherence.ratingHint')"
|
|
63
67
|
>
|
|
64
68
|
{{ t('panels.stepDetail.adherence.outOfTen', { value: item.rating }) }}
|
|
@@ -67,17 +71,17 @@ function label(item: FragmentAdherence[number]): string {
|
|
|
67
71
|
<MarkdownProse
|
|
68
72
|
v-if="item.assessment"
|
|
69
73
|
:text="item.assessment"
|
|
70
|
-
class="mt-1 text-[12px] leading-relaxed text-
|
|
74
|
+
class="mt-1 text-[12px] leading-relaxed text-toned"
|
|
71
75
|
/>
|
|
72
76
|
<div v-if="item.relatedFindings.length" class="mt-1.5">
|
|
73
|
-
<p class="text-[10px] font-semibold uppercase tracking-wide text-
|
|
77
|
+
<p class="text-[10px] font-semibold uppercase tracking-wide text-dimmed">
|
|
74
78
|
{{ t('panels.stepDetail.adherence.relatedFindings') }}
|
|
75
79
|
</p>
|
|
76
80
|
<ul class="mt-0.5 space-y-0.5">
|
|
77
81
|
<li
|
|
78
82
|
v-for="(finding, fi) in item.relatedFindings"
|
|
79
83
|
:key="fi"
|
|
80
|
-
class="flex items-start gap-1.5 text-[11px] text-
|
|
84
|
+
class="flex items-start gap-1.5 text-[11px] text-muted"
|
|
81
85
|
>
|
|
82
86
|
<UIcon name="i-lucide-dot" class="mt-0.5 h-3.5 w-3.5 shrink-0" />
|
|
83
87
|
<span>{{ finding }}</span>
|
|
@@ -10,6 +10,7 @@ import type { BadgeColor } from '~/utils/badge'
|
|
|
10
10
|
import { subtaskIconClass } from '~/utils/pipelineRender'
|
|
11
11
|
import StepModelActivity from '~/components/observability/StepModelActivity.vue'
|
|
12
12
|
import StepContainerStatus from '~/components/panels/StepContainerStatus.vue'
|
|
13
|
+
import StepDelegatedStatus from '~/components/panels/StepDelegatedStatus.vue'
|
|
13
14
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
14
15
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
15
16
|
|
|
@@ -32,8 +33,28 @@ const props = defineProps<{
|
|
|
32
33
|
}>()
|
|
33
34
|
|
|
34
35
|
const models = useModelsStore()
|
|
36
|
+
const agents = useAgentsStore()
|
|
35
37
|
const { t, d } = useI18n()
|
|
36
38
|
|
|
39
|
+
/**
|
|
40
|
+
* The registered executor behind a DELEGATED step, when this build still registers it.
|
|
41
|
+
*
|
|
42
|
+
* Read off the agent catalog rather than the step, because the step persists only the executor's
|
|
43
|
+
* ID: a card that named that id would show `acme:executor` where a person wants the label the
|
|
44
|
+
* deployment gave it. Undefined for every other step, and the card renders nothing.
|
|
45
|
+
*/
|
|
46
|
+
const delegatedExecutor = computed(() => {
|
|
47
|
+
const meta = agents.get(props.step.agentKind)?.delegatedExecutor
|
|
48
|
+
if (!meta) return undefined
|
|
49
|
+
return {
|
|
50
|
+
// `||`, not `??`: an entry that carried an empty label would otherwise satisfy the fallback and
|
|
51
|
+
// leave the card with a blank name, which is the one thing naming the id exists to prevent.
|
|
52
|
+
label: meta.label || meta.id,
|
|
53
|
+
description: meta.description ?? '',
|
|
54
|
+
telemetry: meta.telemetry ?? ('not-reported' as const),
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
37
58
|
const STATE_LABEL_KEYS: Record<AgentState, string> = {
|
|
38
59
|
pending: 'panels.stepMeta.state.pending',
|
|
39
60
|
working: 'panels.stepMeta.state.working',
|
|
@@ -41,10 +62,10 @@ const STATE_LABEL_KEYS: Record<AgentState, string> = {
|
|
|
41
62
|
done: 'panels.stepMeta.state.done',
|
|
42
63
|
}
|
|
43
64
|
const STATE_COLOR: Record<AgentState, string> = {
|
|
44
|
-
pending: '
|
|
45
|
-
working: '
|
|
46
|
-
waiting_decision: '
|
|
47
|
-
done: '
|
|
65
|
+
pending: 'var(--ui-text-muted)',
|
|
66
|
+
working: 'var(--ui-primary)',
|
|
67
|
+
waiting_decision: 'var(--ui-warning)',
|
|
68
|
+
done: 'var(--ui-success)',
|
|
48
69
|
}
|
|
49
70
|
|
|
50
71
|
// The state badge: a step left mid-flight on a failed run keeps `state: 'working'`,
|
|
@@ -52,7 +73,7 @@ const STATE_COLOR: Record<AgentState, string> = {
|
|
|
52
73
|
const stateMeta = computed(() => {
|
|
53
74
|
const s = props.step
|
|
54
75
|
if (props.runFailed && s.state === 'working')
|
|
55
|
-
return { label: t('panels.stepMeta.state.failed'), color: '
|
|
76
|
+
return { label: t('panels.stepMeta.state.failed'), color: 'var(--ui-error)' }
|
|
56
77
|
return { label: t(STATE_LABEL_KEYS[s.state]), color: STATE_COLOR[s.state] }
|
|
57
78
|
})
|
|
58
79
|
|
|
@@ -163,10 +184,10 @@ async function copyRunId() {
|
|
|
163
184
|
<div>
|
|
164
185
|
<dl class="grid grid-cols-2 gap-x-6 gap-y-3 text-[13px] sm:grid-cols-3">
|
|
165
186
|
<div>
|
|
166
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
187
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
167
188
|
{{ t('panels.stepMeta.stateLabel') }}
|
|
168
189
|
</dt>
|
|
169
|
-
<dd class="mt-0.5 flex items-center gap-1.5 text-
|
|
190
|
+
<dd class="mt-0.5 flex items-center gap-1.5 text-default">
|
|
170
191
|
<UIcon
|
|
171
192
|
v-if="runFailed && step.state === 'working'"
|
|
172
193
|
name="i-lucide-circle-x"
|
|
@@ -178,66 +199,66 @@ async function copyRunId() {
|
|
|
178
199
|
</dd>
|
|
179
200
|
</div>
|
|
180
201
|
<div>
|
|
181
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
202
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
182
203
|
{{ t('panels.stepMeta.duration') }}
|
|
183
204
|
</dt>
|
|
184
|
-
<dd class="mt-0.5 flex items-center gap-1.5 tabular-nums text-
|
|
205
|
+
<dd class="mt-0.5 flex items-center gap-1.5 tabular-nums text-default">
|
|
185
206
|
<UIcon
|
|
186
207
|
v-if="isRunning"
|
|
187
208
|
name="i-lucide-loader-circle"
|
|
188
|
-
class="h-3 w-3 animate-spin text-
|
|
209
|
+
class="h-3 w-3 animate-spin text-primary"
|
|
189
210
|
/>
|
|
190
211
|
<span v-if="durationLabel">{{ durationLabel }}</span>
|
|
191
|
-
<span v-else class="text-
|
|
192
|
-
<span v-if="isRunning" class="text-[11px] text-
|
|
212
|
+
<span v-else class="text-dimmed">—</span>
|
|
213
|
+
<span v-if="isRunning" class="text-[11px] text-dimmed">{{
|
|
193
214
|
t('panels.stepMeta.elapsed')
|
|
194
215
|
}}</span>
|
|
195
216
|
</dd>
|
|
196
217
|
</div>
|
|
197
218
|
<div>
|
|
198
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
219
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
199
220
|
{{ t('panels.stepMeta.step') }}
|
|
200
221
|
</dt>
|
|
201
|
-
<dd class="mt-0.5 text-
|
|
222
|
+
<dd class="mt-0.5 text-default">
|
|
202
223
|
{{ t('panels.stepMeta.stepOf', { number: stepNumber, total: totalSteps }) }}
|
|
203
224
|
</dd>
|
|
204
225
|
</div>
|
|
205
226
|
<div>
|
|
206
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
227
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
207
228
|
{{ t('panels.stepMeta.started') }}
|
|
208
229
|
</dt>
|
|
209
|
-
<dd class="mt-0.5 text-
|
|
230
|
+
<dd class="mt-0.5 text-toned">{{ formatClock(step.startedAt) ?? '—' }}</dd>
|
|
210
231
|
</div>
|
|
211
232
|
<div>
|
|
212
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
233
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
213
234
|
{{ t('panels.stepMeta.finished') }}
|
|
214
235
|
</dt>
|
|
215
|
-
<dd class="mt-0.5 text-
|
|
236
|
+
<dd class="mt-0.5 text-toned">{{ formatClock(step.finishedAt) ?? '—' }}</dd>
|
|
216
237
|
</div>
|
|
217
238
|
<div>
|
|
218
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
239
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
219
240
|
{{ t('panels.stepMeta.model') }}
|
|
220
241
|
</dt>
|
|
221
|
-
<dd class="mt-0.5 truncate text-
|
|
242
|
+
<dd class="mt-0.5 truncate text-toned" :title="step.model">
|
|
222
243
|
{{ modelLabel ?? t('panels.stepMeta.notRecorded') }}
|
|
223
244
|
</dd>
|
|
224
245
|
</div>
|
|
225
246
|
<div v-if="promptVariant">
|
|
226
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
247
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
227
248
|
{{ t('panels.stepMeta.promptVariant') }}
|
|
228
249
|
</dt>
|
|
229
|
-
<dd class="mt-0.5 truncate text-
|
|
230
|
-
<dd v-if="promptVariant.note" class="mt-0.5 text-[11px] text-
|
|
250
|
+
<dd class="mt-0.5 truncate text-toned">{{ promptVariant.label }}</dd>
|
|
251
|
+
<dd v-if="promptVariant.note" class="mt-0.5 text-[11px] text-app-warning-400/80">
|
|
231
252
|
{{ promptVariant.note }}
|
|
232
253
|
</dd>
|
|
233
254
|
</div>
|
|
234
255
|
<!-- The run id this step belongs to, surfaced for debugging (copyable). -->
|
|
235
256
|
<div class="col-span-2 sm:col-span-3">
|
|
236
|
-
<dt class="text-[11px] uppercase tracking-wide text-
|
|
257
|
+
<dt class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
237
258
|
{{ t('panels.stepMeta.run') }}
|
|
238
259
|
</dt>
|
|
239
260
|
<dd
|
|
240
|
-
class="mt-0.5 cursor-pointer truncate font-mono text-[12px] text-
|
|
261
|
+
class="mt-0.5 cursor-pointer truncate font-mono text-[12px] text-muted hover:text-default"
|
|
241
262
|
:title="t('panels.stepMeta.clickToCopy', { id: step.runId ?? instanceId ?? '' })"
|
|
242
263
|
@click="copyRunId"
|
|
243
264
|
>
|
|
@@ -255,9 +276,15 @@ async function copyRunId() {
|
|
|
255
276
|
class="mt-4"
|
|
256
277
|
/>
|
|
257
278
|
|
|
279
|
+
<!-- the EXTERNAL work a delegated step dispatched: which executor, what it is doing, the link
|
|
280
|
+
to its own logs, and what this platform therefore cannot measure. Its own component
|
|
281
|
+
because the two records share no field: a delegated step has no container to report a
|
|
282
|
+
phase, an id or an address for. -->
|
|
283
|
+
<StepDelegatedStatus :step="step" :executor="delegatedExecutor" class="mt-4" />
|
|
284
|
+
|
|
258
285
|
<!-- live subtask breakdown -->
|
|
259
286
|
<div v-if="step.subtasks && step.subtasks.total > 0" class="mt-4">
|
|
260
|
-
<div class="text-[11px] uppercase tracking-wide text-
|
|
287
|
+
<div class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
261
288
|
{{
|
|
262
289
|
t('panels.stepMeta.subtasks', {
|
|
263
290
|
completed: step.subtasks.completed,
|
|
@@ -265,9 +292,9 @@ async function copyRunId() {
|
|
|
265
292
|
})
|
|
266
293
|
}}
|
|
267
294
|
</div>
|
|
268
|
-
<div class="mt-1 h-1 overflow-hidden rounded-full bg-
|
|
295
|
+
<div class="mt-1 h-1 overflow-hidden rounded-full bg-accented/60">
|
|
269
296
|
<div
|
|
270
|
-
class="h-full rounded-full bg-
|
|
297
|
+
class="h-full rounded-full bg-primary transition-all duration-500"
|
|
271
298
|
:style="{
|
|
272
299
|
width: `${(step.subtasks.completed / step.subtasks.total) * 100}%`,
|
|
273
300
|
}"
|
|
@@ -280,10 +307,10 @@ async function copyRunId() {
|
|
|
280
307
|
class="flex items-start gap-1.5 text-[12px]"
|
|
281
308
|
:class="
|
|
282
309
|
item.status === 'completed'
|
|
283
|
-
? 'text-
|
|
310
|
+
? 'text-dimmed line-through'
|
|
284
311
|
: item.status === 'in_progress'
|
|
285
|
-
? 'text-
|
|
286
|
-
: 'text-
|
|
312
|
+
? 'text-app-100'
|
|
313
|
+
: 'text-muted'
|
|
287
314
|
"
|
|
288
315
|
>
|
|
289
316
|
<UIcon
|
|
@@ -309,7 +336,7 @@ async function copyRunId() {
|
|
|
309
336
|
<!-- standards (prompt fragments) folded into this step -->
|
|
310
337
|
<div v-if="step.selectedFragmentIds && step.selectedFragmentIds.length" class="mt-4">
|
|
311
338
|
<div
|
|
312
|
-
class="text-[11px] uppercase tracking-wide text-
|
|
339
|
+
class="text-[11px] uppercase tracking-wide text-dimmed"
|
|
313
340
|
:title="t('panels.stepMeta.standardsAppliedHint')"
|
|
314
341
|
>
|
|
315
342
|
{{ t('panels.stepMeta.standardsApplied') }}
|
|
@@ -329,28 +356,28 @@ async function copyRunId() {
|
|
|
329
356
|
|
|
330
357
|
<!-- decision raised on this step -->
|
|
331
358
|
<div v-if="step.decision" class="mt-4">
|
|
332
|
-
<div class="text-[11px] uppercase tracking-wide text-
|
|
359
|
+
<div class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
333
360
|
{{ t('panels.stepMeta.decision') }}
|
|
334
361
|
</div>
|
|
335
|
-
<p class="mt-0.5 text-[13px] text-
|
|
362
|
+
<p class="mt-0.5 text-[13px] text-default">{{ step.decision.question }}</p>
|
|
336
363
|
<p
|
|
337
364
|
v-if="step.decision.chosen"
|
|
338
|
-
class="mt-0.5 flex items-center gap-1 text-[12px] text-
|
|
365
|
+
class="mt-0.5 flex items-center gap-1 text-[12px] text-app-success-400"
|
|
339
366
|
>
|
|
340
367
|
<UIcon name="i-lucide-check" class="h-3 w-3 shrink-0" />
|
|
341
368
|
{{ step.decision.chosen }}
|
|
342
369
|
</p>
|
|
343
|
-
<p v-else class="mt-0.5 text-[12px] text-
|
|
370
|
+
<p v-else class="mt-0.5 text-[12px] text-app-warning-400">
|
|
344
371
|
{{ t('panels.stepMeta.awaitingChoice') }}
|
|
345
372
|
</p>
|
|
346
373
|
</div>
|
|
347
374
|
|
|
348
375
|
<!-- approval gate state -->
|
|
349
376
|
<div v-if="step.approval" class="mt-4">
|
|
350
|
-
<div class="text-[11px] uppercase tracking-wide text-
|
|
377
|
+
<div class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
351
378
|
{{ t('panels.stepMeta.approvalGate') }}
|
|
352
379
|
</div>
|
|
353
|
-
<p class="mt-0.5 text-[13px] text-
|
|
380
|
+
<p class="mt-0.5 text-[13px] text-default">
|
|
354
381
|
{{ approvalStatusLabel }}
|
|
355
382
|
</p>
|
|
356
383
|
</div>
|
|
@@ -358,7 +385,7 @@ async function copyRunId() {
|
|
|
358
385
|
<!-- companion verdict + full correction sequence -->
|
|
359
386
|
<div v-if="companionVerdicts.length" class="mt-4">
|
|
360
387
|
<div class="flex items-center justify-between">
|
|
361
|
-
<span class="text-[11px] uppercase tracking-wide text-
|
|
388
|
+
<span class="text-[11px] uppercase tracking-wide text-dimmed">
|
|
362
389
|
{{ t('panels.stepMeta.companionReview') }}
|
|
363
390
|
</span>
|
|
364
391
|
<!-- The COLOUR is the verdict (`passed`) and the GLYPH is the arithmetic, which are no
|
|
@@ -380,19 +407,21 @@ async function copyRunId() {
|
|
|
380
407
|
v-for="({ verdict: v, findings }, i) in verdictRounds"
|
|
381
408
|
:key="i"
|
|
382
409
|
data-testid="companion-verdict"
|
|
383
|
-
class="relative rounded-lg border border-
|
|
410
|
+
class="relative rounded-lg border border-default bg-default/60 px-3 py-2"
|
|
384
411
|
>
|
|
385
412
|
<CopyButton v-if="v.feedback" :text="v.feedback" class="absolute end-1 top-1" />
|
|
386
413
|
<div class="flex items-center gap-2 text-[12px]">
|
|
387
414
|
<span
|
|
388
415
|
class="inline-flex h-4 shrink-0 items-center rounded px-1 font-mono text-[11px] tabular-nums"
|
|
389
416
|
:class="
|
|
390
|
-
v.passed
|
|
417
|
+
v.passed
|
|
418
|
+
? 'bg-app-success-500/15 text-app-success-300'
|
|
419
|
+
: 'bg-app-warning-500/15 text-app-warning-300'
|
|
391
420
|
"
|
|
392
421
|
>
|
|
393
422
|
{{ i + 1 }}
|
|
394
423
|
</span>
|
|
395
|
-
<span :class="v.passed ? 'text-
|
|
424
|
+
<span :class="v.passed ? 'text-app-success-300' : 'text-app-warning-300'">
|
|
396
425
|
{{ pctOf(v.rating) }} {{ ratingMeetsBar(v) ? '≥' : '<' }} {{ pctOf(v.threshold) }}
|
|
397
426
|
</span>
|
|
398
427
|
</div>
|
|
@@ -400,7 +429,7 @@ async function copyRunId() {
|
|
|
400
429
|
v-if="v.feedback"
|
|
401
430
|
:text="v.feedback"
|
|
402
431
|
data-testid="companion-verdict-summary"
|
|
403
|
-
class="mt-1.5 pe-6 text-[12px] leading-relaxed text-
|
|
432
|
+
class="mt-1.5 pe-6 text-[12px] leading-relaxed text-toned"
|
|
404
433
|
/>
|
|
405
434
|
<ul v-if="findings.length" class="mt-2 space-y-1.5">
|
|
406
435
|
<li
|
|
@@ -419,13 +448,13 @@ async function copyRunId() {
|
|
|
419
448
|
</UBadge>
|
|
420
449
|
<MarkdownProse
|
|
421
450
|
:text="finding.body"
|
|
422
|
-
class="min-w-0 text-[12px] leading-relaxed text-
|
|
451
|
+
class="min-w-0 text-[12px] leading-relaxed text-toned"
|
|
423
452
|
/>
|
|
424
453
|
</li>
|
|
425
454
|
</ul>
|
|
426
455
|
</li>
|
|
427
456
|
</ol>
|
|
428
|
-
<p v-if="companionVerdicts.length > 1" class="mt-1 text-[11px] text-
|
|
457
|
+
<p v-if="companionVerdicts.length > 1" class="mt-1 text-[11px] text-dimmed">
|
|
429
458
|
{{
|
|
430
459
|
t(
|
|
431
460
|
'panels.stepMeta.correctionIterations',
|