@cat-factory/app 0.165.0 → 0.167.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.
@@ -7,9 +7,40 @@
7
7
  import { computed, reactive, ref, watch } from 'vue'
8
8
  import type { MergeClassRules, RiskPolicy, RequirementConcernLevel } from '~/types/merge'
9
9
  import type { StepGating } from '@cat-factory/contracts'
10
+ import {
11
+ RISK_POLICY_AXES,
12
+ RISK_POLICY_CEILING_FIELD,
13
+ type RiskPolicyAxis,
14
+ } from '~/utils/riskPolicy'
10
15
 
11
16
  const { t } = useI18n()
12
17
 
18
+ // Both axis groups below iterate the SHARED presentation order rather than hard-coding one,
19
+ // so this editor can't drift from the order the picker's preview and the inspector's summary
20
+ // line use (it used to read complexity-first while they read risk-first).
21
+ const CEILING_LABEL_KEYS: Record<RiskPolicyAxis, string> = {
22
+ risk: 'settings.riskPolicy.field.maxRisk',
23
+ impact: 'settings.riskPolicy.field.maxImpact',
24
+ complexity: 'settings.riskPolicy.field.maxComplexity',
25
+ }
26
+
27
+ // The fork-decision group is the same three axes read as FLOORS (how big an estimate has to
28
+ // be before the coder stops to propose implementations), so it shares the order but not the
29
+ // fields.
30
+ const FORK_FLOOR_FIELD: Record<
31
+ RiskPolicyAxis,
32
+ 'forkMinRisk' | 'forkMinImpact' | 'forkMinComplexity'
33
+ > = {
34
+ risk: 'forkMinRisk',
35
+ impact: 'forkMinImpact',
36
+ complexity: 'forkMinComplexity',
37
+ }
38
+ const FORK_FLOOR_LABEL_KEYS: Record<RiskPolicyAxis, string> = {
39
+ risk: 'settings.riskPolicy.forkDecision.minRisk',
40
+ impact: 'settings.riskPolicy.forkDecision.minImpact',
41
+ complexity: 'settings.riskPolicy.forkDecision.minComplexity',
42
+ }
43
+
13
44
  // Per-concern-level label. An exhaustive Record keyed off the union (a missing member fails
14
45
  // the typecheck); each value is a LITERAL catalog key so the typed-message-keys check sees
15
46
  // it. Leaf keys mirror the enum value verbatim.
@@ -276,36 +307,12 @@ async function create() {
276
307
  </div>
277
308
 
278
309
  <div class="grid grid-cols-2 gap-3 sm:grid-cols-4">
279
- <label class="block">
280
- <span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
281
- {{ t('settings.riskPolicy.field.maxComplexity') }}
282
- </span>
283
- <UInput
284
- v-model.number="drafts[p.id]!.maxComplexity"
285
- type="number"
286
- :min="0"
287
- :max="100"
288
- size="sm"
289
- />
290
- </label>
291
- <label class="block">
310
+ <label v-for="axis in RISK_POLICY_AXES" :key="axis" class="block">
292
311
  <span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
293
- {{ t('settings.riskPolicy.field.maxRisk') }}
312
+ {{ t(CEILING_LABEL_KEYS[axis]) }}
294
313
  </span>
295
314
  <UInput
296
- v-model.number="drafts[p.id]!.maxRisk"
297
- type="number"
298
- :min="0"
299
- :max="100"
300
- size="sm"
301
- />
302
- </label>
303
- <label class="block">
304
- <span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
305
- {{ t('settings.riskPolicy.field.maxImpact') }}
306
- </span>
307
- <UInput
308
- v-model.number="drafts[p.id]!.maxImpact"
315
+ v-model.number="drafts[p.id]![RISK_POLICY_CEILING_FIELD[axis]]"
309
316
  type="number"
310
317
  :min="0"
311
318
  :max="100"
@@ -369,36 +376,12 @@ async function create() {
369
376
  :description="t('settings.riskPolicy.forkDecision.hint')"
370
377
  />
371
378
  <div v-if="drafts[p.id]!.forkEnabled" class="mt-3 grid grid-cols-2 gap-3 sm:grid-cols-4">
372
- <label class="block">
373
- <span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
374
- {{ t('settings.riskPolicy.forkDecision.minComplexity') }}
375
- </span>
376
- <UInput
377
- v-model.number="drafts[p.id]!.forkMinComplexity"
378
- type="number"
379
- size="sm"
380
- :min="0"
381
- :max="100"
382
- />
383
- </label>
384
- <label class="block">
385
- <span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
386
- {{ t('settings.riskPolicy.forkDecision.minRisk') }}
387
- </span>
388
- <UInput
389
- v-model.number="drafts[p.id]!.forkMinRisk"
390
- type="number"
391
- size="sm"
392
- :min="0"
393
- :max="100"
394
- />
395
- </label>
396
- <label class="block">
379
+ <label v-for="axis in RISK_POLICY_AXES" :key="axis" class="block">
397
380
  <span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
398
- {{ t('settings.riskPolicy.forkDecision.minImpact') }}
381
+ {{ t(FORK_FLOOR_LABEL_KEYS[axis]) }}
399
382
  </span>
400
383
  <UInput
401
- v-model.number="drafts[p.id]!.forkMinImpact"
384
+ v-model.number="drafts[p.id]![FORK_FLOOR_FIELD[axis]]"
402
385
  type="number"
403
386
  size="sm"
404
387
  :min="0"
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import type { RiskPolicy } from '~/types/merge'
3
+ import { RISK_POLICY_AXES, RISK_POLICY_CEILING_FIELD, riskPolicyCeilings } from '~/utils/riskPolicy'
4
+
5
+ const policy = (over: Partial<RiskPolicy> = {}): RiskPolicy =>
6
+ ({
7
+ id: 'mp_balanced',
8
+ name: 'Balanced',
9
+ maxComplexity: 0.6,
10
+ maxRisk: 0.4,
11
+ maxImpact: 0.5,
12
+ ciMaxAttempts: 10,
13
+ maxRequirementIterations: 6,
14
+ maxRequirementConcernAllowed: 'none',
15
+ maxTesterQualityIterations: 3,
16
+ releaseWatchWindowMinutes: 30,
17
+ releaseMaxAttempts: 1,
18
+ humanReviewGraceMinutes: 10,
19
+ judgeMinScore: 0.7,
20
+ judgeMaxBounces: 2,
21
+ autoMergeEnabled: true,
22
+ classRules: {},
23
+ isDefault: true,
24
+ version: 1,
25
+ createdAt: 0,
26
+ updatedAt: 0,
27
+ ...over,
28
+ }) as RiskPolicy
29
+
30
+ describe('riskPolicyCeilings', () => {
31
+ it('groups the three axes in presentation order', () => {
32
+ expect(riskPolicyCeilings(policy()).map((c) => c.axis)).toEqual([
33
+ 'risk',
34
+ 'impact',
35
+ 'complexity',
36
+ ])
37
+ })
38
+
39
+ it('carries each axis ceiling as the stored 0..1 ratio', () => {
40
+ expect(riskPolicyCeilings(policy())).toEqual([
41
+ { axis: 'risk', max: 0.4 },
42
+ { axis: 'impact', max: 0.5 },
43
+ { axis: 'complexity', max: 0.6 },
44
+ ])
45
+ })
46
+
47
+ it('follows the shared axis order, which the settings editor iterates too', () => {
48
+ // The point of the exported order: the picker preview, the inspector summary and the
49
+ // settings editor all read it, so none of them can drift into its own sequence.
50
+ expect(riskPolicyCeilings(policy()).map((c) => c.axis)).toEqual([...RISK_POLICY_AXES])
51
+ expect(Object.keys(RISK_POLICY_CEILING_FIELD).sort()).toEqual([...RISK_POLICY_AXES].sort())
52
+ })
53
+ })
@@ -1,21 +1,42 @@
1
1
  import type { RiskPolicy } from '~/types/merge'
2
2
 
3
3
  /**
4
- * A compact one-line summary of a merge preset's auto-merge ceilings + CI-fix budget,
5
- * suitable for a dropdown option label so the user sees each preset's actual thresholds
6
- * (not just its name) while choosing one. Percentages are the stored 0..1 ratios
7
- * rendered as whole percents.
4
+ * The three axes a `merger` agent scores a pull request on. Presentation order is
5
+ * risk impact complexity: what the PR could break first, then how far it reaches, then
6
+ * how hard it was to write.
7
+ *
8
+ * This array IS the order — every surface that shows the three axes iterates it rather than
9
+ * hard-coding a sequence, so the picker's preview, the inspector's summary line and the
10
+ * settings editor cannot drift into three different orders (which is exactly what they had).
8
11
  */
9
- export function riskPolicySummary(p: RiskPolicy): string {
10
- // Auto-merge disabled: the thresholds don't apply, every PR goes to human review.
11
- if (!p.autoMergeEnabled) return `manual review only · ${p.ciMaxAttempts} CI fixes`
12
- const pct = (n: number) => `${Math.round(n * 100)}%`
13
- return `cx ≤${pct(p.maxComplexity)} · risk ≤${pct(p.maxRisk)} · impact ≤${pct(
14
- p.maxImpact,
15
- )} · ${p.ciMaxAttempts} CI fixes`
12
+ export const RISK_POLICY_AXES = ['risk', 'impact', 'complexity'] as const
13
+
14
+ export type RiskPolicyAxis = (typeof RISK_POLICY_AXES)[number]
15
+
16
+ /**
17
+ * Which `RiskPolicy` field carries each axis's auto-merge ceiling. Exhaustive over the axis
18
+ * union, so adding an axis fails the typecheck here rather than silently rendering two.
19
+ */
20
+ export const RISK_POLICY_CEILING_FIELD: Record<
21
+ RiskPolicyAxis,
22
+ 'maxRisk' | 'maxImpact' | 'maxComplexity'
23
+ > = {
24
+ risk: 'maxRisk',
25
+ impact: 'maxImpact',
26
+ complexity: 'maxComplexity',
16
27
  }
17
28
 
18
- /** The preset name followed by its thresholds, for a single-line dropdown option. */
19
- export function riskPolicyOptionLabel(p: RiskPolicy): string {
20
- return `${p.name} — ${riskPolicySummary(p)}`
29
+ /** One axis of a policy, with the ceiling a score must stay at or below to auto-merge. */
30
+ export interface RiskPolicyCeiling {
31
+ axis: RiskPolicyAxis
32
+ /** The stored 0..1 ratio. Render it through the `percent` number format, never raw. */
33
+ max: number
34
+ }
35
+
36
+ /**
37
+ * A policy's auto-merge ceilings, one entry per axis in presentation order, so every
38
+ * surface that explains a policy groups the three axes the same way.
39
+ */
40
+ export function riskPolicyCeilings(p: RiskPolicy): RiskPolicyCeiling[] {
41
+ return RISK_POLICY_AXES.map((axis) => ({ axis, max: p[RISK_POLICY_CEILING_FIELD[axis]] }))
21
42
  }
@@ -1318,8 +1318,8 @@
1318
1318
  "unassigned": "Nicht zugewiesen",
1319
1319
  "workspaceDefault": "Workspace-Standard",
1320
1320
  "workspaceDefaultParen": "(Workspace-Standard)",
1321
- "defaultPresetThresholds": "Standard ({name}): {thresholds}",
1322
- "defaultPreset": "Standard ({name})",
1321
+ "defaultRiskPolicy": "Standard ({name})",
1322
+ "defaultModelPreset": "Standard ({name})",
1323
1323
  "noDefault": "Kein Standard",
1324
1324
  "inheritWorkspace": "Vom Workspace erben",
1325
1325
  "on": "An",
@@ -1335,7 +1335,8 @@
1335
1335
  "pipelineEmpty": "Kein Standard. Wähle eine Pipeline, wenn du diese Aufgabe ausführst.",
1336
1336
  "pipelineHint": "Die Pipeline, die der Run-Button standardmäßig startet: die Abfolge der Agent-Schritte (zum Beispiel Spec, Code, Test, Merge), die für diese Aufgabe ausgeführt werden.",
1337
1337
  "mergePolicy": "Risikorichtlinie",
1338
- "riskPolicyDetail": "{name}: automatisch mergen, wenn Komplexität ≤ {complexity}, Risiko ≤ {risk}, Wirkung ≤ {impact}; bis zu {attempts} CI-Fix-Versuche.",
1338
+ "riskPolicyDetail": "{name}: mergt ohne menschliche Prüfung, wenn Risiko ≤ {risk}, Wirkung ≤ {impact} und Komplexität ≤ {complexity}; bis zu {attempts} CI-Fix-Versuche.",
1339
+ "riskPolicyManual": "{name}: mergt nie von selbst, jeder Pull Request wartet also auf eine menschliche Prüfung; bis zu {attempts} CI-Fix-Versuche.",
1339
1340
  "riskPolicyEmpty": "Keine Risikorichtlinie konfiguriert. Der Merger löst für jeden PR eine Prüfbenachrichtigung aus.",
1340
1341
  "mergePolicyHint": "Entscheidet, wann ein fertiger Pull Request automatisch mergt, statt auf eine menschliche Prüfung zu warten, und wie viele CI-Fix-Versuche ein Lauf erhält.",
1341
1342
  "modelPreset": "Modell-Preset",
@@ -2304,7 +2305,7 @@
2304
2305
  "chooseAtRunTime": "Zur Laufzeit auswählen",
2305
2306
  "mergePolicy": "Risikorichtlinie",
2306
2307
  "workspaceDefault": "Workspace-Standard",
2307
- "defaultPreset": "Standard ({name}) — {thresholds}",
2308
+ "defaultPreset": "Standard ({name})",
2308
2309
  "defaultModelPreset": "Standard ({name})",
2309
2310
  "modelPreset": "Modell-Preset",
2310
2311
  "bestPractices": "Best Practices",
@@ -3550,6 +3551,7 @@
3550
3551
  "title": "Anforderungsprüfung",
3551
3552
  "iteration": "Iteration {current} / {max}",
3552
3553
  "intro": "Ein KI-Prüfer hat die gesammelten Anforderungen dieses {level} untersucht — die Beschreibung sowie alle verknüpften PRDs und Tracker-Issues — und die folgenden Befunde erhoben. {answer} Sie die relevanten und {dismiss} Sie die irrelevanten, arbeiten Sie sie dann ein; der Prüfer prüft erneut, bis die Anforderungen klar sind.",
3554
+ "scopeNote": "Diese Phase umfasst ausschließlich Produkt- und Geschäftsanforderungen: was die Software leisten muss und welche Regeln dafür gelten. Technische Entscheidungen wie Technologieauswahl, Architektur und Datenstrukturen treffen später die Schritte Architekt und Rechercheur, die dabei Zugriff auf die Codebasis haben.",
3553
3555
  "levelFallback": "Element",
3554
3556
  "answerVerb": "Beantworten",
3555
3557
  "dismissVerb": "verwerfen",
@@ -5136,6 +5138,25 @@
5136
5138
  "toast": {
5137
5139
  "reseedFailed": "Risikorichtlinie konnte nicht erneut geseedet werden"
5138
5140
  }
5141
+ },
5142
+ "picker": {
5143
+ "workspaceDefaultCaption": "Gilt, weil diese Aufgabe keine eigene Richtlinie wählt.",
5144
+ "noneHint": "Keine Risikorichtlinie konfiguriert. Jeder Pull Request wartet auf eine menschliche Prüfung."
5145
+ },
5146
+ "preview": {
5147
+ "defaultBadge": "Standard",
5148
+ "autoMergeHeading": "Schwellen für automatisches Mergen",
5149
+ "axis": {
5150
+ "risk": "Risiko",
5151
+ "impact": "Wirkung",
5152
+ "complexity": "Komplexität"
5153
+ },
5154
+ "ceiling": "höchstens {value}",
5155
+ "autoMergeExplainer": "Sobald die CI grün ist, bewertet der Merger-Agent den Pull Request auf diesen drei Achsen. Bleibt jede Bewertung auf oder unter ihrer Obergrenze, mergt der Pull Request von selbst und überspringt die menschliche Prüfung; alles darüber geht an eine Person.",
5156
+ "manualHeading": "Nur manuelle Prüfung",
5157
+ "manualExplainer": "Diese Richtlinie mergt nie von selbst, jeder Pull Request wartet also unabhängig von den Bewertungen auf eine menschliche Prüfung.",
5158
+ "ciHeading": "CI-Fixes",
5159
+ "ciAttempts": "Der Lauf darf {count} Mal versuchen, eine rote CI grün zu bekommen, bevor er aufgibt. | Der Lauf darf {count} Mal versuchen, eine rote CI grün zu bekommen, bevor er aufgibt."
5139
5160
  }
5140
5161
  },
5141
5162
  "modelPreset": {
@@ -290,7 +290,7 @@
290
290
  "chooseAtRunTime": "Choose at run time",
291
291
  "mergePolicy": "Risk policy",
292
292
  "workspaceDefault": "Workspace default",
293
- "defaultPreset": "Default ({name}) — {thresholds}",
293
+ "defaultPreset": "Default ({name})",
294
294
  "defaultModelPreset": "Default ({name})",
295
295
  "modelPreset": "Model preset",
296
296
  "bestPractices": "Best practices",
@@ -1063,8 +1063,8 @@
1063
1063
  "unassigned": "Unassigned",
1064
1064
  "workspaceDefault": "Workspace default",
1065
1065
  "workspaceDefaultParen": "(workspace default)",
1066
- "defaultPresetThresholds": "Default ({name}): {thresholds}",
1067
- "defaultPreset": "Default ({name})",
1066
+ "defaultRiskPolicy": "Default ({name})",
1067
+ "defaultModelPreset": "Default ({name})",
1068
1068
  "noDefault": "No default",
1069
1069
  "inheritWorkspace": "Inherit workspace",
1070
1070
  "on": "On",
@@ -1080,7 +1080,8 @@
1080
1080
  "pipelineEmpty": "No default. Pick a pipeline when you run this task.",
1081
1081
  "pipelineHint": "The pipeline the Run button starts by default: the sequence of agent steps (for example spec, code, test, merge) executed for this task.",
1082
1082
  "mergePolicy": "Risk policy",
1083
- "riskPolicyDetail": "{name}: auto-merge when complexity {complexity}, risk ≤ {risk}, impact ≤ {impact}; up to {attempts} CI-fix attempts.",
1083
+ "riskPolicyDetail": "{name}: merges without human review when risk ≤ {risk}, impact ≤ {impact} and complexity ≤ {complexity}; up to {attempts} CI-fix attempts.",
1084
+ "riskPolicyManual": "{name}: never merges on its own, so every pull request waits for a human review; up to {attempts} CI-fix attempts.",
1084
1085
  "riskPolicyEmpty": "No risk policy configured. The merger raises a review notification for every PR.",
1085
1086
  "mergePolicyHint": "Decides when a finished pull request merges automatically instead of waiting for a human review, and how many CI-fix attempts a run gets.",
1086
1087
  "modelPreset": "Model preset",
@@ -3968,6 +3969,25 @@
3968
3969
  "toast": {
3969
3970
  "reseedFailed": "Could not reseed risk policy"
3970
3971
  }
3972
+ },
3973
+ "picker": {
3974
+ "workspaceDefaultCaption": "Applied because this task picks no policy of its own.",
3975
+ "noneHint": "No risk policy configured. Every pull request waits for a human review."
3976
+ },
3977
+ "preview": {
3978
+ "defaultBadge": "Default",
3979
+ "autoMergeHeading": "Automatic merge thresholds",
3980
+ "axis": {
3981
+ "risk": "Risk",
3982
+ "impact": "Impact",
3983
+ "complexity": "Complexity"
3984
+ },
3985
+ "ceiling": "at or below {value}",
3986
+ "autoMergeExplainer": "Once CI is green the merger agent scores the pull request on these three axes. Every score at or below its ceiling means the pull request merges on its own and skips human review; anything above sends it to a person instead.",
3987
+ "manualHeading": "Manual review only",
3988
+ "manualExplainer": "This policy never merges on its own, so every pull request waits for a human review whatever it scores.",
3989
+ "ciHeading": "CI fixes",
3990
+ "ciAttempts": "The run may try {count} time to turn a red CI green before it gives up. | The run may try {count} times to turn a red CI green before it gives up."
3971
3991
  }
3972
3992
  },
3973
3993
  "modelPreset": {
@@ -4103,6 +4123,7 @@
4103
4123
  "title": "Requirements review",
4104
4124
  "iteration": "Iteration {current} / {max}",
4105
4125
  "intro": "An AI reviewer inspected this {level}'s collected requirements — its description plus any linked PRDs and tracker issues — and raised the findings below. {answer} the relevant ones and {dismiss} the irrelevant, then incorporate them; the reviewer re-reviews until the requirements are clear.",
4126
+ "scopeNote": "This stage covers product and business requirements only: what the software must do and the rules that govern it. Technical decisions such as technology choice, architecture and data shapes are settled later by the Architect and Researcher steps, which run with the codebase in hand.",
4106
4127
  "levelFallback": "item",
4107
4128
  "answerVerb": "Answer",
4108
4129
  "dismissVerb": "dismiss",
@@ -269,7 +269,7 @@
269
269
  "chooseAtRunTime": "Elegir al ejecutar",
270
270
  "mergePolicy": "Política de riesgo",
271
271
  "workspaceDefault": "Predeterminado del espacio",
272
- "defaultPreset": "Predeterminado ({name}): {thresholds}",
272
+ "defaultPreset": "Predeterminada ({name})",
273
273
  "defaultModelPreset": "Predeterminado ({name})",
274
274
  "modelPreset": "Preset de modelo",
275
275
  "bestPractices": "Buenas prácticas",
@@ -1003,8 +1003,8 @@
1003
1003
  "unassigned": "Sin asignar",
1004
1004
  "workspaceDefault": "Predeterminado del espacio de trabajo",
1005
1005
  "workspaceDefaultParen": "(predeterminado del espacio de trabajo)",
1006
- "defaultPresetThresholds": "Predeterminado ({name}): {thresholds}",
1007
- "defaultPreset": "Predeterminado ({name})",
1006
+ "defaultRiskPolicy": "Predeterminada ({name})",
1007
+ "defaultModelPreset": "Predeterminado ({name})",
1008
1008
  "noDefault": "Sin predeterminado",
1009
1009
  "inheritWorkspace": "Heredar del espacio de trabajo",
1010
1010
  "on": "Activado",
@@ -1020,7 +1020,8 @@
1020
1020
  "pipelineEmpty": "Sin predeterminado. Elige un pipeline cuando ejecutes esta tarea.",
1021
1021
  "pipelineHint": "El pipeline que el botón Ejecutar inicia por defecto: la secuencia de pasos de agente (por ejemplo especificación, código, pruebas, fusión) que se ejecuta para esta tarea.",
1022
1022
  "mergePolicy": "Política de riesgo",
1023
- "riskPolicyDetail": "{name}: fusión automática cuando complejidad {complexity}, riesgo ≤ {risk}, impacto ≤ {impact}; hasta {attempts} intentos de corrección de CI.",
1023
+ "riskPolicyDetail": "{name}: se fusiona sin revisión humana cuando riesgo ≤ {risk}, impacto ≤ {impact} y complejidad ≤ {complexity}; hasta {attempts} intentos de corrección de CI.",
1024
+ "riskPolicyManual": "{name}: nunca se fusiona por su cuenta, así que cada pull request espera una revisión humana; hasta {attempts} intentos de corrección de CI.",
1024
1025
  "riskPolicyEmpty": "No hay política de riesgo configurada. El fusionador genera una notificación de revisión para cada PR.",
1025
1026
  "mergePolicyHint": "Decide cuándo un pull request terminado se fusiona automáticamente en lugar de esperar una revisión humana, y cuántos intentos de arreglo de CI tiene una ejecución.",
1026
1027
  "modelPreset": "Preajuste de modelo",
@@ -3954,6 +3955,7 @@
3954
3955
  "title": "Revisión de requisitos",
3955
3956
  "iteration": "Iteración {current} / {max}",
3956
3957
  "intro": "Un revisor de IA inspeccionó los requisitos recopilados de este {level} — su descripción más cualquier PRD y ticket vinculados — y planteó los hallazgos siguientes. {answer} los relevantes y {dismiss} los irrelevantes, luego incorpóralos; el revisor vuelve a revisar hasta que los requisitos queden claros.",
3958
+ "scopeNote": "Esta etapa cubre solo los requisitos de producto y negocio: qué debe hacer el software y las reglas que lo rigen. Las decisiones técnicas, como la elección de tecnología, la arquitectura y las estructuras de datos, se resuelven después en los pasos de Arquitecto e Investigador, que trabajan con el código a la vista.",
3957
3959
  "levelFallback": "elemento",
3958
3960
  "answerVerb": "Responde",
3959
3961
  "dismissVerb": "descarta",
@@ -5019,6 +5021,25 @@
5019
5021
  "toast": {
5020
5022
  "reseedFailed": "No se pudo regenerar la política de riesgo"
5021
5023
  }
5024
+ },
5025
+ "picker": {
5026
+ "workspaceDefaultCaption": "Se aplica porque esta tarea no elige una política propia.",
5027
+ "noneHint": "No hay ninguna política de riesgo configurada. Cada pull request espera una revisión humana."
5028
+ },
5029
+ "preview": {
5030
+ "defaultBadge": "Predeterminada",
5031
+ "autoMergeHeading": "Umbrales de fusión automática",
5032
+ "axis": {
5033
+ "risk": "Riesgo",
5034
+ "impact": "Impacto",
5035
+ "complexity": "Complejidad"
5036
+ },
5037
+ "ceiling": "igual o inferior a {value}",
5038
+ "autoMergeExplainer": "Cuando CI está en verde, el agente fusionador puntúa el pull request en estos tres ejes. Si todas las puntuaciones quedan en su límite o por debajo, el pull request se fusiona solo y se salta la revisión humana; cualquier valor superior lo envía a una persona.",
5039
+ "manualHeading": "Solo revisión manual",
5040
+ "manualExplainer": "Esta política nunca fusiona por su cuenta, así que cada pull request espera una revisión humana sea cual sea su puntuación.",
5041
+ "ciHeading": "Correcciones de CI",
5042
+ "ciAttempts": "La ejecución puede intentar {count} vez poner CI en verde antes de rendirse. | La ejecución puede intentar {count} veces poner CI en verde antes de rendirse."
5022
5043
  }
5023
5044
  },
5024
5045
  "modelPreset": {
@@ -269,7 +269,7 @@
269
269
  "chooseAtRunTime": "Choisir au lancement",
270
270
  "mergePolicy": "Politique de risque",
271
271
  "workspaceDefault": "Valeur par défaut de l’espace",
272
- "defaultPreset": "Par défaut ({name}) : {thresholds}",
272
+ "defaultPreset": "Par défaut ({name})",
273
273
  "defaultModelPreset": "Par défaut ({name})",
274
274
  "modelPreset": "Préréglage de modèle",
275
275
  "bestPractices": "Bonnes pratiques",
@@ -1003,8 +1003,8 @@
1003
1003
  "unassigned": "Non assigné",
1004
1004
  "workspaceDefault": "Valeur par défaut de l'espace de travail",
1005
1005
  "workspaceDefaultParen": "(valeur par défaut de l'espace de travail)",
1006
- "defaultPresetThresholds": "Par défaut ({name}) : {thresholds}",
1007
- "defaultPreset": "Par défaut ({name})",
1006
+ "defaultRiskPolicy": "Par défaut ({name})",
1007
+ "defaultModelPreset": "Par défaut ({name})",
1008
1008
  "noDefault": "Aucune valeur par défaut",
1009
1009
  "inheritWorkspace": "Hériter de l'espace de travail",
1010
1010
  "on": "Activé",
@@ -1020,7 +1020,8 @@
1020
1020
  "pipelineEmpty": "Aucune valeur par défaut. Choisissez un pipeline lorsque vous exécutez cette tâche.",
1021
1021
  "pipelineHint": "Le pipeline que le bouton Exécuter démarre par défaut : la séquence d'étapes d'agent (par exemple spécification, code, test, fusion) exécutée pour cette tâche.",
1022
1022
  "mergePolicy": "Politique de risque",
1023
- "riskPolicyDetail": "{name} : fusion automatique lorsque la complexité ≤ {complexity}, le risque ≤ {risk}, l'impact ≤ {impact} ; jusqu'à {attempts} tentatives de correction CI.",
1023
+ "riskPolicyDetail": "{name} : fusionne sans revue humaine lorsque le risque ≤ {risk}, l'impact ≤ {impact} et la complexité ≤ {complexity} ; jusqu'à {attempts} tentatives de correction CI.",
1024
+ "riskPolicyManual": "{name} : ne fusionne jamais de lui-même, chaque pull request attend donc une revue humaine ; jusqu'à {attempts} tentatives de correction CI.",
1024
1025
  "riskPolicyEmpty": "Aucune politique de risque configurée. Le fusionneur déclenche une notification de revue pour chaque PR.",
1025
1026
  "mergePolicyHint": "Décide quand une pull request terminée est fusionnée automatiquement au lieu d'attendre une revue humaine, et combien de tentatives de correction de CI une exécution obtient.",
1026
1027
  "modelPreset": "Preset de modèle",
@@ -3954,6 +3955,7 @@
3954
3955
  "title": "Revue des exigences",
3955
3956
  "iteration": "Itération {current} / {max}",
3956
3957
  "intro": "Un relecteur IA a inspecté les exigences collectées de cet {level} — sa description ainsi que les PRD et tickets liés — et a soulevé les observations ci-dessous. {answer} celles qui sont pertinentes et {dismiss} les autres, puis incorporez-les ; le relecteur relit jusqu'à ce que les exigences soient claires.",
3958
+ "scopeNote": "Cette étape couvre uniquement les exigences produit et métier : ce que le logiciel doit faire et les règles qui le régissent. Les décisions techniques comme le choix des technologies, l'architecture et les structures de données sont tranchées plus tard par les étapes Architecte et Chercheur, qui disposent du code source.",
3957
3959
  "levelFallback": "élément",
3958
3960
  "answerVerb": "Répondez à",
3959
3961
  "dismissVerb": "écartez",
@@ -5019,6 +5021,25 @@
5019
5021
  "toast": {
5020
5022
  "reseedFailed": "Impossible de régénérer la politique de risque"
5021
5023
  }
5024
+ },
5025
+ "picker": {
5026
+ "workspaceDefaultCaption": "Appliquée parce que cette tâche ne choisit aucune politique.",
5027
+ "noneHint": "Aucune politique de risque configurée. Chaque pull request attend une revue humaine."
5028
+ },
5029
+ "preview": {
5030
+ "defaultBadge": "Par défaut",
5031
+ "autoMergeHeading": "Seuils de fusion automatique",
5032
+ "axis": {
5033
+ "risk": "Risque",
5034
+ "impact": "Impact",
5035
+ "complexity": "Complexité"
5036
+ },
5037
+ "ceiling": "inférieur ou égal à {value}",
5038
+ "autoMergeExplainer": "Une fois la CI au vert, l'agent fusionneur note la pull request sur ces trois axes. Si chaque note reste sous son plafond, la pull request fusionne toute seule et saute la revue humaine ; au-dessus, elle part vers une personne.",
5039
+ "manualHeading": "Revue manuelle uniquement",
5040
+ "manualExplainer": "Cette politique ne fusionne jamais d'elle-même : chaque pull request attend une revue humaine, quelles que soient les notes.",
5041
+ "ciHeading": "Corrections CI",
5042
+ "ciAttempts": "L'exécution peut tenter {count} fois de remettre la CI au vert avant d'abandonner. | L'exécution peut tenter {count} fois de remettre la CI au vert avant d'abandonner."
5022
5043
  }
5023
5044
  },
5024
5045
  "modelPreset": {
@@ -269,7 +269,7 @@
269
269
  "chooseAtRunTime": "בחר בזמן הריצה",
270
270
  "mergePolicy": "מדיניות סיכון",
271
271
  "workspaceDefault": "ברירת מחדל של סביבת העבודה",
272
- "defaultPreset": "ברירת מחדל ({name}) — {thresholds}",
272
+ "defaultPreset": "ברירת מחדל ({name})",
273
273
  "defaultModelPreset": "ברירת מחדל ({name})",
274
274
  "modelPreset": "הגדרה קבועה של מודל",
275
275
  "bestPractices": "מומלצות עבודה",
@@ -1003,8 +1003,8 @@
1003
1003
  "unassigned": "לא משויך",
1004
1004
  "workspaceDefault": "ברירת מחדל של מרחב העבודה",
1005
1005
  "workspaceDefaultParen": "(ברירת מחדל של מרחב העבודה)",
1006
- "defaultPresetThresholds": "ברירת מחדל ({name}): {thresholds}",
1007
- "defaultPreset": "ברירת מחדל ({name})",
1006
+ "defaultRiskPolicy": "ברירת מחדל ({name})",
1007
+ "defaultModelPreset": "ברירת מחדל ({name})",
1008
1008
  "noDefault": "אין ברירת מחדל",
1009
1009
  "inheritWorkspace": "ירש ממרחב העבודה",
1010
1010
  "on": "פעיל",
@@ -1020,7 +1020,8 @@
1020
1020
  "pipelineEmpty": "אין ברירת מחדל. בחר פייפליין כשאתה מריץ משימה זו.",
1021
1021
  "pipelineHint": "הפייפליין שכפתור ההרצה מפעיל כברירת מחדל: רצף שלבי הסוכנים (למשל אפיון, קוד, בדיקות, מיזוג) שמורץ עבור משימה זו.",
1022
1022
  "mergePolicy": "מדיניות סיכון",
1023
- "riskPolicyDetail": "{name}: מיזוג אוטומטי כאשר מורכבות ≤ {complexity}, סיכון ≤ {risk}, השפעה ≤ {impact}; עד {attempts} ניסיונות תיקון CI.",
1023
+ "riskPolicyDetail": "{name}: ממזג ללא סקירה אנושית כאשר סיכון ≤ {risk}, השפעה ≤ {impact} ומורכבות ≤ {complexity}; עד {attempts} ניסיונות תיקון CI.",
1024
+ "riskPolicyManual": "{name}: לעולם לא ממזג מעצמו, ולכן כל בקשת משיכה ממתינה לסקירה אנושית; עד {attempts} ניסיונות תיקון CI.",
1024
1025
  "riskPolicyEmpty": "לא הוגדרה מדיניות סיכון. הממזג מעלה התראת סקירה עבור כל PR.",
1025
1026
  "mergePolicyHint": "קובע מתי בקשת משיכה שהושלמה ממוזגת אוטומטית במקום להמתין לסקירה אנושית, וכמה ניסיונות תיקון CI מקבלת הרצה.",
1026
1027
  "modelPreset": "תבנית מודל",
@@ -3965,6 +3966,7 @@
3965
3966
  "title": "סקירת דרישות",
3966
3967
  "iteration": "איטרציה {current} / {max}",
3967
3968
  "intro": "סוקר AI בחן את הדרישות שנאספו עבור ה{level} הזה — התיאור שלו בתוספת כל ה-PRD והאישוז המקושרים — והעלה את הממצאים שלהלן. {answer} את הרלוונטיים ו{dismiss} את שאינם רלוונטיים, ולאחר מכן שלב אותם; הסוקר סוקר מחדש עד שהדרישות ברורות.",
3969
+ "scopeNote": "שלב זה עוסק בדרישות מוצר ועסקים בלבד: מה התוכנה צריכה לעשות ואילו כללים חלים עליה. החלטות טכניות כמו בחירת טכנולוגיה, ארכיטקטורה ומבני נתונים נקבעות בהמשך בשלבי הארכיטקט והחוקר, שעובדים מול קוד המקור.",
3968
3970
  "levelFallback": "פריט",
3969
3971
  "answerVerb": "ענה על",
3970
3972
  "dismissVerb": "בטל",
@@ -5030,6 +5032,25 @@
5030
5032
  "toast": {
5031
5033
  "reseedFailed": "לא ניתן לזרוע מחדש את מדיניות הסיכון"
5032
5034
  }
5035
+ },
5036
+ "picker": {
5037
+ "workspaceDefaultCaption": "חלה מפני שהמשימה הזו לא בוחרת מדיניות משלה.",
5038
+ "noneHint": "לא הוגדרה מדיניות סיכון. כל בקשת משיכה ממתינה לסקירה אנושית."
5039
+ },
5040
+ "preview": {
5041
+ "defaultBadge": "ברירת מחדל",
5042
+ "autoMergeHeading": "ספי מיזוג אוטומטי",
5043
+ "axis": {
5044
+ "risk": "סיכון",
5045
+ "impact": "השפעה",
5046
+ "complexity": "מורכבות"
5047
+ },
5048
+ "ceiling": "עד {value}",
5049
+ "autoMergeExplainer": "כאשר ה-CI ירוק, סוכן המיזוג מנקד את בקשת המשיכה בשלושת הצירים האלה. אם כל ניקוד נמצא בתקרה שלו או מתחתיה, בקשת המשיכה ממוזגת מעצמה ומדלגת על סקירה אנושית; ניקוד גבוה יותר שולח אותה לאדם.",
5050
+ "manualHeading": "סקירה ידנית בלבד",
5051
+ "manualExplainer": "מדיניות זו לעולם אינה ממזגת מעצמה, ולכן כל בקשת משיכה ממתינה לסקירה אנושית ללא קשר לניקוד.",
5052
+ "ciHeading": "תיקוני CI",
5053
+ "ciAttempts": "ההרצה רשאית לנסות פעם {count} להחזיר CI אדום למצב ירוק לפני שהיא מוותרת. | ההרצה רשאית לנסות {count} פעמים להחזיר CI אדום למצב ירוק לפני שהיא מוותרת."
5033
5054
  }
5034
5055
  },
5035
5056
  "modelPreset": {
@@ -1318,8 +1318,8 @@
1318
1318
  "unassigned": "Non assegnato",
1319
1319
  "workspaceDefault": "Predefinito del workspace",
1320
1320
  "workspaceDefaultParen": "(predefinito del workspace)",
1321
- "defaultPresetThresholds": "Predefinito ({name}): {thresholds}",
1322
- "defaultPreset": "Predefinito ({name})",
1321
+ "defaultRiskPolicy": "Predefinito ({name})",
1322
+ "defaultModelPreset": "Predefinito ({name})",
1323
1323
  "noDefault": "Nessun predefinito",
1324
1324
  "inheritWorkspace": "Eredita dal workspace",
1325
1325
  "on": "Attivo",
@@ -1335,7 +1335,8 @@
1335
1335
  "pipelineEmpty": "Nessun predefinito. Scegli una pipeline quando esegui questa attivita'.",
1336
1336
  "pipelineHint": "La pipeline che il pulsante Esegui avvia per impostazione predefinita: la sequenza di passaggi dell'agente (ad esempio spec, code, test, merge) eseguiti per questa attivita'.",
1337
1337
  "mergePolicy": "Criterio di rischio",
1338
- "riskPolicyDetail": "{name}: unione automatica quando complessita' ≤ {complexity}, rischio ≤ {risk}, impatto ≤ {impact}; fino a {attempts} tentativi di correzione CI.",
1338
+ "riskPolicyDetail": "{name}: unisce senza revisione umana quando rischio ≤ {risk}, impatto ≤ {impact} e complessita ≤ {complexity}; fino a {attempts} tentativi di correzione CI.",
1339
+ "riskPolicyManual": "{name}: non unisce mai da solo, quindi ogni pull request attende una revisione umana; fino a {attempts} tentativi di correzione CI.",
1339
1340
  "riskPolicyEmpty": "Nessun criterio di rischio configurato. Il merger genera una notifica di revisione per ogni PR.",
1340
1341
  "mergePolicyHint": "Decide quando una pull request completata viene unita automaticamente invece di attendere una revisione umana, e quanti tentativi di correzione CI ottiene un'esecuzione.",
1341
1342
  "modelPreset": "Preset del modello",
@@ -2304,7 +2305,7 @@
2304
2305
  "chooseAtRunTime": "Scegli al momento dell'esecuzione",
2305
2306
  "mergePolicy": "Criterio di rischio",
2306
2307
  "workspaceDefault": "Predefinito del workspace",
2307
- "defaultPreset": "Predefinito ({name}) — {thresholds}",
2308
+ "defaultPreset": "Predefinito ({name})",
2308
2309
  "defaultModelPreset": "Predefinito ({name})",
2309
2310
  "modelPreset": "Preset di modello",
2310
2311
  "bestPractices": "Best practice",
@@ -3550,6 +3551,7 @@
3550
3551
  "title": "Revisione dei requisiti",
3551
3552
  "iteration": "Iterazione {current} / {max}",
3552
3553
  "intro": "Un revisore AI ha esaminato i requisiti raccolti di questo {level} — la sua descrizione piu eventuali PRD e issue del tracker collegati — e ha sollevato i rilievi qui sotto. {answer} quelli pertinenti e {dismiss} quelli irrilevanti, poi incorporali; il revisore rivede di nuovo finche i requisiti non sono chiari.",
3554
+ "scopeNote": "Questa fase copre solo i requisiti di prodotto e di business: che cosa il software deve fare e quali regole lo governano. Le decisioni tecniche come la scelta della tecnologia, l'architettura e le strutture dati vengono prese più avanti negli step Architetto e Ricercatore, che lavorano con il codice a disposizione.",
3553
3555
  "levelFallback": "elemento",
3554
3556
  "answerVerb": "Rispondi a",
3555
3557
  "dismissVerb": "ignora",
@@ -5136,6 +5138,25 @@
5136
5138
  "toast": {
5137
5139
  "reseedFailed": "Impossibile ripristinare il criterio di rischio"
5138
5140
  }
5141
+ },
5142
+ "picker": {
5143
+ "workspaceDefaultCaption": "Si applica perche questa attivita non sceglie un criterio proprio.",
5144
+ "noneHint": "Nessun criterio di rischio configurato. Ogni pull request attende una revisione umana."
5145
+ },
5146
+ "preview": {
5147
+ "defaultBadge": "Predefinito",
5148
+ "autoMergeHeading": "Soglie di unione automatica",
5149
+ "axis": {
5150
+ "risk": "Rischio",
5151
+ "impact": "Impatto",
5152
+ "complexity": "Complessita"
5153
+ },
5154
+ "ceiling": "pari o inferiore a {value}",
5155
+ "autoMergeExplainer": "Quando la CI e verde, l'agente merger valuta la pull request su questi tre assi. Se ogni punteggio resta entro il proprio limite, la pull request si unisce da sola e salta la revisione umana; qualsiasi valore superiore la manda a una persona.",
5156
+ "manualHeading": "Solo revisione manuale",
5157
+ "manualExplainer": "Questo criterio non unisce mai da solo, quindi ogni pull request attende una revisione umana qualunque sia il punteggio.",
5158
+ "ciHeading": "Correzioni CI",
5159
+ "ciAttempts": "L'esecuzione può fare {count} tentativo per rimettere in verde la CI prima di arrendersi. | L'esecuzione può fare {count} tentativi per rimettere in verde la CI prima di arrendersi."
5139
5160
  }
5140
5161
  },
5141
5162
  "modelPreset": {