@cat-factory/app 0.109.4 → 0.110.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 (36) hide show
  1. package/app/components/board/AddTaskModal.vue +15 -15
  2. package/app/components/panels/inspector/TaskRunSettings.vue +12 -12
  3. package/app/components/pipeline/PipelineBuilder.vue +22 -0
  4. package/app/components/requirements/RequirementsReviewWindow.vue +300 -203
  5. package/app/components/settings/{MergePresetHealthModal.vue → RiskPolicyHealthModal.vue} +19 -19
  6. package/app/components/settings/{MergeThresholdsPanel.vue → RiskPolicyPanel.vue} +46 -46
  7. package/app/components/settings/UsageSettings.vue +142 -0
  8. package/app/components/settings/WorkspaceSettingsPanel.vue +14 -2
  9. package/app/composables/api/board.ts +1 -1
  10. package/app/composables/api/execution.ts +5 -0
  11. package/app/composables/api/presets.ts +18 -18
  12. package/app/composables/api/reviews.ts +7 -6
  13. package/app/composables/{useMergePresetHealth.ts → useRiskPolicyHealth.ts} +10 -10
  14. package/app/pages/index.vue +9 -9
  15. package/app/stores/board.ts +2 -2
  16. package/app/stores/pipelines.ts +41 -1
  17. package/app/stores/requirements.ts +9 -13
  18. package/app/stores/{mergePresets.ts → riskPolicies.ts} +13 -13
  19. package/app/stores/ui.ts +17 -17
  20. package/app/stores/usage.ts +60 -0
  21. package/app/stores/workspace.spec.ts +1 -1
  22. package/app/stores/workspace.ts +4 -4
  23. package/app/types/merge.ts +3 -3
  24. package/app/types/requirements.ts +1 -0
  25. package/app/utils/{mergePreset.ts → riskPolicy.ts} +4 -4
  26. package/i18n/locales/de.json +52 -27
  27. package/i18n/locales/en.json +52 -27
  28. package/i18n/locales/es.json +52 -27
  29. package/i18n/locales/fr.json +53 -28
  30. package/i18n/locales/he.json +53 -28
  31. package/i18n/locales/it.json +53 -28
  32. package/i18n/locales/ja.json +52 -27
  33. package/i18n/locales/pl.json +53 -28
  34. package/i18n/locales/tr.json +52 -27
  35. package/i18n/locales/uk.json +53 -28
  36. package/package.json +2 -2
@@ -21,14 +21,14 @@ import type {
21
21
  import { DOC_KINDS, DOC_KIND_FIELDS } from '~/types/domain'
22
22
  import ContextDocumentPicker from '~/components/documents/ContextDocumentPicker.vue'
23
23
  import ContextIssuePicker from '~/components/tasks/ContextIssuePicker.vue'
24
- import { mergePresetOptionLabel, mergePresetThresholds } from '~/utils/mergePreset'
24
+ import { riskPolicyOptionLabel, riskPolicySummary } from '~/utils/riskPolicy'
25
25
  import { pipelineAllowedForManualStart } from '~/utils/pipeline'
26
26
 
27
27
  const ui = useUiStore()
28
28
  const board = useBoardStore()
29
29
  const documents = useDocumentsStore()
30
30
  const tasks = useTasksStore()
31
- const mergePresets = useMergePresetsStore()
31
+ const riskPolicies = useRiskPoliciesStore()
32
32
  const modelPresets = useModelPresetsStore()
33
33
  const pipelines = usePipelinesStore()
34
34
  const agentConfig = useAgentConfigStore()
@@ -181,15 +181,15 @@ const recurringFrameId = computed(() => {
181
181
 
182
182
  // Run configuration picked up front. Empty string = use the default (workspace
183
183
  // default merge preset / no pinned pipeline).
184
- const mergePresetId = ref('')
184
+ const riskPolicyId = ref('')
185
185
  const modelPresetId = ref('')
186
186
  const pipelineId = ref('')
187
187
 
188
188
  const defaultPresetLabel = computed(() =>
189
- mergePresets.defaultPreset
189
+ riskPolicies.defaultPreset
190
190
  ? t('board.addTask.defaultPreset', {
191
- name: mergePresets.defaultPreset.name,
192
- thresholds: mergePresetThresholds(mergePresets.defaultPreset),
191
+ name: riskPolicies.defaultPreset.name,
192
+ thresholds: riskPolicySummary(riskPolicies.defaultPreset),
193
193
  })
194
194
  : t('board.addTask.workspaceDefault'),
195
195
  )
@@ -198,19 +198,19 @@ const presetMenu = computed(() => [
198
198
  {
199
199
  label: defaultPresetLabel.value,
200
200
  icon: 'i-lucide-rotate-ccw',
201
- onSelect: () => (mergePresetId.value = ''),
201
+ onSelect: () => (riskPolicyId.value = ''),
202
202
  },
203
- ...mergePresets.presets.map((p) => ({
204
- label: mergePresetOptionLabel(p),
203
+ ...riskPolicies.presets.map((p) => ({
204
+ label: riskPolicyOptionLabel(p),
205
205
  icon: 'i-lucide-git-merge',
206
- onSelect: () => (mergePresetId.value = p.id),
206
+ onSelect: () => (riskPolicyId.value = p.id),
207
207
  })),
208
208
  ],
209
209
  ])
210
210
  const selectedPresetLabel = computed(() => {
211
- if (!mergePresetId.value) return defaultPresetLabel.value
212
- const picked = mergePresets.presets.find((p) => p.id === mergePresetId.value)
213
- return picked ? mergePresetOptionLabel(picked) : t('board.addTask.workspaceDefault')
211
+ if (!riskPolicyId.value) return defaultPresetLabel.value
212
+ const picked = riskPolicies.presets.find((p) => p.id === riskPolicyId.value)
213
+ return picked ? riskPolicyOptionLabel(picked) : t('board.addTask.workspaceDefault')
214
214
  })
215
215
 
216
216
  // Model preset: which model each agent runs on. Empty = workspace default preset.
@@ -383,7 +383,7 @@ watch(open, (isOpen) => {
383
383
  docOutlineHints.value = ''
384
384
  for (const key of Object.keys(docKindFieldValues) as DocKindFieldKey[])
385
385
  delete docKindFieldValues[key]
386
- mergePresetId.value = ''
386
+ riskPolicyId.value = ''
387
387
  modelPresetId.value = ''
388
388
  pipelineId.value = ''
389
389
  agentConfigValues.value = {}
@@ -436,7 +436,7 @@ async function add() {
436
436
  const block = await board.addTask(containerId, title.value.trim(), fullDescription, {
437
437
  taskType: taskType.value as CreateTaskType,
438
438
  ...(typeFields ? { taskTypeFields: typeFields } : {}),
439
- ...(mergePresetId.value ? { mergePresetId: mergePresetId.value } : {}),
439
+ ...(riskPolicyId.value ? { riskPolicyId: riskPolicyId.value } : {}),
440
440
  ...(modelPresetId.value ? { modelPresetId: modelPresetId.value } : {}),
441
441
  ...(pipelineId.value ? { pipelineId: pipelineId.value } : {}),
442
442
  ...(Object.keys(agentConfigValues.value).length
@@ -3,14 +3,14 @@ import { computed, onMounted } from 'vue'
3
3
  import { connectionNeighborIds } from '@cat-factory/contracts'
4
4
  import type { Block } from '~/types/domain'
5
5
  import type { WritebackOverride } from '~/types/tracker'
6
- import { mergePresetOptionLabel, mergePresetThresholds } from '~/utils/mergePreset'
6
+ import { riskPolicyOptionLabel, riskPolicySummary } from '~/utils/riskPolicy'
7
7
  import { pipelineAllowedForManualStart } from '~/utils/pipeline'
8
8
  import InspectorSection from '~/components/panels/inspector/InspectorSection.vue'
9
9
 
10
10
  const props = defineProps<{ block: Block }>()
11
11
 
12
12
  const board = useBoardStore()
13
- const mergePresets = useMergePresetsStore()
13
+ const riskPolicies = useRiskPoliciesStore()
14
14
  const modelPresets = useModelPresetsStore()
15
15
  const models = useModelsStore()
16
16
  const pipelines = usePipelinesStore()
@@ -65,28 +65,28 @@ function setAutoStartDependents(value: boolean) {
65
65
  // Which merge threshold preset governs this task's auto-merge decision + CI-fixer
66
66
  // budget. None selected → the workspace default preset. (The old confidence-based
67
67
  // auto-merge threshold is gone; the `merger` step gates on this policy instead.)
68
- const selectedPreset = computed(() => mergePresets.resolve(props.block.mergePresetId))
68
+ const selectedPreset = computed(() => riskPolicies.resolve(props.block.riskPolicyId))
69
69
  const presetMenu = computed(() => [
70
70
  [
71
71
  {
72
- label: mergePresets.defaultPreset
72
+ label: riskPolicies.defaultPreset
73
73
  ? t('inspector.runSettings.defaultPresetThresholds', {
74
- name: mergePresets.defaultPreset.name,
75
- thresholds: mergePresetThresholds(mergePresets.defaultPreset),
74
+ name: riskPolicies.defaultPreset.name,
75
+ thresholds: riskPolicySummary(riskPolicies.defaultPreset),
76
76
  })
77
77
  : t('inspector.runSettings.workspaceDefault'),
78
78
  icon: 'i-lucide-rotate-ccw',
79
79
  onSelect: () => setPreset(''),
80
80
  },
81
- ...mergePresets.presets.map((p) => ({
82
- label: mergePresetOptionLabel(p),
81
+ ...riskPolicies.presets.map((p) => ({
82
+ label: riskPolicyOptionLabel(p),
83
83
  icon: 'i-lucide-git-merge',
84
84
  onSelect: () => setPreset(p.id),
85
85
  })),
86
86
  ],
87
87
  ])
88
88
  function setPreset(id: string) {
89
- board.updateBlock(props.block.id, { mergePresetId: id })
89
+ board.updateBlock(props.block.id, { riskPolicyId: id })
90
90
  }
91
91
 
92
92
  // ---- model preset ----------------------------------------------------------
@@ -316,7 +316,7 @@ const technicalLabel = computed(() => {
316
316
  </UDropdownMenu>
317
317
  </div>
318
318
  <div v-if="selectedPreset" class="text-[11px] text-slate-400">
319
- <i18n-t keypath="inspector.runSettings.mergePresetDetail" tag="span" scope="global">
319
+ <i18n-t keypath="inspector.runSettings.riskPolicyDetail" tag="span" scope="global">
320
320
  <template #name>
321
321
  <span class="text-slate-300">{{ selectedPreset.name }}</span>
322
322
  </template>
@@ -325,12 +325,12 @@ const technicalLabel = computed(() => {
325
325
  <template #impact>{{ n(selectedPreset.maxImpact, { key: 'percent' }) }}</template>
326
326
  <template #attempts>{{ selectedPreset.ciMaxAttempts }}</template>
327
327
  </i18n-t>
328
- <span v-if="!block.mergePresetId" class="text-slate-500">{{
328
+ <span v-if="!block.riskPolicyId" class="text-slate-500">{{
329
329
  t('inspector.runSettings.workspaceDefaultParen')
330
330
  }}</span>
331
331
  </div>
332
332
  <div v-else class="text-[11px] text-slate-500">
333
- {{ t('inspector.runSettings.mergePresetEmpty') }}
333
+ {{ t('inspector.runSettings.riskPolicyEmpty') }}
334
334
  </div>
335
335
  <p class="mt-1 text-[11px] leading-snug text-slate-500">
336
336
  {{ t('inspector.runSettings.mergePolicyHint') }}
@@ -466,6 +466,28 @@ async function clone(p: Pipeline) {
466
466
  "
467
467
  @click="pipelines.toggleDraftTesterQuality(unit.index)"
468
468
  />
469
+ <!-- Auto-recommendation: the requirements reviewer pre-answers findings it
470
+ judges answerable from universal practice / provided context, offering them
471
+ as editable default answers (requirements-review steps only). On by default. -->
472
+ <UButton
473
+ v-if="unit.kind === 'requirements-review'"
474
+ :icon="
475
+ pipelines.draftAutoRecommendEnabled(unit.index)
476
+ ? 'i-lucide-sparkles'
477
+ : 'i-lucide-circle-slash'
478
+ "
479
+ :color="
480
+ pipelines.draftAutoRecommendEnabled(unit.index) ? 'secondary' : 'neutral'
481
+ "
482
+ variant="ghost"
483
+ size="xs"
484
+ :title="
485
+ pipelines.draftAutoRecommendEnabled(unit.index)
486
+ ? t('pipeline.builder.autoRecommendDisableTooltip')
487
+ : t('pipeline.builder.autoRecommendEnableTooltip')
488
+ "
489
+ @click="pipelines.toggleDraftAutoRecommend(unit.index)"
490
+ />
469
491
  <UButton
470
492
  icon="i-lucide-chevron-up"
471
493
  color="neutral"