@cat-factory/app 0.294.0 → 0.296.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.
@@ -0,0 +1,37 @@
1
+ import { computed, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'
2
+ import {
3
+ bootstrapResumeStep,
4
+ bootstrapRunSteps,
5
+ type BootstrapRunStep,
6
+ type BootstrapStepId,
7
+ } from '@cat-factory/contracts'
8
+ import { useAgentRunsStore } from '~/stores/agentRuns'
9
+
10
+ /**
11
+ * A bootstrap run projected onto its steps, for the surfaces that render them and for the
12
+ * button that resumes one.
13
+ *
14
+ * The projection itself lives in `@cat-factory/contracts` and is shared with the backend, which
15
+ * BRANCHES on the same rule (`bootstrapResume`) in `BootstrapService.retry`; this side needs only
16
+ * the step it answers with, never the state it carries. What this composable adds is the
17
+ * one SPA-side question the backend never asks: whether the run has more than one step at all.
18
+ * A new-repo bootstrap is a single move, so for it a step list restates the banner it sits under
19
+ * and "resume from…" is a promise about progress there is none of: it simply starts again.
20
+ */
21
+ export function useBootstrapRunSteps(runId: MaybeRefOrGetter<string | null | undefined>): {
22
+ /** The run's steps in order, with the reached one carrying the run's state. Empty if unknown. */
23
+ steps: ComputedRef<BootstrapRunStep[]>
24
+ /** Whether the run is a multi-step (monorepo) one: the gate every caller here needs. */
25
+ multiStep: ComputedRef<boolean>
26
+ /** The step a retry re-enters at, or null when the run is single-step or unknown. */
27
+ resumeStep: ComputedRef<BootstrapStepId | null>
28
+ } {
29
+ const agentRuns = useAgentRunsStore()
30
+ const job = computed(() => agentRuns.bootstrapById(toValue(runId)))
31
+ const steps = computed<BootstrapRunStep[]>(() => (job.value ? bootstrapRunSteps(job.value) : []))
32
+ const multiStep = computed(() => steps.value.length > 1)
33
+ const resumeStep = computed<BootstrapStepId | null>(() =>
34
+ job.value && multiStep.value ? bootstrapResumeStep(job.value) : null,
35
+ )
36
+ return { steps, multiStep, resumeStep }
37
+ }
@@ -20,6 +20,7 @@ function job(id: string, over: Partial<BootstrapJob> = {}): BootstrapJob {
20
20
  failure: null,
21
21
  monorepo: null,
22
22
  phase: null,
23
+ delivery: 'direct_push',
23
24
  adoptionPlan: null,
24
25
  adoptionReview: null,
25
26
  prUrl: null,
@@ -158,6 +158,18 @@ export const useAgentRunsStore = defineStore('agentRuns', () => {
158
158
  return map
159
159
  })
160
160
 
161
+ /**
162
+ * One bootstrap run by its RUN id.
163
+ *
164
+ * The counterpart to `execution.getInstance`, and it exists for the same surfaces: anything
165
+ * that holds a run id and needs the run WHOLE rather than the coarse {@link byBlock} summary:
166
+ * the observability panel's header, and the step list a card renders. A retry mints a NEW id,
167
+ * so unlike the block-keyed reads below this one needs nothing of the list's ordering.
168
+ */
169
+ function bootstrapById(runId: string | null | undefined): BootstrapJob | undefined {
170
+ return runId ? bootstrapJobs.value.find((job) => job.id === runId) : undefined
171
+ }
172
+
161
173
  /**
162
174
  * The parked monorepo bootstrap for a block, when it is waiting on an adoption review.
163
175
  *
@@ -221,6 +233,7 @@ export const useAgentRunsStore = defineStore('agentRuns', () => {
221
233
 
222
234
  return {
223
235
  bootstrapJobs,
236
+ bootstrapById,
224
237
  awaitingReview,
225
238
  submitAdoptionReview,
226
239
  hydrate,
@@ -18,6 +18,7 @@ export type {
18
18
  BootstrapFailure,
19
19
  BootstrapJob,
20
20
  BootstrapPhase,
21
+ BootstrapDelivery,
21
22
  BootstrapRepoInput,
22
23
  MonorepoBootstrapTarget,
23
24
  MonorepoBootstrapRef,
@@ -0,0 +1,60 @@
1
+ import type { BootstrapStepState } from '@cat-factory/contracts'
2
+
3
+ // Display metadata for a bootstrap run's step states, the `catalog.ts` idea at the scale of one
4
+ // vocabulary: the icon and the two tones that render a state, in ONE record rather than three
5
+ // parallel ones keyed alike. Three had to be kept in step by hand, which is a silent way to give
6
+ // a newly added state (`stopped`, say) a red icon and calm text.
7
+ //
8
+ // Module scope rather than a component's `<script setup>`, where a top-level const is rebuilt for
9
+ // every instance: the step list renders on every in-progress, parked and failed bootstrap card on
10
+ // the board, plus the inspector and the failure card.
11
+
12
+ /** How one step state renders: its icon, the icon's tone, and the label's. */
13
+ export interface BootstrapStepStyle {
14
+ icon: string
15
+ iconClass: string
16
+ labelClass: string
17
+ }
18
+
19
+ /**
20
+ * The style per state. `stopped` is deliberately NOT the failure red: a run someone stopped is
21
+ * stored as a failure without being one, and the step they stopped in is usually the review,
22
+ * whose only actor is the reviewer themselves.
23
+ */
24
+ export const BOOTSTRAP_STEP_STYLE: Record<BootstrapStepState, BootstrapStepStyle> = {
25
+ pending: {
26
+ icon: 'i-lucide-circle',
27
+ iconClass: 'text-slate-500',
28
+ labelClass: 'text-slate-500',
29
+ },
30
+ running: {
31
+ icon: 'i-lucide-loader-circle',
32
+ iconClass: 'animate-spin text-amber-400',
33
+ labelClass: 'text-amber-100',
34
+ },
35
+ awaiting_review: {
36
+ icon: 'i-lucide-user-check',
37
+ iconClass: 'text-amber-400',
38
+ labelClass: 'text-amber-100',
39
+ },
40
+ done: {
41
+ icon: 'i-lucide-check-circle-2',
42
+ iconClass: 'text-emerald-400',
43
+ labelClass: 'text-slate-400',
44
+ },
45
+ failed: {
46
+ icon: 'i-lucide-alert-triangle',
47
+ iconClass: 'text-rose-400',
48
+ labelClass: 'text-rose-200',
49
+ },
50
+ stopped: {
51
+ icon: 'i-lucide-circle-stop',
52
+ iconClass: 'text-slate-400',
53
+ labelClass: 'text-slate-300',
54
+ },
55
+ unknown: {
56
+ icon: 'i-lucide-help-circle',
57
+ iconClass: 'text-slate-400',
58
+ labelClass: 'text-slate-400',
59
+ },
60
+ }
@@ -1,5 +1,10 @@
1
1
  import { describe, it, expect } from 'vitest'
2
- import { PIPELINE_PURPOSES, purposeAllowsAgentCategory } from '@cat-factory/contracts'
2
+ import {
3
+ MONOREPO_ADOPTION_AGENT_KIND,
4
+ PIPELINE_PURPOSES,
5
+ purposeAllowsAgentCategory,
6
+ REPO_BOOTSTRAP_AGENT_KIND,
7
+ } from '@cat-factory/contracts'
3
8
  import type { AgentKind, BlockStatus, BlockType } from '~/types/domain'
4
9
  import { narrowAgentPalette } from '~/utils/agentPalette'
5
10
  import {
@@ -78,6 +83,17 @@ describe('catalog', () => {
78
83
  }
79
84
  })
80
85
 
86
+ it('names the kinds a bootstrap run files its telemetry under', () => {
87
+ // The backend stamps these two on a bootstrap run's metric, snapshot and tool-call rows, and
88
+ // the observability panel groups by kind. Unnamed here they roll up under the generic "Agent"
89
+ // fallback: the survey's model calls and the apply container's under one unlabelled heading,
90
+ // on the one panel whose job is telling them apart. Asserted through the same constants the
91
+ // backend imports, so this cannot pass against a stale spelling.
92
+ for (const kind of [REPO_BOOTSTRAP_AGENT_KIND, MONOREPO_ADOPTION_AGENT_KIND]) {
93
+ expect(agentKindMeta(kind).label, `${kind} falls back to the unnamed agent`).not.toBe('Agent')
94
+ }
95
+ })
96
+
81
97
  it('classifies every built-in kind into a tier', () => {
82
98
  // The palette / model-preset surfaces open on `basic`, so a built-in that forgot its tier
83
99
  // would silently fall to the DEFAULT (intermediate) and vanish from the default view for
@@ -8,7 +8,11 @@ import type {
8
8
  TaskTypeMeta,
9
9
  } from '~/types/domain'
10
10
  import type { BadgeColor } from '~/utils/badge'
11
- import { isBuiltinGatableKind } from '@cat-factory/contracts'
11
+ import {
12
+ isBuiltinGatableKind,
13
+ MONOREPO_ADOPTION_AGENT_KIND,
14
+ REPO_BOOTSTRAP_AGENT_KIND,
15
+ } from '@cat-factory/contracts'
12
16
 
13
17
  /** Simple unique id helper (fine for a client-only prototype). */
14
18
  export function uid(prefix = 'id'): string {
@@ -636,6 +640,33 @@ export const SYSTEM_AGENT_META: Record<string, AgentArchetype> = {
636
640
  'Re-examines a single challenged PR-review finding against the full source, then upholds ' +
637
641
  '(strengthening it) or retracts it with a justification. Configurable separately from the reviewer.',
638
642
  },
643
+ // The two agent kinds a REPO BOOTSTRAP run files its telemetry under. Neither is placeable
644
+ // and neither is a model-routing key (the bootstrapper runs on the `architect` routing, the
645
+ // advisor on the workspace default): they are here so the observability panel a bootstrap run
646
+ // opens names what actually ran. Without them both roll up as the generic "Agent" fallback,
647
+ // which puts the survey's model calls and the apply container's under one unnamed heading on
648
+ // the one panel whose job is telling them apart.
649
+ //
650
+ // Keyed off the contracts constants the BACKEND stamps on those rows, never a second spelling:
651
+ // a rename that missed one side would fall back to the unnamed heading with nothing failing.
652
+ [REPO_BOOTSTRAP_AGENT_KIND]: {
653
+ kind: REPO_BOOTSTRAP_AGENT_KIND,
654
+ tier: 'advanced',
655
+ label: 'Repo Bootstrapper',
656
+ icon: 'i-lucide-package-plus',
657
+ color: '#f59e0b',
658
+ description:
659
+ 'Scaffolds a new repository from a reference architecture, or writes a new service into a monorepo and opens the pull request.',
660
+ },
661
+ [MONOREPO_ADOPTION_AGENT_KIND]: {
662
+ kind: MONOREPO_ADOPTION_AGENT_KIND,
663
+ tier: 'advanced',
664
+ label: 'Adoption Advisor',
665
+ icon: 'i-lucide-scale',
666
+ color: '#f59e0b',
667
+ description:
668
+ 'Reads a monorepo and the reference template and proposes what a new service should adopt from each. Its suggestion is the one a human settles before anything is written.',
669
+ },
639
670
  // The Initiative Planning pipeline's steps. Only runnable on an initiative
640
671
  // block (pl_initiative — enforced by the engine), so they are display-metadata
641
672
  // system kinds, never palette archetypes. The analyst runs FIRST, ahead of the
@@ -3195,7 +3195,8 @@
3195
3195
  "retrying": "Wird wiederholt…",
3196
3196
  "history": {
3197
3197
  "previousErrors": "{count} vorheriger Fehler | {count} vorherige Fehler"
3198
- }
3198
+ },
3199
+ "resumeBootstrap": "Fortsetzen ab: {step}"
3199
3200
  },
3200
3201
  "stop": {
3201
3202
  "label": "Stoppen",
@@ -3814,7 +3815,8 @@
3814
3815
  "cacheRead": "{tokens} aus dem Cache gelesen",
3815
3816
  "cacheReadHint": "Eingabe-Tokens, die aus dem Cache des Providers bedient wurden (etwa 0,1x der Preis frischer Eingabe-Tokens)",
3816
3817
  "cacheWrite": "{tokens} in den Cache geschrieben",
3817
- "cacheWriteHint": "Eingabe-Tokens, die in den Cache des Providers geschrieben wurden (1,25x bis 2x der Preis frischer Eingabe-Tokens)"
3818
+ "cacheWriteHint": "Eingabe-Tokens, die in den Cache des Providers geschrieben wurden (1,25x bis 2x der Preis frischer Eingabe-Tokens)",
3819
+ "costNoRollup": "Nicht bepreist: Die Schätzung wird aus der Aufstellung pro Schritt gebildet, und dieser Lauf hat keine. Was seine Aufrufe verbraucht haben, steht unten."
3818
3820
  },
3819
3821
  "phase": {
3820
3822
  "title": "Wohin die Tokens geflossen sind",
@@ -3829,7 +3831,8 @@
3829
3831
  "costHint": "Geschätzte Kosten der Token dieser Phase zu Listenpreisen. Ein Strich bedeutet, dass diese Installation keinen Satz für das ausgeführte Modell kennt.",
3830
3832
  "carryCostHint": "Wie stark jede Phase die nachfolgenden Runden belastet hat: ihr Kontext einmal für jede spätere Runde gezählt, die ihn erneut senden musste. Vergleichen Sie die Phasen eines Laufs miteinander; für sich allein sagt die Zahl nichts aus. Eine spät laufende Phase schleppt wenig mit, wie viel sie auch verbraucht hat; lesen Sie diese Spalte daher zusammen mit den Tokens daneben.",
3831
3833
  "unattributed": "Nicht zugeordnet",
3832
- "unattributedHint": "von einem Kanal erfasst, der keine Phase meldet"
3834
+ "unattributedHint": "von einem Kanal erfasst, der keine Phase meldet",
3835
+ "noRollup": "Dieser Lauf hat keine Pipeline-Schritte, daher gibt es keine Aufstellung nach Phasen: Seine Modellaufrufe sind unten erfasst, aber nichts gruppiert oder bepreist sie."
3833
3836
  },
3834
3837
  "metricsBar": {
3835
3838
  "calls": "{count} Aufruf | {count} Aufrufe",
@@ -3937,7 +3940,8 @@
3937
3940
  "result": "Ergebnis",
3938
3941
  "dropped": "{chars} Zeichen bei der Erfassung verworfen",
3939
3942
  "truncated": "Es werden die ersten {shown} Aufrufe dieses Laufs angezeigt. Die Zahlen oben gelten für den gesamten Lauf; filtere auf die Fehlschläge, um alle zu sehen.",
3940
- "failuresTruncated": "Es werden die ersten {shown} fehlgeschlagenen Aufrufe angezeigt. Die Zahl oben gilt für den gesamten Lauf."
3943
+ "failuresTruncated": "Es werden die ersten {shown} fehlgeschlagenen Aufrufe angezeigt. Die Zahl oben gilt für den gesamten Lauf.",
3944
+ "surveyReadsElsewhere": "Die Lesevorgänge der Erhebung stehen nicht hier: Sie erkundet über den begrenzten Leser der Plattform, und jeder Lesevorgang ist im Übernahmeprotokoll des Laufs erfasst. Unten stehen die Tool-Aufrufe des Containers, der den Service geschrieben hat."
3941
3945
  }
3942
3946
  },
3943
3947
  "platformObservability": {
@@ -5086,7 +5090,8 @@
5086
5090
  "title": "Letzte Läufe",
5087
5091
  "fromArch": "aus {name}",
5088
5092
  "fromScratch": "von Grund auf",
5089
- "open": "Öffnen"
5093
+ "open": "Öffnen",
5094
+ "openPr": "Pull Request"
5090
5095
  },
5091
5096
  "status": {
5092
5097
  "pending": "ausstehend",
@@ -5134,11 +5139,24 @@
5134
5139
  "label": "Wo der Service entsteht",
5135
5140
  "newRepo": {
5136
5141
  "label": "Ein neues Repository",
5137
- "description": "Ein eigenes Repository anlegen und den Service als ersten Commit pushen."
5142
+ "description": "Ein eigenes Repository anlegen und den Service hineinschreiben."
5138
5143
  },
5139
5144
  "monorepo": {
5140
5145
  "label": "Ein Verzeichnis in einem bestehenden Monorepo",
5141
- "description": "Den Service einem vorhandenen Repository hinzufügen und einen Pull Request öffnen."
5146
+ "description": "Den Service einem Repository hinzufügen, das du bereits hast."
5147
+ }
5148
+ },
5149
+ "delivery": {
5150
+ "label": "Wie die Arbeit ankommt",
5151
+ "pullRequest": {
5152
+ "label": "Pull Request öffnen",
5153
+ "descNewRepo": "Einen Branch pushen und einen Pull Request gegen den ersten Commit des Repositories öffnen, damit jemand das Gerüst prüft, bevor es zum Default-Branch wird. Das Repository muss bereits einen Commit haben.",
5154
+ "descMonorepo": "Einen Branch pushen und einen Pull Request öffnen. Es wird nichts für dich gemergt."
5155
+ },
5156
+ "directPush": {
5157
+ "label": "Direkt pushen",
5158
+ "descNewRepo": "Den Service direkt als ersten Commit auf den Default-Branch schreiben.",
5159
+ "descMonorepo": "Während der Agent arbeitet, direkt auf den Default-Branch committen. Bei einem Fehlschlag bleibt liegen, was bereits geschrieben wurde."
5142
5160
  }
5143
5161
  },
5144
5162
  "serviceName": {
@@ -5146,7 +5164,7 @@
5146
5164
  "description": "Benennt den Service auf dem Board und schlägt sein Verzeichnis vor."
5147
5165
  },
5148
5166
  "monorepo": {
5149
- "intro": "Der Service wird in ein Verzeichnis eines bestehenden Repositories geschrieben und als Pull Request geliefert. Es wird nichts für dich gemergt und nichts außerhalb des neuen Verzeichnisses geändert.",
5167
+ "intro": "Der Service wird in ein Verzeichnis eines bestehenden Repositories geschrieben; außerhalb dieses Verzeichnisses wird nichts geändert.",
5150
5168
  "repo": {
5151
5169
  "label": "Monorepo",
5152
5170
  "description": "Das Repository, in dem der neue Service liegt. Es muss bereits mit diesem Workspace verknüpft sein.",
@@ -5236,7 +5254,26 @@
5236
5254
  "approvedDesc": "Der Agent schreibt jetzt {directory} und öffnet einen Pull Request.",
5237
5255
  "failed": "Prüfung konnte nicht abgeschickt werden"
5238
5256
  }
5239
- }
5257
+ },
5258
+ "steps": {
5259
+ "title": "Bootstrap-Schritte",
5260
+ "name": {
5261
+ "scaffold": "Repository aufsetzen",
5262
+ "survey": "Monorepo und Vorlage untersuchen",
5263
+ "review": "Deine Übernahme-Entscheidungen",
5264
+ "apply": "Service schreiben und Pull Request öffnen"
5265
+ },
5266
+ "state": {
5267
+ "pending": "Nicht begonnen",
5268
+ "running": "Läuft",
5269
+ "awaiting_review": "Wartet auf dich",
5270
+ "done": "Fertig",
5271
+ "failed": "Fehlgeschlagen",
5272
+ "stopped": "Gestoppt",
5273
+ "unknown": "Status nicht lesbar"
5274
+ }
5275
+ },
5276
+ "runKind": "Repository-Bootstrap"
5240
5277
  },
5241
5278
  "fragments": {
5242
5279
  "panel": {
@@ -464,6 +464,10 @@
464
464
  "@previousErrors": {
465
465
  "description": "Count-based tally of a run's earlier failed attempts, rendered as e.g. '3 previous errors' (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)."
466
466
  }
467
+ },
468
+ "resumeBootstrap": "Resume from: {step}",
469
+ "@resumeBootstrap": {
470
+ "description": "Retry label for a multi-step (monorepo) bootstrap, which resumes at the step the run reached rather than starting over. {step} is one of the bootstrap.steps.name values."
467
471
  }
468
472
  },
469
473
  "stop": {
@@ -1872,7 +1876,8 @@
1872
1876
  "cacheRead": "{tokens} cache read",
1873
1877
  "cacheReadHint": "Input tokens served from the provider's cache (about 0.1x the price of fresh input)",
1874
1878
  "cacheWrite": "{tokens} cache write",
1875
- "cacheWriteHint": "Input tokens written into the provider's cache (1.25x to 2x the price of fresh input)"
1879
+ "cacheWriteHint": "Input tokens written into the provider's cache (1.25x to 2x the price of fresh input)",
1880
+ "costNoRollup": "Not priced: the estimate is folded from a run's per-step rollup, and this run has none. What its calls consumed is listed below."
1876
1881
  },
1877
1882
  "phase": {
1878
1883
  "title": "Where the tokens went",
@@ -1887,7 +1892,8 @@
1887
1892
  "costHint": "Estimated cost of this phase's tokens at list rates. A dash means this deployment has no rate for the model that ran.",
1888
1893
  "carryCostHint": "How much each phase burdened the turns that came after it: its context counted once for every later turn that had to re-send it. Compare a run's phases with each other; on its own the number means nothing. A phase that runs late carries little however much it spent, so read this column alongside the tokens beside it.",
1889
1894
  "unattributed": "Unattributed",
1890
- "unattributedHint": "recorded by a channel that reports no phase"
1895
+ "unattributedHint": "recorded by a channel that reports no phase",
1896
+ "noRollup": "This run has no pipeline steps, so there is no per-phase rollup to fold: its model calls are recorded below, but nothing groups or prices them."
1891
1897
  },
1892
1898
  "metricsBar": {
1893
1899
  "calls": "{count} call | {count} calls",
@@ -1995,7 +2001,8 @@
1995
2001
  "result": "Result",
1996
2002
  "dropped": "{chars} characters dropped at capture",
1997
2003
  "truncated": "Showing the first {shown} calls of this run. The counts above are for the whole run; narrow to the failures to see all of them.",
1998
- "failuresTruncated": "Showing the first {shown} failing calls. The count above is for the whole run."
2004
+ "failuresTruncated": "Showing the first {shown} failing calls. The count above is for the whole run.",
2005
+ "surveyReadsElsewhere": "The survey's own reads are not here: it explores through the platform's bounded reader, and every read it made is recorded on the run's adoption transcript. Below are the tool calls of the container that wrote the service."
1999
2006
  }
2000
2007
  },
2001
2008
  "platformObservability": {
@@ -7276,7 +7283,8 @@
7276
7283
  "title": "Recent runs",
7277
7284
  "fromArch": "from {name}",
7278
7285
  "fromScratch": "from scratch",
7279
- "open": "Open"
7286
+ "open": "Open",
7287
+ "openPr": "Pull request"
7280
7288
  },
7281
7289
  "status": {
7282
7290
  "pending": "pending",
@@ -7324,11 +7332,24 @@
7324
7332
  "label": "Where the service goes",
7325
7333
  "newRepo": {
7326
7334
  "label": "A new repository",
7327
- "description": "Create a repository of its own and push the service as its first commit."
7335
+ "description": "Create a repository of its own and write the service into it."
7328
7336
  },
7329
7337
  "monorepo": {
7330
7338
  "label": "A directory in an existing monorepo",
7331
- "description": "Add the service to a repository you already have, and open a pull request."
7339
+ "description": "Add the service to a repository you already have."
7340
+ }
7341
+ },
7342
+ "delivery": {
7343
+ "label": "How the work lands",
7344
+ "pullRequest": {
7345
+ "label": "Open a pull request",
7346
+ "descNewRepo": "Push a branch and open a pull request against the repository's first commit, so someone reviews the scaffold before it becomes the default branch. The repository must already have a commit.",
7347
+ "descMonorepo": "Push a branch and open a pull request. Nothing is merged for you."
7348
+ },
7349
+ "directPush": {
7350
+ "label": "Push directly",
7351
+ "descNewRepo": "Write the service straight onto the default branch as the repository's first commit.",
7352
+ "descMonorepo": "Commit onto the default branch as the agent works. A run that fails leaves what it had already written behind."
7332
7353
  }
7333
7354
  },
7334
7355
  "serviceName": {
@@ -7336,7 +7357,7 @@
7336
7357
  "description": "Names the service on the board and seeds its directory."
7337
7358
  },
7338
7359
  "monorepo": {
7339
- "intro": "The service is written into a directory of an existing repository and delivered as a pull request. Nothing is merged for you, and nothing outside the new directory is changed.",
7360
+ "intro": "The service is written into a directory of an existing repository, and nothing outside that directory is changed.",
7340
7361
  "repo": {
7341
7362
  "label": "Monorepo",
7342
7363
  "description": "The repository the new service lives in. It must already be linked to this workspace.",
@@ -7426,6 +7447,31 @@
7426
7447
  "approvedDesc": "The agent is now writing {directory} and will open a pull request.",
7427
7448
  "failed": "Could not submit the review"
7428
7449
  }
7450
+ },
7451
+ "steps": {
7452
+ "title": "Bootstrap steps",
7453
+ "name": {
7454
+ "scaffold": "Scaffold the repository",
7455
+ "survey": "Survey the monorepo and the template",
7456
+ "review": "Your adoption decisions",
7457
+ "apply": "Write the service and open the pull request"
7458
+ },
7459
+ "state": {
7460
+ "pending": "Not started",
7461
+ "running": "Running",
7462
+ "awaiting_review": "Waiting for you",
7463
+ "done": "Done",
7464
+ "failed": "Failed",
7465
+ "stopped": "Stopped",
7466
+ "unknown": "State unreadable"
7467
+ }
7468
+ },
7469
+ "@steps": {
7470
+ "description": "The moves a bootstrap run is made of. A new-repo bootstrap is only `scaffold`; a monorepo bootstrap is survey → your decisions → apply. `state.stopped` is a run a person stopped, which is stored as a failure without being one; `state.unknown` is for a stored run status this build no longer defines."
7471
+ },
7472
+ "runKind": "Repo bootstrap",
7473
+ "@runKind": {
7474
+ "description": "The kind of run the observability panel is showing, in the line under its title where a task run names its pipeline instead. Keep it short."
7429
7475
  }
7430
7476
  },
7431
7477
  "initiative": {
@@ -413,7 +413,8 @@
413
413
  "retrying": "Reintentando…",
414
414
  "history": {
415
415
  "previousErrors": "{count} error anterior | {count} errores anteriores"
416
- }
416
+ },
417
+ "resumeBootstrap": "Reanudar desde: {step}"
417
418
  },
418
419
  "stop": {
419
420
  "label": "Detener",
@@ -1768,7 +1769,8 @@
1768
1769
  "cacheRead": "{tokens} leídos de caché",
1769
1770
  "cacheReadHint": "Tokens de entrada servidos desde la caché del proveedor (unas 0,1 veces el precio de la entrada fresca)",
1770
1771
  "cacheWrite": "{tokens} escritos en caché",
1771
- "cacheWriteHint": "Tokens de entrada escritos en la caché del proveedor (de 1,25 a 2 veces el precio de la entrada fresca)"
1772
+ "cacheWriteHint": "Tokens de entrada escritos en la caché del proveedor (de 1,25 a 2 veces el precio de la entrada fresca)",
1773
+ "costNoRollup": "Sin valorar: la estimación se calcula a partir del resumen por paso, y esta ejecución no tiene ninguno. Abajo se indica lo que consumieron sus llamadas."
1772
1774
  },
1773
1775
  "phase": {
1774
1776
  "title": "Adónde fueron los tokens",
@@ -1783,7 +1785,8 @@
1783
1785
  "costHint": "Coste estimado de los tokens de esta fase a precios de lista. Un guion indica que esta instalación no tiene tarifa para el modelo que se ejecutó.",
1784
1786
  "carryCostHint": "Cuánto cargó cada fase sobre los turnos posteriores: su contexto contado una vez por cada turno que tuvo que reenviarlo. Compara entre sí las fases de una ejecución; por sí sola la cifra no significa nada. Una fase que se ejecuta al final arrastra poco por mucho que haya gastado, así que lee esta columna junto a los tokens de al lado.",
1785
1787
  "unattributed": "Sin atribuir",
1786
- "unattributedHint": "registrado por un canal que no informa de la fase"
1788
+ "unattributedHint": "registrado por un canal que no informa de la fase",
1789
+ "noRollup": "Esta ejecución no tiene pasos de pipeline, así que no hay un resumen por fase: sus llamadas al modelo están registradas abajo, pero nada las agrupa ni las valora."
1787
1790
  },
1788
1791
  "metricsBar": {
1789
1792
  "calls": "{count} llamada | {count} llamadas",
@@ -1891,7 +1894,8 @@
1891
1894
  "result": "Resultado",
1892
1895
  "dropped": "{chars} caracteres descartados al capturar",
1893
1896
  "truncated": "Se muestran las primeras {shown} llamadas de esta ejecución. Los recuentos de arriba corresponden a la ejecución completa; filtra por los fallos para verlos todos.",
1894
- "failuresTruncated": "Se muestran las primeras {shown} llamadas fallidas. El recuento de arriba corresponde a la ejecución completa."
1897
+ "failuresTruncated": "Se muestran las primeras {shown} llamadas fallidas. El recuento de arriba corresponde a la ejecución completa.",
1898
+ "surveyReadsElsewhere": "Las lecturas del estudio no están aquí: explora mediante el lector acotado de la plataforma y cada lectura queda registrada en la transcripción de adopción de la ejecución. Abajo están las llamadas a herramientas del contenedor que escribió el servicio."
1895
1899
  }
1896
1900
  },
1897
1901
  "platformObservability": {
@@ -6952,7 +6956,8 @@
6952
6956
  "title": "Ejecuciones recientes",
6953
6957
  "fromArch": "desde {name}",
6954
6958
  "fromScratch": "desde cero",
6955
- "open": "Abrir"
6959
+ "open": "Abrir",
6960
+ "openPr": "Pull request"
6956
6961
  },
6957
6962
  "status": {
6958
6963
  "pending": "pendiente",
@@ -7004,11 +7009,24 @@
7004
7009
  "label": "Dónde va el servicio",
7005
7010
  "newRepo": {
7006
7011
  "label": "Un repositorio nuevo",
7007
- "description": "Crear un repositorio propio y subir el servicio como su primer commit."
7012
+ "description": "Crear un repositorio propio y escribir el servicio en él."
7008
7013
  },
7009
7014
  "monorepo": {
7010
7015
  "label": "Un directorio de un monorepo existente",
7011
- "description": "Añadir el servicio a un repositorio que ya tienes y abrir un pull request."
7016
+ "description": "Añadir el servicio a un repositorio que ya tienes."
7017
+ }
7018
+ },
7019
+ "delivery": {
7020
+ "label": "Cómo se entrega el trabajo",
7021
+ "pullRequest": {
7022
+ "label": "Abrir un pull request",
7023
+ "descNewRepo": "Subir una rama y abrir un pull request contra el primer commit del repositorio, para que alguien revise el andamiaje antes de que sea la rama principal. El repositorio ya debe tener un commit.",
7024
+ "descMonorepo": "Subir una rama y abrir un pull request. No se fusiona nada por ti."
7025
+ },
7026
+ "directPush": {
7027
+ "label": "Subir directamente",
7028
+ "descNewRepo": "Escribir el servicio directamente en la rama principal como primer commit del repositorio.",
7029
+ "descMonorepo": "Hacer commits en la rama principal mientras el agente trabaja. Si la ejecución falla, queda lo que ya se había escrito."
7012
7030
  }
7013
7031
  },
7014
7032
  "serviceName": {
@@ -7016,7 +7034,7 @@
7016
7034
  "description": "Nombra el servicio en el tablero y propone su directorio."
7017
7035
  },
7018
7036
  "monorepo": {
7019
- "intro": "El servicio se escribe en un directorio de un repositorio existente y se entrega como pull request. No se fusiona nada por ti ni se cambia nada fuera del nuevo directorio.",
7037
+ "intro": "El servicio se escribe en un directorio de un repositorio existente, y no se cambia nada fuera de ese directorio.",
7020
7038
  "repo": {
7021
7039
  "label": "Monorepo",
7022
7040
  "description": "El repositorio donde vivirá el nuevo servicio. Ya debe estar vinculado a este espacio de trabajo.",
@@ -7106,7 +7124,26 @@
7106
7124
  "approvedDesc": "El agente está escribiendo {directory} y abrirá un pull request.",
7107
7125
  "failed": "No se pudo enviar la revisión"
7108
7126
  }
7109
- }
7127
+ },
7128
+ "steps": {
7129
+ "title": "Pasos del bootstrap",
7130
+ "name": {
7131
+ "scaffold": "Crear la estructura del repositorio",
7132
+ "survey": "Analizar el monorepo y la plantilla",
7133
+ "review": "Tus decisiones de adopción",
7134
+ "apply": "Escribir el servicio y abrir la pull request"
7135
+ },
7136
+ "state": {
7137
+ "pending": "Sin empezar",
7138
+ "running": "En curso",
7139
+ "awaiting_review": "Esperándote",
7140
+ "done": "Hecho",
7141
+ "failed": "Con error",
7142
+ "stopped": "Detenido",
7143
+ "unknown": "Estado ilegible"
7144
+ }
7145
+ },
7146
+ "runKind": "Arranque de repositorio"
7110
7147
  },
7111
7148
  "riskPolicy": {
7112
7149
  "health": {