Skip to content

UX review · the 0.0.1 lite boards

ux-reviewer on the 0.0.1 lite boards of design/ui-canvas/ (commit 0b89cb9, page 0.0.1 lite of canvas.json), 2026-10-28, against ui-spec.md, mvp-0.0.1.md, api-and-data-model.md and P1 Tasks 17 to 20 and 25. The findings were applied on branch autopilot/ui-lite-review with the decisions below. Thomas had asked for a home / overview screen and for a run detail "with all its steps and their status" (2026-10-28). Board table: design/README.md. Progress page: UILITE. Format: README.md.

UX-REVIEW  boards=0.0.1-lite  verdict=changes  b/M/m=0/7/6  applied=13/13  rounds=1
UX-RECHECK boards=0.0.1-lite  verdict=changes  b/M/m=0/4/6  applied=10/10  rounds=2
UX-FINAL   boards=0.0.1-lite  verdict=changes  b/M/m=0/3/8  applied=11/11  rounds=3
Id Severity Finding Status
UX-292 major the boards showed named stage cards, "stage n of m" and a Stage column, which the 0.0.1 API cannot serve applied with Thomas's decision of 2026-10-28 ("les 2 dans 0.0.1": both): LiteRunDetail, LiteRunDetailSnakemake (new), MLiteRunDetail show the stages in order, declared or detected (how they are found: ui-spec §5.1.1; presentation owned by the ui-spec §4.4 note), each with a state word and icon, "n of m tasks" and a Declared or Detected badge, opening to its processes or rules in first-seen order, plus "Not in a stage"; with no stage, LiteRunFailed, LiteRunObserved and MLiteRunObserved show the flat list and "No stages for this pipeline"; "stage n of m" stays in the run header of runs that have stages; the Stage column and stage text on home and the runs list are gone; P1 Assumption 6 and Task 18 (GET /runs/{id}/stages); superseded by UX-306 (the header) and UX-308 (the examples, from the detector's output, ui-spec §5.1.1)
UX-293 major "Refreshed every 5 s" and "poll every 5 s" contradicted the SSE decision applied: every screen says "live, updated N s ago"; the LiteLegend caption rewritten for SSE (one stream per browser, the age of the last frame, "Reconnecting…"); MLiteRuns footer says the list follows the server's event stream
UX-294 major runs started from a terminal were not drawn applied: neutral "From a terminal" chip in LiteRuns, MLiteRuns, LiteHome, MLiteHome; new boards LiteRunObserved and MLiteRunObserved with no Cancel, "Started from a terminal · monitor only in 0.0.1", Head "head on login2, not checked", no tmux card, the Logs tab showing the engine log only with the reason (architecture §13.8)
UX-295 major the head facts did not match Task 20 and showed data the API does not return applied: facts split into Head session, Head (Alive / Exited), Login node and Exit code; no PID on driven runs; the queued case "Head not started yet" (head: null) in LiteStatesRun and the runs lists; on the phone the head status is in the header card
UX-296 major the runs list filters, the counts and other facts needed endpoints Task 18 did not define applied: P1 Task 18 gains GET /runs?state=&q=, GET /runs:summary?group_by=state with no time window ("last 24 h" dropped), origin, engine_version (from check_engine at launch, from the pointer for terminal runs) and workflow.version (null when undeclared; Nextflow workflow.manifest.version [to be validated]), and a minimal GET /version → {version, node, runs_root, account}, with tests; partition and every other unserved fact dropped from the boards; api §5 dated note 2026-10-28 for the subset it already specifies; the 0.0.1 /version shape stays in P1
UX-297 major the Cancel confirm text contradicted the P1 wording and the tmux head applied: LiteCancelDialog and MLiteCancelSheet use the Task 20 sentence verbatim ("Cancel this run?" as the title, then "Spectio interrupts its head in the tmux session, and the engine stops its tasks.")
UX-298 minor Home is a fourth screen while the specs said three applied: Home kept (Thomas, decision log); mvp-0.0.1 §1 and dev-env §15.1 say four screens; P1 M4 and Tasks 19 and 20: routes /, /runs, /launch, /runs/:id, Task 20 depends on runs:summary
UX-299 major loading, empty, not-found and refused states were missing for the three screens applied: new board LiteStatesRun (run detail loading, not found, queued with head not started, launch loading, directory refused, value refused after submit, no tasks yet, no match, log not readable, log not created yet); LiteStates gains "Home, first use"
UX-300 minor phone gaps: no Tasks or Logs board, small chips, unwrapped meta lines, no sticky Launch applied: new MLiteRunTasks and MLiteRunLogs; 44 px chips with a fade at the scroll edge; ellipsis on the meta lines of MLiteHome and MLiteRuns; MLiteLaunch gains the "Alignment options" group with the two changed values and a sticky Launch bar above the tab bar
UX-301 minor the Cancel opener was <a role="button"> applied: a native <button type="button" aria-haspopup="dialog"> on every run board
UX-302 minor stage bars reused a run-state token applied: stages and processes use one neutral indigo bar (#5A4FCF) for done and the running blue (#3B82F6) for the active row; the state is carried by the word and its icon; the paused colour is not used
UX-303 minor naming and copy drift applied: spectio-open embl in the expired-link state, the P1 Review Focus 5 wording, "Download last 64 KiB", one session-name form spectio-<run ID>, accessible names on the filter buttons ("Failed, 3 runs")
UX-304 minor keyboard details applied: tabindex="0" and a name on the log and table scrollers; hidden tab panels so every aria-controls target exists; the page behind LiteCancelDialog and MLiteCancelSheet is inert and aria-hidden

Every changed or new board was rendered (desktop 1440 × 1180, phone 390 × 844) with node tools/canvas/render.js and looked at.

Re-check, 2026-10-28 (UX-305 to UX-314)

A second ux-reviewer pass on the boards of commit 8bba74e, after Thomas's design requests below. All ten findings were applied on the same branch.

Id Severity Finding Status
UX-305 major stage and process state words did not follow one rule and disagreed with their counts applied: one rule, owned by the ui-spec §4.4 note: Pending while no task has started (succeeded + cached + running + failed = 0), Running once one has and not every known task has finished, Done when every known task succeeded or was cached, Failed when a task failed on its last attempt; the words of ended runs unchanged; each word mapped to an api §7 run_stages.state; "No task yet" dropped; linked from P1 Assumption 6 and stateWord.ts (Task 20)
UX-306 major "stage n of m" read as a position in a sequence while two stages run at once applied: "3 of 8 stages done · 4 running" in the desktop header, the phone top bar and the Snakemake board ("2 of 8 stages done · 2 running"), and in P1 Task 20
UX-307 major process names were short names, which collide across subworkflows (two SAMTOOLS_INDEX) applied: processes keyed by the fully qualified Nextflow name (at the re-check task.process [to be validated]; verified by the stage-detection spike, ui-spec §5.1.1, after APPLY6 merged), in P1 Task 18: /processes items use that key, and stage_id ties them to /stages; the boards show the last segment, with the full name as the accessible name; the process filter of the Tasks table lists /processes with their count ("All processes (25)")
UX-308 major the rnaseq stage example was not credible, and its numbers did not add up across the header, stages, processes, home and the runs list applied: the examples are rebuilt on the stage-detection spike's real output (tests/pipelines/real/stages/expected/, from APPLY6: rnaseq-3.27.0_star_salmon_detected.json, mosaicatcher-v2.5.1_detected.json): stage names, order and membership verbatim, processes by their fully qualified names; detected names stay technical in 0.0.1. The counts are one fixture used by every rnaseq board: 20 samples, 803 known tasks (524 succeeded, 64 running, 215 pending, 0 failed, 7 retried), 67 processes, eight stages with every process in one (UX-316); MosaiCatcher v2.5.1: 96 cells, eight stages, 347 jobs. Each board caption cites its file
UX-309 minor long process and stage names overflowed on the phone applied: overflow-wrap: break-word and <wbr> after each _ in phone names
UX-310 minor the phone run detail hid its last rows behind the tab bar, and the running work was not visible without scrolling applied: phone mains padded by 100px + env(safe-area-inset-bottom) with scroll-padding-bottom; a "Now" line with the running tasks and the stages they are in ("Now · 64 tasks running in stages 4 to 7")
UX-311 minor "EMBL cluster", "Tasks go to" and the executor were facts the API does not serve applied: P1 Task 18 adds executor: "slurm" \| "local" to GET /version; the boards show "Executor: SLURM" from it and drop "EMBL cluster" and "Tasks go to"; filter placeholders read "Filter by run name"
UX-312 minor list orders were not stated and the sidebar badge disagreed with the active runs applied: lists newest first by creation ("13 of 15 runs · newest first"); home's runs that ended recently use sort=-ended_at (P1 Task 18, api §5 note) with the caption "Ordered by end time"; the sidebar badge reads 6 active runs, as home does
UX-313 minor log timestamps did not match the run's elapsed time applied: log lines at 08:42 to 08:45, naming processes of the fixture
UX-314 minor the legend had no stage words or source badges, and Submitted was missing applied: LiteLegend gains "Stage and process states" (word → run_stages.state) and "Where a stage comes from" (Declared, Detected, Not in a stage), and says Pending includes Submitted; nit "1 runs" fixed to "1 run"

Final review of 722af76, 2026-10-28 (UX-315 to UX-324)

A third ux-reviewer pass and a doc review (approve, 12/14) on the boards of commit 722af76. All eleven findings were applied in one pass on the same branch; the boards are generated by scripts kept out of the repository, and every changed board was rendered and looked at.

Id Severity Finding Status
UX-315 major the run started from a terminal showed a flat list and "Spectio read no pipeline directory… detected no stage", while ui-spec §5.1.1 gives terminal runs the same stages applied: LiteRunObserved and MLiteRunObserved show the eight detected rnaseq stages, with the "From a terminal" mark, "2 of 8 stages done · 5 running · 288 / 384 tasks known so far" and the line that the stages come from the process names nf-spectio sent; a Snakemake terminal run gets its stages from the rule files of snakefile_main (§5.1.1), so no board shows a flat list for it; the flat list with the §4.4 line stays on LiteRunFailed (wgs-germline, a single rule file)
UX-316 major stage membership did not match rnaseq-3.27.0_star_salmon_detected.json: stage 6 listed 6 of its 9 processes, and the counts read 63 processes applied: every stage is checked against the fixture, 67 processes in all; stage 6 lists its 9 processes, the three UCSC_BEDGRAPHTOBIGWIG and the combined UCSC_BEDCLIP Pending with "0 tasks yet"; duplicate short names are told apart by their scope ("UCSC_BEDCLIP · forward"); "All processes (67)" on both Tasks boards; the rule is in the ui-spec §4.4 note
UX-317 major the titled collapsible sections put an h2 inside <summary>, which drops the heading role for some screen readers [to be validated], and the stage progress bars repeated the text next to them applied: each titled section is a <section> with <h2><button type="button" aria-expanded aria-controls>, the icon and the closed-state summary inside the button, and the body in the controlled element (hidden when closed); stage rows stay <details>; their progress bars and the process bars are aria-hidden="true", the "n of m" text carries the numbers; design/README.md describes the pattern
UX-318 minor nothing said which groups open by default, nor what happens to a refused value in a closed group applied: the ui-spec §4.4 note gains "Open sections": open by default Stages, the running stage, Why it failed and every group with a required, changed or invalid field; on a refused submit the group of the first invalid field opens and focus moves to it; open state remembered per screen in the browser, a convenience only; drawn in LiteStatesRun
UX-319 minor home counts disagreed: "5 runs · 2 failed" over 3 failed rows; the phone home listed 4 of the 6 active runs and had no finished runs applied: "5 runs · 3 failed"; MLiteHome lists the 6 active runs (Queued and Cancelling included), then Finished recently (5 runs, end times as on desktop) and "All runs (15)"
UX-320 minor "Stopped" was defined three ways applied: settled once in the ui-spec §4.4 note: Stopped is a stage, process or rule that had started and not finished when the run ended, by Cancel or because the engine stopped after another stage failed; not a failure of its own. It is not cancel-only because a Snakemake run that fails stops its other rules too (LiteRunFailed), and those rules did not fail. failed maps to Failed only when one of the stage's own tasks failed; LiteLegend and the LiteRunFailed caption say the same
UX-321 minor the Launch groups and counts were not the schema they cite applied: regenerated from the rnaseq a1fcddd schema: 11 groups, 114 parameters shown (22 hidden), Alignment 22; Read filtering, UMI options and Optional outputs added as closed groups, Institutional config options shown with its 6 hidden parameters; each closed group draws its first three parameters with their help texts and defaults; pseudo_aligner is an enum of salmon and kallisto with no default, and its [to be validated] is gone
UX-296 (rest) minor the launch boards showed a pipeline version and an engine version that GET /workflows:inspect did not return applied: P1 Task 17 (it owns inspect) adds version (Nextflow manifest.version, null for Snakemake [to be validated]) and engine_version; LiteLaunch and MLiteLaunch show "nf-core/rnaseq 3.27.0 · Nextflow 25.10.4", LiteLaunchSnakemake "rna-seq-star-deseq2 · Snakemake 9.27.1 … no version declared", with no "v2.1.2"
UX-322 minor the 104 px phone bar repeated the page title, and the tabs started below the middle of the screen applied: row 2's title is the page h1 (MLiteTopbar); the run card drops the name and the state word and keeps the run ID, the time and the live line; the tabs stick under the bar; row 2 shows only on inner screens, so MLiteHome has a 48 px bar; MLiteRuns and MLiteLaunch get their h1 from the bar; the MLiteLaunch bar pads by env(safe-area-inset-bottom)
UX-323 minor the boards showed the nf-core and Nextflow marks together, while ui-spec said "one mark per workflow" applied: a dated 0.0.1 note on that line of ui-spec §4.3: the pipeline mark next to the pipeline name, the engine mark in the Engine fact or next to the engine version
UX-324 minor LiteRunFailed cited the spike branch in user-facing copy applied: "No stages for this pipeline: rules as the engine reports them. It is a single rule file, so no stage was detected, and it declares none."

Doc review of 722af76 (approve, 12/14), applied in the same pass:

  • the decision log's Changed line says "the complete logo in the app bar; emblem as favicon" for the ui-spec §2 note;
  • the figure's alt text says /stages returns {items: []} for a run with no stage, P1 Task 27 filling run_stages, and that processes are keyed by their fully qualified name;
  • UX-292 above names no branch and no stale [to be validated], and says what superseded it;
  • LiteRunFailed copy (UX-324);
  • "/processes items use that key, and stage_id ties them to /stages" in the ui-spec §4.4 note and in UX-307 above;
  • the gate output pasted in the Progress page;
  • optional, applied: the "Now" line quoted as drawn ("Now · 64 tasks running in stages 4 to 7") in mvp-0.0.1 and UX-310; the /stages id is run_stages.stage_id, the value /processes items carry in stage_id (P1 Task 18, api §5 note); the figure's sources name this step, not a branch; the Progress page banner split.

Thomas's design requests, 2026-10-28

Thomas: "pour le design ; n'oublie pas les logos snakemake/nextflow/nf-core. Light icons par partie (stages, processes ...) et chaique partie collapsible ; pareil dans launch. Spectio logo uniquement en favico dans la barre ; pas le logo lui mm". Applied on the same branch:

  • Logos. The Nextflow, Snakemake and nf-core logos (docs/assets/logos/) mark the pipeline in the facts of the run boards, on the launch boards, in the phone run headers and in home's recent runs; tools/canvas/render.js now also looks for logos in docs/assets/logos/.
  • Light icons and collapsible sections. Every section of the run boards (Facts, Stages, the head, logs, Parameters), of LiteRunFailed, LiteRunObserved and LiteHome, and of the launch boards (Pipeline, each schema group, Where it runs, the preview) is collapsible, with a light line icon, a summary shown when closed and a chevron (since UX-317, an h2 holding a toggle button); on the phone the same for the run detail, home, the runs list and launch.
  • Spectio logo, corrected. The last sentence above was misread as "favicon only", and the logo was taken out of the bar. Thomas's correction, same day: "Non je veux le logo mais pas juste le favico en mode mobile mais le logo complet" (no: I want the logo, not just the favicon as in the phone view, but the complete logo). Now LiteTopbar starts with the complete logo, the emblem and the "Spectio" wordmark, linking to Home with "Spectio" as its accessible name and the emblem aria-hidden; MLiteTopbar has two rows, the logo and the login node, then the back arrow and the page title (104 px; the phone boards' content starts below it). The emblem alone stays the favicon in the browser tab (ui-spec §2 note).