@cat-factory/app 0.174.0 → 0.176.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 +25 -13
- package/app/components/board/nodes/BlockNode.vue +30 -0
- package/app/components/layout/IntegrationsHub.vue +14 -1
- package/app/components/panels/InspectorPanel.vue +3 -28
- package/app/components/panels/inspector/ContainerSummary.vue +54 -62
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +11 -0
- package/app/modular/nav-contributions.spec.ts +54 -19
- package/app/modular/nav-contributions.ts +26 -12
- package/i18n/locales/de.json +7 -9
- package/i18n/locales/en.json +7 -9
- package/i18n/locales/es.json +7 -9
- package/i18n/locales/fr.json +7 -9
- package/i18n/locales/he.json +7 -9
- package/i18n/locales/it.json +7 -9
- package/i18n/locales/ja.json +7 -9
- package/i18n/locales/pl.json +7 -9
- package/i18n/locales/tr.json +7 -9
- package/i18n/locales/uk.json +7 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,10 +56,10 @@ over the WebSocket. How that sync works is written up in
|
|
|
56
56
|
## Interface modes (basic / advanced)
|
|
57
57
|
|
|
58
58
|
The SPA renders at one of two **interface tiers**. `basic` (the default) is the everyday
|
|
59
|
-
surface
|
|
60
|
-
|
|
61
|
-
to
|
|
62
|
-
match wins:
|
|
59
|
+
**delivery** surface — plan work on a board, run it, review and merge it: the run/pipeline
|
|
60
|
+
options that only exist to override a workspace-level default are left at that default, and
|
|
61
|
+
the nav is trimmed to what that loop needs. `advanced` shows everything. The tier resolves in
|
|
62
|
+
a fixed order, first match wins:
|
|
63
63
|
|
|
64
64
|
1. **`NUXT_PUBLIC_UI_MODE`** (`basic` | `advanced`) — the deployment pin. Like
|
|
65
65
|
`NUXT_PUBLIC_API_BASE` it is baked in at **build** time (`ssr: false`), and while it is
|
|
@@ -82,20 +82,32 @@ hoc where it can be avoided:
|
|
|
82
82
|
- **A nav destination** declares `advanced: true` in `app/modular/nav-contributions.ts`. The
|
|
83
83
|
shared `navSlotFilter` drops it in basic mode across all three shells (sidebar, command
|
|
84
84
|
palette, toolbar), independently of its RBAC `gate` — both must pass. A consumer module's
|
|
85
|
-
own contributions take the same flag. The bar
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
own contributions take the same flag. The bar is **whether the everyday delivery loop needs
|
|
86
|
+
it**, and marking an item does one of two distinguishable things:
|
|
87
|
+
- **Reached another way** — a shortcut whose surface a basic destination also opens, so
|
|
88
|
+
nothing is lost (the Merge / Service-best-practices palette entries into Workspace
|
|
89
|
+
settings, the local-models knob the Integrations hub already offers).
|
|
90
|
+
- **Out of the tier** — the sole route, hidden on purpose, so the capability is _absent_
|
|
91
|
+
from basic mode and the tier switch is the way to it (Sandbox, Kaizen, repo bootstrap,
|
|
92
|
+
and the deployment-wide operator + reports rollups).
|
|
93
|
+
|
|
94
|
+
Sole-route items stay in basic when the delivery loop runs on them: the pipeline builder,
|
|
95
|
+
add-from-repo, the fragment library, the infrastructure/PREnv windows, and the workspace /
|
|
96
|
+
model configuration a run actually reads. `nav-contributions.spec.ts` pins the advanced set
|
|
97
|
+
against a table naming each item's kind and reason, so promoting one forces that claim to be
|
|
98
|
+
written down rather than assumed.
|
|
99
|
+
|
|
94
100
|
- **A less-used option inside a surface** reads `useUiModeStore().isAdvanced`. Hide, never
|
|
95
101
|
disable, and only ever hide an OVERRIDE: what remains must be exactly the default the hidden
|
|
96
102
|
field would have shown, so a basic-mode user never gets different behaviour from an advanced
|
|
97
103
|
one — only fewer choices. An input nothing else supplies (the pipeline, the apriori branches)
|
|
98
104
|
stays in both tiers however advanced it feels.
|
|
105
|
+
- **A whole AUTHORING affordance** may be tier-scoped the same way — the frame header's
|
|
106
|
+
recurring-schedule and initiative buttons are advanced-only — but only while the tier hides
|
|
107
|
+
the ability to CREATE, never the ability to SEE. Existing state has to stay legible in basic
|
|
108
|
+
mode through its normal surfaces (a live schedule still badges its task card and opens its
|
|
109
|
+
inspector panel; an initiative is still a block on the board with its own inspector), or the
|
|
110
|
+
tier turns into a way for a user to be acted on by configuration they cannot find.
|
|
99
111
|
- **An override control on an EXISTING entity gates on `showOverrideField(isAdvanced, …values)`**
|
|
100
112
|
(`app/utils/uiMode.ts`) rather than on `isAdvanced` alone. Hiding an override is only safe
|
|
101
113
|
while it is unset — always true for a creation form, never guaranteed for a block that a
|
|
@@ -24,6 +24,7 @@ const agentRuns = useAgentRunsStore()
|
|
|
24
24
|
const services = useServicesStore()
|
|
25
25
|
const reviews = useReviewStage()
|
|
26
26
|
const access = useWorkspaceAccess()
|
|
27
|
+
const uiMode = useUiModeStore()
|
|
27
28
|
const { t } = useI18n()
|
|
28
29
|
const { lod } = useSemanticZoom()
|
|
29
30
|
// Coarse-pointer (touch) bumps the frame-header actions from `xs` to `sm` so
|
|
@@ -161,6 +162,13 @@ function addRecurring() {
|
|
|
161
162
|
ui.openAddRecurring(props.id)
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
// Hunt this service's tracker board for a bug worth picking up. Scoped to THIS frame, so
|
|
166
|
+
// an adopted candidate lands here rather than wherever the board's first frame happens to be.
|
|
167
|
+
function huntBugs() {
|
|
168
|
+
ui.expandFrame(props.id)
|
|
169
|
+
ui.openBugHunt(null, props.id)
|
|
170
|
+
}
|
|
171
|
+
|
|
164
172
|
function createInitiative() {
|
|
165
173
|
ui.expandFrame(props.id)
|
|
166
174
|
ui.openCreateInitiative(props.id)
|
|
@@ -491,8 +499,18 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
491
499
|
:title="t('board.frame.createTaskFromIssueTitle')"
|
|
492
500
|
@click.stop="createTaskFromIssue"
|
|
493
501
|
/>
|
|
502
|
+
<!-- Recurring pipelines + initiatives are ADVANCED-tier authoring: both plan
|
|
503
|
+
work rather than do it (a schedule that fires runs on a cadence, an
|
|
504
|
+
initiative that groups tasks under a goal), and the basic frame header is
|
|
505
|
+
the most-used control strip on the board. Hiding the CREATE affordance
|
|
506
|
+
removes neither's existing state from basic mode — a live schedule still
|
|
507
|
+
badges its task card and opens its inspector panel, and an initiative is
|
|
508
|
+
still a block on the board with its own inspector — so what a basic-mode
|
|
509
|
+
user loses is the ability to author a new one, not sight of one. -->
|
|
494
510
|
<UButton
|
|
511
|
+
v-if="uiMode.isAdvanced"
|
|
495
512
|
class="nodrag"
|
|
513
|
+
data-testid="frame-add-recurring"
|
|
496
514
|
:size="isTouch ? 'sm' : 'xs'"
|
|
497
515
|
variant="ghost"
|
|
498
516
|
color="neutral"
|
|
@@ -501,6 +519,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
501
519
|
@click.stop="addRecurring"
|
|
502
520
|
/>
|
|
503
521
|
<UButton
|
|
522
|
+
v-if="uiMode.isAdvanced"
|
|
504
523
|
class="nodrag"
|
|
505
524
|
data-testid="frame-add-initiative"
|
|
506
525
|
:size="isTouch ? 'sm' : 'xs'"
|
|
@@ -510,6 +529,17 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
510
529
|
:title="t('board.frame.createInitiativeTitle')"
|
|
511
530
|
@click.stop="createInitiative"
|
|
512
531
|
/>
|
|
532
|
+
<UButton
|
|
533
|
+
v-if="tasks.anyOffered"
|
|
534
|
+
class="nodrag"
|
|
535
|
+
data-testid="frame-hunt-bugs"
|
|
536
|
+
:size="isTouch ? 'sm' : 'xs'"
|
|
537
|
+
variant="ghost"
|
|
538
|
+
color="neutral"
|
|
539
|
+
icon="i-lucide-radar"
|
|
540
|
+
:title="t('board.frame.huntBugsTitle')"
|
|
541
|
+
@click.stop="huntBugs"
|
|
542
|
+
/>
|
|
513
543
|
</template>
|
|
514
544
|
<UButton
|
|
515
545
|
class="nodrag"
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { showOverrideField } from '~/utils/uiMode'
|
|
3
|
+
|
|
2
4
|
// The Integrations hub: a single modal that lists every external system the WORKSPACE can
|
|
3
5
|
// enable or link in. Each row reuses the existing per-integration panel handlers on the `ui`
|
|
4
6
|
// store (so the integrations themselves are unchanged); opening one closes the hub and
|
|
@@ -25,6 +27,7 @@ const publicApiKeys = usePublicApiKeysStore()
|
|
|
25
27
|
const userSecrets = useUserSecretsStore()
|
|
26
28
|
const apiKeys = useApiKeysStore()
|
|
27
29
|
const workspace = useWorkspaceStore()
|
|
30
|
+
const uiMode = useUiModeStore()
|
|
28
31
|
|
|
29
32
|
// True when the per-user "My setup" hub is reachable (UserMenu renders only when signed in).
|
|
30
33
|
// When false (auth disabled / local mode) we fold the personal rows back into this hub so
|
|
@@ -268,7 +271,17 @@ const groups = computed<IntegrationGroup[]>(() => {
|
|
|
268
271
|
// Gated like every other backend-toggleable system: hidden until a probe confirms
|
|
269
272
|
// the observability module is enabled (`available === true`), so a disabled backend
|
|
270
273
|
// doesn't show a dead "Connect" row that only 503s.
|
|
271
|
-
|
|
274
|
+
//
|
|
275
|
+
// Also an ADVANCED-tier row. Post-release health is the one integration here that acts
|
|
276
|
+
// AFTER delivery rather than during it — it watches monitors once a release ships and can
|
|
277
|
+
// spawn an on-call agent — so it sits outside the everyday loop the basic tier serves.
|
|
278
|
+
// Gated with `showOverrideField` rather than a bare `isAdvanced`: an already-connected
|
|
279
|
+
// Datadog is live behaviour on this workspace, and a tier must never conceal a connection a
|
|
280
|
+
// basic-mode user would then have no way to inspect or disconnect.
|
|
281
|
+
if (
|
|
282
|
+
releaseHealth.available &&
|
|
283
|
+
showOverrideField(uiMode.isAdvanced, releaseHealth.connection.connected || null)
|
|
284
|
+
) {
|
|
272
285
|
out.push({
|
|
273
286
|
title: t('layout.integrationsHub.groups.observability'),
|
|
274
287
|
items: [
|
|
@@ -13,7 +13,6 @@ const pipelines = usePipelinesStore()
|
|
|
13
13
|
const execution = useExecutionStore()
|
|
14
14
|
const ui = useUiStore()
|
|
15
15
|
const documents = useDocumentsStore()
|
|
16
|
-
const tasks = useTasksStore()
|
|
17
16
|
const fragments = useFragmentsStore()
|
|
18
17
|
const agentRuns = useAgentRunsStore()
|
|
19
18
|
const github = useGitHubStore()
|
|
@@ -450,33 +449,9 @@ const showOriginalDescription = ref(false)
|
|
|
450
449
|
>
|
|
451
450
|
{{ block!.pullRequest!.branch }}
|
|
452
451
|
</UButton>
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
variant="soft"
|
|
457
|
-
size="xs"
|
|
458
|
-
icon="i-lucide-ticket"
|
|
459
|
-
@click="ui.openTaskImport()"
|
|
460
|
-
>
|
|
461
|
-
{{
|
|
462
|
-
tasks.anyOffered
|
|
463
|
-
? t('panels.inspector.importIssue')
|
|
464
|
-
: t('panels.inspector.connectTracker')
|
|
465
|
-
}}
|
|
466
|
-
</UButton>
|
|
467
|
-
<!-- Hunt this service's tracker board for a bug worth picking up. Scoped to the
|
|
468
|
-
selected container, so an adopted candidate lands here rather than wherever the
|
|
469
|
-
board's first frame happens to be. -->
|
|
470
|
-
<UButton
|
|
471
|
-
v-if="isContainer && tasks.anyOffered"
|
|
472
|
-
color="neutral"
|
|
473
|
-
variant="soft"
|
|
474
|
-
size="xs"
|
|
475
|
-
icon="i-lucide-radar"
|
|
476
|
-
@click="ui.openBugHunt(null, block!.id)"
|
|
477
|
-
>
|
|
478
|
-
{{ t('panels.inspector.huntBugs') }}
|
|
479
|
-
</UButton>
|
|
452
|
+
<!-- Tracker entry points (import an issue, hunt bugs) live on the service frame's
|
|
453
|
+
header, where they are already scoped to a frame — the inspector doesn't
|
|
454
|
+
duplicate them. -->
|
|
480
455
|
<UButton
|
|
481
456
|
v-if="isContainer && documents.available && documents.anyConnected"
|
|
482
457
|
color="neutral"
|
|
@@ -22,72 +22,64 @@ function addTask() {
|
|
|
22
22
|
</script>
|
|
23
23
|
|
|
24
24
|
<template>
|
|
25
|
+
<!-- Modules and tasks are two peer collapsible lists, not one "Contents" group: the
|
|
26
|
+
grouping added a level of nesting without adding information, and a service's task
|
|
27
|
+
list is long enough to want collapsing independently of its modules. -->
|
|
25
28
|
<InspectorSection
|
|
26
|
-
|
|
27
|
-
:
|
|
28
|
-
:
|
|
29
|
+
v-if="modules.length"
|
|
30
|
+
:title="t('inspector.container.modulesTitle')"
|
|
31
|
+
:hint="t('inspector.container.modulesHint')"
|
|
32
|
+
:count="modules.length"
|
|
29
33
|
default-open
|
|
30
34
|
>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
)
|
|
51
|
-
}}</span>
|
|
52
|
-
</li>
|
|
53
|
-
</ul>
|
|
54
|
-
</div>
|
|
35
|
+
<ul class="space-y-1">
|
|
36
|
+
<li
|
|
37
|
+
v-for="m in modules"
|
|
38
|
+
:key="m.id"
|
|
39
|
+
class="flex cursor-pointer items-center gap-2 rounded-md px-2 py-1 hover:bg-slate-800/60"
|
|
40
|
+
@click="ui.select(m.id)"
|
|
41
|
+
>
|
|
42
|
+
<UIcon name="i-lucide-package" class="h-3.5 w-3.5 text-violet-400" />
|
|
43
|
+
<span class="truncate text-xs text-slate-200">{{ m.title }}</span>
|
|
44
|
+
<span class="ms-auto text-[10px] text-slate-500">{{
|
|
45
|
+
t(
|
|
46
|
+
'inspector.container.taskCount',
|
|
47
|
+
{ count: board.tasksOf(m.id).length },
|
|
48
|
+
board.tasksOf(m.id).length,
|
|
49
|
+
)
|
|
50
|
+
}}</span>
|
|
51
|
+
</li>
|
|
52
|
+
</ul>
|
|
53
|
+
</InspectorSection>
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
class="
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<span class="ms-auto text-[10px] text-slate-500">{{
|
|
85
|
-
STATUS_META[task.status].label
|
|
86
|
-
}}</span>
|
|
87
|
-
</li>
|
|
88
|
-
</ul>
|
|
89
|
-
<div v-else class="text-[11px] text-slate-500">{{ t('inspector.container.noTasks') }}</div>
|
|
90
|
-
</div>
|
|
55
|
+
<InspectorSection
|
|
56
|
+
:title="isFrame ? t('inspector.container.allTasksTitle') : t('inspector.container.tasksTitle')"
|
|
57
|
+
:hint="t('inspector.container.tasksHint')"
|
|
58
|
+
:count="tasks.length"
|
|
59
|
+
default-open
|
|
60
|
+
>
|
|
61
|
+
<template #actions>
|
|
62
|
+
<ReviewDebtBadge />
|
|
63
|
+
<UButton size="xs" variant="soft" color="primary" icon="i-lucide-plus" @click="addTask">
|
|
64
|
+
{{ t('inspector.container.addTask') }}
|
|
65
|
+
</UButton>
|
|
66
|
+
</template>
|
|
67
|
+
<ul v-if="tasks.length" class="space-y-1">
|
|
68
|
+
<li
|
|
69
|
+
v-for="task in tasks"
|
|
70
|
+
:key="task.id"
|
|
71
|
+
class="flex cursor-pointer items-center gap-2 rounded-md px-2 py-1 hover:bg-slate-800/60"
|
|
72
|
+
@click="ui.select(task.id)"
|
|
73
|
+
>
|
|
74
|
+
<span
|
|
75
|
+
class="h-2 w-2 shrink-0 rounded-full"
|
|
76
|
+
:style="{ backgroundColor: STATUS_META[task.status].color }"
|
|
77
|
+
/>
|
|
78
|
+
<span class="truncate text-xs text-slate-200">{{ task.title }}</span>
|
|
79
|
+
<span class="ms-auto text-[10px] text-slate-500">{{ STATUS_META[task.status].label }}</span>
|
|
80
|
+
</li>
|
|
81
|
+
</ul>
|
|
82
|
+
<div v-else class="text-[11px] text-slate-500">{{ t('inspector.container.noTasks') }}</div>
|
|
91
83
|
<p v-if="isFrame" class="text-[11px] text-slate-500">
|
|
92
84
|
{{ t('inspector.container.servicesHint') }}
|
|
93
85
|
</p>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { computed, reactive, ref, watch } from 'vue'
|
|
3
3
|
import type { Block } from '~/types/domain'
|
|
4
4
|
import InspectorSection from '~/components/panels/inspector/InspectorSection.vue'
|
|
5
|
+
import { showOverrideField } from '~/utils/uiMode'
|
|
5
6
|
|
|
6
7
|
// Per-service (frame) post-release-health mapping: which observability monitors/SLOs the
|
|
7
8
|
// `post-release-health` gate watches after this service's PRs ship. Keyed by THIS block's
|
|
@@ -11,6 +12,7 @@ const props = defineProps<{ block: Block }>()
|
|
|
11
12
|
|
|
12
13
|
const store = useReleaseHealthStore()
|
|
13
14
|
const ui = useUiStore()
|
|
15
|
+
const uiMode = useUiModeStore()
|
|
14
16
|
const toast = useToast()
|
|
15
17
|
const { t } = useI18n()
|
|
16
18
|
const { confirmAction, toastDone } = useConfirmAction()
|
|
@@ -21,6 +23,14 @@ const draft = reactive({ monitorIds: '', sloIds: '', envTag: '' })
|
|
|
21
23
|
const connected = computed(() => store.connection.connected)
|
|
22
24
|
const saved = computed(() => store.configForBlock(props.block.id))
|
|
23
25
|
|
|
26
|
+
// Post-release health is an ADVANCED-tier concern: with no mapping the gate is a pass-through,
|
|
27
|
+
// so basic mode hides the whole section rather than showing a service-level knob whose absence
|
|
28
|
+
// changes nothing. `showOverrideField` (not a bare `isAdvanced`) because the mapping is per
|
|
29
|
+
// SERVICE and durable — once a teammate on the advanced tier maps monitors onto this frame,
|
|
30
|
+
// hiding the panel would leave a basic-mode user with releases being watched (and an on-call
|
|
31
|
+
// agent that can spawn) by a configuration they can neither see nor clear.
|
|
32
|
+
const show = computed(() => showOverrideField(uiMode.isAdvanced, saved.value))
|
|
33
|
+
|
|
24
34
|
function parseIds(csv: string): string[] {
|
|
25
35
|
return csv
|
|
26
36
|
.split(',')
|
|
@@ -91,6 +101,7 @@ async function clear() {
|
|
|
91
101
|
|
|
92
102
|
<template>
|
|
93
103
|
<InspectorSection
|
|
104
|
+
v-if="show"
|
|
94
105
|
:title="t('inspector.releaseHealth.title')"
|
|
95
106
|
:hint="t('inspector.releaseHealth.sectionHint')"
|
|
96
107
|
>
|
|
@@ -99,36 +99,71 @@ describe('navSlotFilter', () => {
|
|
|
99
99
|
expect(kept).toContain('integrations-hub')
|
|
100
100
|
expect(kept).toContain('workspace-settings')
|
|
101
101
|
expect(kept).toContain('model-config')
|
|
102
|
-
// ...and so does
|
|
103
|
-
//
|
|
104
|
-
// aggregate run-health / spend views.
|
|
102
|
+
// ...and so does everything the everyday delivery loop runs on, however deep it feels:
|
|
103
|
+
// authoring a flow, the standards library, and the PREnv/runner plumbing.
|
|
105
104
|
expect(kept).toContain('build-pipeline')
|
|
106
105
|
expect(kept).toContain('fragments')
|
|
107
106
|
expect(kept).toContain('infrastructure')
|
|
108
107
|
expect(kept).toContain('environment-setup')
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
// basic mode already reaches another way.
|
|
108
|
+
// What drops is either a shortcut basic mode reaches another way, or a capability
|
|
109
|
+
// deliberately kept out of the tier (experimentation, one-off repo setup, the
|
|
110
|
+
// deployment-wide operator rollups).
|
|
113
111
|
expect(kept).not.toContain('sandbox')
|
|
114
112
|
expect(kept).not.toContain('kaizen')
|
|
115
113
|
expect(kept).not.toContain('merge-thresholds')
|
|
114
|
+
expect(kept).not.toContain('bootstrap-repo')
|
|
115
|
+
expect(kept).not.toContain('operator-dashboard')
|
|
116
|
+
expect(kept).not.toContain('reports')
|
|
116
117
|
})
|
|
117
118
|
|
|
118
|
-
it('
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
'merge-thresholds':
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
it('states, per advanced item, whether basic mode still reaches its capability', () => {
|
|
120
|
+
// Marking an item `advanced` does one of two things, and which one has to be said out
|
|
121
|
+
// loud. `reached-another-way` promises a basic destination opens the same surface, so
|
|
122
|
+
// nothing is lost. `out-of-tier` concedes the opposite: the capability is ABSENT from
|
|
123
|
+
// basic mode and the tier switch is the only way to it. Both are legitimate; a silent
|
|
124
|
+
// one is not. The table is the claim, and it must match the catalog exactly, so adding
|
|
125
|
+
// `advanced: true` fails here until the reason is written down.
|
|
126
|
+
const REASON: Record<string, { kind: 'reached-another-way' | 'out-of-tier'; why: string }> = {
|
|
127
|
+
'merge-thresholds': {
|
|
128
|
+
kind: 'reached-another-way',
|
|
129
|
+
why: 'workspace-settings -> Merge tab',
|
|
130
|
+
},
|
|
131
|
+
'service-fragment-defaults': {
|
|
132
|
+
kind: 'reached-another-way',
|
|
133
|
+
why: 'workspace-settings -> Service best practices tab',
|
|
134
|
+
},
|
|
135
|
+
'local-models': {
|
|
136
|
+
kind: 'reached-another-way',
|
|
137
|
+
why: 'integrations-hub -> Local runners',
|
|
138
|
+
},
|
|
139
|
+
sandbox: {
|
|
140
|
+
kind: 'out-of-tier',
|
|
141
|
+
why: 'experimentation surface, beside the delivery path',
|
|
142
|
+
},
|
|
143
|
+
kaizen: {
|
|
144
|
+
kind: 'out-of-tier',
|
|
145
|
+
why: 'self-grading history, beside the delivery path',
|
|
146
|
+
},
|
|
147
|
+
'bootstrap-repo': {
|
|
148
|
+
kind: 'out-of-tier',
|
|
149
|
+
why: 'one-off new-repo setup, not part of running work on an existing board',
|
|
150
|
+
},
|
|
151
|
+
'operator-dashboard': {
|
|
152
|
+
kind: 'out-of-tier',
|
|
153
|
+
why: 'deployment-wide health rollup - an operator job, not a delivery one',
|
|
154
|
+
},
|
|
155
|
+
reports: {
|
|
156
|
+
kind: 'out-of-tier',
|
|
157
|
+
why: 'deployment-wide spend/activity rollup - an operator job, not a delivery one',
|
|
158
|
+
},
|
|
129
159
|
}
|
|
130
160
|
const advanced = NAV_CONTRIBUTIONS.filter((i) => i.advanced).map((i) => i.id)
|
|
131
|
-
expect(advanced.sort()).toEqual(Object.keys(
|
|
161
|
+
expect(advanced.sort()).toEqual(Object.keys(REASON).sort())
|
|
162
|
+
// An `out-of-tier` item is a real capability loss, so the switcher back must survive basic
|
|
163
|
+
// mode — pinned by the next case. Assert here only that every claim carries a reason.
|
|
164
|
+
for (const [id, reason] of Object.entries(REASON)) {
|
|
165
|
+
expect(reason.why.length, `${id} has no stated reason`).toBeGreaterThan(0)
|
|
166
|
+
}
|
|
132
167
|
})
|
|
133
168
|
|
|
134
169
|
it('keeps the tier switch itself reachable in basic mode', () => {
|
|
@@ -153,24 +153,35 @@ const S = (...s: NavSurface[]) => s as readonly NavSurface[]
|
|
|
153
153
|
* with accounts enabled).
|
|
154
154
|
* - one icon per destination across shells.
|
|
155
155
|
*
|
|
156
|
-
* `advanced: true` marks the power-user half, hidden in basic interface mode.
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
156
|
+
* `advanced: true` marks the power-user half, hidden in basic interface mode. Basic is the
|
|
157
|
+
* EVERYDAY DELIVERY SURFACE — plan work on a board, run it, review and merge it — so an item
|
|
158
|
+
* is advanced when it is not part of that loop. That happens two ways, and the difference
|
|
159
|
+
* matters when reading the list (it is the column `nav-contributions.spec.ts` makes you fill
|
|
160
|
+
* in):
|
|
161
161
|
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
162
|
+
* REACHED ANOTHER WAY — hiding a shortcut removes nothing, because a basic destination opens
|
|
163
|
+
* the same surface:
|
|
164
164
|
* - `merge-thresholds` / `service-fragment-defaults` — palette shortcuts into Workspace
|
|
165
165
|
* settings tabs (Merge, Service best practices), which basic mode reaches via
|
|
166
166
|
* `workspace-settings`.
|
|
167
167
|
* - `local-models` — a per-user endpoint knob the Integrations hub already offers.
|
|
168
168
|
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
169
|
+
* OUT OF THE TIER — the sole route, hidden deliberately, so the capability itself is absent
|
|
170
|
+
* from basic mode. This is a product decision, not an oversight: each of these answers a
|
|
171
|
+
* question an everyday delivery user does not ask, and carrying it costs the basic nav more
|
|
172
|
+
* than the capability is worth there. Switching to advanced is the way to it.
|
|
173
|
+
* - `sandbox` / `kaizen` — experimentation and self-grading surfaces, beside the delivery
|
|
174
|
+
* path rather than on it.
|
|
175
|
+
* - `bootstrap-repo` — standing a NEW repository up from a reference architecture: a
|
|
176
|
+
* once-per-service setup act, not part of running work on an existing board.
|
|
177
|
+
* - `operator-dashboard` / `reports` — the deployment-wide health and spend rollups. They
|
|
178
|
+
* read across every workspace for whoever operates the deployment, which is a different
|
|
179
|
+
* job from delivering a task on one board.
|
|
180
|
+
*
|
|
181
|
+
* Everything else stays in basic because the delivery loop needs it: authoring a flow
|
|
182
|
+
* (`build-pipeline`), adding a repo (`add-from-repo`), the standards/skills library
|
|
183
|
+
* (`fragments`), the PREnv + runner plumbing (`infrastructure`, `environment-setup`), and the
|
|
184
|
+
* workspace/model configuration a run actually reads (`workspace-settings`, `model-config`).
|
|
174
185
|
*/
|
|
175
186
|
export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
176
187
|
{
|
|
@@ -210,6 +221,7 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
210
221
|
labelKey: 'nav.bootstrapRepo',
|
|
211
222
|
icon: 'i-lucide-git-branch-plus',
|
|
212
223
|
surfaces: S('sidebar', 'command'),
|
|
224
|
+
advanced: true,
|
|
213
225
|
gate: (g) => g.canManageIntegrations,
|
|
214
226
|
action: 'bootstrapRepo',
|
|
215
227
|
testId: 'nav-bootstrap-repo',
|
|
@@ -388,6 +400,7 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
388
400
|
labelKey: 'nav.operatorDashboard',
|
|
389
401
|
icon: 'i-lucide-gauge',
|
|
390
402
|
surfaces: S('sidebar'),
|
|
403
|
+
advanced: true,
|
|
391
404
|
gate: (g) => g.accountsEnabled && g.isAccountAdmin,
|
|
392
405
|
action: 'operatorDashboard',
|
|
393
406
|
testId: 'nav-operator-dashboard',
|
|
@@ -398,6 +411,7 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
398
411
|
labelKey: 'nav.reports',
|
|
399
412
|
icon: 'i-lucide-chart-column',
|
|
400
413
|
surfaces: S('sidebar'),
|
|
414
|
+
advanced: true,
|
|
401
415
|
gate: (g) => g.accountsEnabled && g.isAccountAdmin,
|
|
402
416
|
action: 'reports',
|
|
403
417
|
testId: 'nav-reports',
|
package/i18n/locales/de.json
CHANGED
|
@@ -948,12 +948,12 @@
|
|
|
948
948
|
"inspector": {
|
|
949
949
|
"detectRepoUnresolved": "Das Repository dieses Blocks gehört nicht zu den verbundenen GitHub-Repos und kann daher nicht gelesen werden. Verbinde oder synchronisiere GitHub dafür und versuche es erneut.",
|
|
950
950
|
"container": {
|
|
951
|
-
"
|
|
952
|
-
"
|
|
953
|
-
"modules": "Module ({count})",
|
|
951
|
+
"modulesTitle": "Module",
|
|
952
|
+
"modulesHint": "Die Module innerhalb dieses Service. Klicke auf ein Modul, um es auf dem Board auszuwählen.",
|
|
954
953
|
"taskCount": "{count} Aufgabe | {count} Aufgaben",
|
|
955
|
-
"
|
|
956
|
-
"
|
|
954
|
+
"tasksTitle": "Aufgaben",
|
|
955
|
+
"allTasksTitle": "Alle Aufgaben",
|
|
956
|
+
"tasksHint": "Die Aufgaben innerhalb dieses Blocks. Klicke auf eine Aufgabe, um sie auf dem Board auszuwählen.",
|
|
957
957
|
"addTask": "Aufgabe hinzufügen",
|
|
958
958
|
"noTasks": "Noch keine Aufgaben. Füge eine hinzu, um mit der Arbeit zu beginnen.",
|
|
959
959
|
"servicesHint": "Services sind langlebig und werden nicht abgeschlossen. Die Arbeit findet in ihren Aufgaben und Modulen statt."
|
|
@@ -1658,8 +1658,6 @@
|
|
|
1658
1658
|
"lastIncorporatedRequirements": "Zuletzt eingearbeitete Anforderungen",
|
|
1659
1659
|
"priorDocHint": "Aus der vorherigen Prüfung. Verwende es als Basis: bearbeite die Beschreibung oben und reiche erneut ein.",
|
|
1660
1660
|
"bootstrapping": "Wird initialisiert…",
|
|
1661
|
-
"importIssue": "Issue importieren",
|
|
1662
|
-
"connectTracker": "Einen Tracker verbinden",
|
|
1663
1661
|
"spawnFromDocument": "Aus Dokument erzeugen",
|
|
1664
1662
|
"viewRequirements": "Anforderungen anzeigen",
|
|
1665
1663
|
"reRun": "Erneut ausführen",
|
|
@@ -1670,8 +1668,7 @@
|
|
|
1670
1668
|
"title": "Diesen Dienst archivieren?",
|
|
1671
1669
|
"body": "„{name}“ und seine Aufgaben werden vom Board ausgeblendet. Du kannst den Dienst jederzeit wiederherstellen."
|
|
1672
1670
|
},
|
|
1673
|
-
"runBlocked": "Blockiert durch eine unerledigte Abhängigkeit: {names} | Blockiert durch {count} unerledigte Abhängigkeiten: {names}"
|
|
1674
|
-
"huntBugs": "Fehler jagen"
|
|
1671
|
+
"runBlocked": "Blockiert durch eine unerledigte Abhängigkeit: {names} | Blockiert durch {count} unerledigte Abhängigkeiten: {names}"
|
|
1675
1672
|
}
|
|
1676
1673
|
},
|
|
1677
1674
|
"layout": {
|
|
@@ -2446,6 +2443,7 @@
|
|
|
2446
2443
|
"dragToResize": "Zum Ändern der Größe ziehen",
|
|
2447
2444
|
"addFirstTask": "Die erste Aufgabe hinzufügen",
|
|
2448
2445
|
"createInitiativeTitle": "Initiative erstellen",
|
|
2446
|
+
"huntBugsTitle": "Fehler jagen",
|
|
2449
2447
|
"accessDenied": {
|
|
2450
2448
|
"title": "Zugriff verweigert",
|
|
2451
2449
|
"hint": "Sie haben keinen Zugriff auf das Repository, das diesem Service zugrunde liegt."
|
package/i18n/locales/en.json
CHANGED
|
@@ -433,6 +433,7 @@
|
|
|
433
433
|
"dragToResize": "Drag to resize",
|
|
434
434
|
"addFirstTask": "Add the first task",
|
|
435
435
|
"createInitiativeTitle": "Create initiative",
|
|
436
|
+
"huntBugsTitle": "Hunt bugs",
|
|
436
437
|
"accessDenied": {
|
|
437
438
|
"title": "Permission denied",
|
|
438
439
|
"hint": "You don't have access to the repository backing this service."
|
|
@@ -694,12 +695,12 @@
|
|
|
694
695
|
"inspector": {
|
|
695
696
|
"detectRepoUnresolved": "This block's repository isn't among the connected GitHub repos, so it can't be read. Connect or sync GitHub for it, then retry.",
|
|
696
697
|
"container": {
|
|
697
|
-
"
|
|
698
|
-
"
|
|
699
|
-
"modules": "Modules ({count})",
|
|
698
|
+
"modulesTitle": "Modules",
|
|
699
|
+
"modulesHint": "The modules inside this service. Click one to select it on the board.",
|
|
700
700
|
"taskCount": "{count} task | {count} tasks",
|
|
701
|
-
"
|
|
702
|
-
"
|
|
701
|
+
"tasksTitle": "Tasks",
|
|
702
|
+
"allTasksTitle": "All tasks",
|
|
703
|
+
"tasksHint": "The tasks inside this block. Click one to select it on the board.",
|
|
703
704
|
"addTask": "Add task",
|
|
704
705
|
"noTasks": "No tasks yet. Add one to start work.",
|
|
705
706
|
"servicesHint": "Services are long-lived and don't complete. Work happens in their tasks and modules."
|
|
@@ -1404,8 +1405,6 @@
|
|
|
1404
1405
|
"lastIncorporatedRequirements": "Last incorporated requirements",
|
|
1405
1406
|
"priorDocHint": "From the previous review. Use it as a base: edit the description above and resubmit.",
|
|
1406
1407
|
"bootstrapping": "Bootstrapping…",
|
|
1407
|
-
"importIssue": "Import issue",
|
|
1408
|
-
"connectTracker": "Connect a tracker",
|
|
1409
1408
|
"spawnFromDocument": "Spawn from document",
|
|
1410
1409
|
"viewRequirements": "View Requirements",
|
|
1411
1410
|
"reRun": "Re-run",
|
|
@@ -1419,8 +1418,7 @@
|
|
|
1419
1418
|
"runBlocked": "Blocked by an unfinished dependency: {names} | Blocked by {count} unfinished dependencies: {names}",
|
|
1420
1419
|
"@runBlocked": {
|
|
1421
1420
|
"description": "Count-driven plural: {count} unfinished dependencies, {names} their comma-joined titles. Languages with more than two plural forms (e.g. Polish, Ukrainian: one/few/many) need the extra pipe-separated forms."
|
|
1422
|
-
}
|
|
1423
|
-
"huntBugs": "Hunt bugs"
|
|
1421
|
+
}
|
|
1424
1422
|
}
|
|
1425
1423
|
},
|
|
1426
1424
|
"observability": {
|
package/i18n/locales/es.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "Arrastra para cambiar el tamaño",
|
|
395
395
|
"addFirstTask": "Añade la primera tarea",
|
|
396
396
|
"createInitiativeTitle": "Crear iniciativa",
|
|
397
|
+
"huntBugsTitle": "Cazar errores",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "Permiso denegado",
|
|
399
400
|
"hint": "No tienes acceso al repositorio que respalda este servicio."
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "El repositorio de este bloque no está entre los repositorios de GitHub conectados, por lo que no se puede leer. Conecta o sincroniza GitHub para él y vuelve a intentarlo.",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "Módulos ({count})",
|
|
635
|
+
"modulesTitle": "Módulos",
|
|
636
|
+
"modulesHint": "Los módulos dentro de este servicio. Haz clic en uno para seleccionarlo en el tablero.",
|
|
637
637
|
"taskCount": "{count} tarea | {count} tareas",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "Tareas",
|
|
639
|
+
"allTasksTitle": "Todas las tareas",
|
|
640
|
+
"tasksHint": "Las tareas dentro de este bloque. Haz clic en una para seleccionarla en el tablero.",
|
|
640
641
|
"addTask": "Añadir tarea",
|
|
641
642
|
"noTasks": "Aún no hay tareas. Añade una para empezar a trabajar.",
|
|
642
643
|
"servicesHint": "Los servicios son de larga duración y no se completan. El trabajo ocurre en sus tareas y módulos."
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "Últimos requisitos incorporados",
|
|
1319
1320
|
"priorDocHint": "De la revisión anterior. Úsalo como base: edita la descripción de arriba y reenvíala.",
|
|
1320
1321
|
"bootstrapping": "Inicializando…",
|
|
1321
|
-
"importIssue": "Importar incidencia",
|
|
1322
|
-
"connectTracker": "Conectar un tracker",
|
|
1323
1322
|
"spawnFromDocument": "Generar desde documento",
|
|
1324
1323
|
"viewRequirements": "Ver requisitos",
|
|
1325
1324
|
"reRun": "Reejecutar",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "¿Archivar este servicio?",
|
|
1354
1353
|
"body": "«{name}» y sus tareas se ocultarán del tablero. Puedes restaurarlo en cualquier momento."
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "Bloqueado por una dependencia sin terminar: {names} | Bloqueado por {count} dependencias sin terminar: {names}"
|
|
1357
|
-
"huntBugs": "Cazar errores"
|
|
1355
|
+
"runBlocked": "Bloqueado por una dependencia sin terminar: {names} | Bloqueado por {count} dependencias sin terminar: {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/i18n/locales/fr.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "Glisser pour redimensionner",
|
|
395
395
|
"addFirstTask": "Ajouter la première tâche",
|
|
396
396
|
"createInitiativeTitle": "Creer une initiative",
|
|
397
|
+
"huntBugsTitle": "Chasser les bugs",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "Autorisation refusée",
|
|
399
400
|
"hint": "Vous n'avez pas accès au dépôt sur lequel repose ce service."
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "Le dépôt de ce bloc ne figure pas parmi les dépôts GitHub connectés et ne peut donc pas être lu. Connectez ou synchronisez GitHub pour ce dépôt, puis réessayez.",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "Modules ({count})",
|
|
635
|
+
"modulesTitle": "Modules",
|
|
636
|
+
"modulesHint": "Les modules de ce service. Cliquez sur l'un d'eux pour le sélectionner sur le tableau.",
|
|
637
637
|
"taskCount": "{count} tâche | {count} tâches",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "Tâches",
|
|
639
|
+
"allTasksTitle": "Toutes les tâches",
|
|
640
|
+
"tasksHint": "Les tâches contenues dans ce bloc. Cliquez sur l'une d'elles pour la sélectionner sur le tableau.",
|
|
640
641
|
"addTask": "Ajouter une tâche",
|
|
641
642
|
"noTasks": "Aucune tâche pour le moment. Ajoutez-en une pour commencer.",
|
|
642
643
|
"servicesHint": "Les services sont permanents et ne se terminent pas. Le travail se fait dans leurs tâches et modules."
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "Dernières exigences intégrées",
|
|
1319
1320
|
"priorDocHint": "Issu de la revue précédente. Utilisez-le comme base : modifiez la description ci-dessus et resoumettez.",
|
|
1320
1321
|
"bootstrapping": "Initialisation…",
|
|
1321
|
-
"importIssue": "Importer une issue",
|
|
1322
|
-
"connectTracker": "Connecter un tracker",
|
|
1323
1322
|
"spawnFromDocument": "Créer à partir d'un document",
|
|
1324
1323
|
"viewRequirements": "Voir les exigences",
|
|
1325
1324
|
"reRun": "Relancer",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "Archiver ce service ?",
|
|
1354
1353
|
"body": "« {name} » et ses tâches seront masqués du tableau. Vous pouvez le restaurer à tout moment."
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "Bloqué par une dépendance non terminée : {names} | Bloqué par {count} dépendances non terminées : {names}"
|
|
1357
|
-
"huntBugs": "Chasser les bugs"
|
|
1355
|
+
"runBlocked": "Bloqué par une dépendance non terminée : {names} | Bloqué par {count} dépendances non terminées : {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/i18n/locales/he.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "גרור לשינוי גודל",
|
|
395
395
|
"addFirstTask": "הוסף את המשימה הראשונה",
|
|
396
396
|
"createInitiativeTitle": "יצירת יוזמה",
|
|
397
|
+
"huntBugsTitle": "צוד באגים",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "הגישה נדחתה",
|
|
399
400
|
"hint": "אין לך גישה למאגר שעליו מבוסס שירות זה."
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "מאגר הקוד של בלוק זה אינו נמצא בין מאגרי GitHub המחוברים, ולכן לא ניתן לקרוא אותו. חבר או סנכרן את GitHub עבורו ונסה שוב.",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "מודולים ({count})",
|
|
635
|
+
"modulesTitle": "מודולים",
|
|
636
|
+
"modulesHint": "המודולים בתוך שירות זה. לחץ על מודול כדי לבחור אותו בלוח.",
|
|
637
637
|
"taskCount": "משימה {count} | {count} משימות",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "משימות",
|
|
639
|
+
"allTasksTitle": "כל המשימות",
|
|
640
|
+
"tasksHint": "המשימות בתוך בלוק זה. לחץ על משימה כדי לבחור אותה בלוח.",
|
|
640
641
|
"addTask": "הוסף משימה",
|
|
641
642
|
"noTasks": "אין עדיין משימות. הוסף אחת כדי להתחיל בעבודה.",
|
|
642
643
|
"servicesHint": "שירותים הם ארוכי טווח ואינם מסתיימים. העבודה מתבצעת במשימות ובמודולים שלהם."
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "הדרישות האחרונות ששולבו",
|
|
1319
1320
|
"priorDocHint": "מהסקירה הקודמת. השתמש בו כבסיס: ערוך את התיאור למעלה ושלח מחדש.",
|
|
1320
1321
|
"bootstrapping": "מאתחל…",
|
|
1321
|
-
"importIssue": "ייבא ניושן",
|
|
1322
|
-
"connectTracker": "חבר מערכת מעקב",
|
|
1323
1322
|
"spawnFromDocument": "צור ממסמך",
|
|
1324
1323
|
"viewRequirements": "הצג דרישות",
|
|
1325
1324
|
"reRun": "הרץ מחדש",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "להעביר שירות זה לארכיון?",
|
|
1354
1353
|
"body": "\"{name}\" והמשימות שלו יוסתרו מהלוח. אפשר לשחזר אותו בכל עת."
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "חסום על ידי תלות אחת שלא הושלמה: {names} | חסום על ידי {count} תלויות שלא הושלמו: {names}"
|
|
1357
|
-
"huntBugs": "צוד באגים"
|
|
1355
|
+
"runBlocked": "חסום על ידי תלות אחת שלא הושלמה: {names} | חסום על ידי {count} תלויות שלא הושלמו: {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/i18n/locales/it.json
CHANGED
|
@@ -948,12 +948,12 @@
|
|
|
948
948
|
"inspector": {
|
|
949
949
|
"detectRepoUnresolved": "Il repository di questo blocco non e' tra i repository GitHub collegati, quindi non puo' essere letto. Collega o sincronizza GitHub per esso, poi riprova.",
|
|
950
950
|
"container": {
|
|
951
|
-
"
|
|
952
|
-
"
|
|
953
|
-
"modules": "Moduli ({count})",
|
|
951
|
+
"modulesTitle": "Moduli",
|
|
952
|
+
"modulesHint": "I moduli all'interno di questo servizio. Fai clic su uno per selezionarlo sulla board.",
|
|
954
953
|
"taskCount": "{count} attivita' | {count} attivita'",
|
|
955
|
-
"
|
|
956
|
-
"
|
|
954
|
+
"tasksTitle": "Attivita'",
|
|
955
|
+
"allTasksTitle": "Tutte le attivita'",
|
|
956
|
+
"tasksHint": "Le attivita' all'interno di questo blocco. Fai clic su una per selezionarla sulla board.",
|
|
957
957
|
"addTask": "Aggiungi attivita'",
|
|
958
958
|
"noTasks": "Nessuna attivita' ancora. Aggiungine una per iniziare il lavoro.",
|
|
959
959
|
"servicesHint": "I servizi sono di lunga durata e non si completano. Il lavoro avviene nelle loro attivita' e nei loro moduli."
|
|
@@ -1658,8 +1658,6 @@
|
|
|
1658
1658
|
"lastIncorporatedRequirements": "Ultimi requisiti incorporati",
|
|
1659
1659
|
"priorDocHint": "Dalla revisione precedente. Usalo come base: modifica la descrizione sopra e reinvia.",
|
|
1660
1660
|
"bootstrapping": "Bootstrap in corso…",
|
|
1661
|
-
"importIssue": "Importa issue",
|
|
1662
|
-
"connectTracker": "Collega un tracker",
|
|
1663
1661
|
"spawnFromDocument": "Genera da documento",
|
|
1664
1662
|
"viewRequirements": "Visualizza requisiti",
|
|
1665
1663
|
"reRun": "Riesegui",
|
|
@@ -1670,8 +1668,7 @@
|
|
|
1670
1668
|
"title": "Archiviare questo servizio?",
|
|
1671
1669
|
"body": "\"{name}\" e le sue attività verranno nascosti dalla board. Puoi ripristinarlo in qualsiasi momento."
|
|
1672
1670
|
},
|
|
1673
|
-
"runBlocked": "Bloccato da una dipendenza non completata: {names} | Bloccato da {count} dipendenze non completate: {names}"
|
|
1674
|
-
"huntBugs": "Cerca bug"
|
|
1671
|
+
"runBlocked": "Bloccato da una dipendenza non completata: {names} | Bloccato da {count} dipendenze non completate: {names}"
|
|
1675
1672
|
}
|
|
1676
1673
|
},
|
|
1677
1674
|
"layout": {
|
|
@@ -2446,6 +2443,7 @@
|
|
|
2446
2443
|
"dragToResize": "Trascina per ridimensionare",
|
|
2447
2444
|
"addFirstTask": "Aggiungi la prima attività",
|
|
2448
2445
|
"createInitiativeTitle": "Crea iniziativa",
|
|
2446
|
+
"huntBugsTitle": "Cerca bug",
|
|
2449
2447
|
"accessDenied": {
|
|
2450
2448
|
"title": "Autorizzazione negata",
|
|
2451
2449
|
"hint": "Non hai accesso al repository che supporta questo servizio."
|
package/i18n/locales/ja.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "ドラッグしてサイズ変更",
|
|
395
395
|
"addFirstTask": "最初のタスクを追加",
|
|
396
396
|
"createInitiativeTitle": "イニシアチブを作成",
|
|
397
|
+
"huntBugsTitle": "バグをハント",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "アクセスが拒否されました",
|
|
399
400
|
"hint": "このサービスの基盤となるリポジトリにアクセスする権限がありません。"
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "このブロックのリポジトリは接続済みの GitHub リポジトリに含まれていないため、読み取れません。GitHub を接続または同期してから、もう一度お試しください。",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "モジュール ({count})",
|
|
635
|
+
"modulesTitle": "モジュール",
|
|
636
|
+
"modulesHint": "このサービス内のモジュール。クリックするとボード上で選択されます。",
|
|
637
637
|
"taskCount": "{count} 件のタスク | {count} 件のタスク",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "タスク",
|
|
639
|
+
"allTasksTitle": "すべてのタスク",
|
|
640
|
+
"tasksHint": "このブロック内のタスク。クリックするとボード上で選択されます。",
|
|
640
641
|
"addTask": "タスクを追加",
|
|
641
642
|
"noTasks": "タスクはまだありません。追加して作業を始めましょう。",
|
|
642
643
|
"servicesHint": "サービスは長期間存続し、完了しません。作業はそのタスクとモジュールで行われます。"
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "最後に取り込まれた要件",
|
|
1319
1320
|
"priorDocHint": "前回のレビューより。これをベースに、上の説明を編集して再送信してください。",
|
|
1320
1321
|
"bootstrapping": "ブートストラップ中…",
|
|
1321
|
-
"importIssue": "Issue をインポート",
|
|
1322
|
-
"connectTracker": "トラッカーを接続",
|
|
1323
1322
|
"spawnFromDocument": "ドキュメントから生成",
|
|
1324
1323
|
"viewRequirements": "要件を表示",
|
|
1325
1324
|
"reRun": "再実行",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "このサービスをアーカイブしますか?",
|
|
1354
1353
|
"body": "「{name}」とそのタスクはボードから非表示になります。いつでも復元できます。"
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "未完了の依存関係によってブロックされています: {names} | {count} 件の未完了の依存関係によってブロックされています: {names}"
|
|
1357
|
-
"huntBugs": "バグをハント"
|
|
1355
|
+
"runBlocked": "未完了の依存関係によってブロックされています: {names} | {count} 件の未完了の依存関係によってブロックされています: {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/i18n/locales/pl.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "Przeciągnij, aby zmienić rozmiar",
|
|
395
395
|
"addFirstTask": "Dodaj pierwsze zadanie",
|
|
396
396
|
"createInitiativeTitle": "Utworz inicjatywe",
|
|
397
|
+
"huntBugsTitle": "Poluj na błędy",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "Brak uprawnień",
|
|
399
400
|
"hint": "Nie masz dostępu do repozytorium powiązanego z tą usługą."
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "Repozytorium tego bloku nie znajduje się wśród połączonych repozytoriów GitHub, więc nie można go odczytać. Połącz lub zsynchronizuj GitHub dla tego repozytorium, a następnie spróbuj ponownie.",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "Moduły ({count})",
|
|
635
|
+
"modulesTitle": "Moduły",
|
|
636
|
+
"modulesHint": "Moduły wewnątrz tej usługi. Kliknij moduł, aby zaznaczyć go na tablicy.",
|
|
637
637
|
"taskCount": "{count} zadanie | {count} zadania | {count} zadań",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "Zadania",
|
|
639
|
+
"allTasksTitle": "Wszystkie zadania",
|
|
640
|
+
"tasksHint": "Zadania wewnątrz tego bloku. Kliknij zadanie, aby zaznaczyć je na tablicy.",
|
|
640
641
|
"addTask": "Dodaj zadanie",
|
|
641
642
|
"noTasks": "Brak zadań. Dodaj jedno, aby rozpocząć pracę.",
|
|
642
643
|
"servicesHint": "Usługi są długowieczne i nie kończą się. Praca odbywa się w ich zadaniach i modułach."
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "Ostatnie włączone wymagania",
|
|
1319
1320
|
"priorDocHint": "Z poprzedniej recenzji. Użyj go jako bazy: edytuj opis powyżej i prześlij ponownie.",
|
|
1320
1321
|
"bootstrapping": "Inicjowanie…",
|
|
1321
|
-
"importIssue": "Importuj zgłoszenie",
|
|
1322
|
-
"connectTracker": "Połącz tracker",
|
|
1323
1322
|
"spawnFromDocument": "Utwórz z dokumentu",
|
|
1324
1323
|
"viewRequirements": "Wyświetl wymagania",
|
|
1325
1324
|
"reRun": "Uruchom ponownie",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "Zarchiwizować tę usługę?",
|
|
1354
1353
|
"body": "„{name}” i jej zadania zostaną ukryte z tablicy. Możesz przywrócić usługę w dowolnej chwili."
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "Zablokowane przez niedokończoną zależność: {names} | Zablokowane przez {count} niedokończone zależności: {names} | Zablokowane przez {count} niedokończonych zależności: {names}"
|
|
1357
|
-
"huntBugs": "Poluj na błędy"
|
|
1355
|
+
"runBlocked": "Zablokowane przez niedokończoną zależność: {names} | Zablokowane przez {count} niedokończone zależności: {names} | Zablokowane przez {count} niedokończonych zależności: {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/i18n/locales/tr.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "Yeniden boyutlandırmak için sürükle",
|
|
395
395
|
"addFirstTask": "İlk görevi ekle",
|
|
396
396
|
"createInitiativeTitle": "Girisim olustur",
|
|
397
|
+
"huntBugsTitle": "Hata avla",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "İzin reddedildi",
|
|
399
400
|
"hint": "Bu hizmetin dayandığı depoya erişiminiz yok."
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "Bu bloğun deposu bağlı GitHub depoları arasında değil, bu yüzden okunamıyor. Bunun için GitHub'ı bağlayın veya eşitleyin, ardından yeniden deneyin.",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "Modüller ({count})",
|
|
635
|
+
"modulesTitle": "Modüller",
|
|
636
|
+
"modulesHint": "Bu servisin içindeki modüller. Panoda seçmek için birine tıklayın.",
|
|
637
637
|
"taskCount": "{count} görev | {count} görev",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "Görevler",
|
|
639
|
+
"allTasksTitle": "Tüm görevler",
|
|
640
|
+
"tasksHint": "Bu bloğun içindeki görevler. Panoda seçmek için birine tıklayın.",
|
|
640
641
|
"addTask": "Görev ekle",
|
|
641
642
|
"noTasks": "Henüz görev yok. Çalışmaya başlamak için bir tane ekleyin.",
|
|
642
643
|
"servicesHint": "Servisler uzun ömürlüdür ve tamamlanmaz. Çalışma, görevlerinde ve modüllerinde gerçekleşir."
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "Son dahil edilen gereksinimler",
|
|
1319
1320
|
"priorDocHint": "Önceki incelemeden. Bir temel olarak kullanın: yukarıdaki açıklamayı düzenleyip yeniden gönderin.",
|
|
1320
1321
|
"bootstrapping": "Önyükleniyor…",
|
|
1321
|
-
"importIssue": "Sorunu içe aktar",
|
|
1322
|
-
"connectTracker": "Bir izleyici bağla",
|
|
1323
1322
|
"spawnFromDocument": "Belgeden oluştur",
|
|
1324
1323
|
"viewRequirements": "Gereksinimleri Görüntüle",
|
|
1325
1324
|
"reRun": "Yeniden çalıştır",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "Bu hizmet arşivlensin mi?",
|
|
1354
1353
|
"body": "\"{name}\" ve görevleri panodan gizlenecek. İstediğin zaman geri yükleyebilirsin."
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "Tamamlanmamış bir bağımlılık tarafından engellendi: {names} | Tamamlanmamış {count} bağımlılık tarafından engellendi: {names}"
|
|
1357
|
-
"huntBugs": "Hata avla"
|
|
1355
|
+
"runBlocked": "Tamamlanmamış bir bağımlılık tarafından engellendi: {names} | Tamamlanmamış {count} bağımlılık tarafından engellendi: {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/i18n/locales/uk.json
CHANGED
|
@@ -394,6 +394,7 @@
|
|
|
394
394
|
"dragToResize": "Перетягніть, щоб змінити розмір",
|
|
395
395
|
"addFirstTask": "Додати перше завдання",
|
|
396
396
|
"createInitiativeTitle": "Створити ініціативу",
|
|
397
|
+
"huntBugsTitle": "Полювати на помилки",
|
|
397
398
|
"accessDenied": {
|
|
398
399
|
"title": "Доступ заборонено",
|
|
399
400
|
"hint": "У вас немає доступу до репозиторію, що стоїть за цією службою."
|
|
@@ -631,12 +632,12 @@
|
|
|
631
632
|
"inspector": {
|
|
632
633
|
"detectRepoUnresolved": "Репозиторій цього блоку відсутній серед підключених репозиторіїв GitHub, тому його не вдається прочитати. Підключіть або синхронізуйте GitHub для нього та повторіть спробу.",
|
|
633
634
|
"container": {
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"modules": "Модулі ({count})",
|
|
635
|
+
"modulesTitle": "Модулі",
|
|
636
|
+
"modulesHint": "Модулі всередині цього сервісу. Клацніть модуль, щоб вибрати його на дошці.",
|
|
637
637
|
"taskCount": "{count} завдання | {count} завдання | {count} завдань",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"tasksTitle": "Завдання",
|
|
639
|
+
"allTasksTitle": "Усі завдання",
|
|
640
|
+
"tasksHint": "Завдання всередині цього блока. Клацніть завдання, щоб вибрати його на дошці.",
|
|
640
641
|
"addTask": "Додати завдання",
|
|
641
642
|
"noTasks": "Завдань ще немає. Додайте одне, щоб почати роботу.",
|
|
642
643
|
"servicesHint": "Сервіси довготривалі й не завершуються. Робота відбувається в їхніх завданнях і модулях."
|
|
@@ -1318,8 +1319,6 @@
|
|
|
1318
1319
|
"lastIncorporatedRequirements": "Останні внесені вимоги",
|
|
1319
1320
|
"priorDocHint": "З попереднього огляду. Використайте його як основу: відредагуйте опис вище та надішліть повторно.",
|
|
1320
1321
|
"bootstrapping": "Ініціалізація…",
|
|
1321
|
-
"importIssue": "Імпортувати задачу",
|
|
1322
|
-
"connectTracker": "Підключити трекер",
|
|
1323
1322
|
"spawnFromDocument": "Створити з документа",
|
|
1324
1323
|
"viewRequirements": "Переглянути вимоги",
|
|
1325
1324
|
"reRun": "Перезапустити",
|
|
@@ -1353,8 +1352,7 @@
|
|
|
1353
1352
|
"title": "Заархівувати цей сервіс?",
|
|
1354
1353
|
"body": "«{name}» та його завдання буде приховано з дошки. Ви можете відновити його будь-коли."
|
|
1355
1354
|
},
|
|
1356
|
-
"runBlocked": "Заблоковано незавершеною залежністю: {names} | Заблоковано {count} незавершеними залежностями: {names} | Заблоковано {count} незавершеними залежностями: {names}"
|
|
1357
|
-
"huntBugs": "Полювати на помилки"
|
|
1355
|
+
"runBlocked": "Заблоковано незавершеною залежністю: {names} | Заблоковано {count} незавершеними залежностями: {names} | Заблоковано {count} незавершеними залежностями: {names}"
|
|
1358
1356
|
}
|
|
1359
1357
|
},
|
|
1360
1358
|
"observability": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.176.0",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|