@cat-factory/app 0.172.0 → 0.174.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +4 -0
  2. package/app/components/board/AddTaskModal.vue +10 -252
  3. package/app/components/board/CreateInitiativeModal.vue +27 -0
  4. package/app/components/board/nodes/InitiativeCard.vue +14 -0
  5. package/app/components/common/InterviewGateNotice.vue +39 -0
  6. package/app/components/context/ContextAttachmentFields.vue +289 -0
  7. package/app/components/docs/DocInterviewWindow.vue +77 -14
  8. package/app/components/focus/BlockFocusView.vue +35 -1
  9. package/app/components/fragments/FragmentLibraryManager.vue +91 -13
  10. package/app/components/fragments/GitHubDocUrlImport.vue +83 -0
  11. package/app/components/github/RepoTreeBrowser.vue +65 -10
  12. package/app/components/initiative/InitiativePlanningWindow.vue +127 -16
  13. package/app/components/panels/InspectorPanel.vue +17 -3
  14. package/app/components/panels/inspector/InitiativeInspector.vue +15 -0
  15. package/app/components/panels/inspector/TaskExecution.vue +5 -20
  16. package/app/composables/useBlockDeletion.ts +8 -1
  17. package/app/composables/useContextLinking.ts +14 -2
  18. package/app/composables/useInitiativePlanning.ts +28 -6
  19. package/app/composables/useRunReset.ts +48 -0
  20. package/app/modular/panels/inspector.logic.spec.ts +8 -2
  21. package/app/modular/panels/inspector.logic.ts +14 -2
  22. package/app/stores/observability.ts +4 -0
  23. package/app/utils/interviewGate.spec.ts +51 -0
  24. package/app/utils/interviewGate.ts +51 -0
  25. package/i18n/locales/de.json +66 -25
  26. package/i18n/locales/en.json +69 -25
  27. package/i18n/locales/es.json +66 -25
  28. package/i18n/locales/fr.json +66 -25
  29. package/i18n/locales/he.json +66 -25
  30. package/i18n/locales/it.json +66 -25
  31. package/i18n/locales/ja.json +66 -25
  32. package/i18n/locales/pl.json +66 -25
  33. package/i18n/locales/tr.json +66 -25
  34. package/i18n/locales/uk.json +66 -25
  35. package/package.json +2 -2
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The confirm-gated "discard this run" action, shared by every surface that offers it so they
3
+ * can't drift on what it does or how loudly it asks first.
4
+ *
5
+ * Destructive and distinct from a STOP: stop halts a run but keeps it readable and retryable,
6
+ * while this deletes it outright and returns the block to `planned`. That is what makes it the
7
+ * escape hatch for a WEDGED run — a run whose driver will never settle can't be waited out, and
8
+ * until the block's `executionId` clears nothing else may start on it.
9
+ *
10
+ * Two callers today: the inspector's execution panel (tasks and initiatives alike) and the
11
+ * initiative planning window, which needs it in-place because a human whose interview stalled is
12
+ * looking at that window, not at the inspector behind it.
13
+ */
14
+ export function useRunReset() {
15
+ const execution = useExecutionStore()
16
+ const access = useWorkspaceAccess()
17
+ const { confirm } = useConfirm()
18
+ const { t } = useI18n()
19
+
20
+ /** True while a discard is in flight (drives the button spinner). */
21
+ const resetting = ref(false)
22
+
23
+ /**
24
+ * Confirm, then discard the block's run. Resolves `true` only when the run was actually
25
+ * discarded, so a caller can act on it (the planning window closes itself). A read-only viewer
26
+ * no-ops — every button binding this is disabled for them, and this guards the rest.
27
+ */
28
+ async function resetRun(blockId: string): Promise<boolean> {
29
+ if (resetting.value || !access.canExecuteRuns.value) return false
30
+ const ok = await confirm({
31
+ title: t('inspector.execution.resetConfirm.title'),
32
+ description: t('inspector.execution.resetConfirm.body'),
33
+ variant: 'destructive',
34
+ confirmLabel: t('inspector.execution.resetConfirm.confirm'),
35
+ icon: 'i-lucide-trash-2',
36
+ })
37
+ if (!ok) return false
38
+ resetting.value = true
39
+ try {
40
+ await execution.cancel(blockId)
41
+ return true
42
+ } finally {
43
+ resetting.value = false
44
+ }
45
+ }
46
+
47
+ return { resetting, resetRun }
48
+ }
@@ -94,9 +94,15 @@ describe('inspector panel group', () => {
94
94
  ])
95
95
  })
96
96
 
97
- it('epic and initiative each show their single inspector', () => {
97
+ it('an epic shows only its children panel', () => {
98
98
  expect(visibleIds(block('epic'))).toEqual(['epic-children'])
99
- expect(visibleIds(block('initiative'))).toEqual(['initiative-inspector'])
99
+ })
100
+
101
+ // An initiative's planning pipeline is an ordinary run, so it shares the task body's execution
102
+ // panel — its own inspector leading, the run detail under it. Pinned because the panel is the
103
+ // only surface carrying the Stop / Discard-run controls that unwedge a stalled planning run.
104
+ it('an initiative shows its inspector, then the shared execution panel', () => {
105
+ expect(visibleIds(block('initiative'))).toEqual(['initiative-inspector', 'task-execution'])
100
106
  })
101
107
 
102
108
  it('no subject selected resolves to no panels', () => {
@@ -74,6 +74,14 @@ export interface InspectorPanelSpec {
74
74
 
75
75
  const isTask = (b: Block) => b.level === 'task'
76
76
  const isFrame = (b: Block) => b.level === 'frame'
77
+ /**
78
+ * A block whose inspector carries a pipeline RUN. An initiative's planning pipeline is an
79
+ * ordinary run of ordinary agent steps (interviewer → analyst → planner → committer), so it
80
+ * gets the same execution panel a task does — step list, live phases, step-detail drill-down,
81
+ * and the Stop / Discard-run controls that are the only way to unwedge a stalled planning run.
82
+ * Before this it had no run surface at all, which is why a stuck plan was a dead end.
83
+ */
84
+ const hasRuns = (b: Block) => isTask(b) || b.level === 'initiative'
77
85
  /** frame OR module — the "container" panels. */
78
86
  const isContainer = (b: Block) => b.level === 'frame' || b.level === 'module'
79
87
  /**
@@ -106,7 +114,8 @@ export const INSPECTOR_PANEL_SPECS: readonly InspectorPanelSpec[] = [
106
114
  { id: 'task-context-docs', order: 10, when: isTask },
107
115
  { id: 'task-context-issues', order: 20, when: isTask },
108
116
  { id: 'recurring-schedule', order: 30, when: isTask },
109
- { id: 'task-execution', order: 40, when: isTask },
117
+ // Shared with the initiative body — the panel renders a RUN, and an initiative has one.
118
+ { id: 'task-execution', order: 40, when: hasRuns },
110
119
  { id: 'task-estimate', order: 50, when: isTask },
111
120
  { id: 'task-dependencies', order: 60, when: isTask },
112
121
  { id: 'task-run-settings', order: 70, when: isTask },
@@ -124,5 +133,8 @@ export const INSPECTOR_PANEL_SPECS: readonly InspectorPanelSpec[] = [
124
133
  // test-infra and release-health panels above it.
125
134
  { id: 'service-validation-checks', order: 180, when: isDeployableFrame },
126
135
  { id: 'epic-children', order: 200, when: (b) => b.level === 'epic' },
127
- { id: 'initiative-inspector', order: 210, when: (b) => b.level === 'initiative' },
136
+ // Ordered BEFORE the shared execution panel (40) so an initiative reads the way a task does:
137
+ // its own identity + controls first, the run detail under them. Levels never overlap, so this
138
+ // number only ever competes with the task ids the initiative body doesn't render.
139
+ { id: 'initiative-inspector', order: 35, when: (b) => b.level === 'initiative' },
128
140
  ]
@@ -119,6 +119,10 @@ export const useObservabilityStore = defineStore('observability', () => {
119
119
  if (existing.some((c) => c.id === activity.id)) return
120
120
  const row: LlmCallMetric = {
121
121
  ...activity,
122
+ // The live event carries the phase (the proxy knows it) but no turn ordinal — that is
123
+ // the harness's job-scoped counter, which a proxied call has no equivalent of. Null is
124
+ // what the stored row will say too, so the live row and the loaded one agree.
125
+ turnIndex: null,
122
126
  promptText: '',
123
127
  promptPrefixCount: 0,
124
128
  promptHash: '',
@@ -0,0 +1,51 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { interviewGatePhase } from './interviewGate'
3
+
4
+ // `interviewGatePhase` is what stops continue/proceed reading as no-ops in BOTH interview windows
5
+ // (initiative planning, document interview): the resume is asynchronous — the HTTP call only wakes
6
+ // the durable driver, so it returns the PRE-resume entity — and these pin that the RUN status is
7
+ // what distinguishes "parked, waiting on you" from "a pass is running", a distinction the entity
8
+ // alone cannot make.
9
+
10
+ describe('interviewGatePhase', () => {
11
+ it('is awaiting while the run is parked on the human', () => {
12
+ expect(interviewGatePhase('awaiting', 'blocked')).toBe('awaiting')
13
+ })
14
+
15
+ it('is working once the resumed run is running again, even though the entity still says awaiting', () => {
16
+ // The exact regression: continue/proceed leave the entity's status untouched until the pass
17
+ // finishes, so an entity-only reading renders the same questions and looks like a dead button.
18
+ expect(interviewGatePhase('awaiting', 'running')).toBe('working')
19
+ })
20
+
21
+ it('is working for the FIRST pass, before any question exists', () => {
22
+ expect(interviewGatePhase(undefined, 'running')).toBe('working')
23
+ })
24
+
25
+ it('is failed when the run stopped before the interview settled', () => {
26
+ // Must not stay `working`: a pass that dies would otherwise spin forever.
27
+ expect(interviewGatePhase('awaiting', 'failed')).toBe('failed')
28
+ expect(interviewGatePhase(undefined, 'failed')).toBe('failed')
29
+ })
30
+
31
+ it('is converged once the interview settled, whatever the run went on to do', () => {
32
+ // `converged` outranks `failed`: a later step's failure belongs to that step, not the
33
+ // interview, and the block's own failure surface reports it.
34
+ expect(interviewGatePhase('done', 'running')).toBe('converged')
35
+ expect(interviewGatePhase('done', 'failed')).toBe('converged')
36
+ expect(interviewGatePhase('done', undefined)).toBe('converged')
37
+ })
38
+
39
+ it('is idle when the interview never ran', () => {
40
+ expect(interviewGatePhase(undefined, undefined)).toBe('idle')
41
+ })
42
+
43
+ it('degrades to the entity-only reading when the run is not cached', () => {
44
+ // A window opened before the execution snapshot lands must show the questions, never a spinner.
45
+ expect(interviewGatePhase('awaiting', undefined)).toBe('awaiting')
46
+ })
47
+
48
+ it('keeps a paused run answerable', () => {
49
+ expect(interviewGatePhase('awaiting', 'paused')).toBe('awaiting')
50
+ })
51
+ })
@@ -0,0 +1,51 @@
1
+ import type { ExecutionInstance } from '~/types/domain'
2
+
3
+ // The frontend dual of the backend's shared `InterviewGateController` spine. Both interview gates
4
+ // — the initiative-planning interviewer and the document interviewer — park their run on a
5
+ // decision-wait, expose the SAME `awaiting | done` status on their entity, and resume the same
6
+ // way, so how their windows read "what is happening right now" is shared vocabulary rather than
7
+ // two copies. See `docs/initiatives/clarification-items.md`.
8
+
9
+ /**
10
+ * What an interview gate is doing right now, from the human's point of view. Drives the interview
11
+ * window's body AND (for the initiative) the card/inspector affordances, so the surfaces can't
12
+ * disagree about whether there is anything to answer.
13
+ *
14
+ * - `idle` — the interview has not run yet (nothing to answer, nothing in flight).
15
+ * - `working` — an interviewer pass is running; the human waits.
16
+ * - `awaiting` — the run is parked on the human's answers.
17
+ * - `converged` — the interview settled; the run moved on.
18
+ * - `failed` — the run stopped before the interview settled.
19
+ */
20
+ export type InterviewGatePhase = 'idle' | 'working' | 'awaiting' | 'converged' | 'failed'
21
+
22
+ /**
23
+ * Resolve the phase from the interview entity's status AND its run's status.
24
+ *
25
+ * The RUN status is load-bearing, not redundant. Continue/proceed are ASYNC by design: the HTTP
26
+ * call only records the intent on the parked step and wakes the durable driver, which then runs
27
+ * the (slow) interviewer LLM — so the response carries the PRE-resume entity, with the same
28
+ * questions and the same `awaiting` status. Keyed on the entity alone a window is therefore
29
+ * byte-identical before and after the click, which is indistinguishable from the button doing
30
+ * nothing for however long the pass takes. A resumed run flips `blocked` → `running` and emits,
31
+ * so `running` while the interview is unsettled is exactly "a pass is in flight".
32
+ *
33
+ * Deriving this from the run rather than a local in-flight flag also survives a reload and cannot
34
+ * wedge: a pass that FAILS takes the run to `failed`, so the window drops out of `working` and
35
+ * says so instead of spinning forever. An unknown run (no instance cached yet) degrades to the
36
+ * entity-only reading, never to a spinner.
37
+ *
38
+ * `converged` wins over `failed` on purpose: once the interview settled, a later failure belongs
39
+ * to the step that failed (the analyst/planner, the writer), and the block's own failure surface
40
+ * reports it — the interview window claiming the interview broke would be wrong.
41
+ */
42
+ export function interviewGatePhase(
43
+ status: 'awaiting' | 'done' | undefined,
44
+ runStatus: ExecutionInstance['status'] | undefined,
45
+ ): InterviewGatePhase {
46
+ if (status === 'done') return 'converged'
47
+ if (runStatus === 'failed') return 'failed'
48
+ if (runStatus === 'running') return 'working'
49
+ if (status === 'awaiting') return 'awaiting'
50
+ return 'idle'
51
+ }
@@ -1259,7 +1259,7 @@
1259
1259
  },
1260
1260
  "execution": {
1261
1261
  "title": "Ausführung",
1262
- "hint": "Der Live-Lauf der Pipeline dieser Aufgabe: jeder Agent-Schritt, sein Fortschritt und der resultierende Pull Request.",
1262
+ "hint": "Der Live-Lauf der Pipeline: jeder Agent-Schritt, sein Fortschritt und der resultierende Pull Request.",
1263
1263
  "stage": {
1264
1264
  "incorporating": "Wird eingearbeitet…",
1265
1265
  "reviewing": "Wird erneut geprüft…",
@@ -1284,10 +1284,10 @@
1284
1284
  "stop": "Stoppen",
1285
1285
  "stopTooltip": "Den Lauf stoppen, aber behalten (lesbar und wiederholbar)",
1286
1286
  "reset": "Zurücksetzen",
1287
- "resetTooltip": "Diesen Lauf verwerfen und die Aufgabe auf geplant zurücksetzen",
1287
+ "resetTooltip": "Diesen Lauf verwerfen und den Status auf geplant zurücksetzen",
1288
1288
  "resetConfirm": {
1289
1289
  "title": "Diesen Lauf verwerfen?",
1290
- "body": "Dies löscht den Lauf und setzt die Aufgabe auf geplant zurück. Dies kann nicht rückgängig gemacht werden.",
1290
+ "body": "Dies löscht den Lauf und setzt den Status auf geplant zurück. Dies kann nicht rückgängig gemacht werden.",
1291
1291
  "confirm": "Lauf verwerfen"
1292
1292
  },
1293
1293
  "mergeConfirm": {
@@ -1622,6 +1622,7 @@
1622
1622
  "deleteRecurringPipeline": "Wiederkehrende Pipeline löschen",
1623
1623
  "deleteTask": "Aufgabe löschen",
1624
1624
  "deleteModule": "Modul löschen",
1625
+ "deleteInitiative": "Initiative löschen",
1625
1626
  "deleteService": "Service löschen",
1626
1627
  "confirmDelete": {
1627
1628
  "task": {
@@ -1632,6 +1633,10 @@
1632
1633
  "title": "Dieses Modul löschen?",
1633
1634
  "body": "\"{name}\" und alles darin wird entfernt. Dies kann nicht rückgängig gemacht werden."
1634
1635
  },
1636
+ "initiative": {
1637
+ "title": "Diese Initiative löschen?",
1638
+ "body": "\"{name}\" und ihr Plan werden entfernt. Bereits erstellte Aufgaben bleiben auf dem Board. Dies kann nicht rückgängig gemacht werden."
1639
+ },
1635
1640
  "service": {
1636
1641
  "title": "Diesen Service löschen?",
1637
1642
  "body": "\"{name}\" und alles darin wird entfernt. Dies kann nicht rückgängig gemacht werden."
@@ -2332,17 +2337,6 @@
2332
2337
  "bestPractices": "Best Practices",
2333
2338
  "bestPracticesHint": "Best-Practice-Fragmente anheften, damit die Agenten dieser Aufgabe sie zusätzlich zu den Standards auf Service-Ebene befolgen.",
2334
2339
  "agentConfiguration": "Agent-Konfiguration",
2335
- "contextDocuments": "Kontextdokumente",
2336
- "contextIssues": "Kontext-Issues",
2337
- "attach": "Anhängen",
2338
- "connectSource": "Quelle verbinden",
2339
- "connectSourceNamed": "{source} verbinden",
2340
- "done": "Fertig",
2341
- "attachDocDisabledConnect": "Verbinden Sie zuerst eine Dokumentquelle (Integrationen)",
2342
- "attachDocDisabledEnable": "Aktivieren Sie zuerst die Dokumente-Integration",
2343
- "attachIssueDisabledConnect": "Verbinden Sie zuerst einen Issue-Tracker (Integrationen)",
2344
- "attachIssueDisabledEnable": "Aktivieren Sie zuerst die Issue-Tracker-Integration",
2345
- "importsOnAdd": "importiert beim Hinzufügen",
2346
2340
  "noDocsHint": "Hängen Sie eine Anforderung, ein RFC oder ein PRD an, damit Agenten es beim Implementieren dieser Aufgabe sehen.",
2347
2341
  "noIssuesHint": "Hängen Sie ein Tracker-Issue an, damit Agenten dessen Beschreibung und Kommentare beim Implementieren dieser Aufgabe sehen.",
2348
2342
  "plannedHint": "Die Aufgabe wird in einem geplanten Zustand hinzugefügt. Sie läuft erst, wenn Sie eine Pipeline darauf starten — Sie können sie bis dahin weiter bearbeiten.",
@@ -2508,6 +2502,19 @@
2508
2502
  "noTasksYet": "Noch keine Aufgaben"
2509
2503
  }
2510
2504
  },
2505
+ "contextAttachments": {
2506
+ "documents": "Kontextdokumente",
2507
+ "issues": "Kontext-Issues",
2508
+ "attach": "Anhängen",
2509
+ "done": "Fertig",
2510
+ "connectSource": "Quelle verbinden",
2511
+ "connectSourceNamed": "{source} verbinden",
2512
+ "attachDocDisabledConnect": "Verbinden Sie zuerst eine Dokumentquelle (Integrationen)",
2513
+ "attachDocDisabledEnable": "Aktivieren Sie zuerst die Dokumente-Integration",
2514
+ "attachIssueDisabledConnect": "Verbinden Sie zuerst einen Issue-Tracker (Integrationen)",
2515
+ "attachIssueDisabledEnable": "Aktivieren Sie zuerst die Issue-Tracker-Integration",
2516
+ "importsOnAdd": "importiert beim Hinzufügen"
2517
+ },
2511
2518
  "providers": {
2512
2519
  "presetMismatch": {
2513
2520
  "title": "Preset verwendet nicht verfügbare Modelle",
@@ -2840,7 +2847,8 @@
2840
2847
  "useThisFolder": "Diesen Ordner verwenden",
2841
2848
  "errors": {
2842
2849
  "listDirectory": "Verzeichnis konnte nicht aufgelistet werden"
2843
- }
2850
+ },
2851
+ "selectAllFiles": "{count} Datei auswählen | Alle {count} Dateien auswählen"
2844
2852
  }
2845
2853
  },
2846
2854
  "personalSubscriptions": {
@@ -3880,7 +3888,19 @@
3880
3888
  "link": "Als lebendes Fragment verknüpfen",
3881
3889
  "githubBrowseHint": "Durchsuchen Sie das Repo und wählen Sie eine oder mehrere zu verknüpfende Dateien.",
3882
3890
  "selectedFiles": "Ausgewählte Dateien ({count})",
3883
- "removeFile": "Datei entfernen"
3891
+ "removeFile": "Datei entfernen",
3892
+ "blockedReason": {
3893
+ "noSource": "Wählen Sie zuerst oben eine Dokumentquelle aus.",
3894
+ "noRepo": "Wählen Sie ein Repository aus oder fügen Sie oben eine GitHub-Datei- oder Ordner-URL ein.",
3895
+ "noFiles": "Haken Sie im Repository-Browser mindestens eine Datei an.",
3896
+ "noRef": "Geben Sie zuerst eine Seiten-ID oder URL ein."
3897
+ },
3898
+ "urlImport": {
3899
+ "placeholder": "GitHub-Datei- oder Ordner-URL einfügen (z. B. https://github.com/owner/repo/tree/main/docs)",
3900
+ "action": "Suchen",
3901
+ "invalid": "Das sieht nicht nach der URL einer Repository-Datei oder eines Ordners aus.",
3902
+ "notFound": "Kein zugängliches Repository passt zu {slug}. Prüfen Sie die URL oder verbinden Sie das Repository zuerst."
3903
+ }
3884
3904
  },
3885
3905
  "sources": {
3886
3906
  "metaSynced": "synchronisiert · ref {ref}",
@@ -4115,7 +4135,10 @@
4115
4135
  "pathInvalid": "Geben Sie einen Pfad innerhalb des Repositorys an (kein \"..\", keine absoluten Pfade und keine Backslashes).",
4116
4136
  "hint": "Es läuft noch nichts: Führen Sie nach dem Erstellen die Initiative-Planning-Pipeline auf dem Block aus. Sie analysiert die Codebasis und entwirft den mehrphasigen Plan zu Ihrer Freigabe.",
4117
4137
  "submit": "Initiative erstellen",
4118
- "failedTitle": "Die Initiative konnte nicht erstellt werden"
4138
+ "failedTitle": "Die Initiative konnte nicht erstellt werden",
4139
+ "contextDocsHint": "Hänge eine Anforderung, ein RFC oder ein PRD an, damit die Planungsagenten es beim Abstecken und Entwerfen des Plans lesen.",
4140
+ "contextIssuesHint": "Hänge ein Tracker-Issue an, damit die Planungsagenten beim Entwerfen des Plans seine Beschreibung und Kommentare sehen.",
4141
+ "linkFailed": "Initiative erstellt, aber {count} Anhang konnte nicht verknüpft werden | Initiative erstellt, aber {count} Anhänge konnten nicht verknüpft werden"
4119
4142
  },
4120
4143
  "status": {
4121
4144
  "planning": "Planung",
@@ -4168,6 +4191,7 @@
4168
4191
  "inspector": {
4169
4192
  "runPlanning": "Planung ausführen",
4170
4193
  "answerPlanning": "Planungsfragen beantworten",
4194
+ "planningInProgress": "Planung läuft",
4171
4195
  "pause": "Pausieren",
4172
4196
  "resume": "Fortsetzen",
4173
4197
  "cancel": "Initiative abbrechen",
@@ -4176,13 +4200,23 @@
4176
4200
  "planning": {
4177
4201
  "title": "Die Initiative planen",
4178
4202
  "subtitle": "Beantworten Sie die Fragen des Planers, damit er die Initiative eingrenzen kann",
4179
- "intro": "Der Planer grenzt diese Initiative ein. Beantworten Sie seine Fragen, um Ziel und Einschränkungen zu formen, dann fahren Sie fort oder gehen Sie mit dem, was er hat, zur Planung über.",
4203
+ "intro": "Der Planer grenzt diese Initiative ein. Beantworten Sie seine Fragen, um Ziel und Einschränkungen zu formen, und senden Sie sie dann ab. Sie können ihn auch mit dem, was er bereits hat, jetzt planen lassen.",
4180
4204
  "empty": "Keine Initiative für diesen Block gefunden.",
4181
4205
  "converged": "Keine Fragen ausstehend. Der Planer hat, was er braucht, und entwirft den Plan.",
4206
+ "idle": "Die Planung wurde noch nicht gestartet. Führen Sie die Planung von der Initiative aus, um das Interview zu beginnen.",
4207
+ "working": "Der Planer verarbeitet Ihre Antworten",
4208
+ "workingHint": "Das dauert einen Moment. Rückfragen erscheinen hier, sobald er fertig ist, oder er beginnt mit dem Entwurf des Plans, wenn ihm die Angaben genügen.",
4209
+ "failed": "Der Planungslauf wurde abgebrochen",
4210
+ "failedHint": "Er endete, bevor der Planer antworten konnte. Ihre Antworten sind gespeichert; führen Sie die Planung von der Initiative aus erneut aus.",
4182
4211
  "answerPlaceholder": "Ihre Antwort",
4183
- "hint": "Fortfahren lässt den Planer Rückfragen stellen; Übergehen plant mit den bisherigen Antworten.",
4184
- "proceed": "Zur Planung übergehen",
4185
- "continue": "Fortfahren"
4212
+ "hint": "Antworten senden lässt den Planer Rückfragen stellen; Jetzt planen entwirft den Plan mit den bisherigen Antworten.",
4213
+ "unanswered": "Unbeantwortete Fragen: {count}",
4214
+ "proceed": "Jetzt planen",
4215
+ "proceedTitle": "Die restlichen Fragen überspringen und den Plan jetzt entwerfen",
4216
+ "discard": "Lauf verwerfen",
4217
+ "discardTitle": "Den blockierten Planungslauf verwerfen, um die Planung neu zu starten",
4218
+ "continue": "Antworten senden",
4219
+ "continueTitle": "Ihre Antworten senden; der Planer stellt möglicherweise Rückfragen"
4186
4220
  },
4187
4221
  "followUpStatus": {
4188
4222
  "open": "Offen",
@@ -4515,14 +4549,21 @@
4515
4549
  "docInterview": {
4516
4550
  "title": "Das Dokument verfeinern",
4517
4551
  "subtitle": "Beantworte die Fragen des Interviewers, damit er das Dokument formen kann",
4518
- "intro": "Der Interviewer verfeinert dieses Dokument, bevor es geschrieben wird. Beantworte seine Fragen, um Umfang, Zielgruppe und Struktur zu formen, und fahre dann fort oder gehe mit dem vorhandenen Stand direkt zum Entwurf über.",
4552
+ "intro": "Der Interviewer verfeinert dieses Dokument, bevor es geschrieben wird. Beantworte seine Fragen, um Umfang, Zielgruppe und Struktur zu formen, und sende sie dann ab. Du kannst ihn auch mit dem vorhandenen Stand jetzt entwerfen lassen.",
4519
4553
  "empty": "Kein Interview für diesen Block gefunden.",
4520
4554
  "brief": "Autoren-Briefing",
4521
4555
  "converged": "Es stehen keine Fragen aus. Der Interviewer hat, was er braucht, und das Dokument wird entworfen.",
4556
+ "working": "Der Interviewer verarbeitet deine Antworten",
4557
+ "workingHint": "Das dauert einen Moment. Nachfragen erscheinen hier, sobald er fertig ist, oder der Entwurf beginnt, wenn ihm die Angaben genügen.",
4558
+ "failed": "Der Dokumentenlauf wurde abgebrochen",
4559
+ "failedHint": "Er endete, bevor der Interviewer antworten konnte. Deine Antworten sind gespeichert; führe die Dokumentaufgabe erneut aus.",
4522
4560
  "answerPlaceholder": "Deine Antwort",
4523
- "hint": "Mit \"Fortfahren\" kann der Interviewer Nachfragen stellen; mit \"Weiter zum Entwurf\" wird mit den bisherigen Antworten entworfen.",
4524
- "proceed": "Weiter zum Entwurf",
4525
- "continue": "Fortfahren",
4561
+ "hint": "Mit \"Antworten senden\" kann der Interviewer Nachfragen stellen; mit \"Jetzt entwerfen\" wird mit den bisherigen Antworten entworfen.",
4562
+ "unanswered": "Unbeantwortete Fragen: {count}",
4563
+ "proceed": "Jetzt entwerfen",
4564
+ "proceedTitle": "Die restlichen Fragen überspringen und den Entwurf jetzt beginnen",
4565
+ "continue": "Antworten senden",
4566
+ "continueTitle": "Deine Antworten senden; der Interviewer stellt möglicherweise Nachfragen",
4526
4567
  "status": {
4527
4568
  "awaiting": "Warten auf Antworten",
4528
4569
  "done": "Fertig"
@@ -309,17 +309,6 @@
309
309
  "bestPractices": "Best practices",
310
310
  "bestPracticesHint": "Pin best-practice fragments so this task's agents follow them, on top of the service-level standards.",
311
311
  "agentConfiguration": "Agent configuration",
312
- "contextDocuments": "Context documents",
313
- "contextIssues": "Context issues",
314
- "attach": "Attach",
315
- "connectSource": "Connect a source",
316
- "connectSourceNamed": "Connect {source}",
317
- "done": "Done",
318
- "attachDocDisabledConnect": "Connect a document source first (Integrations)",
319
- "attachDocDisabledEnable": "Enable the documents integration first",
320
- "attachIssueDisabledConnect": "Connect an issue tracker first (Integrations)",
321
- "attachIssueDisabledEnable": "Enable the issue-tracker integration first",
322
- "importsOnAdd": "imports on add",
323
312
  "noDocsHint": "Attach a requirement, RFC or PRD so agents see it while implementing this task.",
324
313
  "noIssuesHint": "Attach a tracker issue so agents see its description and comments while implementing this task.",
325
314
  "plannedHint": "The task is added in a planned state. It won't run until you start a pipeline on it — you can keep editing it until then.",
@@ -500,6 +489,19 @@
500
489
  "noTasksYet": "No tasks yet"
501
490
  }
502
491
  },
492
+ "contextAttachments": {
493
+ "documents": "Context documents",
494
+ "issues": "Context issues",
495
+ "attach": "Attach",
496
+ "done": "Done",
497
+ "connectSource": "Connect a source",
498
+ "connectSourceNamed": "Connect {source}",
499
+ "attachDocDisabledConnect": "Connect a document source first (Integrations)",
500
+ "attachDocDisabledEnable": "Enable the documents integration first",
501
+ "attachIssueDisabledConnect": "Connect an issue tracker first (Integrations)",
502
+ "attachIssueDisabledEnable": "Enable the issue-tracker integration first",
503
+ "importsOnAdd": "imports on add"
504
+ },
503
505
  "errors": {
504
506
  "action": {
505
507
  "retryFailed": "Retry failed",
@@ -1003,7 +1005,7 @@
1003
1005
  },
1004
1006
  "execution": {
1005
1007
  "title": "Execution",
1006
- "hint": "The live run of this task's pipeline: each agent step, its progress, and the resulting pull request.",
1008
+ "hint": "The live pipeline run: each agent step, its progress, and the resulting pull request.",
1007
1009
  "stage": {
1008
1010
  "incorporating": "Incorporating…",
1009
1011
  "reviewing": "Re-reviewing…",
@@ -1028,10 +1030,10 @@
1028
1030
  "stop": "Stop",
1029
1031
  "stopTooltip": "Stop the run but keep it (readable and retryable)",
1030
1032
  "reset": "Reset",
1031
- "resetTooltip": "Discard this run and reset the task to planned",
1033
+ "resetTooltip": "Discard this run and reset the status to planned",
1032
1034
  "resetConfirm": {
1033
1035
  "title": "Discard this run?",
1034
- "body": "This deletes the run and returns the task to planned. This can't be undone.",
1036
+ "body": "This deletes the run and resets the status to planned. This can't be undone.",
1035
1037
  "confirm": "Discard run"
1036
1038
  },
1037
1039
  "mergeConfirm": {
@@ -1366,6 +1368,7 @@
1366
1368
  "deleteRecurringPipeline": "Delete recurring pipeline",
1367
1369
  "deleteTask": "Delete task",
1368
1370
  "deleteModule": "Delete module",
1371
+ "deleteInitiative": "Delete initiative",
1369
1372
  "deleteService": "Delete service",
1370
1373
  "confirmDelete": {
1371
1374
  "task": {
@@ -1376,6 +1379,10 @@
1376
1379
  "title": "Delete this module?",
1377
1380
  "body": "\"{name}\" and everything inside it will be removed. This can't be undone."
1378
1381
  },
1382
+ "initiative": {
1383
+ "title": "Delete this initiative?",
1384
+ "body": "\"{name}\" and its plan will be removed. Tasks it already created stay on the board. This can't be undone."
1385
+ },
1379
1386
  "service": {
1380
1387
  "title": "Delete this service?",
1381
1388
  "body": "\"{name}\" and everything inside it will be removed. This can't be undone."
@@ -3502,7 +3509,8 @@
3502
3509
  "useThisFolder": "Use this folder",
3503
3510
  "errors": {
3504
3511
  "listDirectory": "Could not list directory"
3505
- }
3512
+ },
3513
+ "selectAllFiles": "Select {count} file | Select all {count} files"
3506
3514
  }
3507
3515
  },
3508
3516
  "slack": {
@@ -3576,14 +3584,21 @@
3576
3584
  "docInterview": {
3577
3585
  "title": "Refine the document",
3578
3586
  "subtitle": "Answer the interviewer's questions so it can shape the document",
3579
- "intro": "The interviewer is refining this document before it's written. Answer its questions to shape the scope, audience and structure, then continue or proceed to draft with what it has.",
3587
+ "intro": "The interviewer is refining this document before it's written. Answer its questions to shape the scope, audience and structure, then submit them. You can also have it draft now with what it already has.",
3580
3588
  "empty": "No interview found for this block.",
3581
3589
  "brief": "Authoring brief",
3582
3590
  "converged": "No questions are pending. The interviewer has what it needs and the document is being drafted.",
3591
+ "working": "The interviewer is working on your answers",
3592
+ "workingHint": "This takes a moment. Follow-up questions appear here when it is done, or drafting starts if it has enough.",
3593
+ "failed": "The document run stopped",
3594
+ "failedHint": "It ended before the interviewer could answer. Your answers are saved; re-run the document task to try again.",
3583
3595
  "answerPlaceholder": "Your answer",
3584
- "hint": "Continue lets the interviewer ask follow-ups; Proceed drafts with the answers so far.",
3585
- "proceed": "Proceed to draft",
3586
- "continue": "Continue",
3596
+ "hint": "Submit answers lets the interviewer ask follow-ups; Draft now writes the document with the answers so far.",
3597
+ "unanswered": "Unanswered questions: {count}",
3598
+ "proceed": "Draft now",
3599
+ "proceedTitle": "Skip the remaining questions and start the draft now",
3600
+ "continue": "Submit answers",
3601
+ "continueTitle": "Send your answers; the interviewer may ask follow-up questions",
3587
3602
  "status": {
3588
3603
  "awaiting": "Awaiting answers",
3589
3604
  "done": "Done"
@@ -5009,7 +5024,19 @@
5009
5024
  "link": "Link as living fragment",
5010
5025
  "githubBrowseHint": "Browse the repo and pick one or more files to link.",
5011
5026
  "selectedFiles": "Selected files ({count})",
5012
- "removeFile": "Remove file"
5027
+ "removeFile": "Remove file",
5028
+ "blockedReason": {
5029
+ "noSource": "Choose a document source above first.",
5030
+ "noRepo": "Pick a repository, or paste a GitHub file or folder URL above.",
5031
+ "noFiles": "Tick at least one file in the repository browser.",
5032
+ "noRef": "Enter a page id or URL first."
5033
+ },
5034
+ "urlImport": {
5035
+ "placeholder": "Paste a GitHub file or folder URL (e.g. https://github.com/owner/repo/tree/main/docs)",
5036
+ "action": "Find",
5037
+ "invalid": "This doesn't look like a repository file or folder URL.",
5038
+ "notFound": "No accessible repository matches {slug}. Check the URL or connect the repository first."
5039
+ }
5013
5040
  },
5014
5041
  "sources": {
5015
5042
  "metaSynced": "synced · ref {ref}",
@@ -5279,7 +5306,13 @@
5279
5306
  "pathInvalid": "Enter a path inside the repository (no \"..\", absolute paths, or backslashes).",
5280
5307
  "hint": "Nothing runs yet: after creating, run the Initiative Planning pipeline on the block. It analyses the codebase and drafts the multi-phase plan for your approval.",
5281
5308
  "submit": "Create initiative",
5282
- "failedTitle": "Could not create the initiative"
5309
+ "failedTitle": "Could not create the initiative",
5310
+ "contextDocsHint": "Attach a requirement, RFC or PRD so the planning agents read it while scoping and drafting the plan.",
5311
+ "contextIssuesHint": "Attach a tracker issue so the planning agents see its description and comments while drafting the plan.",
5312
+ "linkFailed": "Initiative created, but {count} attachment could not be linked | Initiative created, but {count} attachments could not be linked",
5313
+ "@linkFailed": {
5314
+ "description": "Count-based: how many context attachments (docs/issues) failed to link after the initiative was created (count is always >= 1). Provide ALL plural forms your language needs (English has 2; Polish/Ukrainian need 3 - one/few/many - via the custom pluralRules in i18n.config.ts)."
5315
+ }
5283
5316
  },
5284
5317
  "status": {
5285
5318
  "planning": "Planning",
@@ -5332,6 +5365,7 @@
5332
5365
  "inspector": {
5333
5366
  "runPlanning": "Run planning",
5334
5367
  "answerPlanning": "Answer planning questions",
5368
+ "planningInProgress": "Planning in progress",
5335
5369
  "pause": "Pause",
5336
5370
  "resume": "Resume",
5337
5371
  "cancel": "Cancel initiative",
@@ -5340,13 +5374,23 @@
5340
5374
  "planning": {
5341
5375
  "title": "Plan the initiative",
5342
5376
  "subtitle": "Answer the planner's questions so it can scope the initiative",
5343
- "intro": "The planner is scoping this initiative. Answer its questions to shape the goal and constraints, then continue or proceed to plan with what it has.",
5377
+ "intro": "The planner is scoping this initiative. Answer its questions to shape the goal and constraints, then submit them. You can also have it plan now with what it already has.",
5344
5378
  "empty": "No initiative found for this block.",
5345
5379
  "converged": "No questions are pending. The planner has what it needs and is drafting the plan.",
5380
+ "idle": "Planning has not started yet. Run planning from the initiative to begin the interview.",
5381
+ "working": "The planner is working on your answers",
5382
+ "workingHint": "This takes a moment. Follow-up questions appear here when it is done, or it starts drafting the plan if it has enough.",
5383
+ "failed": "The planning run stopped",
5384
+ "failedHint": "It ended before the planner could answer. Your answers are saved; re-run planning from the initiative to try again.",
5346
5385
  "answerPlaceholder": "Your answer",
5347
- "hint": "Continue lets the planner ask follow-ups; Proceed plans with the answers so far.",
5348
- "proceed": "Proceed to plan",
5349
- "continue": "Continue"
5386
+ "hint": "Submit answers lets the planner ask follow-ups; Plan now drafts the plan with the answers so far.",
5387
+ "unanswered": "Unanswered questions: {count}",
5388
+ "proceed": "Plan now",
5389
+ "proceedTitle": "Skip the remaining questions and draft the plan now",
5390
+ "discard": "Discard run",
5391
+ "discardTitle": "Discard the stalled planning run so you can start planning again",
5392
+ "continue": "Submit answers",
5393
+ "continueTitle": "Send your answers; the planner may ask follow-up questions"
5350
5394
  },
5351
5395
  "followUpStatus": {
5352
5396
  "open": "Open",