@cat-factory/app 0.311.3 → 0.313.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 (46) hide show
  1. package/README.md +32 -0
  2. package/app/components/board/nodes/TaskCard.vue +45 -212
  3. package/app/components/layout/AiProvidersBanner.vue +3 -2
  4. package/app/components/layout/BoardToolbar.vue +24 -26
  5. package/app/components/layout/BoardTopOverlays.vue +8 -2
  6. package/app/components/layout/GitHubPatBanner.vue +2 -2
  7. package/app/components/layout/GitHubPatPermissionsBanner.vue +4 -12
  8. package/app/components/layout/InfraSetupBanner.vue +6 -7
  9. package/app/components/layout/SideBar.vue +5 -0
  10. package/app/components/layout/WorkViewSwitcher.vue +64 -0
  11. package/app/components/queue/QueueCard.vue +269 -0
  12. package/app/components/queue/QueueView.vue +192 -0
  13. package/app/components/setup/SetupChecklistPanel.vue +340 -0
  14. package/app/composables/useFrameLanes.ts +6 -82
  15. package/app/composables/useNavContributions.ts +3 -0
  16. package/app/composables/useSetupChecklist.ts +122 -0
  17. package/app/composables/useSetupRemedies.ts +72 -0
  18. package/app/composables/useTaskActions.ts +254 -0
  19. package/app/composables/useTaskLaneClassifier.ts +88 -0
  20. package/app/modular/nav-contributions.spec.ts +6 -0
  21. package/app/modular/nav-contributions.ts +56 -0
  22. package/app/modular/tutorial-tours.ts +10 -0
  23. package/app/pages/index.vue +43 -6
  24. package/app/stores/github/context.ts +1 -0
  25. package/app/stores/github/probe.ts +7 -3
  26. package/app/stores/github.ts +9 -0
  27. package/app/stores/ui/modals.ts +14 -0
  28. package/app/stores/workView.ts +51 -0
  29. package/app/stores/workspaceQueue.ts +148 -0
  30. package/app/utils/queueSections.spec.ts +111 -0
  31. package/app/utils/queueSections.ts +117 -0
  32. package/app/utils/setupChecklist.spec.ts +184 -0
  33. package/app/utils/setupChecklist.ts +229 -0
  34. package/app/utils/workView.spec.ts +16 -0
  35. package/app/utils/workView.ts +25 -0
  36. package/i18n/locales/de.json +132 -3
  37. package/i18n/locales/en.json +132 -3
  38. package/i18n/locales/es.json +132 -3
  39. package/i18n/locales/fr.json +132 -3
  40. package/i18n/locales/he.json +132 -3
  41. package/i18n/locales/it.json +132 -3
  42. package/i18n/locales/ja.json +132 -3
  43. package/i18n/locales/pl.json +132 -3
  44. package/i18n/locales/tr.json +132 -3
  45. package/i18n/locales/uk.json +132 -3
  46. package/package.json +1 -1
@@ -0,0 +1,229 @@
1
+ import type { InfraSetup, InfraSetupOwners, InfraSetupStatus } from '@cat-factory/contracts'
2
+ import { isInfraSetupHealthStatus } from '@cat-factory/contracts'
3
+ import type { ProviderConnectionKind } from '~/types/providerConnections'
4
+ import {
5
+ canActOnSetup,
6
+ effectiveOwner,
7
+ type SetupActor,
8
+ type SetupRemedy,
9
+ } from '~/utils/setupAudience'
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // The setup checklist: what this workspace needs before a task can run and merge, as ONE list.
13
+ //
14
+ // Every row is composed from a probe that already exists and already drives a banner or a
15
+ // startup dialog (`useAiReadiness`, the GitHub probe, `workspace.infraSetup`, the provider
16
+ // connections' missing-required fields). The checklist adds no probe of its own: it states the
17
+ // same facts in one place, with a finish line, instead of one interruption per missing piece.
18
+ // Who may act on a row is the banners' rule too (`utils/setupAudience.ts`).
19
+ // ---------------------------------------------------------------------------
20
+
21
+ /** The rows. The infrastructure rows are named by their `InfraSetupArea`, the server's vocabulary. */
22
+ export const SETUP_ROWS = [
23
+ 'model',
24
+ 'sourceControl',
25
+ 'agentExecutor',
26
+ 'ephemeralEnvironments',
27
+ 'binaryStorage',
28
+ ] as const
29
+ export type SetupRowId = (typeof SETUP_ROWS)[number]
30
+
31
+ /**
32
+ * A row's state. Five, because they need five different reactions:
33
+ *
34
+ * - `done`: nothing to do.
35
+ * - `missing`: never set up. The fix is to connect something.
36
+ * - `attention`: set up, but broken, unreachable or incomplete. The fix is to repair it, and
37
+ * saying "connect" would send the reader to create a second one. Its {@link SetupRowCause} says
38
+ * which, because each needs a different fix.
39
+ * - `checking`: the probe has not answered. Never rendered as missing: an unanswered probe and
40
+ * an absent capability are opposite facts.
41
+ * - `not_needed`: this deployment does not use the area at all. Left out of the count.
42
+ */
43
+ export type SetupRowStatus = 'done' | 'missing' | 'attention' | 'checking' | 'not_needed'
44
+
45
+ /** Why a row needs attention. Each one names a different fix. */
46
+ export type SetupRowCause =
47
+ /** Configured, and its live probe says it cannot be reached. */
48
+ | 'unreachable'
49
+ /** Connected, but a mandatory provider field is unset. */
50
+ | 'incomplete'
51
+ /** GitHub refused the access token outright. */
52
+ | 'rejected'
53
+ /** The token authenticates but cannot push or open pull requests. */
54
+ | 'underscoped'
55
+ /** Usable models exist, but the default preset names one that is not. */
56
+ | 'presetBroken'
57
+ /** The probe itself failed, so the answer is unknown. The fix is to ask again. */
58
+ | 'probeFailed'
59
+ /** The workspace loaded, and this backend does not report the area at all. */
60
+ | 'notReported'
61
+
62
+ /** Whether a task can run without the row. An optional row only switches off the agents that use it. */
63
+ export const SETUP_ROW_REQUIRED: Record<SetupRowId, boolean> = {
64
+ model: true,
65
+ sourceControl: true,
66
+ agentExecutor: true,
67
+ ephemeralEnvironments: false,
68
+ binaryStorage: false,
69
+ }
70
+
71
+ /** Everything the checklist reads, resolved by the caller so this stays pure. */
72
+ export interface SetupProbeInput {
73
+ readonly model: {
74
+ /** The per-workspace model catalog has loaded for this workspace. */
75
+ readonly loaded: boolean
76
+ /** The last attempt to load it failed. */
77
+ readonly loadFailed: boolean
78
+ readonly usable: boolean
79
+ /** Usable models exist, but the default preset names one that is not. */
80
+ readonly presetBroken: boolean
81
+ }
82
+ readonly sourceControl: {
83
+ /** Null while the GitHub probe is in flight. */
84
+ readonly available: boolean | null
85
+ /** Why `available` is false: switched off by the deployment, or the probe failed. */
86
+ readonly unavailableCause: 'disabled' | 'failed' | null
87
+ readonly connected: boolean
88
+ /** Local mode with no personal access token set. */
89
+ readonly patMissing: boolean
90
+ /** The token check's verdict, when it needs attention. */
91
+ readonly patProblem: 'rejected' | 'underscoped' | null
92
+ }
93
+ /** Null until the workspace snapshot has delivered it, or from a backend that omits it. */
94
+ readonly infra: InfraSetup | null
95
+ /** The workspace snapshot has loaded, so a null `infra` is an answer, not a wait. */
96
+ readonly workspaceLoaded: boolean
97
+ /** Who can close each infrastructure gap; null from a backend that does not report it. */
98
+ readonly infraOwners: InfraSetupOwners | null
99
+ readonly providers: {
100
+ /** The provider connections have loaded, so `needingConfig` is an answer. */
101
+ readonly loaded: boolean
102
+ /** Provider connections that are wired but miss a mandatory field. */
103
+ readonly needingConfig: readonly ProviderConnectionKind[]
104
+ }
105
+ readonly actor: SetupActor
106
+ }
107
+
108
+ /** A row's state and, exactly when it needs attention, why. */
109
+ export type SetupRowState =
110
+ | { readonly status: Exclude<SetupRowStatus, 'attention'>; readonly cause: null }
111
+ | { readonly status: 'attention'; readonly cause: SetupRowCause }
112
+
113
+ export type SetupRow = SetupRowState & {
114
+ readonly id: SetupRowId
115
+ readonly required: boolean
116
+ /** Null when this caller can act on the row; otherwise how the gap gets fixed. */
117
+ readonly remedy: SetupRemedy | null
118
+ }
119
+
120
+ export interface SetupChecklist {
121
+ readonly rows: SetupRow[]
122
+ /** Rows that count toward the finish line (everything except `not_needed`). */
123
+ readonly total: number
124
+ readonly done: number
125
+ /** A counted row has not answered yet, so `done` is not a count of the finished rows yet. */
126
+ readonly checking: boolean
127
+ }
128
+
129
+ type RowState = SetupRowState
130
+ const state = (status: Exclude<SetupRowStatus, 'attention'>): RowState => ({ status, cause: null })
131
+ const attention = (cause: SetupRowCause): RowState => ({ status: 'attention', cause })
132
+
133
+ function infraRow(
134
+ status: InfraSetupStatus | undefined,
135
+ workspaceLoaded: boolean,
136
+ provider: { loaded: boolean; incomplete: boolean } | null,
137
+ ): RowState {
138
+ if (status === undefined) return workspaceLoaded ? attention('notReported') : state('checking')
139
+ if (status === 'not_applicable') return state('not_needed')
140
+ if (status === 'not_defined') return state('missing')
141
+ if (isInfraSetupHealthStatus(status)) return attention('unreachable')
142
+ // Configured. Whether a mandatory field is unset is known only once the providers load; until
143
+ // then the row has not answered, rather than claiming done.
144
+ if (provider && !provider.loaded) return state('checking')
145
+ return provider?.incomplete ? attention('incomplete') : state('done')
146
+ }
147
+
148
+ function modelRow(m: SetupProbeInput['model']): RowState {
149
+ if (!m.loaded) return m.loadFailed ? attention('probeFailed') : state('checking')
150
+ if (!m.usable) return state('missing')
151
+ return m.presetBroken ? attention('presetBroken') : state('done')
152
+ }
153
+
154
+ function sourceControlRow(s: SetupProbeInput['sourceControl']): RowState {
155
+ if (s.patMissing) return state('missing')
156
+ if (s.patProblem) return attention(s.patProblem)
157
+ if (s.connected) return state('done')
158
+ if (s.available === null) return state('checking')
159
+ if (s.available === false) {
160
+ if (s.unavailableCause === 'disabled') return state('not_needed')
161
+ if (s.unavailableCause === 'failed') return attention('probeFailed')
162
+ }
163
+ return state('missing')
164
+ }
165
+
166
+ /**
167
+ * Who closes a row's gap. Infrastructure follows its reported owner. A personal access token is
168
+ * fixed by whoever holds it: the remedy is a token page, not a workspace setting, so every caller
169
+ * gets the link. A model or a GitHub connection is a workspace setting.
170
+ */
171
+ function rowOwner(id: SetupRowId, input: SetupProbeInput): unknown {
172
+ switch (id) {
173
+ case 'agentExecutor':
174
+ return input.infraOwners?.agentExecutor
175
+ case 'ephemeralEnvironments':
176
+ return input.infraOwners?.ephemeralEnvironments
177
+ case 'binaryStorage':
178
+ return input.infraOwners?.binaryStorage
179
+ case 'model':
180
+ return 'workspace_admin'
181
+ case 'sourceControl':
182
+ return input.sourceControl.patMissing || input.sourceControl.patProblem
183
+ ? null
184
+ : 'workspace_admin'
185
+ default: {
186
+ const unreachable: never = id
187
+ return unreachable
188
+ }
189
+ }
190
+ }
191
+
192
+ function remedyFor(owner: unknown, actor: SetupActor): SetupRemedy | null {
193
+ if (owner === null) return null
194
+ if (canActOnSetup(owner, actor)) return null
195
+ return canActOnSetup(owner, { ...actor, fullSurface: true })
196
+ ? 'full_surface'
197
+ : effectiveOwner(owner)
198
+ }
199
+
200
+ export function deriveSetupChecklist(input: SetupProbeInput): SetupChecklist {
201
+ const { loaded, needingConfig } = input.providers
202
+ const states: Record<SetupRowId, RowState> = {
203
+ model: modelRow(input.model),
204
+ sourceControl: sourceControlRow(input.sourceControl),
205
+ agentExecutor: infraRow(input.infra?.agentExecutor, input.workspaceLoaded, {
206
+ loaded,
207
+ incomplete: needingConfig.includes('runner-pool'),
208
+ }),
209
+ ephemeralEnvironments: infraRow(input.infra?.ephemeralEnvironments, input.workspaceLoaded, {
210
+ loaded,
211
+ incomplete: needingConfig.includes('environment'),
212
+ }),
213
+ // Storage has no provider connection, so nothing about it waits on the providers.
214
+ binaryStorage: infraRow(input.infra?.binaryStorage, input.workspaceLoaded, null),
215
+ }
216
+ const rows = SETUP_ROWS.map((id) => ({
217
+ id,
218
+ ...states[id],
219
+ required: SETUP_ROW_REQUIRED[id],
220
+ remedy: remedyFor(rowOwner(id, input), input.actor),
221
+ }))
222
+ const counted = rows.filter((r) => r.status !== 'not_needed')
223
+ return {
224
+ rows,
225
+ total: counted.length,
226
+ done: counted.filter((r) => r.status === 'done').length,
227
+ checking: counted.some((r) => r.status === 'checking'),
228
+ }
229
+ }
@@ -0,0 +1,16 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { DEFAULT_WORK_VIEW, isWorkView } from '~/utils/workView'
3
+
4
+ describe('isWorkView', () => {
5
+ it('accepts the two views and nothing else', () => {
6
+ expect(isWorkView('queue')).toBe(true)
7
+ expect(isWorkView('board')).toBe(true)
8
+ // A retired or hand-edited persisted value is not a view, so the store falls back.
9
+ expect(isWorkView('setup')).toBe(false)
10
+ expect(isWorkView(null)).toBe(false)
11
+ })
12
+
13
+ it('lands a person who has not chosen on the queue', () => {
14
+ expect(DEFAULT_WORK_VIEW).toBe('queue')
15
+ })
16
+ })
@@ -0,0 +1,25 @@
1
+ // ---------------------------------------------------------------------------
2
+ // The two views of a board (issue #2258): the QUEUE (every task across every service, in the
3
+ // column that says what it needs) and the BOARD (the canvas, where the work is planned).
4
+ //
5
+ // They are two views of one board, not two products: the queue reads the same lane verdict the
6
+ // canvas's swimlanes do. Which one a person opens on is THEIR choice, remembered as the view they
7
+ // used last, because the jobs differ: someone who reviews all day wants the list, someone who
8
+ // plans the next service wants the map.
9
+ // ---------------------------------------------------------------------------
10
+
11
+ export const WORK_VIEWS = ['queue', 'board'] as const
12
+ export type WorkView = (typeof WORK_VIEWS)[number]
13
+
14
+ /**
15
+ * Where a person lands before they have chosen. The queue: it answers the first question a
16
+ * person opens the app with ("what needs me?"), and the canvas is one click away.
17
+ */
18
+ export const DEFAULT_WORK_VIEW: WorkView = 'queue'
19
+
20
+ export function isWorkView(value: unknown): value is WorkView {
21
+ return typeof value === 'string' && (WORK_VIEWS as readonly string[]).includes(value)
22
+ }
23
+
24
+ /** The query parameter that opens a view, so a link can say "look at the queue". */
25
+ export const WORK_VIEW_PARAM = 'view'
@@ -2773,7 +2773,10 @@
2773
2773
  "toggleUiMode": "Oberflächenmodus wechseln",
2774
2774
  "chooseRole": "Rolle wechseln",
2775
2775
  "foundationalServices": "Basisdienste",
2776
- "notificationSettings": "Benachrichtigungs-Routing verwalten"
2776
+ "notificationSettings": "Benachrichtigungs-Routing verwalten",
2777
+ "setupChecklist": "Einrichtungs-Checkliste",
2778
+ "queueView": "Warteschlangen-Ansicht öffnen",
2779
+ "boardView": "Board-Ansicht öffnen"
2777
2780
  },
2778
2781
  "keywords": {
2779
2782
  "newPipeline": "pipeline agents chain",
@@ -2801,7 +2804,10 @@
2801
2804
  "chooseRole": "rolle entwickler produktmanager designer persona einfachere ansicht",
2802
2805
  "tutorial": "tutorial tour einführung hilfe onboarding lernen grundlagen",
2803
2806
  "foundationalServices": "gemeinsame Fähigkeit Plattform Dienst API Vertrag OpenAPI Katalog",
2804
- "notificationSettings": "benachrichtigungen e-mail routing kanäle posteingang"
2807
+ "notificationSettings": "benachrichtigungen e-mail routing kanäle posteingang",
2808
+ "setupChecklist": "einrichtung checkliste setup runner modell github speicher umgebung konfigurieren",
2809
+ "queueView": "warteschlange ansicht wartet auf dich liste",
2810
+ "boardView": "board canvas karte ansicht planen"
2805
2811
  }
2806
2812
  },
2807
2813
  "shortcuts": {
@@ -6294,7 +6300,8 @@
6294
6300
  "reports": "Berichte",
6295
6301
  "foundationalServices": "Basisdienste",
6296
6302
  "tutorials": "Tutorials",
6297
- "help": "Hilfe"
6303
+ "help": "Hilfe",
6304
+ "setupChecklist": "Einrichtungs-Checkliste"
6298
6305
  },
6299
6306
  "errors": {
6300
6307
  "generic": {
@@ -8115,6 +8122,10 @@
8115
8122
  "title": "Das Board",
8116
8123
  "body": "Services, Module und Aufgaben liegen auf dieser Fläche. Ziehe zum Verschieben, scrolle zum Zoomen und klicke auf eine Karte, um Details zu sehen."
8117
8124
  },
8125
+ "views": {
8126
+ "title": "Zwei Ansichten",
8127
+ "body": "Das Board hat eine zweite Ansicht. Die Warteschlange zeigt, was über alle Services hinweg auf dich wartet. Nach der Tour wechselst du hier zwischen der Warteschlange und dieser Arbeitsfläche. Die App öffnet die Ansicht, die du zuletzt genutzt hast."
8128
+ },
8118
8129
  "sidebar": {
8119
8130
  "title": "Die Seitenleiste",
8120
8131
  "body": "Alles Weitere findest du hier: Pipelines erstellen, Repositories und Integrationen verbinden, Workspace-Einstellungen."
@@ -8734,5 +8745,123 @@
8734
8745
  "unsupportedVersion": "Dieses Design stammt aus einem neueren Editor-Format, als diese App versteht."
8735
8746
  }
8736
8747
  }
8748
+ },
8749
+ "setup": {
8750
+ "title": "Einrichtung",
8751
+ "progress": "{done} von {total} erledigt",
8752
+ "intro": "Was dieser Workspace braucht, damit eine Aufgabe laufen und gemergt werden kann.",
8753
+ "required": "erforderlich",
8754
+ "optional": "optional",
8755
+ "action": {
8756
+ "change": "Ändern",
8757
+ "connect": "Einrichten",
8758
+ "fix": "Beheben",
8759
+ "review": "Prüfen",
8760
+ "retry": "Erneut versuchen"
8761
+ },
8762
+ "rows": {
8763
+ "checking": "Wird geprüft…",
8764
+ "notNeeded": "Diese Bereitstellung nutzt das nicht.",
8765
+ "model": {
8766
+ "title": "Modell",
8767
+ "done": "Ein Modell ist verfügbar.",
8768
+ "missing": "Kein Modell verfügbar. Kein Agent kann laufen, bis du einen Anbieter verbindest."
8769
+ },
8770
+ "sourceControl": {
8771
+ "title": "Quellcodeverwaltung",
8772
+ "done": "Verbunden. Agenten können Branches pushen und Pull Requests öffnen.",
8773
+ "missing": "Nicht verbunden. Agenten können keine Pull Requests öffnen."
8774
+ },
8775
+ "agentExecutor": {
8776
+ "title": "Wo Agenten laufen",
8777
+ "done": "Ein Runner ist konfiguriert.",
8778
+ "missing": "Kein Runner konfiguriert. Nichts kann laufen, bis du einen verbindest.",
8779
+ "notNeeded": "Diese Bereitstellung führt Agenten ohne Runner aus."
8780
+ },
8781
+ "ephemeralEnvironments": {
8782
+ "title": "Testumgebungen",
8783
+ "done": "Konfiguriert. Tester können eine Live-Vorschau nutzen.",
8784
+ "missing": "Nicht eingerichtet. Tester, die eine Live-Vorschau brauchen, laufen nicht. Alle anderen Agenten laufen."
8785
+ },
8786
+ "binaryStorage": {
8787
+ "title": "Screenshot-Speicher",
8788
+ "done": "Konfiguriert. Visuelle Prüfungen sind aktiv.",
8789
+ "missing": "Nicht eingerichtet. Visuelle Prüfungen sind aus."
8790
+ }
8791
+ },
8792
+ "causes": {
8793
+ "unreachable": "Eingerichtet, aber gerade nicht erreichbar.",
8794
+ "incomplete": "Verbunden, aber eine erforderliche Einstellung fehlt.",
8795
+ "rejected": "GitHub hat den Zugriffstoken abgelehnt.",
8796
+ "underscoped": "Der Zugriffstoken kann weder pushen noch Pull Requests öffnen.",
8797
+ "presetBroken": "Das Standard-Modell-Preset nennt ein Modell, das nicht verfügbar ist.",
8798
+ "probeFailed": "Die Prüfung hat nicht geantwortet.",
8799
+ "notReported": "Diese Bereitstellung meldet es nicht."
8800
+ },
8801
+ "also": {
8802
+ "title": "Außerdem hier",
8803
+ "pipelines": "Pipelines",
8804
+ "riskPolicies": "Merge-Richtlinien",
8805
+ "modelPresets": "Modell-Presets",
8806
+ "counts": {
8807
+ "repair": "Zu reparieren: {count}",
8808
+ "outdated": "Veraltet: {count}",
8809
+ "new": "Neu: {count}"
8810
+ },
8811
+ "settings": "Einstellungen und Verbindungen",
8812
+ "workspaceSettings": "Workspace-Einstellungen",
8813
+ "integrations": "Integrationen"
8814
+ }
8815
+ },
8816
+ "queue": {
8817
+ "title": "Warteschlange",
8818
+ "summary": "{needsYou} warten auf dich · {ready} bereit zum Mergen",
8819
+ "filter": {
8820
+ "allServices": "Alle Services",
8821
+ "service": "Nach Service filtern"
8822
+ },
8823
+ "columns": {
8824
+ "needsYou": {
8825
+ "label": "Wartet auf dich",
8826
+ "empty": "Nichts wartet auf dich."
8827
+ },
8828
+ "inFlight": {
8829
+ "label": "In Arbeit",
8830
+ "empty": "Derzeit arbeitet kein Agent."
8831
+ },
8832
+ "readyToMerge": {
8833
+ "label": "Bereit zum Mergen",
8834
+ "empty": "Kein Pull Request wartet auf den Merge."
8835
+ }
8836
+ },
8837
+ "waiting": {
8838
+ "label": "Nicht begonnen ({count})",
8839
+ "empty": "Nichts wartet auf den Start."
8840
+ },
8841
+ "done": {
8842
+ "count": "Seit {date} gemergt: {count}",
8843
+ "countAll": "Gemergt: {count}",
8844
+ "show": "Anzeigen",
8845
+ "hide": "Ausblenden",
8846
+ "capped": "Zeigt die neuesten {shown} von {total}."
8847
+ },
8848
+ "card": {
8849
+ "waited": "wartete {duration}",
8850
+ "active": "vor {duration} aktiv",
8851
+ "merged": "vor {duration} gemergt",
8852
+ "step": "Schritt {current} von {total}",
8853
+ "showOnBoard": "Auf dem Board zeigen",
8854
+ "answer": "Antworten",
8855
+ "budgetPaused": "Das Ausgabenlimit hat diesen Durchlauf angehalten. Er läuft weiter, sobald das Limit erhöht wird.",
8856
+ "parked": "Der Durchlauf wartet auf einen Menschen. Öffne die Aufgabe, um zu sehen, was fehlt.",
8857
+ "waitingOn": "Wartet auf {deps}",
8858
+ "pr": "Pull Request #{number}"
8859
+ }
8860
+ },
8861
+ "views": {
8862
+ "title": "Ansichten",
8863
+ "queue": "Warteschlange",
8864
+ "board": "Board",
8865
+ "openQueue": "Warteschlangen-Ansicht öffnen"
8737
8866
  }
8738
8867
  }
@@ -180,7 +180,8 @@
180
180
  "reports": "Reports",
181
181
  "foundationalServices": "Foundational services",
182
182
  "tutorials": "Tutorials",
183
- "help": "Help"
183
+ "help": "Help",
184
+ "setupChecklist": "Setup checklist"
184
185
  },
185
186
  "board": {
186
187
  "toast": {
@@ -2800,7 +2801,10 @@
2800
2801
  "toggleUiMode": "Switch interface mode",
2801
2802
  "chooseRole": "Change your role",
2802
2803
  "foundationalServices": "Foundational services",
2803
- "notificationSettings": "Manage notification routing"
2804
+ "notificationSettings": "Manage notification routing",
2805
+ "setupChecklist": "Setup checklist",
2806
+ "queueView": "Open the queue view",
2807
+ "boardView": "Open the board view"
2804
2808
  },
2805
2809
  "keywords": {
2806
2810
  "newPipeline": "pipeline agents chain",
@@ -2828,7 +2832,10 @@
2828
2832
  "chooseRole": "role engineer product manager designer persona simpler view",
2829
2833
  "tutorial": "tutorial onboarding tour guide help learn basics",
2830
2834
  "foundationalServices": "shared capability platform service api contract openapi catalog",
2831
- "notificationSettings": "notifications email routing channels inbox"
2835
+ "notificationSettings": "notifications email routing channels inbox",
2836
+ "setupChecklist": "setup checklist runner model github storage environment configure",
2837
+ "queueView": "queue view needs you inbox list waiting",
2838
+ "boardView": "board canvas map view plan"
2832
2839
  }
2833
2840
  },
2834
2841
  "shortcuts": {
@@ -8434,6 +8441,10 @@
8434
8441
  "title": "The board",
8435
8442
  "body": "Services, modules, and tasks live on this canvas. Drag to pan, scroll to zoom, and click any card to inspect it."
8436
8443
  },
8444
+ "views": {
8445
+ "title": "Two views",
8446
+ "body": "The board has a second view. The queue lists what needs you across every service. Once the tour is over, switch between the queue and this canvas here. The app opens on the view you used last."
8447
+ },
8437
8448
  "sidebar": {
8438
8449
  "title": "The sidebar",
8439
8450
  "body": "Everything else lives here: building pipelines, connecting repositories and integrations, and workspace settings."
@@ -9065,5 +9076,123 @@
9065
9076
  "unsupportedVersion": "This theme was made with a newer editor format than this app understands."
9066
9077
  }
9067
9078
  }
9079
+ },
9080
+ "setup": {
9081
+ "title": "Setup",
9082
+ "progress": "{done} of {total} done",
9083
+ "intro": "What this workspace needs before a task can run and merge.",
9084
+ "required": "required",
9085
+ "optional": "optional",
9086
+ "action": {
9087
+ "change": "Change",
9088
+ "connect": "Set up",
9089
+ "fix": "Fix",
9090
+ "review": "Review",
9091
+ "retry": "Try again"
9092
+ },
9093
+ "rows": {
9094
+ "checking": "Checking…",
9095
+ "notNeeded": "This deployment does not use it.",
9096
+ "model": {
9097
+ "title": "Model",
9098
+ "done": "A model is available.",
9099
+ "missing": "No model is available. No agent can run until you connect a provider."
9100
+ },
9101
+ "sourceControl": {
9102
+ "title": "Source control",
9103
+ "done": "Connected. Agents can push branches and open pull requests.",
9104
+ "missing": "Not connected. Agents cannot open pull requests."
9105
+ },
9106
+ "agentExecutor": {
9107
+ "title": "Where agents run",
9108
+ "done": "A runner is configured.",
9109
+ "missing": "No runner is configured. Nothing can run until you connect one.",
9110
+ "notNeeded": "This deployment runs agents without a runner."
9111
+ },
9112
+ "ephemeralEnvironments": {
9113
+ "title": "Test environments",
9114
+ "done": "Configured. Testers can use a live preview.",
9115
+ "missing": "Not set up. Testers that need a live preview do not run. All other agents run."
9116
+ },
9117
+ "binaryStorage": {
9118
+ "title": "Screenshot storage",
9119
+ "done": "Configured. Visual checks are on.",
9120
+ "missing": "Not set up. Visual checks are off."
9121
+ }
9122
+ },
9123
+ "causes": {
9124
+ "unreachable": "Configured, but unreachable right now.",
9125
+ "incomplete": "Connected, but a required setting is missing.",
9126
+ "rejected": "GitHub rejected the access token.",
9127
+ "underscoped": "The access token cannot push or open pull requests.",
9128
+ "presetBroken": "The default model preset names a model that is not available.",
9129
+ "probeFailed": "The check did not answer.",
9130
+ "notReported": "This deployment does not report it."
9131
+ },
9132
+ "also": {
9133
+ "title": "Also here",
9134
+ "pipelines": "Pipelines",
9135
+ "riskPolicies": "Merge policies",
9136
+ "modelPresets": "Model presets",
9137
+ "counts": {
9138
+ "repair": "To repair: {count}",
9139
+ "outdated": "Outdated: {count}",
9140
+ "new": "New: {count}"
9141
+ },
9142
+ "settings": "Settings and connections",
9143
+ "workspaceSettings": "Workspace settings",
9144
+ "integrations": "Integrations"
9145
+ }
9146
+ },
9147
+ "queue": {
9148
+ "title": "Queue",
9149
+ "summary": "{needsYou} need you · {ready} ready to merge",
9150
+ "filter": {
9151
+ "allServices": "All services",
9152
+ "service": "Filter by service"
9153
+ },
9154
+ "columns": {
9155
+ "needsYou": {
9156
+ "label": "Needs you",
9157
+ "empty": "Nothing waits on you."
9158
+ },
9159
+ "inFlight": {
9160
+ "label": "In flight",
9161
+ "empty": "No agent is working now."
9162
+ },
9163
+ "readyToMerge": {
9164
+ "label": "Ready to merge",
9165
+ "empty": "No pull request waits to merge."
9166
+ }
9167
+ },
9168
+ "waiting": {
9169
+ "label": "Not started ({count})",
9170
+ "empty": "Nothing waits to start."
9171
+ },
9172
+ "done": {
9173
+ "count": "Merged since {date}: {count}",
9174
+ "countAll": "Merged: {count}",
9175
+ "show": "Show",
9176
+ "hide": "Hide",
9177
+ "capped": "Shows the newest {shown} of {total}."
9178
+ },
9179
+ "card": {
9180
+ "waited": "waited {duration}",
9181
+ "active": "active {duration} ago",
9182
+ "merged": "merged {duration} ago",
9183
+ "step": "step {current} of {total}",
9184
+ "showOnBoard": "Show on the board",
9185
+ "answer": "Answer",
9186
+ "budgetPaused": "The spend limit paused this run. It continues when the limit goes up.",
9187
+ "parked": "The run waits for a person. Open the task to see what it needs.",
9188
+ "waitingOn": "Waits for {deps}",
9189
+ "pr": "Pull request #{number}"
9190
+ }
9191
+ },
9192
+ "views": {
9193
+ "title": "Views",
9194
+ "queue": "Queue",
9195
+ "board": "Board",
9196
+ "openQueue": "Open the queue view"
9068
9197
  }
9069
9198
  }