@cat-factory/app 0.246.0 → 0.248.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 (41) hide show
  1. package/app/components/board/RecurringPipelineModal.vue +57 -2
  2. package/app/components/environments/EnvironmentSetupWizard.vue +1 -1
  3. package/app/components/environments/steps/JourneyStepNav.vue +1 -1
  4. package/app/components/layout/BoardToolbar.vue +1 -1
  5. package/app/components/layout/CommandBar.vue +1 -1
  6. package/app/components/layout/SideBar.vue +2 -2
  7. package/app/components/merge/MergeEffortChips.vue +1 -1
  8. package/app/components/panels/InspectorPanel.vue +1 -1
  9. package/app/components/panels/ResultWindowShell.vue +2 -2
  10. package/app/components/panels/StepResultViewHost.vue +1 -1
  11. package/app/components/panels/inspector/TaskRunSettings.vue +1 -1
  12. package/app/components/settings/MergeClassRulesEditor.vue +1 -1
  13. package/app/components/tasks/BugHuntModal.vue +19 -2
  14. package/app/modular/agent-kinds.ts +1 -1
  15. package/app/modular/journeys/environmentSetup.logic.ts +1 -1
  16. package/app/modular/journeys/environmentSetup.ts +1 -1
  17. package/app/modular/journeys/persistence.ts +1 -1
  18. package/app/modular/nav-contributions.ts +1 -1
  19. package/app/modular/panels/inspector.logic.ts +1 -1
  20. package/app/modular/registry.ts +1 -1
  21. package/app/modular/result-views.ts +1 -1
  22. package/app/modular/slots.ts +1 -1
  23. package/app/plugins/modular.client.ts +1 -1
  24. package/app/stores/agents.ts +1 -1
  25. package/app/stores/environmentWizard.ts +1 -1
  26. package/app/stores/publicApiKeys.spec.ts +1 -0
  27. package/app/stores/tasks.spec.ts +1 -0
  28. package/app/utils/intakePredicates.spec.ts +43 -0
  29. package/app/utils/intakePredicates.ts +25 -0
  30. package/app/utils/modular.ts +1 -1
  31. package/i18n/locales/de.json +4 -0
  32. package/i18n/locales/en.json +4 -0
  33. package/i18n/locales/es.json +4 -0
  34. package/i18n/locales/fr.json +4 -0
  35. package/i18n/locales/he.json +4 -0
  36. package/i18n/locales/it.json +4 -0
  37. package/i18n/locales/ja.json +4 -0
  38. package/i18n/locales/pl.json +4 -0
  39. package/i18n/locales/tr.json +4 -0
  40. package/i18n/locales/uk.json +4 -0
  41. package/package.json +2 -2
@@ -11,6 +11,7 @@ import type { IssueIntakeRefusalReason } from '@cat-factory/contracts'
11
11
  import { BUILTIN_TASK_SOURCE_KINDS } from '@cat-factory/contracts'
12
12
  import { apiErrorReason } from '~/composables/api/errors'
13
13
  import { pipelineAllowedForSchedule } from '~/utils/pipeline'
14
+ import { appliesIntakePredicate } from '~/utils/intakePredicates'
14
15
 
15
16
  const ui = useUiStore()
16
17
  const board = useBoardStore()
@@ -48,6 +49,10 @@ const intakeSource = ref<TaskSourceKind | null>(null)
48
49
  const intakeJiraProjectKey = ref('')
49
50
  const intakeLinearTeamId = ref('')
50
51
  const intakeGithubRepo = ref('')
52
+ // A GitLab project is its full path with namespace, which NESTS (`group/sub/project`), so it is
53
+ // its own field rather than a reuse of the GitHub one: the two are not the same shape and the two
54
+ // providers read different legs of the stored board scope.
55
+ const intakeGitlabProject = ref('')
51
56
  /**
52
57
  * The board scope for a DEPLOYMENT-REGISTERED source, held opaquely. Its own field rather than
53
58
  * reusing one of the three above, mirroring `issueIntakeConfigSchema.board.boardId`: only that
@@ -181,6 +186,20 @@ const intakeDispatch = computed<'queue' | 'per-ticket'>(() =>
181
186
  // (`supportsIntake`, derived from the registered provider) rather than inferred from the id here.
182
187
  const intakeSources = computed(() => tasks.offeredSources.filter((s) => s.supportsIntake))
183
188
 
189
+ /** The selected source's state, which is what declares the predicates it will not apply. */
190
+ const intakeSourceState = computed(() =>
191
+ intakeSource.value ? tasks.descriptorFor(intakeSource.value) : undefined,
192
+ )
193
+ const intakeSourceLabel = computed(() => intakeSourceState.value?.label ?? '')
194
+ /**
195
+ * Whether the selected source will actually apply the issue-type predicate. A schedule fires
196
+ * unattended, and `BugIntakeService` defaults the predicate to `bug`, so a source that drops it
197
+ * starts the bugfix pipeline on whatever is oldest and open with nothing to point at.
198
+ */
199
+ const intakeIssueTypeApplies = computed(() =>
200
+ appliesIntakePredicate(intakeSourceState.value, 'issueType'),
201
+ )
202
+
184
203
  watch(open, (isOpen) => {
185
204
  if (!isOpen) return
186
205
  name.value = ''
@@ -199,6 +218,7 @@ watch(open, (isOpen) => {
199
218
  intakeJiraProjectKey.value = ''
200
219
  intakeLinearTeamId.value = ''
201
220
  intakeGithubRepo.value = ''
221
+ intakeGitlabProject.value = ''
202
222
  intakeBoardId.value = ''
203
223
  trackerTrigger.value = false
204
224
  intakeTitleFragment.value = ''
@@ -229,6 +249,7 @@ const { requestClose } = useUnsavedGuard({
229
249
  intakeJiraProjectKey: intakeJiraProjectKey.value.trim(),
230
250
  intakeLinearTeamId: intakeLinearTeamId.value.trim(),
231
251
  intakeGithubRepo: intakeGithubRepo.value.trim(),
252
+ intakeGitlabProject: intakeGitlabProject.value.trim(),
232
253
  intakeBoardId: intakeBoardId.value.trim(),
233
254
  trackerTrigger: trackerTrigger.value,
234
255
  intakeTitleFragment: intakeTitleFragment.value.trim(),
@@ -253,6 +274,7 @@ const intakeReady = computed(() => {
253
274
  if (intakeSource.value === 'jira') return intakeJiraProjectKey.value.trim().length > 0
254
275
  if (intakeSource.value === 'linear') return intakeLinearTeamId.value.trim().length > 0
255
276
  if (intakeSource.value === 'github') return intakeGithubRepo.value.trim().length > 0
277
+ if (intakeSource.value === 'gitlab') return intakeGitlabProject.value.trim().length > 0
256
278
  // A registered source is scoped by its opaque board id. Falling through to `false` here would
257
279
  // make its schedule permanently unsaveable rather than merely unscoped.
258
280
  if (intakeSource.value) return intakeBoardId.value.trim().length > 0
@@ -277,6 +299,9 @@ function buildIssueIntake(): IssueIntakeConfig {
277
299
  ...(source === 'github' && intakeGithubRepo.value.trim()
278
300
  ? { githubRepo: intakeGithubRepo.value.trim() }
279
301
  : {}),
302
+ ...(source === 'gitlab' && intakeGitlabProject.value.trim()
303
+ ? { gitlabProject: intakeGitlabProject.value.trim() }
304
+ : {}),
280
305
  ...(!intakeSourceIsBuiltin.value && intakeBoardId.value.trim()
281
306
  ? { boardId: intakeBoardId.value.trim() }
282
307
  : {}),
@@ -286,7 +311,12 @@ function buildIssueIntake(): IssueIntakeConfig {
286
311
  ? { titleFragment: intakeTitleFragment.value.trim() }
287
312
  : {}),
288
313
  ...(labels.length ? { labels } : {}),
289
- ...(intakeIssueType.value.trim() ? { issueType: intakeIssueType.value.trim() } : {}),
314
+ // Withheld for a source that would drop it anyway, so the STORED config carries no
315
+ // predicate the schedule never applies: a config read back later is evidence of what the
316
+ // schedule does, and a dead `issueType: 'bug'` on it is the same lie the form would tell.
317
+ ...(intakeIssueTypeApplies.value && intakeIssueType.value.trim()
318
+ ? { issueType: intakeIssueType.value.trim() }
319
+ : {}),
290
320
  },
291
321
  ...(source === 'github' && intakeInProgressLabel.value.trim()
292
322
  ? { inProgressLabel: intakeInProgressLabel.value.trim() }
@@ -546,6 +576,15 @@ async function add() {
546
576
  <!-- A GitHub repo ref is always the literal `owner/name` path, never localized. -->
547
577
  <UInput v-model="intakeGithubRepo" placeholder="owner/name" class="w-full" />
548
578
  </UFormField>
579
+ <UFormField
580
+ v-if="intakeSource === 'gitlab'"
581
+ :label="t('board.recurring.intakeGitlabProject')"
582
+ :help="t('board.recurring.intakeGitlabProjectHelp')"
583
+ required
584
+ >
585
+ <!-- A GitLab project path is literal, and NESTS: subgroups are part of it. -->
586
+ <UInput v-model="intakeGitlabProject" placeholder="group/project" class="w-full" />
587
+ </UFormField>
549
588
  <UFormField
550
589
  v-if="intakeSource && !intakeSourceIsBuiltin"
551
590
  :label="t('board.recurring.intakeBoardId')"
@@ -579,7 +618,23 @@ async function add() {
579
618
  </UFormField>
580
619
  <UFormField :label="t('board.recurring.intakeIssueType')">
581
620
  <!-- A literal issue-type example (tracker vocabulary), kept verbatim across locales. -->
582
- <UInput v-model="intakeIssueType" placeholder="bug" class="w-full" />
621
+ <UInput
622
+ v-if="intakeIssueTypeApplies"
623
+ v-model="intakeIssueType"
624
+ placeholder="bug"
625
+ class="w-full"
626
+ />
627
+ <!-- Not a disabled input: this source's provider never sends the predicate, so a box
628
+ still holding a value would read as a filter that is on. Stated here because a
629
+ schedule fires unattended — the only other evidence of the gap is a bugfix run
630
+ started on a docs chore. -->
631
+ <p v-else class="text-xs text-amber-400">
632
+ {{
633
+ t('board.recurring.intakeIssueTypeUnsupported', {
634
+ tracker: intakeSourceLabel,
635
+ })
636
+ }}
637
+ </p>
583
638
  </UFormField>
584
639
  <UFormField
585
640
  v-if="intakeSource === 'github'"
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  // The environment setup wizard shell (shared-stacks slice 7; converted to a
3
3
  // modular-vue journey in slice 3 of the modular-vue adoption —
4
- // docs/initiatives/modular-vue-adoption.md).
4
+ // backend/docs/adr/0049-modular-vue-adoption.md).
5
5
  //
6
6
  // This component is now purely the MODAL + STEPPER CHROME. The step sequence,
7
7
  // forward/back navigation, and resume are owned by the `environment-setup`
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  // Shared footer chrome for a modular-vue journey step (slice 3 of the modular-vue
3
- // adoption — docs/initiatives/modular-vue-adoption.md). Renders the Back control
3
+ // adoption — backend/docs/adr/0049-modular-vue-adoption.md). Renders the Back control
4
4
  // (wired to the host-provided `goBack`, present only when the current entry
5
5
  // declared `allowBack` and there's a prior step) plus a `primary` slot for the
6
6
  // step's own advance affordance, so gating stays local to each step.
@@ -5,7 +5,7 @@ import IconButton from '~/components/common/IconButton.vue'
5
5
 
6
6
  const ui = useUiStore()
7
7
  const board = useBoardStore()
8
- // Toolbar contributions from the shared nav manifest (docs/initiatives/modular-vue-adoption.md,
8
+ // Toolbar contributions from the shared nav manifest (backend/docs/adr/0049-modular-vue-adoption.md,
9
9
  // slice 1). First-party contributes none — this is the reactive extension point a consumer
10
10
  // deployment uses to add a board-toolbar action via `registerAppModule`, gated + rendered like
11
11
  // the sidebar/command entries with zero edits here.
@@ -26,7 +26,7 @@ const library = useFragmentLibraryStore()
26
26
  const access = useWorkspaceAccess()
27
27
 
28
28
  // The static destination catalog + its RBAC/availability gating now comes from
29
- // the shared nav manifest (docs/initiatives/modular-vue-adoption.md, slice 1),
29
+ // the shared nav manifest (backend/docs/adr/0049-modular-vue-adoption.md, slice 1),
30
30
  // rendered here as command entries. The DYNAMIC per-connection commands below
31
31
  // (github/slack/doc/task connect + import) stay local to the palette — they vary
32
32
  // per live connection, so they are not part of the static manifest this slice.
@@ -31,7 +31,7 @@ const providerConnections = useProviderConnectionsStore()
31
31
  const ui = useUiStore()
32
32
 
33
33
  // The nav catalog + its reactive RBAC/availability gating now lives in the shared
34
- // modular-vue manifest (docs/initiatives/modular-vue-adoption.md, slice 1): every
34
+ // modular-vue manifest (backend/docs/adr/0049-modular-vue-adoption.md, slice 1): every
35
35
  // destination is declared once in `nav-contributions.ts`, gated by `navSlotFilter`
36
36
  // over a reactive `gates` service, and rendered here (and in CommandBar / BoardToolbar)
37
37
  // from `useReactiveSlots`. Sections + items appear/disappear reactively as a permission
@@ -230,7 +230,7 @@ watch(
230
230
  </button>
231
231
 
232
232
  <!-- Sections + items come from the shared nav manifest, already gated by the
233
- reactive slotFilter (docs/initiatives/modular-vue-adoption.md, slice 1) — which
233
+ reactive slotFilter (backend/docs/adr/0049-modular-vue-adoption.md, slice 1) — which
234
234
  also drops the `advanced` items in basic interface mode. An empty section is
235
235
  dropped upstream, so there is no per-section `v-if` here.
236
236
  In the rail the section HEADERS go (they'd wrap to nothing at 3.5rem) but the
@@ -6,7 +6,7 @@
6
6
  // Tagging is never mandatory: the parent can always act without a selection, and an untagged
7
7
  // merge records a null tag. This component only chooses; the parent performs the action.
8
8
  //
9
- // See docs/initiatives/merge-track-record.md.
9
+ // See backend/docs/adr/0046-merge-track-record.md.
10
10
  import { computed } from 'vue'
11
11
  import { REVIEW_EFFORTS } from '@cat-factory/contracts'
12
12
  import type { ChangeClass, MergeClassRollup, ReviewEffort } from '~/types/merge'
@@ -524,7 +524,7 @@ const showOriginalDescription = ref(false)
524
524
  `Block | null` is rejected at compile time. `unknown` is the real
525
525
  runtime contract; `as any` is the minimal unblock until the binding
526
526
  types the prop explicitly (filed upstream — see the slice-4 residuals
527
- in docs/initiatives/modular-vue-slice4-upstream-zones.md). -->
527
+ in backend/docs/adr/0049-modular-vue-adoption.md). -->
528
528
  <PanelsOutlet
529
529
  :group="inspectorPanels"
530
530
  :subject="(block ?? null) as any"
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  // Shared modal shell for the agent-run result windows (slice 5 of the modular-vue
3
- // adoption — docs/initiatives/modular-vue-adoption.md; progress in
4
- // docs/initiatives/modular-vue-slice5-progress.md).
3
+ // adoption — backend/docs/adr/0049-modular-vue-adoption.md; progress in
4
+ // backend/docs/adr/0049-modular-vue-adoption.md).
5
5
  //
6
6
  // Every result window (the merger verdict, the tester report, the requirements-review
7
7
  // loop, the gates, …) used to hand-roll the SAME modal chrome — `<Teleport>`, a
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  // Universal dedicated-result-view host (slice 2 of the modular-vue adoption —
3
- // docs/initiatives/modular-vue-adoption.md). An agent archetype can declare a
3
+ // backend/docs/adr/0049-modular-vue-adoption.md). An agent archetype can declare a
4
4
  // `resultView` id (see `~/utils/catalog`); when a step of that kind is opened,
5
5
  // `ui.resultView` is set and this host mounts the matching registered window
6
6
  // instead of the generic `AgentStepDetail` prose panel.
@@ -195,7 +195,7 @@ function setResolveOnMerge(value: WritebackOverride | null) {
195
195
  board.updateBlock(props.block.id, { trackerResolveOnMerge: value })
196
196
  }
197
197
  // Only consulted for runs started through the public API — a task started here keeps its in-app
198
- // clarification window regardless (docs/initiatives/headless-clarification-loop.md).
198
+ // clarification window regardless (backend/docs/adr/0047-headless-clarification-loop.md).
199
199
  function setQuestionsOnPark(value: WritebackOverride | null) {
200
200
  board.updateBlock(props.block.id, { trackerQuestionsOnPark: value })
201
201
  }
@@ -6,7 +6,7 @@
6
6
  //
7
7
  // `unknown` is deliberately not listed: no rule may ever match it (an unclassifiable diff must
8
8
  // fall back to the score ceilings), so offering one would be a lie. See
9
- // docs/initiatives/merge-track-record.md.
9
+ // backend/docs/adr/0046-merge-track-record.md.
10
10
  import { computed } from 'vue'
11
11
  import { autoMergeShare, frictionlessShare, RULEABLE_CHANGE_CLASSES } from '@cat-factory/contracts'
12
12
  import type { MergeClassRule, MergeClassRules } from '~/types/merge'
@@ -36,6 +36,7 @@ import {
36
36
  sourceMenuItems,
37
37
  } from '~/utils/sourcePicker'
38
38
  import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
39
+ import { appliesIntakePredicate } from '~/utils/intakePredicates'
39
40
 
40
41
  const { t, d, n } = useI18n()
41
42
  const ui = useUiStore()
@@ -67,6 +68,13 @@ const {
67
68
 
68
69
  const descriptor = computed(() => (source.value ? tasks.descriptorFor(source.value) : undefined))
69
70
 
71
+ /**
72
+ * Whether the picked tracker will actually apply the issue-type predicate. Asked of the source's
73
+ * own declaration, because a hunt whose type filter is silently dropped ranks and adopts whatever
74
+ * is oldest and open, and `run` sends the `bug` default whether or not the user typed one.
75
+ */
76
+ const issueTypeApplies = computed(() => appliesIntakePredicate(descriptor.value, 'issueType'))
77
+
70
78
  /**
71
79
  * Wording for an addable tracker, as an exhaustive map over the add actions a TRACKER menu can
72
80
  * carry: `enable` is connected but toggled off for this workspace, so the user is never told to
@@ -325,8 +333,17 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
325
333
  </p>
326
334
  </UFormField>
327
335
 
328
- <UFormField :label="t('bugHunt.issueType')" :help="t('bugHunt.issueTypeHelp')">
329
- <UInput v-model="issueType" placeholder="bug" class="w-full" />
336
+ <UFormField
337
+ :label="t('bugHunt.issueType')"
338
+ :help="issueTypeApplies ? t('bugHunt.issueTypeHelp') : undefined"
339
+ >
340
+ <UInput v-if="issueTypeApplies" v-model="issueType" placeholder="bug" class="w-full" />
341
+ <!-- Not a disabled input: this tracker's provider never sends the predicate, so a box
342
+ still holding a value would read as a filter that is on. What it CAN narrow by is
343
+ named instead, since the alternative is a hunt over every open issue. -->
344
+ <p v-else class="text-xs text-amber-400">
345
+ {{ t('bugHunt.issueTypeUnsupported', { tracker: descriptor?.label ?? '' }) }}
346
+ </p>
330
347
  </UFormField>
331
348
 
332
349
  <UFormField :label="t('bugHunt.labels')" :help="t('bugHunt.labelsHelp')">
@@ -2,7 +2,7 @@ import type { AgentArchetype, CustomAgentKind } from '~/types/domain'
2
2
 
3
3
  /**
4
4
  * Custom agent-kind projection (slice 2 of the modular-vue adoption —
5
- * docs/initiatives/modular-vue-adoption.md).
5
+ * backend/docs/adr/0049-modular-vue-adoption.md).
6
6
  *
7
7
  * A deployment's BACKEND-registered agent kinds arrive in the workspace snapshot as
8
8
  * `customAgentKinds` (wire data), folded into the shared per-workspace capability manifest
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Pure navigation logic for the environment-setup journey (slice 3 of the
3
- * modular-vue adoption — docs/initiatives/modular-vue-adoption.md).
3
+ * modular-vue adoption — backend/docs/adr/0049-modular-vue-adoption.md).
4
4
  *
5
5
  * The journey owns only the WIZARD NAVIGATION — the ordered steps
6
6
  * (pick → review → preflight → save), the forward transitions, and the
@@ -18,7 +18,7 @@ import {
18
18
 
19
19
  /**
20
20
  * The environment-setup journey — the slice-3 pilot of the modular-vue adoption
21
- * (docs/initiatives/modular-vue-adoption.md). It replaces the wizard's hand-rolled
21
+ * (backend/docs/adr/0049-modular-vue-adoption.md). It replaces the wizard's hand-rolled
22
22
  * `STEP_ORDER` + `step` ref + `goToStep` navigation (in `stores/environmentWizard.ts`)
23
23
  * with a typed, back/rewind-capable, resumable journey; the per-step data + async
24
24
  * actions stay in that Pinia store, driven by the step components below.
@@ -5,7 +5,7 @@ import { createPiniaJourneyPersistence } from '@modular-vue/journeys'
5
5
 
6
6
  /**
7
7
  * Pinia-backed journey persistence (slice 3 of the modular-vue adoption —
8
- * docs/initiatives/modular-vue-adoption.md).
8
+ * backend/docs/adr/0049-modular-vue-adoption.md).
9
9
  *
10
10
  * A journey's `persistence` adapter is what makes `runtime.start()` mean
11
11
  * RESUME: it probes `keyFor(input)` for an in-flight serialized instance and
@@ -10,7 +10,7 @@ export type { AppSlots } from './slots'
10
10
 
11
11
  /**
12
12
  * The single nav/command catalog for the layer (slice 1 of the modular-vue
13
- * adoption — docs/initiatives/modular-vue-adoption.md).
13
+ * adoption — backend/docs/adr/0049-modular-vue-adoption.md).
14
14
  *
15
15
  * Every destination is declared ONCE here as data and rendered three ways —
16
16
  * `SideBar`, `CommandBar`, `BoardToolbar` — instead of each shell hand-rolling
@@ -3,7 +3,7 @@ import type { Block } from '~/types/domain'
3
3
 
4
4
  /**
5
5
  * Pure definition of the block-inspector panel group (slice 4 of the modular-vue
6
- * adoption — docs/initiatives/modular-vue-adoption.md).
6
+ * adoption — backend/docs/adr/0049-modular-vue-adoption.md).
7
7
  *
8
8
  * The inspector used to be a 631-line `v-if` fan in `InspectorPanel.vue` that
9
9
  * switched its body on the selected block's `level` (frame/module/task/epic/
@@ -8,7 +8,7 @@ import type { AppSlots } from '~/modular/slots'
8
8
 
9
9
  /**
10
10
  * modular-vue registry for the `@cat-factory/app` layer (slice 0 of the
11
- * modular-vue adoption — docs/initiatives/modular-vue-adoption.md).
11
+ * modular-vue adoption — backend/docs/adr/0049-modular-vue-adoption.md).
12
12
  *
13
13
  * This is the frontend analogue of the backend's public registries
14
14
  * (`registerAgentKind`, `registerGate`): a single registry into which the layer
@@ -25,7 +25,7 @@ import type { ResultViewContribution } from './slots'
25
25
 
26
26
  /**
27
27
  * The first-party result-view registry (slice 2 of the modular-vue adoption —
28
- * docs/initiatives/modular-vue-adoption.md).
28
+ * backend/docs/adr/0049-modular-vue-adoption.md).
29
29
  *
30
30
  * Every built-in dedicated result window is contributed as a `ComponentEntry`
31
31
  * to the `resultViews` slot instead of living in a hardcoded `Record` in
@@ -10,7 +10,7 @@ import type { WorkspaceMetadataFieldDefinition } from './workspace-metadata'
10
10
  * The layer's aggregated slot map — the single home for every slot key the
11
11
  * first-party modules (and consumer deployments) contribute to. Grows one key
12
12
  * per converted seam as the modular-vue adoption proceeds
13
- * (docs/initiatives/modular-vue-adoption.md):
13
+ * (backend/docs/adr/0049-modular-vue-adoption.md):
14
14
  *
15
15
  * - `nav` (slice 1) — the nav/command catalog, rendered by the three shells.
16
16
  * - `resultViews` (slice 2) — the id → dedicated result-window registry
@@ -20,7 +20,7 @@ import type { Block, CustomAgentKind, CustomTaskType } from '~/types/domain'
20
20
 
21
21
  /**
22
22
  * Wire the modular-vue registry into the Nuxt app (slice 0 of the modular-vue
23
- * adoption — docs/initiatives/modular-vue-adoption.md).
23
+ * adoption — backend/docs/adr/0049-modular-vue-adoption.md).
24
24
  *
25
25
  * `enforce: 'post'` is load-bearing for the consumer-contribution seam. Nuxt
26
26
  * loads layer plugins before the consuming app's plugins within the same enforce
@@ -16,7 +16,7 @@ import type { AgentArchetype, AgentKind, AgentKindVariant, CustomAgentKind } fro
16
16
 
17
17
  /**
18
18
  * The agent palette catalog (slice 2 of the modular-vue adoption —
19
- * docs/initiatives/modular-vue-adoption.md).
19
+ * backend/docs/adr/0049-modular-vue-adoption.md).
20
20
  *
21
21
  * Reactive union of three sources, none of which mutates the frozen built-in
22
22
  * {@link AGENT_BY_KIND} const any more:
@@ -33,7 +33,7 @@ import { createSaveActions } from '~/stores/environmentWizard/save'
33
33
  // compose provider keys purely on the saved recipe (the build-flag rule). Mirrors the other infra
34
34
  // stores' idiom; the flow state is a singleton so the wizard's step children share it.
35
35
  //
36
- // Since slice 3 of the modular-vue adoption (docs/initiatives/modular-vue-adoption.md) the wizard's
36
+ // Since slice 3 of the modular-vue adoption (backend/docs/adr/0049-modular-vue-adoption.md) the wizard's
37
37
  // step NAVIGATION lives in a modular-vue journey (`app/modular/journeys/environmentSetup.ts`), NOT
38
38
  // here — this store no longer holds a `step` / `STEP_ORDER` / `goToStep`. It is purely the per-frame
39
39
  // data+action layer the journey's step components drive; `beginForFrame` seeds it when a step first
@@ -13,6 +13,7 @@ function key(over: Partial<PublicApiKey> = {}): PublicApiKey {
13
13
  scope: 'write',
14
14
  createdByUserId: null,
15
15
  createdByKeyId: null,
16
+ externalIdentity: null,
16
17
  createdAt: 1,
17
18
  lastUsedAt: null,
18
19
  revokedAt: null,
@@ -33,6 +33,7 @@ const jiraDescriptor: TaskSourceState = {
33
33
  available: true,
34
34
  enabled: true,
35
35
  supportsIntake: true,
36
+ ignoredIntakePredicates: [],
36
37
  // Jira carries its own credentials, so it rides no VCS connection.
37
38
  ridesVcsProvider: null,
38
39
  }
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import type { TaskSourceState } from '@cat-factory/contracts'
3
+ import { appliesIntakePredicate } from './intakePredicates'
4
+
5
+ function state(ignored: TaskSourceState['ignoredIntakePredicates']): TaskSourceState {
6
+ return {
7
+ source: 'gitlab',
8
+ label: 'GitLab Issues',
9
+ icon: 'i-lucide-gitlab',
10
+ credentialFields: [],
11
+ refLabel: 'Issue URL',
12
+ refPlaceholder: 'acme/web#123',
13
+ available: true,
14
+ enabled: true,
15
+ ridesVcsProvider: 'gitlab',
16
+ supportsIntake: true,
17
+ ignoredIntakePredicates: ignored,
18
+ }
19
+ }
20
+
21
+ describe('appliesIntakePredicate', () => {
22
+ it('applies a predicate the source did not name', () => {
23
+ expect(appliesIntakePredicate(state(['issueType']), 'labels')).toBe(true)
24
+ })
25
+
26
+ it('withholds the one it did', () => {
27
+ expect(appliesIntakePredicate(state(['issueType']), 'issueType')).toBe(false)
28
+ })
29
+
30
+ // An unresolved source is not a source with a known gap. Answering `false` here would put a
31
+ // warning under every freshly-opened form, before anything has been picked to warn about.
32
+ it('treats an unresolved source as applying everything', () => {
33
+ expect(appliesIntakePredicate(undefined, 'issueType')).toBe(true)
34
+ })
35
+
36
+ // A state from an older backend carries no array at all; a missing declaration is the same
37
+ // claim as an empty one ("this source applies them all"), not a reason to render nothing.
38
+ it('treats a missing declaration as applying everything', () => {
39
+ const legacy = { ...state([]) } as Partial<TaskSourceState>
40
+ delete legacy.ignoredIntakePredicates
41
+ expect(appliesIntakePredicate(legacy as TaskSourceState, 'issueType')).toBe(true)
42
+ })
43
+ })
@@ -0,0 +1,25 @@
1
+ import type { IssueIntakePredicate, TaskSourceState } from '@cat-factory/contracts'
2
+
3
+ /**
4
+ * Whether the selected task source will actually APPLY an intake predicate the form offers.
5
+ *
6
+ * Both surfaces that compose an intake query (the recurring `bug-intake` schedule and the
7
+ * interactive bug hunt) render one field per predicate, and not every tracker can evaluate every
8
+ * one: Linear has no issue-type notion at all, and GitLab's is a closed set with no member meaning
9
+ * "bug". A field whose value the backend then drops is worse than a missing field, because the
10
+ * schedule saves, fires, and picks up an issue the operator believes it filtered out.
11
+ *
12
+ * The answer comes off `TaskSourceState`, which each provider declares, rather than a source-id
13
+ * check here: restating the backend's compiler in the SPA is exactly how the two drift, and the
14
+ * deployment-registered sources are not on a list this file could hold anyway.
15
+ *
16
+ * An UNRESOLVED source (nothing picked yet, or a state not loaded) answers `true`. The field is
17
+ * shown plainly in that case, which is what it looked like before a source was chosen; claiming a
18
+ * gap we cannot see yet would put a warning under every freshly-opened form.
19
+ */
20
+ export function appliesIntakePredicate(
21
+ state: TaskSourceState | undefined,
22
+ predicate: IssueIntakePredicate,
23
+ ): boolean {
24
+ return !state?.ignoredIntakePredicates?.includes(predicate)
25
+ }
@@ -6,6 +6,6 @@
6
6
  * ergonomics as the layer's auto-imported stores and composables.
7
7
  *
8
8
  * See `app/modular/registry.ts` for the seam itself and
9
- * docs/initiatives/modular-vue-adoption.md for the adoption plan.
9
+ * backend/docs/adr/0049-modular-vue-adoption.md for the adoption plan.
10
10
  */
11
11
  export { registerAppModule } from '~/modular/registry'
@@ -2920,6 +2920,8 @@
2920
2920
  "intakeNoSources": "Verbinden Sie zuerst eine Task-Quelle, um Issues daraus zu ziehen.",
2921
2921
  "intakeNoIntakeSources": "Eine Task-Quelle ist verbunden, aber keine der verbundenen Quellen kann bereits eine geplante Issue-Suche ausführen.",
2922
2922
  "intakeGithubRepo": "Repository",
2923
+ "intakeGitlabProject": "Projekt",
2924
+ "intakeGitlabProjectHelp": "Der vollständige Pfad des GitLab-Projekts, einschließlich aller Untergruppen, z. B. gruppe/untergruppe/projekt.",
2923
2925
  "intakeBoardId": "Board-ID",
2924
2926
  "intakeBoardIdHelp": "Das Board, Projekt oder die Warteschlange, auf die dieser Tracker die Aufnahme eingrenzt. Das Format gibt der Tracker vor.",
2925
2927
  "trackerTrigger": "Läufe durch Tracker-Webhooks starten",
@@ -2931,6 +2933,7 @@
2931
2933
  "intakeLabels": "Labels",
2932
2934
  "intakeLabelsPlaceholder": "durch Komma getrennt",
2933
2935
  "intakeIssueType": "Issue-Typ",
2936
+ "intakeIssueTypeUnsupported": "{tracker} kennt keinen Ticket-Typ mit der Bedeutung „Bug“, daher wendet dieser Zeitplan ihn nicht an. Grenzen Sie die Auswahl stattdessen mit einem Label ein.",
2934
2937
  "intakeInProgressLabel": "In-Bearbeitung-Label",
2935
2938
  "refusalPerTicketRequiresOnDemand": "Ein per Tracker ausgelöster Zeitplan muss bedarfsgesteuert sein. Ein Rhythmus-Tick enthält kein Ticket, das übergeben werden könnte.",
2936
2939
  "refusalPerTicketConflictsWithBugIntake": "Diese Pipeline wählt ihr Issue selbst vom Board und kann daher nicht zusätzlich von einem eingehenden Ticket gesteuert werden. Wählen Sie eine Pipeline ohne Bug-Intake-Schritt."
@@ -4068,6 +4071,7 @@
4068
4071
  "boardsFailed": "Boards konnten nicht geladen werden: {reason}",
4069
4072
  "issueType": "Vorgangstyp",
4070
4073
  "issueTypeHelp": "Standard ist bug. Wird von Trackern ohne Vorgangstypen ignoriert.",
4074
+ "issueTypeUnsupported": "{tracker} kennt keinen Ticket-Typ mit der Bedeutung „Bug“, daher wird dieser Filter nicht angewendet. Grenzen Sie den Scan stattdessen mit einem Label ein.",
4071
4075
  "labels": "Labels",
4072
4076
  "labelsHelp": "Durch Komma getrennt. Alle müssen vorhanden sein.",
4073
4077
  "adoptInto": "Ausgewählten Fehler hinzufügen zu",
@@ -386,6 +386,8 @@
386
386
  "intakeNoSources": "Connect a task source first to pull issues from it.",
387
387
  "intakeNoIntakeSources": "A task source is connected, but none of the connected sources can run a scheduled issue search yet.",
388
388
  "intakeGithubRepo": "Repository",
389
+ "intakeGitlabProject": "Project",
390
+ "intakeGitlabProjectHelp": "The GitLab project's full path, including any subgroups, e.g. group/sub/project.",
389
391
  "intakeBoardId": "Board id",
390
392
  "intakeBoardIdHelp": "The board, project or queue this tracker scopes intake to. Its format is defined by the tracker.",
391
393
  "trackerTrigger": "Start runs from tracker webhooks",
@@ -397,6 +399,7 @@
397
399
  "intakeLabels": "Labels",
398
400
  "intakeLabelsPlaceholder": "comma-separated",
399
401
  "intakeIssueType": "Issue type",
402
+ "intakeIssueTypeUnsupported": "{tracker} has no issue type that means \"bug\", so this schedule will not apply it. Narrow the pickup with a label instead.",
400
403
  "intakeInProgressLabel": "In-progress label",
401
404
  "refusalPerTicketRequiresOnDemand": "A tracker-triggered schedule must be on-demand. A cadence tick carries no ticket to dispatch.",
402
405
  "refusalPerTicketConflictsWithBugIntake": "This pipeline picks its own issue from the board, so it cannot also be driven by a pushed ticket. Choose a pipeline without a bug-intake step."
@@ -4593,6 +4596,7 @@
4593
4596
  "boardsFailed": "Boards could not be loaded: {reason}",
4594
4597
  "issueType": "Issue type",
4595
4598
  "issueTypeHelp": "Defaults to bug. Ignored by trackers with no issue types.",
4599
+ "issueTypeUnsupported": "{tracker} has no issue type that means \"bug\", so this filter is not applied. Narrow the scan with a label instead.",
4596
4600
  "labels": "Labels",
4597
4601
  "labelsHelp": "Comma separated. All of them must be present.",
4598
4602
  "adoptInto": "Add the picked bug to",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "Primero conecta una fuente de tareas para extraer incidencias de ella.",
348
348
  "intakeNoIntakeSources": "Hay una fuente de tareas conectada, pero ninguna de las fuentes conectadas puede ejecutar todavía una búsqueda programada de incidencias.",
349
349
  "intakeGithubRepo": "Repositorio",
350
+ "intakeGitlabProject": "Proyecto",
351
+ "intakeGitlabProjectHelp": "La ruta completa del proyecto de GitLab, incluidos los subgrupos, p. ej. grupo/subgrupo/proyecto.",
350
352
  "intakeBoardId": "ID del tablero",
351
353
  "intakeBoardIdHelp": "El tablero, proyecto o cola al que este rastreador limita la admisión. El formato lo define el rastreador.",
352
354
  "trackerTrigger": "Iniciar ejecuciones desde webhooks del rastreador",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "Etiquetas",
359
361
  "intakeLabelsPlaceholder": "separadas por comas",
360
362
  "intakeIssueType": "Tipo de incidencia",
363
+ "intakeIssueTypeUnsupported": "{tracker} no tiene ningún tipo de incidencia que signifique «bug», así que esta programación no lo aplicará. Acota la selección con una etiqueta en su lugar.",
361
364
  "intakeInProgressLabel": "Etiqueta de en progreso",
362
365
  "refusalPerTicketRequiresOnDemand": "Una programación activada por el rastreador debe ser bajo demanda. Un ciclo de cadencia no lleva ningún ticket que despachar.",
363
366
  "refusalPerTicketConflictsWithBugIntake": "Esta canalización elige su propia incidencia del tablero, así que no puede además activarse con un ticket entrante. Elija una canalización sin paso de admisión de errores."
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "No se pudieron cargar los tableros: {reason}",
4454
4457
  "issueType": "Tipo de incidencia",
4455
4458
  "issueTypeHelp": "Por defecto bug. Se ignora en gestores sin tipos de incidencia.",
4459
+ "issueTypeUnsupported": "{tracker} no tiene ningún tipo de incidencia que signifique «bug», por lo que este filtro no se aplica. Acota el análisis con una etiqueta en su lugar.",
4456
4460
  "labels": "Etiquetas",
4457
4461
  "labelsHelp": "Separadas por comas. Todas deben estar presentes.",
4458
4462
  "adoptInto": "Añadir el error elegido a",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "Connectez d'abord une source de tâches pour en extraire des tickets.",
348
348
  "intakeNoIntakeSources": "Une source de tâches est connectée, mais aucune des sources connectées ne peut encore exécuter une recherche de tickets planifiée.",
349
349
  "intakeGithubRepo": "Dépôt",
350
+ "intakeGitlabProject": "Projet",
351
+ "intakeGitlabProjectHelp": "Le chemin complet du projet GitLab, sous-groupes compris, par exemple groupe/sous-groupe/projet.",
350
352
  "intakeBoardId": "ID du tableau",
351
353
  "intakeBoardIdHelp": "Le tableau, projet ou file d’attente auquel ce traqueur limite la prise en charge. Son format est défini par le traqueur.",
352
354
  "trackerTrigger": "Lancer des exécutions depuis les webhooks du traqueur",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "Étiquettes",
359
361
  "intakeLabelsPlaceholder": "séparées par des virgules",
360
362
  "intakeIssueType": "Type de ticket",
363
+ "intakeIssueTypeUnsupported": "{tracker} n’a aucun type de ticket signifiant « bug », cette planification ne l’appliquera donc pas. Restreignez plutôt la sélection avec une étiquette.",
361
364
  "intakeInProgressLabel": "Étiquette en cours",
362
365
  "refusalPerTicketRequiresOnDemand": "Une planification déclenchée par le traqueur doit être à la demande. Un cycle de cadence ne porte aucun ticket à répartir.",
363
366
  "refusalPerTicketConflictsWithBugIntake": "Ce pipeline choisit lui-même son ticket sur le tableau : il ne peut pas être piloté en plus par un ticket entrant. Choisissez un pipeline sans étape de collecte de bogues."
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "Impossible de charger les tableaux : {reason}",
4454
4457
  "issueType": "Type de ticket",
4455
4458
  "issueTypeHelp": "Par défaut bug. Ignoré par les gestionnaires sans types de tickets.",
4459
+ "issueTypeUnsupported": "{tracker} n’a aucun type de ticket signifiant « bug », ce filtre n’est donc pas appliqué. Restreignez plutôt l’analyse avec une étiquette.",
4456
4460
  "labels": "Étiquettes",
4457
4461
  "labelsHelp": "Séparées par des virgules. Toutes doivent être présentes.",
4458
4462
  "adoptInto": "Ajouter le bug retenu à",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "חבר תחילה מקור משימות כדי למשוך ממנו תקלות.",
348
348
  "intakeNoIntakeSources": "מקור משימות מחובר, אך אף אחד מהמקורות המחוברים אינו יכול עדיין להריץ חיפוש תקלות מתוזמן.",
349
349
  "intakeGithubRepo": "מאגר",
350
+ "intakeGitlabProject": "פרויקט",
351
+ "intakeGitlabProjectHelp": "הנתיב המלא של פרויקט ה-GitLab, כולל תת-קבוצות, לדוגמה group/sub/project.",
350
352
  "intakeBoardId": "מזהה לוח",
351
353
  "intakeBoardIdHelp": "הלוח, הפרויקט או התור שאליהם מערכת המעקב מגבילה את הקליטה. התבנית נקבעת על ידי מערכת המעקב.",
352
354
  "trackerTrigger": "להתחיל הרצות מ-webhooks של מערכת המעקב",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "תוויות",
359
361
  "intakeLabelsPlaceholder": "מופרדות בפסיקים",
360
362
  "intakeIssueType": "סוג תקלה",
363
+ "intakeIssueTypeUnsupported": "ל-{tracker} אין סוג פנייה שמשמעותו „bug”, לכן תזמון זה לא יחיל אותו. צמצמו את הבחירה באמצעות תווית במקום זאת.",
361
364
  "intakeInProgressLabel": "תווית בתהליך",
362
365
  "refusalPerTicketRequiresOnDemand": "תזמון המופעל ממערכת המעקב חייב להיות לפי דרישה. פעימת קצב אינה נושאת כרטיס לשיגור.",
363
366
  "refusalPerTicketConflictsWithBugIntake": "צינור זה בוחר בעצמו את הנושא מהלוח, ולכן אינו יכול להיות מונע גם מכרטיס נכנס. בחרו צינור ללא שלב bug-intake."
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "לא ניתן היה לטעון את הלוחות: {reason}",
4454
4457
  "issueType": "סוג הפנייה",
4455
4458
  "issueTypeHelp": "ברירת המחדל היא bug. מתעלמים ממנו במערכות ללא סוגי פניות.",
4459
+ "issueTypeUnsupported": "ל-{tracker} אין סוג פנייה שמשמעותו „bug”, לכן מסנן זה אינו מוחל. צמצמו את הסריקה באמצעות תווית במקום זאת.",
4456
4460
  "labels": "תוויות",
4457
4461
  "labelsHelp": "מופרדות בפסיקים. כולן חייבות להופיע.",
4458
4462
  "adoptInto": "הוסף את הבאג הנבחר אל",
@@ -2920,6 +2920,8 @@
2920
2920
  "intakeNoSources": "Connetti prima una sorgente di attività per estrarne le issue.",
2921
2921
  "intakeNoIntakeSources": "Una sorgente di attività è connessa, ma nessuna delle sorgenti connesse può ancora eseguire una ricerca pianificata delle issue.",
2922
2922
  "intakeGithubRepo": "Repository",
2923
+ "intakeGitlabProject": "Progetto",
2924
+ "intakeGitlabProjectHelp": "Il percorso completo del progetto GitLab, sottogruppi inclusi, ad esempio gruppo/sottogruppo/progetto.",
2923
2925
  "intakeBoardId": "ID della board",
2924
2926
  "intakeBoardIdHelp": "La board, il progetto o la coda a cui questo tracker limita l’acquisizione. Il formato è definito dal tracker.",
2925
2927
  "trackerTrigger": "Avvia esecuzioni dai webhook del tracker",
@@ -2931,6 +2933,7 @@
2931
2933
  "intakeLabels": "Etichette",
2932
2934
  "intakeLabelsPlaceholder": "separate da virgole",
2933
2935
  "intakeIssueType": "Tipo di issue",
2936
+ "intakeIssueTypeUnsupported": "{tracker} non ha un tipo di issue che significhi «bug», quindi questa pianificazione non lo applicherà. Restringi la selezione con un’etichetta.",
2934
2937
  "intakeInProgressLabel": "Etichetta in corso",
2935
2938
  "refusalPerTicketRequiresOnDemand": "Una pianificazione attivata dal tracker deve essere su richiesta. Un ciclo a cadenza non porta con sé alcun ticket da assegnare.",
2936
2939
  "refusalPerTicketConflictsWithBugIntake": "Questa pipeline sceglie da sola il proprio problema dalla bacheca, quindi non può essere guidata anche da un ticket in arrivo. Scegli una pipeline senza passaggio di raccolta bug."
@@ -4068,6 +4071,7 @@
4068
4071
  "boardsFailed": "Impossibile caricare le board: {reason}",
4069
4072
  "issueType": "Tipo di ticket",
4070
4073
  "issueTypeHelp": "Per impostazione predefinita bug. Ignorato dai tracker senza tipi di ticket.",
4074
+ "issueTypeUnsupported": "{tracker} non ha un tipo di issue che significhi «bug», quindi questo filtro non viene applicato. Restringi la scansione con un’etichetta.",
4071
4075
  "labels": "Etichette",
4072
4076
  "labelsHelp": "Separate da virgole. Devono essere tutte presenti.",
4073
4077
  "adoptInto": "Aggiungi il bug scelto a",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "課題を取り込むには、まずタスクソースを接続してください。",
348
348
  "intakeNoIntakeSources": "タスクソースは接続されていますが、接続済みのソースはいずれもまだ定期的な課題検索を実行できません。",
349
349
  "intakeGithubRepo": "リポジトリ",
350
+ "intakeGitlabProject": "プロジェクト",
351
+ "intakeGitlabProjectHelp": "GitLab プロジェクトのフルパス。サブグループを含みます (例: group/sub/project)。",
350
352
  "intakeBoardId": "ボード ID",
351
353
  "intakeBoardIdHelp": "このトラッカーが取り込み対象とするボード、プロジェクト、またはキュー。形式はトラッカーが定めます。",
352
354
  "trackerTrigger": "トラッカーの Webhook から実行を開始",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "ラベル",
359
361
  "intakeLabelsPlaceholder": "カンマ区切り",
360
362
  "intakeIssueType": "課題タイプ",
363
+ "intakeIssueTypeUnsupported": "{tracker} には「bug」を意味する課題タイプがないため、このスケジュールでは適用されません。代わりにラベルで取得対象を絞り込んでください。",
361
364
  "intakeInProgressLabel": "進行中ラベル",
362
365
  "refusalPerTicketRequiresOnDemand": "トラッカー起動のスケジュールはオンデマンドである必要があります。定期実行のタイミングには、割り当てるチケットがありません。",
363
366
  "refusalPerTicketConflictsWithBugIntake": "このパイプラインはボードから自分で課題を選ぶため、送信されたチケットで駆動することはできません。bug-intake ステップのないパイプラインを選んでください。"
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "ボードを読み込めませんでした: {reason}",
4454
4457
  "issueType": "課題タイプ",
4455
4458
  "issueTypeHelp": "既定は bug です。課題タイプを持たないトラッカーでは無視されます。",
4459
+ "issueTypeUnsupported": "{tracker} には「bug」を意味する課題タイプがないため、このフィルターは適用されません。代わりにラベルでスキャンを絞り込んでください。",
4456
4460
  "labels": "ラベル",
4457
4461
  "labelsHelp": "カンマ区切り。すべて付いている必要があります。",
4458
4462
  "adoptInto": "選んだバグの追加先",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "Najpierw połącz źródło zadań, aby pobierać z niego zgłoszenia.",
348
348
  "intakeNoIntakeSources": "Źródło zadań jest połączone, ale żadne z połączonych źródeł nie może jeszcze uruchomić zaplanowanego wyszukiwania zgłoszeń.",
349
349
  "intakeGithubRepo": "Repozytorium",
350
+ "intakeGitlabProject": "Projekt",
351
+ "intakeGitlabProjectHelp": "Pełna ścieżka projektu GitLab, wraz z podgrupami, np. grupa/podgrupa/projekt.",
350
352
  "intakeBoardId": "ID tablicy",
351
353
  "intakeBoardIdHelp": "Tablica, projekt lub kolejka, do której ten tracker ogranicza pozyskiwanie. Format określa tracker.",
352
354
  "trackerTrigger": "Uruchamiaj przebiegi z webhooków trackera",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "Etykiety",
359
361
  "intakeLabelsPlaceholder": "oddzielone przecinkami",
360
362
  "intakeIssueType": "Typ zgłoszenia",
363
+ "intakeIssueTypeUnsupported": "{tracker} nie ma typu zgłoszenia oznaczającego „bug”, więc ten harmonogram go nie zastosuje. Zawęż wybór etykietą.",
361
364
  "intakeInProgressLabel": "Etykieta w toku",
362
365
  "refusalPerTicketRequiresOnDemand": "Harmonogram wyzwalany przez tracker musi być na żądanie. Takt cyklu nie niesie ze sobą żadnego zgłoszenia do przekazania.",
363
366
  "refusalPerTicketConflictsWithBugIntake": "Ten potok sam wybiera zgłoszenie z tablicy, więc nie może być dodatkowo sterowany przesłanym zgłoszeniem. Wybierz potok bez kroku bug-intake."
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "Nie udało się wczytać tablic: {reason}",
4454
4457
  "issueType": "Typ zgłoszenia",
4455
4458
  "issueTypeHelp": "Domyślnie bug. Ignorowane przez systemy bez typów zgłoszeń.",
4459
+ "issueTypeUnsupported": "{tracker} nie ma typu zgłoszenia oznaczającego „bug”, więc ten filtr nie jest stosowany. Zawęż skanowanie etykietą.",
4456
4460
  "labels": "Etykiety",
4457
4461
  "labelsHelp": "Oddzielone przecinkami. Wszystkie muszą występować.",
4458
4462
  "adoptInto": "Dodaj wybrany błąd do",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "Sorunları çekmek için önce bir görev kaynağı bağlayın.",
348
348
  "intakeNoIntakeSources": "Bir görev kaynağı bağlı, ancak bağlı kaynakların hiçbiri henüz zamanlanmış bir sorun aramasını çalıştıramıyor.",
349
349
  "intakeGithubRepo": "Depo",
350
+ "intakeGitlabProject": "Proje",
351
+ "intakeGitlabProjectHelp": "GitLab projesinin alt gruplar dahil tam yolu, örneğin grup/altgrup/proje.",
350
352
  "intakeBoardId": "Pano kimliği",
351
353
  "intakeBoardIdHelp": "Bu izleyicinin alımı kapsamlandırdığı pano, proje veya kuyruk. Biçimini izleyici belirler.",
352
354
  "trackerTrigger": "Çalıştırmaları izleyici webhookları ile başlat",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "Etiketler",
359
361
  "intakeLabelsPlaceholder": "virgülle ayrılmış",
360
362
  "intakeIssueType": "Sorun türü",
363
+ "intakeIssueTypeUnsupported": "{tracker} “bug” anlamına gelen bir konu türüne sahip değil, bu nedenle bu zamanlama onu uygulamaz. Seçimi bunun yerine bir etiketle daraltın.",
361
364
  "intakeInProgressLabel": "Devam ediyor etiketi",
362
365
  "refusalPerTicketRequiresOnDemand": "İzleyici tetiklemeli bir zamanlama istek üzerine olmalıdır. Döngü tikinin gönderilecek bir kaydı yoktur.",
363
366
  "refusalPerTicketConflictsWithBugIntake": "Bu işlem hattı kendi kaydını panodan seçer, bu nedenle ayrıca gelen bir kayıtla sürülemez. Bug-intake adımı olmayan bir işlem hattı seçin."
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "Panolar yüklenemedi: {reason}",
4454
4457
  "issueType": "Kayıt türü",
4455
4458
  "issueTypeHelp": "Varsayılan olarak bug. Kayıt türü olmayan araçlarda yok sayılır.",
4459
+ "issueTypeUnsupported": "{tracker} “bug” anlamına gelen bir konu türüne sahip değil, bu nedenle bu filtre uygulanmaz. Taramayı bunun yerine bir etiketle daraltın.",
4456
4460
  "labels": "Etiketler",
4457
4461
  "labelsHelp": "Virgülle ayrılır. Hepsinin bulunması gerekir.",
4458
4462
  "adoptInto": "Seçilen hatayı şuraya ekle",
@@ -347,6 +347,8 @@
347
347
  "intakeNoSources": "Спочатку підключіть джерело завдань, щоб отримувати з нього завдання.",
348
348
  "intakeNoIntakeSources": "Джерело завдань підключено, але жодне з підключених джерел ще не може виконувати заплановий пошук завдань.",
349
349
  "intakeGithubRepo": "Репозиторій",
350
+ "intakeGitlabProject": "Проєкт",
351
+ "intakeGitlabProjectHelp": "Повний шлях проєкту GitLab, включно з підгрупами, напр. group/sub/project.",
350
352
  "intakeBoardId": "ID дошки",
351
353
  "intakeBoardIdHelp": "Дошка, проєкт або черга, якими цей трекер обмежує приймання. Формат визначає трекер.",
352
354
  "trackerTrigger": "Запускати виконання з вебхуків трекера",
@@ -358,6 +360,7 @@
358
360
  "intakeLabels": "Мітки",
359
361
  "intakeLabelsPlaceholder": "через кому",
360
362
  "intakeIssueType": "Тип завдання",
363
+ "intakeIssueTypeUnsupported": "{tracker} не має типу завдання зі значенням «bug», тому цей графік його не застосує. Натомість звузьте відбір міткою.",
361
364
  "intakeInProgressLabel": "Мітка «в роботі»",
362
365
  "refusalPerTicketRequiresOnDemand": "Розклад, запущений трекером, має бути на вимогу. Спрацювання за розкладом не несе жодної заявки для передавання.",
363
366
  "refusalPerTicketConflictsWithBugIntake": "Цей конвеєр сам обирає задачу з дошки, тож його не можна додатково запускати надісланою заявкою. Оберіть конвеєр без кроку bug-intake."
@@ -4453,6 +4456,7 @@
4453
4456
  "boardsFailed": "Не вдалося завантажити дошки: {reason}",
4454
4457
  "issueType": "Тип запиту",
4455
4458
  "issueTypeHelp": "Типово bug. Ігнорується трекерами без типів запитів.",
4459
+ "issueTypeUnsupported": "{tracker} не має типу завдання зі значенням «bug», тому цей фільтр не застосовується. Натомість звузьте сканування міткою.",
4456
4460
  "labels": "Мітки",
4457
4461
  "labelsHelp": "Через кому. Усі мають бути присутні.",
4458
4462
  "adoptInto": "Додати обрану помилку до",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.246.0",
3
+ "version": "0.248.0",
4
4
  "description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,7 +40,7 @@
40
40
  "valibot": "^1.4.2",
41
41
  "vue": "3.5.40",
42
42
  "wretch": "^3.0.9",
43
- "@cat-factory/contracts": "0.268.0"
43
+ "@cat-factory/contracts": "0.270.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@toad-contracts/testing": "0.3.2",