@cat-factory/app 0.198.1 → 0.200.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.
- package/README.md +6 -1
- package/app/components/foundational/FoundationalContractSummary.vue +36 -0
- package/app/components/foundational/FoundationalServiceCatalogList.vue +170 -0
- package/app/components/foundational/FoundationalServiceManager.vue +111 -0
- package/app/components/foundational/FoundationalServicePanel.vue +37 -0
- package/app/components/foundational/FoundationalServiceRegistry.vue +339 -0
- package/app/components/foundational/FoundationalServiceSources.vue +398 -0
- package/app/components/foundational/FoundationalSuppressions.vue +75 -0
- package/app/components/layout/AccountFoundationalSettings.vue +25 -0
- package/app/components/layout/BoardToolbar.vue +1 -1
- package/app/components/layout/CommandBar.vue +8 -2
- package/app/components/layout/SideBar.vue +24 -3
- package/app/components/settings/AccountSettingsPanel.vue +17 -1
- package/app/components/settings/WorkspaceMetadataSettings.vue +151 -0
- package/app/components/settings/WorkspaceSettingsPanel.vue +27 -0
- package/app/composables/api/foundationalServices.ts +131 -0
- package/app/composables/useApi.ts +2 -0
- package/app/composables/useNavContributions.ts +92 -1
- package/app/composables/usePipelineErrorToast.ts +4 -0
- package/app/docs/consumer-extensions.md +76 -10
- package/app/modular/external-tools.spec.ts +281 -0
- package/app/modular/external-tools.ts +265 -0
- package/app/modular/nav-contributions.spec.ts +38 -14
- package/app/modular/nav-contributions.ts +58 -1
- package/app/modular/registry.ts +2 -0
- package/app/modular/slots.ts +15 -0
- package/app/modular/workspace-metadata.spec.ts +160 -0
- package/app/modular/workspace-metadata.ts +173 -0
- package/app/pages/index.vue +4 -0
- package/app/stores/foundationalServices.spec.ts +121 -0
- package/app/stores/foundationalServices.ts +276 -0
- package/app/stores/ui/modals.ts +12 -0
- package/app/stores/workspaceSettings.ts +3 -0
- package/app/types/domain.ts +2 -0
- package/app/types/foundationalServices.ts +32 -0
- package/i18n/locales/de.json +162 -6
- package/i18n/locales/en.json +162 -6
- package/i18n/locales/es.json +162 -6
- package/i18n/locales/fr.json +162 -6
- package/i18n/locales/he.json +162 -6
- package/i18n/locales/it.json +162 -6
- package/i18n/locales/ja.json +162 -6
- package/i18n/locales/pl.json +162 -6
- package/i18n/locales/tr.json +162 -6
- package/i18n/locales/uk.json +162 -6
- package/package.json +2 -2
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
import type {
|
|
4
|
+
ApiContractDocument,
|
|
5
|
+
CreateFoundationalServiceInput,
|
|
6
|
+
FoundationalService,
|
|
7
|
+
FoundationalServiceOwnerKind,
|
|
8
|
+
FoundationalServiceSource,
|
|
9
|
+
FoundationalServiceSuppression,
|
|
10
|
+
FoundationalServiceSyncResult,
|
|
11
|
+
LinkFoundationalServiceSourceInput,
|
|
12
|
+
ResolvedFoundationalService,
|
|
13
|
+
UpdateFoundationalServiceInput,
|
|
14
|
+
} from '~/types/domain'
|
|
15
|
+
import { useSingleFlightProbe } from '~/composables/useSingleFlightProbe'
|
|
16
|
+
import { useWorkspaceStore } from '~/stores/workspace'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The foundational-services catalog for one owner — a board (`workspace`) or an `account`
|
|
20
|
+
* (backend/docs/adr/0031-foundational-services.md). Holds that owner's own (raw) tier of registered
|
|
21
|
+
* services, its linked repo sources, and — at the **workspace** tier only — the merged catalog an
|
|
22
|
+
* Architect actually sees (account ⊕ workspace, workspace winning).
|
|
23
|
+
*
|
|
24
|
+
* Three things about this store follow the feature's design rather than the fragment library's:
|
|
25
|
+
*
|
|
26
|
+
* - **Contract documents are never held here.** The catalog reads carry a contract MANIFEST
|
|
27
|
+
* (id, format, size, operation names) and no bodies, because that is the whole reason a design
|
|
28
|
+
* prompt scales with the number of an org's services rather than the size of its specs. A body
|
|
29
|
+
* is fetched on demand, per service, by {@link contractsFor}, and cached only for the session.
|
|
30
|
+
* - **`suppress` / `restore` are workspace-only**, and they are not "delete". Suppression opts a
|
|
31
|
+
* board out of an INHERITED account service and destroys nothing; deleting removes the board's
|
|
32
|
+
* own registration and its uploaded documents.
|
|
33
|
+
* - **`sourcesAvailable` is the finer gate**, exactly as in the skill library: the catalog works
|
|
34
|
+
* without the GitHub integration (contracts can be uploaded directly), while the repo-source
|
|
35
|
+
* routes 503 without it.
|
|
36
|
+
*/
|
|
37
|
+
function foundationalServicesSetup(
|
|
38
|
+
kind: FoundationalServiceOwnerKind,
|
|
39
|
+
resolveOwnerId: () => string | null,
|
|
40
|
+
) {
|
|
41
|
+
const api = useApi()
|
|
42
|
+
|
|
43
|
+
/** The merged/resolved catalog only exists at the workspace tier. */
|
|
44
|
+
const hasResolved = kind === 'workspace'
|
|
45
|
+
|
|
46
|
+
/** null = not probed yet; true/false = the catalog is on/off for this deployment. */
|
|
47
|
+
const available = ref<boolean | null>(null)
|
|
48
|
+
/** false when the GitHub integration is off: the catalog works, repo sources do not. */
|
|
49
|
+
const sourcesAvailable = ref(true)
|
|
50
|
+
/** This owner's own registered services (its tier, raw). */
|
|
51
|
+
const services = ref<FoundationalService[]>([])
|
|
52
|
+
/** The merged catalog an Architect sees (workspace tier only; empty otherwise). */
|
|
53
|
+
const resolved = ref<ResolvedFoundationalService[]>([])
|
|
54
|
+
/**
|
|
55
|
+
* What this board is opted OUT of (workspace tier only; empty otherwise). Its own read because
|
|
56
|
+
* a suppressed id is by construction absent from {@link resolved} — without it, suppression
|
|
57
|
+
* would be a one-way door.
|
|
58
|
+
*/
|
|
59
|
+
const suppressions = ref<FoundationalServiceSuppression[]>([])
|
|
60
|
+
/** Linked repo sources for this owner. */
|
|
61
|
+
const sources = ref<FoundationalServiceSource[]>([])
|
|
62
|
+
/** Per-source "changes available" flag from the last status check. */
|
|
63
|
+
const sourceChanges = ref<Record<string, boolean>>({})
|
|
64
|
+
/**
|
|
65
|
+
* Session cache of fetched contract DOCUMENTS, keyed by service id. Populated only by an
|
|
66
|
+
* explicit {@link contractsFor}, so opening the surface never transfers a document body — the
|
|
67
|
+
* property the whole two-table split exists to guarantee.
|
|
68
|
+
*/
|
|
69
|
+
const contractBodies = ref<Record<string, ApiContractDocument[]>>({})
|
|
70
|
+
|
|
71
|
+
/** How many entries of the merged catalog this board inherits rather than owns. */
|
|
72
|
+
const inheritedCount = computed(
|
|
73
|
+
() => resolved.value.filter((entry) => entry.tier === 'account').length,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
function requireOwnerId(): string {
|
|
77
|
+
const id = resolveOwnerId()
|
|
78
|
+
if (!id) throw new Error('No foundational-services owner')
|
|
79
|
+
return id
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function requireWorkspaceId(): string {
|
|
83
|
+
if (!hasResolved) throw new Error('Foundational-service inheritance is workspace-scoped')
|
|
84
|
+
return requireOwnerId()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Probe the feature + load this owner's tier, sources and (ws) the merged catalog. */
|
|
88
|
+
async function runProbe() {
|
|
89
|
+
const id = resolveOwnerId()
|
|
90
|
+
if (!id) return
|
|
91
|
+
try {
|
|
92
|
+
const [tier, merged, opted] = await Promise.all([
|
|
93
|
+
api.listFoundationalServices(kind, id),
|
|
94
|
+
hasResolved
|
|
95
|
+
? api.getResolvedFoundationalServices(id)
|
|
96
|
+
: Promise.resolve([] as ResolvedFoundationalService[]),
|
|
97
|
+
hasResolved
|
|
98
|
+
? api.listFoundationalServiceSuppressions(id)
|
|
99
|
+
: Promise.resolve([] as FoundationalServiceSuppression[]),
|
|
100
|
+
])
|
|
101
|
+
services.value = tier
|
|
102
|
+
resolved.value = merged
|
|
103
|
+
suppressions.value = opted
|
|
104
|
+
available.value = true
|
|
105
|
+
} catch {
|
|
106
|
+
// Reset EVERY view, `sourcesAvailable` included. Leaving it at its previous value would
|
|
107
|
+
// let a re-probe of an owner whose catalog is now unreachable keep claiming the repo-source
|
|
108
|
+
// half is wired, which is the one flag here that gates an affordance rather than content.
|
|
109
|
+
available.value = false
|
|
110
|
+
services.value = []
|
|
111
|
+
resolved.value = []
|
|
112
|
+
suppressions.value = []
|
|
113
|
+
sources.value = []
|
|
114
|
+
sourceChanges.value = {}
|
|
115
|
+
sourcesAvailable.value = false
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
// Repo sources need the GitHub integration; a 503 here hides only the linking UI — the
|
|
119
|
+
// catalog read above already succeeded, so the feature itself is on.
|
|
120
|
+
try {
|
|
121
|
+
sources.value = await api.listFoundationalSources(kind, id)
|
|
122
|
+
sourcesAvailable.value = true
|
|
123
|
+
} catch {
|
|
124
|
+
sources.value = []
|
|
125
|
+
sourcesAvailable.value = false
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Single-flight the probe keyed on the owner id, so a panel-open fan-out loads once per owner.
|
|
129
|
+
const { probe, ensureProbed } = useSingleFlightProbe(runProbe, () => resolveOwnerId())
|
|
130
|
+
|
|
131
|
+
async function reloadTier() {
|
|
132
|
+
services.value = await api.listFoundationalServices(kind, requireOwnerId())
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function refreshResolved() {
|
|
136
|
+
if (!hasResolved) return
|
|
137
|
+
const id = requireOwnerId()
|
|
138
|
+
// Both in one pass: a write that changes the merge routinely changes the opt-out list too
|
|
139
|
+
// (suppressing removes an entry from one and adds it to the other), and refreshing only the
|
|
140
|
+
// catalog would leave the way BACK stale — the exact state the pair exists to avoid.
|
|
141
|
+
const [merged, opted] = await Promise.all([
|
|
142
|
+
api.getResolvedFoundationalServices(id),
|
|
143
|
+
api.listFoundationalServiceSuppressions(id),
|
|
144
|
+
])
|
|
145
|
+
resolved.value = merged
|
|
146
|
+
suppressions.value = opted
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Every write invalidates both views: a tier edit changes what the merge resolves to. */
|
|
150
|
+
async function reload() {
|
|
151
|
+
await Promise.all([reloadTier(), refreshResolved()])
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function create(input: CreateFoundationalServiceInput) {
|
|
155
|
+
await api.createFoundationalService(kind, requireOwnerId(), input)
|
|
156
|
+
await reload()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function update(serviceId: string, patch: UpdateFoundationalServiceInput) {
|
|
160
|
+
await api.updateFoundationalService(kind, requireOwnerId(), serviceId, patch)
|
|
161
|
+
// A contract replacement changes the stored bodies, so drop the cached copy rather than
|
|
162
|
+
// letting a stale document be shown as what a consumer would receive.
|
|
163
|
+
delete contractBodies.value[serviceId]
|
|
164
|
+
await reload()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Remove this tier's OWN registration (and its uploaded documents). */
|
|
168
|
+
async function remove(serviceId: string) {
|
|
169
|
+
await api.deleteFoundationalService(kind, requireOwnerId(), serviceId)
|
|
170
|
+
delete contractBodies.value[serviceId]
|
|
171
|
+
await reload()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Opt this board out of an inherited ACCOUNT service. Destroys nothing; reversible. */
|
|
175
|
+
async function suppress(serviceId: string) {
|
|
176
|
+
await api.suppressFoundationalService(requireWorkspaceId(), serviceId)
|
|
177
|
+
await reload()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Lift a suppression, so the board inherits the account service again. */
|
|
181
|
+
async function restore(serviceId: string) {
|
|
182
|
+
await api.restoreFoundationalService(requireWorkspaceId(), serviceId)
|
|
183
|
+
await reload()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Fetch (and cache for the session) one service's full contract documents — the same lazy read
|
|
188
|
+
* a consumer dispatch makes, so what a human inspects here is what an agent would be handed.
|
|
189
|
+
*/
|
|
190
|
+
async function contractsFor(serviceId: string): Promise<ApiContractDocument[]> {
|
|
191
|
+
const cached = contractBodies.value[serviceId]
|
|
192
|
+
if (cached) return cached
|
|
193
|
+
const documents = await api.getFoundationalServiceContracts(requireWorkspaceId(), serviceId)
|
|
194
|
+
contractBodies.value = { ...contractBodies.value, [serviceId]: documents }
|
|
195
|
+
return documents
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function reloadSources() {
|
|
199
|
+
sources.value = await api.listFoundationalSources(kind, requireOwnerId())
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function linkSource(input: LinkFoundationalServiceSourceInput) {
|
|
203
|
+
const source = await api.linkFoundationalSource(kind, requireOwnerId(), input)
|
|
204
|
+
sources.value = [source, ...sources.value]
|
|
205
|
+
// Sync immediately so the linked repo's services land in the catalog rather than waiting for
|
|
206
|
+
// the autorefresh sweep — a freshly linked source that shows nothing reads as a broken link.
|
|
207
|
+
await syncSource(source.id)
|
|
208
|
+
return source
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function unlinkSource(sourceId: string) {
|
|
212
|
+
await api.unlinkFoundationalSource(kind, requireOwnerId(), sourceId)
|
|
213
|
+
sources.value = sources.value.filter((s) => s.id !== sourceId)
|
|
214
|
+
delete sourceChanges.value[sourceId]
|
|
215
|
+
await reload()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Resync a source's definitions into the catalog, then refresh both views. */
|
|
219
|
+
async function syncSource(sourceId: string): Promise<FoundationalServiceSyncResult> {
|
|
220
|
+
const result = await api.syncFoundationalSource(kind, requireOwnerId(), sourceId)
|
|
221
|
+
delete sourceChanges.value[sourceId]
|
|
222
|
+
await Promise.all([reloadSources(), reload()])
|
|
223
|
+
return result
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** The cheap commit-version "check for changes" for a source; caches the flag. */
|
|
227
|
+
async function checkSource(sourceId: string) {
|
|
228
|
+
const status = await api.foundationalSourceStatus(kind, requireOwnerId(), sourceId)
|
|
229
|
+
sourceChanges.value = { ...sourceChanges.value, [sourceId]: status.changed }
|
|
230
|
+
return status
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
kind,
|
|
235
|
+
hasResolved,
|
|
236
|
+
available,
|
|
237
|
+
sourcesAvailable,
|
|
238
|
+
services,
|
|
239
|
+
resolved,
|
|
240
|
+
suppressions,
|
|
241
|
+
sources,
|
|
242
|
+
sourceChanges,
|
|
243
|
+
contractBodies,
|
|
244
|
+
inheritedCount,
|
|
245
|
+
probe,
|
|
246
|
+
ensureProbed,
|
|
247
|
+
create,
|
|
248
|
+
update,
|
|
249
|
+
remove,
|
|
250
|
+
suppress,
|
|
251
|
+
restore,
|
|
252
|
+
contractsFor,
|
|
253
|
+
linkSource,
|
|
254
|
+
unlinkSource,
|
|
255
|
+
syncSource,
|
|
256
|
+
checkSource,
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The workspace-tier catalog for the **active** board — a singleton that resolves the owner
|
|
262
|
+
* lazily, so it follows board switches and is shared by the navbar and the board modal.
|
|
263
|
+
*/
|
|
264
|
+
export const useFoundationalServicesStore = defineStore('foundationalServices', () =>
|
|
265
|
+
foundationalServicesSetup('workspace', () => useWorkspaceStore().workspaceId),
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* An owner-keyed catalog store, used for the **account** tier (and reusable for any explicit
|
|
270
|
+
* owner). Keyed by `(kind, ownerId)` so each account gets isolated state.
|
|
271
|
+
*/
|
|
272
|
+
export function useFoundationalServices(kind: FoundationalServiceOwnerKind, ownerId: string) {
|
|
273
|
+
return defineStore(`foundationalServices:${kind}:${ownerId}`, () =>
|
|
274
|
+
foundationalServicesSetup(kind, () => ownerId),
|
|
275
|
+
)()
|
|
276
|
+
}
|
package/app/stores/ui/modals.ts
CHANGED
|
@@ -344,6 +344,9 @@ function createOverlayModals() {
|
|
|
344
344
|
// Prompt-fragment library panel (manage the board's best-practice catalog +
|
|
345
345
|
// linked guideline repos; ADR 0006).
|
|
346
346
|
const fragmentLibraryOpen = ref(false)
|
|
347
|
+
// Foundational-services panel (register the shared capabilities the org already runs, and see
|
|
348
|
+
// the merged catalog an Architect designs against; backend/docs/adr/0031-foundational-services.md).
|
|
349
|
+
const foundationalServicesOpen = ref(false)
|
|
347
350
|
// Command bar (⌘K) — searchable launcher for every navbar action.
|
|
348
351
|
const commandBarOpen = ref(false)
|
|
349
352
|
// Keyboard-shortcuts cheatsheet (?) — a modal listing every global shortcut.
|
|
@@ -373,6 +376,12 @@ function createOverlayModals() {
|
|
|
373
376
|
function closeFragmentLibrary() {
|
|
374
377
|
fragmentLibraryOpen.value = false
|
|
375
378
|
}
|
|
379
|
+
function openFoundationalServices() {
|
|
380
|
+
foundationalServicesOpen.value = true
|
|
381
|
+
}
|
|
382
|
+
function closeFoundationalServices() {
|
|
383
|
+
foundationalServicesOpen.value = false
|
|
384
|
+
}
|
|
376
385
|
function openCommandBar() {
|
|
377
386
|
commandBarOpen.value = true
|
|
378
387
|
}
|
|
@@ -411,6 +420,7 @@ function createOverlayModals() {
|
|
|
411
420
|
bootstrapOpen,
|
|
412
421
|
addServiceOpen,
|
|
413
422
|
fragmentLibraryOpen,
|
|
423
|
+
foundationalServicesOpen,
|
|
414
424
|
commandBarOpen,
|
|
415
425
|
shortcutsHelpOpen,
|
|
416
426
|
mobileNavOpen,
|
|
@@ -421,6 +431,8 @@ function createOverlayModals() {
|
|
|
421
431
|
closeAddService,
|
|
422
432
|
openFragmentLibrary,
|
|
423
433
|
closeFragmentLibrary,
|
|
434
|
+
openFoundationalServices,
|
|
435
|
+
closeFoundationalServices,
|
|
424
436
|
openCommandBar,
|
|
425
437
|
closeCommandBar,
|
|
426
438
|
toggleCommandBar,
|
|
@@ -25,6 +25,9 @@ const DEFAULTS: WorkspaceSettings = {
|
|
|
25
25
|
// banner on every board before the snapshot even lands.
|
|
26
26
|
defaultProvisionType: null,
|
|
27
27
|
defaultProvisionManifestId: null,
|
|
28
|
+
// The custom metadata bag: empty until someone fills a declared field in. Never null — an
|
|
29
|
+
// external-tool resolver indexes it (`ctx.metadata.gameId`) with no guard.
|
|
30
|
+
metadata: {},
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/**
|
package/app/types/domain.ts
CHANGED
|
@@ -82,6 +82,7 @@ export type {
|
|
|
82
82
|
TaskLimitMode,
|
|
83
83
|
ReviewFrictionMode,
|
|
84
84
|
WorkspaceSettings,
|
|
85
|
+
WorkspaceMetadata,
|
|
85
86
|
UpdateWorkspaceSettingsInput,
|
|
86
87
|
UserSettings,
|
|
87
88
|
UpdateUserSettingsInput,
|
|
@@ -176,6 +177,7 @@ export type * from './execution'
|
|
|
176
177
|
export type * from './models'
|
|
177
178
|
export type * from './fragments'
|
|
178
179
|
export type * from './skills'
|
|
180
|
+
export type * from './foundationalServices'
|
|
179
181
|
export type * from './documents'
|
|
180
182
|
export type * from './tasks'
|
|
181
183
|
export type * from './bugHunt'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Foundational services (backend/docs/adr/0031-foundational-services.md). Mirrors the
|
|
3
|
+
// `@cat-factory/contracts` schemas: the tiered catalog of shared capabilities an
|
|
4
|
+
// organisation already runs (file storage, notifications, audit …), each with its
|
|
5
|
+
// API contracts, plus the repo sources that feed it.
|
|
6
|
+
//
|
|
7
|
+
// Note `ApiContractSummary` (no body) and `ApiContractDocument` (with body) are two
|
|
8
|
+
// separate types on purpose — the catalog read never carries a document, and the
|
|
9
|
+
// management surface reads one only when a human opens it.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
//
|
|
12
|
+
// All wire shapes are sourced from @cat-factory/contracts (single source of truth).
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
ApiContractDocument,
|
|
16
|
+
ApiContractFormat,
|
|
17
|
+
ApiContractSummary,
|
|
18
|
+
CreateFoundationalServiceInput,
|
|
19
|
+
FoundationalService,
|
|
20
|
+
FoundationalServiceOwnerKind,
|
|
21
|
+
FoundationalServiceSelection,
|
|
22
|
+
FoundationalServiceSource,
|
|
23
|
+
FoundationalServiceSourceMode,
|
|
24
|
+
FoundationalServiceSourceStatus,
|
|
25
|
+
FoundationalServiceSuppression,
|
|
26
|
+
FoundationalServiceSyncResult,
|
|
27
|
+
FoundationalServiceTier,
|
|
28
|
+
LinkFoundationalServiceSourceInput,
|
|
29
|
+
ResolvedFoundationalService,
|
|
30
|
+
UpdateFoundationalServiceInput,
|
|
31
|
+
UploadApiContract,
|
|
32
|
+
} from '@cat-factory/contracts'
|
package/i18n/locales/de.json
CHANGED
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"tabs": {
|
|
52
52
|
"team": "Team & Zugriff",
|
|
53
53
|
"fragments": "Kontextfragmente",
|
|
54
|
-
"skills": "Skills"
|
|
54
|
+
"skills": "Skills",
|
|
55
|
+
"foundational": "Basisdienste"
|
|
55
56
|
}
|
|
56
57
|
},
|
|
57
58
|
"infrastructure": {
|
|
@@ -781,6 +782,7 @@
|
|
|
781
782
|
"merge": "Risikorichtlinien",
|
|
782
783
|
"tracker": "Issue-Tracker",
|
|
783
784
|
"fragments": "Dienst-Best-Practices",
|
|
785
|
+
"metadata": "Metadaten",
|
|
784
786
|
"members": "Mitglieder"
|
|
785
787
|
},
|
|
786
788
|
"waiting": {
|
|
@@ -846,6 +848,12 @@
|
|
|
846
848
|
"body": "Nach Abschluss jeder Ausführung bewertet der Kaizen-Agent, wie jeder Agentenschritt verlief, von reibungslos und effizient bis verwirrt und chaotisch, und empfiehlt Prompt-/Modellverbesserungen. Eine Kombination aus Prompt, Agent und Modell, die fünfmal in Folge hoch bewertet wird und keine Empfehlungen erhält, wird als verifiziert markiert und nicht mehr bewertet. Die Bewertung läuft im Hintergrund und wird in den Ausführungsdetails und im Kaizen-Bildschirm angezeigt. Lege das Modell des Bewerters in der Modellkonfiguration fest (der \"Kaizen\"-Agent).",
|
|
847
849
|
"toggle": "Agenten-Ausführungen mit Kaizen bewerten"
|
|
848
850
|
},
|
|
851
|
+
"metadata": {
|
|
852
|
+
"heading": "Arbeitsbereich-Metadaten",
|
|
853
|
+
"body": "Werte für die benutzerdefinierten Felder dieser Installation. Externe Tools lesen sie und öffnen direkt das richtige Projekt für diesen Arbeitsbereich.",
|
|
854
|
+
"empty": "Diese Installation definiert keine benutzerdefinierten Arbeitsbereichsfelder.",
|
|
855
|
+
"unset": "Nicht gesetzt"
|
|
856
|
+
},
|
|
849
857
|
"budget": {
|
|
850
858
|
"heading": "Monatliches Ausgabenbudget",
|
|
851
859
|
"body": "Der Token-Verbrauch wird pro LLM-Aufruf gemessen, bepreist und durch diese Budgets begrenzt. Eine Ausführung pausiert, wenn eine Stufe, zu der sie gehört, ausgeschöpft ist. Lasse ein Feld leer für kein Limit auf dieser Stufe (die Workspace-Stufe übernimmt dann den integrierten Standard, etwa 100 EUR/Monat).",
|
|
@@ -2107,6 +2115,7 @@
|
|
|
2107
2115
|
"create": "Erstellen",
|
|
2108
2116
|
"repositories": "Repositories",
|
|
2109
2117
|
"integrations": "Integrationen",
|
|
2118
|
+
"externalTools": "Externe Tools",
|
|
2110
2119
|
"workspace": "Workspace",
|
|
2111
2120
|
"account": "Konto"
|
|
2112
2121
|
},
|
|
@@ -2133,7 +2142,8 @@
|
|
|
2133
2142
|
"shortcuts": "Tastenkürzel",
|
|
2134
2143
|
"bugHunt": "Fehlerjagd",
|
|
2135
2144
|
"toggleUiMode": "Oberflächenmodus wechseln",
|
|
2136
|
-
"tutorial": "Tour starten"
|
|
2145
|
+
"tutorial": "Tour starten",
|
|
2146
|
+
"foundationalServices": "Basisdienste"
|
|
2137
2147
|
},
|
|
2138
2148
|
"keywords": {
|
|
2139
2149
|
"newPipeline": "pipeline agents chain",
|
|
@@ -2156,7 +2166,8 @@
|
|
|
2156
2166
|
"shortcuts": "keyboard shortcuts keys hotkeys cheatsheet help",
|
|
2157
2167
|
"bugHunt": "fehler bug jagd triage backlog tracker nicht zugewiesen",
|
|
2158
2168
|
"toggleUiMode": "oberfläche modus einfach erweitert anzeigen ausblenden",
|
|
2159
|
-
"tutorial": "tutorial tour einführung hilfe onboarding lernen grundlagen"
|
|
2169
|
+
"tutorial": "tutorial tour einführung hilfe onboarding lernen grundlagen",
|
|
2170
|
+
"foundationalServices": "gemeinsame Fähigkeit Plattform Dienst API Vertrag OpenAPI Katalog"
|
|
2160
2171
|
}
|
|
2161
2172
|
},
|
|
2162
2173
|
"shortcuts": {
|
|
@@ -2316,6 +2327,9 @@
|
|
|
2316
2327
|
"title": "Standard-Testumgebung wählen",
|
|
2317
2328
|
"body": "Für dieses Board ist noch nicht festgelegt, wie seine Services eine Testumgebung erhalten. Wählen Sie einen Standard, dann startet jeder künftig hinzugefügte Service damit, statt einzeln eingerichtet zu werden. Pro Service lässt sich das weiterhin ändern.",
|
|
2318
2329
|
"action": "Standard wählen"
|
|
2330
|
+
},
|
|
2331
|
+
"accountFoundational": {
|
|
2332
|
+
"intro": "Die gemeinsamen Fähigkeiten, die diese Organisation bereits betreibt - Dateiablage, Benachrichtigungen, Audit - samt ihren API-Verträgen. Jedes Board erbt sie, und einem Architekten wird gesagt, sie zu nutzen statt einen Neubau vorzuschlagen."
|
|
2319
2333
|
}
|
|
2320
2334
|
},
|
|
2321
2335
|
"board": {
|
|
@@ -4203,6 +4217,135 @@
|
|
|
4203
4217
|
},
|
|
4204
4218
|
"unavailable": "Die Prompt-Fragment-Bibliothek ist für dieses Deployment nicht aktiviert."
|
|
4205
4219
|
},
|
|
4220
|
+
"foundational": {
|
|
4221
|
+
"unavailable": "Der Katalog der Basisdienste ist für diese Installation nicht aktiviert.",
|
|
4222
|
+
"owner": {
|
|
4223
|
+
"workspace": "Dieses Board",
|
|
4224
|
+
"account": "Dieses Konto"
|
|
4225
|
+
},
|
|
4226
|
+
"tab": {
|
|
4227
|
+
"catalog": "Katalog",
|
|
4228
|
+
"sources": "Repo-Quellen"
|
|
4229
|
+
},
|
|
4230
|
+
"panel": {
|
|
4231
|
+
"title": "Basisdienste",
|
|
4232
|
+
"subtitle": "Die gemeinsamen Fähigkeiten, die eure Organisation bereits betreibt, damit ein Entwurf sie nutzt statt sie neu zu bauen."
|
|
4233
|
+
},
|
|
4234
|
+
"tier": {
|
|
4235
|
+
"account": "Konto",
|
|
4236
|
+
"workspace": "Board"
|
|
4237
|
+
},
|
|
4238
|
+
"format": {
|
|
4239
|
+
"openapi": "OpenAPI",
|
|
4240
|
+
"toadContract": "toad-contracts",
|
|
4241
|
+
"lokaliseApiContract": "lokalise/api-contract"
|
|
4242
|
+
},
|
|
4243
|
+
"contracts": {
|
|
4244
|
+
"omitted": "+{count} weitere nicht aufgeführt",
|
|
4245
|
+
"none": "Kein API-Vertrag hinterlegt. Einem Agenten wird gesagt, dass die Schnittstelle unbekannt ist, statt dass er sie errät."
|
|
4246
|
+
},
|
|
4247
|
+
"catalog": {
|
|
4248
|
+
"intro": "Was ein Architekt auf diesem Board erhält: Identität, Fähigkeits-Tags und Operationsnamen. Vertragsdokumente werden erst gelesen, wenn ein Entwurf den Dienst benennt.",
|
|
4249
|
+
"empty": "Noch keine Basisdienste. Registriere unten einen oder verknüpfe ein Repo, das sie beschreibt.",
|
|
4250
|
+
"suppress": "Diesen Dienst auf diesem Board nicht anbieten",
|
|
4251
|
+
"showDocuments": "Vertragsdokumente anzeigen",
|
|
4252
|
+
"hideDocuments": "Vertragsdokumente ausblenden"
|
|
4253
|
+
},
|
|
4254
|
+
"suppressions": {
|
|
4255
|
+
"title": "Auf diesem Board abgewählt",
|
|
4256
|
+
"intro": "Diese Kontodienste sind für Entwürfe auf diesem Board ausgeblendet. Nichts wurde gelöscht, und das Konto behält sie für alle anderen Boards.",
|
|
4257
|
+
"restore": "Wieder anbieten",
|
|
4258
|
+
"shadowsNothing": "Unter dieser ID wird derzeit nichts geerbt, diese Abwahl blendet also aktuell nichts aus."
|
|
4259
|
+
},
|
|
4260
|
+
"registry": {
|
|
4261
|
+
"empty": "In diesem Bereich ist noch nichts registriert.",
|
|
4262
|
+
"add": "Dienst registrieren",
|
|
4263
|
+
"addTitle": "Basisdienst registrieren",
|
|
4264
|
+
"editTitle": "Basisdienst bearbeiten",
|
|
4265
|
+
"edit": "Bearbeiten",
|
|
4266
|
+
"delete": "Löschen",
|
|
4267
|
+
"save": "Speichern",
|
|
4268
|
+
"cancel": "Abbrechen",
|
|
4269
|
+
"fromSource": "Aus einem verknüpften Repo synchronisiert ({path}). Bearbeite ihn im Repo; die nächste Synchronisierung überschreibt Änderungen von hier.",
|
|
4270
|
+
"idFixed": "die ID, die ein Architekt in seinem Entwurf schreibt - nach der Registrierung unveränderlich",
|
|
4271
|
+
"idPlaceholder": "ID (Kleinbuchstaben mit Bindestrich, z. B. file-storage)",
|
|
4272
|
+
"namePlaceholder": "Name (z. B. File Storage)",
|
|
4273
|
+
"summaryPlaceholder": "einzeilige Zusammenfassung - wofür er da ist",
|
|
4274
|
+
"descriptionPlaceholder": "was er tut, wann er zu nutzen ist und was er NICHT abdeckt",
|
|
4275
|
+
"capabilitiesPlaceholder": "Fähigkeits-Tags, durch Komma getrennt (z. B. file-storage, cdn)",
|
|
4276
|
+
"contractsTitle": "API-Verträge",
|
|
4277
|
+
"contractsKeep": "Unverändert lassen, um die gespeicherten Dokumente zu behalten.",
|
|
4278
|
+
"contractsReplace": "Beim Speichern wird der gesamte gespeicherte Satz durch das Hier-Aufgeführte ERSETZT.",
|
|
4279
|
+
"addContract": "Vertrag hinzufügen",
|
|
4280
|
+
"removeContract": "Diesen Vertrag entfernen",
|
|
4281
|
+
"contractIdPlaceholder": "Vertrags-ID (Kleinbuchstaben mit Bindestrich, z. B. openapi)",
|
|
4282
|
+
"contractTitlePlaceholder": "Titel (z. B. HTTP API)",
|
|
4283
|
+
"contractBodyPlaceholder": "Dokument einfügen: eine OpenAPI-3.x-Datei oder der Quelltext eines Vertragsmoduls"
|
|
4284
|
+
},
|
|
4285
|
+
"sources": {
|
|
4286
|
+
"empty": "Keine verknüpften Repos. Verknüpfe unten eines, um Dienstdefinitionen und ihre Vertragsdateien zu synchronisieren.",
|
|
4287
|
+
"linkTitle": "Repo-Quelle verknüpfen",
|
|
4288
|
+
"link": "Verknüpfen & synchronisieren",
|
|
4289
|
+
"metaSynced": "synchronisiert {date} · Ref {ref}",
|
|
4290
|
+
"metaNever": "nie synchronisiert · Ref {ref}",
|
|
4291
|
+
"metaFiles": "{service} · {count} Vertragsdateien",
|
|
4292
|
+
"metaDirectory": "ein Dienst je Unterverzeichnis",
|
|
4293
|
+
"changes": "Änderungen",
|
|
4294
|
+
"check": "Auf Änderungen prüfen",
|
|
4295
|
+
"sync": "Erneut synchronisieren",
|
|
4296
|
+
"unlink": "Verknüpfung lösen",
|
|
4297
|
+
"selectedDir": "Verzeichnis:",
|
|
4298
|
+
"selectedFiles": "Ausgewählte Dateien: {count}",
|
|
4299
|
+
"wholeRepo": "Gesamtes Repository (Wurzel).",
|
|
4300
|
+
"ownerPlaceholder": "Owner",
|
|
4301
|
+
"repoPlaceholder": "Repo",
|
|
4302
|
+
"dirPlaceholder": "Verzeichnispfad (z. B. foundational)",
|
|
4303
|
+
"filePathsPlaceholder": "Pfade der Vertragsdateien, einer pro Zeile",
|
|
4304
|
+
"refPlaceholder": "Ref (Standard HEAD)",
|
|
4305
|
+
"githubRequired": "Zum Verknüpfen eines Repos wird die Versionsverwaltungs-Integration benötigt. Verbinde sie zuerst auf einem Board.",
|
|
4306
|
+
"serviceIdPlaceholder": "Dienst-ID (Kleinbuchstaben mit Bindestrich)",
|
|
4307
|
+
"serviceNamePlaceholder": "Dienstname",
|
|
4308
|
+
"serviceSummaryPlaceholder": "einzeilige Zusammenfassung (optional)",
|
|
4309
|
+
"mode": {
|
|
4310
|
+
"directory": "Ein Ordner mit Diensten",
|
|
4311
|
+
"files": "Bestimmte Dateien, ein Dienst",
|
|
4312
|
+
"directoryHint": "Jedes Unterverzeichnis des verknüpften Pfads ist ein Dienst, beschrieben durch eine service.md mit den Vertragsdateien daneben.",
|
|
4313
|
+
"filesHint": "Die aufgeführten Dateien beschreiben alle den einen Dienst, den du hier benennst. Nutze das, wenn es keine Ordnerkonvention gibt."
|
|
4314
|
+
}
|
|
4315
|
+
},
|
|
4316
|
+
"confirmUnlinkSource": {
|
|
4317
|
+
"title": "Verknüpfung zu diesem Repo lösen?",
|
|
4318
|
+
"body": "\"{repo}\" und die daraus synchronisierten Dienste werden aus dem Katalog entfernt. Du kannst es später erneut verknüpfen.",
|
|
4319
|
+
"confirm": "Verknüpfung lösen"
|
|
4320
|
+
},
|
|
4321
|
+
"confirmDelete": {
|
|
4322
|
+
"title": "Diesen Dienst löschen?",
|
|
4323
|
+
"body": "\"{name}\" und die hochgeladenen Vertragsdokumente werden aus diesem Bereich entfernt.",
|
|
4324
|
+
"bodyWorkspace": "\"{name}\" und die hochgeladenen Vertragsdokumente werden von diesem Board entfernt. Falls das Konto einen Dienst unter derselben ID führt, erbt dieses Board ihn ebenfalls nicht mehr; rückgängig machen kannst du das unter \"Auf diesem Board abgewählt\".",
|
|
4325
|
+
"confirm": "Löschen"
|
|
4326
|
+
},
|
|
4327
|
+
"toast": {
|
|
4328
|
+
"created": "Dienst registriert",
|
|
4329
|
+
"updated": "Dienst aktualisiert",
|
|
4330
|
+
"deleted": "Dienst gelöscht",
|
|
4331
|
+
"saveFailed": "Dienst konnte nicht gespeichert werden",
|
|
4332
|
+
"deleteFailed": "Dienst konnte nicht gelöscht werden",
|
|
4333
|
+
"suppressed": "Für Entwürfe auf diesem Board ausgeblendet",
|
|
4334
|
+
"suppressFailed": "Dienst konnte nicht ausgeblendet werden",
|
|
4335
|
+
"restored": "Auf diesem Board wieder angeboten",
|
|
4336
|
+
"restoreFailed": "Dienst konnte nicht wiederhergestellt werden",
|
|
4337
|
+
"contractsFailed": "Vertragsdokumente konnten nicht geladen werden",
|
|
4338
|
+
"sourceLinked": "Repo verknüpft & synchronisiert",
|
|
4339
|
+
"linkSourceFailed": "Repo konnte nicht verknüpft werden",
|
|
4340
|
+
"synced": "Synchronisiert: {updated} aktualisiert, {removed} entfernt",
|
|
4341
|
+
"syncFailed": "Repo konnte nicht synchronisiert werden",
|
|
4342
|
+
"changesAvailable": "Stromaufwärts liegen Änderungen vor",
|
|
4343
|
+
"upToDate": "Bereits aktuell",
|
|
4344
|
+
"checkSourceFailed": "Repo konnte nicht geprüft werden",
|
|
4345
|
+
"sourceUnlinked": "Repo-Verknüpfung gelöst",
|
|
4346
|
+
"unlinkSourceFailed": "Repo-Verknüpfung konnte nicht gelöst werden"
|
|
4347
|
+
}
|
|
4348
|
+
},
|
|
4206
4349
|
"brainstorm": {
|
|
4207
4350
|
"title": {
|
|
4208
4351
|
"architecture": "Architektur-Brainstorm",
|
|
@@ -4635,12 +4778,14 @@
|
|
|
4635
4778
|
"kaizen": "Kaizen",
|
|
4636
4779
|
"workspaceContext": "Workspace-Kontext",
|
|
4637
4780
|
"contextFragments": "Kontextfragmente",
|
|
4781
|
+
"externalTools": "Externe Tools",
|
|
4638
4782
|
"configuration": "Konfiguration",
|
|
4639
4783
|
"workspaceSettings": "Workspace-Einstellungen",
|
|
4640
4784
|
"modelConfiguration": "Modellkonfiguration",
|
|
4641
4785
|
"accountSettings": "Kontoeinstellungen",
|
|
4642
4786
|
"operatorDashboard": "Plattform-Observability",
|
|
4643
|
-
"reports": "Berichte"
|
|
4787
|
+
"reports": "Berichte",
|
|
4788
|
+
"foundationalServices": "Basisdienste"
|
|
4644
4789
|
},
|
|
4645
4790
|
"errors": {
|
|
4646
4791
|
"generic": {
|
|
@@ -4709,7 +4854,8 @@
|
|
|
4709
4854
|
"pipeline_schedule_attached": "Wiederkehrender Zeitplan nutzt diese Pipeline",
|
|
4710
4855
|
"pipeline_schedule_requires_recurring": "Wiederkehrender Zeitplan braucht diese Pipeline",
|
|
4711
4856
|
"pipeline_schedule_intake_unconfigured": "Zeitplan ohne Ticket-Erfassung",
|
|
4712
|
-
"foundational_service_exists": "Basisdienst existiert bereits"
|
|
4857
|
+
"foundational_service_exists": "Basisdienst existiert bereits",
|
|
4858
|
+
"foundational_service_not_inherited": "Dieses Board hat den Dienst registriert"
|
|
4713
4859
|
},
|
|
4714
4860
|
"description": {
|
|
4715
4861
|
"dependencies_unmet": "Diese Aufgabe hängt von anderen ab, die noch nicht abgeschlossen sind. Schließe sie ab oder gib sie frei und starte dann erneut.",
|
|
@@ -4738,7 +4884,8 @@
|
|
|
4738
4884
|
"pipeline_schedule_attached": "Ein wiederkehrender Zeitplan verweist noch auf diese Pipeline, und jeder von ihm gestartete Lauf löst die Pipeline über ihre ID auf. Lösen oder löschen Sie zuerst diesen Zeitplan und entfernen Sie danach die Pipeline.",
|
|
4739
4885
|
"pipeline_schedule_requires_recurring": "Ein wiederkehrender Zeitplan verweist noch auf diese Pipeline. Sie nur einmalig zu machen würde jeden künftigen Lauf unterbrechen. Lösen Sie zuerst diesen Zeitplan.",
|
|
4740
4886
|
"pipeline_schedule_intake_unconfigured": "Ein Bug-Intake-Schritt bezieht seine Arbeit aus der Ticket-Erfassung des Zeitplans, und der verknüpfte Zeitplan hat keine. Konfigurieren Sie zuerst die Ticket-Erfassung im Zeitplan.",
|
|
4741
|
-
"foundational_service_exists": "Ein Basisdienst mit dieser ID ist in diesem Bereich bereits registriert. Öffnen Sie den vorhandenen Eintrag und bearbeiten Sie ihn — zwei Dienste können sich keine ID teilen, denn die ID ist der Name, den ein Architekt in seinem Entwurf verwendet."
|
|
4887
|
+
"foundational_service_exists": "Ein Basisdienst mit dieser ID ist in diesem Bereich bereits registriert. Öffnen Sie den vorhandenen Eintrag und bearbeiten Sie ihn — zwei Dienste können sich keine ID teilen, denn die ID ist der Name, den ein Architekt in seinem Entwurf verwendet.",
|
|
4888
|
+
"foundational_service_not_inherited": "Abwählen gilt für einen vom Konto geerbten Dienst. Diese ID ist von diesem Board registriert, es gibt also nichts abzuwählen - lösche stattdessen den eigenen Eintrag des Boards."
|
|
4742
4889
|
},
|
|
4743
4890
|
"action": {
|
|
4744
4891
|
"connectGitHub": "GitHub verbinden",
|
|
@@ -6115,5 +6262,14 @@
|
|
|
6115
6262
|
}
|
|
6116
6263
|
}
|
|
6117
6264
|
}
|
|
6265
|
+
},
|
|
6266
|
+
"externalTools": {
|
|
6267
|
+
"unavailable": {
|
|
6268
|
+
"title": "{tool} kann nicht geöffnet werden",
|
|
6269
|
+
"missingMetadata": "Füllen Sie zuerst {fields} im Tab Metadaten der Arbeitsbereichseinstellungen aus.",
|
|
6270
|
+
"unresolved": "Dieses Tool hat für den aktuellen Arbeitsbereich keine Adresse geliefert.",
|
|
6271
|
+
"resolverFailed": "Beim Ermitteln der Adresse ist in diesem Tool ein Fehler aufgetreten. Die Ursache steht in der Browser-Konsole, für die Betreuer dieser Installation.",
|
|
6272
|
+
"unsafeUrl": "Dieses Tool hat eine Adresse geliefert, die kein Weblink ist, und wurde daher nicht geöffnet."
|
|
6273
|
+
}
|
|
6118
6274
|
}
|
|
6119
6275
|
}
|