Skip to content

UX review · P3 G2, the launch boards: engine buttons and path-or-Git

Board review of autopilot/P3-G2, base 531112f, 2026-10-30. The step is P2 §10.2 G2. It applies ui-spec §4.6 (note 2026-10-29), P1 Assumption 2 and api §5 (imports are untrusted input) to LiteLaunch, LiteLaunchSnakemake and MLiteLaunch in design/ui-canvas/, with the page head of ui-spec §7.

Reviewers. The worker session had no tool to start a sub-agent, as in G1. It first ran a self-check against the ux-reviewer brief (.claude/agents/ux-reviewer.md): findings UX-G2-01 to -08. The coordinator then ran an independent ux-reviewer: findings UX-G2-09 to -14 and a few nits in round 1, then UX-G2-15 to -17 and a nit in round 2. The doc-reviewer returned changes (9/14) on the first docs, then approve (12/14) after the revision in efe9e31.

Round Head Reviewer Verdict
self the first draw, before its fixes worker, ux-reviewer brief changes (0 blockers, 2 majors, 6 minors): UX-G2-01 to -03 fixed in 9a61c33; UX-G2-04 to -06 deferred to /apply-findings; UX-G2-07 and -08 left for Task 19
1 1c94012 ux-reviewer, independent changes (0 blockers, 2 majors, 6 minors): UX-G2-09 to -13 and the nits fixed in 7114560; UX-G2-14 deferred to /apply-findings
2 efe9e31 ux-reviewer, independent approve (0 blockers, 0 majors, 3 minors and a nit): UX-G2-15, -16 and the nit fixed in 3c955ae; UX-G2-17 left for Task 19

What was rendered and looked at. After every board change:

  • LiteLaunch and LiteLaunchSnakemake at 1440 × 1180 and 1024 × 1180. They were also rendered 4600 px (LiteLaunch) and 5200 px (LiteLaunchSnakemake) tall, to read the "Pipeline section: other states" cards at the foot of the page.
  • MLiteLaunch at 390 × 844. A scratch copy with a 3400 px frame showed the state cards at the foot; it was deleted after the render.
  • The regenerated lite-launch screenshot.

A script checked the three boards: no duplicate id, and every for, aria-describedby, aria-labelledby and aria-controls points to an existing id.

What the boards show

At 7114560:

  • Page head (desktop): a 48 px icon tile with the sidebar's Launch tint (#FDF2F5) and a coral-700 icon (#A54666), "Launch a workflow" in the Outfit heading font, one line of description, and Launch on the right.
  • Launch at the end of the aside, as in ui-spec §4.6. It shares the head button's state; on LiteLaunchSnakemake both are disabled with "Fill the required field: samples" beside them. From 1200 px the aside is sticky (top: 8px), so the second Launch stays in view while the parameters scroll.
  • Pipeline field: it takes an absolute path, a GitHub or nf-core name, or an https:// or ssh URL. Revision (Git only) and Load sit beside it.
    • With a path, the revision is a disabled native input, and its reason is shown: "Read as a directory: there is no revision to give".
    • With a Git source, Revision is required (required, aria-required). A short name is read before Load: "Read as GitHub: https://github.com/snakemake-workflows/rna-seq-star-deseq2".
    • LiteLaunch and MLiteLaunch show a path; LiteLaunchSnakemake shows snakemake-workflows/rna-seq-star-deseq2 at v2.1.2.
  • Engine: a role="group" labelled "Engine", with two native <button type="button" aria-pressed>, Nextflow and Snakemake, each with its logo. The pressed button has a check mark and a heavier border, so the state is not shown by colour alone. Beside them:
    • "Nextflow, as in rnaseq-2026-10-25 · change it if it is wrong" on LiteLaunch, which is prefilled from that run;
    • "Guessed from workflow/Snakefile · change it if the guess is wrong" on LiteLaunchSnakemake;
    • "Guessed from main.nf · change it if the guess is wrong" on MLiteLaunch.
  • Errors: each error comes first in its field's aria-describedby and has role="alert", so it is announced when Load is pressed.
  • States, drawn as cards under "Pipeline section: other states":
Board State What it shows
LiteLaunch, MLiteLaunch No guess: both files found main.nf and workflow/Snakefile found. No engine button is pressed, "No guess: choose the engine", and Launch is disabled with "Choose the engine" (on the phone, in a drawn copy of the pinned bar)
LiteLaunch Guess overruled: Snakemake chosen, no Snakefile here Snakemake pressed on a directory with only main.nf. Beside the buttons: "workflow/Snakefile not found: Launch will refuse. Guessed: Nextflow (main.nf)". Launch is disabled with "No Snakefile in this directory: press Nextflow or check the path"
LiteLaunchSnakemake No guess: neither file found No main.nf, Snakefile or workflow/Snakefile. Neither button is pressed, and Launch stays disabled with "No main.nf or Snakefile in this directory: check the path", whatever is pressed
LiteLaunchSnakemake Load pressed without a revision The "Read as GitHub" line; Revision empty and aria-invalid, with "Give a tag, branch or commit."
LiteLaunchSnakemake Fetching… at v2.1.2 Load reads "Fetching…" with aria-busy="true". Status: "Cloning https://github.com/snakemake-workflows/rna-seq-star-deseq2 (once per revision)". Launch waits with "Wait for the pipeline to load", in neutral grey, as it is not an error
LiteLaunchSnakemake Not fetched: revision not found Field error on Revision: "Not fetched: revision v9 not found in snakemake-workflows/rna-seq-star-deseq2." The card note lists the other fetch failures: repository not found or private, login1 cannot reach github.com, ssh asked for a password or a passphrase
LiteLaunch, MLiteLaunch Refused: a file:// URL aria-invalid on the Pipeline field. "Refused: Git repositories are fetched over https:// or ssh only, so file:// and ext:: are refused. For a directory on this machine, type its absolute path."
LiteLaunchSnakemake Refused: a revision that starts with - --upload-pack=x: "Refused: a revision cannot start with -. Type a tag, branch or commit." (G5's test_git_revision_not_an_option). The note: "A separate rule refuses a file:// or ext:: URL in the Pipeline field."

Findings

UX-G2-01 · major · The state cards squeezed the Pipeline field to a few pixels at 1024 px

  • Where: LiteLaunch.dc.html, LiteLaunchSnakemake.dc.html, the two state cards at the foot of the page.
  • Evidence: in the first draw, the Pipeline, Revision and Load row was a grid with a fixed Revision column. At 1024 px each card is about 360 px wide. The Pipeline input shrank to about 40 px ("/g/de"), and its help text wrapped one word per line.
  • Fix: the row is a wrapping flex row: Pipeline flex: 999 1 280px, Revision flex: 1 1 220px up to 260 px, then Load. In a narrow card, Revision and Load go to a second line.
  • Status: applied in 9a61c33. Checked at 1440 and 1024 px.

UX-G2-02 · minor · The Revision placeholder was clipped at 1440 px

  • Where: the same row in the Pipeline section of both desktop boards.
  • Evidence: at a 160 px basis, the placeholder read "tag, branch or comm".
  • Fix: a 220 px basis. The placeholder now fits.
  • Status: applied in 9a61c33.

UX-G2-03 · minor · The repeated Load and Launch buttons in the state cards did not name their card

  • Where: the state cards of the three boards.
  • Evidence: a screen reader's button list read "Load" three times and "Launch" three times, with no way to tell which card each belongs to (CLAUDE.md: per-row labels name the row).
  • Fix: each card's Load and Launch buttons carry aria-describedby with the card's heading ("No guess: both files found", "Refused: a file:// URL"…). Each card's engine group is labelled by "Engine" and the card heading.
  • Status: applied in 9a61c33.

UX-G2-04 · major · GET /workflows:inspect cannot feed the guess line or tell "both" from "neither"

  • Where: P1 Task 17 (interface of GET /api/v1/workflows:inspect), api §5; the boards' "Guessed from main.nf", "both found" and "neither found" texts.
  • Evidence: inspect returns engine (null for both and for neither) and engine_version for that engine only. It does not return the files it found. The board needs them to say which file the guess came from, and to tell the two no-guess cases apart. G5's guessEngine(files: string[]) has no input either. "Where it runs" also shows an engine version; once the user presses the other engine, that version has no source.
  • Proposal: inspect also returns engine_files (those of main.nf, Snakefile and workflow/Snakefile that exist), and an engine version per engine, or GET /version lists both. guessEngine takes engine_files.
  • Status: deferred to /apply-findings (P1 Task 17 and api §5 are specs; not edited in a board step).

UX-G2-05 · minor · ui-spec §4.6 does not give the wording and placement drawn here

  • Where: ui-spec §4.6, note 2026-10-29.
  • Evidence: the note says "two buttons" and "a path on the machine or a Git repository and revision". It says nothing about:
    • the Revision field ("Git only", disabled with its reason for a path);
    • the "Guessed from " line beside the buttons;
    • the no-guess text, and that Launch stays disabled until an engine is chosen;
    • the refusal messages;
    • Launch in the page head, with its reason beside it;
    • Launch appears twice, in the page head and at the end of the aside, with one shared state (UX-G2-09);
    • the short-name grammar: owner/repo is read as GitHub, nf-core/<name> as https://github.com/nf-core/<name> (UX-G2-12);
    • Revision is required for a Git source;
    • on a prefilled launch, the engine line names the source run ("Nextflow, as in rnaseq-2026-10-25") instead of the guess (UX-G2-13).
  • Proposal: extend the note with these points and link the three boards.
  • Status: deferred to /apply-findings.

UX-G2-06 · minor · mvp-0.0.1 §2 still describes the old launch form

  • Where: mvp-0.0.1 §2, the note of 2026-10-29 above the screenshots, and the lite-launch alt text.
  • Evidence: the note says the boards "show the look before depictio's Paper chrome and a detected engine". The alt text names "a pipeline directory and Load, the detected engine". The regenerated screenshot now shows the Pipeline and Revision fields and the two engine buttons, with Nextflow pressed.
  • Proposal: once G2 and G3a are merged, update the note and the alt text: "a Pipeline field with Revision and Load, the Engine buttons with Nextflow pressed and 'Guessed from main.nf'".
  • Status: deferred to /apply-findings.

UX-G2-07 · minor · Two toggle buttons stand for a one-of-two choice

  • Where: the Engine group of the three boards.
  • Evidence: P2 §10.2 and G5's component test fix the control as two <button aria-pressed>. A radio group is the native one-of-two pattern. Toggle buttons are right only if pressing one releases the other, and if none can be pressed while there is no guess.
  • Proposal: keep the buttons, as planned. Task 19's component test also checks that pressing one releases the other, and that the group keeps its label.
  • Status: open, for Task 19.

UX-G2-08 · minor · The disabled Revision field cannot take focus

  • Where: the Revision field when the Pipeline field holds a path.
  • Evidence: a disabled input is skipped by Tab, so a keyboard user does not reach its reason ("Read as a directory…"). Sighted users see the reason beside the field.
  • Proposal: keep it for 0.0.1. Task 19 may instead hide Revision until the Pipeline field reads as a repository.
  • Status: open, for Task 19.

UX-G2-09 · major · Launch existed only in the page head

  • Found by: ux-reviewer, round 1.
  • Where: LiteLaunch.dc.html, LiteLaunchSnakemake.dc.html, the aside.
  • Evidence: at 1024 px the aside stacks about 1850 px below the head, so the form ended with no submit button. ui-spec §4.6 puts the launch button in the aside, with its reason.
  • Fix:
    • Launch stays in the page head, and a second Launch ends the aside, with the same disabled reason (one shared state).
    • The aside is position: sticky; top: 8px from 1200 px.
    • #launch-what reads "Starts the engine in a new tmux session on login1…", with no "at the top of the page".
    • "Launch appears twice" is added to UX-G2-05's list.
  • Status: applied in 7114560.

UX-G2-10 · major · "Neither file found" asked for a choice that cannot work

  • Found by: ux-reviewer, round 1.
  • Where: LiteLaunchSnakemake.dc.html, the "No guess: neither file found" card.
  • Evidence: the card said "Choose the engine". But P1 Assumption 2 has Launch check that the chosen engine's file exists, so with neither file every choice fails.
  • Fix:
    • The card keeps both buttons unpressed. Launch is disabled with "No main.nf or Snakefile in this directory: check the path", whatever is pressed.
    • A new card on LiteLaunch, "Guess overruled: Snakemake chosen, no Snakefile here": Snakemake pressed; beside it, "workflow/Snakefile not found: Launch will refuse. Guessed: Nextflow (main.nf)"; Launch disabled with that reason.
    • Both cards depend on UX-G2-04: the server must say which files it found.
  • For /apply-findings: the entry-file list (main.nf, Snakefile, workflow/Snakefile) may miss a lowercase snakefile and a Nextflow manifest.mainScript other than main.nf [to be validated], for the fact-checker.
  • Status: applied in 7114560; the entry-file list is deferred with UX-G2-04.

UX-G2-11 · minor · No fetching or fetch-failure state for a Git source

  • Found by: ux-reviewer, round 1.
  • Where: LiteLaunchSnakemake.dc.html.
  • Fix:
    • A "Fetching… at v2.1.2" card: Load busy (aria-busy="true"), with the status "Cloning https://github.com/… (once per revision)".
    • A "Not fetched: revision not found" card, with the field error on Revision. Its note lists the other failures: repository not found or private, no network from login1, ssh asking for a password or a passphrase.
  • For Task 17: that the clone runs without prompts (no terminal, so ssh fails instead of asking) is [to be validated].
  • Status: applied in 7114560.

UX-G2-12 · minor · A short name gave no feedback before Load, and Revision was not marked required

  • Found by: ux-reviewer, round 1.
  • Where: LiteLaunchSnakemake.dc.html, the Pipeline section.
  • Fix:
    • Under the field: "Read as GitHub: https://github.com/snakemake-workflows/rna-seq-star-deseq2".
    • For a Git source, Revision has a required mark, required and aria-required.
    • The "Load pressed without a revision" card (titled "Before Load…" until round 2, UX-G2-15) draws the empty-Revision reason, "Give a tag, branch or commit."
    • The short-name grammar is added to UX-G2-05's list.
  • Status: applied in 7114560.

UX-G2-13 · minor · A prefilled launch said "Guessed from main.nf"

  • Found by: ux-reviewer, round 1.
  • Where: LiteLaunch.dc.html, which is prefilled from rnaseq-2026-10-25.
  • Fix: the engine line reads "Nextflow, as in rnaseq-2026-10-25 · change it if it is wrong". Added to UX-G2-05's list.
  • Status: applied in 7114560.

UX-G2-14 · minor · G5's tests do not reach GET /workflows:inspect

  • Found by: ux-reviewer, round 1.
  • Where: P2 §10.6 G5.
  • Evidence: the refused-URL and revision tests post to POST /runs, with fields workflow.location and workflow.revision. Load calls GET /workflows:inspect first, and that call also fetches from Git.
  • Proposal: the same tests also hit GET /workflows:inspect, with fields location and revision.
  • Status: deferred to /apply-findings.

Nits from round 1

All applied in 7114560:

  • Each error comes before its help in aria-describedby, and the error spans have role="alert", so the error is announced when Load is pressed.
  • The phone refusal reads "Git repositories are fetched over https:// or ssh only…", as on the desktop.
  • The phone no-guess card draws the pinned launch bar, disabled, with its reason.
  • Load sits in the Revision row, beside its input. It no longer floats with a top margin when the row wraps.
  • The note of the refused-revision card reads "A separate rule refuses a file:// or ext:: URL".

Left for Task 19: on MLiteLaunch the pinned launch bar sits over the tab bar's area. This was already so before G2.

UX-G2-15 · minor · The empty-revision card was titled "Before Load" but showed an error

  • Found by: ux-reviewer, round 2.
  • Where: LiteLaunchSnakemake.dc.html, card s4.
  • Evidence: the field error "Give a tag, branch or commit." appears once Load is pressed, not before, so the title contradicted the card.
  • Fix: the card is titled "Load pressed without a revision"; the error is kept.
  • Status: applied in 3c955ae.

UX-G2-16 · minor · The phone refused-URL card did not mark Revision required

  • Found by: ux-reviewer, round 2.
  • Where: MLiteLaunch.dc.html, the "Refused: a file:// URL" card.
  • Fix: Revision gets the desktop's required mark (aria-hidden star), required aria-required="true", and the help "Tag, branch or commit; required for a Git repository."
  • Status: applied in 3c955ae.

UX-G2-17 · minor · The sticky aside can be taller than a short laptop viewport

  • Found by: ux-reviewer, round 2.
  • Where: LiteLaunch.dc.html, LiteLaunchSnakemake.dc.html, the aside, sticky from 1200 px (UX-G2-09).
  • Evidence: on a short screen (for example 1280 × 720), a sticky aside taller than the viewport hides its own foot, the second Launch included, until the page ends.
  • Proposal: Task 19 makes the aside sticky only when it fits (max-height: calc(100vh - 16px) with its own scroll, or no sticky below a height).
  • Status: open, for Task 19. No board change.

Nit from round 2

  • The fetching card's Launch reason, "Wait for the pipeline to load", is neutral #4D5065 instead of error red. Applied in 3c955ae.
  • Task 19 also decides whether editing the Pipeline or Revision field during a fetch cancels it. Open, for Task 19.

Status

Approved by the independent ux-reviewer in round 2 (efe9e31); its minors are fixed in 3c955ae. doc-reviewer: approve (12/14). Open:

  • deferred to /apply-findings: UX-G2-04 (major; it must land before Task 17), UX-G2-05, -06 and -14, and the entry-file list of UX-G2-10;
  • for Task 19: UX-G2-07, -08, -17, whether an edit cancels a fetch, and the phone tab bar under the pinned bar.