@cat-factory/app 0.302.2 → 0.303.1
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 +99 -14
- package/app/app.config.ts +19 -10
- package/app/assets/css/main.css +13 -13
- package/app/assets/css/prose.css +22 -22
- package/app/assets/css/tokens.css +298 -0
- package/app/components/assistant/AssistantModal.vue +22 -22
- package/app/components/auth/AuthGate.vue +1 -1
- package/app/components/auth/BackendMisconfiguredScreen.vue +10 -10
- package/app/components/auth/LoginScreen.vue +34 -36
- package/app/components/auth/ResetPasswordScreen.vue +12 -12
- package/app/components/auth/UserMenu.vue +4 -4
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +27 -25
- package/app/components/binaryOutput/BinaryOutputReport.vue +15 -15
- package/app/components/binaryOutput/StoredAssetView.vue +5 -5
- package/app/components/board/AddTaskModal.vue +17 -20
- package/app/components/board/AgentFailureCard.vue +11 -11
- package/app/components/board/AgentFailureHistory.vue +2 -2
- package/app/components/board/BoardCanvas.vue +6 -5
- package/app/components/board/CreateInitiativeModal.vue +8 -10
- package/app/components/board/DependencyConnectOverlay.vue +1 -1
- package/app/components/board/FailureHistoryList.vue +7 -7
- package/app/components/board/RecurringPipelineModal.vue +17 -17
- package/app/components/board/ReviewFrictionDialog.vue +6 -6
- package/app/components/board/StepExecutionHistory.vue +13 -13
- package/app/components/board/TaskDependencyEdges.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +10 -10
- package/app/components/board/nodes/BlockNode.vue +29 -29
- package/app/components/board/nodes/DecisionBadge.vue +2 -2
- package/app/components/board/nodes/EpicNode.vue +14 -10
- package/app/components/board/nodes/FrameSwimlanes.vue +7 -9
- package/app/components/board/nodes/InitiativeCard.vue +8 -8
- package/app/components/board/nodes/LaneGroup.vue +1 -1
- package/app/components/board/nodes/LaneTask.vue +2 -2
- package/app/components/board/nodes/ResizeGrips.vue +4 -4
- package/app/components/board/nodes/TaskCard.vue +18 -18
- package/app/components/board/nodes/TaskLane.vue +5 -5
- package/app/components/board/nodes/TaskPipelineMini.vue +18 -18
- package/app/components/bootstrap/AdoptionReviewModal.vue +29 -26
- package/app/components/bootstrap/BootstrapModal.vue +21 -23
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +30 -33
- package/app/components/bugFishing/BugFishingWindow.vue +49 -49
- package/app/components/clarity/ClarityReviewWindow.vue +30 -30
- package/app/components/common/AsyncViewError.vue +5 -5
- package/app/components/common/ClarificationItem.vue +8 -13
- package/app/components/common/ConfirmDialog.vue +4 -2
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +3 -3
- package/app/components/common/InterviewGateNotice.vue +7 -7
- package/app/components/common/KeyboardShortcutsHelp.vue +1 -1
- package/app/components/common/MarkdownProse.vue +14 -13
- package/app/components/consensus/ConsensusSessionWindow.vue +26 -26
- package/app/components/context/ContextAttachmentFields.vue +17 -17
- package/app/components/docs/DocInterviewWindow.vue +14 -14
- package/app/components/documents/ContextDocumentPicker.vue +17 -17
- package/app/components/documents/DocumentImportModal.vue +7 -7
- package/app/components/documents/DocumentSourceConnectModal.vue +3 -3
- package/app/components/documents/DocumentSyncState.vue +5 -5
- package/app/components/documents/DocumentTemplatesModal.vue +15 -15
- package/app/components/documents/RepoContextDocPicker.vue +5 -5
- package/app/components/documents/SpawnPreviewModal.vue +12 -12
- package/app/components/documents/StartFromDesignModal.vue +11 -11
- package/app/components/documents/TaskContextDocs.vue +5 -5
- package/app/components/environments/EnvSetupStepper.vue +6 -6
- package/app/components/environments/EnvironmentStatusPanel.vue +17 -17
- package/app/components/environments/steps/EnvPickStep.vue +3 -3
- package/app/components/environments/steps/EnvPreflightStep.vue +9 -9
- package/app/components/environments/steps/EnvReviewStep.vue +25 -22
- package/app/components/environments/steps/EnvSaveStep.vue +7 -5
- package/app/components/environments/steps/JourneyStepNav.vue +1 -1
- package/app/components/focus/BlockFocusView.vue +17 -19
- package/app/components/followUp/FollowUpWindow.vue +23 -23
- package/app/components/forkDecision/ForkDecisionWindow.vue +37 -39
- package/app/components/foundational/FoundationalContractSummary.vue +7 -7
- package/app/components/foundational/FoundationalServiceCatalogList.vue +11 -11
- package/app/components/foundational/FoundationalServiceManager.vue +1 -1
- package/app/components/foundational/FoundationalServiceRegistry.vue +13 -13
- package/app/components/foundational/FoundationalServiceSources.vue +13 -13
- package/app/components/foundational/FoundationalSuppressions.vue +7 -7
- package/app/components/foundational/ServiceCatalogConnection.vue +10 -10
- package/app/components/fragments/FragmentLibraryManager.vue +41 -44
- package/app/components/fragments/FragmentSelector.vue +13 -13
- package/app/components/fragments/GitHubDocUrlImport.vue +1 -1
- package/app/components/gates/GateFailingCheckList.vue +5 -5
- package/app/components/gates/GateResultView.vue +50 -47
- package/app/components/github/AddServiceFromRepoModal.vue +14 -14
- package/app/components/github/BranchProtectionPreflight.vue +13 -13
- package/app/components/github/GitHubConnect.vue +7 -7
- package/app/components/github/GitHubOnboarding.vue +7 -7
- package/app/components/github/GitHubPanel.vue +37 -40
- package/app/components/github/RepoTreeBrowser.vue +18 -18
- package/app/components/humanTest/HumanTestWindow.vue +30 -33
- package/app/components/initiative/InitiativePlanNotice.vue +5 -5
- package/app/components/initiative/InitiativePlanReview.vue +27 -29
- package/app/components/initiative/InitiativePlanningWindow.vue +10 -10
- package/app/components/initiative/InitiativeTrackerWindow.vue +71 -65
- package/app/components/inputGate/InputGateNotice.vue +2 -4
- package/app/components/judge/JudgeResultView.vue +30 -32
- package/app/components/kaizen/KaizenPanel.vue +40 -36
- package/app/components/kaizen/KaizenStepStatus.vue +21 -21
- package/app/components/layout/AccountAuditLog.vue +10 -10
- package/app/components/layout/AccountDeploymentSettings.vue +20 -20
- package/app/components/layout/AccountFailureKindRules.vue +13 -13
- package/app/components/layout/AccountFoundationalSettings.vue +1 -1
- package/app/components/layout/AccountFragmentSettings.vue +1 -1
- package/app/components/layout/AccountModelPolicySettings.vue +9 -9
- package/app/components/layout/AccountPlatformAlertSettings.vue +11 -11
- package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
- package/app/components/layout/AccountRunCredentialSettings.vue +5 -5
- package/app/components/layout/AccountSkillSettings.vue +1 -1
- package/app/components/layout/AccountTeamSettings.vue +23 -15
- package/app/components/layout/AiProvidersBanner.vue +11 -8
- package/app/components/layout/AppearanceSwitcher.vue +108 -0
- package/app/components/layout/BoardSwitcher.vue +8 -11
- package/app/components/layout/BoardToolbar.vue +3 -3
- package/app/components/layout/CommandBar.vue +7 -9
- package/app/components/layout/ConnectionStatusBanner.vue +2 -2
- package/app/components/layout/DefaultTestEnvBanner.vue +5 -5
- package/app/components/layout/GitHubPatBanner.vue +5 -5
- package/app/components/layout/GitHubPatPermissionsBanner.vue +16 -10
- package/app/components/layout/InfraSetupBanner.vue +6 -6
- package/app/components/layout/IntegrationsHub.vue +15 -15
- package/app/components/layout/LanguageSwitcher.vue +5 -5
- package/app/components/layout/ModelProvidersHub.vue +13 -16
- package/app/components/layout/NotificationsInbox.vue +10 -10
- package/app/components/layout/PersonalSetupModal.vue +8 -8
- package/app/components/layout/ProviderConfigBanner.vue +4 -4
- package/app/components/layout/RolePrompt.vue +7 -7
- package/app/components/layout/SideBar.vue +6 -4
- package/app/components/layout/SpendWarningBanner.vue +17 -14
- package/app/components/layout/TranslationWarningBanner.vue +4 -4
- package/app/components/layout/UiModeSwitcher.vue +13 -13
- package/app/components/layout/UiRoleSwitcher.vue +8 -8
- package/app/components/layout/WorkspaceMembersSettings.vue +15 -11
- package/app/components/media/ArtifactLightbox.vue +13 -13
- package/app/components/media/ImageCompare.vue +31 -24
- package/app/components/merge/MergeEffortChips.vue +2 -2
- package/app/components/notifications/NotificationSettingsPanel.vue +14 -12
- package/app/components/observability/OutcomeFilterChips.vue +6 -6
- package/app/components/observability/RunFailureSummary.vue +28 -25
- package/app/components/observability/StepMetricsBar.vue +26 -28
- package/app/components/observability/StepModelActivity.vue +2 -2
- package/app/components/observability/ToolCallList.vue +24 -24
- package/app/components/outcome/OutcomeSummaryWindow.vue +47 -47
- package/app/components/palettes/AgentPalette.vue +8 -8
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +52 -51
- package/app/components/panels/AttemptEntryHeader.vue +4 -6
- package/app/components/panels/DecisionModal.vue +7 -7
- package/app/components/panels/GenericStructuredResultView.vue +7 -7
- package/app/components/panels/InspectorPanel.vue +17 -17
- package/app/components/panels/MergerResultView.vue +19 -19
- package/app/components/panels/ObservabilityPanel.vue +115 -123
- package/app/components/panels/OperatorDashboardPanel.vue +89 -97
- package/app/components/panels/ReportsPanel.vue +69 -66
- package/app/components/panels/ReportsSpendBreakdown.vue +9 -9
- package/app/components/panels/ResultWindowShell.vue +38 -38
- package/app/components/panels/RunDetailLoadState.vue +2 -2
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.logic.spec.ts +135 -0
- package/app/components/panels/StepDelegatedStatus.logic.ts +160 -0
- package/app/components/panels/StepDelegatedStatus.vue +181 -0
- package/app/components/panels/StepEffortReport.vue +16 -15
- package/app/components/panels/StepFragmentAdherence.vue +14 -10
- package/app/components/panels/StepMetadataCard.vue +74 -45
- package/app/components/panels/StepReproductionReport.vue +25 -21
- package/app/components/panels/StepRunMeta.vue +20 -20
- package/app/components/panels/StepTestReport.logic.spec.ts +8 -3
- package/app/components/panels/StepTestReport.logic.ts +4 -4
- package/app/components/panels/StepTestReport.vue +28 -28
- package/app/components/panels/StepToolServers.vue +14 -11
- package/app/components/panels/StepValidationReport.vue +7 -7
- package/app/components/panels/inspector/ContainerSummary.vue +9 -9
- package/app/components/panels/inspector/DocReferenceRepos.vue +3 -3
- package/app/components/panels/inspector/EnvProbeReport.vue +24 -27
- package/app/components/panels/inspector/EpicChildren.vue +8 -12
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +11 -11
- package/app/components/panels/inspector/FrontendConfig.vue +37 -41
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +6 -6
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +16 -19
- package/app/components/panels/inspector/ServiceConnections.vue +2 -2
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
- package/app/components/panels/inspector/ServiceSelfTests.vue +21 -17
- package/app/components/panels/inspector/ServiceTestConfig.vue +51 -59
- package/app/components/panels/inspector/ServiceTestSecrets.vue +5 -5
- package/app/components/panels/inspector/ServiceTestingContext.vue +3 -3
- package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAgentConfig.vue +3 -3
- package/app/components/panels/inspector/TaskAprioriBranches.vue +8 -5
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +11 -11
- package/app/components/panels/inspector/TaskExecution.vue +17 -17
- package/app/components/panels/inspector/TaskReviewTarget.vue +2 -2
- package/app/components/panels/inspector/TaskRunSettings.vue +35 -37
- package/app/components/panels/inspector/TaskStructure.vue +3 -3
- package/app/components/pipeline/AgentKindIcon.vue +1 -1
- package/app/components/pipeline/AgentPromptEditor.vue +17 -17
- package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -56
- package/app/components/pipeline/EstimateThresholdFields.vue +4 -4
- package/app/components/pipeline/GateConfigFields.vue +13 -10
- package/app/components/pipeline/IterationCapPrompt.vue +4 -2
- package/app/components/pipeline/PipelineBuilder.vue +47 -55
- package/app/components/pipeline/PipelineHealthModal.vue +27 -29
- package/app/components/pipeline/PipelinePicker.vue +10 -10
- package/app/components/pipeline/PipelinePreview.vue +10 -10
- package/app/components/pipeline/PipelineProgress.vue +64 -67
- package/app/components/prReview/PrReviewPhaseBadge.vue +7 -7
- package/app/components/prReview/PrReviewWindow.vue +75 -77
- package/app/components/providers/AiPresetMismatchDialog.vue +5 -5
- package/app/components/providers/AiProviderOnboardingModal.vue +9 -9
- package/app/components/providers/ApiKeysSection.vue +13 -13
- package/app/components/providers/PersonalCredentialModal.vue +2 -2
- package/app/components/providers/PersonalSubscriptionSection.vue +10 -10
- package/app/components/providers/SignInRequiredNotice.vue +1 -1
- package/app/components/providers/VendorCredentialsModal.vue +10 -10
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +13 -13
- package/app/components/ralph/RalphLoopResultView.vue +28 -30
- package/app/components/recurring/RecurrenceEditor.vue +2 -2
- package/app/components/requirements/RequirementsReviewWindow.vue +51 -58
- package/app/components/riskPolicy/RiskPolicyPicker.vue +12 -15
- package/app/components/riskPolicy/RiskPolicyPreview.vue +14 -14
- package/app/components/sandbox/SandboxPanel.vue +58 -59
- package/app/components/settings/AccountSettingsPanel.vue +1 -1
- package/app/components/settings/ApiTokensPanel.vue +10 -10
- package/app/components/settings/BudgetSettings.vue +18 -22
- package/app/components/settings/CapabilityCredentialsPanel.vue +15 -15
- package/app/components/settings/CloudflareHandlerSection.vue +20 -20
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +13 -13
- package/app/components/settings/ConnectionTestVerdict.vue +3 -3
- package/app/components/settings/ConnectionWarnings.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +27 -35
- package/app/components/settings/CustomManifestTypeEditor.vue +10 -10
- package/app/components/settings/DefaultProvisionTypeSection.vue +6 -6
- package/app/components/settings/InfraHandlersConfigurator.vue +24 -22
- package/app/components/settings/InfrastructureBackendPicker.vue +6 -6
- package/app/components/settings/InfrastructureWindow.vue +5 -5
- package/app/components/settings/IssueTrackerPanel.vue +29 -23
- package/app/components/settings/KubernetesEngineForm.vue +11 -11
- package/app/components/settings/KubernetesEnvironmentForm.vue +4 -4
- package/app/components/settings/LocalContainerPoolSettings.vue +6 -11
- package/app/components/settings/LocalModelEndpointsPanel.vue +20 -18
- package/app/components/settings/McpAuthorizeScreen.vue +13 -15
- package/app/components/settings/McpOAuthCallbackScreen.vue +16 -10
- package/app/components/settings/MergeClassRulesEditor.vue +6 -9
- package/app/components/settings/MergeRolePolicyEditor.vue +16 -16
- package/app/components/settings/ModelConfigurationPanel.vue +23 -30
- package/app/components/settings/ModelPresetHealthModal.vue +15 -13
- package/app/components/settings/ObservabilityConnectionPanel.vue +4 -4
- package/app/components/settings/OpenRouterCatalogPanel.vue +26 -19
- package/app/components/settings/PackageRegistriesPanel.vue +8 -8
- package/app/components/settings/ProviderConnectionTab.vue +8 -11
- package/app/components/settings/ProviderManifestEditor.vue +9 -9
- package/app/components/settings/ProviderPreferenceEditor.vue +8 -8
- package/app/components/settings/RiskPolicyCreateForm.vue +10 -10
- package/app/components/settings/RiskPolicyEditorRow.vue +14 -14
- package/app/components/settings/RiskPolicyHealthModal.vue +15 -13
- package/app/components/settings/RiskPolicyInheritedRow.vue +1 -1
- package/app/components/settings/RiskPolicyPanel.vue +10 -15
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +7 -7
- package/app/components/settings/SharedStacksPanel.vue +9 -12
- package/app/components/settings/TaskSourceCard.vue +4 -4
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +6 -6
- package/app/components/settings/ToolServerChecklist.vue +36 -29
- package/app/components/settings/UsageSettings.vue +15 -15
- package/app/components/settings/UserSecretsSection.vue +9 -12
- package/app/components/settings/WorkspaceMetadataSettings.vue +5 -5
- package/app/components/settings/WorkspaceSettingsPanel.vue +47 -47
- package/app/components/skills/ReviewSkillQueue.vue +10 -10
- package/app/components/skills/SkillLibraryManager.vue +23 -20
- package/app/components/slack/SlackPanel.vue +13 -17
- package/app/components/spec/ServiceSpecWindow.vue +45 -42
- package/app/components/tasks/BugHuntModal.vue +24 -27
- package/app/components/tasks/ContextIssuePicker.vue +11 -11
- package/app/components/tasks/TaskContextIssues.vue +3 -3
- package/app/components/tasks/TaskImportModal.vue +7 -7
- package/app/components/tasks/TaskSourceConnectModal.vue +10 -8
- package/app/components/testing/TestReportWindow.vue +99 -82
- package/app/components/theme/ThemeImportModal.vue +115 -0
- package/app/components/tutorial/TutorialCatalogue.vue +9 -9
- package/app/components/tutorial/TutorialNudge.vue +5 -5
- package/app/components/tutorial/TutorialOverlay.vue +12 -12
- package/app/components/tutorial/TutorialPrompt.vue +6 -9
- package/app/components/vcs/GitLabConnect.vue +4 -4
- package/app/components/vcs/VcsConnectSurfaces.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +36 -36
- package/app/composables/api/client.ts +6 -1
- package/app/composables/usePipelineErrorToast.ts +17 -0
- package/app/modular/agent-kinds.ts +24 -0
- package/app/pages/index.vue +5 -5
- package/app/plugins/theme.client.ts +125 -0
- package/app/spa-loading-template.html +52 -14
- package/app/stores/agents.ts +1 -1
- package/app/stores/theme.spec.ts +56 -0
- package/app/stores/theme.ts +87 -0
- package/app/types/domain.ts +19 -0
- package/app/types/execution.ts +4 -0
- package/app/utils/agentOutput.ts +1 -1
- package/app/utils/binaryOutput.ts +6 -6
- package/app/utils/bootstrapSteps.ts +14 -14
- package/app/utils/catalog.ts +87 -83
- package/app/utils/colorTint.ts +10 -0
- package/app/utils/failureKinds.ts +1 -0
- package/app/utils/observability.ts +3 -3
- package/app/utils/pipelineRender.ts +13 -17
- package/app/utils/swimlanes.ts +4 -4
- package/app/utils/theme/bootPalette.spec.ts +54 -0
- package/app/utils/theme/bootPalette.ts +108 -0
- package/app/utils/theme/builtins.spec.ts +38 -0
- package/app/utils/theme/builtins.ts +55 -0
- package/app/utils/theme/css.ts +162 -0
- package/app/utils/theme/doc.ts +353 -0
- package/app/utils/theme/link.ts +93 -0
- package/app/utils/theme/presets.ts +509 -0
- package/app/utils/theme/theme.spec.ts +224 -0
- package/i18n/locales/de.json +61 -4
- package/i18n/locales/en.json +70 -4
- package/i18n/locales/es.json +61 -4
- package/i18n/locales/fr.json +61 -4
- package/i18n/locales/he.json +61 -4
- package/i18n/locales/it.json +61 -4
- package/i18n/locales/ja.json +61 -4
- package/i18n/locales/pl.json +61 -4
- package/i18n/locales/tr.json +61 -4
- package/i18n/locales/uk.json +61 -4
- package/nuxt.config.ts +37 -11
- package/package.json +10 -9
|
@@ -182,7 +182,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
182
182
|
<ResultWindowShell
|
|
183
183
|
:open="open"
|
|
184
184
|
icon="i-lucide-scroll-text"
|
|
185
|
-
icon-class="bg-
|
|
185
|
+
icon-class="bg-primary/15 text-primary"
|
|
186
186
|
:title="t('spec.title')"
|
|
187
187
|
:subtitle="block ? spec?.service || block.title : undefined"
|
|
188
188
|
variant="centered"
|
|
@@ -191,7 +191,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
191
191
|
>
|
|
192
192
|
<!-- view toggle: Gherkin only when the spec (and its feature files) are on main -->
|
|
193
193
|
<template v-if="present" #header-extras>
|
|
194
|
-
<div class="flex items-center rounded-lg border border-
|
|
194
|
+
<div class="flex items-center rounded-lg border border-muted p-0.5">
|
|
195
195
|
<UButton
|
|
196
196
|
:color="mode === 'structured' ? 'primary' : 'neutral'"
|
|
197
197
|
:variant="mode === 'structured' ? 'soft' : 'ghost'"
|
|
@@ -226,7 +226,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
226
226
|
<!-- loading -->
|
|
227
227
|
<div
|
|
228
228
|
v-if="loading && !view"
|
|
229
|
-
class="flex flex-1 items-center justify-center gap-2 text-sm text-
|
|
229
|
+
class="flex flex-1 items-center justify-center gap-2 text-sm text-muted"
|
|
230
230
|
>
|
|
231
231
|
<UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
|
|
232
232
|
{{ t('spec.loading') }}
|
|
@@ -235,9 +235,9 @@ function kindLabel(item: RequirementItem): string {
|
|
|
235
235
|
<!-- error -->
|
|
236
236
|
<div
|
|
237
237
|
v-else-if="errored"
|
|
238
|
-
class="flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center text-sm text-
|
|
238
|
+
class="flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center text-sm text-muted"
|
|
239
239
|
>
|
|
240
|
-
<UIcon name="i-lucide-triangle-alert" class="h-6 w-6 text-
|
|
240
|
+
<UIcon name="i-lucide-triangle-alert" class="h-6 w-6 text-app-warning-400" />
|
|
241
241
|
{{ t('spec.error') }}
|
|
242
242
|
<UButton
|
|
243
243
|
icon="i-lucide-rotate-cw"
|
|
@@ -256,10 +256,10 @@ function kindLabel(item: RequirementItem): string {
|
|
|
256
256
|
v-else-if="!present"
|
|
257
257
|
class="flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center"
|
|
258
258
|
>
|
|
259
|
-
<UIcon name="i-lucide-scroll-text" class="h-8 w-8 text-
|
|
259
|
+
<UIcon name="i-lucide-scroll-text" class="h-8 w-8 text-app-600" />
|
|
260
260
|
<div>
|
|
261
|
-
<p class="text-sm font-medium text-
|
|
262
|
-
<p class="mx-auto mt-1 max-w-md text-xs text-
|
|
261
|
+
<p class="text-sm font-medium text-toned">{{ t('spec.empty.title') }}</p>
|
|
262
|
+
<p class="mx-auto mt-1 max-w-md text-xs text-dimmed">
|
|
263
263
|
{{ t('spec.empty.description') }}
|
|
264
264
|
</p>
|
|
265
265
|
</div>
|
|
@@ -268,7 +268,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
268
268
|
<!-- spec body: navigable tree + detail -->
|
|
269
269
|
<div v-else class="flex min-h-0 flex-1">
|
|
270
270
|
<!-- nav: modules → feature groups -->
|
|
271
|
-
<nav class="w-64 shrink-0 overflow-y-auto border-e border-
|
|
271
|
+
<nav class="w-64 shrink-0 overflow-y-auto border-e border-default px-3 py-4">
|
|
272
272
|
<UButton
|
|
273
273
|
block
|
|
274
274
|
class="mb-2 justify-start"
|
|
@@ -285,7 +285,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
285
285
|
{{ t('spec.overview') }}
|
|
286
286
|
</UButton>
|
|
287
287
|
<div v-for="(mod, mi) in modules" :key="mi" class="mb-3">
|
|
288
|
-
<div class="px-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-
|
|
288
|
+
<div class="px-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
|
|
289
289
|
{{ mod.name }}
|
|
290
290
|
</div>
|
|
291
291
|
<ul class="space-y-0.5">
|
|
@@ -295,18 +295,18 @@ function kindLabel(item: RequirementItem): string {
|
|
|
295
295
|
class="flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-start text-[13px] transition"
|
|
296
296
|
:class="
|
|
297
297
|
selected?.m === mi && selected?.g === gi
|
|
298
|
-
? 'bg-
|
|
299
|
-
: 'text-
|
|
298
|
+
? 'bg-primary/15 text-primary'
|
|
299
|
+
: 'text-toned hover:bg-elevated'
|
|
300
300
|
"
|
|
301
301
|
@click="selectGroup(mi, gi)"
|
|
302
302
|
>
|
|
303
303
|
<span class="truncate">{{ group.name }}</span>
|
|
304
|
-
<span class="shrink-0 text-[10px] text-
|
|
304
|
+
<span class="shrink-0 text-[10px] text-dimmed">{{ reqCount(group) }}</span>
|
|
305
305
|
</button>
|
|
306
306
|
</li>
|
|
307
307
|
<li
|
|
308
308
|
v-if="(mod.groups?.length ?? 0) === 0"
|
|
309
|
-
class="px-2 py-1 text-[11px] italic text-
|
|
309
|
+
class="px-2 py-1 text-[11px] italic text-app-600"
|
|
310
310
|
>
|
|
311
311
|
{{ t('spec.noFeatureGroups') }}
|
|
312
312
|
</li>
|
|
@@ -318,14 +318,14 @@ function kindLabel(item: RequirementItem): string {
|
|
|
318
318
|
<div class="min-w-0 flex-1 overflow-y-auto px-6 py-5">
|
|
319
319
|
<!-- service overview -->
|
|
320
320
|
<template v-if="selected === null">
|
|
321
|
-
<h2 class="text-lg font-semibold text-
|
|
321
|
+
<h2 class="text-lg font-semibold text-highlighted">{{ spec?.service }}</h2>
|
|
322
322
|
<!-- The service's own prose, so it takes the reading measure the shell's `full` width
|
|
323
323
|
obliges (see the `width` prop). The requirement rows and Gherkin blocks below keep
|
|
324
324
|
the full span — they are structure, not paragraphs. -->
|
|
325
|
-
<p v-if="spec?.summary" class="mt-2 max-w-3xl whitespace-pre-line text-sm text-
|
|
325
|
+
<p v-if="spec?.summary" class="mt-2 max-w-3xl whitespace-pre-line text-sm text-toned">
|
|
326
326
|
{{ spec.summary }}
|
|
327
327
|
</p>
|
|
328
|
-
<p v-else class="mt-2 text-sm text-
|
|
328
|
+
<p v-else class="mt-2 text-sm text-dimmed">{{ t('spec.noSummary') }}</p>
|
|
329
329
|
<!-- implementation-state rollup: how much of the written-down behaviour is observed
|
|
330
330
|
to hold, rather than merely agreed -->
|
|
331
331
|
<div
|
|
@@ -339,9 +339,9 @@ function kindLabel(item: RequirementItem): string {
|
|
|
339
339
|
<UBadge color="neutral" variant="subtle" size="sm">
|
|
340
340
|
{{ t('spec.state.aspirationalCount', { count: specStates.aspirational }) }}
|
|
341
341
|
</UBadge>
|
|
342
|
-
<span class="text-
|
|
342
|
+
<span class="text-dimmed">{{ t('spec.state.rollupHint') }}</span>
|
|
343
343
|
</div>
|
|
344
|
-
<p class="mt-4 text-xs text-
|
|
344
|
+
<p class="mt-4 text-xs text-dimmed">
|
|
345
345
|
{{
|
|
346
346
|
hasGherkin
|
|
347
347
|
? t('spec.moduleHintGherkin', { count: modules.length }, modules.length)
|
|
@@ -352,11 +352,11 @@ function kindLabel(item: RequirementItem): string {
|
|
|
352
352
|
|
|
353
353
|
<!-- selected feature group -->
|
|
354
354
|
<template v-else-if="selectedGroup">
|
|
355
|
-
<div class="mb-1 text-[11px] uppercase tracking-wide text-
|
|
355
|
+
<div class="mb-1 text-[11px] uppercase tracking-wide text-dimmed">
|
|
356
356
|
{{ selectedModule?.name }}
|
|
357
357
|
</div>
|
|
358
|
-
<h2 class="text-lg font-semibold text-
|
|
359
|
-
<p v-if="selectedGroup.summary" class="mt-1 max-w-3xl text-sm text-
|
|
358
|
+
<h2 class="text-lg font-semibold text-highlighted">{{ selectedGroup.name }}</h2>
|
|
359
|
+
<p v-if="selectedGroup.summary" class="mt-1 max-w-3xl text-sm text-muted">
|
|
360
360
|
{{ selectedGroup.summary }}
|
|
361
361
|
</p>
|
|
362
362
|
|
|
@@ -364,11 +364,11 @@ function kindLabel(item: RequirementItem): string {
|
|
|
364
364
|
<template v-if="mode === 'gherkin'">
|
|
365
365
|
<pre
|
|
366
366
|
v-if="selectedFeature"
|
|
367
|
-
class="mt-4 overflow-x-auto rounded-lg border border-
|
|
367
|
+
class="mt-4 overflow-x-auto rounded-lg border border-default bg-app-950/60 p-4 text-[12.5px] leading-relaxed text-default"
|
|
368
368
|
><code>{{ selectedFeature.content }}</code></pre>
|
|
369
369
|
<div
|
|
370
370
|
v-else
|
|
371
|
-
class="mt-4 rounded-lg border border-dashed border-
|
|
371
|
+
class="mt-4 rounded-lg border border-dashed border-muted p-6 text-center text-sm text-dimmed"
|
|
372
372
|
>
|
|
373
373
|
{{ t('spec.noGherkinForGroup') }}
|
|
374
374
|
</div>
|
|
@@ -376,7 +376,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
376
376
|
|
|
377
377
|
<!-- STRUCTURED view: requirements + acceptance + domain rules -->
|
|
378
378
|
<template v-else>
|
|
379
|
-
<div v-if="reqCount(selectedGroup) === 0" class="mt-4 text-sm text-
|
|
379
|
+
<div v-if="reqCount(selectedGroup) === 0" class="mt-4 text-sm text-dimmed">
|
|
380
380
|
{{ t('spec.noRequirements') }}
|
|
381
381
|
</div>
|
|
382
382
|
<!-- per-group implementation-state rollup + the filter over the two halves -->
|
|
@@ -385,8 +385,11 @@ function kindLabel(item: RequirementItem): string {
|
|
|
385
385
|
class="mt-4 flex flex-wrap items-center justify-between gap-2"
|
|
386
386
|
data-testid="spec-state-filter"
|
|
387
387
|
>
|
|
388
|
-
<div class="flex items-center gap-1.5 text-[11px] text-
|
|
389
|
-
<UIcon
|
|
388
|
+
<div class="flex items-center gap-1.5 text-[11px] text-dimmed">
|
|
389
|
+
<UIcon
|
|
390
|
+
:name="STATE_META.established.icon"
|
|
391
|
+
class="h-3.5 w-3.5 text-app-success-400"
|
|
392
|
+
/>
|
|
390
393
|
{{
|
|
391
394
|
t('spec.state.groupRollup', {
|
|
392
395
|
established: groupStates.established,
|
|
@@ -394,7 +397,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
394
397
|
})
|
|
395
398
|
}}
|
|
396
399
|
</div>
|
|
397
|
-
<div class="flex items-center rounded-lg border border-
|
|
400
|
+
<div class="flex items-center rounded-lg border border-muted p-0.5">
|
|
398
401
|
<UButton
|
|
399
402
|
v-for="option in STATE_FILTERS"
|
|
400
403
|
:key="option.value"
|
|
@@ -418,7 +421,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
418
421
|
back here rather than making them find the toggle again. -->
|
|
419
422
|
<div
|
|
420
423
|
v-if="reqCount(selectedGroup) > 0 && visibleRequirements.length === 0"
|
|
421
|
-
class="mt-4 flex flex-wrap items-center gap-2 text-sm text-
|
|
424
|
+
class="mt-4 flex flex-wrap items-center gap-2 text-sm text-dimmed"
|
|
422
425
|
data-testid="spec-state-filter-empty"
|
|
423
426
|
>
|
|
424
427
|
{{ t('spec.state.noneMatchFilter') }}
|
|
@@ -441,10 +444,10 @@ function kindLabel(item: RequirementItem): string {
|
|
|
441
444
|
<li
|
|
442
445
|
v-for="req in visibleRequirements"
|
|
443
446
|
:key="req.id"
|
|
444
|
-
class="rounded-lg border border-
|
|
447
|
+
class="rounded-lg border border-default bg-default/60 p-4"
|
|
445
448
|
>
|
|
446
449
|
<div class="flex items-start justify-between gap-3">
|
|
447
|
-
<h3 class="text-sm font-semibold text-
|
|
450
|
+
<h3 class="text-sm font-semibold text-app-100">{{ req.title }}</h3>
|
|
448
451
|
<div class="flex shrink-0 items-center gap-1.5">
|
|
449
452
|
<!-- implementation state: agreed vs observed to hold. The distinction the
|
|
450
453
|
build prompt and the tester act on, so a reader must see it too. -->
|
|
@@ -463,7 +466,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
463
466
|
<UBadge color="neutral" variant="subtle" size="sm">{{ kindLabel(req) }}</UBadge>
|
|
464
467
|
</div>
|
|
465
468
|
</div>
|
|
466
|
-
<p class="mt-1.5 whitespace-pre-line text-[13px] leading-relaxed text-
|
|
469
|
+
<p class="mt-1.5 whitespace-pre-line text-[13px] leading-relaxed text-toned">
|
|
467
470
|
{{ req.statement }}
|
|
468
471
|
</p>
|
|
469
472
|
<!-- acceptance criteria (Given/When/Then) -->
|
|
@@ -471,22 +474,22 @@ function kindLabel(item: RequirementItem): string {
|
|
|
471
474
|
<div
|
|
472
475
|
v-for="ac in req.acceptance ?? []"
|
|
473
476
|
:key="ac.id"
|
|
474
|
-
class="rounded-md border border-
|
|
477
|
+
class="rounded-md border border-default bg-app-950/50 px-3 py-2 text-[12.5px] leading-relaxed"
|
|
475
478
|
>
|
|
476
|
-
<p class="text-
|
|
477
|
-
<span class="font-semibold text-
|
|
479
|
+
<p class="text-toned">
|
|
480
|
+
<span class="font-semibold text-app-success-400">{{
|
|
478
481
|
t('spec.acceptance.given')
|
|
479
482
|
}}</span>
|
|
480
483
|
{{ ac.given }}
|
|
481
484
|
</p>
|
|
482
|
-
<p class="text-
|
|
483
|
-
<span class="font-semibold text-
|
|
485
|
+
<p class="text-toned">
|
|
486
|
+
<span class="font-semibold text-app-info-400">{{
|
|
484
487
|
t('spec.acceptance.when')
|
|
485
488
|
}}</span>
|
|
486
489
|
{{ ac.when }}
|
|
487
490
|
</p>
|
|
488
|
-
<p class="text-
|
|
489
|
-
<span class="font-semibold text-
|
|
491
|
+
<p class="text-toned">
|
|
492
|
+
<span class="font-semibold text-app-secondary-400">{{
|
|
490
493
|
t('spec.acceptance.then')
|
|
491
494
|
}}</span>
|
|
492
495
|
{{ ac.outcome }}
|
|
@@ -499,7 +502,7 @@ function kindLabel(item: RequirementItem): string {
|
|
|
499
502
|
<!-- domain rules / invariants scoped to this group -->
|
|
500
503
|
<div v-if="(selectedGroup.rules?.length ?? 0) > 0" class="mt-6">
|
|
501
504
|
<div
|
|
502
|
-
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-
|
|
505
|
+
class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
|
|
503
506
|
>
|
|
504
507
|
<UIcon name="i-lucide-shield-check" class="h-3.5 w-3.5" />
|
|
505
508
|
{{ t('spec.domainRules') }}
|
|
@@ -508,10 +511,10 @@ function kindLabel(item: RequirementItem): string {
|
|
|
508
511
|
<li
|
|
509
512
|
v-for="rule in selectedGroup.rules ?? []"
|
|
510
513
|
:key="rule.id"
|
|
511
|
-
class="rounded-md border border-
|
|
514
|
+
class="rounded-md border border-default bg-default/60 px-3 py-2 text-[13px] text-toned"
|
|
512
515
|
>
|
|
513
516
|
{{ rule.rule }}
|
|
514
|
-
<span v-if="rule.rationale" class="text-
|
|
517
|
+
<span v-if="rule.rationale" class="text-dimmed">{{
|
|
515
518
|
t('spec.ruleRationale', { rationale: rule.rationale })
|
|
516
519
|
}}</span>
|
|
517
520
|
</li>
|
|
@@ -339,8 +339,8 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
339
339
|
<template #body>
|
|
340
340
|
<!-- No tracker offered (none connected/installed, or all disabled). -->
|
|
341
341
|
<div v-if="!tasks.anyOffered" class="space-y-3 text-center">
|
|
342
|
-
<UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-
|
|
343
|
-
<p class="text-sm text-
|
|
342
|
+
<UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-dimmed" />
|
|
343
|
+
<p class="text-sm text-muted">{{ t('bugHunt.connectFirst') }}</p>
|
|
344
344
|
<div class="flex flex-wrap justify-center gap-2">
|
|
345
345
|
<UButton
|
|
346
346
|
v-for="choice in addableSources"
|
|
@@ -356,12 +356,12 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
356
356
|
</div>
|
|
357
357
|
|
|
358
358
|
<!-- No service frame yet → nowhere for an adopted bug to land. -->
|
|
359
|
-
<p v-else-if="!containerItems.length" class="text-center text-xs text-
|
|
359
|
+
<p v-else-if="!containerItems.length" class="text-center text-xs text-dimmed">
|
|
360
360
|
{{ t('bugHunt.needFrameFirst') }}
|
|
361
361
|
</p>
|
|
362
362
|
|
|
363
363
|
<div v-else class="space-y-4">
|
|
364
|
-
<p class="text-xs text-
|
|
364
|
+
<p class="text-xs text-muted">{{ t('bugHunt.intro') }}</p>
|
|
365
365
|
|
|
366
366
|
<div class="grid gap-3 sm:grid-cols-2">
|
|
367
367
|
<UFormField :label="t('bugHunt.tracker')">
|
|
@@ -386,7 +386,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
386
386
|
<span class="truncate">{{ descriptor?.label ?? t('bugHunt.pickTracker') }}</span>
|
|
387
387
|
</UButton>
|
|
388
388
|
</UDropdownMenu>
|
|
389
|
-
<p v-else class="flex items-center gap-1.5 py-1 text-sm text-
|
|
389
|
+
<p v-else class="flex items-center gap-1.5 py-1 text-sm text-toned">
|
|
390
390
|
<UIcon v-if="descriptor?.icon" :name="descriptor.icon" class="h-4 w-4 shrink-0" />
|
|
391
391
|
<span class="truncate">{{ descriptor?.label ?? t('bugHunt.pickTracker') }}</span>
|
|
392
392
|
</p>
|
|
@@ -397,10 +397,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
397
397
|
STATED rather than asked: the repository the service below is linked to. No
|
|
398
398
|
control at all, because every value one could offer here is either that repo
|
|
399
399
|
(nothing to choose) or another one this board holds no service for. -->
|
|
400
|
-
<p
|
|
401
|
-
v-if="boardFromService"
|
|
402
|
-
class="flex items-center gap-1.5 py-1 text-sm text-slate-300"
|
|
403
|
-
>
|
|
400
|
+
<p v-if="boardFromService" class="flex items-center gap-1.5 py-1 text-sm text-toned">
|
|
404
401
|
<UIcon name="i-lucide-folder-git-2" class="h-4 w-4 shrink-0" />
|
|
405
402
|
<span class="truncate">{{ scopedRepo ?? t('bugHunt.boardFromService') }}</span>
|
|
406
403
|
</p>
|
|
@@ -422,12 +419,12 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
422
419
|
/>
|
|
423
420
|
<!-- The service holds no repository, so there are no issues to read. Said here
|
|
424
421
|
rather than in a toast: it invalidates the scope named right above it. -->
|
|
425
|
-
<p v-if="huntNeedsRepo" class="mt-1 text-xs text-
|
|
422
|
+
<p v-if="huntNeedsRepo" class="mt-1 text-xs text-app-warning-400">
|
|
426
423
|
{{ t('bugHunt.boardNeedsRepo') }}
|
|
427
424
|
</p>
|
|
428
425
|
<!-- A board read that failed for a fixable reason (unreachable site, expired
|
|
429
426
|
token): named, so the user isn't left with an empty picker and no cause. -->
|
|
430
|
-
<p v-else-if="boardsFailure" class="mt-1 text-xs text-
|
|
427
|
+
<p v-else-if="boardsFailure" class="mt-1 text-xs text-app-warning-400">
|
|
431
428
|
{{ t('bugHunt.boardsFailed', { reason: boardsFailure }) }}
|
|
432
429
|
</p>
|
|
433
430
|
</UFormField>
|
|
@@ -440,7 +437,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
440
437
|
<!-- Not a disabled input: this tracker's provider never sends the predicate, so a box
|
|
441
438
|
still holding a value would read as a filter that is on. What it CAN narrow by is
|
|
442
439
|
named instead, since the alternative is a hunt over every open issue. -->
|
|
443
|
-
<p v-else class="text-xs text-
|
|
440
|
+
<p v-else class="text-xs text-app-warning-400">
|
|
444
441
|
{{ t('bugHunt.issueTypeUnsupported', { tracker: descriptor?.label ?? '' }) }}
|
|
445
442
|
</p>
|
|
446
443
|
</UFormField>
|
|
@@ -458,15 +455,15 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
458
455
|
<!-- Two blocks rather than one with a computed `keypath`: the i18n extractor reads a
|
|
459
456
|
bound keypath as the key itself, so a dynamic one is a key missing from every
|
|
460
457
|
locale. Every other `<i18n-t>` in the SPA names its key statically for that reason. -->
|
|
461
|
-
<p v-if="containerStated" class="text-xs text-
|
|
458
|
+
<p v-if="containerStated" class="text-xs text-muted">
|
|
462
459
|
<i18n-t v-if="boardFromService" keypath="bugHunt.huntingIn" tag="span" scope="global">
|
|
463
460
|
<template #container>
|
|
464
|
-
<span class="font-medium text-
|
|
461
|
+
<span class="font-medium text-default">{{ pinnedContainer!.title }}</span>
|
|
465
462
|
</template>
|
|
466
463
|
</i18n-t>
|
|
467
464
|
<i18n-t v-else keypath="bugHunt.adoptingInto" tag="span" scope="global">
|
|
468
465
|
<template #container>
|
|
469
|
-
<span class="font-medium text-
|
|
466
|
+
<span class="font-medium text-default">{{ pinnedContainer!.title }}</span>
|
|
470
467
|
</template>
|
|
471
468
|
</i18n-t>
|
|
472
469
|
</p>
|
|
@@ -490,33 +487,33 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
490
487
|
>
|
|
491
488
|
{{ t('bugHunt.run') }}
|
|
492
489
|
</UButton>
|
|
493
|
-
<span v-if="hunt.hunting" class="text-xs text-
|
|
490
|
+
<span v-if="hunt.hunting" class="text-xs text-muted">
|
|
494
491
|
{{ t('bugHunt.running') }}
|
|
495
492
|
</span>
|
|
496
493
|
</div>
|
|
497
494
|
|
|
498
495
|
<!-- Results -->
|
|
499
|
-
<div v-if="hunt.hasResult" class="space-y-3 border-t border-
|
|
500
|
-
<p class="text-xs text-
|
|
496
|
+
<div v-if="hunt.hasResult" class="space-y-3 border-t border-default pt-3">
|
|
497
|
+
<p class="text-xs text-muted">
|
|
501
498
|
<!-- The board the scan actually ran against, named because on a repo-backed tracker
|
|
502
499
|
the platform resolved it: the person reading the shortlist should not have to
|
|
503
500
|
infer which repository it came out of. -->
|
|
504
|
-
<span class="text-
|
|
501
|
+
<span class="text-dimmed">
|
|
505
502
|
{{ t('bugHunt.scannedBoard', { board: hunt.result!.board }) }}
|
|
506
503
|
</span>
|
|
507
504
|
{{ t(STATUS_KEYS[hunt.result!.analysisStatus]) }}
|
|
508
|
-
<span v-if="hunt.result!.model" class="text-
|
|
505
|
+
<span v-if="hunt.result!.model" class="text-dimmed">
|
|
509
506
|
{{ t('bugHunt.viaModel', { model: hunt.result!.model }) }}
|
|
510
507
|
</span>
|
|
511
508
|
</p>
|
|
512
|
-
<p v-if="hunt.result!.truncated" class="text-xs text-
|
|
509
|
+
<p v-if="hunt.result!.truncated" class="text-xs text-app-warning-400">
|
|
513
510
|
{{ t('bugHunt.truncated', { count: hunt.result!.scanned }) }}
|
|
514
511
|
</p>
|
|
515
512
|
|
|
516
513
|
<div
|
|
517
514
|
v-for="candidate in hunt.candidates"
|
|
518
515
|
:key="candidate.externalId"
|
|
519
|
-
class="space-y-2 rounded-md border border-
|
|
516
|
+
class="space-y-2 rounded-md border border-default p-3"
|
|
520
517
|
>
|
|
521
518
|
<div class="flex items-start justify-between gap-3">
|
|
522
519
|
<div class="min-w-0 space-y-1">
|
|
@@ -535,12 +532,12 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
535
532
|
:to="candidate.url"
|
|
536
533
|
target="_blank"
|
|
537
534
|
rel="noopener noreferrer"
|
|
538
|
-
class="truncate text-sm font-medium text-
|
|
535
|
+
class="truncate text-sm font-medium text-app-100"
|
|
539
536
|
>
|
|
540
537
|
{{ candidate.externalId }}: {{ candidate.title }}
|
|
541
538
|
</ULink>
|
|
542
539
|
</div>
|
|
543
|
-
<p v-if="candidate.analysis" class="text-xs text-
|
|
540
|
+
<p v-if="candidate.analysis" class="text-xs text-muted">
|
|
544
541
|
{{
|
|
545
542
|
t('bugHunt.ratings', {
|
|
546
543
|
impact: candidate.analysis.impact,
|
|
@@ -549,10 +546,10 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
549
546
|
})
|
|
550
547
|
}}
|
|
551
548
|
</p>
|
|
552
|
-
<p v-if="candidate.analysis?.rationale" class="text-xs text-
|
|
549
|
+
<p v-if="candidate.analysis?.rationale" class="text-xs text-toned">
|
|
553
550
|
{{ candidate.analysis.rationale }}
|
|
554
551
|
</p>
|
|
555
|
-
<div class="flex flex-wrap items-center gap-2 text-[11px] text-
|
|
552
|
+
<div class="flex flex-wrap items-center gap-2 text-[11px] text-dimmed">
|
|
556
553
|
<span v-if="candidate.priority">{{ candidate.priority }}</span>
|
|
557
554
|
<span v-for="label in candidate.labels" :key="label">{{ label }}</span>
|
|
558
555
|
<span v-if="createdAtDate(candidate.createdAt)">
|
|
@@ -582,7 +579,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
582
579
|
</div>
|
|
583
580
|
</div>
|
|
584
581
|
|
|
585
|
-
<p v-if="!hunt.candidates.length" class="text-center text-xs text-
|
|
582
|
+
<p v-if="!hunt.candidates.length" class="text-center text-xs text-dimmed">
|
|
586
583
|
{{ t('bugHunt.noCandidates') }}
|
|
587
584
|
</p>
|
|
588
585
|
</div>
|
|
@@ -284,7 +284,7 @@ onMounted(() => {
|
|
|
284
284
|
</script>
|
|
285
285
|
|
|
286
286
|
<template>
|
|
287
|
-
<div class="space-y-2 rounded-lg border border-
|
|
287
|
+
<div class="space-y-2 rounded-lg border border-default bg-default/40 p-2">
|
|
288
288
|
<!-- Which tracker is being searched, always visible, plus the trackers the user could add from
|
|
289
289
|
here (each opens the connect modal over the caller's form). With a single entry there is
|
|
290
290
|
nothing to decide, so the tracker is named as plain text: a chevron opening a one-item menu
|
|
@@ -293,7 +293,7 @@ onMounted(() => {
|
|
|
293
293
|
<div class="flex items-center gap-1.5">
|
|
294
294
|
<span
|
|
295
295
|
:id="sourceLabelId"
|
|
296
|
-
class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-
|
|
296
|
+
class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-dimmed"
|
|
297
297
|
>
|
|
298
298
|
{{ t('tasks.picker.sourceLabel') }}
|
|
299
299
|
</span>
|
|
@@ -315,7 +315,7 @@ onMounted(() => {
|
|
|
315
315
|
<span class="truncate">{{ descriptor?.label ?? t('tasks.picker.noSource') }}</span>
|
|
316
316
|
</UButton>
|
|
317
317
|
</UDropdownMenu>
|
|
318
|
-
<span v-else class="flex min-w-0 items-center gap-1 text-xs text-
|
|
318
|
+
<span v-else class="flex min-w-0 items-center gap-1 text-xs text-toned">
|
|
319
319
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0" />
|
|
320
320
|
<span class="truncate">{{ descriptor?.label ?? t('tasks.picker.noSource') }}</span>
|
|
321
321
|
</span>
|
|
@@ -335,7 +335,7 @@ onMounted(() => {
|
|
|
335
335
|
@keydown.enter="refRow && pickRef(refRow)"
|
|
336
336
|
/>
|
|
337
337
|
|
|
338
|
-
<p v-if="searchError" class="px-1 text-[11px] text-
|
|
338
|
+
<p v-if="searchError" class="px-1 text-[11px] text-app-warning-400">
|
|
339
339
|
{{ searchError }}
|
|
340
340
|
</p>
|
|
341
341
|
|
|
@@ -345,10 +345,10 @@ onMounted(() => {
|
|
|
345
345
|
v-for="row in importedRows"
|
|
346
346
|
:key="`imp:${row.externalId}`"
|
|
347
347
|
type="button"
|
|
348
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-
|
|
348
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
349
349
|
@click="pickImported(row)"
|
|
350
350
|
>
|
|
351
|
-
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-
|
|
351
|
+
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-primary" />
|
|
352
352
|
<span class="truncate">{{ row.externalId }} · {{ row.title }}</span>
|
|
353
353
|
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
|
|
354
354
|
t('tasks.picker.imported')
|
|
@@ -360,10 +360,10 @@ onMounted(() => {
|
|
|
360
360
|
v-for="r in searchRows"
|
|
361
361
|
:key="`hit:${r.externalId}`"
|
|
362
362
|
type="button"
|
|
363
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-
|
|
363
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
364
364
|
@click="pickSearch(r)"
|
|
365
365
|
>
|
|
366
|
-
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-
|
|
366
|
+
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-muted" />
|
|
367
367
|
<span class="truncate">{{ r.externalId }} · {{ r.title }}</span>
|
|
368
368
|
<UBadge v-if="r.status" color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
|
|
369
369
|
{{ r.status }}
|
|
@@ -374,14 +374,14 @@ onMounted(() => {
|
|
|
374
374
|
<button
|
|
375
375
|
v-if="refRow"
|
|
376
376
|
type="button"
|
|
377
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-
|
|
377
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
378
378
|
@click="pickRef(refRow)"
|
|
379
379
|
>
|
|
380
|
-
<UIcon name="i-lucide-link" class="h-3.5 w-3.5 shrink-0 text-
|
|
380
|
+
<UIcon name="i-lucide-link" class="h-3.5 w-3.5 shrink-0 text-muted" />
|
|
381
381
|
<span class="truncate">
|
|
382
382
|
<i18n-t keypath="tasks.picker.attachByReference" tag="span" scope="global">
|
|
383
383
|
<template #ref>
|
|
384
|
-
<span class="text-
|
|
384
|
+
<span class="text-default">{{ refRow }}</span>
|
|
385
385
|
</template>
|
|
386
386
|
</i18n-t>
|
|
387
387
|
</span>
|
|
@@ -138,11 +138,11 @@ async function attach(item: PendingContext) {
|
|
|
138
138
|
:href="issue.url"
|
|
139
139
|
target="_blank"
|
|
140
140
|
rel="noopener"
|
|
141
|
-
class="flex items-center gap-1.5 rounded-md border border-
|
|
141
|
+
class="flex items-center gap-1.5 rounded-md border border-default bg-default/60 px-2 py-1.5 text-xs text-toned hover:bg-elevated/60"
|
|
142
142
|
>
|
|
143
143
|
<UIcon
|
|
144
144
|
:name="tasks.descriptorFor(issue.source)?.icon ?? 'i-lucide-square-check'"
|
|
145
|
-
class="h-3.5 w-3.5 shrink-0 text-
|
|
145
|
+
class="h-3.5 w-3.5 shrink-0 text-primary"
|
|
146
146
|
/>
|
|
147
147
|
<span class="truncate">{{ issue.externalId }} · {{ issue.title }}</span>
|
|
148
148
|
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
|
|
@@ -150,7 +150,7 @@ async function attach(item: PendingContext) {
|
|
|
150
150
|
</UBadge>
|
|
151
151
|
</a>
|
|
152
152
|
</div>
|
|
153
|
-
<p v-else class="text-[11px] text-
|
|
153
|
+
<p v-else class="text-[11px] text-dimmed">
|
|
154
154
|
{{ emptyHint }}
|
|
155
155
|
</p>
|
|
156
156
|
</InspectorSection>
|
|
@@ -126,8 +126,8 @@ async function doSpawnEpic() {
|
|
|
126
126
|
<template #body>
|
|
127
127
|
<!-- Empty state: no source offered (none connected/installed, or all disabled) -->
|
|
128
128
|
<div v-if="!tasks.anyOffered" class="space-y-3 text-center">
|
|
129
|
-
<UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-
|
|
130
|
-
<p class="text-sm text-
|
|
129
|
+
<UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-dimmed" />
|
|
130
|
+
<p class="text-sm text-muted">{{ t('tasks.import.connectFirst') }}</p>
|
|
131
131
|
<div class="flex justify-center gap-2">
|
|
132
132
|
<UButton
|
|
133
133
|
v-for="choice in addableSources"
|
|
@@ -143,7 +143,7 @@ async function doSpawnEpic() {
|
|
|
143
143
|
</div>
|
|
144
144
|
|
|
145
145
|
<!-- No service frame yet → nowhere to create a task. -->
|
|
146
|
-
<p v-else-if="!containerItems.length" class="text-center text-xs text-
|
|
146
|
+
<p v-else-if="!containerItems.length" class="text-center text-xs text-dimmed">
|
|
147
147
|
{{ t('tasks.import.needFrameFirst') }}
|
|
148
148
|
</p>
|
|
149
149
|
|
|
@@ -152,10 +152,10 @@ async function doSpawnEpic() {
|
|
|
152
152
|
<!-- Where the new task lands. Stated when there is one legal target (opened from a service
|
|
153
153
|
frame that has no modules); otherwise a real choice, scoped to that frame when the
|
|
154
154
|
modal was opened from one. -->
|
|
155
|
-
<p v-if="containerStated" class="text-xs text-
|
|
155
|
+
<p v-if="containerStated" class="text-xs text-muted">
|
|
156
156
|
<i18n-t keypath="tasks.import.creatingIn" tag="span" scope="global">
|
|
157
157
|
<template #container>
|
|
158
|
-
<span class="font-medium text-
|
|
158
|
+
<span class="font-medium text-default">{{ pinnedContainer!.title }}</span>
|
|
159
159
|
</template>
|
|
160
160
|
</i18n-t>
|
|
161
161
|
</p>
|
|
@@ -182,8 +182,8 @@ async function doSpawnEpic() {
|
|
|
182
182
|
</UFormField>
|
|
183
183
|
|
|
184
184
|
<!-- Secondary: spawn a parent/epic issue as a whole linked task group. -->
|
|
185
|
-
<div class="space-y-2 border-t border-
|
|
186
|
-
<span class="text-[11px] font-semibold uppercase tracking-wide text-
|
|
185
|
+
<div class="space-y-2 border-t border-default pt-3">
|
|
186
|
+
<span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
187
187
|
{{ t('tasks.import.asEpic') }}
|
|
188
188
|
</span>
|
|
189
189
|
<div class="flex items-end gap-2">
|
|
@@ -122,16 +122,16 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
122
122
|
</template>
|
|
123
123
|
<template #body>
|
|
124
124
|
<div v-if="descriptor" class="space-y-4">
|
|
125
|
-
<p class="text-sm text-
|
|
125
|
+
<p class="text-sm text-muted">
|
|
126
126
|
{{ t('tasks.connect.intro', { label: descriptor.label }) }}
|
|
127
127
|
</p>
|
|
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-[11px] text-
|
|
131
|
+
<p class="text-[11px] text-dimmed">
|
|
132
132
|
{{ t('tasks.connect.credentialless') }}
|
|
133
133
|
</p>
|
|
134
|
-
<p v-if="!available" class="text-[11px] text-
|
|
134
|
+
<p v-if="!available" class="text-[11px] 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-[11px] text-
|
|
152
|
+
<p class="text-center text-[11px] 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-[11px] text-
|
|
170
|
+
<p v-else class="text-[11px] text-dimmed">
|
|
171
171
|
{{
|
|
172
172
|
connection?.label
|
|
173
173
|
? t('tasks.connect.connectedTo', { label: connection.label })
|
|
@@ -178,11 +178,13 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
178
178
|
<!-- The per-workspace on/off toggle, available once the source is usable. -->
|
|
179
179
|
<div
|
|
180
180
|
v-if="available"
|
|
181
|
-
class="flex items-center justify-between gap-2 rounded-md border border-
|
|
181
|
+
class="flex items-center justify-between gap-2 rounded-md border border-default px-3 py-2"
|
|
182
182
|
>
|
|
183
183
|
<div class="text-sm">
|
|
184
|
-
<div class="font-medium text-
|
|
185
|
-
|
|
184
|
+
<div class="font-medium text-default">
|
|
185
|
+
{{ t('tasks.connect.offerToWorkspace') }}
|
|
186
|
+
</div>
|
|
187
|
+
<div class="text-[11px] text-dimmed">
|
|
186
188
|
{{ t('tasks.connect.offerHint', { label: descriptor.label }) }}
|
|
187
189
|
</div>
|
|
188
190
|
</div>
|