diff --git a/src/renderer/src/components/worktree-creation/VmBuildSheet.tsx b/src/renderer/src/components/worktree-creation/VmBuildSheet.tsx
index 0748c02cdac..0ef94ca7d64 100644
--- a/src/renderer/src/components/worktree-creation/VmBuildSheet.tsx
+++ b/src/renderer/src/components/worktree-creation/VmBuildSheet.tsx
@@ -293,11 +293,7 @@ export function VmBuildSheet({
: null
}
timing={timings[step.id] ?? null}
- stopped={failure !== null}
t={t}
- waitedMs={
- steps.find((candidate) => candidate.id === 'provision')?.elapsedMs ?? 0
- }
/>
))}
{/* Orca Cloud: agent setup happens after create (the setup page and the workspace's
diff --git a/src/renderer/src/components/worktree-creation/VmBuildStepRow.test.tsx b/src/renderer/src/components/worktree-creation/VmBuildStepRow.test.tsx
index 1d1cf2fd03f..97d5cf80dfa 100644
--- a/src/renderer/src/components/worktree-creation/VmBuildStepRow.test.tsx
+++ b/src/renderer/src/components/worktree-creation/VmBuildStepRow.test.tsx
@@ -1,15 +1,12 @@
// @vitest-environment happy-dom
-import { act, cleanup, render } from '@testing-library/react'
-import { afterEach, expect, it, vi } from 'vitest'
+import { cleanup, render } from '@testing-library/react'
+import { afterEach, expect, it } from 'vitest'
import type { Translate } from '@/i18n/use-translate'
import { VmBuildStepRow } from './VmBuildStepRow'
import type { VmBuildStep } from './vm-build-steps'
-afterEach(() => {
- cleanup()
- vi.useRealTimers()
-})
+afterEach(cleanup)
const t: Translate = (_key, fallback) => fallback
const pendingClone = (cloneMode?: 'clone' | 'update'): VmBuildStep => ({
@@ -22,50 +19,19 @@ const pendingClone = (cloneMode?: 'clone' | 'update'): VmBuildStep => ({
...(cloneMode ? { cloneMode } : {})
})
-it('names the repository row once: no label guessed, a placeholder only after 150 ms (PC-4)', () => {
- vi.useFakeTimers()
- const row = (step: VmBuildStep) => (
-
-
-
- )
- const { container, rerender } = render(row(pendingClone()))
- // Accessible name only; no visible label, no placeholder yet (the plan usually answers by now).
- expect(container.textContent).toContain('Repository')
- expect(container.textContent).not.toContain('Clone repository')
- expect(container.querySelector('[data-slot="skeleton"]')).toBeNull()
- act(() => {
- vi.advanceTimersByTime(160)
- })
- expect(container.querySelector('[data-slot="skeleton"]')).not.toBeNull()
- // The plan answers: the one label, never changed afterwards.
- rerender(row(pendingClone('update')))
- expect(container.querySelector('[data-slot="skeleton"]')).toBeNull()
- expect(container.textContent).toContain('Update repository')
-})
+const row = (step: VmBuildStep) => (
+
+
+
+)
-it('names an undecided repository step neutrally once the start has failed (N-12)', () => {
- const { container } = render(
-
-
-
- )
+it('reads "Get repository" until the boot plan answers, then switches in place, no placeholder bar', () => {
+ const { container, rerender } = render(row(pendingClone()))
expect(container.textContent).toContain('Get repository')
expect(container.querySelector('[data-slot="skeleton"]')).toBeNull()
-})
-
-it('shows the placeholder at once when the create has already waited past 150 ms (no blank row)', () => {
- const { container } = render(
-
-
-
- )
- expect(container.querySelector('[data-slot="skeleton"]')).not.toBeNull()
+ rerender(row(pendingClone('update')))
+ expect(container.textContent).toContain('Update repository')
+ expect(container.textContent).not.toContain('Get repository')
+ rerender(row(pendingClone('clone')))
+ expect(container.textContent).toContain('Clone repository')
})
diff --git a/src/renderer/src/components/worktree-creation/VmBuildStepRow.tsx b/src/renderer/src/components/worktree-creation/VmBuildStepRow.tsx
index 5379ee88272..f11eba5fa55 100644
--- a/src/renderer/src/components/worktree-creation/VmBuildStepRow.tsx
+++ b/src/renderer/src/components/worktree-creation/VmBuildStepRow.tsx
@@ -3,7 +3,6 @@ import { CircleSlash } from 'lucide-react'
import { cn } from '@/lib/utils'
import type { Translate } from '@/i18n/use-translate'
import { Progress } from '@/components/ui/progress'
-import { Skeleton } from '@/components/ui/skeleton'
import { StepIcon } from './WorktreeSetupSteps'
import type { VmBuildStep } from './vm-build-steps'
import {
@@ -14,47 +13,21 @@ import {
import { formatElapsedTime } from './worktree-creation-clock'
import { stepLabel, stepStateLabel } from './vm-build-sheet-copy'
-/** The boot plan usually answers within this; only a slower answer shows the placeholder. */
-const PLACEHOLDER_DELAY_MS = 150
-
-/** True once `active` has held for `delayMs` (the row's mode is unknown only once per create). */
-function useDelayedFlag(active: boolean, delayMs: number): boolean {
- const [due, setDue] = React.useState(false)
- React.useEffect(() => {
- if (!active) {
- return
- }
- const timer = window.setTimeout(() => setDue(true), delayMs)
- return () => window.clearTimeout(timer)
- }, [active, delayMs])
- return active && due
-}
-
/** One timed row of the build checklist; the failure card, not the row, carries the red. */
export function VmBuildStepRow({
step,
cloud,
detail,
timing,
- stopped = false,
- t,
- waitedMs = 0
+ t
}: {
step: VmBuildStep
cloud: boolean
- /** The build stopped (a failure card shows): an undecided clone/update never will be decided. */
- stopped?: boolean
/** The step's measured duration, when there is one. */
timing: VmBuildStepTiming | null
/** What the running step is doing right now, in plain words. */
detail: string | null
t: Translate
- /**
- * How long the create has been running (the sandbox step's time). Past PLACEHOLDER_DELAY_MS the
- * boot plan had its chance to answer, so a still-unknown row shows its placeholder at once: no
- * blank row, also not in a fixture or a remount.
- */
- waitedMs?: number
}): React.JSX.Element {
const labelId = React.useId()
// A live percent already says how far along the step is.
@@ -65,11 +38,9 @@ export function VmBuildStepRow({
timing?.p95Ms ?? (cloud && step.id === 'provision' ? SLOW_WITHOUT_MEASURE_MS : null)
const slow =
measuring && slowAfterMs !== null && step.elapsedMs !== null && step.elapsedMs > slowAfterMs
+ // Clone or update is known once the boot plan answers; until then (or for good, if the start
+ // failed first) the row reads "Get repository" with its empty circle, then switches in place.
const undecided = cloud && step.id === 'clone' && step.state === 'pending' && !step.cloneMode
- // N-12: once the start has failed, the mode stays unknown for good: name the step neutrally.
- const modeUnknown = undecided && !stopped
- const placeholderDelayed = useDelayedFlag(modeUnknown, PLACEHOLDER_DELAY_MS)
- const placeholderDue = modeUnknown && (placeholderDelayed || waitedMs >= PLACEHOLDER_DELAY_MS)
return (
- {modeUnknown ? (
- // Clone or update is decided in a moment (boot plan): a placeholder, never a guessed label.
- // Usually decided within ~150 ms, so the placeholder shows only after that (no blink).
- <>
-
- {t(
- 'auto.components.worktree.creation.VmBuildSheet.repositoryPending',
- 'Repository'
- )}
-
- {placeholderDue ? (
-
- ) : (
-
- {'\u00a0'}
-
- )}
- >
- ) : undecided ? (
- t('auto.components.worktree.creation.VmBuildSheet.getRepository', 'Get repository')
- ) : (
- stepLabel(step, cloud, t)
- )}
+ {undecided
+ ? t('auto.components.worktree.creation.VmBuildSheet.getRepository', 'Get repository')
+ : stepLabel(step, cloud, t)}
{step.skipped
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index a2f3a926a1d..77ef1aa3a4f 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -4258,7 +4258,6 @@
"cloneCounting": "Counting objects…",
"updateCloud": "Update repository",
"updateFetching": "Fetching changes…",
- "repositoryPending": "Repository",
"getRepository": "Get repository"
},
"VmBuildFailureCard": {