@cat-factory/app 0.109.2 → 0.109.3
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/app/components/board/nodes/InitiativeCard.vue +1 -0
- package/app/components/initiative/InitiativeTrackerWindow.vue +97 -2
- package/app/utils/initiative.spec.ts +73 -0
- package/app/utils/initiative.ts +30 -4
- package/i18n/locales/de.json +7 -0
- package/i18n/locales/en.json +7 -0
- package/i18n/locales/es.json +7 -0
- package/i18n/locales/fr.json +7 -0
- package/i18n/locales/he.json +7 -0
- package/i18n/locales/it.json +7 -0
- package/i18n/locales/ja.json +7 -0
- package/i18n/locales/pl.json +7 -0
- package/i18n/locales/tr.json +7 -0
- package/i18n/locales/uk.json +7 -0
- package/package.json +1 -1
|
@@ -76,6 +76,7 @@ function onHandle(e: PointerEvent) {
|
|
|
76
76
|
</div>
|
|
77
77
|
<div
|
|
78
78
|
data-testid="initiative-card"
|
|
79
|
+
:data-status="status"
|
|
79
80
|
class="cursor-pointer rounded-b-lg border border-indigo-800/60 bg-indigo-950/40 p-3 transition hover:border-indigo-600"
|
|
80
81
|
:class="[selected ? 'ring-2 ring-indigo-400/60' : '', awaitingAnswers ? 'board-pulse' : '']"
|
|
81
82
|
@click.stop="select"
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
INITIATIVE_ITEM_STATUS_LABEL_KEYS,
|
|
17
17
|
INITIATIVE_STATUS_LABEL_KEYS,
|
|
18
18
|
initiativeProgress,
|
|
19
|
+
pendingCheckpointPhase,
|
|
19
20
|
} from '~/utils/initiative'
|
|
20
21
|
|
|
21
22
|
const board = useBoardStore()
|
|
@@ -42,6 +43,33 @@ const progressPct = computed(() =>
|
|
|
42
43
|
: 0,
|
|
43
44
|
)
|
|
44
45
|
|
|
46
|
+
// Phase checkpoints (D2): the phase whose completed checkpoint is awaiting review (recomputed
|
|
47
|
+
// live from the entity — mirrors the loop's `pendingCheckpoint`), and whether the initiative is
|
|
48
|
+
// currently PAUSED at it. The tracker is the review surface: it shows the phase's committed
|
|
49
|
+
// artifacts + PRs, so a resume/cancel decision is taken right here.
|
|
50
|
+
const checkpointPhase = computed(() =>
|
|
51
|
+
pendingCheckpointPhase(initiative.value?.phases, initiative.value?.items),
|
|
52
|
+
)
|
|
53
|
+
const pausedAtCheckpoint = computed(
|
|
54
|
+
() => initiative.value?.status === 'paused' && checkpointPhase.value !== null,
|
|
55
|
+
)
|
|
56
|
+
// The phase whose checkpoint is genuinely holding the initiative RIGHT NOW (paused for review) —
|
|
57
|
+
// only then does its badge read "awaiting review". A phase whose items just settled but whose
|
|
58
|
+
// pause hasn't landed yet stays an upcoming checkpoint, so the badge can't get ahead of the banner.
|
|
59
|
+
const awaitingReviewPhaseId = computed(() =>
|
|
60
|
+
pausedAtCheckpoint.value ? (checkpointPhase.value?.id ?? null) : null,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
/** Resume (GO) or cancel (NO_GO) an initiative paused at a checkpoint. */
|
|
64
|
+
async function checkpointControl(action: 'resume' | 'cancel') {
|
|
65
|
+
if (!blockId.value) return
|
|
66
|
+
try {
|
|
67
|
+
await initiatives.control(blockId.value, action)
|
|
68
|
+
} catch (error) {
|
|
69
|
+
reportError(error)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
45
73
|
const policyRules = computed(() => initiative.value?.policy?.rules ?? [])
|
|
46
74
|
function ruleAxes(rule: { minComplexity?: number; minRisk?: number; minImpact?: number }): string {
|
|
47
75
|
const axes = [
|
|
@@ -205,6 +233,48 @@ async function savePolicy() {
|
|
|
205
233
|
</div>
|
|
206
234
|
|
|
207
235
|
<template v-else>
|
|
236
|
+
<!-- Paused at a phase checkpoint (D2): a completed checkpoint phase is awaiting
|
|
237
|
+
review before the next phase spawns. Read the phase's artifacts/PRs below,
|
|
238
|
+
then resume (continue) or cancel (stop) the initiative right here. -->
|
|
239
|
+
<section
|
|
240
|
+
v-if="pausedAtCheckpoint"
|
|
241
|
+
class="mb-4 rounded-lg border border-amber-500/40 bg-amber-500/10 p-3.5"
|
|
242
|
+
data-testid="initiative-checkpoint-pause"
|
|
243
|
+
>
|
|
244
|
+
<div class="flex items-start gap-2.5">
|
|
245
|
+
<UIcon
|
|
246
|
+
name="i-lucide-pause-circle"
|
|
247
|
+
class="mt-0.5 h-4 w-4 shrink-0 text-amber-300"
|
|
248
|
+
/>
|
|
249
|
+
<div class="min-w-0 flex-1">
|
|
250
|
+
<h3 class="text-[13px] font-semibold text-amber-200">
|
|
251
|
+
{{ t('initiative.checkpoint.pausedTitle') }}
|
|
252
|
+
</h3>
|
|
253
|
+
<p class="mt-0.5 text-[12px] leading-relaxed text-amber-100/80">
|
|
254
|
+
{{ t('initiative.checkpoint.pausedBody', { phase: checkpointPhase!.title }) }}
|
|
255
|
+
</p>
|
|
256
|
+
<div class="mt-2.5 flex flex-wrap gap-2">
|
|
257
|
+
<button
|
|
258
|
+
class="rounded bg-indigo-600 px-2.5 py-1 text-[11px] font-medium text-white hover:bg-indigo-500 disabled:opacity-50"
|
|
259
|
+
:disabled="initiatives.controlling"
|
|
260
|
+
data-testid="initiative-checkpoint-resume"
|
|
261
|
+
@click="checkpointControl('resume')"
|
|
262
|
+
>
|
|
263
|
+
{{ t('initiative.inspector.resume') }}
|
|
264
|
+
</button>
|
|
265
|
+
<button
|
|
266
|
+
class="rounded border border-rose-500/50 px-2.5 py-1 text-[11px] font-medium text-rose-300 hover:bg-rose-500/10 disabled:opacity-50"
|
|
267
|
+
:disabled="initiatives.controlling"
|
|
268
|
+
data-testid="initiative-checkpoint-cancel"
|
|
269
|
+
@click="checkpointControl('cancel')"
|
|
270
|
+
>
|
|
271
|
+
{{ t('initiative.inspector.cancel') }}
|
|
272
|
+
</button>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
</section>
|
|
277
|
+
|
|
208
278
|
<!-- Goal & constraints -->
|
|
209
279
|
<section v-if="initiative.goal" class="mb-4">
|
|
210
280
|
<h3 class="mb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
@@ -249,8 +319,33 @@ async function savePolicy() {
|
|
|
249
319
|
|
|
250
320
|
<!-- Phases + items -->
|
|
251
321
|
<section v-for="phase in phases" :key="phase.id" class="mb-5">
|
|
252
|
-
<h3 class="mb-1 text-sm font-semibold text-slate-200">
|
|
253
|
-
{{ t('initiative.tracker.phase', { title: phase.title }) }}
|
|
322
|
+
<h3 class="mb-1 flex items-center gap-2 text-sm font-semibold text-slate-200">
|
|
323
|
+
<span>{{ t('initiative.tracker.phase', { title: phase.title }) }}</span>
|
|
324
|
+
<!-- Checkpoint annotation (D2): this phase pauses the initiative for human review
|
|
325
|
+
once its items settle. Cleared → already reviewed; the pending one → awaiting
|
|
326
|
+
review; otherwise an upcoming gate. -->
|
|
327
|
+
<UBadge
|
|
328
|
+
v-if="phase.checkpoint"
|
|
329
|
+
:color="
|
|
330
|
+
phase.checkpointClearedAt
|
|
331
|
+
? 'neutral'
|
|
332
|
+
: awaitingReviewPhaseId === phase.id
|
|
333
|
+
? 'warning'
|
|
334
|
+
: 'info'
|
|
335
|
+
"
|
|
336
|
+
variant="subtle"
|
|
337
|
+
size="sm"
|
|
338
|
+
:data-testid="`initiative-phase-checkpoint-${phase.id}`"
|
|
339
|
+
>
|
|
340
|
+
<UIcon name="i-lucide-flag" class="mr-1 h-3 w-3" />
|
|
341
|
+
{{
|
|
342
|
+
phase.checkpointClearedAt
|
|
343
|
+
? t('initiative.checkpoint.cleared')
|
|
344
|
+
: awaitingReviewPhaseId === phase.id
|
|
345
|
+
? t('initiative.checkpoint.awaiting')
|
|
346
|
+
: t('initiative.checkpoint.badge')
|
|
347
|
+
}}
|
|
348
|
+
</UBadge>
|
|
254
349
|
</h3>
|
|
255
350
|
<p v-if="phase.goal" class="mb-2 text-[12px] text-slate-400">{{ phase.goal }}</p>
|
|
256
351
|
<div class="overflow-x-auto rounded-lg border border-slate-800">
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { INITIATIVE_ITEM_TERMINAL_STATUSES } from '@cat-factory/contracts'
|
|
2
|
+
import { describe, it, expect } from 'vitest'
|
|
3
|
+
import type { InitiativeItem, InitiativePhase } from '~/types/domain'
|
|
4
|
+
import { pendingCheckpointPhase } from './initiative'
|
|
5
|
+
|
|
6
|
+
// `pendingCheckpointPhase` mirrors the backend `pendingCheckpoint` (orchestration
|
|
7
|
+
// `initiative.logic.ts`); these pin the same ordering/edge cases the loop pauses on, so the
|
|
8
|
+
// tracker window's live banner + phase badges can't drift from the engine's decision.
|
|
9
|
+
|
|
10
|
+
const phase = (over: Partial<InitiativePhase> & { id: string }): InitiativePhase => ({
|
|
11
|
+
title: over.id,
|
|
12
|
+
goal: '',
|
|
13
|
+
...over,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const item = (id: string, phaseId: string, status: InitiativeItem['status']): InitiativeItem => ({
|
|
17
|
+
id,
|
|
18
|
+
phaseId,
|
|
19
|
+
title: id,
|
|
20
|
+
description: '',
|
|
21
|
+
dependsOn: [],
|
|
22
|
+
status,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('pendingCheckpointPhase', () => {
|
|
26
|
+
it('returns null when no phase is flagged checkpoint', () => {
|
|
27
|
+
const phases = [phase({ id: 'p1' })]
|
|
28
|
+
const items = [item('a', 'p1', 'done')]
|
|
29
|
+
expect(pendingCheckpointPhase(phases, items)).toBeNull()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('returns a checkpoint phase once all its items settle (done/skipped)', () => {
|
|
33
|
+
const phases = [phase({ id: 'p1', checkpoint: true })]
|
|
34
|
+
const items = [item('a', 'p1', 'done'), item('b', 'p1', 'skipped')]
|
|
35
|
+
expect(pendingCheckpointPhase(phases, items)?.id).toBe('p1')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('does not fire while a checkpoint phase still holds a non-terminal item', () => {
|
|
39
|
+
const phases = [phase({ id: 'p1', checkpoint: true })]
|
|
40
|
+
expect(pendingCheckpointPhase(phases, [item('a', 'p1', 'in_progress')])).toBeNull()
|
|
41
|
+
// A BLOCKED item (a halted phase) is non-terminal too, so the checkpoint waits.
|
|
42
|
+
expect(pendingCheckpointPhase(phases, [item('a', 'p1', 'blocked')])).toBeNull()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('never re-fires a cleared checkpoint', () => {
|
|
46
|
+
const phases = [phase({ id: 'p1', checkpoint: true, checkpointClearedAt: 123 })]
|
|
47
|
+
expect(pendingCheckpointPhase(phases, [item('a', 'p1', 'done')])).toBeNull()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('skips an item-less checkpoint phase (nothing to review)', () => {
|
|
51
|
+
const phases = [phase({ id: 'p1', checkpoint: true })]
|
|
52
|
+
expect(pendingCheckpointPhase(phases, [])).toBeNull()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('returns the FIRST uncleared, completed checkpoint phase in declared order', () => {
|
|
56
|
+
const phases = [
|
|
57
|
+
phase({ id: 'p1', checkpoint: true, checkpointClearedAt: 1 }),
|
|
58
|
+
phase({ id: 'p2', checkpoint: true }),
|
|
59
|
+
phase({ id: 'p3', checkpoint: true }),
|
|
60
|
+
]
|
|
61
|
+
const items = [item('a', 'p1', 'done'), item('b', 'p2', 'done'), item('c', 'p3', 'done')]
|
|
62
|
+
// p1 already cleared → p2 is the pending one (even though p3 is also complete + uncleared).
|
|
63
|
+
expect(pendingCheckpointPhase(phases, items)?.id).toBe('p2')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// Drift guard: the checkpoint fires on EVERY status the backend counts as terminal, because the
|
|
67
|
+
// frontend gates on the SAME `INITIATIVE_ITEM_TERMINAL_STATUSES` the engine does — not a local
|
|
68
|
+
// copy. If the backend adds a terminal status, this fires the checkpoint on it automatically.
|
|
69
|
+
it.each([...INITIATIVE_ITEM_TERMINAL_STATUSES])('fires on the terminal status %s', (status) => {
|
|
70
|
+
const phases = [phase({ id: 'p1', checkpoint: true })]
|
|
71
|
+
expect(pendingCheckpointPhase(phases, [item('a', 'p1', status)])?.id).toBe('p1')
|
|
72
|
+
})
|
|
73
|
+
})
|
package/app/utils/initiative.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { INITIATIVE_ITEM_TERMINAL_STATUSES } from '@cat-factory/contracts'
|
|
1
2
|
import type {
|
|
2
3
|
InitiativeFollowUp,
|
|
3
4
|
InitiativeItem,
|
|
4
5
|
InitiativeItemStatus,
|
|
6
|
+
InitiativePhase,
|
|
5
7
|
InitiativePresetDescriptor,
|
|
6
8
|
InitiativePresetInputs,
|
|
7
9
|
InitiativeStatus,
|
|
@@ -98,13 +100,37 @@ export function defaultPresetInputs(
|
|
|
98
100
|
return inputs
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
/** Item statuses that count as settled — mirrors the backend terminal-status set. */
|
|
102
|
-
const SETTLED: ReadonlySet<InitiativeItemStatus> = new Set(['done', 'skipped'])
|
|
103
|
-
|
|
104
103
|
/** Completion rollup across an initiative's items, or null when there are none. */
|
|
105
104
|
export function initiativeProgress(
|
|
106
105
|
items: InitiativeItem[] | undefined,
|
|
107
106
|
): { settled: number; total: number } | null {
|
|
108
107
|
if (!items || items.length === 0) return null
|
|
109
|
-
return {
|
|
108
|
+
return {
|
|
109
|
+
settled: items.filter((i) => INITIATIVE_ITEM_TERMINAL_STATUSES.has(i.status)).length,
|
|
110
|
+
total: items.length,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The phase whose completed checkpoint (D2) is awaiting a human, or null. Mirrors the backend
|
|
116
|
+
* `pendingCheckpoint` (orchestration `initiative.logic.ts`) so the SPA recomputes the pending
|
|
117
|
+
* checkpoint from the live entity — the same shape the loop pauses on — rather than reading a
|
|
118
|
+
* derived flag off the wire: the FIRST phase, in declared order, flagged `checkpoint`, NOT yet
|
|
119
|
+
* cleared (`checkpointClearedAt`), holding at least one item, with every item terminal. Uses the
|
|
120
|
+
* canonical `INITIATIVE_ITEM_TERMINAL_STATUSES` (the SAME set the backend gates on) so the
|
|
121
|
+
* terminal-status membership cannot drift from the engine, not just the ordering. An open tracker
|
|
122
|
+
* window then follows the checkpoint as items settle without a reload.
|
|
123
|
+
*/
|
|
124
|
+
export function pendingCheckpointPhase(
|
|
125
|
+
phases: InitiativePhase[] | undefined,
|
|
126
|
+
items: InitiativeItem[] | undefined,
|
|
127
|
+
): InitiativePhase | null {
|
|
128
|
+
const all = items ?? []
|
|
129
|
+
for (const phase of phases ?? []) {
|
|
130
|
+
if (phase.checkpoint !== true || phase.checkpointClearedAt !== undefined) continue
|
|
131
|
+
const phaseItems = all.filter((i) => i.phaseId === phase.id)
|
|
132
|
+
if (phaseItems.length === 0) continue
|
|
133
|
+
if (phaseItems.every((i) => INITIATIVE_ITEM_TERMINAL_STATUSES.has(i.status))) return phase
|
|
134
|
+
}
|
|
135
|
+
return null
|
|
110
136
|
}
|
package/i18n/locales/de.json
CHANGED
|
@@ -3547,6 +3547,13 @@
|
|
|
3547
3547
|
"maxConcurrentField": "Max. gleichzeitige Aufgaben",
|
|
3548
3548
|
"defaultPipelineField": "Standard-Pipeline",
|
|
3549
3549
|
"failed": "Die Initiative konnte nicht aktualisiert werden"
|
|
3550
|
+
},
|
|
3551
|
+
"checkpoint": {
|
|
3552
|
+
"badge": "Checkpoint",
|
|
3553
|
+
"awaiting": "Warten auf Prüfung",
|
|
3554
|
+
"cleared": "Geprüft",
|
|
3555
|
+
"pausedTitle": "Pausiert zur Prüfung",
|
|
3556
|
+
"pausedBody": "Phase „{phase}\" ist abgeschlossen. Prüfe oben die committeten Artefakte und PRs, setze dann fort, um weiterzumachen, oder brich die Initiative ab."
|
|
3550
3557
|
}
|
|
3551
3558
|
},
|
|
3552
3559
|
"app": {
|
package/i18n/locales/en.json
CHANGED
|
@@ -4522,6 +4522,13 @@
|
|
|
4522
4522
|
"maxConcurrentField": "Max concurrent tasks",
|
|
4523
4523
|
"defaultPipelineField": "Default pipeline",
|
|
4524
4524
|
"failed": "Could not update the initiative"
|
|
4525
|
+
},
|
|
4526
|
+
"checkpoint": {
|
|
4527
|
+
"badge": "Checkpoint",
|
|
4528
|
+
"awaiting": "Awaiting review",
|
|
4529
|
+
"cleared": "Reviewed",
|
|
4530
|
+
"pausedTitle": "Paused for review",
|
|
4531
|
+
"pausedBody": "Phase \"{phase}\" is complete. Review its committed artifacts and PRs above, then resume to continue or cancel to stop the initiative."
|
|
4525
4532
|
}
|
|
4526
4533
|
},
|
|
4527
4534
|
"environmentWizard": {
|
package/i18n/locales/es.json
CHANGED
|
@@ -4393,6 +4393,13 @@
|
|
|
4393
4393
|
"maxConcurrentField": "Tareas concurrentes maximas",
|
|
4394
4394
|
"defaultPipelineField": "Pipeline por defecto",
|
|
4395
4395
|
"failed": "No se pudo actualizar la iniciativa"
|
|
4396
|
+
},
|
|
4397
|
+
"checkpoint": {
|
|
4398
|
+
"badge": "Punto de control",
|
|
4399
|
+
"awaiting": "Pendiente de revisión",
|
|
4400
|
+
"cleared": "Revisado",
|
|
4401
|
+
"pausedTitle": "En pausa para revisión",
|
|
4402
|
+
"pausedBody": "La fase «{phase}» está completa. Revisa arriba los artefactos y las PR confirmados y luego reanuda para continuar o cancela para detener la iniciativa."
|
|
4396
4403
|
}
|
|
4397
4404
|
},
|
|
4398
4405
|
"environmentWizard": {
|
package/i18n/locales/fr.json
CHANGED
|
@@ -4393,6 +4393,13 @@
|
|
|
4393
4393
|
"maxConcurrentField": "Taches simultanees maximales",
|
|
4394
4394
|
"defaultPipelineField": "Pipeline par defaut",
|
|
4395
4395
|
"failed": "Impossible de mettre a jour l'initiative"
|
|
4396
|
+
},
|
|
4397
|
+
"checkpoint": {
|
|
4398
|
+
"badge": "Point de contrôle",
|
|
4399
|
+
"awaiting": "En attente de revue",
|
|
4400
|
+
"cleared": "Revu",
|
|
4401
|
+
"pausedTitle": "En pause pour revue",
|
|
4402
|
+
"pausedBody": "La phase « {phase} » est terminée. Examinez ci-dessus les artefacts et les PR validés, puis reprenez pour continuer ou annulez pour arrêter l'initiative."
|
|
4396
4403
|
}
|
|
4397
4404
|
},
|
|
4398
4405
|
"environmentWizard": {
|
package/i18n/locales/he.json
CHANGED
|
@@ -4404,6 +4404,13 @@
|
|
|
4404
4404
|
"maxConcurrentField": "מקסימום משימות במקביל",
|
|
4405
4405
|
"defaultPipelineField": "צינור ברירת מחדל",
|
|
4406
4406
|
"failed": "לא ניתן לעדכן את היוזמה"
|
|
4407
|
+
},
|
|
4408
|
+
"checkpoint": {
|
|
4409
|
+
"badge": "נקודת ביקורת",
|
|
4410
|
+
"awaiting": "ממתין לבדיקה",
|
|
4411
|
+
"cleared": "נבדק",
|
|
4412
|
+
"pausedTitle": "מושהה לבדיקה",
|
|
4413
|
+
"pausedBody": "השלב \"{phase}\" הושלם. בדקו למעלה את הפריטים וה-PR שנשמרו, ואז חדשו כדי להמשיך או בטלו כדי לעצור את היוזמה."
|
|
4407
4414
|
}
|
|
4408
4415
|
},
|
|
4409
4416
|
"environmentWizard": {
|
package/i18n/locales/it.json
CHANGED
|
@@ -3547,6 +3547,13 @@
|
|
|
3547
3547
|
"maxConcurrentField": "Massimo di attivita concorrenti",
|
|
3548
3548
|
"defaultPipelineField": "Pipeline predefinita",
|
|
3549
3549
|
"failed": "Impossibile aggiornare l'iniziativa"
|
|
3550
|
+
},
|
|
3551
|
+
"checkpoint": {
|
|
3552
|
+
"badge": "Checkpoint",
|
|
3553
|
+
"awaiting": "In attesa di revisione",
|
|
3554
|
+
"cleared": "Revisionato",
|
|
3555
|
+
"pausedTitle": "In pausa per la revisione",
|
|
3556
|
+
"pausedBody": "La fase «{phase}» è completa. Rivedi sopra gli artefatti e le PR salvati, poi riprendi per continuare o annulla per interrompere l'iniziativa."
|
|
3550
3557
|
}
|
|
3551
3558
|
},
|
|
3552
3559
|
"app": {
|
package/i18n/locales/ja.json
CHANGED
|
@@ -4405,6 +4405,13 @@
|
|
|
4405
4405
|
"maxConcurrentField": "最大同時実行タスク数",
|
|
4406
4406
|
"defaultPipelineField": "既定のパイプライン",
|
|
4407
4407
|
"failed": "イニシアチブを更新できませんでした"
|
|
4408
|
+
},
|
|
4409
|
+
"checkpoint": {
|
|
4410
|
+
"badge": "チェックポイント",
|
|
4411
|
+
"awaiting": "レビュー待ち",
|
|
4412
|
+
"cleared": "レビュー済み",
|
|
4413
|
+
"pausedTitle": "レビューのため一時停止",
|
|
4414
|
+
"pausedBody": "フェーズ「{phase}」が完了しました。上記のコミット済み成果物と PR を確認し、続行する場合は再開、中止する場合はイニシアチブをキャンセルしてください。"
|
|
4408
4415
|
}
|
|
4409
4416
|
},
|
|
4410
4417
|
"environmentWizard": {
|
package/i18n/locales/pl.json
CHANGED
|
@@ -4393,6 +4393,13 @@
|
|
|
4393
4393
|
"maxConcurrentField": "Maks. rownoczesnych zadan",
|
|
4394
4394
|
"defaultPipelineField": "Domyslny pipeline",
|
|
4395
4395
|
"failed": "Nie udalo sie zaktualizowac inicjatywy"
|
|
4396
|
+
},
|
|
4397
|
+
"checkpoint": {
|
|
4398
|
+
"badge": "Punkt kontrolny",
|
|
4399
|
+
"awaiting": "Oczekuje na przegląd",
|
|
4400
|
+
"cleared": "Sprawdzono",
|
|
4401
|
+
"pausedTitle": "Wstrzymano do przeglądu",
|
|
4402
|
+
"pausedBody": "Faza „{phase}\" została ukończona. Przejrzyj powyżej zatwierdzone artefakty i PR-y, a następnie wznów, aby kontynuować, albo anuluj, aby zatrzymać inicjatywę."
|
|
4396
4403
|
}
|
|
4397
4404
|
},
|
|
4398
4405
|
"environmentWizard": {
|
package/i18n/locales/tr.json
CHANGED
|
@@ -4405,6 +4405,13 @@
|
|
|
4405
4405
|
"maxConcurrentField": "Maks. es zamanli gorev",
|
|
4406
4406
|
"defaultPipelineField": "Varsayilan pipeline",
|
|
4407
4407
|
"failed": "Girisim guncellenemedi"
|
|
4408
|
+
},
|
|
4409
|
+
"checkpoint": {
|
|
4410
|
+
"badge": "Kontrol noktası",
|
|
4411
|
+
"awaiting": "İnceleme bekliyor",
|
|
4412
|
+
"cleared": "İncelendi",
|
|
4413
|
+
"pausedTitle": "İnceleme için duraklatıldı",
|
|
4414
|
+
"pausedBody": "\"{phase}\" aşaması tamamlandı. Yukarıdaki işlenmiş yapıtları ve PR'leri inceleyin, ardından devam etmek için sürdürün ya da girişimi durdurmak için iptal edin."
|
|
4408
4415
|
}
|
|
4409
4416
|
},
|
|
4410
4417
|
"environmentWizard": {
|
package/i18n/locales/uk.json
CHANGED
|
@@ -4393,6 +4393,13 @@
|
|
|
4393
4393
|
"maxConcurrentField": "Макс. одночасних завдань",
|
|
4394
4394
|
"defaultPipelineField": "Типовий конвеєр",
|
|
4395
4395
|
"failed": "Не вдалося оновити ініціативу"
|
|
4396
|
+
},
|
|
4397
|
+
"checkpoint": {
|
|
4398
|
+
"badge": "Контрольна точка",
|
|
4399
|
+
"awaiting": "Очікує на перегляд",
|
|
4400
|
+
"cleared": "Переглянуто",
|
|
4401
|
+
"pausedTitle": "Призупинено для перегляду",
|
|
4402
|
+
"pausedBody": "Фазу «{phase}» завершено. Перегляньте вище закомічені артефакти та PR, потім відновіть, щоб продовжити, або скасуйте, щоб зупинити ініціативу."
|
|
4396
4403
|
}
|
|
4397
4404
|
},
|
|
4398
4405
|
"environmentWizard": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.109.
|
|
3
|
+
"version": "0.109.3",
|
|
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",
|