vitrinka.docs

Workflows

The plugins' unattended Claude Code workflows: /vitrinka-experimental:make-idea takes an idea to a draft pull request with you in the loop twice, /vitrinka-experimental:test runs the device pass you chose, /vitrinka-experimental:cleanup checks a backlog against reality.

What a workflow is

Beside their skills, two plugins ship six Claude Code workflows: the core vitrinka plugin carries map, review-loop and code-loop (vitrinka:map, …) and one subagent, vitrinka-publisher; the opt-in vitrinka-experimental plugin carries build-idea, test and cleanup (vitrinka-experimental:build-idea, …). A workflow is a script of stages whose agents run unattended: it never asks you anything mid-run, so every decision it needs is settled before it starts, and its completion notification is the only way it reports back. Three skills launch them — make-idea, test and cleanup, all in the experimental plugin. They need Claude Code's workflow runtime; Codex has none, so the experimental plugin is Claude Code only, installed with vitrinka setup --experimental or vitrinka setup modules enable experimental.

From an idea to a pull request

/vitrinka-experimental:make-idea <idea> takes an idea to a draft pull request. You decide twice — in the brainstorm and when the feature is in front of you; everything between runs on its own, in the worktree the session already has.

/vitrinka-experimental:make-idea "Guests can split the bill at checkout"
  1. Map — map charts the terrain the idea stands on: the routes, the model and doors, the components and the tests it touches, the extend points to build on, what the idea would duplicate, and the open questions — one terrain artifact on the board.
  2. Brainstorm — the brainstorming skill runs with the terrain in hand: its open questions are the first round, and every duplication risk becomes a decision — extend or replace, never silently both. It ends with the epic, the decision log and the committed brief. No brief, no build.
  3. Build — build-idea plans the brief into at most four disjoint slices, implements them with one agent per slice, runs the gates, makes one quick "does it work" check — every changed route once at desktop, the main journey once, one small board — opens a draft pull request and hands the task back with the running app, the parked state and what to poke at. No device matrix, no review loop, no code loop: a device pass is not a build decision, so cap, severity, matrix and lanes are refused here.
  4. Look, then test — you look at the feature; /vitrinka-experimental:test asks one batched question (lanes, thoroughness, cap, severity) and runs the device pass: it shoots the chosen lanes — viewports, simulators, iOS 26 Safari — with a usertest beside each, publishes every lane as its own tab of one run board, reviews, accepts, fixes and reshoots up to the cap, files each lane through the run door, runs code-loop over the diff and marks the pull request ready. You merge.
Argument (test)What it sets
capPasses, 1–6. Default 2.
severityThe lowest defect level the loop accepts and fixes on its own: blocker, major (default) or minor. Anything below stays staged on the board for you; suggestions are never auto-accepted.

The device matrix and the review checklist belong to the repository, not the run. By default they follow the project type — iPhone, iPad and desktop for the web, the iOS and Android simulators for Expo — and a repository overrides them in .claude/vitrinka-workflows.json (projectType, matrix, checklist, exclude, board, baseUrl, and run.web — auto, devbox or local — for where the app starts), never in the invocation.

The stages on their own

WorkflowWhat it does
mapFour read-only explorers, one per layer, then one terrain artifact: extend points, duplication risks, open questions. scope: "idea" before a brainstorm, scope: "app" before a review pass.
review-loopShoots every route on every device of the matrix with a usertest pass beside it, publishes the pass as a section of one run board, reviews every screen against the checklist and files findings, accepts those at or above the severity threshold, fixes them and runs the gates — until a pass is clean or the cap is hit. Run it alone for a responsivity or UX pass over an existing surface.
code-loopCode review with the fixes applied, gated by the test suites, until the diff reviews clean; what it cannot apply becomes one pull-request comment for you. Then it opens the pull request — it never merges.
build-idea (experimental)Plan, implement, one quick check, ship — a draft pull request and the hand-back, starting from a committed brief. No device pass.
test (experimental)The ask-first device pass: the chosen lanes shot and reviewed up to the cap, one run board with a tab per lane, each lane filed through the run door, then code-loop and the pull request.

The UI polish loop

When a repository's vybava.config.ts has a uiLoop section, map and review-loop drive the Výbava ui-loop applet instead of shooting routes. The applet owns the screen manifest, the capture, the publish and the scoreboard. The workflows own the judgment.

  • map with scope: "screens" extends the typed screen manifest (<uiLoop.dir>/screens/<area>.ts). With scope: "app" it does the same whenever uiLoop is configured. It covers every route, tab, overlay and state, each with a recipe that reaches it. A recipe reaches a control by its role and accessible name (the harness's action step), not by a CSS chain or an nth= index. A screen the seed data cannot reach is marked unreachable, and one whose code is dead, whose plugin is not installed or whose feature is off is marked retired: it is never shot or counted. Explorers only add entries and never rewrite one. The run ends with vybava ui-loop check and vybava ui-loop map. Pass areas to map only some areas.
  • review-loop runs one stage of a pass per run, so that no run needs more than ten agents. The stages are capture, review, fix and verify. Every run starts with one low-effort agent that relays vybava ui-loop state and vybava ui-loop doctor (a Výbava release with ui-loop state contract 10 or later; an older one, or a failing doctor check, stops the run before it changes anything), so the default stage: "auto" picks up wherever the files say, including after a cutoff. The Výbava verbs own every list: the screens, the review batches, the backlog, the fix lanes and the fix checkpoints. No agent is asked to list them, and agents read item bodies from disk by key. The run returns next, the arguments for the run that follows. When next is null, the loop has converged or needs you. While a capture runs, every stage returns at once as wait and starts no agent: the run that is capturing continues the loop. While the loop is paused (vybava ui-loop pause), every stage returns as paused with next null and a resume, the arguments to launch once vybava ui-loop resume lifts the pause; a stage already running stops at its next boundary (after its reviewer round, before the synthesis, between fix lanes or before Settle) and keeps what it did. A stage you ask for is never swapped for another: when the app changed since the capture, a review stops, lists the changed paths and returns the capture to run, and a run limited to areas never captures. A pass the state cannot date (shot before passes recorded their revision, or at a revision this clone lacks) is never reviewed or verified: the run returns the capture to run, or names the fetch that restores the revision.
StageWhat it does
captureRuns vybava ui-loop run on the Devbox, copies the pass back, splits and publishes it, then lays the pass out on each area's board. Every set on vitrinka is a board, and ui-loop publish keeps one set per area across every pass, so each area has exactly one board. Each pass adds its own Pass N · viewport · theme sections to it, plus one card listing the screens that could not be captured, one line per screen with its reason. If the newest pass was never published, it finishes that pass. Then vybava ui-loop triage groups the shots that failed by cause, and the screens that failed on infrastructure (a network blip, a page that stayed blank) come back as one vybava ui-loop run --retake … command in the run's problems.
reviewvybava ui-loop batches fixes the batches in review/batches.json. Each run claims up to four batches with vybava ui-loop batches --claim, and their reviewers judge each screen against uiLoop.spec. They also judge each open item from the previous pass as met, partly or not met. Each batch saves its result to review/raw/<batch>.json as it finishes, and a later run reviews only the batches still missing. A big pass is reviewed by several identical runs at once: a run that hands on another review returns parallel, how many such runs the batches left can use (each of them continues as one run, so the runs never multiply), and a run that finds every batch left claimed by another run ends. Each batch carries a digest per screen and its reviewer records the digests of the screens it read, so retaking a few shots reopens only those screens. A reviewer that stalls (the watchdog stops it) is counted: at its second stall the batch is split in halves and the same run reviews them with the agents it has left, and a half that stalls twice is blocked: its screens stay unreviewed, are reported in the run's problems and never stop the pass from being synthesized. A screen whose shots did not change since the previous pass is carried: it keeps its findings and verdicts and sits in no batch. Once every batch is in, vybava ui-loop merge-review folds them into a draft, and one agent settles only the keys it flags and writes review/backlog.json. Only the run that takes the pass's synthesis lease does this and posts the scoreboard; any other run ends there. Its reviewed list names the screens a reviewer actually judged, meaning every screen of a saved batch except those its reviewer marked unreviewed, plus every carried screen, and only those can count as clean on the scoreboard (Výbava v0.24.1 or later). A screen that was shot but that its reviewer cannot judge (a shot missing, blank or showing another page) is filed as a finding of its own, so the fix round repairs its recipe and the verify reshoots it. A screen without a single usable shot (unreachable, a failed recipe, an error) is never batched or reviewed and never counted against coverage: the fix round's rig lane repairs its recipe, unless the manifest marks it unreachable with the seed data, and the screens still without a shot when the pass reaches its gate are named in one problems line and keep it from completing. One application failure that the triage finds behind several screens is filed as ONE broken item naming them all. The scoreboard is then posted as a callout in the pass's first section on each area board.
fixvybava ui-loop lanes plans the lanes by ownership: each lane owns whole directories, so parallel lanes never edit one file. The primitives lanes run first. Then their directories are frozen and up to four area lanes run, one item at a time, keeping the shared dev server green. An item whose fix needs a file another lane owns is deferred with the change it needs there, and rework lanes that own both run after the area lanes. Each finished item leaves a checkpoint in fix/<key>.json that is never committed. Nobody owns the i18n catalogs: lanes record the strings they need, and a closing Settle agent adds them, checkpoints the items whose fix lands in another repository, and type-checks the round. Last, a rig lane repairs the capture recipes: the names vybava ui-loop check --labels finds in no label source, the screens the pass never shot, those whose recipe failed in this pass and those behind a triage recipe-drift group (a literal the recipe looks for left the app). It retires a screen whose code is dead or whose feature is off, and it checks each repair with vybava ui-loop run --probe before its checkpoint, so the verify pass reshoots the screen. A pass whose review converged gets a fix round of the rig lane alone, followed by a capture of the screens it repaired. Items blocked on something outside the repository, the rig lane's too, come back as one list, ownerQuestions, from the run that ends the fix round, for their owner to answer in a single batch; a recipe the rig lane cannot repair without changing the app is named in reworkStuck.
verifyCaptures a new pass of exactly the screens vybava ui-loop state selects: every screen that still has an open item, the screens the fix round touched and the screens whose source files changed. A changed shared primitive reshoots every screen. A review run follows it.

Chain the stages from a session, one Workflow call after another, passing each result's next.args on unchanged. Repeat the last call with next.args until next is null:

{ name: "vitrinka:map", args: { scope: "screens" } }
{ name: "vitrinka:review-loop", args: { mode: "ui-loop", stage: "capture" } }
{ name: "vitrinka:review-loop", args: { mode: "ui-loop", repo: "/abs/path/to/app/.worktrees/ui-polish" } }
{ name: "vitrinka:review-loop", args: { mode: "ui-loop" } }

repo (an absolute path, for review-loop in ui-loop mode and map with scope: "screens") pins the run to one checkout. Workflow agents start in the directory of the session that launched them, so without it a run launched from the main clone works there. With repo, every agent prompt opens by telling the agent to cd there first, the first agent reports the repository it actually ran in, and the run stops before changing anything if that is not repo. It rides along in next.args.

Other arguments: apps, only, viewports, themes and workers go to the capture. batch (screens per reviewer, default 14) and reviewers (batches a run claims, at most 4) shape the review; areas no longer narrows it. primitives is the list of directory prefixes that hold shared primitives. A directory that items from two areas share also counts as a primitive. cap is the pass limit (default 6). test always passes mode: "routes", so the device pass of a feature build stays the route-and-device loop. The operational rules every agent carries come from lib/uiloop.js.

Cleaning a backlog

/vitrinka-experimental:cleanup [project] makes one unattended pass over a project's open tasks: inventory, group — duplicates, contradicted statuses, orphans outside their epic, epics nobody closed, stale work — verify every flag against the code, the pull requests and the QA record, apply what is proven, propose the rest, and write one report page. You decide twice: the trust level before the run, the proposals after it.

TrustWhat gets applied
evidence (default)Only proven corrections — a merged pull request, a passing run, a commit trailer, the thing visibly there or gone. Likely closes and merges become proposals.
allLikely corrections too.
noneNothing — the dry run; proven and likely changes become proposals.

Every applied change goes through the engine's own doors and leaves one comment on its task naming the evidence. Nothing is deleted: a duplicate is linked and cancelled, and the survivor keeps the history. Judgment calls land as plan proposals in intake for your verdict, new work as intake drafts. It touches tasks, bugs, stories and epics only — never todos, QA plans, journeys or meetings — and a repository can protect labels and set the stale threshold (45 days by default) in .claude/vitrinka-workflows.json. A rerun the same day replays the cached stages, so a none run first and an evidence run after reading the report costs one extra apply, not a second inventory. Claude Code only, like the rest of the experimental plugin.

The publisher agent

vitrinka-publisher is the core plugin's board-publishing subagent. A session dispatches it in the background once capture is done, and it does the token-heavy board work — a journey's structure pass, steps sections, summary cards, walkthrough narrative, board suites, artifact authoring — then returns the board URL the server minted. It never captures screenshots, commits or arms listeners, and it links boards to the feature's QA plan without creating tasks. review-loop uses it to publish each pass.

On this page