Repository navigation
Cloud: show startup checklist in chat #30386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
650e977
1b7e56b
f84428e
1357cf7
33c0699
961bd86
8fb4e85
55091e8
a9df367
c9403f3
975eedf
98174c3
8009b7b
73fd563
f7093c3
b624e25
c8012ba
9db6f6d
1de8175
409d77a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -17,9 +17,10 @@ const begun: CloudStartProgress = { | |||||
| folder: "paint", | ||||||
| }; | ||||||
| const known = { machine: "paint-dev", size: "4 CPU · 16 GB", secrets: 3, network: "limited" } as const; | ||||||
| const timing = { startedAt: 10_000, finishedAt: 12_400 } as const; | ||||||
|
|
||||||
| const showStart: Play = async (ctx) => { | ||||||
| await ctx.waitFor(() => ctx.document.querySelector(".acpmux-cloud-start__status")); | ||||||
| await ctx.waitFor(() => ctx.document.querySelector(".acpmux-cloud-start__summary")); | ||||||
| }; | ||||||
|
|
||||||
| export default componentEntry<ComponentProps<typeof CloudStartView>>({ | ||||||
|
|
@@ -63,6 +64,34 @@ export default componentEntry<ComponentProps<typeof CloudStartView>>({ | |||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| "checklist-machine": { | ||||||
| note: "Cloud machine is being created; the machine step spins while later steps remain quiet.", | ||||||
| props: { start: { ...begun, machineStartedAt: 10_000, machine: known.machine } }, | ||||||
| }, | ||||||
| "checklist-clone": { | ||||||
| note: "A repository is being cloned into the chat folder.", | ||||||
| props: { start: { ...begun, hasRepository: true, repository: "manaflow-ai/cmux", machine: known.machine, machineFinishedAt: 12_400, clone: { state: "running", ...timing } } }, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The clone fixture marks the operation running but supplies Prompt for AI agents |
||||||
| }, | ||||||
| "checklist-setup-cached": { | ||||||
| note: "The environment snapshot is ready, so setup completes from cache.", | ||||||
| props: { start: { ...begun, hasRepository: true, repository: "manaflow-ai/cmux", clone: { state: "done", ...timing }, setup: { state: "done", status: "ready", ...timing } } }, | ||||||
| }, | ||||||
| "checklist-setup-running": { | ||||||
| note: "The derived environment is still building its setup snapshot.", | ||||||
| props: { start: { ...begun, hasRepository: true, repository: "manaflow-ai/cmux", clone: { state: "done", ...timing }, setup: { state: "running", status: "building", startedAt: 10_000 } } }, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The running fixtures pass an epoch timestamp of Prompt for AI agents |
||||||
| }, | ||||||
| "checklist-setup-failed": { | ||||||
| note: "Setup failed and the card keeps the short log tail inline.", | ||||||
| props: { start: { ...begun, hasRepository: true, repository: "manaflow-ai/cmux", clone: { state: "done", ...timing }, setup: { state: "failed", status: "failed", logTail: "npm ERR! missing script: build", ...timing } } }, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The expanded checklist scenes exceed the entry's fixed 300px gallery surface, so the new rows and setup log tail are clipped by the gallery window. Give the checklist variants a larger height or raise the entry height. Prompt for AI agents |
||||||
| }, | ||||||
| "checklist-setup-skipped": { | ||||||
| note: "No setup script is configured; the link opens Edit cloud environment at Script.", | ||||||
| props: { start: { ...begun, hasRepository: true, repository: "manaflow-ai/cmux", clone: { state: "done", ...timing }, setup: { state: "skipped", hasScript: false } } }, | ||||||
| }, | ||||||
| initialized: { | ||||||
| note: "Once the harness starts, the checklist folds to one quiet line.", | ||||||
| props: { start: { ...begun, initialized: true, agent: "Claude Code", harnessStartedAt: 12_400, harnessFinishedAt: 12_900 } }, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The initialized fixture has a repository folder but no completed clone state, so expanding its collapsed summary shows Prompt for AI agents
Suggested change
|
||||||
| }, | ||||||
| }, | ||||||
| // The gallery loads no experiment without a step (format.ts validateEntries): the card is static, | ||||||
| // so its one step waits for the card the arm draws. | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,7 +4,7 @@ | |||||||||||||||||
| // `cloud-start-look` experiment draws the same facts. | ||||||||||||||||||
| import { afterEach, expect, test } from "bun:test"; | ||||||||||||||||||
| import { renderToStaticMarkup } from "react-dom/server"; | ||||||||||||||||||
| import { CloudStartView } from "./CloudStartView"; | ||||||||||||||||||
| import { CloudStartView, startupChecklist } from "./CloudStartView"; | ||||||||||||||||||
| import type { CloudStartProgress } from "./cloudStartProgress"; | ||||||||||||||||||
|
|
||||||||||||||||||
| const start: CloudStartProgress = { | ||||||||||||||||||
|
|
@@ -54,3 +54,34 @@ test("a failure says the host's words with no spinner, and the New Tab page draw | |||||||||||||||||
| expect(html).not.toContain("cv-spinner"); | ||||||||||||||||||
| expect(html).not.toContain("fix the build"); | ||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| test("the startup checklist skips clone without a repository and explains a missing script", () => { | ||||||||||||||||||
| const rows = startupChecklist({ key: "k", task: "hi", state: "starting", home: true, setup: { state: "skipped", hasScript: false } }); | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: This new checklist input exceeds the repository's 120-column Oxfmt width, so Prompt for AI agents
Suggested change
|
||||||||||||||||||
| expect(rows.map((row) => row.status)).toEqual(["pending", "skipped", "skipped", "pending"]); | ||||||||||||||||||
| expect(rows[2]?.action).toBe(true); | ||||||||||||||||||
| expect(rows[2]?.detail).toContain("Add a setup script"); | ||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| test("environment setup status maps cached, running and failed states", () => { | ||||||||||||||||||
| const base = { key: "k", task: "hi", state: "starting" as const }; | ||||||||||||||||||
| expect(startupChecklist({ ...base, setup: { state: "done", status: "ready" } })[2]?.detail).toBe("cached"); | ||||||||||||||||||
| expect(startupChecklist({ ...base, setup: { state: "running", status: "building" } })[2]?.status).toBe("running"); | ||||||||||||||||||
| expect(startupChecklist({ ...base, setup: { state: "failed", status: "failed", logTail: "npm ERR!" } })[2]).toMatchObject({ status: "error", logTail: "npm ERR!" }); | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: This new assertion also exceeds the repository's 120-column Oxfmt width, so the formatting check will still fail after the other long line is fixed. Break the nested call before the matcher. Prompt for AI agents
Suggested change
|
||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| test("clone status keeps seed phase and object progress in the row", () => { | ||||||||||||||||||
| const rows = startupChecklist({ key: "k", task: "hi", state: "starting", hasRepository: true, clone: { state: "running", phase: "Receiving objects", progress: { objects: 2, totalObjects: 4, receivedBytes: 2048 } } }); | ||||||||||||||||||
| expect(rows[1]?.detail).toBe("Receiving objects · 2/4 objects · 2 KB"); | ||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| test("a machine failure stops a clone spinner", () => { | ||||||||||||||||||
| const rows = startupChecklist({ key: "k", task: "hi", state: "failed", step: "machine", hasRepository: true, clone: { state: "running" } }); | ||||||||||||||||||
| expect(rows[0]?.status).toBe("error"); | ||||||||||||||||||
| expect(rows[1]?.status).toBe("pending"); | ||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| test("a missing setup script is plain text without an environment callback", () => { | ||||||||||||||||||
| const html = renderToStaticMarkup(<CloudStartView start={{ key: "k", task: "hi", state: "starting", home: true, setup: { state: "skipped", hasScript: false } }} />); | ||||||||||||||||||
| expect(html).toContain("Add a setup script to install dependencies and configure your environment."); | ||||||||||||||||||
| expect(html).not.toContain('class="acpmux-cloud-start__link"'); | ||||||||||||||||||
| }); | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: These fixtures do not render the checklist states described by their notes: the machine row remains pending because the fixtures omit
step. Setstep: "machine"for the machine scene andstep: "folder"for later-stage scenes so the machine row becomes running or done.Prompt for AI agents