@cat-factory/app 0.35.0 → 0.37.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 (87) hide show
  1. package/app/components/auth/UserMenu.vue +11 -1
  2. package/app/components/brainstorm/BrainstormWindow.vue +2 -1
  3. package/app/components/clarity/ClarityReviewWindow.vue +2 -1
  4. package/app/components/gates/GateResultView.vue +107 -12
  5. package/app/components/layout/IntegrationBackTitle.vue +12 -7
  6. package/app/components/layout/IntegrationsHub.vue +191 -43
  7. package/app/components/layout/NotificationsInbox.vue +16 -0
  8. package/app/components/layout/PersonalSetupModal.vue +141 -0
  9. package/app/components/pipeline/PipelineBuilder.vue +1 -1
  10. package/app/components/providers/VendorCredentialsModal.vue +7 -2
  11. package/app/components/slack/SlackPanel.vue +1 -0
  12. package/app/composables/api/accounts.ts +36 -51
  13. package/app/composables/api/auth.ts +20 -19
  14. package/app/composables/api/board.ts +60 -40
  15. package/app/composables/api/bootstrap.ts +25 -22
  16. package/app/composables/api/client.ts +102 -0
  17. package/app/composables/api/context.ts +25 -6
  18. package/app/composables/api/documents.ts +36 -34
  19. package/app/composables/api/execution.ts +65 -48
  20. package/app/composables/api/followUps.ts +26 -26
  21. package/app/composables/api/fragments.ts +47 -34
  22. package/app/composables/api/github.ts +65 -45
  23. package/app/composables/api/humanReview.ts +19 -0
  24. package/app/composables/api/humanTest.ts +15 -11
  25. package/app/composables/api/kaizen.ts +8 -6
  26. package/app/composables/api/localSettings.ts +5 -4
  27. package/app/composables/api/models.ts +58 -51
  28. package/app/composables/api/notifications.ts +13 -7
  29. package/app/composables/api/presets.ts +34 -28
  30. package/app/composables/api/providerConnections.ts +68 -26
  31. package/app/composables/api/recurring.ts +40 -30
  32. package/app/composables/api/releaseHealth.ts +28 -26
  33. package/app/composables/api/reviews.ts +136 -114
  34. package/app/composables/api/sandbox.ts +52 -34
  35. package/app/composables/api/slack.ts +22 -25
  36. package/app/composables/api/spec.ts +3 -3
  37. package/app/composables/api/tasks.ts +42 -41
  38. package/app/composables/api/userSecrets.ts +12 -17
  39. package/app/composables/api/workspaces.ts +21 -15
  40. package/app/composables/useApi.ts +11 -1
  41. package/app/composables/useIntegrationBack.ts +9 -3
  42. package/app/pages/index.vue +2 -0
  43. package/app/stores/auth.ts +2 -1
  44. package/app/stores/board.ts +2 -1
  45. package/app/stores/brainstorm.ts +2 -2
  46. package/app/stores/clarity.ts +6 -2
  47. package/app/stores/execution.ts +3 -2
  48. package/app/stores/github.ts +1 -2
  49. package/app/stores/humanReview.ts +41 -0
  50. package/app/stores/mergePresets.ts +2 -6
  51. package/app/stores/pipelines.ts +1 -1
  52. package/app/stores/recurringPipelines.ts +2 -7
  53. package/app/stores/sandbox.ts +1 -2
  54. package/app/stores/ui.ts +62 -19
  55. package/app/types/accountSettings.ts +11 -36
  56. package/app/types/accounts.ts +16 -71
  57. package/app/types/bootstrap.ts +13 -75
  58. package/app/types/brainstorm.ts +13 -38
  59. package/app/types/clarity.ts +12 -43
  60. package/app/types/consensus.ts +16 -89
  61. package/app/types/documents.ts +19 -94
  62. package/app/types/domain.ts +54 -582
  63. package/app/types/execution.ts +48 -499
  64. package/app/types/fragments.ts +15 -83
  65. package/app/types/github.ts +25 -161
  66. package/app/types/incidentEnrichment.ts +10 -25
  67. package/app/types/localModels.ts +11 -61
  68. package/app/types/localSettings.ts +9 -26
  69. package/app/types/merge.ts +10 -68
  70. package/app/types/model-presets.ts +7 -28
  71. package/app/types/models.ts +16 -164
  72. package/app/types/notifications.ts +18 -76
  73. package/app/types/openrouter.ts +8 -34
  74. package/app/types/providerConnections.ts +21 -41
  75. package/app/types/provisioningLogs.ts +9 -29
  76. package/app/types/recurring.ts +10 -63
  77. package/app/types/releaseHealth.ts +15 -39
  78. package/app/types/requirements.ts +14 -84
  79. package/app/types/sandbox.ts +45 -161
  80. package/app/types/services.ts +3 -22
  81. package/app/types/slack.ts +10 -47
  82. package/app/types/spec.ts +15 -68
  83. package/app/types/tasks.ts +15 -111
  84. package/app/types/tracker.ts +9 -24
  85. package/app/types/userSecrets.ts +12 -47
  86. package/app/utils/catalog.ts +12 -0
  87. package/package.json +9 -2
package/app/stores/ui.ts CHANGED
@@ -91,6 +91,14 @@ export const useUiStore = defineStore('ui', () => {
91
91
  // is one. Every direct `open*` below resets it; `openFromIntegrations` sets it.
92
92
  const cameFromIntegrations = ref(false)
93
93
 
94
+ // Personal "My setup" hub: a user-scoped sibling of the Integrations hub, listing the
95
+ // signed-in user's own connections (GitHub PAT, local runners, personal subscriptions)
96
+ // separated out of the workspace-scoped Integrations hub. `cameFromPersonal` is the
97
+ // symmetric came-from marker, so a panel reached from here renders a "Back to My setup"
98
+ // control instead of "Back to Integrations".
99
+ const personalSetupOpen = ref(false)
100
+ const cameFromPersonal = ref(false)
101
+
94
102
  // Workspace-settings modal: a single tabbed window gathering the workspace-wide
95
103
  // config (workspace / merge thresholds / issue writeback / service best practices).
96
104
  // `workspaceSettingsTab` lets other surfaces deep-link straight to a tab.
@@ -112,8 +120,10 @@ export const useUiStore = defineStore('ui', () => {
112
120
  const providerConnectionKind = ref<'environment' | 'runner-pool' | null>(null)
113
121
  const modelConfigOpen = ref(false)
114
122
  // LLM-vendor subscription credentials (the token pool powering the Claude Code
115
- // / Codex harnesses).
123
+ // / Codex harnesses). `vendorCredentialsTab` lets a caller deep-link to one tab —
124
+ // the user-scoped "My subscriptions" entry opens straight onto the `personal` tab.
116
125
  const vendorCredentialsOpen = ref(false)
126
+ const vendorCredentialsTab = ref('pool')
117
127
  // Per-user settings panel: the signed-in user's own-machine local model runners.
118
128
  const localModelsOpen = ref(false)
119
129
  // Local-mode-only settings panel: the warm-container pool sizing + per-repo checkout reuse
@@ -267,7 +277,7 @@ export const useUiStore = defineStore('ui', () => {
267
277
  }
268
278
 
269
279
  function openDocumentConnect(source: DocumentSourceKind) {
270
- cameFromIntegrations.value = false
280
+ resetHubReturn()
271
281
  documentConnect.value = { source }
272
282
  }
273
283
  function closeDocumentConnect() {
@@ -277,7 +287,7 @@ export const useUiStore = defineStore('ui', () => {
277
287
  targetFrameId: string | null = null,
278
288
  source: DocumentSourceKind | null = null,
279
289
  ) {
280
- cameFromIntegrations.value = false
290
+ resetHubReturn()
281
291
  documentImport.value = { source, targetFrameId }
282
292
  }
283
293
  function closeDocumentImport() {
@@ -294,14 +304,14 @@ export const useUiStore = defineStore('ui', () => {
294
304
  spawnPreview.value = null
295
305
  }
296
306
  function openTaskConnect(source: TaskSourceKind) {
297
- cameFromIntegrations.value = false
307
+ resetHubReturn()
298
308
  taskConnect.value = { source }
299
309
  }
300
310
  function closeTaskConnect() {
301
311
  taskConnect.value = null
302
312
  }
303
313
  function openTaskImport(source: TaskSourceKind | null = null, containerId: string | null = null) {
304
- cameFromIntegrations.value = false
314
+ resetHubReturn()
305
315
  taskImport.value = { source, containerId }
306
316
  }
307
317
  function closeTaskImport() {
@@ -334,14 +344,14 @@ export const useUiStore = defineStore('ui', () => {
334
344
  addServiceOpen.value = false
335
345
  }
336
346
  function openGitHub() {
337
- cameFromIntegrations.value = false
347
+ resetHubReturn()
338
348
  githubOpen.value = true
339
349
  }
340
350
  function closeGitHub() {
341
351
  githubOpen.value = false
342
352
  }
343
353
  function openSlack() {
344
- cameFromIntegrations.value = false
354
+ resetHubReturn()
345
355
  slackOpen.value = true
346
356
  }
347
357
  function closeSlack() {
@@ -362,15 +372,37 @@ export const useUiStore = defineStore('ui', () => {
362
372
  function toggleCommandBar() {
363
373
  commandBarOpen.value = !commandBarOpen.value
364
374
  }
375
+ // Clear BOTH hub came-from markers. Every direct `open*` below calls this so that a
376
+ // panel opened outside the hubs never grows a dead Back control, and so switching from
377
+ // one hub's panel to the other's clears the stale marker.
378
+ function resetHubReturn() {
379
+ resetHubReturn()
380
+ cameFromPersonal.value = false
381
+ }
365
382
  function openIntegrations() {
366
383
  // Reaching the hub itself (fresh, or via a panel's Back control) clears the
367
- // came-from marker — we're at the hub, not inside a hub-spawned panel.
368
- cameFromIntegrations.value = false
384
+ // came-from markers — we're at the hub, not inside a hub-spawned panel.
385
+ resetHubReturn()
369
386
  integrationsOpen.value = true
370
387
  }
371
388
  function closeIntegrations() {
372
389
  integrationsOpen.value = false
373
390
  }
391
+ function openPersonalSetup() {
392
+ resetHubReturn()
393
+ personalSetupOpen.value = true
394
+ }
395
+ function closePersonalSetup() {
396
+ personalSetupOpen.value = false
397
+ }
398
+ // Open a user-scoped panel FROM the My-setup hub: run its open handler (which resets the
399
+ // markers), then mark that we came from My setup and dismiss it, so the panel's
400
+ // IntegrationBackTitle returns here rather than to the workspace Integrations hub.
401
+ function openFromPersonal(open: () => void) {
402
+ open()
403
+ cameFromPersonal.value = true
404
+ personalSetupOpen.value = false
405
+ }
374
406
  // Open an integration's own panel FROM the hub: run its open handler (which resets
375
407
  // `cameFromIntegrations`), then mark that we came from the hub and dismiss it. The
376
408
  // panel reads `cameFromIntegrations` to show its Back control.
@@ -380,7 +412,7 @@ export const useUiStore = defineStore('ui', () => {
380
412
  integrationsOpen.value = false
381
413
  }
382
414
  function openWorkspaceSettings(tab = 'workspace') {
383
- cameFromIntegrations.value = false
415
+ resetHubReturn()
384
416
  workspaceSettingsTab.value = tab
385
417
  workspaceSettingsOpen.value = true
386
418
  }
@@ -391,7 +423,7 @@ export const useUiStore = defineStore('ui', () => {
391
423
  workspaceSettingsTab.value = tab
392
424
  }
393
425
  function openAccountSettings(tab = 'team') {
394
- cameFromIntegrations.value = false
426
+ resetHubReturn()
395
427
  accountSettingsTab.value = tab
396
428
  accountSettingsOpen.value = true
397
429
  }
@@ -402,14 +434,14 @@ export const useUiStore = defineStore('ui', () => {
402
434
  accountSettingsTab.value = tab
403
435
  }
404
436
  function openObservabilityConnection() {
405
- cameFromIntegrations.value = false
437
+ resetHubReturn()
406
438
  observabilityConnectionOpen.value = true
407
439
  }
408
440
  function closeObservabilityConnection() {
409
441
  observabilityConnectionOpen.value = false
410
442
  }
411
443
  function openProviderConnection(kind: 'environment' | 'runner-pool') {
412
- cameFromIntegrations.value = false
444
+ resetHubReturn()
413
445
  providerConnectionKind.value = kind
414
446
  }
415
447
  function closeProviderConnection() {
@@ -421,22 +453,26 @@ export const useUiStore = defineStore('ui', () => {
421
453
  function closeModelConfig() {
422
454
  modelConfigOpen.value = false
423
455
  }
424
- function openVendorCredentials() {
425
- cameFromIntegrations.value = false
456
+ function openVendorCredentials(tab = 'pool') {
457
+ resetHubReturn()
458
+ vendorCredentialsTab.value = tab
426
459
  vendorCredentialsOpen.value = true
427
460
  }
461
+ function setVendorCredentialsTab(tab: string) {
462
+ vendorCredentialsTab.value = tab
463
+ }
428
464
  function closeVendorCredentials() {
429
465
  vendorCredentialsOpen.value = false
430
466
  }
431
467
  function openLocalModels() {
432
- cameFromIntegrations.value = false
468
+ resetHubReturn()
433
469
  localModelsOpen.value = true
434
470
  }
435
471
  function closeLocalModels() {
436
472
  localModelsOpen.value = false
437
473
  }
438
474
  function openLocalModeSettings() {
439
- cameFromIntegrations.value = false
475
+ resetHubReturn()
440
476
  localModeSettingsOpen.value = true
441
477
  }
442
478
  function closeLocalModeSettings() {
@@ -449,14 +485,14 @@ export const useUiStore = defineStore('ui', () => {
449
485
  sandboxOpen.value = false
450
486
  }
451
487
  function openUserSecrets() {
452
- cameFromIntegrations.value = false
488
+ resetHubReturn()
453
489
  userSecretsOpen.value = true
454
490
  }
455
491
  function closeUserSecrets() {
456
492
  userSecretsOpen.value = false
457
493
  }
458
494
  function openOpenRouter() {
459
- cameFromIntegrations.value = false
495
+ resetHubReturn()
460
496
  openRouterOpen.value = true
461
497
  }
462
498
  function closeOpenRouter() {
@@ -581,6 +617,8 @@ export const useUiStore = defineStore('ui', () => {
581
617
  commandBarOpen,
582
618
  integrationsOpen,
583
619
  cameFromIntegrations,
620
+ personalSetupOpen,
621
+ cameFromPersonal,
584
622
  workspaceSettingsOpen,
585
623
  workspaceSettingsTab,
586
624
  accountSettingsOpen,
@@ -589,6 +627,7 @@ export const useUiStore = defineStore('ui', () => {
589
627
  providerConnectionKind,
590
628
  modelConfigOpen,
591
629
  vendorCredentialsOpen,
630
+ vendorCredentialsTab,
592
631
  localModelsOpen,
593
632
  localModeSettingsOpen,
594
633
  sandboxOpen,
@@ -645,6 +684,9 @@ export const useUiStore = defineStore('ui', () => {
645
684
  openIntegrations,
646
685
  closeIntegrations,
647
686
  openFromIntegrations,
687
+ openPersonalSetup,
688
+ closePersonalSetup,
689
+ openFromPersonal,
648
690
  openWorkspaceSettings,
649
691
  closeWorkspaceSettings,
650
692
  setWorkspaceSettingsTab,
@@ -658,6 +700,7 @@ export const useUiStore = defineStore('ui', () => {
658
700
  openModelConfig,
659
701
  closeModelConfig,
660
702
  openVendorCredentials,
703
+ setVendorCredentialsTab,
661
704
  closeVendorCredentials,
662
705
  openLocalModels,
663
706
  closeLocalModels,
@@ -1,39 +1,14 @@
1
1
  // Per-account (deployment-wide) integration settings. Mirrors
2
2
  // `@cat-factory/contracts` accountSettings. Secrets are write-only — the read view
3
3
  // returns only `config` + a non-secret presence `summary`.
4
-
5
- export interface SlackOAuthSecret {
6
- clientId: string
7
- clientSecret: string
8
- redirectUrl: string
9
- }
10
-
11
- export interface WebSearchSecret {
12
- braveApiKey?: string
13
- searxngUrl?: string
14
- searxngApiKey?: string
15
- }
16
-
17
- /** Non-secret per-account config (empty today; reserved for forward-compatible tuning). */
18
- export type AccountSettingsConfig = Record<string, never>
19
-
20
- export interface AccountSettingsSummary {
21
- slackOAuthConfigured: boolean
22
- webSearch: 'brave' | 'searxng' | null
23
- }
24
-
25
- export interface AccountSettingsView {
26
- config: AccountSettingsConfig
27
- summary: AccountSettingsSummary
28
- }
29
-
30
- /**
31
- * Admin write. Each secrets group: omit ⇒ leave unchanged, `null` ⇒ clear, value ⇒ set.
32
- */
33
- export interface UpdateAccountSettingsInput {
34
- config?: AccountSettingsConfig
35
- secrets?: {
36
- slackOAuth?: SlackOAuthSecret | null
37
- webSearch?: WebSearchSecret | null
38
- }
39
- }
4
+ //
5
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
6
+
7
+ export type {
8
+ SlackOAuthSecret,
9
+ WebSearchSecret,
10
+ AccountSettingsConfig,
11
+ AccountSettingsSummary,
12
+ AccountSettingsView,
13
+ UpdateAccountSettingsInput,
14
+ } from '@cat-factory/contracts'
@@ -4,74 +4,19 @@
4
4
  // to accounts with a role. Mirrors the `@cat-factory/contracts` account schemas
5
5
  // so responses drop straight into the Pinia store.
6
6
  // ---------------------------------------------------------------------------
7
-
8
- import type { CloudProvider } from './domain'
9
-
10
- export type AccountType = 'personal' | 'org'
11
- /** Combinable account roles: admin controls the org account, product owns tasks. */
12
- export type AccountRole = 'admin' | 'developer' | 'product'
13
-
14
- /** An account, annotated with the signed-in caller's roles in it. */
15
- export interface Account {
16
- id: string
17
- type: AccountType
18
- name: string
19
- githubAccountLogin: string | null
20
- createdAt: number
21
- /** The caller's roles in this account (`null` in the auth-disabled path). */
22
- roles: AccountRole[] | null
23
- /** The cloud provider new services in this account default to; absent = built-in default. */
24
- defaultCloudProvider?: CloudProvider
25
- }
26
-
27
- /** A member of an account, with display details when resolvable. */
28
- export interface AccountMember {
29
- accountId: string
30
- userId: string
31
- roles: AccountRole[]
32
- createdAt: number
33
- name?: string | null
34
- email?: string | null
35
- avatarUrl?: string | null
36
- }
37
-
38
- export interface CreateAccountInput {
39
- name: string
40
- githubAccountLogin?: string
41
- }
42
-
43
- /** Update an account's settings (today: its default cloud provider for new services). */
44
- export interface UpdateAccountInput {
45
- defaultCloudProvider?: CloudProvider
46
- }
47
-
48
- export interface AddMemberInput {
49
- userId: string
50
- roles?: AccountRole[]
51
- }
52
-
53
- /** Set a member's role set (admin-only). */
54
- export interface SetMemberRolesInput {
55
- roles: AccountRole[]
56
- }
57
-
58
- /** An email invitation into an org account (never carries the raw token). */
59
- export interface AccountInvitation {
60
- id: string
61
- accountId: string
62
- email: string
63
- roles: AccountRole[]
64
- status: 'pending' | 'accepted' | 'revoked'
65
- invitedBy: string
66
- expiresAt: number
67
- createdAt: number
68
- }
69
-
70
- export type EmailProviderKind = 'sendgrid' | 'resend'
71
-
72
- /** A per-account email-sender connection (safe metadata; never the API key). */
73
- export interface EmailConnection {
74
- provider: EmailProviderKind
75
- fromAddress: string
76
- connectedAt: number
77
- }
7
+ //
8
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
9
+
10
+ export type {
11
+ AccountType,
12
+ AccountRole,
13
+ Account,
14
+ AccountMember,
15
+ CreateAccountInput,
16
+ UpdateAccountInput,
17
+ AddMemberInput,
18
+ SetMemberRolesInput,
19
+ AccountInvitation,
20
+ EmailProviderKind,
21
+ EmailConnection,
22
+ } from '@cat-factory/contracts'
@@ -6,78 +6,16 @@
6
6
  // org wants new services to follow); the "bootstrap repo" task creates a new repo
7
7
  // from one and runs a bootstrapper agent in a container to adapt it.
8
8
  // ---------------------------------------------------------------------------
9
-
10
- import type { AgentFailure, AgentFailureKind, StepSubtasks } from './execution'
11
-
12
- /** A managed base repository new repos are bootstrapped from. */
13
- export interface ReferenceArchitecture {
14
- id: string
15
- workspaceId: string
16
- name: string
17
- description: string
18
- repoOwner: string
19
- repoName: string
20
- defaultInstructions: string
21
- createdAt: number
22
- updatedAt: number
23
- }
24
-
25
- /** Body to register a reference architecture. */
26
- export interface CreateReferenceArchitectureInput {
27
- name: string
28
- description?: string
29
- repoOwner: string
30
- repoName: string
31
- defaultInstructions?: string
32
- }
33
-
34
- /** Body to patch a reference architecture (only supplied fields change). */
35
- export type UpdateReferenceArchitectureInput = Partial<CreateReferenceArchitectureInput>
36
-
37
- /** Lifecycle of a single "bootstrap repo" run. */
38
- export type BootstrapStatus = 'pending' | 'running' | 'succeeded' | 'failed'
39
-
40
- /**
41
- * A bootstrap run's failure is now the shared {@link AgentFailure} (same shape
42
- * execution runs use), so the board renders one failure banner + retry for any
43
- * agent. These aliases stay for back-compat / documentation of the bootstrap
44
- * subset; `bootstrapFailureKindSchema` on the backend stays narrow.
45
- */
46
- export type BootstrapFailureKind = AgentFailureKind
47
-
48
- /** Structured failure diagnostics captured when a bootstrap run fails. */
49
- export type BootstrapFailure = AgentFailure
50
-
51
- /** One "bootstrap repo" run with its outcome. */
52
- export interface BootstrapJob {
53
- id: string
54
- workspaceId: string
55
- /** Reference architecture the run was based on, or null for a from-scratch run. */
56
- referenceArchitectureId: string | null
57
- /** Denormalized reference architecture name, or null for a from-scratch run. */
58
- referenceArchitectureName: string | null
59
- repoName: string
60
- repoOwner: string | null
61
- repoUrl: string | null
62
- instructions: string
63
- status: BootstrapStatus
64
- /** The board service frame this run materialises, or null if none was created. */
65
- blockId: string | null
66
- /** Live subtask counts from the bootstrapper agent, or null until it reports. */
67
- subtasks: StepSubtasks | null
68
- error: string | null
69
- /** Structured failure diagnostics when `status` is `failed`; null otherwise. */
70
- failure: BootstrapFailure | null
71
- createdAt: number
72
- updatedAt: number
73
- }
74
-
75
- /** Body to kick off a bootstrap run. Omit `referenceArchitectureId` to bootstrap
76
- * from a freeform prompt alone (then `instructions` must be non-empty). */
77
- export interface BootstrapRepoInput {
78
- referenceArchitectureId?: string | null
79
- repoName: string
80
- description?: string
81
- private?: boolean
82
- instructions?: string
83
- }
9
+ //
10
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
11
+
12
+ export type {
13
+ ReferenceArchitecture,
14
+ CreateReferenceArchitectureInput,
15
+ UpdateReferenceArchitectureInput,
16
+ BootstrapStatus,
17
+ BootstrapFailureKind,
18
+ BootstrapFailure,
19
+ BootstrapJob,
20
+ BootstrapRepoInput,
21
+ } from '@cat-factory/contracts'
@@ -10,46 +10,21 @@
10
10
  // Structurally identical to a requirements review (the items share the same shape), so the
11
11
  // per-item types are reused from `~/types/requirements`; only the `stage` discriminator and
12
12
  // the converged document (`convergedDirection`) differ.
13
+ //
14
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
13
15
 
14
- import type {
15
- RequirementReviewItem,
16
+ export type {
17
+ BrainstormStage,
18
+ BrainstormItem,
19
+ BrainstormStatus,
20
+ ResolveBrainstormExceededChoice,
21
+ BrainstormSession,
22
+ // The per-item types are shared with a requirements review (same shape).
16
23
  ReviewItemCategory,
17
24
  ReviewItemSeverity,
18
25
  ReviewItemStatus,
19
- } from '~/types/requirements'
20
-
21
- export type { ReviewItemCategory, ReviewItemSeverity, ReviewItemStatus }
22
-
23
- /** Which dialogue a brainstorm session drives. */
24
- export type BrainstormStage = 'requirements' | 'architecture'
25
-
26
- /** A brainstorm option is the same shape as a requirements-review item. */
27
- export type BrainstormItem = RequirementReviewItem
28
-
29
- /** Lifecycle of a brainstorm session — identical to the requirements review lifecycle. */
30
- export type BrainstormStatus =
31
- | 'ready'
32
- | 'incorporating'
33
- | 'reviewing'
34
- | 'merged'
35
- | 'exceeded'
36
- | 'incorporated'
37
-
38
- /** How a human resolves a session that hit its iteration cap. */
39
- export type ResolveBrainstormExceededChoice = 'extra-round' | 'proceed' | 'stop-reset'
26
+ } from '@cat-factory/contracts'
27
+ import type { UpdateBrainstormItemStatusInput } from '@cat-factory/contracts'
40
28
 
41
- export interface BrainstormSession {
42
- id: string
43
- blockId: string
44
- stage: BrainstormStage
45
- status: BrainstormStatus
46
- items: BrainstormItem[]
47
- model: string | null
48
- convergedDirection: string | null
49
- /** Agent passes run so far (initial pass is 1; each re-run adds one). */
50
- iteration: number
51
- /** The agent-pass budget (from the task's merge preset; an extra round bumps it). */
52
- maxIterations: number
53
- createdAt: number
54
- updatedAt: number
55
- }
29
+ /** The narrower status set the set-item-status action accepts (a subset of ReviewItemStatus). */
30
+ export type BrainstormItemStatus = UpdateBrainstormItemStatusInput['status']
@@ -9,51 +9,20 @@
9
9
  // Structurally identical to a requirements review (the items share the same shape),
10
10
  // so the per-item types are reused from `~/types/requirements`; only the
11
11
  // incorporated document differs (`clarifiedReport`).
12
+ //
13
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
12
14
 
13
- import type {
14
- RequirementReviewItem,
15
+ export type {
16
+ ClarityReviewItem,
17
+ ClarityReviewStatus,
18
+ ResolveClarityExceededChoice,
19
+ ClarityReview,
20
+ // The per-item types are shared with a requirements review (same shape).
15
21
  ReviewItemCategory,
16
22
  ReviewItemSeverity,
17
23
  ReviewItemStatus,
18
- } from '~/types/requirements'
19
-
20
- export type { ReviewItemCategory, ReviewItemSeverity, ReviewItemStatus }
21
-
22
- /** A clarity-review item is the same shape as a requirements-review item. */
23
- export type ClarityReviewItem = RequirementReviewItem
24
-
25
- /**
26
- * - `ready`: the reviewer raised findings awaiting human answers/dismissals.
27
- * - `incorporating`: transient; the driver is folding the answers into a document (the FIRST
28
- * async stage — the user is back on the board).
29
- * - `reviewing`: transient; the reviewer is RE-reviewing the folded document (the SECOND
30
- * async stage). Distinct from `incorporating` so the UI can show which stage is running.
31
- * - `merged`: the companion produced a document (an internal transient on the async path).
32
- * - `exceeded`: the iteration cap was hit with findings open — awaiting the human's choice.
33
- * - `incorporated`: terminal; the clarity phase is settled.
34
- */
35
- export type ClarityReviewStatus =
36
- | 'ready'
37
- | 'incorporating'
38
- | 'reviewing'
39
- | 'merged'
40
- | 'exceeded'
41
- | 'incorporated'
42
-
43
- /** How a human resolves a review that hit its iteration cap. */
44
- export type ResolveClarityExceededChoice = 'extra-round' | 'proceed' | 'stop-reset'
24
+ } from '@cat-factory/contracts'
25
+ import type { UpdateClarityItemStatusInput } from '@cat-factory/contracts'
45
26
 
46
- export interface ClarityReview {
47
- id: string
48
- blockId: string
49
- status: ClarityReviewStatus
50
- items: ClarityReviewItem[]
51
- model: string | null
52
- clarifiedReport: string | null
53
- /** Reviewer passes run so far (initial review is 1; each re-review adds one). */
54
- iteration: number
55
- /** The reviewer-pass budget (from the task's merge preset; an extra round bumps it). */
56
- maxIterations: number
57
- createdAt: number
58
- updatedAt: number
59
- }
27
+ /** The narrower status set the set-item-status action accepts (a subset of ReviewItemStatus). */
28
+ export type ClarityItemStatus = UpdateClarityItemStatusInput['status']