@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
|
@@ -128,10 +128,10 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
128
128
|
|
|
129
129
|
<!-- Credentialless source (GitHub Issues): no form, just the on/off toggle. -->
|
|
130
130
|
<template v-if="credentialless">
|
|
131
|
-
<p class="text-
|
|
131
|
+
<p class="text-2xs text-dimmed">
|
|
132
132
|
{{ t('tasks.connect.credentialless') }}
|
|
133
133
|
</p>
|
|
134
|
-
<p v-if="!available" class="text-
|
|
134
|
+
<p v-if="!available" class="text-2xs text-app-warning-400">
|
|
135
135
|
{{ t('tasks.connect.installAppHint', { label: descriptor.label }) }}
|
|
136
136
|
</p>
|
|
137
137
|
</template>
|
|
@@ -149,7 +149,7 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
149
149
|
>
|
|
150
150
|
{{ t('tasks.connect.oauthButton', { label: descriptor.label }) }}
|
|
151
151
|
</UButton>
|
|
152
|
-
<p class="text-center text-
|
|
152
|
+
<p class="text-center text-2xs text-dimmed">
|
|
153
153
|
{{ t('tasks.connect.oauthOr') }}
|
|
154
154
|
</p>
|
|
155
155
|
</template>
|
|
@@ -167,7 +167,7 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
167
167
|
/>
|
|
168
168
|
</UFormField>
|
|
169
169
|
</div>
|
|
170
|
-
<p v-else class="text-
|
|
170
|
+
<p v-else class="text-2xs text-dimmed">
|
|
171
171
|
{{
|
|
172
172
|
connection?.label
|
|
173
173
|
? t('tasks.connect.connectedTo', { label: connection.label })
|
|
@@ -184,7 +184,7 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
184
184
|
<div class="font-medium text-default">
|
|
185
185
|
{{ t('tasks.connect.offerToWorkspace') }}
|
|
186
186
|
</div>
|
|
187
|
-
<div class="text-
|
|
187
|
+
<div class="text-2xs text-dimmed">
|
|
188
188
|
{{ t('tasks.connect.offerHint', { label: descriptor.label }) }}
|
|
189
189
|
</div>
|
|
190
190
|
</div>
|
|
@@ -22,6 +22,7 @@ import EnvironmentStatusPanel from '~/components/environments/EnvironmentStatusP
|
|
|
22
22
|
import ProvisioningLogsDrawer from '~/components/provisioning/ProvisioningLogsDrawer.vue'
|
|
23
23
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
24
24
|
import { runIsActive } from '~/utils/pipelineRender'
|
|
25
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
25
26
|
|
|
26
27
|
const board = useBoardStore()
|
|
27
28
|
const execution = useExecutionStore()
|
|
@@ -361,7 +362,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
361
362
|
</UBadge>
|
|
362
363
|
<span
|
|
363
364
|
v-if="testState && testState.attempts > 0"
|
|
364
|
-
class="text-
|
|
365
|
+
class="text-2xs text-muted"
|
|
365
366
|
:title="t('testing.fixerAttempts')"
|
|
366
367
|
>
|
|
367
368
|
{{ t('testing.fixCount', { attempts: testState.attempts, max: testState.maxAttempts }) }}
|
|
@@ -384,9 +385,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
384
385
|
data-testid="tester-infrastructure"
|
|
385
386
|
class="space-y-3"
|
|
386
387
|
>
|
|
387
|
-
<
|
|
388
|
+
<SectionLabel as="h3">
|
|
388
389
|
{{ t('testing.infrastructure') }}
|
|
389
|
-
</
|
|
390
|
+
</SectionLabel>
|
|
390
391
|
<StepContainerStatus :step="step" :run-failed="runFailed" :run-active="runActive" />
|
|
391
392
|
<EnvironmentStatusPanel
|
|
392
393
|
v-if="stepEnvironment"
|
|
@@ -414,10 +415,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
414
415
|
class="h-3.5 w-3.5 shrink-0"
|
|
415
416
|
:class="infraSetup.started ? 'text-app-success-400' : 'text-app-error-400'"
|
|
416
417
|
/>
|
|
417
|
-
<span class="text-
|
|
418
|
+
<span class="text-sm font-medium text-default">
|
|
418
419
|
{{ standupHeadline }}
|
|
419
420
|
</span>
|
|
420
|
-
<span v-if="infraSetup.durationMs != null" class="ms-auto text-
|
|
421
|
+
<span v-if="infraSetup.durationMs != null" class="ms-auto text-2xs text-dimmed">
|
|
421
422
|
{{
|
|
422
423
|
t('testing.standup.took', {
|
|
423
424
|
seconds: n(infraSetup.durationMs / 1000, 'decimal'),
|
|
@@ -425,12 +426,12 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
425
426
|
}}
|
|
426
427
|
</span>
|
|
427
428
|
</div>
|
|
428
|
-
<p v-if="infraSetup.composePath" class="mt-1 font-mono text-
|
|
429
|
+
<p v-if="infraSetup.composePath" class="mt-1 font-mono text-2xs text-dimmed">
|
|
429
430
|
{{ infraSetup.composePath }}
|
|
430
431
|
</p>
|
|
431
432
|
<p
|
|
432
433
|
v-if="infraSetup.error"
|
|
433
|
-
class="mt-1 text-
|
|
434
|
+
class="mt-1 text-xs leading-snug text-app-error-300"
|
|
434
435
|
data-testid="tester-infra-setup-error"
|
|
435
436
|
>
|
|
436
437
|
{{ infraSetup.error }}
|
|
@@ -455,7 +456,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
455
456
|
<pre
|
|
456
457
|
v-if="showInfraSetupLogs"
|
|
457
458
|
data-testid="tester-infra-setup-logs"
|
|
458
|
-
class="mt-2 max-h-64 overflow-auto rounded bg-app-950/70 p-2 font-mono text-
|
|
459
|
+
class="mt-2 max-h-64 overflow-auto rounded-sm bg-app-950/70 p-2 font-mono text-2xs leading-relaxed text-toned"
|
|
459
460
|
>{{ infraSetup.logs }}</pre>
|
|
460
461
|
</template>
|
|
461
462
|
</div>
|
|
@@ -467,7 +468,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
467
468
|
<div
|
|
468
469
|
v-if="infraReady"
|
|
469
470
|
data-testid="tester-env-ready"
|
|
470
|
-
class="flex items-center gap-2 rounded-lg border border-app-success-500/30 bg-app-success-500/10 px-3 py-2 text-
|
|
471
|
+
class="flex items-center gap-2 rounded-lg border border-app-success-500/30 bg-app-success-500/10 px-3 py-2 text-sm text-app-success-200"
|
|
471
472
|
>
|
|
472
473
|
<UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0 text-app-success-400" />
|
|
473
474
|
<span>{{ t('testing.readyBanner') }}</span>
|
|
@@ -504,9 +505,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
504
505
|
how it ended), so the otherwise-opaque fixer sub-jobs have a surface — the
|
|
505
506
|
analogue of the polling gate's attempt history. -->
|
|
506
507
|
<section v-if="fixerAttempts.length" data-testid="tester-fixer-attempts" class="space-y-2">
|
|
507
|
-
<
|
|
508
|
+
<SectionLabel as="h3">
|
|
508
509
|
{{ t('testing.fixerAttempts') }}
|
|
509
|
-
</
|
|
510
|
+
</SectionLabel>
|
|
510
511
|
<ol class="space-y-2">
|
|
511
512
|
<li
|
|
512
513
|
v-for="a in fixerAttempts"
|
|
@@ -531,20 +532,20 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
531
532
|
<MarkdownProse
|
|
532
533
|
v-if="a.summary"
|
|
533
534
|
:text="a.summary"
|
|
534
|
-
class="mt-1 max-w-3xl text-
|
|
535
|
+
class="mt-1 max-w-3xl text-xs leading-snug text-muted"
|
|
535
536
|
/>
|
|
536
537
|
<div v-if="a.concerns && a.concerns.length" class="mt-1.5">
|
|
537
|
-
<p class="text-
|
|
538
|
+
<p class="text-2xs text-dimmed">
|
|
538
539
|
{{ t('testing.fixerTimeline.addressed') }}
|
|
539
540
|
</p>
|
|
540
541
|
<ul class="mt-1 space-y-0.5">
|
|
541
542
|
<li
|
|
542
543
|
v-for="(c, ci) in a.concerns"
|
|
543
544
|
:key="`fa${a.attempt}-c${ci}`"
|
|
544
|
-
class="flex items-center gap-1.5 text-
|
|
545
|
+
class="flex items-center gap-1.5 text-xs text-toned"
|
|
545
546
|
>
|
|
546
547
|
<span
|
|
547
|
-
class="rounded px-1 text-
|
|
548
|
+
class="rounded-sm px-1 text-3xs uppercase"
|
|
548
549
|
:class="SEVERITY_META[c.severity].chip"
|
|
549
550
|
>{{ SEVERITY_LABELS[c.severity] }}</span
|
|
550
551
|
>
|
|
@@ -566,12 +567,12 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
566
567
|
class="space-y-2"
|
|
567
568
|
>
|
|
568
569
|
<div class="flex items-center gap-2">
|
|
569
|
-
<
|
|
570
|
+
<SectionLabel as="h3">
|
|
570
571
|
{{ t('testing.quality.heading') }}
|
|
571
|
-
</
|
|
572
|
+
</SectionLabel>
|
|
572
573
|
<span
|
|
573
574
|
v-if="quality.attempts"
|
|
574
|
-
class="text-
|
|
575
|
+
class="text-2xs text-muted"
|
|
575
576
|
:title="t('testing.quality.reruns')"
|
|
576
577
|
>
|
|
577
578
|
{{
|
|
@@ -604,30 +605,30 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
604
605
|
class="h-3.5 w-3.5 shrink-0"
|
|
605
606
|
:class="vd.adequate ? 'text-app-success-400' : 'text-app-warning-300'"
|
|
606
607
|
/>
|
|
607
|
-
<span class="text-
|
|
608
|
+
<span class="text-sm font-medium text-default">
|
|
608
609
|
{{
|
|
609
610
|
vd.adequate ? t('testing.quality.adequate') : t('testing.quality.inadequate')
|
|
610
611
|
}}
|
|
611
612
|
</span>
|
|
612
|
-
<span v-if="vd.model" class="ms-auto font-mono text-
|
|
613
|
+
<span v-if="vd.model" class="ms-auto font-mono text-3xs text-dimmed">{{
|
|
613
614
|
vd.model
|
|
614
615
|
}}</span>
|
|
615
|
-
<span class="text-
|
|
616
|
+
<span class="text-2xs text-dimmed" :class="{ 'ms-auto': !vd.model }">{{
|
|
616
617
|
d(new Date(vd.at), 'short')
|
|
617
618
|
}}</span>
|
|
618
619
|
</div>
|
|
619
620
|
<MarkdownProse
|
|
620
621
|
v-if="vd.feedback"
|
|
621
622
|
:text="vd.feedback"
|
|
622
|
-
class="mt-1 text-
|
|
623
|
+
class="mt-1 text-xs leading-snug text-muted"
|
|
623
624
|
/>
|
|
624
625
|
<div v-if="vd.gaps.length" class="mt-1.5">
|
|
625
|
-
<p class="text-
|
|
626
|
+
<p class="text-2xs text-dimmed">{{ t('testing.quality.gaps') }}</p>
|
|
626
627
|
<ul class="mt-1 space-y-0.5">
|
|
627
628
|
<li
|
|
628
629
|
v-for="(gap, gi) in vd.gaps"
|
|
629
630
|
:key="`qc${vi}-g${gi}`"
|
|
630
|
-
class="flex items-start gap-1.5 text-
|
|
631
|
+
class="flex items-start gap-1.5 text-xs text-toned"
|
|
631
632
|
>
|
|
632
633
|
<UIcon
|
|
633
634
|
name="i-lucide-dot"
|
|
@@ -647,7 +648,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
647
648
|
>
|
|
648
649
|
<UIcon name="i-lucide-flask-conical" class="h-8 w-8 opacity-40" />
|
|
649
650
|
<p class="text-sm">{{ t('testing.empty.title') }}</p>
|
|
650
|
-
<p class="max-w-sm text-
|
|
651
|
+
<p class="max-w-sm text-2xs text-dimmed">
|
|
651
652
|
{{ t('testing.empty.hint') }}
|
|
652
653
|
</p>
|
|
653
654
|
</div>
|
|
@@ -659,12 +660,12 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
659
660
|
<MarkdownProse
|
|
660
661
|
v-if="report.summary"
|
|
661
662
|
:text="report.summary"
|
|
662
|
-
class="mb-4 max-w-3xl text-
|
|
663
|
+
class="mb-4 max-w-3xl text-sm leading-relaxed text-toned"
|
|
663
664
|
/>
|
|
664
665
|
|
|
665
|
-
<h3 class="mb-2
|
|
666
|
+
<SectionLabel as="h3" class="mb-2">
|
|
666
667
|
{{ t('testing.scenariosOutcomes') }}
|
|
667
|
-
</
|
|
668
|
+
</SectionLabel>
|
|
668
669
|
<ul class="space-y-2">
|
|
669
670
|
<li
|
|
670
671
|
v-for="g in groups"
|
|
@@ -685,7 +686,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
685
686
|
:class="GROUP_STATUS_META[g.status].text"
|
|
686
687
|
/>
|
|
687
688
|
<span
|
|
688
|
-
class="min-w-0 flex-1 truncate text-
|
|
689
|
+
class="min-w-0 flex-1 truncate text-sm"
|
|
689
690
|
:class="g.other ? 'text-muted' : 'font-medium text-default'"
|
|
690
691
|
>
|
|
691
692
|
{{ g.title }}
|
|
@@ -702,7 +703,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
702
703
|
)
|
|
703
704
|
"
|
|
704
705
|
/>
|
|
705
|
-
<span class="shrink-0 text-
|
|
706
|
+
<span class="shrink-0 text-2xs text-dimmed">
|
|
706
707
|
{{ t('testing.checkCount', { count: g.outcomes.length }, g.outcomes.length) }}
|
|
707
708
|
<template v-if="g.concerns.length">
|
|
708
709
|
·
|
|
@@ -724,15 +725,15 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
724
725
|
:class="STATUS_META[o.status].text"
|
|
725
726
|
/>
|
|
726
727
|
<div class="min-w-0">
|
|
727
|
-
<span class="text-
|
|
728
|
+
<span class="text-sm text-default">{{ o.name }}</span>
|
|
728
729
|
<MarkdownProse
|
|
729
730
|
v-if="o.detail"
|
|
730
731
|
:text="o.detail"
|
|
731
|
-
class="max-w-3xl text-
|
|
732
|
+
class="max-w-3xl text-xs leading-snug text-muted"
|
|
732
733
|
/>
|
|
733
734
|
</div>
|
|
734
735
|
</div>
|
|
735
|
-
<p v-if="!g.outcomes.length" class="py-0.5 text-
|
|
736
|
+
<p v-if="!g.outcomes.length" class="py-0.5 text-xs italic text-dimmed">
|
|
736
737
|
{{ t('testing.noDiscreteCheck') }}
|
|
737
738
|
</p>
|
|
738
739
|
|
|
@@ -749,9 +750,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
749
750
|
/>
|
|
750
751
|
<div class="min-w-0">
|
|
751
752
|
<div class="flex items-center gap-1.5">
|
|
752
|
-
<span class="text-
|
|
753
|
+
<span class="text-xs font-medium text-default">{{ c.title }}</span>
|
|
753
754
|
<span
|
|
754
|
-
class="rounded px-1 text-
|
|
755
|
+
class="rounded-sm px-1 text-3xs uppercase"
|
|
755
756
|
:class="SEVERITY_META[c.severity].chip"
|
|
756
757
|
>
|
|
757
758
|
{{ SEVERITY_LABELS[c.severity] }}
|
|
@@ -760,7 +761,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
760
761
|
<MarkdownProse
|
|
761
762
|
v-if="c.detail"
|
|
762
763
|
:text="c.detail"
|
|
763
|
-
class="max-w-3xl text-
|
|
764
|
+
class="max-w-3xl text-xs leading-snug text-muted"
|
|
764
765
|
/>
|
|
765
766
|
</div>
|
|
766
767
|
</div>
|
|
@@ -771,7 +772,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
771
772
|
v-for="(s, si) in g.screenshots"
|
|
772
773
|
:key="`shot${si}`"
|
|
773
774
|
data-testid="tester-screenshot"
|
|
774
|
-
class="group relative h-20 w-28 shrink-0 overflow-hidden rounded border border-default bg-app-950/60 hover:border-app-600"
|
|
775
|
+
class="group relative h-20 w-28 shrink-0 overflow-hidden rounded-sm border border-default bg-app-950/60 hover:border-app-600"
|
|
775
776
|
:title="s.view"
|
|
776
777
|
@click="openShot(s.artifactId)"
|
|
777
778
|
>
|
|
@@ -783,7 +784,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
783
784
|
/>
|
|
784
785
|
<span
|
|
785
786
|
v-else
|
|
786
|
-
class="flex h-full w-full items-center justify-center text-
|
|
787
|
+
class="flex h-full w-full items-center justify-center text-3xs text-app-600"
|
|
787
788
|
>
|
|
788
789
|
{{
|
|
789
790
|
blobs.statusFor(s.artifactId) === 'error'
|
|
@@ -792,7 +793,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
792
793
|
}}
|
|
793
794
|
</span>
|
|
794
795
|
<span
|
|
795
|
-
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1 py-0.5 text-
|
|
796
|
+
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1 py-0.5 text-3xs text-toned"
|
|
796
797
|
>{{ s.view }}</span
|
|
797
798
|
>
|
|
798
799
|
</button>
|
|
@@ -803,9 +804,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
803
804
|
|
|
804
805
|
<!-- Standalone gallery: any captures not mapped to a scenario above -->
|
|
805
806
|
<section v-if="ungroupedScreenshots.length" class="mt-5">
|
|
806
|
-
<h3 class="mb-2
|
|
807
|
+
<SectionLabel as="h3" class="mb-2">
|
|
807
808
|
{{ t('testing.screenshots') }}
|
|
808
|
-
</
|
|
809
|
+
</SectionLabel>
|
|
809
810
|
<div class="grid grid-cols-2 gap-3 sm:grid-cols-3">
|
|
810
811
|
<button
|
|
811
812
|
v-for="(s, si) in ungroupedScreenshots"
|
|
@@ -822,7 +823,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
822
823
|
/>
|
|
823
824
|
<span
|
|
824
825
|
v-else
|
|
825
|
-
class="flex h-full w-full items-center justify-center text-
|
|
826
|
+
class="flex h-full w-full items-center justify-center text-2xs text-app-600"
|
|
826
827
|
>
|
|
827
828
|
{{
|
|
828
829
|
blobs.statusFor(s.artifactId) === 'error'
|
|
@@ -831,7 +832,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
831
832
|
}}
|
|
832
833
|
</span>
|
|
833
834
|
<span
|
|
834
|
-
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1.5 py-0.5 text-
|
|
835
|
+
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1.5 py-0.5 text-3xs text-toned"
|
|
835
836
|
>{{ s.view }}</span
|
|
836
837
|
>
|
|
837
838
|
</button>
|
|
@@ -845,10 +846,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
845
846
|
class="hidden w-60 shrink-0 flex-col gap-4 border-s border-default bg-default/50 px-4 py-4 lg:flex"
|
|
846
847
|
>
|
|
847
848
|
<div v-if="report">
|
|
848
|
-
<h4 class="mb-2
|
|
849
|
+
<SectionLabel as="h4" class="mb-2">
|
|
849
850
|
{{ t('testing.verdict.heading') }}
|
|
850
|
-
</
|
|
851
|
-
<div class="flex items-center gap-2 text-
|
|
851
|
+
</SectionLabel>
|
|
852
|
+
<div class="flex items-center gap-2 text-sm">
|
|
852
853
|
<UIcon
|
|
853
854
|
:name="report.greenlight ? 'i-lucide-circle-check' : 'i-lucide-circle-x'"
|
|
854
855
|
class="h-4 w-4"
|
|
@@ -861,10 +862,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
861
862
|
</div>
|
|
862
863
|
|
|
863
864
|
<div v-if="report">
|
|
864
|
-
<h4 class="mb-2
|
|
865
|
+
<SectionLabel as="h4" class="mb-2">
|
|
865
866
|
{{ t('testing.outcomes.heading') }}
|
|
866
|
-
</
|
|
867
|
-
<dl class="space-y-1 text-
|
|
867
|
+
</SectionLabel>
|
|
868
|
+
<dl class="space-y-1 text-xs">
|
|
868
869
|
<div class="flex items-center justify-between">
|
|
869
870
|
<dt class="text-muted">{{ t('testing.outcomes.passed') }}</dt>
|
|
870
871
|
<dd class="text-app-success-300">{{ counts.passed }}</dd>
|
|
@@ -892,10 +893,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
892
893
|
</div>
|
|
893
894
|
|
|
894
895
|
<div v-if="report?.environment">
|
|
895
|
-
<h4 class="mb-1
|
|
896
|
+
<SectionLabel as="h4" class="mb-1">
|
|
896
897
|
{{ t('testing.environment') }}
|
|
897
|
-
</
|
|
898
|
-
<p class="text-
|
|
898
|
+
</SectionLabel>
|
|
899
|
+
<p class="text-xs capitalize text-toned">{{ report.environment }}</p>
|
|
899
900
|
</div>
|
|
900
901
|
|
|
901
902
|
<!-- Shared run metadata + embedded observability (model, run id, timing,
|
|
@@ -910,7 +911,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
910
911
|
:failure-at="instance?.failure?.occurredAt"
|
|
911
912
|
/>
|
|
912
913
|
|
|
913
|
-
<p class="mt-auto text-
|
|
914
|
+
<p class="mt-auto text-3xs leading-relaxed text-app-600">
|
|
914
915
|
{{ t('testing.footer') }}
|
|
915
916
|
</p>
|
|
916
917
|
</aside>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
3
4
|
|
|
4
5
|
// The contextual offer's surface: one walkthrough, offered beside the work that just made it
|
|
5
6
|
// relevant. Deliberately NOT a modal — the whole point is the moment, and a modal would
|
|
@@ -75,9 +76,9 @@ function take(tourId: string) {
|
|
|
75
76
|
class="text-primary mt-0.5 h-4 w-4 shrink-0"
|
|
76
77
|
/>
|
|
77
78
|
<div class="min-w-0 flex-1">
|
|
78
|
-
<
|
|
79
|
+
<SectionLabel as="p">
|
|
79
80
|
{{ t('tutorial.nudge.label') }}
|
|
80
|
-
</
|
|
81
|
+
</SectionLabel>
|
|
81
82
|
<p class="mt-0.5 text-sm font-medium text-app-100">{{ t(offered.titleKey) }}</p>
|
|
82
83
|
<p class="mt-0.5 text-xs text-muted">{{ t(offered.descriptionKey) }}</p>
|
|
83
84
|
</div>
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
waitBudgetMs,
|
|
21
21
|
} from './TutorialOverlay.logic'
|
|
22
22
|
import type { TutorialAdvanceCause, TutorialDirection } from './TutorialOverlay.logic'
|
|
23
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
23
24
|
|
|
24
25
|
// The one shared tour runtime: resolves the running tour from the `tutorialTours` slot,
|
|
25
26
|
// anchors a highlight ring + tooltip to the current step's `data-testid`, and advances
|
|
@@ -628,9 +629,9 @@ onUnmounted(() => {
|
|
|
628
629
|
class="mt-3 rounded-lg border border-muted/70 bg-elevated/40 p-2.5"
|
|
629
630
|
data-testid="tutorial-next-tour"
|
|
630
631
|
>
|
|
631
|
-
<
|
|
632
|
+
<SectionLabel as="p">
|
|
632
633
|
{{ t('tutorial.overlay.nextUp') }}
|
|
633
|
-
</
|
|
634
|
+
</SectionLabel>
|
|
634
635
|
<p class="mt-0.5 text-sm font-medium text-app-100">{{ t(nextTour.titleKey) }}</p>
|
|
635
636
|
<p class="mt-0.5 text-xs text-muted">{{ t(nextTour.descriptionKey) }}</p>
|
|
636
637
|
<UButton
|
|
@@ -67,7 +67,7 @@ async function connect() {
|
|
|
67
67
|
/>
|
|
68
68
|
</UFormField>
|
|
69
69
|
|
|
70
|
-
<p class="text-
|
|
70
|
+
<p class="text-2xs text-dimmed">
|
|
71
71
|
<ULink :to="tokenUrl" target="_blank" class="text-primary hover:underline">
|
|
72
72
|
{{ t('vcs.connect.gitlab.createToken') }}
|
|
73
73
|
</ULink>
|
|
@@ -14,6 +14,7 @@ import ImageCompare from '~/components/media/ImageCompare.vue'
|
|
|
14
14
|
import ArtifactLightbox from '~/components/media/ArtifactLightbox.vue'
|
|
15
15
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
16
16
|
import StepRunMeta from '~/components/panels/StepRunMeta.vue'
|
|
17
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
17
18
|
|
|
18
19
|
const board = useBoardStore()
|
|
19
20
|
const execution = useExecutionStore()
|
|
@@ -242,7 +243,7 @@ async function onFilePicked(e: Event) {
|
|
|
242
243
|
<template v-else>
|
|
243
244
|
<p
|
|
244
245
|
v-if="vc.degradedReason"
|
|
245
|
-
class="rounded-lg border border-app-warning-700/40 bg-app-warning-500/5 px-3 py-2 text-
|
|
246
|
+
class="rounded-lg border border-app-warning-700/40 bg-app-warning-500/5 px-3 py-2 text-xs text-app-warning-300/90"
|
|
246
247
|
>
|
|
247
248
|
{{ vc.degradedReason }}
|
|
248
249
|
</p>
|
|
@@ -251,7 +252,7 @@ async function onFilePicked(e: Event) {
|
|
|
251
252
|
reference the reviewer is judging against is never anonymous. -->
|
|
252
253
|
<section
|
|
253
254
|
v-if="design"
|
|
254
|
-
class="rounded-lg border border-default bg-default/60 px-3 py-2 text-
|
|
255
|
+
class="rounded-lg border border-default bg-default/60 px-3 py-2 text-xs text-toned"
|
|
255
256
|
>
|
|
256
257
|
<p class="flex items-center gap-1.5">
|
|
257
258
|
<UIcon name="i-lucide-figma" class="h-3.5 w-3.5 shrink-0 text-app-warning-300" />
|
|
@@ -265,10 +266,7 @@ async function onFilePicked(e: Event) {
|
|
|
265
266
|
<!-- One line per short design, carrying both ways it can fall short: what its source
|
|
266
267
|
kept, and what this gallery's shared ceiling cut from it. A design the ceiling shut
|
|
267
268
|
out entirely reads as one with no frames unless it is named here. -->
|
|
268
|
-
<ul
|
|
269
|
-
v-if="design.gaps?.length"
|
|
270
|
-
class="mt-1.5 space-y-1 text-[11px] text-app-warning-300/90"
|
|
271
|
-
>
|
|
269
|
+
<ul v-if="design.gaps?.length" class="mt-1.5 space-y-1 text-2xs text-app-warning-300/90">
|
|
272
270
|
<li v-for="gap in design.gaps" :key="`${gap.title}-${gap.reason ?? 'capped'}`">
|
|
273
271
|
{{ t('visualConfirm.design.gapLine', { title: gap.title }) }}
|
|
274
272
|
<template v-if="gap.reason">{{ DESIGN_GAP_LABELS[gap.reason] }}</template>
|
|
@@ -281,7 +279,7 @@ async function onFilePicked(e: Event) {
|
|
|
281
279
|
|
|
282
280
|
<p
|
|
283
281
|
v-if="working"
|
|
284
|
-
class="flex items-center gap-2 rounded-lg border border-default bg-app-950/40 px-3 py-2 text-
|
|
282
|
+
class="flex items-center gap-2 rounded-lg border border-default bg-app-950/40 px-3 py-2 text-xs text-toned"
|
|
285
283
|
>
|
|
286
284
|
<UIcon name="i-lucide-loader" class="h-3.5 w-3.5 animate-spin text-app-warning-300" />
|
|
287
285
|
{{ phase ? PHASE_LABEL[phase] : '' }}
|
|
@@ -304,7 +302,7 @@ async function onFilePicked(e: Event) {
|
|
|
304
302
|
<!-- Per-view note (folded into the fixer findings) -->
|
|
305
303
|
<div v-if="awaitingHuman" class="px-1">
|
|
306
304
|
<button
|
|
307
|
-
class="flex items-center gap-1.5 text-
|
|
305
|
+
class="flex items-center gap-1.5 text-2xs text-muted hover:text-default"
|
|
308
306
|
@click="noteOpen[p.view] = !noteOpen[p.view]"
|
|
309
307
|
>
|
|
310
308
|
<UIcon
|
|
@@ -314,7 +312,7 @@ async function onFilePicked(e: Event) {
|
|
|
314
312
|
{{ t('visualConfirm.noteIssue', { view: p.view }) }}
|
|
315
313
|
<span
|
|
316
314
|
v-if="perViewNotes[p.view]?.trim()"
|
|
317
|
-
class="rounded-full bg-app-warning-500/15 px-1.5 text-
|
|
315
|
+
class="rounded-full bg-app-warning-500/15 px-1.5 text-3xs text-app-warning-300"
|
|
318
316
|
>{{ t('visualConfirm.noted') }}</span
|
|
319
317
|
>
|
|
320
318
|
</button>
|
|
@@ -323,26 +321,26 @@ async function onFilePicked(e: Event) {
|
|
|
323
321
|
v-model="perViewNotes[p.view]"
|
|
324
322
|
rows="2"
|
|
325
323
|
:placeholder="t('visualConfirm.notePlaceholder', { view: p.view })"
|
|
326
|
-
class="mt-1 w-full rounded-md border border-muted bg-app-950 px-2 py-1.5 text-
|
|
324
|
+
class="mt-1 w-full rounded-md border border-muted bg-app-950 px-2 py-1.5 text-xs text-default placeholder:text-app-600 focus:border-app-warning-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-app-warning-500/60"
|
|
327
325
|
/>
|
|
328
326
|
</div>
|
|
329
327
|
</div>
|
|
330
328
|
</section>
|
|
331
|
-
<p v-else class="text-
|
|
329
|
+
<p v-else class="text-xs italic text-dimmed">
|
|
332
330
|
{{ t('visualConfirm.noScreenshots') }}
|
|
333
331
|
</p>
|
|
334
332
|
|
|
335
333
|
<!-- Upload a reference for any view -->
|
|
336
334
|
<section class="rounded-lg border border-default bg-default/60 p-3">
|
|
337
|
-
<h3 class="mb-2
|
|
335
|
+
<SectionLabel as="h3" class="mb-2">
|
|
338
336
|
{{ t('visualConfirm.upload.heading') }}
|
|
339
|
-
</
|
|
337
|
+
</SectionLabel>
|
|
340
338
|
<div class="flex flex-wrap items-center gap-2">
|
|
341
339
|
<input
|
|
342
340
|
v-model="uploadView"
|
|
343
341
|
list="vc-views"
|
|
344
342
|
:placeholder="t('visualConfirm.upload.viewPlaceholder')"
|
|
345
|
-
class="rounded-md border border-muted bg-app-950 px-2 py-1 text-
|
|
343
|
+
class="rounded-md border border-muted bg-app-950 px-2 py-1 text-xs text-default placeholder:text-app-600"
|
|
346
344
|
/>
|
|
347
345
|
<datalist id="vc-views">
|
|
348
346
|
<option v-for="p in pairs" :key="p.view" :value="p.view" />
|
|
@@ -352,11 +350,11 @@ async function onFilePicked(e: Event) {
|
|
|
352
350
|
type="file"
|
|
353
351
|
accept="image/png,image/jpeg"
|
|
354
352
|
:disabled="busy || !uploadView.trim()"
|
|
355
|
-
class="text-
|
|
353
|
+
class="text-xs text-toned file:me-2 file:rounded-sm file:border-0 file:bg-elevated file:px-2 file:py-1 file:text-default disabled:opacity-40"
|
|
356
354
|
@change="onFilePicked"
|
|
357
355
|
/>
|
|
358
356
|
</div>
|
|
359
|
-
<p class="mt-1.5 text-
|
|
357
|
+
<p class="mt-1.5 text-3xs text-app-600">
|
|
360
358
|
{{
|
|
361
359
|
uploadView.trim()
|
|
362
360
|
? t('visualConfirm.upload.tipReady')
|
|
@@ -367,17 +365,17 @@ async function onFilePicked(e: Event) {
|
|
|
367
365
|
|
|
368
366
|
<!-- Request fix -->
|
|
369
367
|
<section v-if="awaitingHuman" class="rounded-lg border border-default bg-default/60 p-3">
|
|
370
|
-
<h3 class="mb-2
|
|
368
|
+
<SectionLabel as="h3" class="mb-2">
|
|
371
369
|
{{ t('visualConfirm.requestFix.heading') }}
|
|
372
|
-
</
|
|
370
|
+
</SectionLabel>
|
|
373
371
|
<textarea
|
|
374
372
|
v-model="globalFindings"
|
|
375
373
|
rows="3"
|
|
376
374
|
:placeholder="t('visualConfirm.requestFix.placeholder')"
|
|
377
|
-
class="w-full rounded-md border border-muted bg-app-950 px-3 py-2 text-
|
|
375
|
+
class="w-full rounded-md border border-muted bg-app-950 px-3 py-2 text-sm text-default placeholder:text-app-600 focus:border-app-warning-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-app-warning-500/60"
|
|
378
376
|
/>
|
|
379
377
|
<div class="mt-2 flex items-center justify-between">
|
|
380
|
-
<span class="text-
|
|
378
|
+
<span class="text-2xs text-dimmed">
|
|
381
379
|
{{ t('visualConfirm.requestFix.foldedHint') }}
|
|
382
380
|
</span>
|
|
383
381
|
<UButton
|
|
@@ -399,16 +397,16 @@ async function onFilePicked(e: Event) {
|
|
|
399
397
|
v-if="vc.rounds && vc.rounds.length"
|
|
400
398
|
class="rounded-lg border border-default bg-default/60 p-3"
|
|
401
399
|
>
|
|
402
|
-
<h3 class="mb-2
|
|
400
|
+
<SectionLabel as="h3" class="mb-2">
|
|
403
401
|
{{ t('visualConfirm.history.heading', { count: vc.attempts }, vc.attempts) }}
|
|
404
|
-
</
|
|
402
|
+
</SectionLabel>
|
|
405
403
|
<ol class="space-y-2">
|
|
406
|
-
<li v-for="(r, i) in vc.rounds" :key="i" class="flex items-start gap-2 text-
|
|
404
|
+
<li v-for="(r, i) in vc.rounds" :key="i" class="flex items-start gap-2 text-xs">
|
|
407
405
|
<UIcon name="i-lucide-wrench" class="mt-0.5 h-3.5 w-3.5 shrink-0 text-muted" />
|
|
408
406
|
<div class="min-w-0 flex-1">
|
|
409
407
|
<span class="text-default">{{ t('visualConfirm.history.fixRequested') }}</span>
|
|
410
408
|
<span
|
|
411
|
-
class="ms-1.5 rounded px-1 text-
|
|
409
|
+
class="ms-1.5 rounded-sm px-1 text-3xs uppercase"
|
|
412
410
|
:class="
|
|
413
411
|
r.outcome === 'completed'
|
|
414
412
|
? 'bg-app-success-500/15 text-app-success-300'
|
|
@@ -447,7 +445,7 @@ async function onFilePicked(e: Event) {
|
|
|
447
445
|
<div class="flex items-center gap-2">
|
|
448
446
|
<label
|
|
449
447
|
v-if="awaitingHuman && needsAck"
|
|
450
|
-
class="flex items-center gap-1.5 text-
|
|
448
|
+
class="flex items-center gap-1.5 text-2xs text-app-warning-300/90"
|
|
451
449
|
>
|
|
452
450
|
<input v-model="ackDegraded" type="checkbox" class="accent-app-warning-500" />
|
|
453
451
|
{{ t('visualConfirm.reviewedManually') }}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { THEME_DEFAULTS, type ThemeDoc } from '~/utils/theme/doc'
|
|
2
2
|
import { presets } from '~/utils/theme/presets'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -24,12 +24,18 @@ export const DEFAULT_THEME_ID = 'cat-factory'
|
|
|
24
24
|
* Status hues are the app's long-standing choices (amber for warning, rose for error, emerald
|
|
25
25
|
* for success, sky for info, violet for the secondary accent), named here as aliases so a theme
|
|
26
26
|
* that recolours `warning` recolours every warning surface.
|
|
27
|
+
*
|
|
28
|
+
* `radius` is stated even though it equals `THEME_DEFAULTS.radius`, so the value every surface in
|
|
29
|
+
* the app derives from has one visible home. It writes no CSS at that value (`css.ts` skips a
|
|
30
|
+
* default), which is the point: changing the number here is the whole edit, and Nuxt UI's
|
|
31
|
+
* `--radius-*` scale carries it to every `rounded-*` step (issue #2251).
|
|
27
32
|
*/
|
|
28
33
|
export const CAT_FACTORY_THEME: NamedTheme = {
|
|
29
34
|
id: DEFAULT_THEME_ID,
|
|
30
35
|
name: 'Cat Factory',
|
|
31
36
|
doc: {
|
|
32
37
|
version: 1,
|
|
38
|
+
radius: THEME_DEFAULTS.radius,
|
|
33
39
|
colors: {
|
|
34
40
|
primary: 'indigo',
|
|
35
41
|
secondary: 'violet',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.309.0",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|