@cat-factory/app 0.148.1 → 0.149.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.
@@ -135,6 +135,80 @@ const draftValid = computed(
135
135
  () => draft.value.title.trim() && draft.value.summary.trim() && draft.value.body.trim(),
136
136
  )
137
137
 
138
+ // ---- auto-generate a title from the fragment's content (inline LLM call) ---
139
+ // Shared by the create form and the inline editor; keyed so only the button that triggered it
140
+ // spins. Generation needs a body (the title is derived from it); the summary rides along.
141
+ const generatingTitleFor = ref<string | null>(null)
142
+ async function autofillTitle(
143
+ key: string,
144
+ get: () => { body: string; summary?: string },
145
+ set: (title: string) => void,
146
+ ) {
147
+ const { body, summary } = get()
148
+ if (!body.trim() || generatingTitleFor.value) return
149
+ generatingTitleFor.value = key
150
+ try {
151
+ const title = await library.generateTitle({
152
+ body: body.trim(),
153
+ summary: summary?.trim() || undefined,
154
+ })
155
+ set(title)
156
+ } catch (e) {
157
+ notifyError(t('fragments.authored.titleGenFailed'), e)
158
+ } finally {
159
+ generatingTitleFor.value = null
160
+ }
161
+ }
162
+
163
+ // ---- edit an existing hand-authored fragment (title / summary / body / tags) ---
164
+ const editDraft = ref<{
165
+ id: string
166
+ title: string
167
+ summary: string
168
+ body: string
169
+ tags: string
170
+ } | null>(null)
171
+ function startEdit(f: (typeof library.fragments)[number]) {
172
+ editDraft.value = {
173
+ id: f.id,
174
+ title: f.title,
175
+ summary: f.summary,
176
+ body: f.body,
177
+ tags: (f.tags ?? []).join(', '),
178
+ }
179
+ }
180
+ function cancelEdit() {
181
+ editDraft.value = null
182
+ }
183
+ const editValid = computed(
184
+ () =>
185
+ !!editDraft.value &&
186
+ !!editDraft.value.title.trim() &&
187
+ !!editDraft.value.summary.trim() &&
188
+ !!editDraft.value.body.trim(),
189
+ )
190
+ async function saveEdit() {
191
+ const d = editDraft.value
192
+ if (!d || !editValid.value) return
193
+ await withRow(`edit:${d.id}`, async () => {
194
+ try {
195
+ await library.update(d.id, {
196
+ title: d.title.trim(),
197
+ summary: d.summary.trim(),
198
+ body: d.body.trim(),
199
+ tags: d.tags
200
+ .split(',')
201
+ .map((t) => t.trim())
202
+ .filter(Boolean),
203
+ })
204
+ editDraft.value = null
205
+ toast.add({ title: t('fragments.toast.updated'), icon: 'i-lucide-check' })
206
+ } catch (e) {
207
+ notifyError(t('fragments.toast.updateFailed'), e)
208
+ }
209
+ })
210
+ }
211
+
138
212
  async function createFragment() {
139
213
  if (!draftValid.value) return
140
214
  creating.value = true
@@ -522,26 +596,96 @@ async function unlinkSource(id: string) {
522
596
  <div
523
597
  v-for="f in library.fragments"
524
598
  :key="f.id"
525
- class="flex items-start gap-2 rounded-md border border-slate-800 bg-slate-900/60 p-3"
599
+ class="rounded-md border border-slate-800 bg-slate-900/60 p-3"
526
600
  >
527
- <div class="min-w-0">
528
- <div class="flex items-center gap-2">
529
- <span class="font-medium text-slate-100">{{ f.title }}</span>
530
- <UBadge v-if="f.source" size="xs" color="info" variant="subtle">{{
531
- t('fragments.authored.fromRepo')
532
- }}</UBadge>
601
+ <!-- Inline editor (hand-authored fragments): title / summary / body / tags, with the
602
+ same auto-generate-title button as the create form. -->
603
+ <div v-if="editDraft && editDraft.id === f.id" class="flex flex-col gap-2">
604
+ <div class="flex gap-2">
605
+ <UInput
606
+ v-model="editDraft.title"
607
+ :placeholder="t('fragments.authored.titlePlaceholder')"
608
+ class="flex-1"
609
+ />
610
+ <UButton
611
+ icon="i-lucide-wand-2"
612
+ size="sm"
613
+ variant="outline"
614
+ :disabled="!editDraft.body.trim()"
615
+ :loading="generatingTitleFor === `edit:${f.id}`"
616
+ :title="t('fragments.authored.generateTitleHint')"
617
+ @click="
618
+ autofillTitle(
619
+ `edit:${f.id}`,
620
+ () => ({ body: editDraft!.body, summary: editDraft!.summary }),
621
+ (title) => {
622
+ if (editDraft) editDraft.title = title
623
+ },
624
+ )
625
+ "
626
+ >
627
+ {{ t('fragments.authored.generateTitle') }}
628
+ </UButton>
629
+ </div>
630
+ <UInput
631
+ v-model="editDraft.summary"
632
+ :placeholder="t('fragments.authored.summaryPlaceholder')"
633
+ />
634
+ <UTextarea
635
+ v-model="editDraft.body"
636
+ :placeholder="t('fragments.authored.bodyPlaceholder')"
637
+ :rows="4"
638
+ />
639
+ <UInput
640
+ v-model="editDraft.tags"
641
+ :placeholder="t('fragments.authored.tagsPlaceholder')"
642
+ />
643
+ <div class="flex gap-2">
644
+ <UButton
645
+ size="sm"
646
+ :disabled="!editValid"
647
+ :loading="rowBusy(`edit:${f.id}`)"
648
+ @click="saveEdit"
649
+ >
650
+ {{ t('common.save') }}
651
+ </UButton>
652
+ <UButton size="sm" variant="ghost" color="neutral" @click="cancelEdit">
653
+ {{ t('common.cancel') }}
654
+ </UButton>
655
+ </div>
656
+ </div>
657
+ <!-- Row -->
658
+ <div v-else class="flex items-start gap-2">
659
+ <div class="min-w-0">
660
+ <div class="flex items-center gap-2">
661
+ <span class="font-medium text-slate-100">{{ f.title }}</span>
662
+ <UBadge v-if="f.source" size="xs" color="info" variant="subtle">{{
663
+ t('fragments.authored.fromRepo')
664
+ }}</UBadge>
665
+ </div>
666
+ <p class="text-sm text-slate-400">{{ f.summary }}</p>
667
+ </div>
668
+ <div class="ms-auto flex gap-1">
669
+ <!-- Editing a repo-SOURCED fragment locally would be overwritten on the next sync,
670
+ so only hand-authored fragments are editable here. -->
671
+ <UButton
672
+ v-if="!f.source"
673
+ icon="i-lucide-pencil"
674
+ size="xs"
675
+ variant="ghost"
676
+ :title="t('common.edit')"
677
+ @click="startEdit(f)"
678
+ />
679
+ <UButton
680
+ icon="i-lucide-trash-2"
681
+ size="xs"
682
+ color="error"
683
+ variant="ghost"
684
+ :loading="rowBusy(`remove:${f.id}`)"
685
+ @click="removeFragment(f.id)"
686
+ />
533
687
  </div>
534
- <p class="text-sm text-slate-400">{{ f.summary }}</p>
535
688
  </div>
536
- <UButton
537
- icon="i-lucide-trash-2"
538
- size="xs"
539
- color="error"
540
- variant="ghost"
541
- class="ms-auto"
542
- :loading="rowBusy(`remove:${f.id}`)"
543
- @click="removeFragment(f.id)"
544
- />
545
689
  </div>
546
690
  <p v-if="!library.fragments.length" class="text-sm text-slate-500">
547
691
  {{
@@ -554,7 +698,33 @@ async function unlinkSource(id: string) {
554
698
  <div class="rounded-md border border-slate-800 p-3">
555
699
  <p class="mb-2 text-sm font-medium">{{ t('fragments.authored.addTitle') }}</p>
556
700
  <div class="flex flex-col gap-2">
557
- <UInput v-model="draft.title" :placeholder="t('fragments.authored.titlePlaceholder')" />
701
+ <div class="flex gap-2">
702
+ <UInput
703
+ v-model="draft.title"
704
+ :placeholder="t('fragments.authored.titlePlaceholder')"
705
+ class="flex-1"
706
+ />
707
+ <UButton
708
+ icon="i-lucide-wand-2"
709
+ size="sm"
710
+ variant="outline"
711
+ :disabled="!draft.body.trim()"
712
+ :loading="generatingTitleFor === 'create'"
713
+ :title="t('fragments.authored.generateTitleHint')"
714
+ data-testid="fragment-generate-title"
715
+ @click="
716
+ autofillTitle(
717
+ 'create',
718
+ () => ({ body: draft.body, summary: draft.summary }),
719
+ (title) => {
720
+ draft.title = title
721
+ },
722
+ )
723
+ "
724
+ >
725
+ {{ t('fragments.authored.generateTitle') }}
726
+ </UButton>
727
+ </div>
558
728
  <UInput
559
729
  v-model="draft.summary"
560
730
  :placeholder="t('fragments.authored.summaryPlaceholder')"
@@ -483,6 +483,17 @@ async function copyOutput() {
483
483
  it raised and the greenlight verdict; plus the fixer-loop phase -->
484
484
  <StepTestReport v-if="testReport" :report="testReport" :phase="testPhase" />
485
485
 
486
+ <!-- code/PR reviewer's best-practice adherence: per standard, a 1..10 rating of how
487
+ well the change adheres + the issues it surfaced. Only on a review step. -->
488
+ <StepFragmentAdherence
489
+ v-if="step.fragmentAdherence?.length"
490
+ :items="step.fragmentAdherence"
491
+ />
492
+
493
+ <!-- container agent's effort self-assessment (how hard it was, what reduced its
494
+ effectiveness, key obstacles). Only when the agent reported one. -->
495
+ <StepEffortReport v-if="step.effortReport" :report="step.effortReport" />
496
+
486
497
  <!-- edit-then-approve: a direct editor over the raw conclusions; the
487
498
  edits become the approved proposal that flows to the next step -->
488
499
  <section v-if="editing" class="scroll-mt-4">
@@ -0,0 +1,86 @@
1
+ <script setup lang="ts">
2
+ // The container agent's effort self-assessment, surfaced in run details: how hard the work was
3
+ // (1..10), what reduced its effectiveness, and the key obstacles it hit. Populated by the harness
4
+ // from the agent's sentinel file and recorded on the step (`step.effortReport`). Rendered only when
5
+ // present, so a run on an older harness image (or an agent that wrote none) shows nothing.
6
+ import type { AgentEffortReport } from '~/types/execution'
7
+
8
+ const props = defineProps<{ report: AgentEffortReport }>()
9
+ const { t } = useI18n()
10
+
11
+ // Clamp for the bar width; the schema already bounds 1..10 but be defensive against a stray value.
12
+ const difficultyPct = computed(() =>
13
+ Math.min(100, Math.max(0, (props.report.difficulty / 10) * 100)),
14
+ )
15
+ // Colour the difficulty by band: easy (emerald) → moderate (amber) → hard (rose).
16
+ const difficultyClass = computed(() =>
17
+ props.report.difficulty >= 8
18
+ ? 'bg-rose-400'
19
+ : props.report.difficulty >= 5
20
+ ? 'bg-amber-400'
21
+ : 'bg-emerald-400',
22
+ )
23
+ </script>
24
+
25
+ <template>
26
+ <section
27
+ data-testid="step-effort-report"
28
+ class="scroll-mt-4 rounded-xl border border-slate-800 bg-slate-900/50 p-4"
29
+ >
30
+ <div
31
+ class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-slate-400"
32
+ >
33
+ <UIcon name="i-lucide-gauge" class="h-3.5 w-3.5" />
34
+ <span>{{ t('panels.stepDetail.effort.heading') }}</span>
35
+ </div>
36
+
37
+ <div class="flex items-center gap-2">
38
+ <span class="text-[12px] text-slate-300">{{ t('panels.stepDetail.effort.difficulty') }}</span>
39
+ <div class="h-1.5 flex-1 overflow-hidden rounded-full bg-slate-700/60">
40
+ <div
41
+ class="h-full rounded-full"
42
+ :class="difficultyClass"
43
+ :style="{ width: `${difficultyPct}%` }"
44
+ />
45
+ </div>
46
+ <span data-testid="step-effort-difficulty" class="text-[12px] font-medium text-slate-200">
47
+ {{ t('panels.stepDetail.effort.outOfTen', { value: report.difficulty }) }}
48
+ </span>
49
+ </div>
50
+
51
+ <p
52
+ v-if="report.summary"
53
+ class="mt-2 whitespace-pre-wrap text-[13px] leading-relaxed text-slate-300"
54
+ >
55
+ {{ report.summary }}
56
+ </p>
57
+
58
+ <div v-if="report.reducedEffectiveness" class="mt-3">
59
+ <p class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">
60
+ {{ t('panels.stepDetail.effort.reduced') }}
61
+ </p>
62
+ <p class="mt-0.5 whitespace-pre-wrap text-[12px] text-slate-300">
63
+ {{ report.reducedEffectiveness }}
64
+ </p>
65
+ </div>
66
+
67
+ <div v-if="report.obstacles?.length" class="mt-3">
68
+ <p class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">
69
+ {{ t('panels.stepDetail.effort.obstacles') }}
70
+ </p>
71
+ <ul class="mt-0.5 space-y-1">
72
+ <li
73
+ v-for="(obstacle, i) in report.obstacles"
74
+ :key="i"
75
+ class="flex items-start gap-1.5 text-[12px] text-slate-300"
76
+ >
77
+ <UIcon
78
+ name="i-lucide-alert-triangle"
79
+ class="mt-0.5 h-3.5 w-3.5 shrink-0 text-amber-400/80"
80
+ />
81
+ <span>{{ obstacle }}</span>
82
+ </li>
83
+ </ul>
84
+ </div>
85
+ </section>
86
+ </template>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ // A code/PR review step's best-practice adherence report, surfaced in run details: for each
3
+ // best-practice standard (prompt fragment) folded into the reviewer's prompt, how well the reviewed
4
+ // change adheres (1..10) and the issues that standard surfaced. Recorded on the step
5
+ // (`step.fragmentAdherence`) by the engine from the review agent's output. Rendered only when the
6
+ // reviewer reported at least one standard; when none were reachable the reviewer says so in its
7
+ // summary instead (so there is nothing to show here).
8
+ import type { FragmentAdherence } from '~/types/execution'
9
+
10
+ const props = defineProps<{ items: FragmentAdherence }>()
11
+ const { t } = useI18n()
12
+
13
+ /** Rating band → bar colour: poor adherence (rose) → partial (amber) → strong (emerald). */
14
+ function ratingClass(rating: number): string {
15
+ return rating >= 8 ? 'bg-emerald-400' : rating >= 5 ? 'bg-amber-400' : 'bg-rose-400'
16
+ }
17
+ function ratingPct(rating: number): number {
18
+ return Math.min(100, Math.max(0, (rating / 10) * 100))
19
+ }
20
+ /** The label the reviewer was asked to cite the standard by: its title, else its id. */
21
+ function label(item: FragmentAdherence[number]): string {
22
+ return item.title?.trim() || item.fragmentId || t('panels.stepDetail.adherence.unnamed')
23
+ }
24
+ </script>
25
+
26
+ <template>
27
+ <section
28
+ v-if="items.length"
29
+ data-testid="step-fragment-adherence"
30
+ class="scroll-mt-4 rounded-xl border border-slate-800 bg-slate-900/50 p-4"
31
+ >
32
+ <div
33
+ class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-slate-400"
34
+ >
35
+ <UIcon name="i-lucide-clipboard-check" class="h-3.5 w-3.5" />
36
+ <span>{{ t('panels.stepDetail.adherence.heading') }}</span>
37
+ </div>
38
+
39
+ <div class="space-y-2.5">
40
+ <article
41
+ v-for="(item, i) in items"
42
+ :key="item.fragmentId ?? i"
43
+ data-testid="step-fragment-adherence-item"
44
+ class="rounded-lg border border-slate-800 bg-slate-900/60 px-3 py-2"
45
+ >
46
+ <div class="flex items-center gap-2">
47
+ <span class="min-w-0 flex-1 truncate text-[13px] font-medium text-slate-100">{{
48
+ label(item)
49
+ }}</span>
50
+ <div class="h-1.5 w-16 shrink-0 overflow-hidden rounded-full bg-slate-700/60">
51
+ <div
52
+ class="h-full rounded-full"
53
+ :class="ratingClass(item.rating)"
54
+ :style="{ width: `${ratingPct(item.rating)}%` }"
55
+ />
56
+ </div>
57
+ <span class="shrink-0 text-[12px] font-medium text-slate-200">
58
+ {{ t('panels.stepDetail.adherence.outOfTen', { value: item.rating }) }}
59
+ </span>
60
+ </div>
61
+ <p
62
+ v-if="item.assessment"
63
+ class="mt-1 whitespace-pre-wrap text-[12px] leading-relaxed text-slate-300"
64
+ >
65
+ {{ item.assessment }}
66
+ </p>
67
+ <div v-if="item.relatedFindings.length" class="mt-1.5">
68
+ <p class="text-[10px] font-semibold uppercase tracking-wide text-slate-500">
69
+ {{ t('panels.stepDetail.adherence.relatedFindings') }}
70
+ </p>
71
+ <ul class="mt-0.5 space-y-0.5">
72
+ <li
73
+ v-for="(finding, fi) in item.relatedFindings"
74
+ :key="fi"
75
+ class="flex items-start gap-1.5 text-[11px] text-slate-400"
76
+ >
77
+ <UIcon name="i-lucide-dot" class="mt-0.5 h-3.5 w-3.5 shrink-0" />
78
+ <span>{{ finding }}</span>
79
+ </li>
80
+ </ul>
81
+ </div>
82
+ </article>
83
+ </div>
84
+ </section>
85
+ </template>
@@ -466,6 +466,14 @@ async function onDismiss(id: string): Promise<void> {
466
466
  {{ state.summary }}
467
467
  </p>
468
468
 
469
+ <!-- Best-practice adherence: per standard folded into the reviewer's prompt, a 1..10
470
+ rating of how well the PR adheres + the issues that standard surfaced. -->
471
+ <StepFragmentAdherence
472
+ v-if="step?.fragmentAdherence?.length"
473
+ :items="step.fragmentAdherence"
474
+ class="mb-3"
475
+ />
476
+
469
477
  <!-- A clean PR / resolved review with no findings. -->
470
478
  <div
471
479
  v-if="findings.length === 0"
@@ -3,6 +3,7 @@ import {
3
3
  createPromptFragmentContract,
4
4
  deletePromptFragmentContract,
5
5
  fragmentSourceStatusContract,
6
+ generatePromptFragmentTitleContract,
6
7
  linkFragmentSourceContract,
7
8
  listFragmentCatalogContract,
8
9
  listFragmentSourcesContract,
@@ -17,6 +18,7 @@ import type {
17
18
  CreateDocumentFragmentInput,
18
19
  CreatePromptFragmentInput,
19
20
  FragmentOwnerKind,
21
+ GenerateFragmentTitleInput,
20
22
  LinkFragmentSourceInput,
21
23
  UpdatePromptFragmentInput,
22
24
  } from '~/types/domain'
@@ -58,6 +60,21 @@ export function fragmentsApi({ send, ws, scope }: ApiContext) {
58
60
  pathParams: { fragmentId },
59
61
  }),
60
62
 
63
+ // Auto-generate a title for a hand-authored fragment from its content (an inline LLM call).
64
+ // At the account scope the backend resolves the model against `viaWorkspaceId`'s scope;
65
+ // ignored at the workspace scope (which uses the addressed workspace).
66
+ generateFragmentTitle: (
67
+ kind: FragmentOwnerKind,
68
+ id: string,
69
+ body: GenerateFragmentTitleInput,
70
+ viaWorkspaceId?: string,
71
+ ) =>
72
+ send(generatePromptFragmentTitleContract, {
73
+ pathPrefix: scope(kind, id),
74
+ queryParams: { viaWorkspaceId },
75
+ body,
76
+ }),
77
+
61
78
  // Link an external document (Confluence/Notion/GitHub) as a living fragment.
62
79
  createDocumentFragment: (
63
80
  kind: FragmentOwnerKind,
@@ -111,6 +111,21 @@ function fragmentLibrarySetup(kind: FragmentOwnerKind, resolveOwnerId: () => str
111
111
  await Promise.all([reloadTier(), refreshResolved()])
112
112
  }
113
113
 
114
+ /**
115
+ * Auto-generate a title for a fragment from its content (an inline LLM call). Returns the
116
+ * suggested title for the caller to drop into the editor; performs no write. At the account
117
+ * scope the model resolves against `viaWorkspaceId`'s credential scope.
118
+ */
119
+ async function generateTitle(input: { body: string; summary?: string }): Promise<string> {
120
+ const { title } = await api.generateFragmentTitle(
121
+ kind,
122
+ requireOwnerId(),
123
+ input,
124
+ viaWorkspaceId.value,
125
+ )
126
+ return title
127
+ }
128
+
114
129
  /** Link an external document as a living (dynamically-resolved) fragment. */
115
130
  async function createDocumentFragment(input: CreateDocumentFragmentInput) {
116
131
  loading.value = true
@@ -203,6 +218,7 @@ function fragmentLibrarySetup(kind: FragmentOwnerKind, resolveOwnerId: () => str
203
218
  createDocumentFragment,
204
219
  refreshDocumentFragment,
205
220
  update,
221
+ generateTitle,
206
222
  remove,
207
223
  linkSource,
208
224
  unlinkSource,
@@ -52,6 +52,9 @@ export type {
52
52
  PrReviewResolution,
53
53
  PrReviewPostReport,
54
54
  PrReviewPostFailure,
55
+ AgentEffortReport,
56
+ FragmentAdherence,
57
+ FragmentAdherenceItem,
55
58
  GateFailingCheck,
56
59
  GateAttempt,
57
60
  GateStepState,
@@ -11,6 +11,8 @@ export type {
11
11
  FragmentTier,
12
12
  CreatePromptFragmentInput,
13
13
  UpdatePromptFragmentInput,
14
+ GenerateFragmentTitleInput,
15
+ GeneratedFragmentTitle,
14
16
  CreateDocumentFragmentInput,
15
17
  ResolvedFragment,
16
18
  FragmentSource,
@@ -1476,7 +1476,20 @@
1476
1476
  "confirmReject": "Ablehnung bestätigen",
1477
1477
  "requestChanges": "Änderungen anfordern",
1478
1478
  "reject": "Ablehnen",
1479
- "requestChangesHint": "Änderungen anfordern führt diesen Schritt mit deinem Feedback & deinen Kommentaren erneut aus. Ablehnen stoppt den Lauf vollständig."
1479
+ "requestChangesHint": "Änderungen anfordern führt diesen Schritt mit deinem Feedback & deinen Kommentaren erneut aus. Ablehnen stoppt den Lauf vollständig.",
1480
+ "effort": {
1481
+ "heading": "Agenten-Aufwand",
1482
+ "difficulty": "Schwierigkeit",
1483
+ "outOfTen": "{value}/10",
1484
+ "reduced": "Was die Effektivität verringert hat",
1485
+ "obstacles": "Wichtigste Hindernisse"
1486
+ },
1487
+ "adherence": {
1488
+ "heading": "Einhaltung der Best Practices",
1489
+ "outOfTen": "{value}/10",
1490
+ "relatedFindings": "Zugehörige Befunde",
1491
+ "unnamed": "Standard"
1492
+ }
1480
1493
  },
1481
1494
  "inspector": {
1482
1495
  "frameStatus": {
@@ -3565,7 +3578,10 @@
3565
3578
  "summaryPlaceholder": "Einzeilige Zusammenfassung (vom Selektor verwendet)",
3566
3579
  "bodyPlaceholder": "Richtlinientext (in den Prompt injiziert)",
3567
3580
  "tagsPlaceholder": "Tags, kommagetrennt (z. B. backend, db)",
3568
- "add": "Fragment hinzufügen"
3581
+ "add": "Fragment hinzufügen",
3582
+ "generateTitle": "Generieren",
3583
+ "generateTitleHint": "Titel aus dem Inhalt des Fragments vorschlagen",
3584
+ "titleGenFailed": "Titel konnte nicht generiert werden"
3569
3585
  },
3570
3586
  "documents": {
3571
3587
  "intro": "Verknüpfen Sie eine Confluence-/Notion-Seite oder eine GitHub-Datei als Best-Practice-Fragment. Ihre Richtlinie wird zur Laufzeit aus der Quelle neu aufgelöst: Bearbeiten Sie das Dokument, und der nächste Agentenlauf folgt der neuen Version (kein erneuter Import).",
@@ -3615,7 +3631,9 @@
3615
3631
  "checkSourceFailed": "Quelle konnte nicht geprüft werden",
3616
3632
  "sourceUnlinked": "Quelle-Verknüpfung aufgehoben",
3617
3633
  "unlinkSourceFailed": "Quelle-Verknüpfung konnte nicht aufgehoben werden",
3618
- "documentsLinked": "{count} Dokument als lebendes Fragment verknüpft | {count} Dokumente als lebende Fragmente verknüpft"
3634
+ "documentsLinked": "{count} Dokument als lebendes Fragment verknüpft | {count} Dokumente als lebende Fragmente verknüpft",
3635
+ "updated": "Fragment aktualisiert",
3636
+ "updateFailed": "Fragment konnte nicht aktualisiert werden"
3619
3637
  },
3620
3638
  "confirmRemove": {
3621
3639
  "title": "Dieses Fragment löschen?",
@@ -3984,7 +4002,8 @@
3984
4002
  "body": "Du hast Änderungen vorgenommen, die noch nicht gespeichert wurden. Schließen und verlieren?",
3985
4003
  "confirm": "Verwerfen",
3986
4004
  "keep": "Weiter bearbeiten"
3987
- }
4005
+ },
4006
+ "edit": "Bearbeiten"
3988
4007
  },
3989
4008
  "access": {
3990
4009
  "noBoardWrite": "Nur-Lese-Zugriff: Sie können dieses Board ansehen, aber nicht bearbeiten.",
@@ -82,7 +82,8 @@
82
82
  "body": "You've made changes that haven't been saved. Close this and lose them?",
83
83
  "confirm": "Discard",
84
84
  "keep": "Keep editing"
85
- }
85
+ },
86
+ "edit": "Edit"
86
87
  },
87
88
  "access": {
88
89
  "noBoardWrite": "Read-only access: you can view this board but can't edit it.",
@@ -1251,7 +1252,20 @@
1251
1252
  "confirmReject": "Confirm reject",
1252
1253
  "requestChanges": "Request changes",
1253
1254
  "reject": "Reject",
1254
- "requestChangesHint": "Request changes re-runs this step with your feedback & comments. Reject stops the run entirely."
1255
+ "requestChangesHint": "Request changes re-runs this step with your feedback & comments. Reject stops the run entirely.",
1256
+ "effort": {
1257
+ "heading": "Agent effort",
1258
+ "difficulty": "Difficulty",
1259
+ "outOfTen": "{value}/10",
1260
+ "reduced": "What reduced effectiveness",
1261
+ "obstacles": "Key obstacles"
1262
+ },
1263
+ "adherence": {
1264
+ "heading": "Best-practice adherence",
1265
+ "outOfTen": "{value}/10",
1266
+ "relatedFindings": "Related findings",
1267
+ "unnamed": "Standard"
1268
+ }
1255
1269
  },
1256
1270
  "inspector": {
1257
1271
  "frameStatus": {
@@ -4565,7 +4579,10 @@
4565
4579
  "summaryPlaceholder": "One-line summary (used by the selector)",
4566
4580
  "bodyPlaceholder": "Guidance body (injected into the prompt)",
4567
4581
  "tagsPlaceholder": "Tags, comma-separated (e.g. backend, db)",
4568
- "add": "Add fragment"
4582
+ "add": "Add fragment",
4583
+ "generateTitle": "Generate",
4584
+ "generateTitleHint": "Suggest a title from the fragment's content",
4585
+ "titleGenFailed": "Couldn't generate a title"
4569
4586
  },
4570
4587
  "documents": {
4571
4588
  "intro": "Link a Confluence/Notion page or a GitHub file as a best-practice fragment. Its guidance is re-resolved from the source at run time: edit the doc and the next agent run follows the new version (no re-import).",
@@ -4615,7 +4632,9 @@
4615
4632
  "checkSourceFailed": "Could not check source",
4616
4633
  "sourceUnlinked": "Source unlinked",
4617
4634
  "unlinkSourceFailed": "Could not unlink source",
4618
- "documentsLinked": "Linked {count} document as a living fragment | Linked {count} documents as living fragments"
4635
+ "documentsLinked": "Linked {count} document as a living fragment | Linked {count} documents as living fragments",
4636
+ "updated": "Fragment updated",
4637
+ "updateFailed": "Couldn't update the fragment"
4619
4638
  },
4620
4639
  "confirmRemove": {
4621
4640
  "title": "Delete this fragment?",
@@ -73,7 +73,8 @@
73
73
  "body": "Has hecho cambios que no se han guardado. ¿Cerrar y perderlos?",
74
74
  "confirm": "Descartar",
75
75
  "keep": "Seguir editando"
76
- }
76
+ },
77
+ "edit": "Editar"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "Acceso de solo lectura: puedes ver este tablero pero no editarlo.",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "Confirmar rechazo",
1195
1196
  "requestChanges": "Solicitar cambios",
1196
1197
  "reject": "Rechazar",
1197
- "requestChangesHint": "Solicitar cambios vuelve a ejecutar este paso con tus comentarios y observaciones. Rechazar detiene la ejecución por completo."
1198
+ "requestChangesHint": "Solicitar cambios vuelve a ejecutar este paso con tus comentarios y observaciones. Rechazar detiene la ejecución por completo.",
1199
+ "effort": {
1200
+ "heading": "Esfuerzo del agente",
1201
+ "difficulty": "Dificultad",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "Qué redujo la efectividad",
1204
+ "obstacles": "Obstáculos clave"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "Cumplimiento de buenas prácticas",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "Hallazgos relacionados",
1210
+ "unnamed": "Estándar"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4389,7 +4403,10 @@
4389
4403
  "summaryPlaceholder": "Resumen de una línea (usado por el selector)",
4390
4404
  "bodyPlaceholder": "Cuerpo de la guía (inyectado en el prompt)",
4391
4405
  "tagsPlaceholder": "Etiquetas, separadas por comas (p. ej., backend, db)",
4392
- "add": "Añadir fragmento"
4406
+ "add": "Añadir fragmento",
4407
+ "generateTitle": "Generar",
4408
+ "generateTitleHint": "Sugerir un título a partir del contenido del fragmento",
4409
+ "titleGenFailed": "No se pudo generar un título"
4393
4410
  },
4394
4411
  "documents": {
4395
4412
  "intro": "Vincula una página de Confluence/Notion o un archivo de GitHub como fragmento de buenas prácticas. Su guía se vuelve a resolver desde la fuente en tiempo de ejecución: edita el documento y la siguiente ejecución del agente sigue la nueva versión (sin reimportar).",
@@ -4439,7 +4456,9 @@
4439
4456
  "checkSourceFailed": "No se pudo comprobar el origen",
4440
4457
  "sourceUnlinked": "Origen desvinculado",
4441
4458
  "unlinkSourceFailed": "No se pudo desvincular el origen",
4442
- "documentsLinked": "{count} documento vinculado como fragmento vivo | {count} documentos vinculados como fragmentos vivos"
4459
+ "documentsLinked": "{count} documento vinculado como fragmento vivo | {count} documentos vinculados como fragmentos vivos",
4460
+ "updated": "Fragmento actualizado",
4461
+ "updateFailed": "No se pudo actualizar el fragmento"
4443
4462
  },
4444
4463
  "confirmRemove": {
4445
4464
  "title": "¿Eliminar este fragmento?",
@@ -73,7 +73,8 @@
73
73
  "body": "Vous avez effectué des modifications non enregistrées. Fermer et les perdre ?",
74
74
  "confirm": "Ignorer",
75
75
  "keep": "Continuer l'édition"
76
- }
76
+ },
77
+ "edit": "Modifier"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "Accès en lecture seule : vous pouvez consulter ce tableau mais pas le modifier.",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "Confirmer le rejet",
1195
1196
  "requestChanges": "Demander des modifications",
1196
1197
  "reject": "Rejeter",
1197
- "requestChangesHint": "Demander des modifications relance cette étape avec votre retour et vos commentaires. Rejeter arrête complètement l'exécution."
1198
+ "requestChangesHint": "Demander des modifications relance cette étape avec votre retour et vos commentaires. Rejeter arrête complètement l'exécution.",
1199
+ "effort": {
1200
+ "heading": "Effort de l'agent",
1201
+ "difficulty": "Difficulté",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "Ce qui a réduit l'efficacité",
1204
+ "obstacles": "Principaux obstacles"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "Respect des bonnes pratiques",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "Constats associés",
1210
+ "unnamed": "Standard"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4389,7 +4403,10 @@
4389
4403
  "summaryPlaceholder": "Résumé en une ligne (utilisé par le sélecteur)",
4390
4404
  "bodyPlaceholder": "Corps de la consigne (injecté dans le prompt)",
4391
4405
  "tagsPlaceholder": "Étiquettes, séparées par des virgules (par ex. backend, db)",
4392
- "add": "Ajouter le fragment"
4406
+ "add": "Ajouter le fragment",
4407
+ "generateTitle": "Générer",
4408
+ "generateTitleHint": "Proposer un titre à partir du contenu du fragment",
4409
+ "titleGenFailed": "Impossible de générer un titre"
4393
4410
  },
4394
4411
  "documents": {
4395
4412
  "intro": "Liez une page Confluence/Notion ou un fichier GitHub comme fragment de bonnes pratiques. Sa consigne est re-résolue depuis la source à l'exécution : modifiez le document et la prochaine exécution d'agent suit la nouvelle version (sans réimport).",
@@ -4439,7 +4456,9 @@
4439
4456
  "checkSourceFailed": "Impossible de vérifier la source",
4440
4457
  "sourceUnlinked": "Source dissociée",
4441
4458
  "unlinkSourceFailed": "Impossible de dissocier la source",
4442
- "documentsLinked": "{count} document lié comme fragment vivant | {count} documents liés comme fragments vivants"
4459
+ "documentsLinked": "{count} document lié comme fragment vivant | {count} documents liés comme fragments vivants",
4460
+ "updated": "Fragment mis à jour",
4461
+ "updateFailed": "Impossible de mettre à jour le fragment"
4443
4462
  },
4444
4463
  "confirmRemove": {
4445
4464
  "title": "Supprimer ce fragment ?",
@@ -73,7 +73,8 @@
73
73
  "body": "ביצעת שינויים שלא נשמרו. לסגור ולאבד אותם?",
74
74
  "confirm": "לבטל",
75
75
  "keep": "להמשיך לערוך"
76
- }
76
+ },
77
+ "edit": "עריכה"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "גישת קריאה בלבד: אפשר לצפות בלוח הזה אך לא לערוך אותו.",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "אשר דחייה",
1195
1196
  "requestChanges": "בקש שינויים",
1196
1197
  "reject": "דחה",
1197
- "requestChangesHint": "בקשת שינויים מריצה מחדש שלב זה עם המשוב וההערות שלך. דחייה עוצרת את הריצה לחלוטין."
1198
+ "requestChangesHint": "בקשת שינויים מריצה מחדש שלב זה עם המשוב וההערות שלך. דחייה עוצרת את הריצה לחלוטין.",
1199
+ "effort": {
1200
+ "heading": "מאמץ הסוכן",
1201
+ "difficulty": "רמת קושי",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "מה הפחית את היעילות",
1204
+ "obstacles": "מכשולים עיקריים"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "עמידה בשיטות עבודה מומלצות",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "ממצאים קשורים",
1210
+ "unnamed": "תקן"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4400,7 +4414,10 @@
4400
4414
  "summaryPlaceholder": "תקציר בשורה אחת (בשימוש הבורר)",
4401
4415
  "bodyPlaceholder": "גוף ההנחיה (מוזרק לפרומפט)",
4402
4416
  "tagsPlaceholder": "תגיות, מופרדות בפסיקים (למשל backend, db)",
4403
- "add": "הוסף מקטע"
4417
+ "add": "הוסף מקטע",
4418
+ "generateTitle": "יצירה",
4419
+ "generateTitleHint": "הצעת כותרת לפי תוכן הקטע",
4420
+ "titleGenFailed": "לא ניתן היה ליצור כותרת"
4404
4421
  },
4405
4422
  "documents": {
4406
4423
  "intro": "קשר עמוד Confluence/Notion או קובץ GitHub כמקטע מומלץ. ההנחיה שלו מיושבת מחדש מהמקור בזמן ההרצה: ערוך את המסמך וההרצה הבאה עוקבת אחר הגרסה החדשה (ללא ייבוא מחדש).",
@@ -4450,7 +4467,9 @@
4450
4467
  "checkSourceFailed": "לא ניתן היה לבדוק את המקור",
4451
4468
  "sourceUnlinked": "קישור המקור בוטל",
4452
4469
  "unlinkSourceFailed": "לא ניתן היה לבטל את קישור המקור",
4453
- "documentsLinked": "{count} מסמך קושר כמקטע חי | {count} מסמכים קושרו כמקטעים חיים"
4470
+ "documentsLinked": "{count} מסמך קושר כמקטע חי | {count} מסמכים קושרו כמקטעים חיים",
4471
+ "updated": "הקטע עודכן",
4472
+ "updateFailed": "לא ניתן היה לעדכן את הקטע"
4454
4473
  },
4455
4474
  "confirmRemove": {
4456
4475
  "title": "למחוק את המקטע הזה?",
@@ -1476,7 +1476,20 @@
1476
1476
  "confirmReject": "Conferma il rifiuto",
1477
1477
  "requestChanges": "Richiedi modifiche",
1478
1478
  "reject": "Rifiuta",
1479
- "requestChangesHint": "Richiedi modifiche riesegue questo passaggio con il tuo feedback e i tuoi commenti. Rifiuta arresta completamente l'esecuzione."
1479
+ "requestChangesHint": "Richiedi modifiche riesegue questo passaggio con il tuo feedback e i tuoi commenti. Rifiuta arresta completamente l'esecuzione.",
1480
+ "effort": {
1481
+ "heading": "Sforzo dell'agente",
1482
+ "difficulty": "Difficoltà",
1483
+ "outOfTen": "{value}/10",
1484
+ "reduced": "Cosa ha ridotto l'efficacia",
1485
+ "obstacles": "Ostacoli principali"
1486
+ },
1487
+ "adherence": {
1488
+ "heading": "Aderenza alle best practice",
1489
+ "outOfTen": "{value}/10",
1490
+ "relatedFindings": "Rilievi correlati",
1491
+ "unnamed": "Standard"
1492
+ }
1480
1493
  },
1481
1494
  "inspector": {
1482
1495
  "frameStatus": {
@@ -3565,7 +3578,10 @@
3565
3578
  "summaryPlaceholder": "Riepilogo su una riga (usato dal selettore)",
3566
3579
  "bodyPlaceholder": "Corpo delle indicazioni (iniettato nel prompt)",
3567
3580
  "tagsPlaceholder": "Tag, separati da virgola (es. backend, db)",
3568
- "add": "Aggiungi frammento"
3581
+ "add": "Aggiungi frammento",
3582
+ "generateTitle": "Genera",
3583
+ "generateTitleHint": "Suggerisci un titolo dal contenuto del frammento",
3584
+ "titleGenFailed": "Impossibile generare un titolo"
3569
3585
  },
3570
3586
  "documents": {
3571
3587
  "intro": "Collega una pagina Confluence/Notion o un file GitHub come frammento di best practice. Le sue indicazioni vengono ri-risolte dalla sorgente in fase di esecuzione: modifica il documento e la successiva esecuzione dell'agente seguira la nuova versione (nessuna re-importazione).",
@@ -3615,7 +3631,9 @@
3615
3631
  "checkSourceFailed": "Impossibile controllare la sorgente",
3616
3632
  "sourceUnlinked": "Sorgente scollegata",
3617
3633
  "unlinkSourceFailed": "Impossibile scollegare la sorgente",
3618
- "documentsLinked": "{count} documento collegato come frammento vivente | {count} documenti collegati come frammenti viventi"
3634
+ "documentsLinked": "{count} documento collegato come frammento vivente | {count} documenti collegati come frammenti viventi",
3635
+ "updated": "Frammento aggiornato",
3636
+ "updateFailed": "Impossibile aggiornare il frammento"
3619
3637
  },
3620
3638
  "confirmRemove": {
3621
3639
  "title": "Eliminare questo frammento?",
@@ -3984,7 +4002,8 @@
3984
4002
  "body": "Hai apportato modifiche non salvate. Chiudere e perderle?",
3985
4003
  "confirm": "Ignora",
3986
4004
  "keep": "Continua a modificare"
3987
- }
4005
+ },
4006
+ "edit": "Modifica"
3988
4007
  },
3989
4008
  "access": {
3990
4009
  "noBoardWrite": "Accesso in sola lettura: puoi visualizzare questa board ma non modificarla.",
@@ -73,7 +73,8 @@
73
73
  "body": "保存されていない変更があります。閉じて破棄しますか?",
74
74
  "confirm": "破棄",
75
75
  "keep": "編集を続ける"
76
- }
76
+ },
77
+ "edit": "編集"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "読み取り専用アクセス: このボードは閲覧できますが編集はできません。",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "却下を確定",
1195
1196
  "requestChanges": "変更を依頼",
1196
1197
  "reject": "却下",
1197
- "requestChangesHint": "変更を依頼すると、フィードバックとコメントを反映してこのステップを再実行します。却下すると実行を完全に停止します。"
1198
+ "requestChangesHint": "変更を依頼すると、フィードバックとコメントを反映してこのステップを再実行します。却下すると実行を完全に停止します。",
1199
+ "effort": {
1200
+ "heading": "エージェントの労力",
1201
+ "difficulty": "難易度",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "効果を下げた要因",
1204
+ "obstacles": "主な障害"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "ベストプラクティスの遵守",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "関連する指摘",
1210
+ "unnamed": "基準"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4401,7 +4415,10 @@
4401
4415
  "summaryPlaceholder": "1行の要約 (セレクターで使用)",
4402
4416
  "bodyPlaceholder": "ガイダンス本文 (プロンプトに挿入)",
4403
4417
  "tagsPlaceholder": "タグ、カンマ区切り (例: backend, db)",
4404
- "add": "フラグメントを追加"
4418
+ "add": "フラグメントを追加",
4419
+ "generateTitle": "生成",
4420
+ "generateTitleHint": "フラグメントの内容からタイトルを提案",
4421
+ "titleGenFailed": "タイトルを生成できませんでした"
4405
4422
  },
4406
4423
  "documents": {
4407
4424
  "intro": "Confluence/Notion ページまたは GitHub ファイルをベストプラクティスのフラグメントとしてリンクします。そのガイダンスは実行時にソースから再解決されます。ドキュメントを編集すると、次のエージェント実行は新しいバージョンに従います (再インポート不要)。",
@@ -4451,7 +4468,9 @@
4451
4468
  "checkSourceFailed": "ソースを確認できませんでした",
4452
4469
  "sourceUnlinked": "ソースのリンクを解除しました",
4453
4470
  "unlinkSourceFailed": "ソースのリンクを解除できませんでした",
4454
- "documentsLinked": "{count}件のドキュメントをリビングフラグメントとしてリンクしました | {count}件のドキュメントをリビングフラグメントとしてリンクしました"
4471
+ "documentsLinked": "{count}件のドキュメントをリビングフラグメントとしてリンクしました | {count}件のドキュメントをリビングフラグメントとしてリンクしました",
4472
+ "updated": "フラグメントを更新しました",
4473
+ "updateFailed": "フラグメントを更新できませんでした"
4455
4474
  },
4456
4475
  "confirmRemove": {
4457
4476
  "title": "このフラグメントを削除しますか?",
@@ -73,7 +73,8 @@
73
73
  "body": "Masz niezapisane zmiany. Zamknąć i je utracić?",
74
74
  "confirm": "Odrzuć",
75
75
  "keep": "Kontynuuj edycję"
76
- }
76
+ },
77
+ "edit": "Edytuj"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "Dostęp tylko do odczytu: możesz przeglądać tę tablicę, ale nie możesz jej edytować.",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "Potwierdź odrzucenie",
1195
1196
  "requestChanges": "Zażądaj zmian",
1196
1197
  "reject": "Odrzuć",
1197
- "requestChangesHint": "Zażądanie zmian uruchamia ten krok ponownie z Twoją opinią i komentarzami. Odrzucenie całkowicie zatrzymuje uruchomienie."
1198
+ "requestChangesHint": "Zażądanie zmian uruchamia ten krok ponownie z Twoją opinią i komentarzami. Odrzucenie całkowicie zatrzymuje uruchomienie.",
1199
+ "effort": {
1200
+ "heading": "Wysiłek agenta",
1201
+ "difficulty": "Trudność",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "Co obniżyło skuteczność",
1204
+ "obstacles": "Kluczowe przeszkody"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "Zgodność z najlepszymi praktykami",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "Powiązane ustalenia",
1210
+ "unnamed": "Standard"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4389,7 +4403,10 @@
4389
4403
  "summaryPlaceholder": "Jednowierszowe podsumowanie (używane przez selektor)",
4390
4404
  "bodyPlaceholder": "Treść wytycznej (wstrzykiwana do promptu)",
4391
4405
  "tagsPlaceholder": "Tagi, oddzielone przecinkami (np. backend, db)",
4392
- "add": "Dodaj fragment"
4406
+ "add": "Dodaj fragment",
4407
+ "generateTitle": "Generuj",
4408
+ "generateTitleHint": "Zaproponuj tytuł na podstawie treści fragmentu",
4409
+ "titleGenFailed": "Nie udało się wygenerować tytułu"
4393
4410
  },
4394
4411
  "documents": {
4395
4412
  "intro": "Połącz stronę Confluence/Notion lub plik GitHub jako fragment najlepszych praktyk. Jego wytyczna jest ponownie pobierana ze źródła w czasie uruchomienia: zmień dokument, a następne uruchomienie agenta podąży za nową wersją (bez ponownego importu).",
@@ -4439,7 +4456,9 @@
4439
4456
  "checkSourceFailed": "Nie udało się sprawdzić źródła",
4440
4457
  "sourceUnlinked": "Odłączono źródło",
4441
4458
  "unlinkSourceFailed": "Nie udało się odłączyć źródła",
4442
- "documentsLinked": "Połączono {count} dokument jako żywy fragment | Połączono {count} dokumenty jako żywe fragmenty | Połączono {count} dokumentów jako żywe fragmenty"
4459
+ "documentsLinked": "Połączono {count} dokument jako żywy fragment | Połączono {count} dokumenty jako żywe fragmenty | Połączono {count} dokumentów jako żywe fragmenty",
4460
+ "updated": "Zaktualizowano fragment",
4461
+ "updateFailed": "Nie udało się zaktualizować fragmentu"
4443
4462
  },
4444
4463
  "confirmRemove": {
4445
4464
  "title": "Usunąć ten fragment?",
@@ -73,7 +73,8 @@
73
73
  "body": "Kaydedilmemiş değişiklikleriniz var. Kapatıp bunları kaybedecek misiniz?",
74
74
  "confirm": "At",
75
75
  "keep": "Düzenlemeye devam et"
76
- }
76
+ },
77
+ "edit": "Düzenle"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "Salt okunur erişim: bu panoyu görüntüleyebilirsiniz ancak düzenleyemezsiniz.",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "Reddetmeyi onayla",
1195
1196
  "requestChanges": "Değişiklik iste",
1196
1197
  "reject": "Reddet",
1197
- "requestChangesHint": "Değişiklik iste bu adımı geri bildiriminiz ve yorumlarınızla yeniden çalıştırır. Reddet çalıştırmayı tamamen durdurur."
1198
+ "requestChangesHint": "Değişiklik iste bu adımı geri bildiriminiz ve yorumlarınızla yeniden çalıştırır. Reddet çalıştırmayı tamamen durdurur.",
1199
+ "effort": {
1200
+ "heading": "Aracı eforu",
1201
+ "difficulty": "Zorluk",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "Etkinliği azaltan etkenler",
1204
+ "obstacles": "Başlıca engeller"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "En iyi uygulamalara uyum",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "İlgili bulgular",
1210
+ "unnamed": "Standart"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4401,7 +4415,10 @@
4401
4415
  "summaryPlaceholder": "Tek satırlık özet (seçici tarafından kullanılır)",
4402
4416
  "bodyPlaceholder": "Yönerge gövdesi (prompt'a enjekte edilir)",
4403
4417
  "tagsPlaceholder": "Etiketler, virgülle ayrılmış (örn. backend, db)",
4404
- "add": "Parça ekle"
4418
+ "add": "Parça ekle",
4419
+ "generateTitle": "Oluştur",
4420
+ "generateTitleHint": "Parça içeriğinden bir başlık öner",
4421
+ "titleGenFailed": "Başlık oluşturulamadı"
4405
4422
  },
4406
4423
  "documents": {
4407
4424
  "intro": "Bir Confluence/Notion sayfasını veya GitHub dosyasını en iyi uygulama parçası olarak bağlayın. Yönergesi, çalıştırma sırasında kaynaktan yeniden çözümlenir: belgeyi düzenleyin ve sonraki aracı çalıştırması yeni sürümü izlesin (yeniden içe aktarma yok).",
@@ -4451,7 +4468,9 @@
4451
4468
  "checkSourceFailed": "Kaynak denetlenemedi",
4452
4469
  "sourceUnlinked": "Kaynak bağlantısı kaldırıldı",
4453
4470
  "unlinkSourceFailed": "Kaynak bağlantısı kaldırılamadı",
4454
- "documentsLinked": "{count} belge canlı parça olarak bağlandı | {count} belge canlı parça olarak bağlandı"
4471
+ "documentsLinked": "{count} belge canlı parça olarak bağlandı | {count} belge canlı parça olarak bağlandı",
4472
+ "updated": "Parça güncellendi",
4473
+ "updateFailed": "Parça güncellenemedi"
4455
4474
  },
4456
4475
  "confirmRemove": {
4457
4476
  "title": "Bu parça silinsin mi?",
@@ -73,7 +73,8 @@
73
73
  "body": "Ви внесли зміни, які не збережено. Закрити та втратити їх?",
74
74
  "confirm": "Відхилити",
75
75
  "keep": "Продовжити редагування"
76
- }
76
+ },
77
+ "edit": "Редагувати"
77
78
  },
78
79
  "access": {
79
80
  "noBoardWrite": "Доступ лише для перегляду: ви можете переглядати цю дошку, але не можете її редагувати.",
@@ -1194,7 +1195,20 @@
1194
1195
  "confirmReject": "Підтвердити відхилення",
1195
1196
  "requestChanges": "Запросити зміни",
1196
1197
  "reject": "Відхилити",
1197
- "requestChangesHint": "Запит змін перезапускає цей крок з вашим відгуком і коментарями. Відхилення повністю зупиняє запуск."
1198
+ "requestChangesHint": "Запит змін перезапускає цей крок з вашим відгуком і коментарями. Відхилення повністю зупиняє запуск.",
1199
+ "effort": {
1200
+ "heading": "Зусилля агента",
1201
+ "difficulty": "Складність",
1202
+ "outOfTen": "{value}/10",
1203
+ "reduced": "Що знизило ефективність",
1204
+ "obstacles": "Основні перешкоди"
1205
+ },
1206
+ "adherence": {
1207
+ "heading": "Дотримання найкращих практик",
1208
+ "outOfTen": "{value}/10",
1209
+ "relatedFindings": "Пов’язані зауваження",
1210
+ "unnamed": "Стандарт"
1211
+ }
1198
1212
  },
1199
1213
  "inspector": {
1200
1214
  "frameStatus": {
@@ -4389,7 +4403,10 @@
4389
4403
  "summaryPlaceholder": "Однорядковий підсумок (використовується селектором)",
4390
4404
  "bodyPlaceholder": "Текст настанови (вставляється у промпт)",
4391
4405
  "tagsPlaceholder": "Теги, розділені комами (напр. backend, db)",
4392
- "add": "Додати фрагмент"
4406
+ "add": "Додати фрагмент",
4407
+ "generateTitle": "Згенерувати",
4408
+ "generateTitleHint": "Запропонувати назву за вмістом фрагмента",
4409
+ "titleGenFailed": "Не вдалося згенерувати назву"
4393
4410
  },
4394
4411
  "documents": {
4395
4412
  "intro": "Прив'яжіть сторінку Confluence/Notion або файл GitHub як фрагмент найкращих практик. Його настанова повторно розв'язується з джерела під час запуску: відредагуйте документ, і наступний запуск агента дотримуватиметься нової версії (без повторного імпорту).",
@@ -4439,7 +4456,9 @@
4439
4456
  "checkSourceFailed": "Не вдалося перевірити джерело",
4440
4457
  "sourceUnlinked": "Джерело відв'язано",
4441
4458
  "unlinkSourceFailed": "Не вдалося відв'язати джерело",
4442
- "documentsLinked": "Прив’язано {count} документ як живий фрагмент | Прив’язано {count} документи як живі фрагменти | Прив’язано {count} документів як живі фрагменти"
4459
+ "documentsLinked": "Прив’язано {count} документ як живий фрагмент | Прив’язано {count} документи як живі фрагменти | Прив’язано {count} документів як живі фрагменти",
4460
+ "updated": "Фрагмент оновлено",
4461
+ "updateFailed": "Не вдалося оновити фрагмент"
4443
4462
  },
4444
4463
  "confirmRemove": {
4445
4464
  "title": "Видалити цей фрагмент?",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.148.1",
3
+ "version": "0.149.0",
4
4
  "description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,7 +40,7 @@
40
40
  "valibot": "^1.4.2",
41
41
  "vue": "3.5.40",
42
42
  "wretch": "^3.0.9",
43
- "@cat-factory/contracts": "0.156.0"
43
+ "@cat-factory/contracts": "0.157.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@toad-contracts/testing": "0.3.2",