@cat-factory/app 0.309.0 → 0.310.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/app/components/assistant/AssistantModal.vue +5 -4
- package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
- package/app/components/auth/LoginScreen.vue +40 -26
- package/app/components/auth/ResetPasswordScreen.vue +9 -4
- package/app/components/auth/UserMenu.vue +4 -3
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +34 -23
- package/app/components/binaryOutput/StoredAssetView.vue +8 -6
- package/app/components/board/AddTaskModal.vue +16 -15
- package/app/components/board/AgentFailureCard.vue +12 -9
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +5 -4
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/ReviewFrictionDialog.vue +4 -3
- package/app/components/board/nodes/BlockNode.vue +17 -15
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/FrameSwimlanes.vue +4 -3
- package/app/components/board/nodes/TaskCard.vue +12 -7
- package/app/components/board/nodes/TaskPipelineMini.vue +9 -7
- package/app/components/bootstrap/AdoptionReviewModal.vue +30 -21
- package/app/components/bootstrap/BootstrapModal.vue +3 -3
- package/app/components/brainstorm/BrainstormWindow.vue +5 -3
- package/app/components/bugFishing/BugFishingWindow.vue +49 -27
- package/app/components/clarity/ClarityReviewWindow.vue +5 -3
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/context/ContextAttachmentFields.vue +23 -12
- package/app/components/documents/ContextDocumentPicker.vue +12 -9
- package/app/components/documents/DocumentImportModal.vue +4 -3
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSyncState.vue +3 -3
- package/app/components/documents/RepoContextDocPicker.vue +4 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +4 -3
- package/app/components/followUp/FollowUpWindow.vue +9 -6
- package/app/components/forkDecision/ForkDecisionWindow.vue +71 -80
- package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -2
- package/app/components/foundational/FoundationalServiceRegistry.vue +7 -6
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/fragments/FragmentLibraryManager.vue +5 -4
- package/app/components/fragments/FragmentSelector.vue +12 -9
- package/app/components/gates/GateFailingCheckList.vue +4 -3
- package/app/components/gates/GateResultView.vue +17 -12
- package/app/components/github/AddServiceFromRepoModal.vue +11 -7
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +9 -6
- package/app/components/github/RepoTreeBrowser.vue +15 -12
- package/app/components/humanTest/HumanTestWindow.vue +13 -9
- package/app/components/initiative/InitiativePlanReview.vue +28 -18
- package/app/components/initiative/InitiativeTrackerWindow.vue +171 -124
- package/app/components/judge/JudgeResultView.vue +5 -3
- package/app/components/kaizen/KaizenPanel.vue +67 -53
- package/app/components/layout/AccountTeamSettings.vue +9 -9
- package/app/components/layout/AppearanceSwitcher.vue +4 -3
- package/app/components/layout/BoardSwitcher.vue +10 -8
- package/app/components/layout/BoardToolbar.vue +5 -4
- package/app/components/layout/CommandBar.vue +4 -3
- package/app/components/layout/DefaultTestEnvBanner.vue +4 -3
- package/app/components/layout/IntegrationsHub.vue +8 -6
- package/app/components/layout/LanguageSwitcher.vue +4 -3
- package/app/components/layout/ModelProvidersHub.vue +4 -3
- package/app/components/layout/NotificationsInbox.vue +40 -30
- package/app/components/layout/PersonalSetupModal.vue +4 -3
- package/app/components/layout/RolePrompt.vue +4 -3
- package/app/components/layout/SideBar.vue +4 -3
- package/app/components/layout/TranslationWarningBanner.vue +4 -3
- package/app/components/layout/UiModeSwitcher.vue +8 -6
- package/app/components/layout/UiRoleSwitcher.vue +8 -6
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +69 -39
- package/app/components/media/ImageCompare.vue +69 -74
- package/app/components/observability/OutcomeFilterChips.vue +5 -4
- package/app/components/observability/RunFailureSummary.vue +8 -6
- package/app/components/observability/StepModelActivity.vue +5 -3
- package/app/components/observability/ToolCallList.vue +4 -2
- package/app/components/outcome/OutcomeSummaryWindow.vue +5 -4
- package/app/components/palettes/AgentPalette.vue +18 -14
- package/app/components/panels/AgentStepDetail.vue +30 -19
- package/app/components/panels/ObservabilityPanel.vue +149 -114
- package/app/components/panels/OperatorDashboardPanel.vue +99 -91
- package/app/components/panels/ReportsPanel.vue +64 -61
- package/app/components/panels/ResultWindowShell.vue +148 -134
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.vue +11 -9
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/inspector/EpicChildren.vue +4 -3
- package/app/components/panels/inspector/FrontendConfig.vue +3 -2
- package/app/components/panels/inspector/InspectorSection.vue +22 -17
- package/app/components/panels/inspector/ServiceConnections.vue +3 -2
- package/app/components/panels/inspector/ServiceTestConfig.vue +5 -4
- package/app/components/panels/inspector/TaskExecution.vue +5 -4
- package/app/components/panels/inspector/TaskRunSettings.vue +10 -6
- package/app/components/pipeline/EstimateThresholdFields.vue +13 -10
- package/app/components/pipeline/GateConfigFields.vue +14 -18
- package/app/components/pipeline/PipelineBuilder.vue +90 -77
- package/app/components/pipeline/PipelinePicker.vue +8 -6
- package/app/components/pipeline/PipelineProgress.vue +26 -21
- package/app/components/prReview/PrReviewWindow.vue +46 -25
- package/app/components/providers/ApiKeysSection.vue +4 -3
- package/app/components/ralph/RalphLoopResultView.vue +4 -3
- package/app/components/requirements/RequirementsReviewWindow.vue +10 -6
- package/app/components/riskPolicy/RiskPolicyPicker.vue +8 -6
- package/app/components/sandbox/SandboxPanel.vue +73 -54
- package/app/components/settings/CloudflareHandlerSection.vue +33 -30
- package/app/components/settings/ConsensusGroupsSection.vue +40 -30
- package/app/components/settings/InfraHandlersConfigurator.vue +16 -13
- package/app/components/settings/InfrastructureBackendPicker.vue +17 -17
- package/app/components/settings/IssueTrackerPanel.vue +21 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +3 -2
- package/app/components/settings/ModelConfigurationPanel.vue +9 -8
- package/app/components/settings/OpenRouterCatalogPanel.vue +4 -3
- package/app/components/settings/ProviderPreferenceEditor.vue +5 -6
- package/app/components/settings/RiskPolicyEditorRow.vue +3 -2
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +10 -8
- package/app/components/skills/ReviewSkillQueue.vue +4 -3
- package/app/components/skills/SkillLibraryManager.vue +7 -6
- package/app/components/slack/SlackPanel.vue +9 -5
- package/app/components/spec/ServiceSpecWindow.vue +4 -3
- package/app/components/tasks/ContextIssuePicker.vue +12 -9
- package/app/components/tasks/TaskContextIssues.vue +4 -3
- package/app/components/testing/TestReportWindow.vue +14 -8
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +62 -35
- package/i18n/locales/de.json +7 -3
- package/i18n/locales/en.json +7 -3
- package/i18n/locales/es.json +7 -3
- package/i18n/locales/fr.json +7 -3
- package/i18n/locales/he.json +7 -3
- package/i18n/locales/it.json +7 -3
- package/i18n/locales/ja.json +7 -3
- package/i18n/locales/pl.json +7 -3
- package/i18n/locales/tr.json +7 -3
- package/i18n/locales/uk.json +7 -3
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// request-changes rail has to live here or the gate has no resolving surface at all —
|
|
14
14
|
// which is exactly how an approved-only-over-REST plan gate shipped.
|
|
15
15
|
import { computed, reactive, ref } from 'vue'
|
|
16
|
+
import type { TableColumn } from '@nuxt/ui'
|
|
16
17
|
import type { InitiativeFollowUp, InitiativeItem } from '~/types/domain'
|
|
17
18
|
import { useInitiativePlanning } from '~/composables/useInitiativePlanning'
|
|
18
19
|
import {
|
|
@@ -87,6 +88,16 @@ function itemsOf(phaseId: string): InitiativeItem[] {
|
|
|
87
88
|
return (initiative.value?.items ?? []).filter((i) => i.phaseId === phaseId)
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
// One column set for every phase's table, so the header typography is the table theme's rather
|
|
92
|
+
// than a per-file recipe.
|
|
93
|
+
const phaseItems = computed(() => phases.value.map((p) => ({ label: p.title, value: p.id })))
|
|
94
|
+
|
|
95
|
+
const itemColumns = computed<TableColumn<InitiativeItem>[]>(() => [
|
|
96
|
+
{ id: 'item', header: t('initiative.tracker.colItem') },
|
|
97
|
+
{ id: 'status', header: t('initiative.tracker.colStatus') },
|
|
98
|
+
{ id: 'pr', header: t('initiative.tracker.colPr') },
|
|
99
|
+
])
|
|
100
|
+
|
|
90
101
|
const progress = computed(() => initiativeProgress(initiative.value?.items))
|
|
91
102
|
const progressPct = computed(() =>
|
|
92
103
|
progress.value && progress.value.total > 0
|
|
@@ -393,22 +404,26 @@ const { requestClose } = useUnsavedGuard({
|
|
|
393
404
|
{{ t('initiative.checkpoint.pausedBody', { phase: checkpointPhase!.title }) }}
|
|
394
405
|
</p>
|
|
395
406
|
<div class="mt-2.5 flex flex-wrap gap-2">
|
|
396
|
-
<
|
|
407
|
+
<UButton
|
|
408
|
+
color="neutral"
|
|
409
|
+
variant="ghost"
|
|
397
410
|
class="rounded-sm bg-primary/90 px-2.5 py-1 text-2xs font-medium text-inverted hover:bg-primary disabled:opacity-50"
|
|
398
411
|
:disabled="initiatives.controlling"
|
|
399
412
|
data-testid="initiative-checkpoint-resume"
|
|
400
413
|
@click="checkpointControl('resume')"
|
|
401
414
|
>
|
|
402
415
|
{{ t('initiative.inspector.resume') }}
|
|
403
|
-
</
|
|
404
|
-
<
|
|
416
|
+
</UButton>
|
|
417
|
+
<UButton
|
|
418
|
+
color="neutral"
|
|
419
|
+
variant="ghost"
|
|
405
420
|
class="rounded-sm border border-app-error-500/50 px-2.5 py-1 text-2xs font-medium text-app-error-300 hover:bg-app-error-500/10 disabled:opacity-50"
|
|
406
421
|
:disabled="initiatives.controlling"
|
|
407
422
|
data-testid="initiative-checkpoint-cancel"
|
|
408
423
|
@click="checkpointControl('cancel')"
|
|
409
424
|
>
|
|
410
425
|
{{ t('initiative.inspector.cancel') }}
|
|
411
|
-
</
|
|
426
|
+
</UButton>
|
|
412
427
|
</div>
|
|
413
428
|
</div>
|
|
414
429
|
</div>
|
|
@@ -490,84 +505,91 @@ const { requestClose } = useUnsavedGuard({
|
|
|
490
505
|
</UBadge>
|
|
491
506
|
</h3>
|
|
492
507
|
<p v-if="phase.goal" class="mb-2 text-xs text-muted">{{ phase.goal }}</p>
|
|
493
|
-
<
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
508
|
+
<UTable
|
|
509
|
+
:data="itemsOf(phase.id)"
|
|
510
|
+
:columns="itemColumns"
|
|
511
|
+
:ui="{
|
|
512
|
+
root: 'overflow-x-auto rounded-lg border border-default',
|
|
513
|
+
base: 'text-xs',
|
|
514
|
+
th: 'px-3 py-2',
|
|
515
|
+
td: 'px-3 py-2 text-xs whitespace-normal',
|
|
516
|
+
empty: 'py-0',
|
|
517
|
+
tr: 'align-top',
|
|
518
|
+
}"
|
|
519
|
+
>
|
|
520
|
+
<template #item-cell="{ row }">
|
|
521
|
+
<div class="font-medium text-default">{{ row.original.title }}</div>
|
|
522
|
+
<div v-if="row.original.dependsOn?.length" class="mt-0.5 text-3xs text-dimmed">
|
|
523
|
+
{{
|
|
524
|
+
t('initiative.tracker.dependsOn', {
|
|
525
|
+
items: row.original.dependsOn.join(', '),
|
|
526
|
+
})
|
|
527
|
+
}}
|
|
528
|
+
</div>
|
|
529
|
+
<div
|
|
530
|
+
v-if="row.original.note"
|
|
531
|
+
class="mt-0.5 max-w-3xl text-3xs text-app-warning-300/80"
|
|
532
|
+
>
|
|
533
|
+
{{ row.original.note }}
|
|
534
|
+
</div>
|
|
535
|
+
<div
|
|
536
|
+
v-if="
|
|
537
|
+
editable &&
|
|
538
|
+
(row.original.status === 'blocked' || row.original.status === 'pending')
|
|
539
|
+
"
|
|
540
|
+
class="mt-1 flex gap-1.5"
|
|
541
|
+
>
|
|
542
|
+
<UButton
|
|
543
|
+
v-if="row.original.status === 'blocked'"
|
|
544
|
+
color="neutral"
|
|
545
|
+
variant="outline"
|
|
546
|
+
size="xs"
|
|
547
|
+
:label="t('initiative.curation.retry')"
|
|
548
|
+
:disabled="initiatives.curating"
|
|
549
|
+
:data-testid="`initiative-item-retry-${row.original.id}`"
|
|
550
|
+
@click="itemAction(row.original, 'retry')"
|
|
551
|
+
/>
|
|
552
|
+
<UButton
|
|
553
|
+
color="neutral"
|
|
554
|
+
variant="outline"
|
|
555
|
+
size="xs"
|
|
556
|
+
:label="t('initiative.curation.skip')"
|
|
557
|
+
:disabled="initiatives.curating"
|
|
558
|
+
:data-testid="`initiative-item-skip-${row.original.id}`"
|
|
559
|
+
@click="itemAction(row.original, 'skip')"
|
|
560
|
+
/>
|
|
561
|
+
</div>
|
|
562
|
+
</template>
|
|
563
|
+
<template #status-cell="{ row }">
|
|
564
|
+
<UBadge
|
|
565
|
+
:color="INITIATIVE_ITEM_STATUS_CHIPS[row.original.status]"
|
|
566
|
+
variant="subtle"
|
|
567
|
+
size="sm"
|
|
568
|
+
>
|
|
569
|
+
{{ t(INITIATIVE_ITEM_STATUS_LABEL_KEYS[row.original.status]) }}
|
|
570
|
+
</UBadge>
|
|
571
|
+
</template>
|
|
572
|
+
<template #pr-cell="{ row }">
|
|
573
|
+
<ULink
|
|
574
|
+
raw
|
|
575
|
+
v-if="row.original.pr"
|
|
576
|
+
:to="row.original.pr.url"
|
|
577
|
+
target="_blank"
|
|
578
|
+
rel="noopener"
|
|
579
|
+
class="text-app-info-400 hover:underline"
|
|
580
|
+
>
|
|
581
|
+
{{
|
|
582
|
+
row.original.pr.number
|
|
583
|
+
? `#${row.original.pr.number}`
|
|
584
|
+
: t('initiative.tracker.prLink')
|
|
585
|
+
}}
|
|
586
|
+
</ULink>
|
|
587
|
+
<span v-else class="text-app-600">—</span>
|
|
588
|
+
</template>
|
|
589
|
+
<!-- The hand-built table rendered its header and no row; Nuxt UI's fallback is
|
|
590
|
+
an untranslated "No data.", so the slot states the same nothing. -->
|
|
591
|
+
<template #empty />
|
|
592
|
+
</UTable>
|
|
571
593
|
</section>
|
|
572
594
|
|
|
573
595
|
<!-- Execution policy -->
|
|
@@ -576,14 +598,16 @@ const { requestClose } = useUnsavedGuard({
|
|
|
576
598
|
<SectionLabel as="h3">
|
|
577
599
|
{{ t('initiative.tracker.policy') }}
|
|
578
600
|
</SectionLabel>
|
|
579
|
-
<
|
|
601
|
+
<UButton
|
|
602
|
+
color="neutral"
|
|
603
|
+
variant="ghost"
|
|
580
604
|
v-if="editable && !editingPolicy"
|
|
581
605
|
class="rounded-sm border border-muted px-1.5 py-0.5 text-3xs text-toned hover:bg-elevated"
|
|
582
606
|
data-testid="initiative-policy-edit"
|
|
583
607
|
@click="startEditPolicy"
|
|
584
608
|
>
|
|
585
609
|
{{ t('initiative.curation.edit') }}
|
|
586
|
-
</
|
|
610
|
+
</UButton>
|
|
587
611
|
</div>
|
|
588
612
|
<ul v-if="!editingPolicy" class="text-xs text-toned">
|
|
589
613
|
<li>
|
|
@@ -604,41 +628,56 @@ const { requestClose } = useUnsavedGuard({
|
|
|
604
628
|
</ul>
|
|
605
629
|
<!-- Edit form: the two scalar knobs; planner-authored rules are preserved. -->
|
|
606
630
|
<div v-else class="flex flex-col gap-2 rounded-lg border border-default p-3">
|
|
607
|
-
<
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
631
|
+
<UFormField
|
|
632
|
+
size="xs"
|
|
633
|
+
:label="t('initiative.curation.maxConcurrentField')"
|
|
634
|
+
:ui="{ root: 'flex items-center gap-2', label: 'w-40', container: 'mt-0' }"
|
|
635
|
+
>
|
|
636
|
+
<UInputNumber
|
|
637
|
+
v-model.optional="policyForm.maxConcurrent"
|
|
638
|
+
:min="1"
|
|
639
|
+
:max="20"
|
|
640
|
+
size="xs"
|
|
641
|
+
class="w-28"
|
|
615
642
|
data-testid="initiative-policy-max-concurrent"
|
|
616
643
|
/>
|
|
617
|
-
</
|
|
618
|
-
<
|
|
619
|
-
|
|
620
|
-
|
|
644
|
+
</UFormField>
|
|
645
|
+
<UFormField
|
|
646
|
+
size="xs"
|
|
647
|
+
:label="t('initiative.curation.defaultPipelineField')"
|
|
648
|
+
:ui="{
|
|
649
|
+
root: 'flex items-center gap-2',
|
|
650
|
+
label: 'w-40',
|
|
651
|
+
container: 'flex-1 mt-0',
|
|
652
|
+
}"
|
|
653
|
+
>
|
|
654
|
+
<UInput
|
|
621
655
|
v-model="policyForm.defaultPipelineId"
|
|
622
|
-
|
|
623
|
-
class="
|
|
656
|
+
size="xs"
|
|
657
|
+
class="w-full"
|
|
658
|
+
:ui="{ base: 'font-mono' }"
|
|
624
659
|
data-testid="initiative-policy-default-pipeline"
|
|
625
660
|
/>
|
|
626
|
-
</
|
|
661
|
+
</UFormField>
|
|
627
662
|
<div class="flex gap-2">
|
|
628
|
-
<
|
|
663
|
+
<UButton
|
|
664
|
+
color="neutral"
|
|
665
|
+
variant="ghost"
|
|
629
666
|
class="rounded-sm bg-primary/90 px-2 py-1 text-2xs text-inverted hover:bg-primary disabled:opacity-50"
|
|
630
667
|
:disabled="initiatives.curating"
|
|
631
668
|
data-testid="initiative-policy-save"
|
|
632
669
|
@click="savePolicy"
|
|
633
670
|
>
|
|
634
671
|
{{ t('initiative.curation.save') }}
|
|
635
|
-
</
|
|
636
|
-
<
|
|
672
|
+
</UButton>
|
|
673
|
+
<UButton
|
|
674
|
+
color="neutral"
|
|
675
|
+
variant="ghost"
|
|
637
676
|
class="rounded-sm border border-muted px-2 py-1 text-2xs text-toned hover:bg-elevated"
|
|
638
677
|
@click="editingPolicy = false"
|
|
639
678
|
>
|
|
640
679
|
{{ t('initiative.curation.cancel') }}
|
|
641
|
-
</
|
|
680
|
+
</UButton>
|
|
642
681
|
</div>
|
|
643
682
|
</div>
|
|
644
683
|
</section>
|
|
@@ -694,58 +733,66 @@ const { requestClose } = useUnsavedGuard({
|
|
|
694
733
|
<!-- Triage actions for an open follow-up (only while executing) -->
|
|
695
734
|
<div v-if="editable && f.status === 'open'" class="mt-2">
|
|
696
735
|
<div v-if="promotingId === f.id" class="flex flex-col gap-2">
|
|
697
|
-
<
|
|
698
|
-
|
|
699
|
-
|
|
736
|
+
<UFormField
|
|
737
|
+
size="xs"
|
|
738
|
+
:label="t('initiative.curation.phaseField')"
|
|
739
|
+
:ui="{ root: 'flex items-center gap-2', container: 'flex-1 mt-0' }"
|
|
740
|
+
>
|
|
741
|
+
<USelect
|
|
700
742
|
v-model="promoteForm.phaseId"
|
|
701
|
-
|
|
743
|
+
:items="phaseItems"
|
|
744
|
+
size="xs"
|
|
745
|
+
class="w-full"
|
|
702
746
|
data-testid="initiative-promote-phase"
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
</option>
|
|
707
|
-
</select>
|
|
708
|
-
</label>
|
|
709
|
-
<input
|
|
747
|
+
/>
|
|
748
|
+
</UFormField>
|
|
749
|
+
<UInput
|
|
710
750
|
v-model="promoteForm.title"
|
|
711
|
-
|
|
712
|
-
class="rounded-sm border border-muted bg-app-950 px-2 py-1 text-xs text-default"
|
|
751
|
+
size="xs"
|
|
713
752
|
:placeholder="t('initiative.curation.itemTitlePlaceholder')"
|
|
714
753
|
data-testid="initiative-promote-title"
|
|
715
754
|
/>
|
|
716
755
|
<div class="flex gap-2">
|
|
717
|
-
<
|
|
756
|
+
<UButton
|
|
757
|
+
color="neutral"
|
|
758
|
+
variant="ghost"
|
|
718
759
|
class="rounded-sm bg-primary/90 px-2 py-1 text-2xs text-inverted hover:bg-primary disabled:opacity-50"
|
|
719
760
|
:disabled="initiatives.curating || !promoteForm.phaseId"
|
|
720
761
|
data-testid="initiative-promote-submit"
|
|
721
762
|
@click="submitPromote(f)"
|
|
722
763
|
>
|
|
723
764
|
{{ t('initiative.curation.promoteConfirm') }}
|
|
724
|
-
</
|
|
725
|
-
<
|
|
765
|
+
</UButton>
|
|
766
|
+
<UButton
|
|
767
|
+
color="neutral"
|
|
768
|
+
variant="ghost"
|
|
726
769
|
class="rounded-sm border border-muted px-2 py-1 text-2xs text-toned hover:bg-elevated"
|
|
727
770
|
@click="promotingId = null"
|
|
728
771
|
>
|
|
729
772
|
{{ t('initiative.curation.cancel') }}
|
|
730
|
-
</
|
|
773
|
+
</UButton>
|
|
731
774
|
</div>
|
|
732
775
|
</div>
|
|
733
776
|
<div v-else class="flex gap-1.5">
|
|
734
|
-
<
|
|
777
|
+
<UButton
|
|
778
|
+
color="neutral"
|
|
779
|
+
variant="ghost"
|
|
735
780
|
class="rounded-sm border border-muted px-1.5 py-0.5 text-3xs text-toned hover:bg-elevated"
|
|
736
781
|
data-testid="initiative-followup-promote"
|
|
737
782
|
@click="startPromote(f)"
|
|
738
783
|
>
|
|
739
784
|
{{ t('initiative.curation.promote') }}
|
|
740
|
-
</
|
|
741
|
-
<
|
|
785
|
+
</UButton>
|
|
786
|
+
<UButton
|
|
787
|
+
color="neutral"
|
|
788
|
+
variant="ghost"
|
|
742
789
|
class="rounded-sm border border-muted px-1.5 py-0.5 text-3xs text-toned hover:bg-elevated disabled:opacity-50"
|
|
743
790
|
:disabled="initiatives.curating"
|
|
744
791
|
data-testid="initiative-followup-dismiss"
|
|
745
792
|
@click="dismissFollowUp(f)"
|
|
746
793
|
>
|
|
747
794
|
{{ t('initiative.curation.dismiss') }}
|
|
748
|
-
</
|
|
795
|
+
</UButton>
|
|
749
796
|
</div>
|
|
750
797
|
</div>
|
|
751
798
|
</li>
|
|
@@ -253,12 +253,14 @@ async function act(choice: 'proceed' | 'bounce' | 'stop') {
|
|
|
253
253
|
<p class="mb-2 text-2xs leading-relaxed text-dimmed">
|
|
254
254
|
{{ t('judge.decisionDescription') }}
|
|
255
255
|
</p>
|
|
256
|
-
<
|
|
256
|
+
<UTextarea
|
|
257
257
|
v-model="feedback"
|
|
258
|
-
rows="3"
|
|
258
|
+
:rows="3"
|
|
259
259
|
:disabled="busy"
|
|
260
260
|
:placeholder="t('judge.feedbackPlaceholder')"
|
|
261
|
-
|
|
261
|
+
size="sm"
|
|
262
|
+
class="w-full"
|
|
263
|
+
:ui="{ base: 'resize-y' }"
|
|
262
264
|
/>
|
|
263
265
|
<p v-if="judgeStore.error" class="mt-2 text-xs text-app-error-300">
|
|
264
266
|
{{ judgeStore.error }}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, watch } from 'vue'
|
|
3
3
|
import { onKeyStroke } from '@vueuse/core'
|
|
4
|
+
import type { TableColumn } from '@nuxt/ui'
|
|
4
5
|
import type { KaizenGrading } from '~/types/domain'
|
|
5
6
|
import { agentKindMeta } from '~/utils/catalog'
|
|
6
7
|
|
|
@@ -48,6 +49,16 @@ function statusLabel(g: KaizenGrading): string {
|
|
|
48
49
|
if (g.status === 'failed') return t('kaizen.status.failed')
|
|
49
50
|
return g.grade != null ? t('kaizen.gradeValue', { grade: g.grade }) : t('kaizen.status.graded')
|
|
50
51
|
}
|
|
52
|
+
|
|
53
|
+
// Column definitions rather than hand-written `<th>`s, so the header typography comes from the
|
|
54
|
+
// table theme and is the same one every other table in the SPA renders.
|
|
55
|
+
const historyColumns = computed<TableColumn<KaizenGrading>[]>(() => [
|
|
56
|
+
{ id: 'when', header: t('kaizen.history.col.when') },
|
|
57
|
+
{ id: 'agent', header: t('kaizen.history.col.agent') },
|
|
58
|
+
{ id: 'model', header: t('kaizen.history.col.model') },
|
|
59
|
+
{ id: 'grade', header: t('kaizen.history.col.grade') },
|
|
60
|
+
{ id: 'recommendations', header: t('kaizen.history.col.recommendations') },
|
|
61
|
+
])
|
|
51
62
|
</script>
|
|
52
63
|
|
|
53
64
|
<template>
|
|
@@ -155,59 +166,62 @@ function statusLabel(g: KaizenGrading): string {
|
|
|
155
166
|
<UIcon name="i-lucide-history" class="h-4 w-4 text-app-hue-teal" />
|
|
156
167
|
{{ t('kaizen.history.title') }}
|
|
157
168
|
</h2>
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
</
|
|
208
|
-
</
|
|
209
|
-
</
|
|
210
|
-
|
|
169
|
+
<UTable
|
|
170
|
+
:data="kaizen.history"
|
|
171
|
+
:columns="historyColumns"
|
|
172
|
+
:ui="{
|
|
173
|
+
root: 'overflow-hidden rounded-lg border border-default',
|
|
174
|
+
base: 'text-xs',
|
|
175
|
+
th: 'px-3 py-2',
|
|
176
|
+
td: 'px-3 py-2 text-xs whitespace-normal',
|
|
177
|
+
tr: 'align-top',
|
|
178
|
+
}"
|
|
179
|
+
>
|
|
180
|
+
<template #when-cell="{ row }">
|
|
181
|
+
<span class="whitespace-nowrap text-dimmed">{{
|
|
182
|
+
when(row.original.createdAt)
|
|
183
|
+
}}</span>
|
|
184
|
+
</template>
|
|
185
|
+
<template #agent-cell="{ row }">
|
|
186
|
+
<span class="flex items-center gap-1.5">
|
|
187
|
+
<UIcon
|
|
188
|
+
:name="meta(row.original.agentKind).icon"
|
|
189
|
+
class="h-3.5 w-3.5"
|
|
190
|
+
:style="{ color: meta(row.original.agentKind).color }"
|
|
191
|
+
/>
|
|
192
|
+
<span class="text-default">{{ meta(row.original.agentKind).label }}</span>
|
|
193
|
+
<span class="text-app-600">{{
|
|
194
|
+
t('kaizen.promptVersion', { version: row.original.promptVersion })
|
|
195
|
+
}}</span>
|
|
196
|
+
</span>
|
|
197
|
+
</template>
|
|
198
|
+
<template #model-cell="{ row }">
|
|
199
|
+
<span class="block max-w-[12rem] truncate text-muted" :title="row.original.model">
|
|
200
|
+
{{ row.original.model }}
|
|
201
|
+
</span>
|
|
202
|
+
</template>
|
|
203
|
+
<template #grade-cell="{ row }">
|
|
204
|
+
<span class="whitespace-nowrap font-semibold" :class="gradeTone(row.original)">
|
|
205
|
+
{{ statusLabel(row.original) }}
|
|
206
|
+
</span>
|
|
207
|
+
</template>
|
|
208
|
+
<template #recommendations-cell="{ row }">
|
|
209
|
+
<div class="text-muted">
|
|
210
|
+
<ul v-if="row.original.recommendations.length" class="list-disc space-y-0.5 ps-4">
|
|
211
|
+
<li v-for="(r, i) in row.original.recommendations" :key="i">{{ r }}</li>
|
|
212
|
+
</ul>
|
|
213
|
+
<span v-else-if="row.original.status === 'complete'" class="text-app-600">
|
|
214
|
+
—
|
|
215
|
+
</span>
|
|
216
|
+
<span v-else-if="row.original.error" class="text-app-error-400/80">
|
|
217
|
+
{{ row.original.error }}
|
|
218
|
+
</span>
|
|
219
|
+
</div>
|
|
220
|
+
</template>
|
|
221
|
+
<template #empty>
|
|
222
|
+
<span class="text-app-600">{{ t('kaizen.history.empty') }}</span>
|
|
223
|
+
</template>
|
|
224
|
+
</UTable>
|
|
211
225
|
</section>
|
|
212
226
|
</div>
|
|
213
227
|
</div>
|