@cat-factory/app 0.256.3 → 0.258.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.
Files changed (59) hide show
  1. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +284 -0
  2. package/app/components/binaryOutput/BinaryOutputReport.vue +75 -0
  3. package/app/components/board/AddTaskModal.vue +38 -12
  4. package/app/components/board/RecurringPipelineModal.vue +24 -12
  5. package/app/components/board/nodes/TaskCard.vue +34 -7
  6. package/app/components/forkDecision/ForkDecisionWindow.vue +3 -1
  7. package/app/components/panels/AgentStepDetail.vue +42 -20
  8. package/app/components/panels/InspectorPanel.vue +39 -0
  9. package/app/components/panels/ResultWindowShell.logic.spec.ts +4 -0
  10. package/app/components/panels/inspector/TaskExecution.vue +34 -34
  11. package/app/components/pipeline/BinaryOutputStepPicker.logic.spec.ts +119 -1
  12. package/app/components/pipeline/BinaryOutputStepPicker.logic.ts +115 -1
  13. package/app/components/pipeline/BinaryOutputStepPicker.vue +463 -1
  14. package/app/components/pipeline/PipelineBuilder.vue +44 -0
  15. package/app/components/pipeline/PipelinePreview.vue +20 -1
  16. package/app/components/pipeline/PipelineProgress.vue +50 -0
  17. package/app/composables/api/binaryCandidates.ts +36 -0
  18. package/app/composables/api/execution.ts +19 -0
  19. package/app/composables/useApi.ts +2 -0
  20. package/app/composables/usePipelineHealth.spec.ts +42 -5
  21. package/app/composables/usePipelineHealth.ts +109 -48
  22. package/app/modular/agent-kinds.ts +5 -0
  23. package/app/modular/result-views.ts +4 -0
  24. package/app/stores/binaryCandidates.ts +89 -0
  25. package/app/stores/environmentWizard/context.ts +0 -2
  26. package/app/stores/environmentWizard/flow.ts +11 -6
  27. package/app/stores/environmentWizard.ts +12 -11
  28. package/app/stores/execution/commands.ts +26 -1
  29. package/app/stores/pipelines/draftActions.ts +2 -0
  30. package/app/stores/pipelines/draftStepConfig.ts +4 -161
  31. package/app/stores/pipelines/draftStepOptions.ts +204 -0
  32. package/app/stores/ui/resultViews.ts +8 -6
  33. package/app/stores/ui/runStepOpeners.ts +23 -1
  34. package/app/types/domain.ts +6 -0
  35. package/app/types/execution.ts +5 -0
  36. package/app/utils/agentPalette.spec.ts +26 -0
  37. package/app/utils/agentPalette.ts +9 -4
  38. package/app/utils/binaryCandidates.spec.ts +110 -0
  39. package/app/utils/binaryCandidates.ts +126 -0
  40. package/app/utils/binaryOutput.spec.ts +122 -1
  41. package/app/utils/binaryOutput.ts +149 -2
  42. package/app/utils/catalog.spec.ts +24 -0
  43. package/app/utils/catalog.ts +21 -4
  44. package/app/utils/pipeline.spec.ts +35 -3
  45. package/app/utils/pipeline.ts +54 -3
  46. package/app/utils/pipelineRender.spec.ts +122 -1
  47. package/app/utils/pipelineRender.ts +113 -2
  48. package/i18n/locales/de.json +107 -3
  49. package/i18n/locales/en.json +107 -3
  50. package/i18n/locales/es.json +107 -3
  51. package/i18n/locales/fr.json +107 -3
  52. package/i18n/locales/he.json +107 -3
  53. package/i18n/locales/it.json +107 -3
  54. package/i18n/locales/ja.json +107 -3
  55. package/i18n/locales/pl.json +107 -3
  56. package/i18n/locales/tr.json +107 -3
  57. package/i18n/locales/uk.json +107 -3
  58. package/i18n/plural-forms.spec.ts +15 -0
  59. package/package.json +2 -2
@@ -3,6 +3,7 @@
3
3
  // in one place rather than being re-derived as inline ternaries per component.
4
4
 
5
5
  import type { AgentState, ExecutionInstance, PipelineStep } from '~/types/execution'
6
+ import { isStepSkipReason } from '@cat-factory/contracts'
6
7
 
7
8
  /**
8
9
  * Visual state of a conditionally-run companion attached to a gate step (today the
@@ -133,10 +134,17 @@ export function isCompanionKind(kind: string): boolean {
133
134
  )
134
135
  }
135
136
 
137
+ /**
138
+ * The parks a surface must NOT answer with the generic approve rail, named so the tables below
139
+ * and every consumer can be keyed exhaustively by them rather than by a string.
140
+ */
141
+ export type DedicatedParkView = 'follow-ups' | 'fork-decision' | 'binary-candidates' | 'input-gate'
142
+
136
143
  /**
137
144
  * The dedicated window that owns a step's approval park, when the park is NOT a generic
138
145
  * prose approval: the implementation-fork window while a coder waits on (or chats about)
139
- * an approach choice, or the follow-up triage window while surfaced items are undecided.
146
+ * an approach choice, the follow-up triage window while surfaced items are undecided, or the
147
+ * candidate-comparison window while a generating step waits on which candidates survive.
140
148
  * The generic approve/request-changes/reject resolvers deliberately refuse these parks
141
149
  * server-side (`assertNotIterativeGate`), so every surface that offers a step's pending
142
150
  * approval must route these to their window instead of the generic "Approve & proceed"
@@ -149,7 +157,7 @@ export function isCompanionKind(kind: string): boolean {
149
157
  export function dedicatedParkView(
150
158
  step: PipelineStep,
151
159
  instance: ExecutionInstance | null | undefined,
152
- ): 'follow-ups' | 'fork-decision' | 'input-gate' | null {
160
+ ): DedicatedParkView | null {
153
161
  // The PRE-DISPATCH INPUT GATE parks whatever step 0 happens to be, so it leaves nothing on the
154
162
  // STEP to recognise it by: its verdict is a fact about the RUN. Checked first, and off the
155
163
  // instance: approving it generically would mark the run's first working step done and skip
@@ -168,6 +176,9 @@ export function dedicatedParkView(
168
176
  // flight) still belongs to the fork window, which renders the pending reply.
169
177
  const fork = step.forkDecision?.status
170
178
  if (fork === 'awaiting_choice' || fork === 'answering') return 'fork-decision'
179
+ // A generating step parked between its candidate pass and its delivering pass. Approving it
180
+ // generically would mark a step done that has staged files and delivered nothing.
181
+ if (step.binaryCandidates?.status === 'awaiting_choice') return 'binary-candidates'
171
182
  // Follow-ups only own the park itself: while the coder is still WORKING (streaming
172
183
  // items, no approval raised) a step click should keep opening the ordinary detail.
173
184
  if (
@@ -180,6 +191,64 @@ export function dedicatedParkView(
180
191
  return null
181
192
  }
182
193
 
194
+ /**
195
+ * The parks a dedicated WINDOW answers: every member of {@link DedicatedParkView} except the
196
+ * pre-dispatch input gate, which is answered by an inline notice because its remedy is to go and
197
+ * edit the task.
198
+ */
199
+ export type RedirectParkView = Exclude<DedicatedParkView, 'input-gate'>
200
+
201
+ /** How a redirect park presents itself on a surface that has to send a human to its window. */
202
+ export interface RedirectParkPresentation {
203
+ icon: string
204
+ /** Prose explaining why the generic approve rail is not offered here. */
205
+ noticeKey: string
206
+ /** The label on the step overlay's redirect button, which has room for a full phrase. */
207
+ actionKey: string
208
+ /**
209
+ * The label on the inspector's compact action rail. A separate key rather than a reuse of
210
+ * {@link actionKey}: that rail sits in a list of one-line step rows and words the same action
211
+ * more tersely, and collapsing the two would silently restyle copy that is already shipped.
212
+ */
213
+ railActionKey: string
214
+ }
215
+
216
+ /**
217
+ * What each redirect park LOOKS like, in one exhaustive table.
218
+ *
219
+ * A `Record` over the vocabulary rather than a ternary at each of the three surfaces that render
220
+ * one (the step overlay's redirect notice, the pipeline chip, the inspector's action rail),
221
+ * because a ternary has no arm for a member it has never heard of: adding `binary-candidates` to
222
+ * {@link dedicatedParkView} left every one of those surfaces rendering the FORK's copy and icon
223
+ * for it, which is worse than rendering nothing: it names the wrong decision, and the surfaces
224
+ * kept compiling and kept passing. Keyed this way, a new park fails the build here until it says
225
+ * how it presents itself, and each surface picks the entry up with no edit of its own.
226
+ *
227
+ * Presentation only. WHICH window opens is the caller's, because the openers differ in what they
228
+ * need to resolve, and a park with no window (`input-gate`) is excluded from the type entirely
229
+ * rather than carrying null fields nobody may read.
230
+ */
231
+ export const REDIRECT_PARK_PRESENTATION: Record<RedirectParkView, RedirectParkPresentation> = {
232
+ 'follow-ups': {
233
+ icon: 'i-lucide-compass',
234
+ noticeKey: 'panels.stepDetail.followUpsParked',
235
+ actionKey: 'panels.stepDetail.openFollowUps',
236
+ railActionKey: 'inspector.execution.triageFollowUps',
237
+ },
238
+ 'fork-decision': {
239
+ icon: 'i-lucide-git-fork',
240
+ noticeKey: 'panels.stepDetail.forkParked',
241
+ actionKey: 'panels.stepDetail.chooseApproach',
242
+ railActionKey: 'inspector.execution.chooseApproach',
243
+ },
244
+ 'binary-candidates': {
245
+ icon: 'i-lucide-images',
246
+ noticeKey: 'panels.stepDetail.candidatesParked',
247
+ actionKey: 'panels.stepDetail.chooseCandidates',
248
+ railActionKey: 'inspector.execution.chooseCandidates',
249
+ },
250
+ }
251
+
183
252
  /**
184
253
  * The friendly label for a container's live phase (clone → "Preparing workspace",
185
254
  * agent → "Agent running", …), falling back to the raw phase string for an unknown/new
@@ -198,6 +267,48 @@ export function containerPhaseLabel(
198
267
  return i18n.te(key) ? i18n.t(key) : phase
199
268
  }
200
269
 
270
+ /**
271
+ * The i18n key naming WHY a skipped step was skipped, or null when the step ran.
272
+ *
273
+ * The engine records a machine-readable {@link StepSkipReason} rather than a sentence, so the
274
+ * sentence is composed here where it can be translated. The `condition` case narrows further off
275
+ * the step's own `stepOptions.condition.serviceScope` — the condition stays on the step, so the
276
+ * copy and the scope it names are read from one place and cannot drift.
277
+ *
278
+ * An UNRECOGNISED reason (a stored run naming a member this bundle no longer knows, or a browser
279
+ * older than the member it reads) falls back to the bare "skipped" line rather than rendering
280
+ * nothing or guessing onto a current member: what a reader must not lose is that the step did not
281
+ * run. A `skipped` step with NO reason is the same case — runs predating the field.
282
+ */
283
+ export function stepSkipReasonKey(step: PipelineStep): string | null {
284
+ if (!step.skipped) return null
285
+ if (!isStepSkipReason(step.skipReason)) return 'pipeline.progress.skipped.unknown'
286
+ switch (step.skipReason) {
287
+ case 'gated':
288
+ return 'pipeline.progress.skipped.gated'
289
+ case 'producer_skipped':
290
+ return 'pipeline.progress.skipped.producerSkipped'
291
+ case 'run_complete':
292
+ return 'pipeline.progress.skipped.runComplete'
293
+ case 'condition':
294
+ return step.stepOptions?.condition?.serviceScope === 'frontend'
295
+ ? 'pipeline.progress.skipped.conditionFrontend'
296
+ : 'pipeline.progress.skipped.conditionBackend'
297
+ default:
298
+ return describeUnhandledSkipReason(step.skipReason)
299
+ }
300
+ }
301
+
302
+ /**
303
+ * The `never` sink that keeps {@link stepSkipReasonKey}'s switch total: adding a member to
304
+ * `stepSkipReasonSchema` fails the build here until it has copy, while the runtime narrowing above
305
+ * still renders a RETIRED member honestly.
306
+ */
307
+ function describeUnhandledSkipReason(reason: never): string {
308
+ void reason
309
+ return 'pipeline.progress.skipped.unknown'
310
+ }
311
+
201
312
  /**
202
313
  * Tailwind classes for a subtask-item status icon. An in-progress item spins only
203
314
  * while the run is live: once the run has failed, a step left mid-flight (its item
@@ -1654,6 +1654,7 @@
1654
1654
  "mergePr": "PR mergen",
1655
1655
  "chooseApproach": "Ansatz wählen",
1656
1656
  "triageFollowUps": "Folgeaufgaben entscheiden",
1657
+ "chooseCandidates": "Kandidaten entscheiden",
1657
1658
  "elapsedTooltip": "Verstrichene Zeit für diesen Schritt",
1658
1659
  "reviewFindings": "Befunde prüfen",
1659
1660
  "dryRun": "Probelauf",
@@ -1932,8 +1933,10 @@
1932
1933
  "decisionRequired": "Entscheidung erforderlich",
1933
1934
  "followUpsParked": "Der Coder hat Folgeaufgaben aufgeworfen, die entschieden werden müssen, bevor der Lauf fortgesetzt werden kann. Bearbeite jeden Punkt (anlegen, zurückgeben, beantworten oder verwerfen) im Folgeaufgaben-Fenster.",
1934
1935
  "forkParked": "Dieser Coder-Schritt wartet darauf, dass ein Implementierungsansatz gewählt wird, bevor Code geschrieben wird. Wähle einen vorgeschlagenen Ansatz (oder gib einen eigenen ein) im Entscheidungsfenster.",
1936
+ "candidatesParked": "Dieser Schritt hat Kandidaten erzeugt und wartet darauf, dass jemand auswählt, welche behalten werden, bevor er etwas ausliefert. Vergleiche sie im Kandidatenfenster und behalte, was du möchtest.",
1935
1937
  "openFollowUps": "Folgeaufgaben öffnen",
1936
1938
  "chooseApproach": "Ansatz wählen",
1939
+ "chooseCandidates": "Kandidaten wählen",
1937
1940
  "expandAll": "Alle Abschnitte ausklappen",
1938
1941
  "collapseAll": "Alle Abschnitte einklappen",
1939
1942
  "copyRawOutput": "Rohausgabe kopieren",
@@ -2113,6 +2116,8 @@
2113
2116
  "priorDocHint": "Aus der vorherigen Prüfung. Verwende es als Basis: bearbeite die Beschreibung oben und reiche erneut ein.",
2114
2117
  "bootstrapping": "Wird initialisiert…",
2115
2118
  "viewRequirements": "Anforderungen anzeigen",
2119
+ "mapService": "Service kartieren",
2120
+ "mapServiceNoRepo": "Verknüpfen Sie zuerst ein Repository mit diesem Service — es gibt noch nichts zu kartieren.",
2116
2121
  "reRun": "Erneut ausführen",
2117
2122
  "run": "Ausführen",
2118
2123
  "focus": "Fokussieren",
@@ -4161,7 +4166,11 @@
4161
4166
  "preview": {
4162
4167
  "stepCount": "{count} Schritt | {count} Schritte",
4163
4168
  "gateCount": "{count} Freigabe | {count} Freigaben",
4164
- "gated": "Manuelle Freigabe nach diesem Schritt"
4169
+ "gated": "Manuelle Freigabe nach diesem Schritt",
4170
+ "conditionalCount": "{count} bedingter Schritt | {count} bedingte Schritte",
4171
+ "conditionEstimate": "Läuft nur, wenn die Aufwandsschätzung die Schwellenwerte dieses Schritts erreicht",
4172
+ "conditionFrontend": "Läuft nur, wenn die Aufgabe einen Frontend-Service ändert",
4173
+ "conditionBackend": "Läuft nur, wenn die Aufgabe einen Nicht-Frontend-Service ändert"
4165
4174
  },
4166
4175
  "picker": {
4167
4176
  "noneHint": "Keine Standard-Pipeline. Du wählst beim Ausführen der Aufgabe eine aus.",
@@ -4251,6 +4260,11 @@
4251
4260
  "body": "\"{name}\" wird entfernt. Dies kann nicht rückgängig gemacht werden."
4252
4261
  },
4253
4262
  "disabledStepTooltip": "Deaktiviert, wird beim Lauf übersprungen",
4263
+ "condition": {
4264
+ "always": "Läuft bei jeder Aufgabe — klicken, um eine Bedingung zu setzen",
4265
+ "frontend": "Läuft nur bei Aufgaben, die einen Frontend-Service ändern",
4266
+ "backend": "Läuft nur bei Aufgaben, die einen Nicht-Frontend-Service ändern"
4267
+ },
4254
4268
  "cancelEdit": "Bearbeitung abbrechen",
4255
4269
  "clear": "Leeren",
4256
4270
  "update": "Pipeline aktualisieren",
@@ -4327,7 +4341,51 @@
4327
4341
  "3d-model": "3D-Modelle",
4328
4342
  "3d-scene": "3D-Szenen",
4329
4343
  "document": "Dokumente"
4330
- }
4344
+ },
4345
+ "binaryCapability": {
4346
+ "reference-image": "Referenzbild",
4347
+ "multi-reference": "Mehrere Referenzbilder",
4348
+ "instruction-edit": "Bearbeitung per Anweisung",
4349
+ "mask-edit": "Maskierte Bearbeitung",
4350
+ "negative-prompt": "Negativer Prompt",
4351
+ "seed": "Fester Seed",
4352
+ "aspect-ratio": "Seitenverhältnis",
4353
+ "exact-size": "Exakte Größe",
4354
+ "candidate-batch": "Mehrere Kandidaten pro Aufruf",
4355
+ "upscale": "Hochskalierung",
4356
+ "transparent-background": "Transparenter Hintergrund",
4357
+ "tileable": "Nahtlos kachelbar"
4358
+ },
4359
+ "binaryCapabilityUnknown": "{capability} (eine Fähigkeit, die diese Installation nicht definiert)",
4360
+ "binaryCapabilityUnsupported": "Keine ausgewählte Integration unterstützt {capabilities}, was die Generierungsoptionen dieses Schritts verlangen. Entferne die Option oder wähle eine Integration, die die Fähigkeit deklariert.",
4361
+ "binaryCapabilityUnverifiable": "Keine ausgewählte Integration deklariert Unterstützung für {capabilities}, aber eine von ihnen deklariert überhaupt keine Fähigkeiten, daher konnte das nicht geprüft werden. Der Schritt startet trotzdem; prüfe es in der API der Integration.",
4362
+ "binaryReferenceImages": "Referenzbilder",
4363
+ "binaryReferenceImagesPlaceholder": "Rolle{'|'}Ort{'|'}Dienst, eine pro Zeile",
4364
+ "binaryReferenceImagesUnusable": "Nicht als Referenz gespeichert: {entries}. Jede Zeile muss Rolle{'|'}Ort sein, wobei die Rolle style, subject, composition oder base ist.",
4365
+ "binaryEditMode": "Vorhandenes bearbeiten",
4366
+ "binaryEditModeNone": "Neu generieren",
4367
+ "binaryEditModeInstruction": "Per Anweisung",
4368
+ "binaryEditModeMask": "Maskierter Bereich",
4369
+ "binaryEditInstruction": "Was geändert wird",
4370
+ "binaryEditInstructionPlaceholder": "z. B. den Himmel ersetzen",
4371
+ "binaryNegativePrompt": "Negativer Prompt",
4372
+ "binaryNegativePromptPlaceholder": "was vermieden werden soll",
4373
+ "binaryAspectRatio": "Seitenverhältnis",
4374
+ "binaryAspectRatioPlaceholder": "16:9",
4375
+ "binaryOutputSize": "Ausgabegröße",
4376
+ "binaryOutputSizeWidth": "Breite",
4377
+ "binaryOutputSizeHeight": "Höhe",
4378
+ "binaryOutputSizeIncomplete": "Nicht gespeichert: eine exakte Größe braucht Breite und Höhe.",
4379
+ "binaryOutputSizeAmbiguous": "Eine exakte Ausgabegröße lässt sich nicht mit {options} kombinieren: beides gibt die gelieferten Maße ein zweites Mal an. Behalte das, was die Anforderung ist.",
4380
+ "binarySeed": "Seed",
4381
+ "binarySeedPlaceholder": "fester Seed",
4382
+ "binaryTransparent": "Transparenter Hintergrund",
4383
+ "binaryTileable": "Nahtlos kachelbar",
4384
+ "binaryUpscale": "Ergebnis hochskalieren",
4385
+ "binaryComparison": "Kandidaten vor der Lieferung vergleichen",
4386
+ "binaryPerGenerator": "Kandidaten pro Integration",
4387
+ "binaryMultiSelect": "Mehrere behalten erlauben",
4388
+ "binaryComparisonUnreachable": "Dieser Schritt kann nur einen Kandidaten pro Motiv erzeugen, es gäbe also nichts zu vergleichen und der einzige würde ungefragt behalten. Wähle eine zweite Integration oder erhöhe die Anzahl der Kandidaten pro Integration."
4331
4389
  },
4332
4390
  "progress": {
4333
4391
  "status": {
@@ -4374,9 +4432,20 @@
4374
4432
  "proposing": "Ansätze werden vorgeschlagen…",
4375
4433
  "choose": "Ansatz wählen"
4376
4434
  },
4435
+ "binaryCandidates": {
4436
+ "choose": "Kandidaten wählen"
4437
+ },
4377
4438
  "elapsedTooltip": "Verstrichene Zeit für diesen Schritt",
4378
4439
  "prReview": {
4379
4440
  "review": "Befunde prüfen"
4441
+ },
4442
+ "skipped": {
4443
+ "gated": "Übersprungen: Die Aufgabenschätzung lag unter den Schwellenwerten dieses Schritts.",
4444
+ "conditionFrontend": "Übersprungen: Diese Aufgabe ändert keinen Frontend-Dienst, es gibt also keine Oberfläche zu prüfen.",
4445
+ "conditionBackend": "Übersprungen: Diese Aufgabe ändert nur einen Frontend-Dienst, es gibt also keine API dahinter zu prüfen.",
4446
+ "producerSkipped": "Übersprungen: Der geprüfte Schritt wurde übersprungen, es gibt nichts zu bewerten.",
4447
+ "runComplete": "Übersprungen: Der Lauf endete vor diesem Schritt, es blieb nichts zu tun.",
4448
+ "unknown": "Übersprungen: Dieser Schritt wurde nicht ausgeführt."
4380
4449
  }
4381
4450
  },
4382
4451
  "health": {
@@ -5017,13 +5086,21 @@
5017
5086
  "unknownServices": "Nennt einen Dienst, den der Katalog nicht enthält: {ids}. Der Eintrag bleibt wie angegeben erhalten; prüfe die Kennung gegen den Katalog des Boards. | Nennt Dienste, die der Katalog nicht enthält: {ids}. Die Einträge bleiben wie angegeben erhalten; prüfe die Kennungen gegen den Katalog des Boards.",
5018
5087
  "targetUnknown": "Der Katalog enthält den eigenen Speicherdienst dieses Schritts nicht mehr ({id}), deshalb konnte nichts unten dagegen geprüft werden. Registriere ihn erneut, oder verweise den Schritt auf einen anderen Dienst.",
5019
5088
  "undeliveredMediaTypes": "Dieser Schritt sollte {formats} liefern, und kein Artefakt unten meldet dieses Format. | Dieser Schritt sollte {formats} liefern, und kein Artefakt unten meldet diese Formate.",
5089
+ "missized": "1 Artefakt wurde in einer anderen Größe als {width}×{height} geliefert. | {count} Artefakte wurden in einer anderen Größe als {width}×{height} geliefert.",
5090
+ "sizeUnreported": "1 Artefakt meldet keine Abmessungen, daher konnte seine Größe nicht geprüft werden. | {count} Artefakte melden keine Abmessungen, daher konnten ihre Größen nicht geprüft werden.",
5020
5091
  "misdirected": "1 Artefakt ging an einen anderen Dienst als {target}. | {count} Artefakte gingen an einen anderen Dienst als {target}.",
5021
5092
  "invalidEntries": "1 angegebener Eintrag wurde verworfen: er nannte weder Dienst noch Ablageort. | {count} angegebene Einträge wurden verworfen: sie nannten weder Dienst noch Ablageort.",
5022
5093
  "omitted": "1 weiteres Artefakt wurde jenseits der Berichtsgrenze angegeben und ist nicht aufgeführt. | {count} weitere Artefakte wurden jenseits der Berichtsgrenze angegeben und sind nicht aufgeführt.",
5023
5094
  "unknownGenerators": "Eine generative Integration genannt, die diese Installation nicht registriert: {ids}. Der Eintrag bleibt wie angegeben erhalten; die Integration wird im Code der Installation registriert, nicht in diesem Workspace. | Generative Integrationen genannt, die diese Installation nicht registriert: {ids}. Ihre Einträge bleiben wie angegeben erhalten; Integrationen werden im Code der Installation registriert, nicht in diesem Workspace.",
5024
5095
  "generatorsUnverified": "Die generativen Integrationen dieser Installation konnten beim Abschluss des Schritts nicht gelesen werden, daher wurden die unten genannten Integrationen nicht dagegen geprüft. Die Einträge bleiben wie angegeben erhalten."
5025
5096
  },
5026
- "unknownGeneratorBadge": "Nicht registriert"
5097
+ "unknownGeneratorBadge": "Nicht registriert",
5098
+ "missizedBadge": "Falsche Größe",
5099
+ "candidates": {
5100
+ "automatic": "{total} Kandidat wurde erzeugt und ohne Prüfung automatisch behalten.",
5101
+ "chosen": "{kept} von {total} erzeugten Kandidaten wurden behalten.",
5102
+ "awaiting": "{total} Kandidaten wurden erzeugt und warten auf den Vergleich."
5103
+ }
5027
5104
  },
5028
5105
  "brainstorm": {
5029
5106
  "title": {
@@ -7551,5 +7628,32 @@
7551
7628
  "resolverFailed": "Beim Ermitteln der Adresse ist in diesem Tool ein Fehler aufgetreten. Die Ursache steht in der Browser-Konsole, für die Betreuer dieser Installation.",
7552
7629
  "unsafeUrl": "Dieses Tool hat eine Adresse geliefert, die kein Weblink ist, und wurde daher nicht geöffnet."
7553
7630
  }
7631
+ },
7632
+ "binaryCandidates": {
7633
+ "title": "Erzeugte Kandidaten",
7634
+ "titleWithBlock": "Erzeugte Kandidaten: {title}",
7635
+ "subtitle": "Vergleiche, was jede Integration erzeugt hat, und behalte, was du willst",
7636
+ "automatic": "Es wurde nur ein Kandidat erzeugt, daher wurde er automatisch behalten. Niemand hat ihn geprüft.",
7637
+ "unlabelledSubject": "Kein Motiv angegeben",
7638
+ "noPreview": "Keine Vorschau verfügbar",
7639
+ "fromGenerator": "Von {generator}",
7640
+ "unattributed": "Keine Integration erfasst",
7641
+ "kept": "Behalten",
7642
+ "keptAs": "Behalten als {id}",
7643
+ "storeAsPlaceholder": "unter dieser ID ablegen",
7644
+ "notePlaceholder": "Was beim Ablegen geändert werden soll (optional)",
7645
+ "missingAlias": "Gib jedem behaltenen Kandidaten eine eigene ID, sonst würden alle unter demselben Namen abgelegt.",
7646
+ "duplicateAlias": "Zwei behaltene Kandidaten teilen sich eine ID. Zwei Artefakte an einem Ort sind ein Artefakt.",
7647
+ "keepAction": "{count} behalten",
7648
+ "warning": {
7649
+ "omitted": "{count} Kandidaten wurden über der Obergrenze verworfen, diese Liste ist also ein Anfang. ",
7650
+ "invalid": "{count} deklarierte Einträge waren unlesbar und fehlen hier. ",
7651
+ "previews": "{count} Vorschaulinks wurden abgelehnt, diese Kandidaten werden ohne Bild dargestellt."
7652
+ },
7653
+ "noChoice": {
7654
+ "undeclared": "Der Schritt hat seine Kandidaten nie deklariert, es gab also nichts zu vergleichen. Der Lauf ging weiter.",
7655
+ "parseFailed": "Die Kandidaten-Deklaration des Schritts war nicht lesbar, es gab also nichts zu vergleichen. Der Lauf ging weiter.",
7656
+ "noCandidates": "Der Schritt hat keine Kandidaten bereitgestellt, es gab also nichts zu vergleichen. Der Lauf ging weiter."
7657
+ }
7554
7658
  }
7555
7659
  }
@@ -1196,6 +1196,7 @@
1196
1196
  "mergePr": "Merge PR",
1197
1197
  "chooseApproach": "Choose approach",
1198
1198
  "triageFollowUps": "Decide follow-ups",
1199
+ "chooseCandidates": "Decide candidates",
1199
1200
  "elapsedTooltip": "Elapsed time on this step",
1200
1201
  "reviewFindings": "Review findings",
1201
1202
  "dryRun": "Dry run",
@@ -1478,8 +1479,10 @@
1478
1479
  "decisionRequired": "Decision required",
1479
1480
  "followUpsParked": "The Coder surfaced follow-up items that need a decision before the run can continue. Triage each item (file, send back, answer, or dismiss) in the follow-ups window.",
1480
1481
  "forkParked": "This Coder step is waiting for an implementation approach to be chosen before any code is written. Pick a proposed approach (or enter your own) in the fork-decision window.",
1482
+ "candidatesParked": "This step generated candidates and is waiting for someone to choose which ones to keep before it delivers anything. Compare them and keep what you want in the candidates window.",
1481
1483
  "openFollowUps": "Open follow-ups",
1482
1484
  "chooseApproach": "Choose approach",
1485
+ "chooseCandidates": "Choose candidates",
1483
1486
  "expandAll": "Expand all sections",
1484
1487
  "collapseAll": "Collapse all sections",
1485
1488
  "copyRawOutput": "Copy raw output",
@@ -1663,6 +1666,8 @@
1663
1666
  "priorDocHint": "From the previous review. Use it as a base: edit the description above and resubmit.",
1664
1667
  "bootstrapping": "Bootstrapping…",
1665
1668
  "viewRequirements": "View Requirements",
1669
+ "mapService": "Map service",
1670
+ "mapServiceNoRepo": "Link a repository to this service first — there is nothing to map yet.",
1666
1671
  "reRun": "Re-run",
1667
1672
  "run": "Run",
1668
1673
  "focus": "Focus",
@@ -4743,7 +4748,11 @@
4743
4748
  "preview": {
4744
4749
  "stepCount": "{count} step | {count} steps",
4745
4750
  "gateCount": "{count} approval gate | {count} approval gates",
4746
- "gated": "Human approval gate after this step"
4751
+ "gated": "Human approval gate after this step",
4752
+ "conditionalCount": "{count} conditional step | {count} conditional steps",
4753
+ "conditionEstimate": "Runs only when the task estimate clears this step's thresholds",
4754
+ "conditionFrontend": "Runs only when the task changes a frontend service",
4755
+ "conditionBackend": "Runs only when the task changes a non-frontend service"
4747
4756
  },
4748
4757
  "picker": {
4749
4758
  "noneHint": "No default pipeline. You choose one when you run the task.",
@@ -4839,6 +4848,11 @@
4839
4848
  "body": "\"{name}\" will be removed. This can't be undone."
4840
4849
  },
4841
4850
  "disabledStepTooltip": "Disabled, skipped at run",
4851
+ "condition": {
4852
+ "always": "Runs on every task — click to make it conditional",
4853
+ "frontend": "Runs only on tasks that change a frontend service",
4854
+ "backend": "Runs only on tasks that change a non-frontend service"
4855
+ },
4842
4856
  "cancelEdit": "Cancel edit",
4843
4857
  "clear": "Clear",
4844
4858
  "update": "Update pipeline",
@@ -4917,7 +4931,51 @@
4917
4931
  "3d-model": "3D models",
4918
4932
  "3d-scene": "3D scenes",
4919
4933
  "document": "Documents"
4920
- }
4934
+ },
4935
+ "binaryCapability": {
4936
+ "reference-image": "Reference image",
4937
+ "multi-reference": "Several reference images",
4938
+ "instruction-edit": "Editing from an instruction",
4939
+ "mask-edit": "Masked editing",
4940
+ "negative-prompt": "Negative prompt",
4941
+ "seed": "Fixed seed",
4942
+ "aspect-ratio": "Aspect ratio",
4943
+ "exact-size": "Exact size",
4944
+ "candidate-batch": "Several candidates per call",
4945
+ "upscale": "Upscaling",
4946
+ "transparent-background": "Transparent background",
4947
+ "tileable": "Seamless tiling"
4948
+ },
4949
+ "binaryCapabilityUnknown": "{capability} (a capability this deployment does not define)",
4950
+ "binaryCapabilityUnsupported": "No selected integration supports {capabilities}, which this step's generation options ask for. Remove the option, or select an integration that declares the capability.",
4951
+ "binaryCapabilityUnverifiable": "No selected integration declares support for {capabilities}, but one of them declares no capabilities at all, so this could not be checked. The step still starts; confirm it from the integration’s API.",
4952
+ "binaryReferenceImages": "Reference images",
4953
+ "binaryReferenceImagesPlaceholder": "role{'|'}location{'|'}service, one per line",
4954
+ "binaryReferenceImagesUnusable": "Not stored as references: {entries}. Each line must be role{'|'}location, where role is style, subject, composition or base.",
4955
+ "binaryEditMode": "Edit existing",
4956
+ "binaryEditModeNone": "Generate new",
4957
+ "binaryEditModeInstruction": "From an instruction",
4958
+ "binaryEditModeMask": "Masked region",
4959
+ "binaryEditInstruction": "What to change",
4960
+ "binaryEditInstructionPlaceholder": "e.g. replace the sky",
4961
+ "binaryNegativePrompt": "Negative prompt",
4962
+ "binaryNegativePromptPlaceholder": "what to keep out",
4963
+ "binaryAspectRatio": "Aspect ratio",
4964
+ "binaryAspectRatioPlaceholder": "16:9",
4965
+ "binaryOutputSize": "Output size",
4966
+ "binaryOutputSizeWidth": "Width",
4967
+ "binaryOutputSizeHeight": "Height",
4968
+ "binaryOutputSizeIncomplete": "Not saved: an exact size needs both a width and a height.",
4969
+ "binaryOutputSizeAmbiguous": "An exact output size cannot be combined with {options}: each states the delivered dimensions a second time. Keep whichever one is the requirement.",
4970
+ "binarySeed": "Seed",
4971
+ "binarySeedPlaceholder": "fixed seed",
4972
+ "binaryTransparent": "Transparent background",
4973
+ "binaryTileable": "Seamless tiling",
4974
+ "binaryUpscale": "Upscale the result",
4975
+ "binaryComparison": "Compare candidates before delivering",
4976
+ "binaryPerGenerator": "Candidates per integration",
4977
+ "binaryMultiSelect": "Allow keeping more than one",
4978
+ "binaryComparisonUnreachable": "This step can only produce one candidate per subject, so nothing would be compared and the only one would be kept without asking. Select a second integration, or raise the candidates-per-integration count."
4921
4979
  },
4922
4980
  "progress": {
4923
4981
  "status": {
@@ -4964,9 +5022,20 @@
4964
5022
  "proposing": "Proposing approaches…",
4965
5023
  "choose": "Choose an approach"
4966
5024
  },
5025
+ "binaryCandidates": {
5026
+ "choose": "Choose candidates"
5027
+ },
4967
5028
  "elapsedTooltip": "Elapsed time on this step",
4968
5029
  "prReview": {
4969
5030
  "review": "Review findings"
5031
+ },
5032
+ "skipped": {
5033
+ "gated": "Skipped: the task estimate was below this step’s thresholds.",
5034
+ "conditionFrontend": "Skipped: this task changes no frontend service, so there is no UI to exercise.",
5035
+ "conditionBackend": "Skipped: this task changes only a frontend service, so there is no API behind it to exercise.",
5036
+ "producerSkipped": "Skipped: the step it reviews was skipped, so there is nothing to grade.",
5037
+ "runComplete": "Skipped: the run finished before this step, with nothing left to do.",
5038
+ "unknown": "Skipped: this step did not run."
4970
5039
  }
4971
5040
  },
4972
5041
  "health": {
@@ -6544,13 +6613,21 @@
6544
6613
  "unknownServices": "Named a service the catalog does not contain: {ids}. The entry is kept as claimed; check the id against the workspace catalog. | Named services the catalog does not contain: {ids}. Their entries are kept as claimed; check the ids against the workspace catalog.",
6545
6614
  "targetUnknown": "The catalog no longer contains this step's own storage service ({id}), so nothing below could be checked against it. Register it again, or point the step at another service.",
6546
6615
  "undeliveredMediaTypes": "This step was set to deliver {formats}, and no artifact below reports that format. | This step was set to deliver {formats}, and no artifact below reports those formats.",
6616
+ "missized": "1 artifact was delivered at a size other than {width}×{height}. | {count} artifacts were delivered at a size other than {width}×{height}.",
6617
+ "sizeUnreported": "1 artifact reports no dimensions, so its size could not be checked. | {count} artifacts report no dimensions, so their sizes could not be checked.",
6547
6618
  "misdirected": "1 artifact went to a service other than {target}. | {count} artifacts went to a service other than {target}.",
6548
6619
  "invalidEntries": "1 declared entry was dropped: it named no service and location. | {count} declared entries were dropped: they named no service and location.",
6549
6620
  "omitted": "1 more artifact was declared beyond the report's limit and is not listed. | {count} more artifacts were declared beyond the report's limit and are not listed.",
6550
6621
  "unknownGenerators": "Named a generative integration this deployment does not register: {ids}. The entry is kept as claimed; the integration is registered in the deployment's code, not in this workspace. | Named generative integrations this deployment does not register: {ids}. Their entries are kept as claimed; integrations are registered in the deployment's code, not in this workspace.",
6551
6622
  "generatorsUnverified": "This deployment's generative integrations could not be read when the step settled, so the integrations named below were not checked against them. The entries are kept as claimed."
6552
6623
  },
6553
- "unknownGeneratorBadge": "Not registered"
6624
+ "unknownGeneratorBadge": "Not registered",
6625
+ "missizedBadge": "Wrong size",
6626
+ "candidates": {
6627
+ "automatic": "{total} candidate was generated and kept automatically, without review.",
6628
+ "chosen": "{kept} of {total} generated candidates were kept.",
6629
+ "awaiting": "{total} candidates were generated and are waiting to be compared."
6630
+ }
6554
6631
  },
6555
6632
  "sandbox": {
6556
6633
  "title": "Sandbox: prompt and model testing",
@@ -7815,5 +7892,32 @@
7815
7892
  "resolverFailed": "This tool failed while working out its address. The cause is in the browser console, for whoever maintains this deployment.",
7816
7893
  "unsafeUrl": "This tool returned an address that is not a web link, so it was not opened."
7817
7894
  }
7895
+ },
7896
+ "binaryCandidates": {
7897
+ "title": "Generated candidates",
7898
+ "titleWithBlock": "Generated candidates: {title}",
7899
+ "subtitle": "Compare what each integration produced, and keep what you want",
7900
+ "automatic": "Only one candidate was generated, so it was kept automatically. Nobody reviewed it.",
7901
+ "unlabelledSubject": "No subject declared",
7902
+ "noPreview": "No preview available",
7903
+ "fromGenerator": "From {generator}",
7904
+ "unattributed": "No integration recorded",
7905
+ "kept": "Kept",
7906
+ "keptAs": "Kept as {id}",
7907
+ "storeAsPlaceholder": "store under this id",
7908
+ "notePlaceholder": "Anything to change when storing these (optional)",
7909
+ "missingAlias": "Give each kept candidate its own id, or they would all be stored under the same name.",
7910
+ "duplicateAlias": "Two kept candidates share an id. Two artifacts at one location is one artifact.",
7911
+ "keepAction": "Keep {count}",
7912
+ "warning": {
7913
+ "omitted": "{count} candidates were dropped past the cap, so this list is a prefix. ",
7914
+ "invalid": "{count} declared entries were unreadable and are missing here. ",
7915
+ "previews": "{count} preview links were refused, so those candidates render without an image."
7916
+ },
7917
+ "noChoice": {
7918
+ "undeclared": "The step never declared its candidates, so there was nothing to compare. The run continued.",
7919
+ "parseFailed": "The step’s candidate declaration could not be read, so there was nothing to compare. The run continued.",
7920
+ "noCandidates": "The step staged no candidates, so there was nothing to compare. The run continued."
7921
+ }
7818
7922
  }
7819
7923
  }