@cat-factory/app 0.36.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 (82) 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/layout/IntegrationBackTitle.vue +12 -7
  5. package/app/components/layout/IntegrationsHub.vue +191 -43
  6. package/app/components/layout/PersonalSetupModal.vue +141 -0
  7. package/app/components/pipeline/PipelineBuilder.vue +1 -1
  8. package/app/components/providers/VendorCredentialsModal.vue +7 -2
  9. package/app/composables/api/accounts.ts +36 -51
  10. package/app/composables/api/auth.ts +20 -19
  11. package/app/composables/api/board.ts +60 -40
  12. package/app/composables/api/bootstrap.ts +25 -22
  13. package/app/composables/api/client.ts +102 -0
  14. package/app/composables/api/context.ts +25 -6
  15. package/app/composables/api/documents.ts +36 -34
  16. package/app/composables/api/execution.ts +65 -48
  17. package/app/composables/api/followUps.ts +26 -26
  18. package/app/composables/api/fragments.ts +47 -34
  19. package/app/composables/api/github.ts +65 -45
  20. package/app/composables/api/humanReview.ts +7 -6
  21. package/app/composables/api/humanTest.ts +15 -11
  22. package/app/composables/api/kaizen.ts +8 -6
  23. package/app/composables/api/localSettings.ts +5 -4
  24. package/app/composables/api/models.ts +58 -51
  25. package/app/composables/api/notifications.ts +13 -7
  26. package/app/composables/api/presets.ts +34 -28
  27. package/app/composables/api/providerConnections.ts +68 -26
  28. package/app/composables/api/recurring.ts +40 -30
  29. package/app/composables/api/releaseHealth.ts +28 -26
  30. package/app/composables/api/reviews.ts +136 -114
  31. package/app/composables/api/sandbox.ts +52 -34
  32. package/app/composables/api/slack.ts +22 -25
  33. package/app/composables/api/spec.ts +3 -3
  34. package/app/composables/api/tasks.ts +42 -41
  35. package/app/composables/api/userSecrets.ts +12 -17
  36. package/app/composables/api/workspaces.ts +21 -15
  37. package/app/composables/useApi.ts +9 -1
  38. package/app/composables/useIntegrationBack.ts +9 -3
  39. package/app/pages/index.vue +2 -0
  40. package/app/stores/auth.ts +2 -1
  41. package/app/stores/board.ts +2 -1
  42. package/app/stores/brainstorm.ts +2 -2
  43. package/app/stores/clarity.ts +6 -2
  44. package/app/stores/execution.ts +3 -2
  45. package/app/stores/github.ts +1 -2
  46. package/app/stores/mergePresets.ts +2 -6
  47. package/app/stores/pipelines.ts +1 -1
  48. package/app/stores/recurringPipelines.ts +2 -7
  49. package/app/stores/sandbox.ts +1 -2
  50. package/app/stores/ui.ts +62 -19
  51. package/app/types/accountSettings.ts +11 -36
  52. package/app/types/accounts.ts +16 -71
  53. package/app/types/bootstrap.ts +13 -75
  54. package/app/types/brainstorm.ts +13 -38
  55. package/app/types/clarity.ts +12 -43
  56. package/app/types/consensus.ts +16 -89
  57. package/app/types/documents.ts +19 -94
  58. package/app/types/domain.ts +54 -586
  59. package/app/types/execution.ts +48 -515
  60. package/app/types/fragments.ts +15 -83
  61. package/app/types/github.ts +25 -161
  62. package/app/types/incidentEnrichment.ts +10 -25
  63. package/app/types/localModels.ts +11 -61
  64. package/app/types/localSettings.ts +9 -26
  65. package/app/types/merge.ts +10 -68
  66. package/app/types/model-presets.ts +7 -28
  67. package/app/types/models.ts +16 -164
  68. package/app/types/notifications.ts +18 -77
  69. package/app/types/openrouter.ts +8 -34
  70. package/app/types/providerConnections.ts +21 -41
  71. package/app/types/provisioningLogs.ts +9 -29
  72. package/app/types/recurring.ts +10 -63
  73. package/app/types/releaseHealth.ts +15 -39
  74. package/app/types/requirements.ts +14 -84
  75. package/app/types/sandbox.ts +45 -161
  76. package/app/types/services.ts +3 -22
  77. package/app/types/slack.ts +10 -47
  78. package/app/types/spec.ts +15 -68
  79. package/app/types/tasks.ts +15 -111
  80. package/app/types/tracker.ts +9 -24
  81. package/app/types/userSecrets.ts +12 -47
  82. package/package.json +9 -2
@@ -1,61 +1,69 @@
1
- import type {
2
- Block,
3
- SourceTask,
4
- TaskConnection,
5
- TaskSearchResult,
6
- TaskSourceDiagnostic,
7
- TaskSourceKind,
8
- TaskSourceState,
9
- } from '~/types/domain'
10
- import type { PutTrackerSettingsInput, TrackerSettings } from '~/types/tracker'
1
+ import {
2
+ connectTaskSourceContract,
3
+ createTaskFromIssueContract,
4
+ diagnoseTaskSourceContract,
5
+ disconnectTaskSourceContract,
6
+ getTrackerSettingsContract,
7
+ importTaskContract,
8
+ linkTaskContract,
9
+ listTaskConnectionsContract,
10
+ listTaskSourcesContract,
11
+ listTasksContract,
12
+ putTrackerSettingsContract,
13
+ searchTasksContract,
14
+ setTaskSourceEnabledContract,
15
+ spawnEpicContract,
16
+ } from '@cat-factory/contracts'
17
+ import type { TaskSourceKind } from '~/types/domain'
18
+ import type { PutTrackerSettingsInput } from '~/types/tracker'
11
19
  import type { ApiContext } from './context'
12
20
 
13
21
  /** Task sources (Jira, …): connect/import/search/link + the workspace tracker selection. */
14
- export function tasksApi({ http, ws }: ApiContext) {
22
+ export function tasksApi({ send, ws }: ApiContext) {
15
23
  return {
16
24
  // ---- task sources (Jira, …) ------------------------------------------
17
25
  // The configured trackers + their connect/import metadata + the workspace's
18
26
  // per-source state (available + enabled). A 503 means the integration is off
19
27
  // (the store hides its UI on any error here).
20
28
  listTaskSources: (workspaceId: string) =>
21
- http<{ sources: TaskSourceState[] }>(`${ws(workspaceId)}/task-sources`),
29
+ send(listTaskSourcesContract, { pathPrefix: ws(workspaceId) }),
22
30
 
23
31
  setTaskSourceEnabled: (workspaceId: string, source: TaskSourceKind, enabled: boolean) =>
24
- http(`${ws(workspaceId)}/task-sources/${source}/enabled`, {
25
- method: 'PUT',
32
+ send(setTaskSourceEnabledContract, {
33
+ pathPrefix: ws(workspaceId),
34
+ pathParams: { source },
26
35
  body: { enabled },
27
36
  }),
28
37
 
29
38
  listTaskConnections: (workspaceId: string) =>
30
- http<{ connections: TaskConnection[] }>(`${ws(workspaceId)}/task-sources/connections`),
39
+ send(listTaskConnectionsContract, { pathPrefix: ws(workspaceId) }),
31
40
 
32
41
  connectTaskSource: (
33
42
  workspaceId: string,
34
43
  source: TaskSourceKind,
35
44
  credentials: Record<string, string>,
36
45
  ) =>
37
- http<TaskConnection>(`${ws(workspaceId)}/task-sources/${source}/connect`, {
38
- method: 'POST',
46
+ send(connectTaskSourceContract, {
47
+ pathPrefix: ws(workspaceId),
48
+ pathParams: { source },
39
49
  body: { credentials },
40
50
  }),
41
51
 
42
52
  disconnectTaskSource: (workspaceId: string, source: TaskSourceKind) =>
43
- http(`${ws(workspaceId)}/task-sources/${source}/connection`, { method: 'DELETE' }),
53
+ send(disconnectTaskSourceContract, {
54
+ pathPrefix: ws(workspaceId),
55
+ pathParams: { source },
56
+ }),
44
57
 
45
58
  // Live "check setup" probe: authenticates against the source and reads a slice
46
59
  // of its issues API, returning a classified verdict the panel renders verbatim.
47
60
  checkTaskSource: (workspaceId: string, source: TaskSourceKind) =>
48
- http<TaskSourceDiagnostic>(`${ws(workspaceId)}/task-sources/${source}/diagnostics`, {
49
- method: 'POST',
50
- }),
61
+ send(diagnoseTaskSourceContract, { pathPrefix: ws(workspaceId), pathParams: { source } }),
51
62
 
52
- listTasks: (workspaceId: string) => http<SourceTask[]>(`${ws(workspaceId)}/tasks`),
63
+ listTasks: (workspaceId: string) => send(listTasksContract, { pathPrefix: ws(workspaceId) }),
53
64
 
54
65
  importTask: (workspaceId: string, source: TaskSourceKind, body: { ref: string }) =>
55
- http<SourceTask>(`${ws(workspaceId)}/task-sources/${source}/import`, {
56
- method: 'POST',
57
- body,
58
- }),
66
+ send(importTaskContract, { pathPrefix: ws(workspaceId), pathParams: { source }, body }),
59
67
 
60
68
  searchTaskSource: (
61
69
  workspaceId: string,
@@ -63,24 +71,21 @@ export function tasksApi({ http, ws }: ApiContext) {
63
71
  query: string,
64
72
  blockId?: string,
65
73
  ) =>
66
- http<{ results: TaskSearchResult[] }>(`${ws(workspaceId)}/task-sources/${source}/search`, {
67
- method: 'POST',
74
+ send(searchTasksContract, {
75
+ pathPrefix: ws(workspaceId),
76
+ pathParams: { source },
68
77
  body: { query, ...(blockId ? { blockId } : {}) },
69
78
  }),
70
79
 
71
80
  linkTask: (
72
81
  workspaceId: string,
73
82
  body: { source: TaskSourceKind; externalId: string; blockId: string },
74
- ) => http<SourceTask>(`${ws(workspaceId)}/tasks/link`, { method: 'POST', body }),
83
+ ) => send(linkTaskContract, { pathPrefix: ws(workspaceId), body }),
75
84
 
76
85
  createTaskFromIssue: (
77
86
  workspaceId: string,
78
87
  body: { source: TaskSourceKind; externalId: string; containerId: string },
79
- ) =>
80
- http<{ block: Block; task: SourceTask }>(`${ws(workspaceId)}/tasks/create-block`, {
81
- method: 'POST',
82
- body,
83
- }),
88
+ ) => send(createTaskFromIssueContract, { pathPrefix: ws(workspaceId), body }),
84
89
 
85
90
  // Spawn an epic + its children as an epic node + child tasks, with dependency edges
86
91
  // seeded from the issues' blocked-by/depends-on links.
@@ -88,17 +93,13 @@ export function tasksApi({ http, ws }: ApiContext) {
88
93
  workspaceId: string,
89
94
  source: TaskSourceKind,
90
95
  body: { ref: string; containerId: string; position?: { x: number; y: number } },
91
- ) =>
92
- http<{ epic: Block; tasks: Block[] }>(
93
- `${ws(workspaceId)}/task-sources/${source}/epics/spawn`,
94
- { method: 'POST', body },
95
- ),
96
+ ) => send(spawnEpicContract, { pathPrefix: ws(workspaceId), pathParams: { source }, body }),
96
97
 
97
98
  // ---- issue-tracker selection (workspace-level) ------------------------
98
99
  getTrackerSettings: (workspaceId: string) =>
99
- http<TrackerSettings>(`${ws(workspaceId)}/tracker-settings`),
100
+ send(getTrackerSettingsContract, { pathPrefix: ws(workspaceId) }),
100
101
 
101
102
  putTrackerSettings: (workspaceId: string, body: PutTrackerSettingsInput) =>
102
- http<TrackerSettings>(`${ws(workspaceId)}/tracker-settings`, { method: 'PUT', body }),
103
+ send(putTrackerSettingsContract, { pathPrefix: ws(workspaceId), body }),
103
104
  }
104
105
  }
@@ -1,31 +1,26 @@
1
- import type {
2
- ConnectionTestResult,
3
- StoreUserSecretInput,
4
- TestUserSecretInput,
5
- UserSecretDescriptor,
6
- UserSecretKind,
7
- UserSecretStatus,
8
- } from '~/types/userSecrets'
1
+ import {
2
+ listUserSecretsContract,
3
+ removeUserSecretContract,
4
+ storeUserSecretContract,
5
+ testUserSecretContract,
6
+ } from '@cat-factory/contracts'
7
+ import type { StoreUserSecretInput, TestUserSecretInput, UserSecretKind } from '~/types/userSecrets'
9
8
  import type { ApiContext } from './context'
10
9
 
11
10
  // Per-USER generic secrets (a GitHub PAT today). User-scoped (no workspace); the secret
12
11
  // is write-only server-side and never returned — only status metadata + a `hasSecret`
13
12
  // flag. `descriptors` drive the generic connect form; `test` probes before save.
14
- export function userSecretsApi({ http }: ApiContext) {
13
+ export function userSecretsApi({ send }: ApiContext) {
15
14
  return {
16
- listUserSecrets: () =>
17
- http<{ secrets: UserSecretStatus[]; descriptors: UserSecretDescriptor[] }>('/user-secrets'),
15
+ listUserSecrets: () => send(listUserSecretsContract, {}),
18
16
 
19
17
  storeUserSecret: (kind: UserSecretKind, body: StoreUserSecretInput) =>
20
- http<UserSecretStatus>(`/user-secrets/${encodeURIComponent(kind)}`, { method: 'POST', body }),
18
+ send(storeUserSecretContract, { pathParams: { kind }, body }),
21
19
 
22
20
  deleteUserSecret: (kind: UserSecretKind) =>
23
- http(`/user-secrets/${encodeURIComponent(kind)}`, { method: 'DELETE' }),
21
+ send(removeUserSecretContract, { pathParams: { kind } }),
24
22
 
25
23
  testUserSecret: (kind: UserSecretKind, body: TestUserSecretInput) =>
26
- http<ConnectionTestResult>(`/user-secrets/${encodeURIComponent(kind)}/test`, {
27
- method: 'POST',
28
- body,
29
- }),
24
+ send(testUserSecretContract, { pathParams: { kind }, body }),
30
25
  }
31
26
  }
@@ -1,36 +1,42 @@
1
- import type {
2
- UpdateWorkspaceSettingsInput,
3
- Workspace,
4
- WorkspaceSettings,
5
- WorkspaceSnapshot,
6
- } from '~/types/domain'
1
+ import {
2
+ createWorkspaceContract,
3
+ deleteWorkspaceContract,
4
+ getWorkspaceContract,
5
+ getWorkspaceSettingsContract,
6
+ listWorkspacesContract,
7
+ updateWorkspaceContract,
8
+ updateWorkspaceSettingsContract,
9
+ } from '@cat-factory/contracts'
10
+ import type { UpdateWorkspaceSettingsInput } from '~/types/domain'
7
11
  import type { ApiContext } from './context'
8
12
 
9
13
  /** Workspace CRUD + the full snapshot read. */
10
- export function workspacesApi({ http, ws }: ApiContext) {
14
+ export function workspacesApi({ send, ws }: ApiContext) {
11
15
  return {
12
16
  // ---- workspaces -------------------------------------------------------
13
- listWorkspaces: () => http<Workspace[]>('/workspaces'),
17
+ listWorkspaces: () => send(listWorkspacesContract, {}),
14
18
 
15
19
  createWorkspace: (
16
20
  body: { name?: string; description?: string; seed?: boolean; accountId?: string } = {},
17
- ) => http<WorkspaceSnapshot>('/workspaces', { method: 'POST', body }),
21
+ ) => send(createWorkspaceContract, { body }),
18
22
 
19
- getWorkspace: (workspaceId: string) => http<WorkspaceSnapshot>(ws(workspaceId)),
23
+ getWorkspace: (workspaceId: string) =>
24
+ send(getWorkspaceContract, { pathParams: { workspaceId } }),
20
25
 
21
26
  updateWorkspace: (workspaceId: string, body: { name?: string; description?: string | null }) =>
22
- http<Workspace>(ws(workspaceId), { method: 'PATCH', body }),
27
+ send(updateWorkspaceContract, { pathParams: { workspaceId }, body }),
23
28
 
24
29
  renameWorkspace: (workspaceId: string, name: string) =>
25
- http<Workspace>(ws(workspaceId), { method: 'PATCH', body: { name } }),
30
+ send(updateWorkspaceContract, { pathParams: { workspaceId }, body: { name } }),
26
31
 
27
- deleteWorkspace: (workspaceId: string) => http(ws(workspaceId), { method: 'DELETE' }),
32
+ deleteWorkspace: (workspaceId: string) =>
33
+ send(deleteWorkspaceContract, { pathParams: { workspaceId } }),
28
34
 
29
35
  // ---- workspace runtime settings (human-wait escalation + per-service task limit) --
30
36
  getWorkspaceSettings: (workspaceId: string) =>
31
- http<WorkspaceSettings>(`${ws(workspaceId)}/settings`),
37
+ send(getWorkspaceSettingsContract, { pathPrefix: ws(workspaceId) }),
32
38
 
33
39
  updateWorkspaceSettings: (workspaceId: string, body: UpdateWorkspaceSettingsInput) =>
34
- http<WorkspaceSettings>(`${ws(workspaceId)}/settings`, { method: 'PUT', body }),
40
+ send(updateWorkspaceSettingsContract, { pathPrefix: ws(workspaceId), body }),
35
41
  }
36
42
  }
@@ -1,4 +1,5 @@
1
1
  import type { FragmentOwnerKind } from '~/types/domain'
2
+ import { createApiClient, createSend, createSendWith } from './api/client'
2
3
  import type { ApiContext } from './api/context'
3
4
  import { accountsApi } from './api/accounts'
4
5
  import { authApi } from './api/auth'
@@ -75,7 +76,14 @@ export function useApi() {
75
76
  ? `/accounts/${encodeURIComponent(id)}`
76
77
  : `/workspaces/${encodeURIComponent(id)}`
77
78
 
78
- const ctx: ApiContext = { http, ws, scope, pwHeaders }
79
+ // The contract-driven client (wretch + sendByApiContract): one source of truth for
80
+ // path/method/request/response, shared with the backend via @cat-factory/contracts.
81
+ // API groups are migrated onto `send` incrementally; the rest still use `http`.
82
+ const client = createApiClient()
83
+ const send = createSend(client)
84
+ const sendWith = createSendWith(client)
85
+
86
+ const ctx: ApiContext = { http, client, send, sendWith, ws, scope, pwHeaders }
79
87
 
80
88
  return {
81
89
  ...authApi(ctx),
@@ -1,20 +1,26 @@
1
1
  import type { Ref, WritableComputedRef } from 'vue'
2
2
 
3
3
  /**
4
- * The shared "back to Integrations" handler for an integration sub-panel's modal header.
5
- * Every panel reached from the Integrations hub closes itself and reopens the hub when its
4
+ * The shared "back to the hub" handler for an integration sub-panel's modal header.
5
+ * Every panel reached from a hub closes itself and reopens that hub when its
6
6
  * {@link IntegrationBackTitle} Back control fires `@back`. Centralising it keeps the ~13
7
7
  * panels from each re-implementing the two-step close-then-reopen inline — which also
8
8
  * dodges a Vue SFC-compiler trap: a multi-statement inline template handler
9
9
  * (`open = false` ⏎ `ui.openIntegrations()`) is rejected at build time, so callers had to
10
10
  * resort to an obscure comma-operator expression. A named handler reads clearly instead.
11
11
  *
12
+ * Returns to whichever hub the panel was reached from: the user-scoped "My setup" hub when
13
+ * `cameFromPersonal` is set, else the workspace Integrations hub. A shared panel (e.g. the
14
+ * vendor-credentials modal, reachable from both) thus lands the user back where they were.
15
+ *
12
16
  * Pass the panel's `open` model (the writable ref/computed bound to its `UModal`).
13
17
  */
14
18
  export function useIntegrationBack(open: Ref<boolean> | WritableComputedRef<boolean>) {
15
19
  const ui = useUiStore()
16
20
  return () => {
21
+ const toPersonal = ui.cameFromPersonal
17
22
  open.value = false
18
- ui.openIntegrations()
23
+ if (toPersonal) ui.openPersonalSetup()
24
+ else ui.openIntegrations()
19
25
  }
20
26
  }
@@ -28,6 +28,7 @@ import GitHubOnboarding from '~/components/github/GitHubOnboarding.vue'
28
28
  import FragmentLibraryPanel from '~/components/fragments/FragmentLibraryPanel.vue'
29
29
  import CommandBar from '~/components/layout/CommandBar.vue'
30
30
  import IntegrationsHub from '~/components/layout/IntegrationsHub.vue'
31
+ import PersonalSetupModal from '~/components/layout/PersonalSetupModal.vue'
31
32
  import WorkspaceSettingsPanel from '~/components/settings/WorkspaceSettingsPanel.vue'
32
33
  import AccountSettingsPanel from '~/components/settings/AccountSettingsPanel.vue'
33
34
  import ObservabilityConnectionPanel from '~/components/settings/ObservabilityConnectionPanel.vue'
@@ -189,6 +190,7 @@ watch(
189
190
  <FragmentLibraryPanel />
190
191
  <CommandBar />
191
192
  <IntegrationsHub />
193
+ <PersonalSetupModal />
192
194
  <WorkspaceSettingsPanel />
193
195
  <AccountSettingsPanel />
194
196
  <ObservabilityConnectionPanel />
@@ -1,3 +1,4 @@
1
+ import type { LocalModeConfig } from '@cat-factory/contracts'
1
2
  import { defineStore } from 'pinia'
2
3
  import { computed, ref } from 'vue'
3
4
  import type { AuthUser } from '~/types/domain'
@@ -29,7 +30,7 @@ export const useAuthStore = defineStore(
29
30
  * `githubPatSetupUrl` is set when local mode has no GitHub PAT configured (drives the
30
31
  * setup banner). Null on every other facade.
31
32
  */
32
- const localMode = ref<{ enabled: boolean; githubPatSetupUrl?: string } | null>(null)
33
+ const localMode = ref<LocalModeConfig | null>(null)
33
34
  /** True once the initial auth handshake has settled. */
34
35
  const ready = ref(false)
35
36
 
@@ -1,5 +1,6 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref } from 'vue'
3
+ import type { UpdateBlockInput } from '@cat-factory/contracts'
3
4
  import type { Block, BlockType, CreateTaskType, TaskTypeFields } from '~/types/domain'
4
5
  import { useServicesStore } from '~/stores/services'
5
6
  import { useWorkspaceStore } from '~/stores/workspace'
@@ -295,7 +296,7 @@ export const useBoardStore = defineStore('board', () => {
295
296
  }
296
297
 
297
298
  /** Patch the user-editable fields of a block (title, features, threshold…). */
298
- async function updateBlock(id: string, patch: Partial<Block>) {
299
+ async function updateBlock(id: string, patch: UpdateBlockInput) {
299
300
  const b = getBlock(id)
300
301
  if (!b) return
301
302
  Object.assign(b, patch) // optimistic
@@ -1,10 +1,10 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref } from 'vue'
3
3
  import type {
4
+ BrainstormItemStatus,
4
5
  BrainstormSession,
5
6
  BrainstormStage,
6
7
  ResolveBrainstormExceededChoice,
7
- ReviewItemStatus,
8
8
  } from '~/types/brainstorm'
9
9
  import { useWorkspaceStore } from '~/stores/workspace'
10
10
 
@@ -123,7 +123,7 @@ export const useBrainstormStore = defineStore('brainstorm', () => {
123
123
  async function setItemStatus(
124
124
  session: BrainstormSession,
125
125
  itemId: string,
126
- status: ReviewItemStatus,
126
+ status: BrainstormItemStatus,
127
127
  ) {
128
128
  store(await api.setBrainstormItemStatus(workspace.requireId(), session.id, itemId, status))
129
129
  }
@@ -1,6 +1,10 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref } from 'vue'
3
- import type { ClarityReview, ResolveClarityExceededChoice, ReviewItemStatus } from '~/types/clarity'
3
+ import type {
4
+ ClarityItemStatus,
5
+ ClarityReview,
6
+ ResolveClarityExceededChoice,
7
+ } from '~/types/clarity'
4
8
  import { useWorkspaceStore } from '~/stores/workspace'
5
9
 
6
10
  /**
@@ -120,7 +124,7 @@ export const useClarityStore = defineStore('clarity', () => {
120
124
  }
121
125
 
122
126
  /** Set an item's status (dismiss / reopen). */
123
- async function setItemStatus(review: ClarityReview, itemId: string, status: ReviewItemStatus) {
127
+ async function setItemStatus(review: ClarityReview, itemId: string, status: ClarityItemStatus) {
124
128
  store(await api.setClarityItemStatus(workspace.requireId(), review.id, itemId, status))
125
129
  }
126
130
 
@@ -7,7 +7,8 @@ import type {
7
7
  PipelineStep,
8
8
  StepApproval,
9
9
  } from '~/types/domain'
10
- import type { IterationCapChoice, ReviewComment } from '~/types/execution'
10
+ import type { RequestStepChangesInput } from '@cat-factory/contracts'
11
+ import type { IterationCapChoice } from '~/types/execution'
11
12
  import { useWorkspaceStore } from '~/stores/workspace'
12
13
 
13
14
  /**
@@ -163,7 +164,7 @@ export const useExecutionStore = defineStore('execution', () => {
163
164
  async function requestStepChanges(
164
165
  instanceId: string,
165
166
  approvalId: string,
166
- review: { feedback?: string; comments?: ReviewComment[] },
167
+ review: RequestStepChangesInput,
167
168
  ) {
168
169
  const ws = useWorkspaceStore()
169
170
  const personal = usePersonalSubscriptionsStore()
@@ -2,7 +2,6 @@ import { defineStore } from 'pinia'
2
2
  import { computed, ref } from 'vue'
3
3
  import type {
4
4
  CreateBranchInput,
5
- CreateRepoRequest,
6
5
  GitHubAvailableRepo,
7
6
  GitHubBranch,
8
7
  GitHubConnection,
@@ -224,7 +223,7 @@ export const useGitHubStore = defineStore('github', () => {
224
223
  * meaningful when `canCreateRepos`; the backend 409s otherwise. Returns the
225
224
  * created repo so the caller can confirm/link it.
226
225
  */
227
- function createRepo(input: CreateRepoRequest) {
226
+ function createRepo(input: Parameters<typeof api.createGitHubRepo>[1]) {
228
227
  return api.createGitHubRepo(workspace.requireId(), input)
229
228
  }
230
229
 
@@ -1,10 +1,6 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { computed, ref } from 'vue'
3
- import type {
4
- CreateMergePresetInput,
5
- MergeThresholdPreset,
6
- UpdateMergePresetInput,
7
- } from '~/types/domain'
3
+ import type { MergeThresholdPreset, UpdateMergePresetInput } from '~/types/domain'
8
4
  import { useWorkspaceStore } from '~/stores/workspace'
9
5
 
10
6
  /**
@@ -34,7 +30,7 @@ export const useMergePresetsStore = defineStore('mergePresets', () => {
34
30
  return defaultPreset.value
35
31
  }
36
32
 
37
- async function create(input: CreateMergePresetInput) {
33
+ async function create(input: Parameters<typeof api.createMergePreset>[1]) {
38
34
  const ws = useWorkspaceStore()
39
35
  const created = await api.createMergePreset(ws.requireId(), input)
40
36
  await ws.refresh()
@@ -132,7 +132,7 @@ export const usePipelinesStore = defineStore('pipelines', () => {
132
132
  function toggleDraftGating(index: number) {
133
133
  draftGating.value[index] = draftGating.value[index]?.enabled
134
134
  ? null
135
- : { enabled: true, minRisk: 0.5, minImpact: 0.5 }
135
+ : { enabled: true, minRisk: 0.5, minImpact: 0.5, onMissingEstimate: 'run' }
136
136
  }
137
137
 
138
138
  /**
@@ -1,11 +1,6 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { computed, ref } from 'vue'
3
- import type {
4
- CreateScheduleInput,
5
- PipelineSchedule,
6
- ScheduleRun,
7
- UpdateScheduleInput,
8
- } from '~/types/recurring'
3
+ import type { PipelineSchedule, ScheduleRun, UpdateScheduleInput } from '~/types/recurring'
9
4
  import { useWorkspaceStore } from '~/stores/workspace'
10
5
  import { useBoardStore } from '~/stores/board'
11
6
 
@@ -39,7 +34,7 @@ export const useRecurringPipelinesStore = defineStore('recurringPipelines', () =
39
34
  return schedules.value.find((s) => s.blockId === blockId)
40
35
  }
41
36
 
42
- async function create(input: CreateScheduleInput) {
37
+ async function create(input: Parameters<typeof api.createRecurringPipeline>[1]) {
43
38
  const ws = useWorkspaceStore()
44
39
  const created = await api.createRecurringPipeline(ws.requireId(), input)
45
40
  await ws.refresh()
@@ -2,7 +2,6 @@ import { defineStore } from 'pinia'
2
2
  import { computed, ref } from 'vue'
3
3
  import type { ModelOption } from '~/types/domain'
4
4
  import type {
5
- CreateSandboxExperimentInput,
6
5
  SandboxAgentKindMeta,
7
6
  SandboxExperiment,
8
7
  SandboxExperimentDetail,
@@ -118,7 +117,7 @@ export const useSandboxStore = defineStore('sandbox', () => {
118
117
  await load()
119
118
  }
120
119
 
121
- async function createExperiment(input: CreateSandboxExperimentInput) {
120
+ async function createExperiment(input: Parameters<typeof api.createSandboxExperiment>[1]) {
122
121
  const ws = useWorkspaceStore()
123
122
  const created = await api.createSandboxExperiment(ws.requireId(), input)
124
123
  await load()