@cat-factory/app 0.68.1 → 0.69.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.
@@ -41,6 +41,16 @@ const container = computed(() =>
41
41
  ui.addTaskContainerId ? board.getBlock(ui.addTaskContainerId) : undefined,
42
42
  )
43
43
 
44
+ // The enclosing service frame: the container itself when it's a frame, else its parent
45
+ // frame (a module's parent). Drives which task types are offered — a document repository
46
+ // only authors documents/spikes, so the other kinds are hidden (and rejected server-side).
47
+ const frame = computed(() => {
48
+ const c = container.value
49
+ if (!c) return undefined
50
+ return c.level === 'frame' ? c : c.parentId ? board.getBlock(c.parentId) : undefined
51
+ })
52
+ const isDocRepo = computed(() => frame.value?.type === 'document')
53
+
44
54
  const title = ref('')
45
55
  const description = ref('')
46
56
  const saving = ref(false)
@@ -53,13 +63,27 @@ const technical = ref(false)
53
63
  // delegates to <RecurringPipelineModal> instead of creating a one-off task here.
54
64
  type TaskTypeChoice = CreateTaskType | 'recurring'
55
65
  const taskType = ref<TaskTypeChoice>('feature')
56
- const TASK_TYPES = computed<{ value: TaskTypeChoice; label: string; icon: string }[]>(() => [
57
- { value: 'feature', label: t('board.addTask.types.feature'), icon: 'i-lucide-sparkles' },
58
- { value: 'bug', label: t('board.addTask.types.bug'), icon: 'i-lucide-bug' },
59
- { value: 'document', label: t('board.addTask.types.document'), icon: 'i-lucide-file-text' },
60
- { value: 'spike', label: t('board.addTask.types.spike'), icon: 'i-lucide-flask-conical' },
61
- { value: 'recurring', label: t('board.addTask.types.recurring'), icon: 'i-lucide-repeat' },
62
- ])
66
+ const TASK_TYPES = computed<{ value: TaskTypeChoice; label: string; icon: string }[]>(() => {
67
+ const all: { value: TaskTypeChoice; label: string; icon: string }[] = [
68
+ { value: 'feature', label: t('board.addTask.types.feature'), icon: 'i-lucide-sparkles' },
69
+ { value: 'bug', label: t('board.addTask.types.bug'), icon: 'i-lucide-bug' },
70
+ { value: 'document', label: t('board.addTask.types.document'), icon: 'i-lucide-file-text' },
71
+ { value: 'spike', label: t('board.addTask.types.spike'), icon: 'i-lucide-flask-conical' },
72
+ { value: 'recurring', label: t('board.addTask.types.recurring'), icon: 'i-lucide-repeat' },
73
+ ]
74
+ // A document repository only accepts document/spike tasks (see BoardService.addTask).
75
+ return isDocRepo.value ? all.filter((k) => k.value === 'document' || k.value === 'spike') : all
76
+ })
77
+ // Keep the selection valid when the target is a document repo (default to document).
78
+ watch(
79
+ isDocRepo,
80
+ (doc) => {
81
+ if (doc && taskType.value !== 'document' && taskType.value !== 'spike') {
82
+ taskType.value = 'document'
83
+ }
84
+ },
85
+ { immediate: true },
86
+ )
63
87
  const isRecurring = computed(() => taskType.value === 'recurring')
64
88
 
65
89
  // Per-type fields (only the ones relevant to the chosen type are shown / sent).
@@ -293,7 +317,10 @@ watch(open, (isOpen) => {
293
317
  title.value = ''
294
318
  description.value = ''
295
319
  saving.value = false
296
- taskType.value = 'feature'
320
+ // This reset runs after the `isDocRepo` watcher in the same open tick, so it must pick the
321
+ // doc-repo-aware default itself — a document frame only offers document/spike, so `feature`
322
+ // would leave the selector on a hidden, server-rejected value.
323
+ taskType.value = isDocRepo.value ? 'document' : 'feature'
297
324
  technical.value = false
298
325
  severity.value = ''
299
326
  stepsToReproduce.value = ''
@@ -4,7 +4,7 @@
4
4
  // adapt it (in a sandbox container) — either by cloning a chosen reference
5
5
  // architecture, or from scratch following a freeform prompt. The modal pairs the
6
6
  // launch form with the managed base list.
7
- import type { BootstrapStatus, ReferenceArchitecture } from '~/types/domain'
7
+ import type { BootstrapStatus, FrameRepoType, ReferenceArchitecture } from '~/types/domain'
8
8
  // Explicit import (see GitHubPanel): the auto-import name for github/GitHubConnect
9
9
  // doesn't match the `<GitHubConnect>` tag, so bind it directly.
10
10
  import GitHubConnect from '~/components/github/GitHubConnect.vue'
@@ -74,6 +74,11 @@ const isPrivate = ref(true)
74
74
  const instructions = ref('')
75
75
  const launching = ref(false)
76
76
 
77
+ // The behavioural repo role for the bootstrapped frame; `service` (backend) by default. The
78
+ // options are shared with the import modal via useFrameRepoTypeItems.
79
+ const selectedType = ref<FrameRepoType>('service')
80
+ const typeItems = useFrameRepoTypeItems()
81
+
77
82
  const usingReference = computed(() => mode.value === 'reference')
78
83
 
79
84
  // Mirror of the backend `slugField` rule (@cat-factory/contracts bootstrap
@@ -210,6 +215,7 @@ async function launch() {
210
215
  description: description.value.trim(),
211
216
  private: isPrivate.value,
212
217
  instructions: instructions.value.trim(),
218
+ type: selectedType.value,
213
219
  })
214
220
  if (job.status === 'failed') {
215
221
  // The container couldn't even start (pre-flight failure, e.g. the target
@@ -233,6 +239,8 @@ async function launch() {
233
239
  repoName.value = ''
234
240
  description.value = ''
235
241
  instructions.value = ''
242
+ // Reset the repo role too, so a later bootstrap doesn't silently inherit this one's type.
243
+ selectedType.value = 'service'
236
244
  // The run is now tracked on the board, so get out of the way: close the
237
245
  // dialog as soon as bootstrapping has actually started.
238
246
  ui.closeBootstrap()
@@ -469,6 +477,13 @@ const statusLabel = computed<Record<BootstrapStatus, string>>(() => ({
469
477
  </div>
470
478
  </UFormField>
471
479
 
480
+ <UFormField
481
+ :label="t('bootstrap.repoType.label')"
482
+ :description="t('bootstrap.repoType.help')"
483
+ >
484
+ <USelect v-model="selectedType" :items="typeItems" value-key="value" class="w-full" />
485
+ </UFormField>
486
+
472
487
  <UFormField
473
488
  :label="t('bootstrap.description.label')"
474
489
  :description="t('bootstrap.description.help')"
@@ -11,12 +11,19 @@
11
11
  // browses its tree and picks the service's directory before adding (and may add
12
12
  // more than one, a subset of the repo's services).
13
13
  import { refDebounced } from '@vueuse/core'
14
+ import type { FrameRepoType } from '~/types/domain'
14
15
  import GitHubConnect from '~/components/github/GitHubConnect.vue'
15
16
  import RepoTreeBrowser from '~/components/github/RepoTreeBrowser.vue'
16
17
  import ServiceTestConfig from '~/components/panels/inspector/ServiceTestConfig.vue'
17
18
  import ServiceFragments from '~/components/panels/inspector/ServiceFragments.vue'
18
19
 
19
20
  const { t } = useI18n()
21
+
22
+ // The behavioural repo role for the imported frame. `service` (backend) is the default so
23
+ // existing muscle memory is unchanged; the options are the four onboardable roles (shared
24
+ // with the bootstrap modal via useFrameRepoTypeItems).
25
+ const selectedType = ref<FrameRepoType>('service')
26
+ const typeItems = useFrameRepoTypeItems()
20
27
  const ui = useUiStore()
21
28
  const github = useGitHubStore()
22
29
  const board = useBoardStore()
@@ -157,6 +164,7 @@ function resetSelection() {
157
164
  isMonorepo.value = false
158
165
  configuredBlockId.value = undefined
159
166
  repoSearch.value = ''
167
+ selectedType.value = 'service'
160
168
  }
161
169
 
162
170
  // Clear the current repo selection (the combobox's trailing ✕) so the user can pick a
@@ -219,6 +227,7 @@ async function add() {
219
227
  const block = await board.addServiceFromRepo(selectedRepoId.value, {
220
228
  directory: isMonorepo.value ? selectedDirectory.value : undefined,
221
229
  isMonorepo: isMonorepo.value,
230
+ type: selectedType.value,
222
231
  })
223
232
  // Refresh the projection so the new repo↔block link is reflected locally.
224
233
  await github.load()
@@ -324,6 +333,13 @@ function done() {
324
333
  </div>
325
334
  </UFormField>
326
335
 
336
+ <UFormField
337
+ :label="t('github.addService.repoType')"
338
+ :description="t('github.addService.repoTypeHint')"
339
+ >
340
+ <USelect v-model="selectedType" :items="typeItems" value-key="value" class="w-full" />
341
+ </UFormField>
342
+
327
343
  <!-- monorepo handling: flag + directory picker -->
328
344
  <div v-if="selectedRepoId !== undefined" class="space-y-3">
329
345
  <USwitch
@@ -0,0 +1,29 @@
1
+ import { FRAME_REPO_TYPES } from '@cat-factory/contracts'
2
+ import type { FrameRepoType } from '~/types/domain'
3
+ import { BLOCK_TYPE_META } from '~/utils/catalog'
4
+
5
+ // One static, typed message key per onboardable repo role. The exhaustive Record means adding
6
+ // a FrameRepoType fails typecheck until it has a label here (the tier-2 dynamic-lookup guard),
7
+ // and keeping the keys as literals lets the i18n drift check see them.
8
+ const REPO_TYPE_LABEL_KEYS: Record<FrameRepoType, string> = {
9
+ service: 'board.repoTypes.service',
10
+ frontend: 'board.repoTypes.frontend',
11
+ library: 'board.repoTypes.library',
12
+ document: 'board.repoTypes.document',
13
+ }
14
+
15
+ /**
16
+ * The repository-type options for the import + bootstrap selectors: one entry per
17
+ * FRAME_REPO_TYPES role (i18n label + the shared block-type icon). Shared so
18
+ * AddServiceFromRepoModal and BootstrapModal offer exactly the same set and can't drift.
19
+ */
20
+ export function useFrameRepoTypeItems() {
21
+ const { t } = useI18n()
22
+ return computed(() =>
23
+ FRAME_REPO_TYPES.map((value) => ({
24
+ value,
25
+ label: t(REPO_TYPE_LABEL_KEYS[value]),
26
+ icon: BLOCK_TYPE_META[value].icon,
27
+ })),
28
+ )
29
+ }
@@ -1,7 +1,13 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref } from 'vue'
3
3
  import type { UpdateBlockInput } from '@cat-factory/contracts'
4
- import type { Block, BlockType, CreateTaskType, TaskTypeFields } from '~/types/domain'
4
+ import type {
5
+ Block,
6
+ BlockType,
7
+ CreateTaskType,
8
+ FrameRepoType,
9
+ TaskTypeFields,
10
+ } from '~/types/domain'
5
11
  import { useServicesStore } from '~/stores/services'
6
12
  import { useWorkspaceStore } from '~/stores/workspace'
7
13
  import { useBlockQueries } from '~/composables/useBlockQueries'
@@ -79,12 +85,13 @@ export const useBoardStore = defineStore('board', () => {
79
85
  */
80
86
  async function addServiceFromRepo(
81
87
  repoGithubId: number,
82
- opts?: { directory?: string; isMonorepo?: boolean },
88
+ opts?: { directory?: string; isMonorepo?: boolean; type?: FrameRepoType },
83
89
  ): Promise<Block> {
84
90
  const block = await api.addServiceFromRepo(useWorkspaceStore().requireId(), {
85
91
  repoGithubId,
86
92
  ...(opts?.directory ? { directory: opts.directory } : {}),
87
93
  ...(opts?.isMonorepo !== undefined ? { isMonorepo: opts.isMonorepo } : {}),
94
+ ...(opts?.type ? { type: opts.type } : {}),
88
95
  })
89
96
  upsert(block)
90
97
  return block
@@ -18,6 +18,7 @@
18
18
  export type {
19
19
  BlockStatus,
20
20
  BlockType,
21
+ FrameRepoType,
21
22
  BlockLevel,
22
23
  TaskType,
23
24
  CreateTaskType,
@@ -39,6 +39,8 @@ const AGENT_KINDS: AgentKind[] = [
39
39
  const BLOCK_TYPES: BlockType[] = [
40
40
  'frontend',
41
41
  'service',
42
+ 'library',
43
+ 'document',
42
44
  'api',
43
45
  'database',
44
46
  'queue',
@@ -519,6 +519,8 @@ type BlockTypeMeta = { label: string; icon: string; accent: string }
519
519
  export const BLOCK_TYPE_META: Record<BlockType, BlockTypeMeta> = {
520
520
  frontend: { label: 'Frontend', icon: 'i-lucide-monitor', accent: '#60a5fa' },
521
521
  service: { label: 'Service', icon: 'i-lucide-server', accent: '#a78bfa' },
522
+ library: { label: 'Library', icon: 'i-lucide-package', accent: '#f472b6' },
523
+ document: { label: 'Document repository', icon: 'i-lucide-book-text', accent: '#c084fc' },
522
524
  api: { label: 'API', icon: 'i-lucide-route', accent: '#22d3ee' },
523
525
  database: { label: 'Database', icon: 'i-lucide-database', accent: '#34d399' },
524
526
  queue: { label: 'Queue', icon: 'i-lucide-list-ordered', accent: '#fbbf24' },
@@ -51,6 +51,12 @@
51
51
  "accountSettings": "Account settings"
52
52
  },
53
53
  "board": {
54
+ "repoTypes": {
55
+ "service": "Service",
56
+ "frontend": "Frontend",
57
+ "library": "Library",
58
+ "document": "Document repository"
59
+ },
54
60
  "toolbar": {
55
61
  "addService": "Add service",
56
62
  "decisionWord": "decision | decisions",
@@ -2184,6 +2190,8 @@
2184
2190
  "connectFirst": "Connect this workspace to GitHub first. Link an installation the App is already on, or install it.",
2185
2191
  "repository": "Repository",
2186
2192
  "repositoryHint": "Repositories the GitHub App can access. Don't see yours? Grant the App access below, then refresh.",
2193
+ "repoType": "Repository type",
2194
+ "repoTypeHint": "What this repo is: a backend service, a frontend app, a shared library, or a document repository (docs/spikes only).",
2187
2195
  "noReposAvailable": "No repositories available yet. Grant the App access to one below, then refresh.",
2188
2196
  "searchPlaceholder": "Search repositories by owner or name…",
2189
2197
  "searchMinChars": "Type at least {min} character to search. | Type at least {min} characters to search.",
@@ -3613,6 +3621,10 @@
3613
3621
  "label": "Grant the App access to this repo",
3614
3622
  "title": "Open the App's installation settings to grant it access to the new repo"
3615
3623
  },
3624
+ "repoType": {
3625
+ "label": "Repository type",
3626
+ "help": "What this repo is: a backend service, a frontend app, a shared library, or a document repository (docs/spikes only)."
3627
+ },
3616
3628
  "description": {
3617
3629
  "label": "Description",
3618
3630
  "help": "Optional one-line summary for the repo."
@@ -39,6 +39,12 @@
39
39
  "infrastructure": "Infraestructura"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "Servicio",
44
+ "frontend": "Frontend",
45
+ "library": "Biblioteca",
46
+ "document": "Repositorio de documentación"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "Añadir servicio",
44
50
  "decisionWord": "decisión | decisiones",
@@ -2146,7 +2152,9 @@
2146
2152
  "addedTitle": "Servicio añadido",
2147
2153
  "addedDescription": "{title} está en el tablero, configúralo abajo.",
2148
2154
  "addFailedTitle": "No se pudo añadir el servicio"
2149
- }
2155
+ },
2156
+ "repoType": "Tipo de repositorio",
2157
+ "repoTypeHint": "Qué es este repositorio: un servicio backend, una aplicación frontend, una biblioteca compartida o un repositorio de documentación (solo documentos/spikes)."
2150
2158
  },
2151
2159
  "repoTree": {
2152
2160
  "root": "raíz",
@@ -3537,6 +3545,10 @@
3537
3545
  "bootstrapFailed": "No se pudo inicializar",
3538
3546
  "saveArchFailed": "No se pudo guardar la arquitectura de referencia",
3539
3547
  "deleteFailed": "No se pudo eliminar"
3548
+ },
3549
+ "repoType": {
3550
+ "label": "Tipo de repositorio",
3551
+ "help": "Qué es este repositorio: un servicio backend, una aplicación frontend, una biblioteca compartida o un repositorio de documentación (solo documentos/spikes)."
3540
3552
  }
3541
3553
  },
3542
3554
  "mergePreset": {
@@ -39,6 +39,12 @@
39
39
  "infrastructure": "Infrastructure"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "Service",
44
+ "frontend": "Frontend",
45
+ "library": "Bibliothèque",
46
+ "document": "Dépôt de documentation"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "Ajouter un service",
44
50
  "decisionWord": "décision | décisions",
@@ -2146,7 +2152,9 @@
2146
2152
  "addedTitle": "Service ajouté",
2147
2153
  "addedDescription": "{title} est sur le tableau, configurez-le ci-dessous.",
2148
2154
  "addFailedTitle": "Impossible d'ajouter le service"
2149
- }
2155
+ },
2156
+ "repoType": "Type de dépôt",
2157
+ "repoTypeHint": "Ce qu'est ce dépôt : un service backend, une application frontend, une bibliothèque partagée ou un dépôt de documentation (documents/spikes uniquement)."
2150
2158
  },
2151
2159
  "repoTree": {
2152
2160
  "root": "racine",
@@ -3537,6 +3545,10 @@
3537
3545
  "bootstrapFailed": "Impossible d'initialiser",
3538
3546
  "saveArchFailed": "Impossible d'enregistrer l'architecture de référence",
3539
3547
  "deleteFailed": "Impossible de supprimer"
3548
+ },
3549
+ "repoType": {
3550
+ "label": "Type de dépôt",
3551
+ "help": "Ce qu'est ce dépôt : un service backend, une application frontend, une bibliothèque partagée ou un dépôt de documentation (documents/spikes uniquement)."
3540
3552
  }
3541
3553
  },
3542
3554
  "mergePreset": {
@@ -39,6 +39,12 @@
39
39
  "accountSettings": "הגדרות חשבון"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "שירות",
44
+ "frontend": "פרונט-אנד",
45
+ "library": "ספרייה",
46
+ "document": "מאגר תיעוד"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "הוסף שירות",
44
50
  "decisionWord": "החלטה | החלטות",
@@ -2157,7 +2163,9 @@
2157
2163
  "addedTitle": "השירות נוסף",
2158
2164
  "addedDescription": "{title} על הלוח, הגדר אותו למטה.",
2159
2165
  "addFailedTitle": "לא ניתן היה להוסיף שירות"
2160
- }
2166
+ },
2167
+ "repoType": "סוג המאגר",
2168
+ "repoTypeHint": "מה המאגר הזה: שירות בק-אנד, אפליקציית פרונט-אנד, ספרייה משותפת או מאגר תיעוד (מסמכים/ספייקים בלבד)."
2161
2169
  },
2162
2170
  "repoTree": {
2163
2171
  "root": "שורש",
@@ -3548,6 +3556,10 @@
3548
3556
  "bootstrapFailed": "לא ניתן היה לאתחל",
3549
3557
  "saveArchFailed": "לא ניתן היה לשמור ארכיטקטורת ייחוס",
3550
3558
  "deleteFailed": "לא ניתן היה למחוק"
3559
+ },
3560
+ "repoType": {
3561
+ "label": "סוג המאגר",
3562
+ "help": "מה המאגר הזה: שירות בק-אנד, אפליקציית פרונט-אנד, ספרייה משותפת או מאגר תיעוד (מסמכים/ספייקים בלבד)."
3551
3563
  }
3552
3564
  },
3553
3565
  "mergePreset": {
@@ -39,6 +39,12 @@
39
39
  "accountSettings": "アカウント設定"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "サービス",
44
+ "frontend": "フロントエンド",
45
+ "library": "ライブラリ",
46
+ "document": "ドキュメントリポジトリ"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "サービスを追加",
44
50
  "decisionWord": "決定 | 決定",
@@ -2159,7 +2165,9 @@
2159
2165
  "addedTitle": "サービスを追加しました",
2160
2166
  "addedDescription": "{title}がボードに追加されました。以下で設定してください。",
2161
2167
  "addFailedTitle": "サービスを追加できませんでした"
2162
- }
2168
+ },
2169
+ "repoType": "リポジトリの種類",
2170
+ "repoTypeHint": "このリポジトリの種類: バックエンドサービス、フロントエンドアプリ、共有ライブラリ、またはドキュメントリポジトリ(ドキュメント/スパイクのみ)。"
2163
2171
  },
2164
2172
  "repoTree": {
2165
2173
  "root": "ルート",
@@ -3550,6 +3558,10 @@
3550
3558
  "bootstrapFailed": "ブートストラップできませんでした",
3551
3559
  "saveArchFailed": "リファレンスアーキテクチャを保存できませんでした",
3552
3560
  "deleteFailed": "削除できませんでした"
3561
+ },
3562
+ "repoType": {
3563
+ "label": "リポジトリの種類",
3564
+ "help": "このリポジトリの種類: バックエンドサービス、フロントエンドアプリ、共有ライブラリ、またはドキュメントリポジトリ(ドキュメント/スパイクのみ)。"
3553
3565
  }
3554
3566
  },
3555
3567
  "mergePreset": {
@@ -39,6 +39,12 @@
39
39
  "infrastructure": "Infrastruktura"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "Usługa",
44
+ "frontend": "Frontend",
45
+ "library": "Biblioteka",
46
+ "document": "Repozytorium dokumentacji"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "Dodaj usługę",
44
50
  "decisionWord": "decyzja | decyzje | decyzji",
@@ -2146,7 +2152,9 @@
2146
2152
  "addedTitle": "Dodano usługę",
2147
2153
  "addedDescription": "{title} jest na tablicy, skonfiguruj ją poniżej.",
2148
2154
  "addFailedTitle": "Nie udało się dodać usługi"
2149
- }
2155
+ },
2156
+ "repoType": "Typ repozytorium",
2157
+ "repoTypeHint": "Czym jest to repozytorium: usługą backendową, aplikacją frontendową, współdzieloną biblioteką lub repozytorium dokumentacji (tylko dokumenty/spike'i)."
2150
2158
  },
2151
2159
  "repoTree": {
2152
2160
  "root": "katalog główny",
@@ -3537,6 +3545,10 @@
3537
3545
  "bootstrapFailed": "Nie udało się zainicjować",
3538
3546
  "saveArchFailed": "Nie udało się zapisać architektury referencyjnej",
3539
3547
  "deleteFailed": "Nie udało się usunąć"
3548
+ },
3549
+ "repoType": {
3550
+ "label": "Typ repozytorium",
3551
+ "help": "Czym jest to repozytorium: usługą backendową, aplikacją frontendową, współdzieloną biblioteką lub repozytorium dokumentacji (tylko dokumenty/spike'i)."
3540
3552
  }
3541
3553
  },
3542
3554
  "mergePreset": {
@@ -39,6 +39,12 @@
39
39
  "accountSettings": "Hesap ayarları"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "Servis",
44
+ "frontend": "Frontend",
45
+ "library": "Kütüphane",
46
+ "document": "Doküman deposu"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "Servis ekle",
44
50
  "decisionWord": "karar | karar",
@@ -2159,7 +2165,9 @@
2159
2165
  "addedTitle": "Servis eklendi",
2160
2166
  "addedDescription": "{title} panoda, aşağıdan yapılandırın.",
2161
2167
  "addFailedTitle": "Servis eklenemedi"
2162
- }
2168
+ },
2169
+ "repoType": "Depo türü",
2170
+ "repoTypeHint": "Bu deponun türü: bir backend servisi, bir frontend uygulaması, paylaşılan bir kütüphane veya bir doküman deposu (yalnızca doküman/spike)."
2163
2171
  },
2164
2172
  "repoTree": {
2165
2173
  "root": "kök",
@@ -3550,6 +3558,10 @@
3550
3558
  "bootstrapFailed": "Başlatılamadı",
3551
3559
  "saveArchFailed": "Referans mimari kaydedilemedi",
3552
3560
  "deleteFailed": "Silinemedi"
3561
+ },
3562
+ "repoType": {
3563
+ "label": "Depo türü",
3564
+ "help": "Bu deponun türü: bir backend servisi, bir frontend uygulaması, paylaşılan bir kütüphane veya bir doküman deposu (yalnızca doküman/spike)."
3553
3565
  }
3554
3566
  },
3555
3567
  "mergePreset": {
@@ -39,6 +39,12 @@
39
39
  "infrastructure": "Інфраструктура"
40
40
  },
41
41
  "board": {
42
+ "repoTypes": {
43
+ "service": "Сервіс",
44
+ "frontend": "Фронтенд",
45
+ "library": "Бібліотека",
46
+ "document": "Репозиторій документації"
47
+ },
42
48
  "toolbar": {
43
49
  "addService": "Додати сервіс",
44
50
  "decisionWord": "рішення | рішення | рішень",
@@ -2146,7 +2152,9 @@
2146
2152
  "addedTitle": "Сервіс додано",
2147
2153
  "addedDescription": "{title} на дошці, налаштуйте його нижче.",
2148
2154
  "addFailedTitle": "Не вдалося додати сервіс"
2149
- }
2155
+ },
2156
+ "repoType": "Тип репозиторію",
2157
+ "repoTypeHint": "Що це за репозиторій: бекенд-сервіс, фронтенд-застосунок, спільна бібліотека або репозиторій документації (лише документи/спайки)."
2150
2158
  },
2151
2159
  "repoTree": {
2152
2160
  "root": "корінь",
@@ -3537,6 +3545,10 @@
3537
3545
  "bootstrapFailed": "Не вдалося ініціалізувати",
3538
3546
  "saveArchFailed": "Не вдалося зберегти еталонну архітектуру",
3539
3547
  "deleteFailed": "Не вдалося видалити"
3548
+ },
3549
+ "repoType": {
3550
+ "label": "Тип репозиторію",
3551
+ "help": "Що це за репозиторій: бекенд-сервіс, фронтенд-застосунок, спільна бібліотека або репозиторій документації (лише документи/спайки)."
3540
3552
  }
3541
3553
  },
3542
3554
  "mergePreset": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.68.1",
3
+ "version": "0.69.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",
@@ -34,7 +34,7 @@
34
34
  "valibot": "^1.4.2",
35
35
  "vue": "^3.5.39",
36
36
  "wretch": "^3.0.9",
37
- "@cat-factory/contracts": "0.73.0"
37
+ "@cat-factory/contracts": "0.74.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@toad-contracts/testing": "0.3.2",