@cat-factory/app 0.308.0 → 0.309.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- 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 +3 -2
- package/app/components/auth/UserMenu.vue +1 -1
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +15 -15
- package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
- package/app/components/binaryOutput/StoredAssetView.vue +5 -5
- package/app/components/board/AddTaskModal.vue +16 -14
- package/app/components/board/AgentFailureCard.vue +9 -9
- package/app/components/board/AgentFailureHistory.vue +1 -1
- package/app/components/board/CreateInitiativeModal.vue +2 -2
- package/app/components/board/FailureDetail.vue +1 -1
- package/app/components/board/FailureHistoryList.vue +5 -5
- package/app/components/board/RecurringPipelineModal.vue +12 -11
- package/app/components/board/ReviewFrictionDialog.vue +4 -3
- package/app/components/board/StepExecutionHistory.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +1 -1
- package/app/components/board/nodes/BlockNode.vue +8 -9
- package/app/components/board/nodes/EpicNode.vue +4 -4
- package/app/components/board/nodes/FrameSwimlanes.vue +4 -7
- 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 +8 -8
- package/app/components/board/nodes/TaskLane.vue +3 -3
- package/app/components/board/nodes/TaskPipelineMini.vue +13 -12
- package/app/components/bootstrap/AdoptionReviewModal.vue +7 -6
- package/app/components/bootstrap/BootstrapModal.vue +11 -10
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +8 -7
- package/app/components/bugFishing/BugFishingWindow.vue +37 -36
- package/app/components/clarity/ClarityReviewWindow.vue +8 -7
- package/app/components/common/AsyncViewError.vue +1 -1
- package/app/components/common/ClarificationItem.vue +6 -6
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +1 -1
- 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 +9 -8
- package/app/components/docs/DocInterviewWindow.vue +10 -9
- package/app/components/documents/ContextDocumentPicker.vue +10 -12
- package/app/components/documents/DocumentImportModal.vue +3 -2
- package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
- package/app/components/documents/DocumentSyncState.vue +1 -1
- package/app/components/documents/DocumentTemplatesModal.vue +5 -4
- package/app/components/documents/RepoContextDocPicker.vue +3 -6
- 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 +11 -10
- 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 +10 -10
- package/app/components/forkDecision/ForkDecisionWindow.vue +23 -26
- package/app/components/foundational/FoundationalContractSummary.vue +2 -2
- package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -3
- package/app/components/foundational/FoundationalServiceRegistry.vue +3 -3
- package/app/components/foundational/FoundationalSuppressions.vue +2 -2
- package/app/components/fragments/FragmentLibraryManager.vue +3 -3
- package/app/components/fragments/FragmentSelector.vue +10 -11
- package/app/components/gates/GateFailingCheckList.vue +3 -3
- package/app/components/gates/GateResultView.vue +39 -38
- package/app/components/github/AddServiceFromRepoModal.vue +5 -4
- package/app/components/github/BranchProtectionPreflight.vue +5 -5
- package/app/components/github/GitHubConnect.vue +5 -3
- package/app/components/github/GitHubPanel.vue +14 -13
- package/app/components/github/RepoTreeBrowser.vue +1 -1
- package/app/components/humanTest/HumanTestWindow.vue +18 -17
- package/app/components/initiative/InitiativePlanNotice.vue +3 -3
- package/app/components/initiative/InitiativePlanReview.vue +19 -21
- package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
- package/app/components/initiative/InitiativeTrackerWindow.vue +54 -53
- package/app/components/judge/JudgeResultView.vue +24 -25
- package/app/components/kaizen/KaizenPanel.vue +4 -4
- 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 +4 -0
- package/app/components/layout/AiProvidersBanner.vue +1 -1
- package/app/components/layout/AppearanceSwitcher.vue +1 -1
- package/app/components/layout/BoardSwitcher.vue +3 -2
- package/app/components/layout/BoardToolbar.vue +6 -2
- package/app/components/layout/CommandBar.vue +4 -2
- package/app/components/layout/DefaultTestEnvBanner.vue +2 -2
- package/app/components/layout/IntegrationsHub.vue +4 -3
- package/app/components/layout/LanguageSwitcher.vue +1 -1
- package/app/components/layout/ModelProvidersHub.vue +6 -4
- package/app/components/layout/NotificationsInbox.vue +8 -7
- package/app/components/layout/PersonalSetupModal.vue +5 -3
- package/app/components/layout/RolePrompt.vue +1 -1
- package/app/components/layout/SideBar.vue +3 -5
- package/app/components/layout/SpendWarningBanner.vue +3 -3
- package/app/components/layout/TranslationWarningBanner.vue +1 -1
- package/app/components/layout/UiModeSwitcher.vue +7 -6
- package/app/components/layout/UiRoleSwitcher.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +6 -6
- package/app/components/media/ImageCompare.vue +16 -16
- package/app/components/merge/MergeEffortChips.vue +4 -6
- package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
- package/app/components/observability/OutcomeFilterChips.vue +1 -1
- package/app/components/observability/RunFailureSummary.vue +14 -17
- package/app/components/observability/StepMetricsBar.vue +9 -8
- package/app/components/observability/StepModelActivity.vue +4 -3
- package/app/components/observability/ToolCallList.vue +15 -18
- package/app/components/outcome/OutcomeSummaryWindow.vue +43 -42
- package/app/components/palettes/AgentPalette.vue +7 -5
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +27 -30
- 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 +66 -76
- package/app/components/panels/OperatorDashboardPanel.vue +27 -26
- package/app/components/panels/ReportsPanel.vue +26 -25
- package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
- package/app/components/panels/ResultWindowShell.vue +19 -18
- package/app/components/panels/RunDetailLoadState.vue +1 -1
- package/app/components/panels/StepContainerStatus.vue +8 -7
- package/app/components/panels/StepDelegatedStatus.vue +13 -12
- 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/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 +8 -7
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
- package/app/components/panels/inspector/FrontendConfig.vue +26 -34
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +7 -4
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
- 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 +9 -13
- package/app/components/panels/inspector/ServiceTestConfig.vue +41 -45
- 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 +13 -12
- package/app/components/panels/inspector/TaskRunSettings.vue +35 -38
- 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 +2 -2
- package/app/components/pipeline/GateConfigFields.vue +6 -6
- package/app/components/pipeline/IterationCapPrompt.vue +1 -1
- package/app/components/pipeline/PipelineBuilder.vue +28 -27
- package/app/components/pipeline/PipelineHealthModal.vue +7 -7
- package/app/components/pipeline/PipelinePicker.vue +3 -3
- package/app/components/pipeline/PipelinePreview.vue +6 -7
- package/app/components/pipeline/PipelineProgress.vue +23 -24
- package/app/components/prReview/PrReviewWindow.vue +42 -41
- package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
- package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
- package/app/components/providers/ApiKeysSection.vue +7 -6
- 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 +25 -26
- package/app/components/requirements/RequirementsReviewWindow.vue +13 -12
- package/app/components/riskPolicy/RiskPolicyPicker.vue +5 -5
- package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
- package/app/components/sandbox/SandboxPanel.vue +21 -20
- 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 +16 -16
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
- package/app/components/settings/ConnectionTestVerdict.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +21 -20
- package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
- package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
- package/app/components/settings/InfraHandlersConfigurator.vue +14 -15
- package/app/components/settings/InfrastructureBackendPicker.vue +2 -2
- package/app/components/settings/IssueTrackerPanel.vue +9 -15
- 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 +10 -9
- package/app/components/settings/MergeClassRulesEditor.vue +6 -5
- package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
- package/app/components/settings/ModelConfigurationPanel.vue +8 -11
- package/app/components/settings/ModelPresetHealthModal.vue +3 -3
- package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
- package/app/components/settings/OpenRouterCatalogPanel.vue +6 -5
- 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 +8 -7
- package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
- package/app/components/settings/RiskPolicyEditorRow.vue +18 -17
- package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
- package/app/components/settings/RiskPolicyPanel.vue +11 -13
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +5 -4
- 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 +8 -7
- package/app/components/skills/SkillLibraryManager.vue +2 -2
- package/app/components/slack/SlackPanel.vue +8 -7
- package/app/components/spec/ServiceSpecWindow.vue +15 -16
- package/app/components/tasks/BugHuntModal.vue +1 -1
- package/app/components/tasks/ContextIssuePicker.vue +4 -6
- package/app/components/tasks/TaskContextIssues.vue +1 -1
- package/app/components/tasks/TaskImportModal.vue +3 -2
- package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
- package/app/components/testing/TestReportWindow.vue +54 -53
- 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 +23 -25
- package/app/utils/theme/builtins.ts +7 -1
- package/package.json +1 -1
|
@@ -23,24 +23,24 @@ const ordered = computed(() => [...props.failures].reverse())
|
|
|
23
23
|
class="rounded-md border border-default/80 bg-app-950/50 px-2.5 py-2"
|
|
24
24
|
data-testid="agent-failure-history-entry"
|
|
25
25
|
>
|
|
26
|
-
<div class="flex items-center gap-1.5 text-
|
|
26
|
+
<div class="flex items-center gap-1.5 text-3xs text-dimmed">
|
|
27
27
|
<UIcon name="i-lucide-alert-triangle" class="h-3 w-3 shrink-0 text-app-error-400/70" />
|
|
28
28
|
<time>{{ d(new Date(failure.occurredAt), 'long') }}</time>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
|
-
<p class="mt-1 text-
|
|
31
|
+
<p class="mt-1 text-2xs leading-snug text-toned" :title="failure.message">
|
|
32
32
|
{{ failure.message }}
|
|
33
33
|
</p>
|
|
34
34
|
|
|
35
|
-
<p v-if="failure.hint" class="mt-1 text-
|
|
35
|
+
<p v-if="failure.hint" class="mt-1 text-3xs leading-snug text-dimmed">
|
|
36
36
|
{{ failure.hint }}
|
|
37
37
|
</p>
|
|
38
38
|
|
|
39
39
|
<FailureDetail
|
|
40
40
|
:detail="failure.detail"
|
|
41
41
|
:message="failure.message"
|
|
42
|
-
summary-class="text-
|
|
43
|
-
pre-class="bg-app-950/80 text-
|
|
42
|
+
summary-class="text-3xs text-dimmed hover:text-toned"
|
|
43
|
+
pre-class="bg-app-950/80 text-3xs text-muted"
|
|
44
44
|
/>
|
|
45
45
|
</li>
|
|
46
46
|
</ol>
|
|
@@ -12,6 +12,7 @@ import { BUILTIN_TASK_SOURCE_KINDS } from '@cat-factory/contracts'
|
|
|
12
12
|
import { apiErrorReason } from '~/composables/api/errors'
|
|
13
13
|
import { pipelineAllowedForSchedule } from '~/utils/pipeline'
|
|
14
14
|
import { appliesIntakePredicate } from '~/utils/intakePredicates'
|
|
15
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
16
|
|
|
16
17
|
const ui = useUiStore()
|
|
17
18
|
const board = useBoardStore()
|
|
@@ -453,7 +454,7 @@ async function add() {
|
|
|
453
454
|
<USwitch v-model="onDemand" :disabled="onDemandLocked" size="sm" class="mt-0.5" />
|
|
454
455
|
<div class="space-y-0.5">
|
|
455
456
|
<p class="text-xs font-medium text-default">{{ t('board.recurring.onDemand') }}</p>
|
|
456
|
-
<p class="text-
|
|
457
|
+
<p class="text-2xs text-dimmed">
|
|
457
458
|
{{
|
|
458
459
|
onDemandLocked
|
|
459
460
|
? t('board.recurring.onDemandLockedHint')
|
|
@@ -466,10 +467,10 @@ async function add() {
|
|
|
466
467
|
<RecurringRecurrenceEditor v-if="!onDemand" v-model="recurrence" />
|
|
467
468
|
|
|
468
469
|
<div v-if="filesTicket" class="space-y-3 rounded-lg border border-default p-3">
|
|
469
|
-
<
|
|
470
|
+
<SectionLabel as="p">
|
|
470
471
|
{{ t('board.recurring.issueTracker') }}
|
|
471
|
-
</
|
|
472
|
-
<p class="text-
|
|
472
|
+
</SectionLabel>
|
|
473
|
+
<p class="text-2xs text-dimmed">
|
|
473
474
|
{{ t('board.recurring.issueTrackerHint') }}
|
|
474
475
|
</p>
|
|
475
476
|
<div class="flex gap-1">
|
|
@@ -541,22 +542,22 @@ async function add() {
|
|
|
541
542
|
<p class="text-xs font-medium text-default">
|
|
542
543
|
{{ t('board.recurring.trackerTrigger') }}
|
|
543
544
|
</p>
|
|
544
|
-
<p class="text-
|
|
545
|
+
<p class="text-2xs text-dimmed">
|
|
545
546
|
{{ t('board.recurring.trackerTriggerHint') }}
|
|
546
547
|
</p>
|
|
547
548
|
</div>
|
|
548
549
|
</div>
|
|
549
550
|
|
|
550
551
|
<div v-if="showIntake" class="space-y-3 rounded-lg border border-default p-3">
|
|
551
|
-
<
|
|
552
|
+
<SectionLabel as="p">
|
|
552
553
|
{{ t('board.recurring.intake') }}
|
|
553
|
-
</
|
|
554
|
-
<p class="text-
|
|
554
|
+
</SectionLabel>
|
|
555
|
+
<p class="text-2xs text-dimmed">
|
|
555
556
|
{{ t('board.recurring.intakeHint') }}
|
|
556
557
|
</p>
|
|
557
558
|
<!-- Two different remedies: connect something, versus connect something ELSE. A source
|
|
558
559
|
that is connected but cannot run a scheduled search is not an absent connection. -->
|
|
559
|
-
<p v-if="intakeSources.length === 0" class="text-
|
|
560
|
+
<p v-if="intakeSources.length === 0" class="text-2xs text-app-warning-500">
|
|
560
561
|
{{
|
|
561
562
|
tasks.anyOffered
|
|
562
563
|
? t('board.recurring.intakeNoIntakeSources')
|
|
@@ -626,7 +627,7 @@ async function add() {
|
|
|
626
627
|
</UFormField>
|
|
627
628
|
|
|
628
629
|
<template v-if="intakeSource">
|
|
629
|
-
<p class="text-
|
|
630
|
+
<p class="text-2xs text-dimmed">
|
|
630
631
|
{{
|
|
631
632
|
intakeDispatch === 'per-ticket'
|
|
632
633
|
? t('board.recurring.intakeDispatchPerTicketHint')
|
|
@@ -677,7 +678,7 @@ async function add() {
|
|
|
677
678
|
</template>
|
|
678
679
|
</div>
|
|
679
680
|
|
|
680
|
-
<p class="text-
|
|
681
|
+
<p class="text-2xs text-dimmed">
|
|
681
682
|
{{ t('board.recurring.footerHint') }}
|
|
682
683
|
</p>
|
|
683
684
|
</div>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// flag); the hard `blocked` tier does not. Driven by `ui.reviewFrictionContext`, mounted in
|
|
7
7
|
// pages/index.vue. See backend/docs/review-debt-friction.md.
|
|
8
8
|
import { computed } from 'vue'
|
|
9
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
9
10
|
|
|
10
11
|
const { t } = useI18n()
|
|
11
12
|
const ui = useUiStore()
|
|
@@ -84,9 +85,9 @@ function createAnyway() {
|
|
|
84
85
|
<p class="text-sm text-toned">{{ body }}</p>
|
|
85
86
|
|
|
86
87
|
<div class="rounded-lg border border-muted bg-default/50 p-2">
|
|
87
|
-
<p class="mb-1.5 px-1
|
|
88
|
+
<SectionLabel as="p" class="mb-1.5 px-1">
|
|
88
89
|
{{ t('errors.reviewFriction.waitingHeading') }}
|
|
89
|
-
</
|
|
90
|
+
</SectionLabel>
|
|
90
91
|
<ul class="space-y-1">
|
|
91
92
|
<li v-for="item in ctx.debt" :key="item.blockId">
|
|
92
93
|
<button
|
|
@@ -98,7 +99,7 @@ function createAnyway() {
|
|
|
98
99
|
<span class="truncate text-default">
|
|
99
100
|
{{ item.title || t('errors.reviewFriction.untitled') }}
|
|
100
101
|
</span>
|
|
101
|
-
<span class="shrink-0 text-
|
|
102
|
+
<span class="shrink-0 text-xs text-dimmed">
|
|
102
103
|
{{ t('errors.reviewFriction.waiting', { minutes: item.waitingMinutes }) }}
|
|
103
104
|
</span>
|
|
104
105
|
</button>
|
|
@@ -55,7 +55,7 @@ const entries = computed<Entry[]>(() =>
|
|
|
55
55
|
>
|
|
56
56
|
<!-- a superseded SUCCESSFUL attempt: its output, collapsible + copyable -->
|
|
57
57
|
<template v-if="entry.kind === 'success'">
|
|
58
|
-
<div class="flex items-center gap-1.5 text-
|
|
58
|
+
<div class="flex items-center gap-1.5 text-3xs text-dimmed">
|
|
59
59
|
<UIcon name="i-lucide-check-circle-2" class="h-3 w-3 shrink-0 text-app-success-400/70" />
|
|
60
60
|
<time>{{ d(new Date(entry.occurredAt), 'long') }}</time>
|
|
61
61
|
<span class="text-app-success-400/80">{{ t('panels.stepDetail.attemptSucceeded') }}</span>
|
|
@@ -63,31 +63,31 @@ const entries = computed<Entry[]>(() =>
|
|
|
63
63
|
<div class="relative mt-1">
|
|
64
64
|
<CopyButton :text="entry.output.output" class="absolute end-1 top-1 z-10" />
|
|
65
65
|
<pre
|
|
66
|
-
class="max-h-40 overflow-auto whitespace-pre-wrap rounded bg-app-950/80 p-1.5 pe-9 text-
|
|
66
|
+
class="max-h-40 overflow-auto whitespace-pre-wrap rounded-sm bg-app-950/80 p-1.5 pe-9 text-3xs leading-snug text-toned"
|
|
67
67
|
>{{ entry.output.output }}</pre>
|
|
68
68
|
</div>
|
|
69
|
-
<p v-if="entry.output.truncated" class="mt-1 text-
|
|
69
|
+
<p v-if="entry.output.truncated" class="mt-1 text-3xs text-dimmed">
|
|
70
70
|
{{ t('panels.stepDetail.outputTruncated') }}
|
|
71
71
|
</p>
|
|
72
72
|
</template>
|
|
73
73
|
|
|
74
74
|
<!-- a FAILED attempt: mirrors FailureHistoryList's entry markup -->
|
|
75
75
|
<template v-else>
|
|
76
|
-
<div class="flex items-center gap-1.5 text-
|
|
76
|
+
<div class="flex items-center gap-1.5 text-3xs text-dimmed">
|
|
77
77
|
<UIcon name="i-lucide-alert-triangle" class="h-3 w-3 shrink-0 text-app-error-400/70" />
|
|
78
78
|
<time>{{ d(new Date(entry.occurredAt), 'long') }}</time>
|
|
79
79
|
</div>
|
|
80
|
-
<p class="mt-1 text-
|
|
80
|
+
<p class="mt-1 text-2xs leading-snug text-toned" :title="entry.failure.message">
|
|
81
81
|
{{ entry.failure.message }}
|
|
82
82
|
</p>
|
|
83
|
-
<p v-if="entry.failure.hint" class="mt-1 text-
|
|
83
|
+
<p v-if="entry.failure.hint" class="mt-1 text-3xs leading-snug text-dimmed">
|
|
84
84
|
{{ entry.failure.hint }}
|
|
85
85
|
</p>
|
|
86
86
|
<FailureDetail
|
|
87
87
|
:detail="entry.failure.detail"
|
|
88
88
|
:message="entry.failure.message"
|
|
89
|
-
summary-class="text-
|
|
90
|
-
pre-class="bg-app-950/80 text-
|
|
89
|
+
summary-class="text-3xs text-dimmed hover:text-toned"
|
|
90
|
+
pre-class="bg-app-950/80 text-3xs text-muted"
|
|
91
91
|
/>
|
|
92
92
|
</template>
|
|
93
93
|
</li>
|
|
@@ -52,7 +52,7 @@ const dim = computed(() => (props.size === 'sm' ? 'h-7 w-7' : 'h-9 w-9'))
|
|
|
52
52
|
/>
|
|
53
53
|
</span>
|
|
54
54
|
</div>
|
|
55
|
-
<span v-if="size !== 'sm'" class="text-
|
|
55
|
+
<span v-if="size !== 'sm'" class="text-3xs leading-none text-toned">
|
|
56
56
|
{{ archetype.label }}
|
|
57
57
|
</span>
|
|
58
58
|
</div>
|
|
@@ -13,7 +13,6 @@ import { useBlockDrag } from '~/composables/useBlockDrag'
|
|
|
13
13
|
import { useFrameStacking } from '~/composables/useFrameStacking'
|
|
14
14
|
import { useViewport } from '~/composables/useViewport'
|
|
15
15
|
import { laneBodyHeightIn } from '~/utils/laneGeometry'
|
|
16
|
-
|
|
17
16
|
// Vue Flow passes the node's `id` and `data` as props to custom node components.
|
|
18
17
|
// Only frames are rendered as board nodes; their tasks live inside the card.
|
|
19
18
|
const props = defineProps<{ id: string }>()
|
|
@@ -249,10 +248,10 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
249
248
|
}}</span>
|
|
250
249
|
</div>
|
|
251
250
|
<div class="px-3 py-3">
|
|
252
|
-
<p class="text-
|
|
251
|
+
<p class="text-2xs leading-snug text-muted">
|
|
253
252
|
{{ t('board.frame.accessDenied.hint') }}
|
|
254
253
|
</p>
|
|
255
|
-
<code class="mt-2 block truncate font-mono text-
|
|
254
|
+
<code class="mt-2 block truncate font-mono text-2xs text-dimmed">{{ block.id }}</code>
|
|
256
255
|
</div>
|
|
257
256
|
</div>
|
|
258
257
|
|
|
@@ -316,9 +315,9 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
316
315
|
}}
|
|
317
316
|
</span>
|
|
318
317
|
</div>
|
|
319
|
-
<div class="mt-1.5 h-1 w-full overflow-hidden rounded bg-app-warning-900/40">
|
|
318
|
+
<div class="mt-1.5 h-1 w-full overflow-hidden rounded-sm bg-app-warning-900/40">
|
|
320
319
|
<div
|
|
321
|
-
class="h-full rounded bg-app-warning-400 transition-all"
|
|
320
|
+
class="h-full rounded-sm bg-app-warning-400 transition-all"
|
|
322
321
|
:style="{ width: bootstrapPct + '%' }"
|
|
323
322
|
/>
|
|
324
323
|
</div>
|
|
@@ -327,7 +326,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
327
326
|
<li
|
|
328
327
|
v-for="(item, i) in bootstrapItems"
|
|
329
328
|
:key="i"
|
|
330
|
-
class="flex items-start gap-1.5 text-
|
|
329
|
+
class="flex items-start gap-1.5 text-2xs"
|
|
331
330
|
:class="
|
|
332
331
|
item.status === 'completed'
|
|
333
332
|
? 'text-app-warning-200/60 line-through'
|
|
@@ -430,7 +429,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
430
429
|
{{ t('board.frame.shared') }}
|
|
431
430
|
</UBadge>
|
|
432
431
|
</div>
|
|
433
|
-
<div class="text-
|
|
432
|
+
<div class="text-2xs text-muted">{{ typeMeta!.label }}</div>
|
|
434
433
|
</div>
|
|
435
434
|
</div>
|
|
436
435
|
<div class="flex items-center gap-1">
|
|
@@ -530,7 +529,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
530
529
|
stays is what the canvas can't show at a glance. -->
|
|
531
530
|
<div
|
|
532
531
|
v-if="modules.length || prTasks"
|
|
533
|
-
class="flex items-center gap-2 text-
|
|
532
|
+
class="flex items-center gap-2 text-3xs uppercase tracking-wide text-dimmed"
|
|
534
533
|
>
|
|
535
534
|
<span v-if="modules.length">{{
|
|
536
535
|
t('board.frame.moduleCount', { count: modules.length }, modules.length)
|
|
@@ -564,7 +563,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
564
563
|
v-if="!hasTasks && access.canWriteBoard.value"
|
|
565
564
|
type="button"
|
|
566
565
|
data-testid="frame-add-task-empty"
|
|
567
|
-
class="absolute inset-4 flex items-center justify-center gap-1 rounded-lg border border-dashed border-muted text-
|
|
566
|
+
class="absolute inset-4 flex items-center justify-center gap-1 rounded-lg border border-dashed border-muted text-2xs text-dimmed hover:border-app-500 hover:text-toned"
|
|
568
567
|
@click.stop="addTask"
|
|
569
568
|
>
|
|
570
569
|
<UIcon name="i-lucide-plus" class="h-3.5 w-3.5" /> {{ t('board.frame.addFirstTask') }}
|
|
@@ -36,10 +36,10 @@ const selected = computed(() => ui.selectedBlockId === props.id)
|
|
|
36
36
|
>
|
|
37
37
|
<div class="flex items-center gap-1.5">
|
|
38
38
|
<UIcon name="i-lucide-layers" class="h-3.5 w-3.5 shrink-0 text-app-secondary-400" />
|
|
39
|
-
<span class="text-
|
|
39
|
+
<span class="text-3xs font-semibold uppercase tracking-wide text-app-secondary-300">{{
|
|
40
40
|
t('board.epic.label')
|
|
41
41
|
}}</span>
|
|
42
|
-
<span class="ms-auto text-
|
|
42
|
+
<span class="ms-auto text-3xs text-muted">{{ done }}/{{ total }}</span>
|
|
43
43
|
</div>
|
|
44
44
|
<div class="mt-1 truncate text-sm font-medium text-app-100" :title="block.title">
|
|
45
45
|
{{ block.title }}
|
|
@@ -50,10 +50,10 @@ const selected = computed(() => ui.selectedBlockId === props.id)
|
|
|
50
50
|
:style="{ width: total ? `${Math.round((done / total) * 100)}%` : '0%' }"
|
|
51
51
|
/>
|
|
52
52
|
</div>
|
|
53
|
-
<div v-if="active" class="mt-1 text-
|
|
53
|
+
<div v-if="active" class="mt-1 text-3xs text-muted">
|
|
54
54
|
{{ t('board.epic.activeCount', { count: active }) }}
|
|
55
55
|
</div>
|
|
56
|
-
<div v-else-if="total === 0" class="mt-1 text-
|
|
56
|
+
<div v-else-if="total === 0" class="mt-1 text-3xs text-dimmed">
|
|
57
57
|
{{ t('board.epic.noTasksYet') }}
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
@@ -83,12 +83,12 @@ const withheldNote = computed(() => {
|
|
|
83
83
|
class="h-3.5 w-3.5 shrink-0"
|
|
84
84
|
:style="{ color: LANE_META.done.color }"
|
|
85
85
|
/>
|
|
86
|
-
<span class="text-
|
|
86
|
+
<span class="text-2xs font-semibold text-default">{{ t(LANE_META.done.labelKey) }}</span>
|
|
87
87
|
<!-- The TOTAL, not what the caps admitted: "this service has finished 312 tasks" is the
|
|
88
88
|
fact the lane carries, and counting only the visible cards would understate it by
|
|
89
89
|
two orders of magnitude. -->
|
|
90
90
|
<span
|
|
91
|
-
class="shrink-0 rounded px-1 text-
|
|
91
|
+
class="shrink-0 rounded-sm px-1 text-3xs font-semibold tabular-nums"
|
|
92
92
|
:style="{
|
|
93
93
|
backgroundColor: tint(LANE_META.done.color),
|
|
94
94
|
color: LANE_META.done.color,
|
|
@@ -96,7 +96,7 @@ const withheldNote = computed(() => {
|
|
|
96
96
|
data-testid="lane-count-done"
|
|
97
97
|
>{{ doneLane.total }}</span
|
|
98
98
|
>
|
|
99
|
-
<span v-if="withheldNote" class="ms-auto truncate text-
|
|
99
|
+
<span v-if="withheldNote" class="ms-auto truncate text-3xs text-dimmed">{{
|
|
100
100
|
withheldNote
|
|
101
101
|
}}</span>
|
|
102
102
|
</button>
|
|
@@ -116,10 +116,7 @@ const withheldNote = computed(() => {
|
|
|
116
116
|
>
|
|
117
117
|
<!-- A zero cap is a real setting ("count them, show none"), so the strip explains why it
|
|
118
118
|
has nothing in it rather than looking broken. -->
|
|
119
|
-
<p
|
|
120
|
-
v-if="doneSelection.shown.length === 0"
|
|
121
|
-
class="px-1 text-[10px] leading-snug text-app-600"
|
|
122
|
-
>
|
|
119
|
+
<p v-if="doneSelection.shown.length === 0" class="px-1 text-3xs leading-snug text-app-600">
|
|
123
120
|
{{ t('board.lanes.done.allWithheld') }}
|
|
124
121
|
</p>
|
|
125
122
|
<LaneGroup
|
|
@@ -82,17 +82,17 @@ function select() {
|
|
|
82
82
|
{{ statusLabel }}
|
|
83
83
|
</UBadge>
|
|
84
84
|
</div>
|
|
85
|
-
<div class="mt-1 text-
|
|
85
|
+
<div class="mt-1 text-3xs uppercase tracking-wide text-primary/70">
|
|
86
86
|
{{ t('initiative.card.kind') }}
|
|
87
87
|
</div>
|
|
88
88
|
<div v-if="progress" class="mt-2 space-y-1">
|
|
89
|
-
<div class="h-1.5 overflow-hidden rounded bg-elevated">
|
|
89
|
+
<div class="h-1.5 overflow-hidden rounded-sm bg-elevated">
|
|
90
90
|
<div
|
|
91
|
-
class="h-full rounded bg-primary"
|
|
91
|
+
class="h-full rounded-sm bg-primary"
|
|
92
92
|
:style="{ width: `${Math.round((progress.settled / progress.total) * 100)}%` }"
|
|
93
93
|
/>
|
|
94
94
|
</div>
|
|
95
|
-
<div class="text-
|
|
95
|
+
<div class="text-3xs text-muted">
|
|
96
96
|
{{ t('initiative.card.progress', { done: progress.settled, total: progress.total }) }}
|
|
97
97
|
</div>
|
|
98
98
|
</div>
|
|
@@ -4,6 +4,7 @@ import { MODULE_META, taskTypeMeta } from '~/utils/catalog'
|
|
|
4
4
|
import { LANE_GEOMETRY } from '~/utils/laneGeometry'
|
|
5
5
|
import type { LaneGroup, LaneGroupKey } from '~/utils/laneSort'
|
|
6
6
|
import { LANE_REASON_LABEL_KEYS, type LaneReason } from '~/utils/swimlanes'
|
|
7
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* One labelled run of cards inside a lane.
|
|
@@ -73,14 +74,11 @@ const icon = computed(() => {
|
|
|
73
74
|
<div :data-drop-zone="dropZone ?? undefined" class="space-y-1.5">
|
|
74
75
|
<!-- `none` grouping renders no header: one unlabelled group IS the flat lane, and a header
|
|
75
76
|
saying "all of them" would be a row of chrome carrying no information. -->
|
|
76
|
-
<
|
|
77
|
-
v-if="groupKey !== 'none'"
|
|
78
|
-
class="flex items-center gap-1 px-0.5 text-[10px] uppercase tracking-wide text-dimmed"
|
|
79
|
-
>
|
|
77
|
+
<SectionLabel v-if="groupKey !== 'none'" class="flex items-center gap-1 px-0.5">
|
|
80
78
|
<UIcon v-if="icon" :name="icon" class="h-3 w-3 shrink-0" />
|
|
81
79
|
<span class="truncate" :title="label">{{ label }}</span>
|
|
82
80
|
<span class="ms-auto shrink-0 tabular-nums">{{ group.entries.length }}</span>
|
|
83
|
-
</
|
|
81
|
+
</SectionLabel>
|
|
84
82
|
<div :class="layout === 'grid' ? 'flex flex-wrap items-start gap-2' : 'space-y-1.5'">
|
|
85
83
|
<LaneTask
|
|
86
84
|
v-for="entry in group.entries"
|
|
@@ -327,7 +327,7 @@ function selectTask() {
|
|
|
327
327
|
hover. Renders a built-in OR a deployment-registered custom type via `taskTypeMeta`. -->
|
|
328
328
|
<span
|
|
329
329
|
v-if="typeBadge"
|
|
330
|
-
class="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded"
|
|
330
|
+
class="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-sm"
|
|
331
331
|
:style="{ color: typeBadge.color, backgroundColor: tint(typeBadge.color) }"
|
|
332
332
|
:title="typeBadge.label"
|
|
333
333
|
:data-task-type-badge="task.taskType"
|
|
@@ -346,7 +346,7 @@ function selectTask() {
|
|
|
346
346
|
"
|
|
347
347
|
/>
|
|
348
348
|
<span
|
|
349
|
-
class="ms-auto truncate text-
|
|
349
|
+
class="ms-auto truncate text-3xs uppercase tracking-wide"
|
|
350
350
|
:class="
|
|
351
351
|
runFailed
|
|
352
352
|
? 'text-app-error-400'
|
|
@@ -379,7 +379,7 @@ function selectTask() {
|
|
|
379
379
|
title is the one always-rendered part of the body that no control can occupy. -->
|
|
380
380
|
<div
|
|
381
381
|
data-testid="task-title"
|
|
382
|
-
class="mt-1 line-clamp-2 break-words text-
|
|
382
|
+
class="mt-1 line-clamp-2 break-words text-2xs font-semibold leading-snug text-app-100"
|
|
383
383
|
:title="task.title"
|
|
384
384
|
>
|
|
385
385
|
{{ task.title }}
|
|
@@ -415,7 +415,7 @@ function selectTask() {
|
|
|
415
415
|
<span
|
|
416
416
|
v-for="d in deps"
|
|
417
417
|
:key="d.id"
|
|
418
|
-
class="inline-flex items-center gap-0.5 rounded bg-elevated/80 px-1 py-0.5 text-
|
|
418
|
+
class="inline-flex items-center gap-0.5 rounded-sm bg-elevated/80 px-1 py-0.5 text-3xs"
|
|
419
419
|
:class="d.status === 'done' ? 'text-muted' : 'text-app-warning-300'"
|
|
420
420
|
:title="depLabel(d)"
|
|
421
421
|
>
|
|
@@ -431,7 +431,7 @@ function selectTask() {
|
|
|
431
431
|
<div class="nodrag mt-2 flex flex-wrap items-center gap-1">
|
|
432
432
|
<!-- a reviewer gate folding/re-reviewing in the background: a working indicator,
|
|
433
433
|
NOT a gate — the human is back on the board and summoned only if input is needed -->
|
|
434
|
-
<span v-if="reviewStage" class="inline-flex items-center gap-1 text-
|
|
434
|
+
<span v-if="reviewStage" class="inline-flex items-center gap-1 text-3xs text-primary">
|
|
435
435
|
<UIcon name="i-lucide-loader-circle" class="h-3 w-3 animate-spin" />
|
|
436
436
|
{{ reviewStageLabel }}
|
|
437
437
|
</span>
|
|
@@ -481,7 +481,7 @@ function selectTask() {
|
|
|
481
481
|
</UButton>
|
|
482
482
|
<span
|
|
483
483
|
v-if="runnable && defaultPipeline"
|
|
484
|
-
class="inline-flex items-center gap-0.5 text-
|
|
484
|
+
class="inline-flex items-center gap-0.5 text-3xs text-dimmed"
|
|
485
485
|
>
|
|
486
486
|
<UIcon name="i-lucide-workflow" class="h-2.5 w-2.5" />{{ defaultPipeline.name }}
|
|
487
487
|
</span>
|
|
@@ -539,7 +539,7 @@ function selectTask() {
|
|
|
539
539
|
<!-- A merged task is the one people come back to READ, so its result stays openable
|
|
540
540
|
rather than collapsing to a tick the moment it lands. -->
|
|
541
541
|
<template v-else-if="task.status === 'done'">
|
|
542
|
-
<span class="inline-flex items-center gap-1 text-
|
|
542
|
+
<span class="inline-flex items-center gap-1 text-3xs text-app-success-400">
|
|
543
543
|
<UIcon name="i-lucide-check-check" class="h-3 w-3" /> {{ t('board.task.implemented') }}
|
|
544
544
|
</span>
|
|
545
545
|
<UButton
|
|
@@ -565,7 +565,7 @@ function selectTask() {
|
|
|
565
565
|
class="mt-2 flex flex-wrap items-center gap-1 border-t border-default pt-2"
|
|
566
566
|
>
|
|
567
567
|
<span
|
|
568
|
-
class="inline-flex items-center gap-1 rounded bg-app-secondary-500/15 px-1.5 py-0.5 text-
|
|
568
|
+
class="inline-flex items-center gap-1 rounded-sm bg-app-secondary-500/15 px-1.5 py-0.5 text-3xs text-app-secondary-200"
|
|
569
569
|
:title="t('board.task.module', { name: task.moduleName })"
|
|
570
570
|
>
|
|
571
571
|
<UIcon :name="MODULE_META.icon" class="h-3 w-3" :style="{ color: MODULE_META.color }" />
|
|
@@ -46,9 +46,9 @@ const isEmpty = computed(() => props.rendered.groups.every((g) => g.entries.leng
|
|
|
46
46
|
:style="{ borderColor: tint(meta.color, 20) }"
|
|
47
47
|
>
|
|
48
48
|
<UIcon :name="meta.icon" class="h-3.5 w-3.5 shrink-0" :style="{ color: meta.color }" />
|
|
49
|
-
<span class="truncate text-
|
|
49
|
+
<span class="truncate text-2xs font-semibold text-default">{{ t(meta.labelKey) }}</span>
|
|
50
50
|
<span
|
|
51
|
-
class="ms-auto shrink-0 rounded px-1 text-
|
|
51
|
+
class="ms-auto shrink-0 rounded-sm px-1 text-3xs font-semibold tabular-nums"
|
|
52
52
|
:style="{ backgroundColor: tint(meta.color), color: meta.color }"
|
|
53
53
|
:data-testid="`lane-count-${rendered.lane}`"
|
|
54
54
|
>{{ rendered.total }}</span
|
|
@@ -65,7 +65,7 @@ const isEmpty = computed(() => props.rendered.groups.every((g) => g.entries.leng
|
|
|
65
65
|
<!-- An empty lane SAYS it is empty. Left blank, "nothing needs you" and "the lane failed
|
|
66
66
|
to render" look identical, and the first is worth stating: it is the answer a reader
|
|
67
67
|
scanning the needs-you column is hoping for. -->
|
|
68
|
-
<p v-if="isEmpty" class="px-1 pt-2 text-
|
|
68
|
+
<p v-if="isEmpty" class="px-1 pt-2 text-3xs leading-snug text-app-600">
|
|
69
69
|
{{ t(meta.emptyKey) }}
|
|
70
70
|
</p>
|
|
71
71
|
<LaneGroup
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { lodAtLeast } from '~/composables/useSemanticZoom'
|
|
13
13
|
import { prReviewPhase } from '~/utils/prReviewProgress'
|
|
14
14
|
import PrReviewPhaseBadge from '~/components/prReview/PrReviewPhaseBadge.vue'
|
|
15
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
16
|
|
|
16
17
|
// Drill-down inside a task card: the task's build-pipeline steps appear on hover (at any
|
|
17
18
|
// zoom level) or once the `steps` zoom band is reached, and one band deeper (`subtasks`)
|
|
@@ -101,14 +102,14 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
101
102
|
|
|
102
103
|
<template>
|
|
103
104
|
<div v-if="showSteps" class="mt-2 space-y-1 border-t border-default pt-2">
|
|
104
|
-
<
|
|
105
|
+
<SectionLabel class="flex items-center gap-1">
|
|
105
106
|
<UIcon name="i-lucide-workflow" class="h-2.5 w-2.5" />
|
|
106
107
|
{{ t('board.task.buildSteps') }}
|
|
107
|
-
</
|
|
108
|
-
<div v-for="(s, i) in steps" :key="i" class="rounded bg-default/60 px-1.5 py-1">
|
|
108
|
+
</SectionLabel>
|
|
109
|
+
<div v-for="(s, i) in steps" :key="i" class="rounded-sm bg-default/60 px-1.5 py-1">
|
|
109
110
|
<button
|
|
110
111
|
type="button"
|
|
111
|
-
class="flex w-full cursor-pointer items-center gap-1 rounded text-start focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
|
|
112
|
+
class="flex w-full cursor-pointer items-center gap-1 rounded-sm text-start focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
|
|
112
113
|
:title="`${agentKindMeta(s.agentKind).label} — ${agentKindMeta(s.agentKind).description}\n${t('board.task.clickToViewStep')}`"
|
|
113
114
|
@click.stop="openStep(i)"
|
|
114
115
|
>
|
|
@@ -117,7 +118,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
117
118
|
class="h-3 w-3 shrink-0"
|
|
118
119
|
:style="{ color: agentKindMeta(s.agentKind).color }"
|
|
119
120
|
/>
|
|
120
|
-
<span class="truncate text-
|
|
121
|
+
<span class="truncate text-3xs text-default">
|
|
121
122
|
{{ agentKindMeta(s.agentKind).label }}
|
|
122
123
|
</span>
|
|
123
124
|
<UIcon
|
|
@@ -129,7 +130,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
129
130
|
live — its slice progress reads better as Slicing… / Reviewing X/Y slices. -->
|
|
130
131
|
<span
|
|
131
132
|
v-if="s.subtasks && s.subtasks.total > 0 && !prPhaseActive(s)"
|
|
132
|
-
class="ms-auto shrink-0 font-mono text-
|
|
133
|
+
class="ms-auto shrink-0 font-mono text-3xs tabular-nums text-muted"
|
|
133
134
|
>
|
|
134
135
|
{{ s.subtasks.completed }}/{{ s.subtasks.total }}
|
|
135
136
|
</span>
|
|
@@ -149,7 +150,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
149
150
|
v-if="prPhaseActive(s)"
|
|
150
151
|
:step="s"
|
|
151
152
|
:run-failed="runFailed"
|
|
152
|
-
class="ms-4 mt-1 text-
|
|
153
|
+
class="ms-4 mt-1 text-3xs"
|
|
153
154
|
/>
|
|
154
155
|
|
|
155
156
|
<!-- pending approval gate: jump straight to the conclusions reader. Suppressed
|
|
@@ -162,7 +163,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
162
163
|
!reviews.isBackground(s.agentKind, props.taskId)
|
|
163
164
|
"
|
|
164
165
|
type="button"
|
|
165
|
-
class="mt-1 flex w-full items-center justify-center gap-1 rounded bg-app-warning-500 px-1.5 py-0.5 text-
|
|
166
|
+
class="mt-1 flex w-full items-center justify-center gap-1 rounded-sm bg-app-warning-500 px-1.5 py-0.5 text-3xs font-semibold text-app-warning-50 dark:text-app-warning-950 transition hover:bg-app-warning-400"
|
|
166
167
|
@click.stop="ui.openApprovalDetail(instance.id, s.approval.id)"
|
|
167
168
|
>
|
|
168
169
|
<UIcon name="i-lucide-shield-check" class="h-2.5 w-2.5" />
|
|
@@ -172,10 +173,10 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
172
173
|
<!-- per-step subtask progress bar -->
|
|
173
174
|
<div
|
|
174
175
|
v-if="s.subtasks && s.subtasks.total > 0"
|
|
175
|
-
class="mt-1 h-0.5 w-full overflow-hidden rounded bg-accented/60"
|
|
176
|
+
class="mt-1 h-0.5 w-full overflow-hidden rounded-sm bg-accented/60"
|
|
176
177
|
>
|
|
177
178
|
<div
|
|
178
|
-
class="h-full rounded bg-primary transition-all"
|
|
179
|
+
class="h-full rounded-sm bg-primary transition-all"
|
|
179
180
|
:style="{ width: `${(s.subtasks.completed / s.subtasks.total) * 100}%` }"
|
|
180
181
|
/>
|
|
181
182
|
</div>
|
|
@@ -183,7 +184,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
183
184
|
<!-- conditionally-run companion (the gate's ci-fixer / conflict-resolver, or the
|
|
184
185
|
Tester's fixer): a compact running/ran/skipped line, so a gate that's working
|
|
185
186
|
its helper reads as actively fixing rather than a frozen subtask list. -->
|
|
186
|
-
<div v-if="companionByStep[i]" class="mt-1 flex items-center gap-1 text-
|
|
187
|
+
<div v-if="companionByStep[i]" class="mt-1 flex items-center gap-1 text-3xs">
|
|
187
188
|
<UIcon
|
|
188
189
|
:name="agentKindMeta(companionByStep[i]!.kind).icon"
|
|
189
190
|
class="h-2.5 w-2.5 shrink-0"
|
|
@@ -208,7 +209,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
208
209
|
<li
|
|
209
210
|
v-for="(item, j) in s.subtasks.items"
|
|
210
211
|
:key="j"
|
|
211
|
-
class="flex items-start gap-1 text-
|
|
212
|
+
class="flex items-start gap-1 text-3xs"
|
|
212
213
|
:class="
|
|
213
214
|
item.status === 'completed'
|
|
214
215
|
? 'text-dimmed line-through'
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// is no suggestion at all as its own state, because "the two repositories agreed on everything"
|
|
10
10
|
// and "the analysis never ran" would otherwise look identical and lead to opposite conclusions.
|
|
11
11
|
import type { AdoptionSource, BootstrapJob } from '~/types/domain'
|
|
12
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
12
13
|
|
|
13
14
|
const props = defineProps<{ job: BootstrapJob }>()
|
|
14
15
|
const emit = defineEmits<{ close: [] }>()
|
|
@@ -239,7 +240,7 @@ watch(open, (isOpen) => {
|
|
|
239
240
|
class="flex items-baseline gap-2"
|
|
240
241
|
>
|
|
241
242
|
<span
|
|
242
|
-
class="shrink-0 font-mono text-
|
|
243
|
+
class="shrink-0 font-mono text-3xs uppercase"
|
|
243
244
|
:class="entry.outcome === 'read' ? 'text-dimmed' : 'text-app-warning-400/80'"
|
|
244
245
|
>
|
|
245
246
|
{{ t(`bootstrap.adoption.survey.outcome.${entry.outcome}`) }}
|
|
@@ -289,9 +290,9 @@ watch(open, (isOpen) => {
|
|
|
289
290
|
<div class="flex items-start justify-between gap-3">
|
|
290
291
|
<div>
|
|
291
292
|
<p class="text-sm font-medium text-app-100">{{ decision.title }}</p>
|
|
292
|
-
<
|
|
293
|
+
<SectionLabel as="p">
|
|
293
294
|
{{ t(`bootstrap.adoption.area.${decision.area}`) }}
|
|
294
|
-
</
|
|
295
|
+
</SectionLabel>
|
|
295
296
|
</div>
|
|
296
297
|
<UBadge v-if="!touched.has(decision.id)" color="warning" variant="subtle" size="sm">
|
|
297
298
|
{{ t('bootstrap.adoption.needsYou') }}
|
|
@@ -299,7 +300,7 @@ watch(open, (isOpen) => {
|
|
|
299
300
|
</div>
|
|
300
301
|
|
|
301
302
|
<div class="grid gap-2 text-xs sm:grid-cols-2">
|
|
302
|
-
<div class="rounded bg-default/60 p-2">
|
|
303
|
+
<div class="rounded-sm bg-default/60 p-2">
|
|
303
304
|
<p class="mb-1 font-semibold text-toned">
|
|
304
305
|
{{ t('bootstrap.adoption.side.monorepo') }}
|
|
305
306
|
</p>
|
|
@@ -307,7 +308,7 @@ watch(open, (isOpen) => {
|
|
|
307
308
|
{{ decision.monorepoPractice ?? t('bootstrap.adoption.side.nothing') }}
|
|
308
309
|
</p>
|
|
309
310
|
</div>
|
|
310
|
-
<div class="rounded bg-default/60 p-2">
|
|
311
|
+
<div class="rounded-sm bg-default/60 p-2">
|
|
311
312
|
<p class="mb-1 font-semibold text-toned">
|
|
312
313
|
{{ t('bootstrap.adoption.side.template') }}
|
|
313
314
|
</p>
|
|
@@ -321,7 +322,7 @@ watch(open, (isOpen) => {
|
|
|
321
322
|
|
|
322
323
|
<!-- The evidence is what makes the suggestion checkable rather than an assertion,
|
|
323
324
|
so it is shown, not tucked away. -->
|
|
324
|
-
<p v-if="decision.evidence.length" class="text-
|
|
325
|
+
<p v-if="decision.evidence.length" class="text-2xs text-dimmed">
|
|
325
326
|
{{ t('bootstrap.adoption.evidence') }}
|
|
326
327
|
<span class="font-mono">{{ decision.evidence.join(', ') }}</span>
|
|
327
328
|
</p>
|