@cat-factory/app 0.266.0 → 0.266.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/app/components/judge/JudgeResultView.vue +11 -8
- package/app/components/panels/StepFragmentAdherence.vue +5 -5
- package/app/components/panels/StepMetadataCard.vue +27 -12
- package/app/components/panels/StepTestReport.vue +7 -4
- package/app/components/prReview/PrReviewWindow.vue +23 -14
- package/app/components/testing/TestReportWindow.vue +24 -16
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ import { agentKindMeta } from '~/utils/catalog'
|
|
|
12
12
|
import type { JudgeFinding, JudgeStepState } from '~/types/execution'
|
|
13
13
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
14
14
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
15
|
+
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
15
16
|
|
|
16
17
|
const board = useBoardStore()
|
|
17
18
|
const execution = useExecutionStore()
|
|
@@ -190,11 +191,14 @@ async function act(choice: 'proceed' | 'bounce' | 'stop') {
|
|
|
190
191
|
{{ judge.note }}
|
|
191
192
|
</p>
|
|
192
193
|
|
|
194
|
+
<!-- The verdict a human reads. Markdown, because the judge prompt asks for a verdict
|
|
195
|
+
line plus grouped bullets rather than one paragraph. -->
|
|
193
196
|
<div v-if="verdict?.summary" class="relative mt-3">
|
|
194
197
|
<CopyButton :text="verdict.summary" class="absolute end-1 top-1" />
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
<MarkdownProse
|
|
199
|
+
:text="verdict.summary"
|
|
200
|
+
class="pe-8 text-[13px] leading-relaxed text-slate-200"
|
|
201
|
+
/>
|
|
198
202
|
</div>
|
|
199
203
|
|
|
200
204
|
<section v-if="findings.length" class="mt-4">
|
|
@@ -220,12 +224,11 @@ async function act(choice: 'proceed' | 'bounce' | 'stop') {
|
|
|
220
224
|
finding.where
|
|
221
225
|
}}</code>
|
|
222
226
|
</div>
|
|
223
|
-
<
|
|
227
|
+
<MarkdownProse
|
|
224
228
|
v-if="finding.detail"
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
</p>
|
|
229
|
+
:text="finding.detail"
|
|
230
|
+
class="mt-1 text-[12px] leading-relaxed text-slate-400"
|
|
231
|
+
/>
|
|
229
232
|
</li>
|
|
230
233
|
</ul>
|
|
231
234
|
</section>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// reviewer reported at least one standard; when none were reachable the reviewer says so in its
|
|
7
7
|
// summary instead (so there is nothing to show here).
|
|
8
8
|
import type { FragmentAdherence } from '~/types/execution'
|
|
9
|
+
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
9
10
|
|
|
10
11
|
const props = defineProps<{ items: FragmentAdherence }>()
|
|
11
12
|
const { t } = useI18n()
|
|
@@ -63,12 +64,11 @@ function label(item: FragmentAdherence[number]): string {
|
|
|
63
64
|
{{ t('panels.stepDetail.adherence.outOfTen', { value: item.rating }) }}
|
|
64
65
|
</span>
|
|
65
66
|
</div>
|
|
66
|
-
<
|
|
67
|
+
<MarkdownProse
|
|
67
68
|
v-if="item.assessment"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
</p>
|
|
69
|
+
:text="item.assessment"
|
|
70
|
+
class="mt-1 text-[12px] leading-relaxed text-slate-300"
|
|
71
|
+
/>
|
|
72
72
|
<div v-if="item.relatedFindings.length" class="mt-1.5">
|
|
73
73
|
<p class="text-[10px] font-semibold uppercase tracking-wide text-slate-500">
|
|
74
74
|
{{ t('panels.stepDetail.adherence.relatedFindings') }}
|
|
@@ -4,6 +4,8 @@ import type { AgentState, PipelineStep, CompanionVerdict, StepApproval } from '~
|
|
|
4
4
|
import { subtaskIconClass } from '~/utils/pipelineRender'
|
|
5
5
|
import StepModelActivity from '~/components/observability/StepModelActivity.vue'
|
|
6
6
|
import StepContainerStatus from '~/components/panels/StepContainerStatus.vue'
|
|
7
|
+
import CopyButton from '~/components/common/CopyButton.vue'
|
|
8
|
+
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
7
9
|
|
|
8
10
|
// The step's metadata card body: state/timing/model/run id, the container cold-boot
|
|
9
11
|
// phase, the live subtask breakdown, the LLM observability rollup, the applied
|
|
@@ -281,22 +283,35 @@ async function copyRunId() {
|
|
|
281
283
|
{{ latestVerdict?.passed ? '≥' : '<' }} {{ pctOf(latestVerdict!.threshold) }}
|
|
282
284
|
</UBadge>
|
|
283
285
|
</div>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
<
|
|
286
|
+
<!-- One card per correction round: the score on its own line, then the reviewer's
|
|
287
|
+
challenge as rendered markdown. The feedback used to trail the score inside the same
|
|
288
|
+
line, which turned a multi-point review into one unreadable run of text. -->
|
|
289
|
+
<ol class="mt-2 space-y-2">
|
|
290
|
+
<li
|
|
291
|
+
v-for="(v, i) in companionVerdicts"
|
|
292
|
+
:key="i"
|
|
293
|
+
data-testid="companion-verdict"
|
|
294
|
+
class="relative rounded-lg border border-slate-800 bg-slate-900/60 px-3 py-2"
|
|
295
|
+
>
|
|
296
|
+
<CopyButton v-if="v.feedback" :text="v.feedback" class="absolute end-1 top-1" />
|
|
297
|
+
<div class="flex items-center gap-2 text-[12px]">
|
|
298
|
+
<span
|
|
299
|
+
class="inline-flex h-4 shrink-0 items-center rounded px-1 font-mono text-[11px] tabular-nums"
|
|
300
|
+
:class="
|
|
301
|
+
v.passed ? 'bg-emerald-500/15 text-emerald-300' : 'bg-amber-500/15 text-amber-300'
|
|
302
|
+
"
|
|
303
|
+
>
|
|
304
|
+
{{ i + 1 }}
|
|
305
|
+
</span>
|
|
295
306
|
<span :class="v.passed ? 'text-emerald-300' : 'text-amber-300'">
|
|
296
307
|
{{ pctOf(v.rating) }} {{ v.passed ? '≥' : '<' }} {{ pctOf(v.threshold) }}
|
|
297
308
|
</span>
|
|
298
|
-
<span v-if="v.feedback" class="ms-1 text-slate-400">— {{ v.feedback }}</span>
|
|
299
309
|
</div>
|
|
310
|
+
<MarkdownProse
|
|
311
|
+
v-if="v.feedback"
|
|
312
|
+
:text="v.feedback"
|
|
313
|
+
class="mt-1.5 pe-6 text-[12px] leading-relaxed text-slate-300"
|
|
314
|
+
/>
|
|
300
315
|
</li>
|
|
301
316
|
</ol>
|
|
302
317
|
<p v-if="companionVerdicts.length > 1" class="mt-1 text-[11px] text-slate-500">
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { RequirementVerdictStatus, TestReport } from '~/types/domain'
|
|
3
3
|
import type { TesterStepState } from '~/types/execution'
|
|
4
4
|
import { resolveVerdictMeta, type VerdictMeta } from './StepTestReport.logic'
|
|
5
|
+
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
5
6
|
|
|
6
7
|
// A tester step's latest structured report (what was tested, the per-area outcomes,
|
|
7
8
|
// the concerns it raised and the greenlight verdict) plus the fixer-loop phase.
|
|
@@ -57,9 +58,11 @@ function verdictMeta(status: RequirementVerdictStatus): VerdictMeta {
|
|
|
57
58
|
}}<span v-if="phase.phase === 'fixing'"> {{ t('panels.testReport.fixing') }}</span>
|
|
58
59
|
</span>
|
|
59
60
|
</div>
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
<MarkdownProse
|
|
62
|
+
v-if="report.summary"
|
|
63
|
+
:text="report.summary"
|
|
64
|
+
class="mb-3 text-[13px] leading-relaxed text-slate-300"
|
|
65
|
+
/>
|
|
63
66
|
|
|
64
67
|
<div v-if="report.tested.length" class="mb-3">
|
|
65
68
|
<div class="mb-1 text-[11px] text-slate-500">{{ t('panels.testReport.tested') }}</div>
|
|
@@ -123,7 +126,7 @@ function verdictMeta(status: RequirementVerdictStatus): VerdictMeta {
|
|
|
123
126
|
>
|
|
124
127
|
<span class="font-medium text-slate-200">{{ c.title }}</span>
|
|
125
128
|
</div>
|
|
126
|
-
<
|
|
129
|
+
<MarkdownProse v-if="c.detail" :text="c.detail" class="mt-1 text-slate-400" />
|
|
127
130
|
</div>
|
|
128
131
|
</div>
|
|
129
132
|
</section>
|
|
@@ -29,6 +29,7 @@ import { activeChunkLabels, chunkReviewPercent, hasNoSlicePlan } from '~/utils/p
|
|
|
29
29
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
30
30
|
import StepRunMeta from '~/components/panels/StepRunMeta.vue'
|
|
31
31
|
import StepFragmentAdherence from '~/components/panels/StepFragmentAdherence.vue'
|
|
32
|
+
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
32
33
|
|
|
33
34
|
const execution = useExecutionStore()
|
|
34
35
|
const board = useBoardStore()
|
|
@@ -527,13 +528,13 @@ async function onDismiss(id: string): Promise<void> {
|
|
|
527
528
|
|
|
528
529
|
<!-- The reviewer's overall assessment. Prose, so it takes the reading measure (see the
|
|
529
530
|
shell's `width` prop) — this window is `full`-width. -->
|
|
530
|
-
<
|
|
531
|
+
<div
|
|
531
532
|
v-if="state?.summary"
|
|
532
533
|
class="mb-3 max-w-3xl rounded-md bg-slate-800/50 px-3 py-2 text-[12px] text-slate-300"
|
|
533
534
|
>
|
|
534
|
-
<span class="text-slate-500">{{ t('prReview.summaryLabel') }}</span>
|
|
535
|
-
|
|
536
|
-
</
|
|
535
|
+
<span class="mb-1 block text-slate-500">{{ t('prReview.summaryLabel') }}</span>
|
|
536
|
+
<MarkdownProse :text="state.summary" />
|
|
537
|
+
</div>
|
|
537
538
|
|
|
538
539
|
<!-- Best-practice adherence: per standard folded into the reviewer's prompt, a 1..10
|
|
539
540
|
rating of how well the PR adheres + the issues that standard surfaced. -->
|
|
@@ -680,12 +681,17 @@ async function onDismiss(id: string): Promise<void> {
|
|
|
680
681
|
bucket to `full`, so these are the three paragraphs the width would
|
|
681
682
|
otherwise have stretched furthest; the path/line row, the badges and the
|
|
682
683
|
per-finding actions are what it is actually for. -->
|
|
683
|
-
<
|
|
684
|
-
|
|
684
|
+
<MarkdownProse
|
|
685
|
+
v-if="f.detail"
|
|
686
|
+
:text="f.detail"
|
|
687
|
+
class="mt-1 max-w-3xl text-[12px] text-slate-300"
|
|
685
688
|
:class="isRetracted(f) ? 'line-through' : ''"
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
+
/>
|
|
690
|
+
<!-- The suggested fix is a VALUE a human copies (a patch line, a command, a
|
|
691
|
+
path), not prose, so it stays preformatted: markdown would emphasise the
|
|
692
|
+
`__dunder__` in an identifier, curl the quotes in a command, and drop the
|
|
693
|
+
indentation of anything longer than a line. Same reason the CI gate's
|
|
694
|
+
failure summary is left alone. -->
|
|
689
695
|
<p
|
|
690
696
|
v-if="f.suggestedFix"
|
|
691
697
|
class="mt-1 max-w-3xl whitespace-pre-wrap rounded-md bg-slate-800/50 px-2 py-1 text-[11px] text-slate-300"
|
|
@@ -696,10 +702,10 @@ async function onDismiss(id: string): Promise<void> {
|
|
|
696
702
|
|
|
697
703
|
<!-- The investigator's justification (why the finding holds up / was retracted),
|
|
698
704
|
or the reason the challenge investigation failed. -->
|
|
699
|
-
<
|
|
705
|
+
<div
|
|
700
706
|
v-if="f.challenge?.justification"
|
|
701
707
|
data-testid="pr-review-finding-justification"
|
|
702
|
-
class="mt-1.5 max-w-3xl
|
|
708
|
+
class="mt-1.5 max-w-3xl rounded-md px-2 py-1 text-[11px]"
|
|
703
709
|
:class="
|
|
704
710
|
isRetracted(f)
|
|
705
711
|
? 'bg-rose-500/10 text-rose-200'
|
|
@@ -708,13 +714,16 @@ async function onDismiss(id: string): Promise<void> {
|
|
|
708
714
|
: 'bg-sky-500/10 text-sky-200'
|
|
709
715
|
"
|
|
710
716
|
>
|
|
711
|
-
|
|
717
|
+
<!-- A label that used to prefix its value inline now heads the block the
|
|
718
|
+
rendered prose became, so it needs to READ as a heading line rather than
|
|
719
|
+
as a stray word above a paragraph. -->
|
|
720
|
+
<span class="mb-1 block font-medium">{{
|
|
712
721
|
isChallengeFailed(f)
|
|
713
722
|
? t('prReview.challenge.failedLabel')
|
|
714
723
|
: t('prReview.challenge.verdictLabel')
|
|
715
724
|
}}</span>
|
|
716
|
-
|
|
717
|
-
</
|
|
725
|
+
<MarkdownProse :text="f.challenge.justification" />
|
|
726
|
+
</div>
|
|
718
727
|
|
|
719
728
|
<!-- Per-finding actions: Challenge + Dismiss (only while awaiting a selection). -->
|
|
720
729
|
<div
|
|
@@ -20,6 +20,7 @@ import StepContainerStatus from '~/components/panels/StepContainerStatus.vue'
|
|
|
20
20
|
import AttemptEntryHeader from '~/components/panels/AttemptEntryHeader.vue'
|
|
21
21
|
import EnvironmentStatusPanel from '~/components/environments/EnvironmentStatusPanel.vue'
|
|
22
22
|
import ProvisioningLogsDrawer from '~/components/provisioning/ProvisioningLogsDrawer.vue'
|
|
23
|
+
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
23
24
|
|
|
24
25
|
const board = useBoardStore()
|
|
25
26
|
const execution = useExecutionStore()
|
|
@@ -489,9 +490,11 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
489
490
|
:icon="a.outcome === 'completed' ? 'i-lucide-wrench' : 'i-lucide-circle-x'"
|
|
490
491
|
:icon-class="a.outcome === 'completed' ? 'text-amber-300' : 'text-rose-400'"
|
|
491
492
|
/>
|
|
492
|
-
<
|
|
493
|
-
|
|
494
|
-
|
|
493
|
+
<MarkdownProse
|
|
494
|
+
v-if="a.summary"
|
|
495
|
+
:text="a.summary"
|
|
496
|
+
class="mt-1 max-w-3xl text-[12px] leading-snug text-slate-400"
|
|
497
|
+
/>
|
|
495
498
|
<div v-if="a.concerns && a.concerns.length" class="mt-1.5">
|
|
496
499
|
<p class="text-[11px] text-slate-500">
|
|
497
500
|
{{ t('testing.fixerTimeline.addressed') }}
|
|
@@ -575,9 +578,11 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
575
578
|
d(new Date(vd.at), 'short')
|
|
576
579
|
}}</span>
|
|
577
580
|
</div>
|
|
578
|
-
<
|
|
579
|
-
|
|
580
|
-
|
|
581
|
+
<MarkdownProse
|
|
582
|
+
v-if="vd.feedback"
|
|
583
|
+
:text="vd.feedback"
|
|
584
|
+
class="mt-1 text-[12px] leading-snug text-slate-400"
|
|
585
|
+
/>
|
|
581
586
|
<div v-if="vd.gaps.length" class="mt-1.5">
|
|
582
587
|
<p class="text-[11px] text-slate-500">{{ t('testing.quality.gaps') }}</p>
|
|
583
588
|
<ul class="mt-1 space-y-0.5">
|
|
@@ -610,12 +615,11 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
610
615
|
<!-- Summary — the tester's own prose, so it takes the reading measure the shell's `full`
|
|
611
616
|
width obliges (see the `width` prop). The scenario rows and log tails below keep the
|
|
612
617
|
full span. -->
|
|
613
|
-
<
|
|
618
|
+
<MarkdownProse
|
|
614
619
|
v-if="report.summary"
|
|
620
|
+
:text="report.summary"
|
|
615
621
|
class="mb-4 max-w-3xl text-[13px] leading-relaxed text-slate-300"
|
|
616
|
-
|
|
617
|
-
{{ report.summary }}
|
|
618
|
-
</p>
|
|
622
|
+
/>
|
|
619
623
|
|
|
620
624
|
<h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
621
625
|
{{ t('testing.scenariosOutcomes') }}
|
|
@@ -680,9 +684,11 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
680
684
|
/>
|
|
681
685
|
<div class="min-w-0">
|
|
682
686
|
<span class="text-[13px] text-slate-200">{{ o.name }}</span>
|
|
683
|
-
<
|
|
684
|
-
|
|
685
|
-
|
|
687
|
+
<MarkdownProse
|
|
688
|
+
v-if="o.detail"
|
|
689
|
+
:text="o.detail"
|
|
690
|
+
class="max-w-3xl text-[12px] leading-snug text-slate-400"
|
|
691
|
+
/>
|
|
686
692
|
</div>
|
|
687
693
|
</div>
|
|
688
694
|
<p v-if="!g.outcomes.length" class="py-0.5 text-[12px] italic text-slate-500">
|
|
@@ -710,9 +716,11 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
710
716
|
{{ SEVERITY_LABELS[c.severity] }}
|
|
711
717
|
</span>
|
|
712
718
|
</div>
|
|
713
|
-
<
|
|
714
|
-
|
|
715
|
-
|
|
719
|
+
<MarkdownProse
|
|
720
|
+
v-if="c.detail"
|
|
721
|
+
:text="c.detail"
|
|
722
|
+
class="max-w-3xl text-[12px] leading-snug text-slate-400"
|
|
723
|
+
/>
|
|
716
724
|
</div>
|
|
717
725
|
</div>
|
|
718
726
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.266.
|
|
3
|
+
"version": "0.266.1",
|
|
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",
|