@cat-factory/app 0.265.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.
@@ -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
- <p class="whitespace-pre-wrap pe-8 text-[13px] leading-relaxed text-slate-200">
196
- {{ verdict.summary }}
197
- </p>
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
- <p
227
+ <MarkdownProse
224
228
  v-if="finding.detail"
225
- class="mt-1 whitespace-pre-wrap text-[12px] leading-relaxed text-slate-400"
226
- >
227
- {{ finding.detail }}
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
- <p
67
+ <MarkdownProse
67
68
  v-if="item.assessment"
68
- class="mt-1 whitespace-pre-wrap text-[12px] leading-relaxed text-slate-300"
69
- >
70
- {{ item.assessment }}
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
- <ol class="mt-2 space-y-1.5">
285
- <li v-for="(v, i) in companionVerdicts" :key="i" class="flex items-start gap-2 text-[12px]">
286
- <span
287
- class="mt-px inline-flex h-4 shrink-0 items-center rounded px-1 font-mono text-[11px] tabular-nums"
288
- :class="
289
- v.passed ? 'bg-emerald-500/15 text-emerald-300' : 'bg-amber-500/15 text-amber-300'
290
- "
291
- >
292
- {{ i + 1 }}
293
- </span>
294
- <div class="min-w-0">
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
- <p v-if="report.summary" class="mb-3 text-[13px] leading-relaxed text-slate-300">
61
- {{ report.summary }}
62
- </p>
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
- <p v-if="c.detail" class="mt-1 text-slate-400">{{ c.detail }}</p>
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
- <p
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
- {{ state.summary }}
536
- </p>
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
- <p
684
- class="mt-1 max-w-3xl whitespace-pre-wrap text-[12px] text-slate-300"
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
- {{ f.detail }}
688
- </p>
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
- <p
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 whitespace-pre-wrap rounded-md px-2 py-1 text-[11px]"
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
- <span class="font-medium">{{
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
- {{ f.challenge.justification }}
717
- </p>
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
@@ -84,6 +84,10 @@ interface Draft {
84
84
  maxRequirementIterations: number
85
85
  maxRequirementConcernAllowed: RequirementConcernLevel
86
86
  autoMergeEnabled: boolean
87
+ // Whether a run under this policy answers the parks its own automatic loops raise when they give
88
+ // up, rather than stopping for a person. Edited as a switch because the vocabulary is two-valued
89
+ // and the OFF state is the historical behaviour.
90
+ unattended: boolean
87
91
  // Per-change-class auto-merge rules. An OMITTED class means "use the score ceilings above",
88
92
  // so `{}` is the identity — the editor stores `thresholds` as an omission for that reason.
89
93
  classRules: MergeClassRules
@@ -131,6 +135,7 @@ function toDraft(p: RiskPolicy): Draft {
131
135
  maxRequirementIterations: p.maxRequirementIterations,
132
136
  maxRequirementConcernAllowed: p.maxRequirementConcernAllowed,
133
137
  autoMergeEnabled: p.autoMergeEnabled,
138
+ unattended: p.autonomy === 'unattended',
134
139
  classRules: { ...p.classRules },
135
140
  classRulesByRole: { ...p.classRulesByRole },
136
141
  dryRunRoles: [...p.dryRunRoles],
@@ -152,8 +157,30 @@ watch(
152
157
  { immediate: true, deep: false },
153
158
  )
154
159
 
160
+ /**
161
+ * Which single control is mid-request, keyed `<policyId>[:<action>]`.
162
+ *
163
+ * Per ACTION and not merely per policy, because a row now carries two independent promote
164
+ * buttons: keyed by policy alone, promoting the in-app default spun the unattended button too and
165
+ * told the operator a change they had not asked for was in flight.
166
+ */
155
167
  const busy = ref<string | null>(null)
156
168
 
169
+ /**
170
+ * Why the delete button is disabled, naming the flag that actually blocks it.
171
+ *
172
+ * The two are promoted by DIFFERENT buttons, so collapsing them into one "promote another preset
173
+ * first" message sends an operator to re-point the in-app default and come back to a delete that
174
+ * is still refused, with nothing on screen saying why.
175
+ */
176
+ function deleteBlockedReason(p: RiskPolicy): string {
177
+ if (p.isDefault && p.isUnattendedDefault)
178
+ return t('settings.riskPolicy.deleteBothDefaultsBlocked')
179
+ if (p.isDefault) return t('settings.riskPolicy.deleteDefaultBlocked')
180
+ if (p.isUnattendedDefault) return t('settings.riskPolicy.deleteUnattendedDefaultBlocked')
181
+ return t('settings.riskPolicy.deletePreset')
182
+ }
183
+
157
184
  async function save(p: RiskPolicy) {
158
185
  const d = drafts[p.id]
159
186
  if (!d) return
@@ -168,6 +195,7 @@ async function save(p: RiskPolicy) {
168
195
  maxRequirementIterations: d.maxRequirementIterations,
169
196
  maxRequirementConcernAllowed: d.maxRequirementConcernAllowed,
170
197
  autoMergeEnabled: d.autoMergeEnabled,
198
+ autonomy: d.unattended ? 'unattended' : 'attended',
171
199
  classRules: d.classRules,
172
200
  classRulesByRole: d.classRulesByRole,
173
201
  dryRunRoles: d.dryRunRoles,
@@ -187,7 +215,7 @@ async function save(p: RiskPolicy) {
187
215
  }
188
216
 
189
217
  async function makeDefault(p: RiskPolicy) {
190
- busy.value = p.id
218
+ busy.value = `${p.id}:default`
191
219
  try {
192
220
  await store.update(p.id, { isDefault: true })
193
221
  } catch (e) {
@@ -197,6 +225,25 @@ async function makeDefault(p: RiskPolicy) {
197
225
  }
198
226
  }
199
227
 
228
+ /**
229
+ * Promote this policy to the UNATTENDED default: the one a task that pins none resolves when
230
+ * nothing is watching the run (a start over the public API, a tracker dispatch, a schedule fire).
231
+ *
232
+ * Its own action rather than a second meaning for the button above, because the two defaults are
233
+ * independent: a board can run one posture in the app and another for the work it never sees, and
234
+ * flagging one policy both ways is a deliberate choice rather than the only option.
235
+ */
236
+ async function makeUnattendedDefault(p: RiskPolicy) {
237
+ busy.value = `${p.id}:unattended`
238
+ try {
239
+ await store.update(p.id, { isUnattendedDefault: true })
240
+ } catch (e) {
241
+ present(e, 'settings.riskPolicy.toast.defaultFailed')
242
+ } finally {
243
+ busy.value = null
244
+ }
245
+ }
246
+
200
247
  async function remove(p: RiskPolicy) {
201
248
  const ok = await confirm({
202
249
  title: t('settings.riskPolicy.confirmDelete.title'),
@@ -227,6 +274,9 @@ const draft = reactive<Draft>({
227
274
  maxRequirementIterations: 6,
228
275
  maxRequirementConcernAllowed: 'none',
229
276
  autoMergeEnabled: true,
277
+ // A new policy parks on its own caps, matching every built-in but the unattended default: a
278
+ // licence to answer them is a posture somebody grants, never one a blank form assumes.
279
+ unattended: false,
230
280
  // The create row authors the numbers only. Class and role rules start at their identity and
231
281
  // are edited on the saved preset, where each rule can be shown beside the base rule (and the
232
282
  // track record) it narrows — neither reads as anything on a policy that does not exist yet.
@@ -254,11 +304,13 @@ async function create() {
254
304
  maxRequirementIterations: draft.maxRequirementIterations,
255
305
  maxRequirementConcernAllowed: draft.maxRequirementConcernAllowed,
256
306
  autoMergeEnabled: draft.autoMergeEnabled,
307
+ autonomy: draft.unattended ? 'unattended' : 'attended',
257
308
  classRules: draft.classRules,
258
309
  forkDecision: forkGating(draft),
259
310
  })
260
311
  draft.name = ''
261
312
  draft.autoMergeEnabled = true
313
+ draft.unattended = false
262
314
  draft.classRules = {}
263
315
  toast.add({
264
316
  title: t('settings.riskPolicy.toast.created'),
@@ -300,6 +352,30 @@ async function create() {
300
352
  class="flex-1"
301
353
  :placeholder="t('settings.riskPolicy.presetNamePlaceholder')"
302
354
  />
355
+ <UBadge v-if="p.isUnattendedDefault" color="info" variant="subtle" size="sm">
356
+ {{ t('settings.riskPolicy.unattendedDefault') }}
357
+ </UBadge>
358
+ <!--
359
+ Visibly labelled, like its `makeDefault` sibling below. `title` is a tooltip, NOT an
360
+ accessible name: icon-only, this was announced as an unlabelled button, and a sighted
361
+ user had to hover a bare glyph to discover it re-points which policy governs every
362
+ unwatched run. The short text is the accessible name (so it is not one of those buttons
363
+ whose spoken name and printed label disagree) and the longer `title` still explains
364
+ which runs those are. `busy` is compared to a per-BUTTON key so promoting one default
365
+ does not spin the other's button too.
366
+ -->
367
+ <UButton
368
+ v-else
369
+ color="neutral"
370
+ variant="ghost"
371
+ size="xs"
372
+ icon="i-lucide-bot"
373
+ :loading="busy === `${p.id}:unattended`"
374
+ :title="t('settings.riskPolicy.makeUnattendedDefault')"
375
+ @click="makeUnattendedDefault(p)"
376
+ >
377
+ {{ t('settings.riskPolicy.makeUnattendedDefaultShort') }}
378
+ </UButton>
303
379
  <UBadge v-if="p.isDefault" color="primary" variant="subtle" size="sm">
304
380
  {{ t('settings.riskPolicy.default') }}
305
381
  </UBadge>
@@ -309,7 +385,7 @@ async function create() {
309
385
  variant="ghost"
310
386
  size="xs"
311
387
  icon="i-lucide-star"
312
- :loading="busy === p.id"
388
+ :loading="busy === `${p.id}:default`"
313
389
  @click="makeDefault(p)"
314
390
  >
315
391
  {{ t('settings.riskPolicy.makeDefault') }}
@@ -319,12 +395,8 @@ async function create() {
319
395
  variant="ghost"
320
396
  size="xs"
321
397
  icon="i-lucide-trash-2"
322
- :disabled="p.isDefault || busy === p.id"
323
- :title="
324
- p.isDefault
325
- ? t('settings.riskPolicy.deleteDefaultBlocked')
326
- : t('settings.riskPolicy.deletePreset')
327
- "
398
+ :disabled="p.isDefault || p.isUnattendedDefault || busy?.startsWith(p.id)"
399
+ :title="deleteBlockedReason(p)"
328
400
  @click="remove(p)"
329
401
  />
330
402
  </div>
@@ -434,6 +506,22 @@ async function create() {
434
506
  </div>
435
507
  </div>
436
508
 
509
+ <!-- The autonomy posture: whether the parks the engine's own quality loops raise when they
510
+ give up wait for a person, or are answered on the record so the run finishes. Never
511
+ touches a gate the PIPELINE asked for. -->
512
+ <div class="mt-3 rounded-md border border-slate-800 bg-slate-900/40 p-3">
513
+ <USwitch
514
+ v-model="drafts[p.id]!.unattended"
515
+ size="sm"
516
+ :label="t('settings.riskPolicy.autonomy.label')"
517
+ :description="
518
+ drafts[p.id]!.unattended
519
+ ? t('settings.riskPolicy.autonomy.unattendedHint')
520
+ : t('settings.riskPolicy.autonomy.attendedHint')
521
+ "
522
+ />
523
+ </div>
524
+
437
525
  <div class="mt-3 flex items-center justify-between gap-3">
438
526
  <USwitch
439
527
  v-model="drafts[p.id]!.autoMergeEnabled"
@@ -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
- <p v-if="a.summary" class="mt-1 max-w-3xl text-[12px] leading-snug text-slate-400">
493
- {{ a.summary }}
494
- </p>
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
- <p v-if="vd.feedback" class="mt-1 text-[12px] leading-snug text-slate-400">
579
- {{ vd.feedback }}
580
- </p>
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
- <p
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
- <p v-if="o.detail" class="max-w-3xl text-[12px] leading-snug text-slate-400">
684
- {{ o.detail }}
685
- </p>
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
- <p v-if="c.detail" class="max-w-3xl text-[12px] leading-snug text-slate-400">
714
- {{ c.detail }}
715
- </p>
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
 
@@ -8,11 +8,17 @@ const refused = (reason: string) => ({
8
8
  body: { error: { code: 'forbidden', details: { reason } } },
9
9
  })
10
10
 
11
- const REASONS: RiskPolicySelectionRefusal[] = [
12
- 'relaxes_role_sandbox',
13
- 'relaxes_role_submission_allowlist',
14
- 'relaxes_role_class_rule',
15
- ]
11
+ /**
12
+ * Exhaustive BY CONSTRUCTION. A bare `RiskPolicySelectionRefusal[]` literal type-checks while
13
+ * being SHORT, so a reason added to the contracts union would reach the user as the backend's
14
+ * untranslated English with nothing failing; `satisfies Record<…>` fails to compile instead.
15
+ */
16
+ const REASONS = Object.keys({
17
+ relaxes_run_oversight: true,
18
+ relaxes_role_sandbox: true,
19
+ relaxes_role_submission_allowlist: true,
20
+ relaxes_role_class_rule: true,
21
+ } satisfies Record<RiskPolicySelectionRefusal, true>) as RiskPolicySelectionRefusal[]
16
22
 
17
23
  describe('moveRefusalKey', () => {
18
24
  it('maps every refusal reason to a key the catalog actually holds', () => {
@@ -21,6 +21,7 @@ import { apiErrorReason } from '~/composables/api/errors'
21
21
  * falls back to the backend's own message, which is the honest last resort.
22
22
  */
23
23
  const MOVE_REFUSAL_KEY: Record<RiskPolicySelectionRefusal, string> = {
24
+ relaxes_run_oversight: 'board.toast.moveRefused.relaxes_run_oversight',
24
25
  relaxes_role_sandbox: 'board.toast.moveRefused.relaxes_role_sandbox',
25
26
  relaxes_role_submission_allowlist: 'board.toast.moveRefused.relaxes_role_submission_allowlist',
26
27
  relaxes_role_class_rule: 'board.toast.moveRefused.relaxes_role_class_rule',
@@ -527,6 +527,8 @@
527
527
  "default": "Standard",
528
528
  "makeDefault": "Als Standard festlegen",
529
529
  "deleteDefaultBlocked": "Die Standardrichtlinie kann nicht gelöscht werden",
530
+ "deleteUnattendedDefaultBlocked": "Die Standardrichtlinie für unbeaufsichtigte Läufe kann nicht gelöscht werden",
531
+ "deleteBothDefaultsBlocked": "Diese Richtlinie ist sowohl der In-App- als auch der unbeaufsichtigte Standard und kann daher nicht gelöscht werden",
530
532
  "deletePreset": "Richtlinie löschen",
531
533
  "field": {
532
534
  "maxComplexity": "Max. Komplexität %",
@@ -601,6 +603,14 @@
601
603
  "redundant": "Ohne Wirkung: Diese Richtlinie ist bereits mindestens so streng.",
602
604
  "alreadyStrictest": "Wird ohnehin immer geprüft",
603
605
  "baseHint": "Diese Richtlinie vergleicht in jeder Kategorie die Bewertungen, eine Rolle kann eine Kategorie daher nur auf \"immer Review\" verschärfen."
606
+ },
607
+ "unattendedDefault": "Standard ohne Aufsicht",
608
+ "makeUnattendedDefault": "Zum Standard für unbeaufsichtigte Läufe machen (API, Tracker, Zeitplan)",
609
+ "makeUnattendedDefaultShort": "Unbeaufsichtigter Standard",
610
+ "autonomy": {
611
+ "label": "Unbeaufsichtigte Läufe ohne Wartezeit auf eine Person abschließen",
612
+ "unattendedHint": "Wenn eine automatische Schleife aufgibt (ein Companion an seinem Überarbeitungslimit, eine Prüfung an ihrem Durchlauflimit, unbearbeitete Folgepunkte), läuft der Durchlauf nachvollziehbar weiter statt anzuhalten. Von der Pipeline angeforderte Gates wie manuelles Testen, Review und Freigabe halten den Durchlauf weiterhin an.",
613
+ "attendedHint": "Wenn eine automatische Schleife aufgibt, hält der Durchlauf an und wartet auf eine Entscheidung. Richtig für ein Board, das jemand beobachtet; ein über die API gestarteter Durchlauf wartet unbegrenzt."
604
614
  }
605
615
  },
606
616
  "observabilityConnection": {
@@ -2852,6 +2862,7 @@
2852
2862
  "archiveFailed": "Dienst konnte nicht archiviert werden",
2853
2863
  "restoreFailed": "Dienst konnte nicht wiederhergestellt werden",
2854
2864
  "moveRefused": {
2865
+ "relaxes_run_oversight": "Dort, wohin du diese Aufgabe verschiebst, beantwortet ein Lauf seine eigenen Prüfpunkte selbst, statt auf eine Person zu warten; die hier geltende Merge-Richtlinie tut das nicht. Bitte eine Administration des Arbeitsbereichs, sie zu verschieben.",
2855
2866
  "relaxes_role_sandbox": "Die Ausführungen dieser Aufgabe laufen an ihrem jetzigen Ort für deine Rolle isoliert, die Merge-Richtlinie am Zielort jedoch nicht. Bitte eine Workspace-Administration, sie zu verschieben.",
2856
2867
  "relaxes_role_submission_allowlist": "Die Merge-Richtlinie am Zielort würde dich Änderungsarten mergen lassen, die dir hier verwehrt sind. Bitte eine Workspace-Administration, sie zu verschieben.",
2857
2868
  "relaxes_role_class_rule": "Die Merge-Richtlinie am Zielort merged Änderungen automatisch, die du hier prüfen musst. Bitte eine Workspace-Administration, sie zu verschieben."
@@ -6837,6 +6848,7 @@
6837
6848
  "workspaceDefaultCaption": "Gilt, weil diese Aufgabe keine eigene Richtlinie wählt.",
6838
6849
  "noneHint": "Keine Risikorichtlinie konfiguriert. Jeder Pull Request wartet auf eine menschliche Prüfung.",
6839
6850
  "refused": {
6851
+ "relaxes_run_oversight": "Für deine Rolle nicht verfügbar: Mit dieser Richtlinie beantwortet ein Lauf seine eigenen Prüfpunkte selbst, statt auf eine Person zu warten. Eine Administration des Arbeitsbereichs kann das ändern.",
6840
6852
  "relaxes_role_sandbox": "Für deine Rolle nicht verfügbar: Läufe dieser Aufgabe laufen in der Sandbox, und diese Richtlinie würde sie mergen lassen. Eine Workspace-Administration kann das ändern.",
6841
6853
  "relaxes_role_submission_allowlist": "Für deine Rolle nicht verfügbar: Diese Richtlinie würde dich Änderungsarten mergen lassen, die dir bei dieser Aufgabe verwehrt sind. Eine Workspace-Administration kann das ändern.",
6842
6854
  "relaxes_role_class_rule": "Für deine Rolle nicht verfügbar: Diese Richtlinie merged Änderungen automatisch, die du bei dieser Aufgabe prüfen musst. Eine Workspace-Administration kann das ändern."
@@ -173,6 +173,7 @@
173
173
  "archiveFailed": "Couldn't archive the service",
174
174
  "restoreFailed": "Couldn't restore the service",
175
175
  "moveRefused": {
176
+ "relaxes_run_oversight": "Where you are moving this task, a run answers its own review checkpoints instead of stopping for a person, and the merge policy governing it here does not. Ask a workspace admin to move it.",
176
177
  "relaxes_role_sandbox": "This task’s runs are sandboxed for your role where it is now, and the merge policy governing it where you are moving it is not. Ask a workspace admin to move it.",
177
178
  "relaxes_role_submission_allowlist": "The merge policy where you are moving this task would let you land kinds of change it holds you back from here. Ask a workspace admin to move it.",
178
179
  "relaxes_role_class_rule": "The merge policy where you are moving this task auto-merges changes you are held to review on it here. Ask a workspace admin to move it."
@@ -3253,6 +3254,8 @@
3253
3254
  "default": "Default",
3254
3255
  "makeDefault": "Make default",
3255
3256
  "deleteDefaultBlocked": "The default policy cannot be deleted",
3257
+ "deleteUnattendedDefaultBlocked": "The unattended default policy cannot be deleted",
3258
+ "deleteBothDefaultsBlocked": "This policy is both the in-app and the unattended default, so it cannot be deleted",
3256
3259
  "deletePreset": "Delete policy",
3257
3260
  "field": {
3258
3261
  "maxComplexity": "Max complexity %",
@@ -3336,6 +3339,14 @@
3336
3339
  "redundant": "No effect: this policy is already at least as strict.",
3337
3340
  "alreadyStrictest": "Already always reviewed",
3338
3341
  "baseHint": "This policy compares the scores for every class, so a role can only narrow a class to review-only."
3342
+ },
3343
+ "unattendedDefault": "Unattended default",
3344
+ "makeUnattendedDefault": "Make the default for unattended runs (API, tracker, schedule)",
3345
+ "makeUnattendedDefaultShort": "Unattended default",
3346
+ "autonomy": {
3347
+ "label": "Finish unattended runs without waiting for a person",
3348
+ "unattendedHint": "When an automatic loop gives up (a companion at its rework cap, a review at its pass cap, untriaged follow-ups), the run proceeds on the record instead of parking. Gates the pipeline asks for, such as human testing, review and approval, still stop the run.",
3349
+ "attendedHint": "When an automatic loop gives up, the run parks and waits for someone to choose. Right for a board somebody is watching; a run started over the API waits indefinitely."
3339
3350
  }
3340
3351
  },
3341
3352
  "observabilityConnection": {
@@ -5300,6 +5311,7 @@
5300
5311
  "workspaceDefaultCaption": "Applied because this task picks no policy of its own.",
5301
5312
  "noneHint": "No risk policy configured. Every pull request waits for a human review.",
5302
5313
  "refused": {
5314
+ "relaxes_run_oversight": "Not available for your role: this policy lets a run answer its own review checkpoints instead of stopping for a person. A workspace admin can change it.",
5303
5315
  "relaxes_role_sandbox": "Not available for your role: this task’s runs are sandboxed, and this policy would let them merge. A workspace admin can change it.",
5304
5316
  "relaxes_role_submission_allowlist": "Not available for your role: this policy would let you land kinds of change this task holds you back from. A workspace admin can change it.",
5305
5317
  "relaxes_role_class_rule": "Not available for your role: this policy auto-merges changes you are held to review on this task. A workspace admin can change it."
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "No se pudo archivar el servicio",
150
150
  "restoreFailed": "No se pudo restaurar el servicio",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "Donde estás moviendo esta tarea, una ejecución responde por sí misma a sus puntos de revisión en lugar de detenerse para una persona, y la política de fusión que la rige aquí no lo hace. Pide a la administración del espacio de trabajo que la mueva.",
152
153
  "relaxes_role_sandbox": "Las ejecuciones de esta tarea están aisladas para tu rol donde está ahora, y la política de fusión que la regiría donde la mueves no lo está. Pide a una administración del espacio de trabajo que la mueva.",
153
154
  "relaxes_role_submission_allowlist": "La política de fusión del destino te dejaría fusionar tipos de cambio que aquí tienes vedados. Pide a una administración del espacio de trabajo que la mueva.",
154
155
  "relaxes_role_class_rule": "La política de fusión del destino fusiona automáticamente cambios que aquí debes revisar. Pide a una administración del espacio de trabajo que la mueva."
@@ -2979,6 +2980,8 @@
2979
2980
  "default": "Predeterminado",
2980
2981
  "makeDefault": "Hacer predeterminado",
2981
2982
  "deleteDefaultBlocked": "La política predeterminada no se puede eliminar",
2983
+ "deleteUnattendedDefaultBlocked": "No se puede eliminar la política predeterminada para ejecuciones sin supervisión",
2984
+ "deleteBothDefaultsBlocked": "Esta política es a la vez la predeterminada en la aplicación y la que no tiene supervisión, así que no se puede eliminar",
2982
2985
  "deletePreset": "Eliminar política",
2983
2986
  "field": {
2984
2987
  "maxComplexity": "Complejidad máx. %",
@@ -3057,6 +3060,14 @@
3057
3060
  "redundant": "Sin efecto: esta política ya es igual de estricta o más.",
3058
3061
  "alreadyStrictest": "Ya se revisa siempre",
3059
3062
  "baseHint": "Esta política compara las puntuaciones en todas las categorías, así que un rol solo puede endurecer una categoría hasta exigir revisión."
3063
+ },
3064
+ "unattendedDefault": "Predeterminada sin supervisión",
3065
+ "makeUnattendedDefault": "Convertir en predeterminada para ejecuciones sin supervisión (API, tracker, programación)",
3066
+ "makeUnattendedDefaultShort": "Predeterminada sin supervisión",
3067
+ "autonomy": {
3068
+ "label": "Completar las ejecuciones sin supervisión sin esperar a una persona",
3069
+ "unattendedHint": "Cuando un bucle automático se rinde (un companion en su límite de reintentos, una revisión en su límite de pasadas, seguimientos sin triar), la ejecución continúa dejando constancia en lugar de detenerse. Las puertas que pide la pipeline, como pruebas manuales, revisión y aprobación, siguen deteniendo la ejecución.",
3070
+ "attendedHint": "Cuando un bucle automático se rinde, la ejecución se detiene y espera a que alguien elija. Adecuado para un tablero que alguien está mirando; una ejecución iniciada por la API espera indefinidamente."
3060
3071
  }
3061
3072
  },
3062
3073
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "Se aplica porque esta tarea no elige una política propia.",
6705
6716
  "noneHint": "No hay ninguna política de riesgo configurada. Cada pull request espera una revisión humana.",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "No disponible para tu rol: esta política deja que una ejecución responda por sí misma a sus puntos de revisión en lugar de detenerse para una persona. La administración del espacio de trabajo puede cambiarlo.",
6707
6719
  "relaxes_role_sandbox": "No disponible para tu rol: las ejecuciones de esta tarea están en un entorno aislado y esta política permitiría fusionarlas. Un administrador del espacio de trabajo puede cambiarlo.",
6708
6720
  "relaxes_role_submission_allowlist": "No disponible para tu rol: esta política te permitiría fusionar tipos de cambio que esta tarea te restringe. Un administrador del espacio de trabajo puede cambiarlo.",
6709
6721
  "relaxes_role_class_rule": "No disponible para tu rol: esta política fusiona automáticamente cambios que tú debes revisar en esta tarea. Un administrador del espacio de trabajo puede cambiarlo."
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "Impossible d'archiver le service",
150
150
  "restoreFailed": "Impossible de restaurer le service",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "Là où tu déplaces cette tâche, une exécution répond elle-même à ses points de contrôle au lieu de s’arrêter pour une personne, ce que la politique de fusion en vigueur ici ne fait pas. Demande à l’administration de l’espace de travail de la déplacer.",
152
153
  "relaxes_role_sandbox": "Les exécutions de cette tâche sont isolées pour votre rôle là où elle se trouve, et la politique de fusion qui la régirait à destination ne l’est pas. Demandez à une administration de l’espace de travail de la déplacer.",
153
154
  "relaxes_role_submission_allowlist": "La politique de fusion à destination vous laisserait fusionner des types de changement dont vous êtes privé ici. Demandez à une administration de l’espace de travail de la déplacer.",
154
155
  "relaxes_role_class_rule": "La politique de fusion à destination fusionne automatiquement des changements que vous devez relire ici. Demandez à une administration de l’espace de travail de la déplacer."
@@ -2979,6 +2980,8 @@
2979
2980
  "default": "Par défaut",
2980
2981
  "makeDefault": "Définir par défaut",
2981
2982
  "deleteDefaultBlocked": "La politique par défaut ne peut pas être supprimée",
2983
+ "deleteUnattendedDefaultBlocked": "La politique par défaut des exécutions sans surveillance ne peut pas être supprimée",
2984
+ "deleteBothDefaultsBlocked": "Cette politique est à la fois le défaut dans l’app et le défaut sans surveillance, elle ne peut donc pas être supprimée",
2982
2985
  "deletePreset": "Supprimer la politique",
2983
2986
  "field": {
2984
2987
  "maxComplexity": "Complexité max %",
@@ -3057,6 +3060,14 @@
3057
3060
  "redundant": "Sans effet : cette politique est déjà au moins aussi stricte.",
3058
3061
  "alreadyStrictest": "Déjà toujours relu",
3059
3062
  "baseHint": "Cette politique compare les scores pour chaque catégorie : un rôle ne peut donc durcir une catégorie que jusqu'à la revue obligatoire."
3063
+ },
3064
+ "unattendedDefault": "Par défaut sans surveillance",
3065
+ "makeUnattendedDefault": "Définir par défaut pour les exécutions sans surveillance (API, tracker, planification)",
3066
+ "makeUnattendedDefaultShort": "Défaut sans surveillance",
3067
+ "autonomy": {
3068
+ "label": "Terminer les exécutions sans surveillance sans attendre une personne",
3069
+ "unattendedHint": "Quand une boucle automatique abandonne (un companion à sa limite de reprises, une revue à sa limite de passes, des suivis non triés), l'exécution continue en le consignant au lieu de s'arrêter. Les points de contrôle demandés par le pipeline, comme le test humain, la revue et l'approbation, arrêtent toujours l'exécution.",
3070
+ "attendedHint": "Quand une boucle automatique abandonne, l'exécution s'arrête et attend un choix. Adapté à un tableau que quelqu'un surveille ; une exécution lancée via l'API attend indéfiniment."
3060
3071
  }
3061
3072
  },
3062
3073
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "Appliquée parce que cette tâche ne choisit aucune politique.",
6705
6716
  "noneHint": "Aucune politique de risque configurée. Chaque pull request attend une revue humaine.",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "Indisponible pour ton rôle : cette politique laisse une exécution répondre elle-même à ses points de contrôle au lieu de s’arrêter pour une personne. L’administration de l’espace de travail peut le changer.",
6707
6719
  "relaxes_role_sandbox": "Indisponible pour votre rôle : les exécutions de cette tâche sont isolées, et cette politique les laisserait fusionner. Un administrateur de l’espace de travail peut le changer.",
6708
6720
  "relaxes_role_submission_allowlist": "Indisponible pour votre rôle : cette politique vous laisserait fusionner des types de changement dont cette tâche vous prive. Un administrateur de l’espace de travail peut le changer.",
6709
6721
  "relaxes_role_class_rule": "Indisponible pour votre rôle : cette politique fusionne automatiquement des changements que vous devez relire sur cette tâche. Un administrateur de l’espace de travail peut le changer."
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "לא ניתן להעביר את השירות לארכיון",
150
150
  "restoreFailed": "לא ניתן לשחזר את השירות",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "במקום שאליו אתם מעבירים את המשימה, הרצה עונה בעצמה על נקודות הבדיקה שלה במקום לעצור ולחכות לאדם, ומדיניות המיזוג שחלה עליה כאן אינה עושה זאת. בקשו ממנהל סביבת העבודה להעביר אותה.",
152
153
  "relaxes_role_sandbox": "ההרצות של משימה זו מבודדות עבור התפקיד שלך במיקומה הנוכחי, ואילו מדיניות המיזוג שתחול במיקום שאליו אתה מעביר אותה אינה כזו. בקש ממנהל סביבת העבודה להעביר אותה.",
153
154
  "relaxes_role_submission_allowlist": "מדיניות המיזוג במיקום שאליו אתה מעביר את המשימה הייתה מאפשרת לך למזג סוגי שינויים שכאן נמנעים ממך. בקש ממנהל סביבת העבודה להעביר אותה.",
154
155
  "relaxes_role_class_rule": "מדיניות המיזוג במיקום שאליו אתה מעביר את המשימה ממזגת אוטומטית שינויים שכאן אתה נדרש לבדוק. בקש ממנהל סביבת העבודה להעביר אותה."
@@ -3121,6 +3122,8 @@
3121
3122
  "default": "ברירת מחדל",
3122
3123
  "makeDefault": "הפוך לברירת מחדל",
3123
3124
  "deleteDefaultBlocked": "לא ניתן למחוק את מדיניות ברירת המחדל",
3125
+ "deleteUnattendedDefaultBlocked": "לא ניתן למחוק את מדיניות ברירת המחדל להרצות ללא פיקוח",
3126
+ "deleteBothDefaultsBlocked": "המדיניות הזו היא גם ברירת המחדל באפליקציה וגם זו שללא פיקוח, ולכן לא ניתן למחוק אותה",
3124
3127
  "deletePreset": "מחיקת מדיניות",
3125
3128
  "field": {
3126
3129
  "maxComplexity": "מורכבות מרבית %",
@@ -3199,6 +3202,14 @@
3199
3202
  "redundant": "ללא השפעה: המדיניות הזו כבר מחמירה לפחות באותה מידה.",
3200
3203
  "alreadyStrictest": "כבר תמיד נדרשת סקירה",
3201
3204
  "baseHint": "המדיניות הזו משווה את הציונים בכל סוג שינוי, ולכן תפקיד יכול להחמיר סוג רק עד דרישת סקירה."
3205
+ },
3206
+ "unattendedDefault": "ברירת מחדל ללא השגחה",
3207
+ "makeUnattendedDefault": "הגדר כברירת מחדל להרצות ללא השגחה (API, מערכת מעקב, תזמון)",
3208
+ "makeUnattendedDefaultShort": "ברירת מחדל ללא פיקוח",
3209
+ "autonomy": {
3210
+ "label": "לסיים הרצות ללא השגחה בלי להמתין לאדם",
3211
+ "unattendedHint": "כשלולאה אוטומטית מוותרת (קומפניון שמיצה את מכסת התיקונים, סקירה שמיצתה את מכסת המעברים, פריטי המשך שלא מוינו), ההרצה ממשיכה תוך תיעוד במקום לעצור. שערים שהצינור ביקש, כגון בדיקה אנושית, סקירה ואישור, עדיין עוצרים את ההרצה.",
3212
+ "attendedHint": "כשלולאה אוטומטית מוותרת, ההרצה נעצרת וממתינה שמישהו יחליט. מתאים ללוח שמישהו צופה בו; הרצה שהופעלה דרך ה-API תמתין ללא הגבלת זמן."
3202
3213
  }
3203
3214
  },
3204
3215
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "חלה מפני שהמשימה הזו לא בוחרת מדיניות משלה.",
6705
6716
  "noneHint": "לא הוגדרה מדיניות סיכון. כל בקשת משיכה ממתינה לסקירה אנושית.",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "לא זמין לתפקיד שלכם: המדיניות הזו מאפשרת להרצה לענות בעצמה על נקודות הבדיקה שלה במקום לעצור ולחכות לאדם. מנהל סביבת העבודה יכול לשנות זאת.",
6707
6719
  "relaxes_role_sandbox": "לא זמין לתפקיד שלך: ההרצות של משימה זו מבודדות, והמדיניות הזו הייתה מאפשרת למזג אותן. מנהל סביבת העבודה יכול לשנות זאת.",
6708
6720
  "relaxes_role_submission_allowlist": "לא זמין לתפקיד שלך: המדיניות הזו הייתה מאפשרת לך למזג סוגי שינויים שמשימה זו מונעת ממך. מנהל סביבת העבודה יכול לשנות זאת.",
6709
6721
  "relaxes_role_class_rule": "לא זמין לתפקיד שלך: המדיניות הזו ממזגת אוטומטית שינויים שאתה נדרש לבדוק במשימה זו. מנהל סביבת העבודה יכול לשנות זאת."
@@ -527,6 +527,8 @@
527
527
  "default": "Predefinito",
528
528
  "makeDefault": "Imposta come predefinito",
529
529
  "deleteDefaultBlocked": "Il criterio predefinito non puo essere eliminato",
530
+ "deleteUnattendedDefaultBlocked": "La policy predefinita per le esecuzioni non presidiate non può essere eliminata",
531
+ "deleteBothDefaultsBlocked": "Questa policy è sia la predefinita in-app sia quella non presidiata, quindi non può essere eliminata",
530
532
  "deletePreset": "Elimina criterio",
531
533
  "field": {
532
534
  "maxComplexity": "Complessita max %",
@@ -601,6 +603,14 @@
601
603
  "redundant": "Nessun effetto: questo criterio è già almeno altrettanto severo.",
602
604
  "alreadyStrictest": "Già sempre in revisione",
603
605
  "baseHint": "Questo criterio confronta i punteggi per ogni categoria, quindi un ruolo può restringere una categoria solo fino alla revisione obbligatoria."
606
+ },
607
+ "unattendedDefault": "Predefinita non presidiata",
608
+ "makeUnattendedDefault": "Imposta come predefinita per le esecuzioni non presidiate (API, tracker, pianificazione)",
609
+ "makeUnattendedDefaultShort": "Predefinita non presidiata",
610
+ "autonomy": {
611
+ "label": "Completare le esecuzioni non presidiate senza attendere una persona",
612
+ "unattendedHint": "Quando un ciclo automatico si arrende (un companion al suo limite di rilavorazioni, una revisione al suo limite di passaggi, follow-up non smistati), l'esecuzione prosegue lasciandone traccia invece di fermarsi. I varchi richiesti dalla pipeline, come test manuale, revisione e approvazione, fermano comunque l'esecuzione.",
613
+ "attendedHint": "Quando un ciclo automatico si arrende, l'esecuzione si ferma e attende una scelta. Adatto a una board che qualcuno sta guardando; un'esecuzione avviata via API attende all'infinito."
604
614
  }
605
615
  },
606
616
  "observabilityConnection": {
@@ -2852,6 +2862,7 @@
2852
2862
  "archiveFailed": "Impossibile archiviare il servizio",
2853
2863
  "restoreFailed": "Impossibile ripristinare il servizio",
2854
2864
  "moveRefused": {
2865
+ "relaxes_run_oversight": "Dove stai spostando questa attività, un’esecuzione risponde da sola ai propri punti di controllo invece di fermarsi per una persona, mentre la policy di merge che la governa qui non lo fa. Chiedi all’amministrazione dello spazio di lavoro di spostarla.",
2855
2866
  "relaxes_role_sandbox": "Le esecuzioni di questa attività sono isolate per il tuo ruolo dove si trova ora, mentre il criterio di merge che la governerebbe a destinazione non lo è. Chiedi a un’amministrazione dello spazio di lavoro di spostarla.",
2856
2867
  "relaxes_role_submission_allowlist": "Il criterio di merge a destinazione ti permetterebbe di unire tipi di modifica che qui ti sono preclusi. Chiedi a un’amministrazione dello spazio di lavoro di spostarla.",
2857
2868
  "relaxes_role_class_rule": "Il criterio di merge a destinazione unisce automaticamente modifiche che qui devi revisionare. Chiedi a un’amministrazione dello spazio di lavoro di spostarla."
@@ -6837,6 +6848,7 @@
6837
6848
  "workspaceDefaultCaption": "Si applica perche questa attivita non sceglie un criterio proprio.",
6838
6849
  "noneHint": "Nessun criterio di rischio configurato. Ogni pull request attende una revisione umana.",
6839
6850
  "refused": {
6851
+ "relaxes_run_oversight": "Non disponibile per il tuo ruolo: questa policy lascia che un’esecuzione risponda da sola ai propri punti di controllo invece di fermarsi per una persona. L’amministrazione dello spazio di lavoro può modificarlo.",
6840
6852
  "relaxes_role_sandbox": "Non disponibile per il tuo ruolo: le esecuzioni di questa attività sono isolate e questo criterio ne consentirebbe il merge. Un amministratore dello spazio di lavoro può cambiarlo.",
6841
6853
  "relaxes_role_submission_allowlist": "Non disponibile per il tuo ruolo: questo criterio ti permetterebbe di unire tipi di modifica che questa attività ti preclude. Un amministratore dello spazio di lavoro può cambiarlo.",
6842
6854
  "relaxes_role_class_rule": "Non disponibile per il tuo ruolo: questo criterio unisce automaticamente modifiche che devi revisionare in questa attività. Un amministratore dello spazio di lavoro può cambiarlo."
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "サービスをアーカイブできませんでした",
150
150
  "restoreFailed": "サービスを復元できませんでした",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "このタスクの移動先では、実行が人の判断を待たずに自身のレビュー確認を自分で処理します。現在このタスクを統制しているマージポリシーはそうではありません。ワークスペース管理者に移動を依頼してください。",
152
153
  "relaxes_role_sandbox": "このタスクの実行は現在の場所ではあなたのロールに対してサンドボックス化されていますが、移動先で適用されるマージポリシーではそうなりません。移動はワークスペース管理者に依頼してください。",
153
154
  "relaxes_role_submission_allowlist": "移動先のマージポリシーでは、ここでは許可されていない種類の変更もマージできてしまいます。移動はワークスペース管理者に依頼してください。",
154
155
  "relaxes_role_class_rule": "移動先のマージポリシーは、ここではあなたのレビューが必要な変更を自動マージします。移動はワークスペース管理者に依頼してください。"
@@ -3121,6 +3122,8 @@
3121
3122
  "default": "デフォルト",
3122
3123
  "makeDefault": "デフォルトにする",
3123
3124
  "deleteDefaultBlocked": "デフォルトポリシーは削除できません",
3125
+ "deleteUnattendedDefaultBlocked": "無人実行の既定ポリシーは削除できません",
3126
+ "deleteBothDefaultsBlocked": "このポリシーはアプリ内の既定と無人実行の既定を兼ねているため、削除できません",
3124
3127
  "deletePreset": "ポリシーを削除",
3125
3128
  "field": {
3126
3129
  "maxComplexity": "最大複雑度 %",
@@ -3199,6 +3202,14 @@
3199
3202
  "redundant": "効果はありません。このポリシーはすでに同等以上に厳しい設定です。",
3200
3203
  "alreadyStrictest": "すでに常にレビュー必須",
3201
3204
  "baseHint": "このポリシーはすべてのカテゴリでスコアを比較するため、ロールはカテゴリを「常にレビュー必須」にすることしかできません。"
3205
+ },
3206
+ "unattendedDefault": "無人実行の既定",
3207
+ "makeUnattendedDefault": "無人実行(API・トラッカー・スケジュール)の既定にする",
3208
+ "makeUnattendedDefaultShort": "無人実行の既定",
3209
+ "autonomy": {
3210
+ "label": "無人実行を人の判断を待たずに完了させる",
3211
+ "unattendedHint": "自動ループが打ち切られたとき(コンパニオンの手戻り上限、レビューのパス上限、未仕分けのフォローアップ)、実行は停止せず記録を残して先に進みます。パイプラインが要求したゲート、たとえば人手テスト・レビュー・承認は、これまでどおり実行を止めます。",
3212
+ "attendedHint": "自動ループが打ち切られると、実行は停止して人の判断を待ちます。誰かが見ているボードには適していますが、API から開始した実行は無期限に待ち続けます。"
3202
3213
  }
3203
3214
  },
3204
3215
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "このタスクが独自のポリシーを選んでいないため、これが適用されます。",
6705
6716
  "noneHint": "リスクポリシーが設定されていません。すべてのプルリクエストは人のレビューを待ちます。",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "あなたのロールでは選択できません: このポリシーでは、実行が人の判断を待たずに自身のレビュー確認を自分で処理します。ワークスペース管理者が変更できます。",
6707
6719
  "relaxes_role_sandbox": "あなたのロールでは選べません。このタスクの実行はサンドボックスで動作しますが、このポリシーではマージが許可されます。ワークスペース管理者が変更できます。",
6708
6720
  "relaxes_role_submission_allowlist": "あなたのロールでは選べません。このポリシーでは、このタスクで許可されていない種類の変更もマージできてしまいます。ワークスペース管理者が変更できます。",
6709
6721
  "relaxes_role_class_rule": "あなたのロールでは選べません。このポリシーは、このタスクであなたのレビューが必要な変更を自動マージします。ワークスペース管理者が変更できます。"
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "Nie udało się zarchiwizować usługi",
150
150
  "restoreFailed": "Nie udało się przywrócić usługi",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "W miejscu, do którego przenosisz to zadanie, uruchomienie samo odpowiada na własne punkty kontrolne zamiast zatrzymywać się na człowieku, a zasada scalania obowiązująca tutaj tego nie robi. Poproś administrację przestrzeni roboczej o przeniesienie.",
152
153
  "relaxes_role_sandbox": "Uruchomienia tego zadania są w obecnym miejscu izolowane dla twojej roli, a zasada scalania obowiązująca w miejscu docelowym już nie. Poproś administrację przestrzeni roboczej o przeniesienie.",
153
154
  "relaxes_role_submission_allowlist": "Zasada scalania w miejscu docelowym pozwoliłaby ci scalać rodzaje zmian, których tutaj nie możesz. Poproś administrację przestrzeni roboczej o przeniesienie.",
154
155
  "relaxes_role_class_rule": "Zasada scalania w miejscu docelowym automatycznie scala zmiany, które tutaj musisz przejrzeć. Poproś administrację przestrzeni roboczej o przeniesienie."
@@ -2979,6 +2980,8 @@
2979
2980
  "default": "Domyślne",
2980
2981
  "makeDefault": "Ustaw jako domyślne",
2981
2982
  "deleteDefaultBlocked": "Nie można usunąć zasady domyślnej",
2983
+ "deleteUnattendedDefaultBlocked": "Nie można usunąć domyślnej zasady dla uruchomień bez nadzoru",
2984
+ "deleteBothDefaultsBlocked": "Ta zasada jest jednocześnie domyślną w aplikacji i domyślną bez nadzoru, więc nie można jej usunąć",
2982
2985
  "deletePreset": "Usuń zasadę",
2983
2986
  "field": {
2984
2987
  "maxComplexity": "Maks. złożoność %",
@@ -3057,6 +3060,14 @@
3057
3060
  "redundant": "Bez efektu: ta zasada jest już co najmniej tak samo surowa.",
3058
3061
  "alreadyStrictest": "Już zawsze przeglądane",
3059
3062
  "baseHint": "Ta zasada porównuje oceny w każdej kategorii, więc rola może zaostrzyć kategorię jedynie do wymogu przeglądu."
3063
+ },
3064
+ "unattendedDefault": "Domyślna dla bez nadzoru",
3065
+ "makeUnattendedDefault": "Ustaw jako domyślną dla uruchomień bez nadzoru (API, tracker, harmonogram)",
3066
+ "makeUnattendedDefaultShort": "Domyślna bez nadzoru",
3067
+ "autonomy": {
3068
+ "label": "Kończ uruchomienia bez nadzoru bez czekania na człowieka",
3069
+ "unattendedHint": "Gdy automatyczna pętla się poddaje (companion na limicie poprawek, przegląd na limicie przebiegów, nieposegregowane zadania pochodne), uruchomienie idzie dalej z zapisem zamiast się zatrzymywać. Bramki, o które prosi pipeline, takie jak testy ręczne, przegląd i zatwierdzenie, nadal je zatrzymują.",
3070
+ "attendedHint": "Gdy automatyczna pętla się poddaje, uruchomienie zatrzymuje się i czeka na decyzję. Właściwe dla tablicy, którą ktoś obserwuje; uruchomienie wystartowane przez API czeka bez końca."
3060
3071
  }
3061
3072
  },
3062
3073
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "Stosowana, ponieważ to zadanie nie wybiera własnej zasady.",
6705
6716
  "noneHint": "Nie skonfigurowano żadnej zasady ryzyka. Każdy pull request czeka na ludzką recenzję.",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "Niedostępne dla twojej roli: ta zasada pozwala uruchomieniu samemu odpowiadać na własne punkty kontrolne zamiast zatrzymywać się na człowieku. Administrator obszaru roboczego może to zmienić.",
6707
6719
  "relaxes_role_sandbox": "Niedostępne dla twojej roli: uruchomienia tego zadania działają w piaskownicy, a ta zasada pozwoliłaby je scalić. Administrator obszaru roboczego może to zmienić.",
6708
6720
  "relaxes_role_submission_allowlist": "Niedostępne dla twojej roli: ta zasada pozwoliłaby ci scalać rodzaje zmian, których to zadanie ci zabrania. Administrator obszaru roboczego może to zmienić.",
6709
6721
  "relaxes_role_class_rule": "Niedostępne dla twojej roli: ta zasada automatycznie scala zmiany, które musisz przejrzeć w tym zadaniu. Administrator obszaru roboczego może to zmienić."
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "Hizmet arşivlenemedi",
150
150
  "restoreFailed": "Hizmet geri yüklenemedi",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "Bu görevi taşıdığın yerde bir çalıştırma, bir kişiyi beklemek yerine kendi inceleme kontrol noktalarını kendisi yanıtlıyor; burada geçerli olan birleştirme ilkesi ise bunu yapmıyor. Taşıması için bir çalışma alanı yöneticisine başvur.",
152
153
  "relaxes_role_sandbox": "Bu görevin çalıştırmaları şu anki yerinde rolün için yalıtılmış, taşıdığın yerde geçerli olacak birleştirme ilkesi ise değil. Taşıması için bir çalışma alanı yöneticisine başvur.",
153
154
  "relaxes_role_submission_allowlist": "Taşıdığın yerdeki birleştirme ilkesi, burada sana kapalı olan değişiklik türlerini birleştirmene izin verirdi. Taşıması için bir çalışma alanı yöneticisine başvur.",
154
155
  "relaxes_role_class_rule": "Taşıdığın yerdeki birleştirme ilkesi, burada incelemekle yükümlü olduğun değişiklikleri otomatik birleştiriyor. Taşıması için bir çalışma alanı yöneticisine başvur."
@@ -3121,6 +3122,8 @@
3121
3122
  "default": "Varsayılan",
3122
3123
  "makeDefault": "Varsayılan yap",
3123
3124
  "deleteDefaultBlocked": "Varsayılan ilke silinemez",
3125
+ "deleteUnattendedDefaultBlocked": "Gözetimsiz çalıştırmaların varsayılan ilkesi silinemez",
3126
+ "deleteBothDefaultsBlocked": "Bu ilke hem uygulama içi hem de gözetimsiz varsayılan olduğu için silinemez",
3124
3127
  "deletePreset": "İlkeyi sil",
3125
3128
  "field": {
3126
3129
  "maxComplexity": "Maks. karmaşıklık %",
@@ -3199,6 +3202,14 @@
3199
3202
  "redundant": "Etkisi yok: bu ilke zaten en az bu kadar katı.",
3200
3203
  "alreadyStrictest": "Zaten her zaman inceleniyor",
3201
3204
  "baseHint": "Bu ilke her kategori için puanları karşılaştırır, bu yüzden bir rol bir kategoriyi yalnızca inceleme zorunluluğuna kadar sıkılaştırabilir."
3205
+ },
3206
+ "unattendedDefault": "Gözetimsiz varsayılan",
3207
+ "makeUnattendedDefault": "Gözetimsiz çalıştırmalar için varsayılan yap (API, takip sistemi, zamanlama)",
3208
+ "makeUnattendedDefaultShort": "Gözetimsiz varsayılan",
3209
+ "autonomy": {
3210
+ "label": "Gözetimsiz çalıştırmaları bir kişiyi beklemeden tamamla",
3211
+ "unattendedHint": "Otomatik bir döngü pes ettiğinde (yeniden çalışma sınırındaki bir companion, geçiş sınırındaki bir inceleme, ayıklanmamış takip maddeleri), çalıştırma durmak yerine kayda geçirilerek devam eder. Hattın istediği kapılar, örneğin insan testi, inceleme ve onay, çalıştırmayı yine durdurur.",
3212
+ "attendedHint": "Otomatik bir döngü pes ettiğinde çalıştırma durur ve birinin seçim yapmasını bekler. Birinin izlediği bir pano için doğrudur; API üzerinden başlatılan bir çalıştırma süresiz bekler."
3202
3213
  }
3203
3214
  },
3204
3215
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "Bu görev kendine bir ilke seçmediği için uygulanır.",
6705
6716
  "noneHint": "Yapılandırılmış risk ilkesi yok. Her pull request insan incelemesini bekler.",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "Rolün için kullanılamaz: bu ilke, bir çalıştırmanın bir kişiyi beklemek yerine kendi inceleme kontrol noktalarını kendisinin yanıtlamasına izin verir. Bir çalışma alanı yöneticisi bunu değiştirebilir.",
6707
6719
  "relaxes_role_sandbox": "Rolün için kullanılamaz: bu görevin çalışmaları yalıtılmış çalışır ve bu ilke birleştirmelerine izin verirdi. Bir çalışma alanı yöneticisi bunu değiştirebilir.",
6708
6720
  "relaxes_role_submission_allowlist": "Rolün için kullanılamaz: bu ilke, bu görevde sana kapalı olan değişiklik türlerini birleştirmene izin verirdi. Bir çalışma alanı yöneticisi bunu değiştirebilir.",
6709
6721
  "relaxes_role_class_rule": "Rolün için kullanılamaz: bu ilke, bu görevde incelemen gereken değişiklikleri otomatik birleştirir. Bir çalışma alanı yöneticisi bunu değiştirebilir."
@@ -149,6 +149,7 @@
149
149
  "archiveFailed": "Не вдалося заархівувати сервіс",
150
150
  "restoreFailed": "Не вдалося відновити сервіс",
151
151
  "moveRefused": {
152
+ "relaxes_run_oversight": "Там, куди ви переносите це завдання, запуск сам відповідає на власні контрольні точки перевірки замість того, щоб зупинитися й дочекатися людини, а політика злиття, що діє тут, — ні. Попросіть адміністрацію робочого простору перенести його.",
152
153
  "relaxes_role_sandbox": "Запуски цього завдання на його теперішньому місці ізольовані для вашої ролі, а політика злиття там, куди ви його переносите, — ні. Попросіть адміністрацію робочого простору перенести його.",
153
154
  "relaxes_role_submission_allowlist": "Політика злиття там, куди ви переносите це завдання, дозволила б вам зливати типи змін, які тут вам заборонені. Попросіть адміністрацію робочого простору перенести його.",
154
155
  "relaxes_role_class_rule": "Політика злиття там, куди ви переносите це завдання, автоматично зливає зміни, які тут ви маєте перевіряти. Попросіть адміністрацію робочого простору перенести його."
@@ -2979,6 +2980,8 @@
2979
2980
  "default": "За замовчуванням",
2980
2981
  "makeDefault": "Зробити за замовчуванням",
2981
2982
  "deleteDefaultBlocked": "Політику за замовчуванням не можна видалити",
2983
+ "deleteUnattendedDefaultBlocked": "Типову політику для запусків без нагляду не можна видалити",
2984
+ "deleteBothDefaultsBlocked": "Ця політика є водночас типовою в застосунку і типовою без нагляду, тому її не можна видалити",
2982
2985
  "deletePreset": "Видалити політику",
2983
2986
  "field": {
2984
2987
  "maxComplexity": "Макс. складність %",
@@ -3057,6 +3060,14 @@
3057
3060
  "redundant": "Без ефекту: ця політика вже щонайменше така сама сувора.",
3058
3061
  "alreadyStrictest": "Уже завжди рецензується",
3059
3062
  "baseHint": "Ця політика порівнює оцінки для кожної категорії, тож роль може посилити категорію лише до обовʼязкового рецензування."
3063
+ },
3064
+ "unattendedDefault": "Типова для без нагляду",
3065
+ "makeUnattendedDefault": "Зробити типовою для запусків без нагляду (API, трекер, розклад)",
3066
+ "makeUnattendedDefaultShort": "Типова без нагляду",
3067
+ "autonomy": {
3068
+ "label": "Завершувати запуски без нагляду, не чекаючи на людину",
3069
+ "unattendedHint": "Коли автоматичний цикл здається (компаньйон на межі доопрацювань, огляд на межі проходів, несортовані подальші пункти), запуск іде далі із записом замість зупинки. Ворота, які просить конвеєр, як-от ручне тестування, огляд і схвалення, усе одно зупиняють запуск.",
3070
+ "attendedHint": "Коли автоматичний цикл здається, запуск зупиняється й чекає на рішення. Це доречно для дошки, за якою хтось стежить; запуск, стартований через API, чекатиме безкінечно."
3060
3071
  }
3061
3072
  },
3062
3073
  "observabilityConnection": {
@@ -6704,6 +6715,7 @@
6704
6715
  "workspaceDefaultCaption": "Застосовується, бо це завдання не обрало власної політики.",
6705
6716
  "noneHint": "Політику ризику не налаштовано. Кожен pull request чекає на людську перевірку.",
6706
6717
  "refused": {
6718
+ "relaxes_run_oversight": "Недоступно для вашої ролі: ця політика дозволяє запуску самому відповідати на власні контрольні точки перевірки замість того, щоб зупинитися й дочекатися людини. Адміністратор робочого простору може це змінити.",
6707
6719
  "relaxes_role_sandbox": "Недоступно для вашої ролі: запуски цього завдання ізольовані, а ця політика дозволила б їх злиття. Адміністратор робочого простору може це змінити.",
6708
6720
  "relaxes_role_submission_allowlist": "Недоступно для вашої ролі: ця політика дозволила б вам зливати типи змін, які це завдання вам забороняє. Адміністратор робочого простору може це змінити.",
6709
6721
  "relaxes_role_class_rule": "Недоступно для вашої ролі: ця політика автоматично зливає зміни, які ви маєте перевіряти в цьому завданні. Адміністратор робочого простору може це змінити."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.265.0",
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",
@@ -40,7 +40,7 @@
40
40
  "valibot": "^1.4.2",
41
41
  "vue": "3.5.41",
42
42
  "wretch": "^3.0.9",
43
- "@cat-factory/contracts": "0.300.0"
43
+ "@cat-factory/contracts": "0.301.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@toad-contracts/testing": "0.3.2",