@cat-factory/app 0.79.2 → 0.81.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 (30) hide show
  1. package/app/components/documents/TaskContextDocs.vue +10 -7
  2. package/app/components/fragments/FragmentLibraryManager.vue +2 -10
  3. package/app/components/github/AddServiceFromRepoModal.vue +2 -1
  4. package/app/components/panels/InspectorPanel.vue +35 -18
  5. package/app/components/panels/inspector/ContainerSummary.vue +8 -2
  6. package/app/components/panels/inspector/EpicChildren.vue +9 -7
  7. package/app/components/panels/inspector/FrontendConfig.vue +175 -248
  8. package/app/components/panels/inspector/InspectorSection.vue +60 -0
  9. package/app/components/panels/inspector/ServiceConnections.vue +10 -10
  10. package/app/components/panels/inspector/ServiceFragments.vue +14 -9
  11. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +8 -7
  12. package/app/components/panels/inspector/ServiceTestConfig.vue +45 -57
  13. package/app/components/panels/inspector/TaskAgentConfig.vue +8 -5
  14. package/app/components/panels/inspector/TaskDependencies.vue +12 -8
  15. package/app/components/panels/inspector/TaskEstimateBadge.vue +9 -8
  16. package/app/components/panels/inspector/TaskExecution.vue +9 -2
  17. package/app/components/panels/inspector/TaskRunSettings.vue +13 -2
  18. package/app/components/panels/inspector/TaskStructure.vue +9 -2
  19. package/app/components/requirements/RequirementsReviewWindow.vue +126 -42
  20. package/app/components/tasks/TaskContextIssues.vue +10 -7
  21. package/app/stores/fragmentLibrary.ts +4 -4
  22. package/i18n/locales/en.json +28 -3
  23. package/i18n/locales/es.json +28 -3
  24. package/i18n/locales/fr.json +28 -3
  25. package/i18n/locales/he.json +28 -3
  26. package/i18n/locales/ja.json +28 -3
  27. package/i18n/locales/pl.json +28 -3
  28. package/i18n/locales/tr.json +28 -3
  29. package/i18n/locales/uk.json +28 -3
  30. package/package.json +2 -2
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { DropdownMenuItem } from '@nuxt/ui'
3
3
  import type { Block, DocumentSourceKind } from '~/types/domain'
4
+ import InspectorSection from '~/components/panels/inspector/InspectorSection.vue'
4
5
 
5
6
  // Documents (from any source) attached to a task as agent context, shown inside
6
7
  // the InspectorPanel. Linked docs are fed to agents during execution (see the
@@ -51,17 +52,19 @@ const attachMenu = computed<DropdownMenuItem[][]>(() => {
51
52
  </script>
52
53
 
53
54
  <template>
54
- <div v-if="documents.available" class="space-y-2">
55
- <div class="flex items-center justify-between">
56
- <span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
57
- {{ t('documents.taskDocs.heading') }}
58
- </span>
55
+ <InspectorSection
56
+ v-if="documents.available"
57
+ :title="t('documents.taskDocs.heading')"
58
+ :hint="t('documents.taskDocs.hint')"
59
+ :count="linked.length"
60
+ >
61
+ <template #actions>
59
62
  <UDropdownMenu :items="attachMenu" :content="{ side: 'bottom', align: 'end' }">
60
63
  <UButton color="neutral" variant="soft" size="xs" icon="i-lucide-plus">{{
61
64
  t('documents.taskDocs.attach')
62
65
  }}</UButton>
63
66
  </UDropdownMenu>
64
- </div>
67
+ </template>
65
68
 
66
69
  <div v-if="linked.length" class="space-y-1">
67
70
  <a
@@ -82,5 +85,5 @@ const attachMenu = computed<DropdownMenuItem[][]>(() => {
82
85
  <p v-else class="text-[11px] text-slate-500">
83
86
  {{ t('documents.taskDocs.empty') }}
84
87
  </p>
85
- </div>
88
+ </InspectorSection>
86
89
  </template>
@@ -298,9 +298,7 @@ async function checkSource(id: string) {
298
298
  try {
299
299
  const status = await library.checkSource(id)
300
300
  toast.add({
301
- title: status.changed
302
- ? t('fragments.toast.changesAvailable', { count: status.changedCount }, status.changedCount)
303
- : t('fragments.toast.upToDate'),
301
+ title: status.changed ? t('fragments.toast.changesAvailable') : t('fragments.toast.upToDate'),
304
302
  icon: status.changed ? 'i-lucide-bell-dot' : 'i-lucide-check',
305
303
  })
306
304
  } catch (e) {
@@ -585,13 +583,7 @@ async function unlinkSource(id: string) {
585
583
  variant="subtle"
586
584
  class="ms-auto"
587
585
  >
588
- {{
589
- t(
590
- 'fragments.sources.changes',
591
- { count: library.sourceChanges[s.id] },
592
- library.sourceChanges[s.id] ?? 0,
593
- )
594
- }}
586
+ {{ t('fragments.sources.changes') }}
595
587
  </UBadge>
596
588
  <div class="ms-auto flex gap-1">
597
589
  <UButton
@@ -370,8 +370,9 @@ function done() {
370
370
  <ServiceTestConfig
371
371
  :block="configuredBlock"
372
372
  :repo="{ githubId: selectedRepoId!, directory: configuredDirectory }"
373
+ default-open
373
374
  />
374
- <ServiceFragments :block="configuredBlock" />
375
+ <ServiceFragments :block="configuredBlock" default-open />
375
376
  </div>
376
377
 
377
378
  <div class="flex flex-wrap items-center gap-2">
@@ -442,10 +442,10 @@ const showOriginalDescription = ref(false)
442
442
  </div>
443
443
 
444
444
  <!-- task: context documents -->
445
- <TaskContextDocs v-if="isTask" :block="block" />
445
+ <TaskContextDocs v-if="isTask" :key="`context-docs-${block.id}`" :block="block" />
446
446
 
447
447
  <!-- task: context issues (tracker) -->
448
- <TaskContextIssues v-if="isTask" :block="block" />
448
+ <TaskContextIssues v-if="isTask" :key="`context-issues-${block.id}`" :block="block" />
449
449
 
450
450
  <!-- service (frame): navigate the prescriptive spec tree (+ Gherkin scenarios when
451
451
  the spec is on the repo's default branch) -->
@@ -462,35 +462,52 @@ const showOriginalDescription = ref(false)
462
462
  </UButton>
463
463
 
464
464
  <!-- service / module: tasks summary -->
465
- <ContainerSummary v-if="isContainer" :block="block" />
465
+ <ContainerSummary v-if="isContainer" :key="`container-${block.id}`" :block="block" />
466
466
  <!-- frontend (frame): build/serve/mock config + backend bindings (board links) -->
467
- <FrontendConfig v-if="isFrame && block.type === 'frontend'" :block="block" />
467
+ <FrontendConfig
468
+ v-if="isFrame && block.type === 'frontend'"
469
+ :key="`frontend-${block.id}`"
470
+ :block="block"
471
+ />
468
472
 
469
473
  <!-- service (frame): directed connections to the other services it uses (board links) -->
470
- <ServiceConnections v-if="isFrame && block.type === 'service'" :block="block" />
474
+ <ServiceConnections
475
+ v-if="isFrame && block.type === 'service'"
476
+ :key="`connections-${block.id}`"
477
+ :block="block"
478
+ />
471
479
 
472
480
  <!-- service (frame): test infra + provisioning configuration -->
473
- <ServiceTestConfig v-if="isFrame" :block="block" />
481
+ <ServiceTestConfig v-if="isFrame" :key="`test-config-${block.id}`" :block="block" />
474
482
 
475
483
  <!-- service (frame): best-practice fragments for code-aware agents -->
476
- <ServiceFragments v-if="isFrame" :block="block" />
484
+ <ServiceFragments v-if="isFrame" :key="`fragments-${block.id}`" :block="block" />
477
485
 
478
486
  <!-- service (frame): post-release-health monitor/SLO mapping -->
479
- <ServiceReleaseHealthConfig v-if="isFrame" :block="block" />
480
-
481
- <!-- task: dependencies, structure, agent config, run settings, execution -->
487
+ <ServiceReleaseHealthConfig
488
+ v-if="isFrame"
489
+ :key="`release-health-${block.id}`"
490
+ :block="block"
491
+ />
492
+
493
+ <!-- task: the live execution surface first (open by default), then the estimate,
494
+ then the collapsed configuration sections (dependencies, run settings, agent
495
+ config, structure) so a running task reads top-down without scrolling. -->
496
+ <!-- Keyed by block id so a manual collapse/expand doesn't leak across task
497
+ selections: switching tasks re-mounts each section back to its default state
498
+ (e.g. the live Execution section is open again for the newly selected task). -->
482
499
  <template v-else-if="isTask">
483
- <RecurringScheduleSettings :block="block" />
484
- <TaskDependencies :block="block" />
485
- <TaskStructure :block="block" />
486
- <TaskAgentConfig :block="block" />
487
- <TaskEstimateBadge :block="block" />
488
- <TaskRunSettings :block="block" />
489
- <TaskExecution :block="block" />
500
+ <RecurringScheduleSettings :key="`schedule-${block.id}`" :block="block" />
501
+ <TaskExecution :key="`execution-${block.id}`" :block="block" />
502
+ <TaskEstimateBadge :key="`estimate-${block.id}`" :block="block" />
503
+ <TaskDependencies :key="`deps-${block.id}`" :block="block" />
504
+ <TaskRunSettings :key="`run-settings-${block.id}`" :block="block" />
505
+ <TaskAgentConfig :key="`agent-config-${block.id}`" :block="block" />
506
+ <TaskStructure :key="`structure-${block.id}`" :block="block" />
490
507
  </template>
491
508
 
492
509
  <!-- epic: the full tree of member tasks, grouped by service → module -->
493
- <EpicChildren v-else-if="isEpic" :block="block" />
510
+ <EpicChildren v-else-if="isEpic" :key="`epic-${block.id}`" :block="block" />
494
511
 
495
512
  <!-- actions -->
496
513
  <div class="flex items-center gap-2">
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { Block } from '~/types/domain'
3
3
  import { STATUS_META } from '~/utils/catalog'
4
+ import InspectorSection from '~/components/panels/inspector/InspectorSection.vue'
4
5
 
5
6
  const props = defineProps<{ block: Block }>()
6
7
 
@@ -20,7 +21,12 @@ function addTask() {
20
21
  </script>
21
22
 
22
23
  <template>
23
- <div class="space-y-4">
24
+ <InspectorSection
25
+ :title="t('inspector.container.title')"
26
+ :hint="t('inspector.container.hint')"
27
+ :count="tasks.length"
28
+ default-open
29
+ >
24
30
  <!-- modules (services only) -->
25
31
  <div v-if="modules.length">
26
32
  <div class="mb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
@@ -81,5 +87,5 @@ function addTask() {
81
87
  <p v-if="isFrame" class="text-[11px] text-slate-500">
82
88
  {{ t('inspector.container.servicesHint') }}
83
89
  </p>
84
- </div>
90
+ </InspectorSection>
85
91
  </template>
@@ -2,6 +2,7 @@
2
2
  import { computed } from 'vue'
3
3
  import type { Block } from '~/types/domain'
4
4
  import { STATUS_META } from '~/utils/catalog'
5
+ import InspectorSection from '~/components/panels/inspector/InspectorSection.vue'
5
6
 
6
7
  // The epic inspector body: the full tree of member tasks (which may live under different
7
8
  // services/modules), grouped service → module → task. Each task row selects it. Membership
@@ -45,15 +46,16 @@ const groups = computed(() => {
45
46
  </script>
46
47
 
47
48
  <template>
48
- <div>
49
- <div class="mb-1 flex items-center justify-between">
50
- <span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
51
- {{ t('inspector.epicChildren.title') }}
52
- </span>
49
+ <InspectorSection
50
+ :title="t('inspector.epicChildren.title')"
51
+ :hint="t('inspector.epicChildren.hint')"
52
+ default-open
53
+ >
54
+ <template #actions>
53
55
  <span class="text-[11px] text-slate-500">{{
54
56
  t('inspector.epicChildren.doneCount', { done, total: members.length })
55
57
  }}</span>
56
- </div>
58
+ </template>
57
59
 
58
60
  <div v-if="members.length === 0" class="text-[11px] text-slate-500">
59
61
  {{ t('inspector.epicChildren.empty') }}
@@ -92,5 +94,5 @@ const groups = computed(() => {
92
94
  </div>
93
95
  </div>
94
96
  </div>
95
- </div>
97
+ </InspectorSection>
96
98
  </template>