@cat-factory/app 0.280.0 → 0.280.2
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 +26 -1
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +142 -5
- package/app/components/board/AddTaskModal.vue +9 -0
- package/app/components/board/ReviewFrictionDialog.vue +35 -4
- package/app/components/board/TaskDependencyEdges.vue +26 -15
- package/app/components/board/nodes/TaskCard.vue +6 -1
- package/app/components/brainstorm/BrainstormWindow.vue +19 -1
- package/app/components/common/AsyncViewError.vue +30 -0
- package/app/components/common/ConfirmDialog.vue +26 -0
- package/app/components/docs/DocInterviewWindow.vue +40 -38
- package/app/components/followUp/FollowUpWindow.vue +32 -2
- package/app/components/forkDecision/ForkDecisionWindow.vue +44 -5
- package/app/components/gates/GateResultView.vue +14 -1
- package/app/components/humanTest/HumanTestWindow.vue +13 -1
- package/app/components/initiative/InitiativePlanDecision.vue +16 -3
- package/app/components/initiative/InitiativePlanReview.vue +16 -1
- package/app/components/initiative/InitiativePlanningWindow.vue +50 -52
- package/app/components/initiative/InitiativeTrackerWindow.vue +59 -1
- package/app/components/judge/JudgeResultView.vue +14 -1
- package/app/components/panels/AgentStepDetail.vue +651 -659
- package/app/components/panels/InspectorPanel.vue +6 -0
- package/app/components/panels/ResultWindowDrafts.logic.spec.ts +233 -0
- package/app/components/panels/inspector/ServiceTestSecrets.vue +17 -6
- package/app/components/pipeline/PipelineHealthModal.vue +55 -16
- package/app/components/prReview/PrReviewWindow.vue +23 -4
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +19 -1
- package/app/composables/useBoardActivity.ts +62 -6
- package/app/composables/useConfirm.spec.ts +62 -0
- package/app/composables/useConfirm.ts +6 -1
- package/app/composables/useInterviewDrafts.spec.ts +198 -0
- package/app/composables/useInterviewDrafts.ts +184 -0
- package/app/composables/useTaskExpansion.ts +10 -25
- package/app/docs/consumer-extensions.md +9 -0
- package/app/modular/result-views.ts +58 -21
- package/app/pages/index.vue +68 -64
- package/app/stores/binaryCandidates.ts +26 -3
- package/app/stores/ui/modals.ts +11 -0
- package/app/utils/asyncView.ts +24 -0
- package/app/utils/binaryCandidates.spec.ts +45 -1
- package/app/utils/binaryCandidates.ts +33 -0
- package/app/utils/blockRects.spec.ts +82 -0
- package/app/utils/blockRects.ts +61 -0
- package/app/utils/boardWakeGate.spec.ts +101 -0
- package/app/utils/boardWakeGate.ts +78 -0
- package/i18n/locales/de.json +25 -2
- package/i18n/locales/en.json +25 -2
- package/i18n/locales/es.json +25 -2
- package/i18n/locales/fr.json +25 -2
- package/i18n/locales/he.json +25 -2
- package/i18n/locales/it.json +25 -2
- package/i18n/locales/ja.json +25 -2
- package/i18n/locales/pl.json +25 -2
- package/i18n/locales/tr.json +25 -2
- package/i18n/locales/uk.json +25 -2
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One measurement pass's view of the board's rendered block cards.
|
|
3
|
+
*
|
|
4
|
+
* The two DOM-measuring drivers on the canvas (dependency edges, task expansion) resolve cards
|
|
5
|
+
* by `[data-block-id]`, which is what lets an arrow follow pan / zoom / drag for free. Done a
|
|
6
|
+
* card at a time it is also the drivers' whole cost: the edge overlay ran two
|
|
7
|
+
* `document.querySelector` scans plus two `getBoundingClientRect` reads PER LINK, so a task with
|
|
8
|
+
* five dependencies was found and measured five times in the same frame, and the expansion sweep
|
|
9
|
+
* ran one scan per candidate task.
|
|
10
|
+
*
|
|
11
|
+
* A pass builds this once instead: one `querySelectorAll` over the board, then map lookups, with
|
|
12
|
+
* each element measured at most once. First-in-document-order wins per id, matching what
|
|
13
|
+
* `document.querySelector` returned before, so a card also rendered outside the canvas (the focus
|
|
14
|
+
* view, the inspector) resolves to the same element it always did.
|
|
15
|
+
*
|
|
16
|
+
* The query itself is DEFERRED to the first lookup, so a pass that turns out to have nothing to
|
|
17
|
+
* resolve costs nothing. That is the common case rather than a corner: a board with no
|
|
18
|
+
* dependency, epic, frontend or connection link runs the edge overlay's pass on every awake
|
|
19
|
+
* frame of a pan and asks it for not one card, and the sweep it replaced did no DOM work there
|
|
20
|
+
* at all. Deferring keeps that property in the helper, where both drivers inherit it, rather
|
|
21
|
+
* than as a `links.length` guard at each call site that a fifth overlay would silently miss.
|
|
22
|
+
*
|
|
23
|
+
* It is still a SNAPSHOT: geometry read inside one frame must not change halfway through a pass,
|
|
24
|
+
* the query runs at most once whenever it runs, and the next pass builds a fresh one.
|
|
25
|
+
*/
|
|
26
|
+
export type BlockMeasurements = {
|
|
27
|
+
/** The rendered card for a block id, or null when nothing on the page renders it. */
|
|
28
|
+
elementFor: (id: string) => HTMLElement | null
|
|
29
|
+
/** The element's viewport rect, measured once per pass. */
|
|
30
|
+
rectFor: (el: Element) => DOMRect
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const BLOCK_ID_ATTRIBUTE = 'data-block-id'
|
|
34
|
+
|
|
35
|
+
export function measureBlocks(root: ParentNode = document): BlockMeasurements {
|
|
36
|
+
let elements: Map<string, HTMLElement> | null = null
|
|
37
|
+
|
|
38
|
+
function index(): Map<string, HTMLElement> {
|
|
39
|
+
if (elements) return elements
|
|
40
|
+
const found = new Map<string, HTMLElement>()
|
|
41
|
+
for (const el of root.querySelectorAll<HTMLElement>(`[${BLOCK_ID_ATTRIBUTE}]`)) {
|
|
42
|
+
const id = el.getAttribute(BLOCK_ID_ATTRIBUTE)
|
|
43
|
+
if (id && !found.has(id)) found.set(id, el)
|
|
44
|
+
}
|
|
45
|
+
elements = found
|
|
46
|
+
return found
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const rects = new WeakMap<Element, DOMRect>()
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
elementFor: (id) => index().get(id) ?? null,
|
|
53
|
+
rectFor(el) {
|
|
54
|
+
const cached = rects.get(el)
|
|
55
|
+
if (cached) return cached
|
|
56
|
+
const rect = el.getBoundingClientRect()
|
|
57
|
+
rects.set(el, rect)
|
|
58
|
+
return rect
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { createWakeGate, type WakeGateScheduler } from './boardWakeGate'
|
|
3
|
+
|
|
4
|
+
/** A hand-driven timer: `run()` fires the one scheduled callback, whatever its delay. */
|
|
5
|
+
function fakeScheduler() {
|
|
6
|
+
let nextHandle = 1
|
|
7
|
+
const pending = new Map<number, { run: () => void; delayMs: number }>()
|
|
8
|
+
const scheduler: WakeGateScheduler = {
|
|
9
|
+
schedule(run, delayMs) {
|
|
10
|
+
const handle = nextHandle++
|
|
11
|
+
pending.set(handle, { run, delayMs })
|
|
12
|
+
return handle
|
|
13
|
+
},
|
|
14
|
+
cancel(handle) {
|
|
15
|
+
pending.delete(handle)
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
scheduler,
|
|
20
|
+
pending: () => pending.size,
|
|
21
|
+
delays: () => [...pending.values()].map((p) => p.delayMs),
|
|
22
|
+
/** Fire every scheduled callback; anything they schedule waits for the next elapse. */
|
|
23
|
+
elapse() {
|
|
24
|
+
const due = [...pending.entries()]
|
|
25
|
+
pending.clear()
|
|
26
|
+
for (const [, { run }] of due) run()
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function gateWith(intervalMs?: number) {
|
|
32
|
+
const clock = fakeScheduler()
|
|
33
|
+
let wakes = 0
|
|
34
|
+
const gate = createWakeGate({
|
|
35
|
+
wake: () => {
|
|
36
|
+
wakes++
|
|
37
|
+
},
|
|
38
|
+
scheduler: clock.scheduler,
|
|
39
|
+
intervalMs,
|
|
40
|
+
})
|
|
41
|
+
return { clock, gate, wakes: () => wakes }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe('createWakeGate', () => {
|
|
45
|
+
it('wakes immediately on the first request', () => {
|
|
46
|
+
const { gate, wakes, clock } = gateWith()
|
|
47
|
+
gate.request()
|
|
48
|
+
expect(wakes()).toBe(1)
|
|
49
|
+
expect(clock.pending()).toBe(1)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('admits at most one wake per interval while requests keep arriving', () => {
|
|
53
|
+
const { gate, wakes, clock } = gateWith()
|
|
54
|
+
gate.request()
|
|
55
|
+
gate.request()
|
|
56
|
+
gate.request()
|
|
57
|
+
expect(wakes()).toBe(1)
|
|
58
|
+
|
|
59
|
+
// The suppressed requests are owed one wake, which lands when the interval ends.
|
|
60
|
+
clock.elapse()
|
|
61
|
+
expect(wakes()).toBe(2)
|
|
62
|
+
// ... and the wake it just admitted opens the next interval, so a continuing stream
|
|
63
|
+
// stays bounded rather than firing per request.
|
|
64
|
+
gate.request()
|
|
65
|
+
expect(wakes()).toBe(2)
|
|
66
|
+
clock.elapse()
|
|
67
|
+
expect(wakes()).toBe(3)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('goes idle after a quiet interval, so an isolated request is never delayed', () => {
|
|
71
|
+
const { gate, wakes, clock } = gateWith()
|
|
72
|
+
gate.request()
|
|
73
|
+
expect(wakes()).toBe(1)
|
|
74
|
+
|
|
75
|
+
clock.elapse()
|
|
76
|
+
// Nothing was owed, so the interval simply closed: no wake, nothing scheduled.
|
|
77
|
+
expect(wakes()).toBe(1)
|
|
78
|
+
expect(clock.pending()).toBe(0)
|
|
79
|
+
|
|
80
|
+
gate.request()
|
|
81
|
+
expect(wakes()).toBe(2)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('drops an owed wake when cancelled, and admits the next request immediately', () => {
|
|
85
|
+
const { gate, wakes, clock } = gateWith()
|
|
86
|
+
gate.request()
|
|
87
|
+
gate.request()
|
|
88
|
+
gate.cancel()
|
|
89
|
+
clock.elapse()
|
|
90
|
+
expect(wakes()).toBe(1)
|
|
91
|
+
|
|
92
|
+
gate.request()
|
|
93
|
+
expect(wakes()).toBe(2)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('schedules the interval the caller configured', () => {
|
|
97
|
+
const { gate, clock } = gateWith(40)
|
|
98
|
+
gate.request()
|
|
99
|
+
expect(clock.delays()).toEqual([40])
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate limiter for the wakes the board's activity pulse raises from RENDERS.
|
|
3
|
+
*
|
|
4
|
+
* The canvas MutationObserver is deliberately broad (see `useBoardActivity`): it watches the
|
|
5
|
+
* whole subtree for structure plus `style`/`class`, which is what lets it catch a geometry
|
|
6
|
+
* change without enumerating the causes. The cost is that every Vue-driven card re-render
|
|
7
|
+
* wakes the two DOM-measuring loops, and each wake carries a settle tail of several frames,
|
|
8
|
+
* so under a steady execution-event stream a busy board never parks them: exactly the board
|
|
9
|
+
* where the measurement is most expensive pays for it continuously.
|
|
10
|
+
*
|
|
11
|
+
* A render is not a gesture, though. A card whose badge changed may or may not have moved its
|
|
12
|
+
* neighbours, and either way nobody is watching that pixel land within one frame, so these
|
|
13
|
+
* wakes may be COALESCED where a pointer/wheel/camera wake may not. This gate fires the first
|
|
14
|
+
* one straight through (an isolated change still follows within a frame) and then admits at
|
|
15
|
+
* most one per interval for as long as the stream lasts.
|
|
16
|
+
*
|
|
17
|
+
* The scheduler is injected so the behaviour is testable without a timer clock.
|
|
18
|
+
*/
|
|
19
|
+
export type WakeGateScheduler = {
|
|
20
|
+
schedule: (run: () => void, delayMs: number) => number
|
|
21
|
+
cancel: (handle: number) => void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type WakeGate = {
|
|
25
|
+
/** Ask for a wake: immediate when the interval is clear, coalesced onto its end otherwise. */
|
|
26
|
+
request: () => void
|
|
27
|
+
/** Drop a coalesced wake that has not fired yet. Idempotent. */
|
|
28
|
+
cancel: () => void
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* How long one admitted render wake covers. The settle tail of a woken loop is ~4 frames
|
|
33
|
+
* (~66ms at 60Hz), so this leaves a busy board measuring for a fraction of each interval
|
|
34
|
+
* instead of every frame, while a change that really did move a card is on screen well inside
|
|
35
|
+
* the window a reader would notice.
|
|
36
|
+
*/
|
|
37
|
+
export const RENDER_WAKE_INTERVAL_MS = 250
|
|
38
|
+
|
|
39
|
+
export function createWakeGate(options: {
|
|
40
|
+
/** Raise the pulse. */
|
|
41
|
+
wake: () => void
|
|
42
|
+
scheduler: WakeGateScheduler
|
|
43
|
+
intervalMs?: number
|
|
44
|
+
}): WakeGate {
|
|
45
|
+
const { wake, scheduler } = options
|
|
46
|
+
const intervalMs = options.intervalMs ?? RENDER_WAKE_INTERVAL_MS
|
|
47
|
+
/** The open interval's handle, or null when no wake has been admitted recently. */
|
|
48
|
+
let window: number | null = null
|
|
49
|
+
/** Whether a request arrived while the interval was open and still owes a wake. */
|
|
50
|
+
let owed = false
|
|
51
|
+
|
|
52
|
+
function closeWindow() {
|
|
53
|
+
window = null
|
|
54
|
+
// A quiet interval simply ends: the next request is admitted immediately, so an isolated
|
|
55
|
+
// render never waits. Only a stream that kept asking re-opens the interval, which is what
|
|
56
|
+
// bounds it to one wake per interval for as long as it lasts.
|
|
57
|
+
if (!owed) return
|
|
58
|
+
owed = false
|
|
59
|
+
wake()
|
|
60
|
+
window = scheduler.schedule(closeWindow, intervalMs)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
request() {
|
|
65
|
+
if (window !== null) {
|
|
66
|
+
owed = true
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
wake()
|
|
70
|
+
window = scheduler.schedule(closeWindow, intervalMs)
|
|
71
|
+
},
|
|
72
|
+
cancel() {
|
|
73
|
+
if (window !== null) scheduler.cancel(window)
|
|
74
|
+
window = null
|
|
75
|
+
owed = false
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
package/i18n/locales/de.json
CHANGED
|
@@ -5689,6 +5689,11 @@
|
|
|
5689
5689
|
"preparingHint": "Die Planung liest zuerst das Repository, damit Sie nicht nach dem gefragt werden, was der Code beantworten kann. Fragen erscheinen hier, sobald das erledigt ist.",
|
|
5690
5690
|
"failed": "Der Planungslauf wurde abgebrochen",
|
|
5691
5691
|
"failedHint": "Er endete, bevor der Planer antworten konnte. Ihre Antworten sind gespeichert; führen Sie die Planung von der Initiative aus erneut aus.",
|
|
5692
|
+
"saveFailed": "Antwort konnte nicht gespeichert werden",
|
|
5693
|
+
"saveFailedCount": "{count} Ihrer Antworten konnten nicht gespeichert werden",
|
|
5694
|
+
"continueFailed": "Antworten konnten nicht gesendet werden",
|
|
5695
|
+
"proceedFailed": "Die Planung konnte nicht gestartet werden",
|
|
5696
|
+
"unanswerable": "Diese Frage hat keine ID, daher kann keine Antwort dazu gespeichert werden.",
|
|
5692
5697
|
"answerPlaceholder": "Ihre Antwort",
|
|
5693
5698
|
"hint": "Antworten senden lässt den Planer Rückfragen stellen; Jetzt planen entwirft den Plan mit den bisherigen Antworten.",
|
|
5694
5699
|
"unanswered": "Unbeantwortete Fragen: {count}",
|
|
@@ -6041,6 +6046,11 @@
|
|
|
6041
6046
|
"body": "Die Bereitstellungsintegration dieses Dienstes hat den Verbindungstest nicht bestanden: {detail}. Überprüfe ihren Endpunkt und ihre Anmeldedaten und teste die Verbindung erneut, um sie auszuführen.",
|
|
6042
6047
|
"action": "Infrastruktur konfigurieren"
|
|
6043
6048
|
}
|
|
6049
|
+
},
|
|
6050
|
+
"asyncView": {
|
|
6051
|
+
"title": "Diese Ansicht konnte nicht geladen werden",
|
|
6052
|
+
"body": "Ihr Code konnte nicht geladen werden. Meist wurde die Anwendung aktualisiert, während dieser Tab geöffnet war, sodass die angeforderten Dateien nicht mehr auf dem Server liegen. Laden Sie neu, um die aktuelle Version zu erhalten.",
|
|
6053
|
+
"reload": "Neu laden"
|
|
6044
6054
|
}
|
|
6045
6055
|
},
|
|
6046
6056
|
"slack": {
|
|
@@ -6189,7 +6199,12 @@
|
|
|
6189
6199
|
"status": {
|
|
6190
6200
|
"awaiting": "Warten auf Antworten",
|
|
6191
6201
|
"done": "Fertig"
|
|
6192
|
-
}
|
|
6202
|
+
},
|
|
6203
|
+
"saveFailedCount": "{count} Ihrer Antworten konnten nicht gespeichert werden",
|
|
6204
|
+
"continueFailed": "Antworten konnten nicht gesendet werden",
|
|
6205
|
+
"proceedFailed": "Der Entwurf konnte nicht gestartet werden",
|
|
6206
|
+
"unanswerable": "Diese Frage hat keine ID, daher kann keine Antwort dazu gespeichert werden.",
|
|
6207
|
+
"saveFailed": "Antwort konnte nicht gespeichert werden"
|
|
6193
6208
|
},
|
|
6194
6209
|
"gates": {
|
|
6195
6210
|
"subtitle": {
|
|
@@ -8030,6 +8045,14 @@
|
|
|
8030
8045
|
"undeclared": "Der Schritt hat seine Kandidaten nie deklariert, es gab also nichts zu vergleichen. Der Lauf ging weiter.",
|
|
8031
8046
|
"parseFailed": "Die Kandidaten-Deklaration des Schritts war nicht lesbar, es gab also nichts zu vergleichen. Der Lauf ging weiter.",
|
|
8032
8047
|
"noCandidates": "Der Schritt hat keine Kandidaten bereitgestellt, es gab also nichts zu vergleichen. Der Lauf ging weiter."
|
|
8033
|
-
}
|
|
8048
|
+
},
|
|
8049
|
+
"noRun": {
|
|
8050
|
+
"title": "Kein Lauf zum Auslesen",
|
|
8051
|
+
"hint": "Dieser Vergleich ist an einen Pipeline-Lauf gebunden. Öffnen Sie ihn über die Karte oder die Zeitleiste des erzeugenden Schritts, damit die Kandidaten geladen werden können."
|
|
8052
|
+
},
|
|
8053
|
+
"empty": {
|
|
8054
|
+
"title": "Nichts zu vergleichen"
|
|
8055
|
+
},
|
|
8056
|
+
"loadFailed": "Die erzeugten Kandidaten konnten nicht geladen werden."
|
|
8034
8057
|
}
|
|
8035
8058
|
}
|
package/i18n/locales/en.json
CHANGED
|
@@ -847,6 +847,11 @@
|
|
|
847
847
|
},
|
|
848
848
|
"action": "Configure infrastructure"
|
|
849
849
|
}
|
|
850
|
+
},
|
|
851
|
+
"asyncView": {
|
|
852
|
+
"title": "This view could not be loaded",
|
|
853
|
+
"body": "Its code failed to load. That usually means the app was updated while this tab was open, so the files this page is asking for are no longer on the server. Reload to pick up the current version.",
|
|
854
|
+
"reload": "Reload"
|
|
850
855
|
}
|
|
851
856
|
},
|
|
852
857
|
"personalSubscriptions": {
|
|
@@ -4763,7 +4768,12 @@
|
|
|
4763
4768
|
"status": {
|
|
4764
4769
|
"awaiting": "Awaiting answers",
|
|
4765
4770
|
"done": "Done"
|
|
4766
|
-
}
|
|
4771
|
+
},
|
|
4772
|
+
"saveFailedCount": "Could not save {count} of your answers",
|
|
4773
|
+
"continueFailed": "Could not submit your answers",
|
|
4774
|
+
"proceedFailed": "Could not start the draft",
|
|
4775
|
+
"unanswerable": "This question carries no id, so an answer cannot be recorded against it.",
|
|
4776
|
+
"saveFailed": "Could not save your answer"
|
|
4767
4777
|
},
|
|
4768
4778
|
"documents": {
|
|
4769
4779
|
"picker": {
|
|
@@ -7340,6 +7350,11 @@
|
|
|
7340
7350
|
"preparingHint": "Planning reads the repository first, so you are not asked what the code can answer. Questions appear here once that is done.",
|
|
7341
7351
|
"failed": "The planning run stopped",
|
|
7342
7352
|
"failedHint": "It ended before the planner could answer. Your answers are saved; re-run planning from the initiative to try again.",
|
|
7353
|
+
"saveFailed": "Could not save your answer",
|
|
7354
|
+
"saveFailedCount": "Could not save {count} of your answers",
|
|
7355
|
+
"continueFailed": "Could not submit your answers",
|
|
7356
|
+
"proceedFailed": "Could not start planning",
|
|
7357
|
+
"unanswerable": "This question carries no id, so an answer cannot be recorded against it.",
|
|
7343
7358
|
"answerPlaceholder": "Your answer",
|
|
7344
7359
|
"hint": "Submit answers lets the planner ask follow-ups; Plan now drafts the plan with the answers so far.",
|
|
7345
7360
|
"unanswered": "Unanswered questions: {count}",
|
|
@@ -8319,6 +8334,14 @@
|
|
|
8319
8334
|
"undeclared": "The step never declared its candidates, so there was nothing to compare. The run continued.",
|
|
8320
8335
|
"parseFailed": "The step’s candidate declaration could not be read, so there was nothing to compare. The run continued.",
|
|
8321
8336
|
"noCandidates": "The step staged no candidates, so there was nothing to compare. The run continued."
|
|
8322
|
-
}
|
|
8337
|
+
},
|
|
8338
|
+
"noRun": {
|
|
8339
|
+
"title": "No run to read",
|
|
8340
|
+
"hint": "This comparison is keyed to a pipeline run. Open it from the generating step's card or timeline so its candidates can be loaded."
|
|
8341
|
+
},
|
|
8342
|
+
"empty": {
|
|
8343
|
+
"title": "Nothing to compare"
|
|
8344
|
+
},
|
|
8345
|
+
"loadFailed": "Could not load the generated candidates."
|
|
8323
8346
|
}
|
|
8324
8347
|
}
|
package/i18n/locales/es.json
CHANGED
|
@@ -757,6 +757,11 @@
|
|
|
757
757
|
"body": "La integración de despliegue de este servicio falló la prueba de conexión: {detail}. Revisa su endpoint y credenciales y vuelve a probar la conexión para ejecutarla.",
|
|
758
758
|
"action": "Configurar infraestructura"
|
|
759
759
|
}
|
|
760
|
+
},
|
|
761
|
+
"asyncView": {
|
|
762
|
+
"title": "No se pudo cargar esta vista",
|
|
763
|
+
"body": "No se pudo cargar su código. Normalmente significa que la aplicación se actualizó mientras esta pestaña estaba abierta, así que los archivos que pide esta página ya no están en el servidor. Vuelve a cargar para obtener la versión actual.",
|
|
764
|
+
"reload": "Volver a cargar"
|
|
760
765
|
}
|
|
761
766
|
},
|
|
762
767
|
"personalSubscriptions": {
|
|
@@ -4602,7 +4607,12 @@
|
|
|
4602
4607
|
"status": {
|
|
4603
4608
|
"awaiting": "Esperando respuestas",
|
|
4604
4609
|
"done": "Hecho"
|
|
4605
|
-
}
|
|
4610
|
+
},
|
|
4611
|
+
"saveFailedCount": "No se pudieron guardar {count} de tus respuestas",
|
|
4612
|
+
"continueFailed": "No se pudieron enviar tus respuestas",
|
|
4613
|
+
"proceedFailed": "No se pudo iniciar el borrador",
|
|
4614
|
+
"unanswerable": "Esta pregunta no tiene id, así que no se puede registrar ninguna respuesta para ella.",
|
|
4615
|
+
"saveFailed": "No se pudo guardar tu respuesta"
|
|
4606
4616
|
},
|
|
4607
4617
|
"documents": {
|
|
4608
4618
|
"picker": {
|
|
@@ -7081,6 +7091,11 @@
|
|
|
7081
7091
|
"preparingHint": "La planificacion lee primero el repositorio para no preguntarte lo que el codigo ya responde. Las preguntas apareceran aqui cuando termine.",
|
|
7082
7092
|
"failed": "La ejecucion de planificacion se detuvo",
|
|
7083
7093
|
"failedHint": "Termino antes de que el planificador pudiera responder. Tus respuestas estan guardadas; vuelve a ejecutar la planificacion desde la iniciativa.",
|
|
7094
|
+
"saveFailed": "No se pudo guardar tu respuesta",
|
|
7095
|
+
"saveFailedCount": "No se pudieron guardar {count} de tus respuestas",
|
|
7096
|
+
"continueFailed": "No se pudieron enviar tus respuestas",
|
|
7097
|
+
"proceedFailed": "No se pudo iniciar la planificación",
|
|
7098
|
+
"unanswerable": "Esta pregunta no tiene id, así que no se puede registrar ninguna respuesta para ella.",
|
|
7084
7099
|
"answerPlaceholder": "Tu respuesta",
|
|
7085
7100
|
"hint": "Enviar respuestas permite al planificador hacer mas preguntas; Planificar ahora redacta el plan con las respuestas actuales.",
|
|
7086
7101
|
"unanswered": "Preguntas sin responder: {count}",
|
|
@@ -8030,6 +8045,14 @@
|
|
|
8030
8045
|
"undeclared": "El paso nunca declaró sus candidatos, así que no había nada que comparar. La ejecución continuó.",
|
|
8031
8046
|
"parseFailed": "No se pudo leer la declaración de candidatos del paso, así que no había nada que comparar. La ejecución continuó.",
|
|
8032
8047
|
"noCandidates": "El paso no preparó ningún candidato, así que no había nada que comparar. La ejecución continuó."
|
|
8033
|
-
}
|
|
8048
|
+
},
|
|
8049
|
+
"noRun": {
|
|
8050
|
+
"title": "No hay ninguna ejecución que leer",
|
|
8051
|
+
"hint": "Esta comparación está vinculada a una ejecución de la canalización. Ábrela desde la tarjeta o la cronología del paso que la generó para que se puedan cargar sus candidatos."
|
|
8052
|
+
},
|
|
8053
|
+
"empty": {
|
|
8054
|
+
"title": "Nada que comparar"
|
|
8055
|
+
},
|
|
8056
|
+
"loadFailed": "No se pudieron cargar los candidatos generados."
|
|
8034
8057
|
}
|
|
8035
8058
|
}
|
package/i18n/locales/fr.json
CHANGED
|
@@ -757,6 +757,11 @@
|
|
|
757
757
|
"body": "L’intégration de déploiement de ce service a échoué au test de connexion : {detail}. Vérifiez son point de terminaison et ses identifiants, puis retestez la connexion pour l’exécuter.",
|
|
758
758
|
"action": "Configurer l’infrastructure"
|
|
759
759
|
}
|
|
760
|
+
},
|
|
761
|
+
"asyncView": {
|
|
762
|
+
"title": "Cette vue n'a pas pu être chargée",
|
|
763
|
+
"body": "Son code n'a pas pu être chargé. Cela signifie généralement que l'application a été mise à jour pendant que cet onglet était ouvert : les fichiers demandés par cette page ne sont plus sur le serveur. Rechargez pour obtenir la version actuelle.",
|
|
764
|
+
"reload": "Recharger"
|
|
760
765
|
}
|
|
761
766
|
},
|
|
762
767
|
"personalSubscriptions": {
|
|
@@ -4602,7 +4607,12 @@
|
|
|
4602
4607
|
"status": {
|
|
4603
4608
|
"awaiting": "En attente de réponses",
|
|
4604
4609
|
"done": "Terminé"
|
|
4605
|
-
}
|
|
4610
|
+
},
|
|
4611
|
+
"saveFailedCount": "Impossible d’enregistrer {count} de vos réponses",
|
|
4612
|
+
"continueFailed": "Impossible d’envoyer vos réponses",
|
|
4613
|
+
"proceedFailed": "Impossible de lancer la rédaction",
|
|
4614
|
+
"unanswerable": "Cette question n’a pas d’identifiant : aucune réponse ne peut y être enregistrée.",
|
|
4615
|
+
"saveFailed": "Impossible d’enregistrer votre réponse"
|
|
4606
4616
|
},
|
|
4607
4617
|
"documents": {
|
|
4608
4618
|
"picker": {
|
|
@@ -7081,6 +7091,11 @@
|
|
|
7081
7091
|
"preparingHint": "La planification lit d'abord le depot afin de ne pas vous demander ce que le code peut repondre. Les questions apparaitront ici une fois termine.",
|
|
7082
7092
|
"failed": "L'execution de planification s'est arretee",
|
|
7083
7093
|
"failedHint": "Elle s'est terminee avant que le planificateur puisse repondre. Vos reponses sont enregistrees ; relancez la planification depuis l'initiative.",
|
|
7094
|
+
"saveFailed": "Impossible d’enregistrer votre réponse",
|
|
7095
|
+
"saveFailedCount": "Impossible d’enregistrer {count} de vos réponses",
|
|
7096
|
+
"continueFailed": "Impossible d’envoyer vos réponses",
|
|
7097
|
+
"proceedFailed": "Impossible de lancer la planification",
|
|
7098
|
+
"unanswerable": "Cette question n’a pas d’identifiant : aucune réponse ne peut y être enregistrée.",
|
|
7084
7099
|
"answerPlaceholder": "Votre reponse",
|
|
7085
7100
|
"hint": "Envoyer les reponses permet au planificateur de poser des questions complementaires ; Planifier maintenant redige le plan avec les reponses actuelles.",
|
|
7086
7101
|
"unanswered": "Questions sans reponse : {count}",
|
|
@@ -8030,6 +8045,14 @@
|
|
|
8030
8045
|
"undeclared": "L’étape n’a jamais déclaré ses candidats, il n’y avait donc rien à comparer. L’exécution a continué.",
|
|
8031
8046
|
"parseFailed": "La déclaration de candidats de l’étape était illisible, il n’y avait donc rien à comparer. L’exécution a continué.",
|
|
8032
8047
|
"noCandidates": "L’étape n’a préparé aucun candidat, il n’y avait donc rien à comparer. L’exécution a continué."
|
|
8033
|
-
}
|
|
8048
|
+
},
|
|
8049
|
+
"noRun": {
|
|
8050
|
+
"title": "Aucune exécution à lire",
|
|
8051
|
+
"hint": "Cette comparaison est liée à une exécution de pipeline. Ouvrez-la depuis la carte ou la chronologie de l’étape qui l’a produite pour que ses candidats puissent être chargés."
|
|
8052
|
+
},
|
|
8053
|
+
"empty": {
|
|
8054
|
+
"title": "Rien à comparer"
|
|
8055
|
+
},
|
|
8056
|
+
"loadFailed": "Impossible de charger les candidats générés."
|
|
8034
8057
|
}
|
|
8035
8058
|
}
|
package/i18n/locales/he.json
CHANGED
|
@@ -757,6 +757,11 @@
|
|
|
757
757
|
"body": "אינטגרציית הפריסה של שירות זה נכשלה בבדיקת החיבור: {detail}. בדוק את נקודת הקצה והאישורים שלה, ואז בדוק שוב את החיבור כדי להריץ אותו.",
|
|
758
758
|
"action": "הגדר תשתית"
|
|
759
759
|
}
|
|
760
|
+
},
|
|
761
|
+
"asyncView": {
|
|
762
|
+
"title": "לא ניתן היה לטעון את התצוגה הזו",
|
|
763
|
+
"body": "טעינת הקוד שלה נכשלה. בדרך כלל המשמעות היא שהאפליקציה עודכנה בזמן שהלשונית הזו הייתה פתוחה, ולכן הקבצים שהדף מבקש כבר אינם בשרת. רעננו כדי לקבל את הגרסה הנוכחית.",
|
|
764
|
+
"reload": "רענון"
|
|
760
765
|
}
|
|
761
766
|
},
|
|
762
767
|
"personalSubscriptions": {
|
|
@@ -4602,7 +4607,12 @@
|
|
|
4602
4607
|
"status": {
|
|
4603
4608
|
"awaiting": "ממתין לתשובות",
|
|
4604
4609
|
"done": "הושלם"
|
|
4605
|
-
}
|
|
4610
|
+
},
|
|
4611
|
+
"saveFailedCount": "לא ניתן היה לשמור {count} מהתשובות שלך",
|
|
4612
|
+
"continueFailed": "לא ניתן היה לשלוח את התשובות שלך",
|
|
4613
|
+
"proceedFailed": "לא ניתן היה להתחיל את הטיוטה",
|
|
4614
|
+
"unanswerable": "לשאלה הזאת אין מזהה, ולכן לא ניתן לרשום עבורה תשובה.",
|
|
4615
|
+
"saveFailed": "לא ניתן היה לשמור את התשובה שלך"
|
|
4606
4616
|
},
|
|
4607
4617
|
"documents": {
|
|
4608
4618
|
"picker": {
|
|
@@ -7081,6 +7091,11 @@
|
|
|
7081
7091
|
"preparingHint": "התכנון קורא תחילה את המאגר כדי שלא תישאל על מה שהקוד יכול לענות. השאלות יופיעו כאן בסיום.",
|
|
7082
7092
|
"failed": "הרצת התכנון נעצרה",
|
|
7083
7093
|
"failedHint": "היא הסתיימה לפני שהמתכנן הספיק להשיב. התשובות שלך נשמרו; הרץ תכנון מחדש מהיוזמה.",
|
|
7094
|
+
"saveFailed": "לא ניתן היה לשמור את התשובה שלך",
|
|
7095
|
+
"saveFailedCount": "לא ניתן היה לשמור {count} מהתשובות שלך",
|
|
7096
|
+
"continueFailed": "לא ניתן היה לשלוח את התשובות שלך",
|
|
7097
|
+
"proceedFailed": "לא ניתן היה להתחיל את התכנון",
|
|
7098
|
+
"unanswerable": "לשאלה הזאת אין מזהה, ולכן לא ניתן לרשום עבורה תשובה.",
|
|
7084
7099
|
"answerPlaceholder": "התשובה שלך",
|
|
7085
7100
|
"hint": "שליחת תשובות מאפשרת למתכנן לשאול שאלות המשך; תכנן עכשיו מנסח את התוכנית עם התשובות עד כה.",
|
|
7086
7101
|
"unanswered": "שאלות ללא מענה: {count}",
|
|
@@ -8030,6 +8045,14 @@
|
|
|
8030
8045
|
"undeclared": "השלב מעולם לא הצהיר על מועמדים, ולכן לא היה מה להשוות. הריצה המשיכה.",
|
|
8031
8046
|
"parseFailed": "לא ניתן היה לקרוא את הצהרת המועמדים של השלב, ולכן לא היה מה להשוות. הריצה המשיכה.",
|
|
8032
8047
|
"noCandidates": "השלב לא הכין אף מועמד, ולכן לא היה מה להשוות. הריצה המשיכה."
|
|
8033
|
-
}
|
|
8048
|
+
},
|
|
8049
|
+
"noRun": {
|
|
8050
|
+
"title": "אין הרצה לקריאה",
|
|
8051
|
+
"hint": "ההשוואה הזאת משויכת להרצה של הפייפליין. פתחו אותה מהכרטיס או מציר הזמן של השלב שיצר אותה, כדי שניתן יהיה לטעון את המועמדים."
|
|
8052
|
+
},
|
|
8053
|
+
"empty": {
|
|
8054
|
+
"title": "אין מה להשוות"
|
|
8055
|
+
},
|
|
8056
|
+
"loadFailed": "לא ניתן היה לטעון את המועמדים שנוצרו."
|
|
8034
8057
|
}
|
|
8035
8058
|
}
|
package/i18n/locales/it.json
CHANGED
|
@@ -5689,6 +5689,11 @@
|
|
|
5689
5689
|
"preparingHint": "La pianificazione legge prima il repository, cosi non ti viene chiesto cio che il codice puo rispondere. Le domande compariranno qui al termine.",
|
|
5690
5690
|
"failed": "L'esecuzione della pianificazione si e interrotta",
|
|
5691
5691
|
"failedHint": "Si e conclusa prima che il pianificatore potesse rispondere. Le tue risposte sono salvate; riesegui la pianificazione dall'iniziativa.",
|
|
5692
|
+
"saveFailed": "Impossibile salvare la tua risposta",
|
|
5693
|
+
"saveFailedCount": "Impossibile salvare {count} delle tue risposte",
|
|
5694
|
+
"continueFailed": "Impossibile inviare le tue risposte",
|
|
5695
|
+
"proceedFailed": "Impossibile avviare la pianificazione",
|
|
5696
|
+
"unanswerable": "Questa domanda non ha un id, quindi non è possibile registrarvi una risposta.",
|
|
5692
5697
|
"answerPlaceholder": "La tua risposta",
|
|
5693
5698
|
"hint": "Invia risposte consente al pianificatore di porre domande di follow-up; Pianifica ora redige il piano con le risposte fornite finora.",
|
|
5694
5699
|
"unanswered": "Domande senza risposta: {count}",
|
|
@@ -6041,6 +6046,11 @@
|
|
|
6041
6046
|
"body": "L’integrazione di deployment di questo servizio non ha superato il test di connessione: {detail}. Controlla il suo endpoint e le credenziali, poi riprova la connessione per eseguirla.",
|
|
6042
6047
|
"action": "Configura infrastruttura"
|
|
6043
6048
|
}
|
|
6049
|
+
},
|
|
6050
|
+
"asyncView": {
|
|
6051
|
+
"title": "Impossibile caricare questa vista",
|
|
6052
|
+
"body": "Il suo codice non è stato caricato. Di solito significa che l'applicazione è stata aggiornata mentre questa scheda era aperta, quindi i file richiesti da questa pagina non sono più sul server. Ricarica per ottenere la versione attuale.",
|
|
6053
|
+
"reload": "Ricarica"
|
|
6044
6054
|
}
|
|
6045
6055
|
},
|
|
6046
6056
|
"slack": {
|
|
@@ -6189,7 +6199,12 @@
|
|
|
6189
6199
|
"status": {
|
|
6190
6200
|
"awaiting": "In attesa di risposte",
|
|
6191
6201
|
"done": "Fatto"
|
|
6192
|
-
}
|
|
6202
|
+
},
|
|
6203
|
+
"saveFailedCount": "Impossibile salvare {count} delle tue risposte",
|
|
6204
|
+
"continueFailed": "Impossibile inviare le tue risposte",
|
|
6205
|
+
"proceedFailed": "Impossibile avviare la bozza",
|
|
6206
|
+
"unanswerable": "Questa domanda non ha un id, quindi non è possibile registrarvi una risposta.",
|
|
6207
|
+
"saveFailed": "Impossibile salvare la tua risposta"
|
|
6193
6208
|
},
|
|
6194
6209
|
"gates": {
|
|
6195
6210
|
"subtitle": {
|
|
@@ -8030,6 +8045,14 @@
|
|
|
8030
8045
|
"undeclared": "Il passo non ha mai dichiarato i suoi candidati, quindi non c’era nulla da confrontare. L’esecuzione è proseguita.",
|
|
8031
8046
|
"parseFailed": "La dichiarazione dei candidati del passo non era leggibile, quindi non c’era nulla da confrontare. L’esecuzione è proseguita.",
|
|
8032
8047
|
"noCandidates": "Il passo non ha preparato alcun candidato, quindi non c’era nulla da confrontare. L’esecuzione è proseguita."
|
|
8033
|
-
}
|
|
8048
|
+
},
|
|
8049
|
+
"noRun": {
|
|
8050
|
+
"title": "Nessuna esecuzione da leggere",
|
|
8051
|
+
"hint": "Questo confronto è legato a un’esecuzione della pipeline. Aprilo dalla scheda o dalla cronologia del passo che l’ha generato, così i suoi candidati possono essere caricati."
|
|
8052
|
+
},
|
|
8053
|
+
"empty": {
|
|
8054
|
+
"title": "Nulla da confrontare"
|
|
8055
|
+
},
|
|
8056
|
+
"loadFailed": "Impossibile caricare i candidati generati."
|
|
8034
8057
|
}
|
|
8035
8058
|
}
|
package/i18n/locales/ja.json
CHANGED
|
@@ -757,6 +757,11 @@
|
|
|
757
757
|
"body": "このサービスのデプロイ連携が接続テストに失敗しました: {detail}。エンドポイントと認証情報を確認し、接続を再テストしてから実行してください。",
|
|
758
758
|
"action": "インフラを設定"
|
|
759
759
|
}
|
|
760
|
+
},
|
|
761
|
+
"asyncView": {
|
|
762
|
+
"title": "このビューを読み込めませんでした",
|
|
763
|
+
"body": "コードの読み込みに失敗しました。多くの場合、このタブを開いたままアプリが更新され、このページが要求しているファイルがサーバー上に存在しなくなったことが原因です。再読み込みして最新版を取得してください。",
|
|
764
|
+
"reload": "再読み込み"
|
|
760
765
|
}
|
|
761
766
|
},
|
|
762
767
|
"personalSubscriptions": {
|
|
@@ -4602,7 +4607,12 @@
|
|
|
4602
4607
|
"status": {
|
|
4603
4608
|
"awaiting": "回答待ち",
|
|
4604
4609
|
"done": "完了"
|
|
4605
|
-
}
|
|
4610
|
+
},
|
|
4611
|
+
"saveFailedCount": "回答のうち {count} 件を保存できませんでした",
|
|
4612
|
+
"continueFailed": "回答を送信できませんでした",
|
|
4613
|
+
"proceedFailed": "下書きを開始できませんでした",
|
|
4614
|
+
"unanswerable": "この質問には ID がないため、回答を記録できません。",
|
|
4615
|
+
"saveFailed": "回答を保存できませんでした"
|
|
4606
4616
|
},
|
|
4607
4617
|
"documents": {
|
|
4608
4618
|
"picker": {
|
|
@@ -7081,6 +7091,11 @@
|
|
|
7081
7091
|
"preparingHint": "計画はまずリポジトリを読み取るため、コードから分かることは質問されません。完了すると質問がここに表示されます。",
|
|
7082
7092
|
"failed": "計画の実行が停止しました",
|
|
7083
7093
|
"failedHint": "プランナーが応答する前に終了しました。回答は保存されています。イニシアチブから計画を再実行してください。",
|
|
7094
|
+
"saveFailed": "回答を保存できませんでした",
|
|
7095
|
+
"saveFailedCount": "回答のうち {count} 件を保存できませんでした",
|
|
7096
|
+
"continueFailed": "回答を送信できませんでした",
|
|
7097
|
+
"proceedFailed": "プランニングを開始できませんでした",
|
|
7098
|
+
"unanswerable": "この質問には ID がないため、回答を記録できません。",
|
|
7084
7099
|
"answerPlaceholder": "回答",
|
|
7085
7100
|
"hint": "「回答を送信」ではプランナーが追加の質問をします。「今すぐ計画」ではこれまでの回答をもとに計画を作成します。",
|
|
7086
7101
|
"unanswered": "未回答の質問: {count}",
|
|
@@ -8030,6 +8045,14 @@
|
|
|
8030
8045
|
"undeclared": "このステップは候補を申告しなかったため、比較するものがありませんでした。実行は続行されました。",
|
|
8031
8046
|
"parseFailed": "このステップの候補の申告を読み取れなかったため、比較するものがありませんでした。実行は続行されました。",
|
|
8032
8047
|
"noCandidates": "このステップは候補を用意しなかったため、比較するものがありませんでした。実行は続行されました。"
|
|
8033
|
-
}
|
|
8048
|
+
},
|
|
8049
|
+
"noRun": {
|
|
8050
|
+
"title": "読み取る実行がありません",
|
|
8051
|
+
"hint": "この比較はパイプラインの実行に紐づいています。候補を読み込めるように、生成したステップのカードまたはタイムラインから開いてください。"
|
|
8052
|
+
},
|
|
8053
|
+
"empty": {
|
|
8054
|
+
"title": "比較する候補はありません"
|
|
8055
|
+
},
|
|
8056
|
+
"loadFailed": "生成された候補を読み込めませんでした。"
|
|
8034
8057
|
}
|
|
8035
8058
|
}
|