Skip to content

Releases: Cavalry-Collective/visual-stack

v6.4.0

Choose a tag to compare

@github-actions github-actions released this 09 Aug 14:41
feecb5d

Changed

  • One place decides what the product looks like. The palette now comes from
    design/tokens.css, the design guide's token source, instead of being decided
    in the shared shell. Every page — the review workspace, the story map, the
    spec tree, the build board, the chooser — picks up the guide's Cavalry brand:
    purple-cast neutrals in place of the cool greys, and the brand red at the step
    that holds its contrast on white. Nothing moved and nothing was renamed; only
    the colours changed.
  • Dark is now part of that source rather than something the shell decided on its
    own, so both themes come from the same place.

v5.0.0 — mark a page by moving things and striking things out

Choose a tag to compare

@DeyangChan DeyangChan released this 05 Aug 10:51
51d539c

Breaking

  • Stop is withdrawn. Asking the agent to stop a round mid-flight could not
    do the one thing it promised — interrupt the turn — so it is out rather than
    half-working. The cancelled command, /api/cancel, the cancel sentinel
    and the CANCELLED stream event are gone, and check always exits 0. A
    round already on disk with status cancelled stays terminal, so nothing in
    your project needs migrating. What it would have to do to come back is written
    down in docs/review-wishlist.md.
  • Host profiles move to plugins/vstack/host-profiles/. hosts/ now holds
    only the adapter markdown that maps review operations to a product's tools.
    This is inside the plugin, so an installed copy updates itself.

Added and fixed

  • Linked now means a session is listening. The workspace used to show Linked
    on evidence a session could produce without receiving anything. A stream
    watcher now opens with a HANDSHAKE line naming a command, and its heartbeat
    only starts once ack answers it; unanswered, the watcher exits after two
    minutes (--handshake-timeout <seconds>). Presence also requires rounds to
    move: one queued and unclaimed for 90 seconds drops the link, because a
    watcher whose events nobody reads should look the same to you as no watcher at
    all. A watcher covering no review reports UNLINKED rather than LINKED.
  • The cog says which version you are on. It shows the version the workspace
    loaded with and the one the server is running now, and offers a reload when
    they differ — so a tab left open across an update says so.
  • An answer written on a comment carried in from an earlier version is kept.
    Replies and note edits copy the comment into the current version first, so the
    answer lands in the file the workspace reads back.
  • Two new ways to mark up a page: Move and Delete. A toolbar beside the page
    holds Comment, Move and Delete — what Annotate draws with, on keys c, m
    and d. Neither new tool needs a note: the mark is the instruction, and
    anything you type adds to it. Both outline whatever the pointer is over, so
    the element the gesture will take is settled before you press.
    • Move draws an arrow from a thing to where it should go. It records the
      element you dropped it on and which side of it — inside, before, or after —
      so your agent is told "after the Cancel button" rather than "180px right",
      which stops meaning anything the moment the page reflows.
    • Delete strikes out what should go. Drag across text and exactly those
      words are marked for removal; the strike finds them again by their text when
      the page is rebuilt, so it stays on them. Click an element instead and the
      whole thing is marked.
  • A watcher finds a review whose page lives outside the directory it was
    started from.
    A review's files sit beside the page under review, and
    watch --all found them by walking the directory it ran in. A page written to
    a temp directory took its files with it, so the watcher walked straight past a
    running review and the workspace said Unlinked while a session was in fact
    listening. Serving now leaves a pointer where it was run from, and the watcher
    follows it.
  • A watcher that covers no review says so. It reports UNLINKED instead of
    LINKED, because nothing is listening to any workspace at that point whatever
    the handshake proved. A handshake also carries the token it printed, so one
    watcher's answer no longer brings a different watcher live.

v4.8.1 — the send button is readable when the workspace is dark

Choose a tag to compare

@DeyangChan DeyangChan released this 04 Aug 16:19
4e6d7d9
  • The comment composer's send button is readable in dark mode. Its label was
    fixed to white while its background follows --ink, which is the text colour
    and therefore near-white under a dark theme. The button rendered as a blank
    white box, at a contrast of 1.12:1. The label now follows --surface, the
    pairing the rest of the interface already uses, giving 15.70:1 in dark and
    leaving light mode exactly as it was.
    | Theme | Before (#fff) | After (var(--surface)) |
    |---|---|---|
    | Light | 17.90:1 | 17.90:1 — unchanged |
    | Dark | 1.12:1 | 15.70:1 |

Update

/plugin marketplace update cavalry-collective
/plugin update vstack@cavalry-collective
/reload-plugins

Full changelog: https://github.com/Cavalry-Collective/visual-stack/blob/main/CHANGELOG.md

v4.8.0 — the plugin has a version, and a comment stays on its own element

Choose a tag to compare

@DeyangChan DeyangChan released this 04 Aug 15:34
ef49c6a
  • The plugin declares a version. Until now it shipped without one, so every
    commit to main counted as a release. Your host now compares version numbers
    and updates when this number changes. A copy installed before this release has
    no version on record and keeps comparing commits until it updates once.
  • A comment lands on the element it was left on, not a lookalike. The
    selector recorded for a comment was cut off after eight steps, and a short
    path can first-match a different element elsewhere on the page, which is the
    one querySelector returns. The recorded selector is now the shortest one
    that matches a single element, and a path still ambiguous at full length is
    rooted at body so the chain is exact.
  • Reanchoring prefers the element carrying the comment's words. When a
    selector still parses but its match shares nothing with what was captured, an
    element scoring on text or identity is now taken ahead of it.
  • Both host manifests carry the full set of distribution metadata: version,
    display name, homepage, repository, license, and keywords covering what
    someone would search for. Descriptions across all three manifests are drawn
    from the README.
  • CI runs the tests on Node 18 and 22, checks the stamped shell for drift, and
    validates both manifests with the same tool the community-marketplace review
    pipeline runs. A release workflow rejects a tag that disagrees with the
    manifest version.
  • Issue and pull request templates, a changelog, and a release procedure in
    CONTRIBUTING.md.

Install

/plugin marketplace add Cavalry-Collective/visual-stack
/plugin install vstack@cavalry-collective

Already installed:

/plugin marketplace update cavalry-collective
/plugin update vstack@cavalry-collective
/reload-plugins

Full changelog: https://github.com/Cavalry-Collective/visual-stack/blob/main/CHANGELOG.md

v4.7.0 — a carried question is on the list

Choose a tag to compare

@DeyangChan DeyangChan released this 04 Aug 14:41

v4.7.0 — a carried question is on the list

A question Claude asks is carried onto the next version, because it is the one
thing in a review waiting on the reviewer. The panel was not drawing the
carried ones. They were counted in the bar below the list, in the server's
unresolved set and in the check that guards sign-off, but there was no card for
them — so no × to dismiss one and no box to answer it in.

Every group in the list now decides "still live" the same way, and a carried
question sits with the other questions at the top, its reply box already open.

A carried card says which version raised it, as from r3 in a live app review
and from v3 in a wireframe review. A question asked ten rounds ago no longer
looks like one asked a minute ago.

The walk over earlier versions sorts explicitly. Which copy of a comment you
see depends on later versions being read last, and that held only because
integer-like object keys happen to iterate in order.

v4.6.0 — the tool is review

Choose a tag to compare

@DeyangChan DeyangChan released this 04 Aug 05:33

The wireframe tool is now /vstack:review, and the review loop stops losing comments across a version bump.

The tool is review

/vstack:wireframe still works, as a thin alias that reads review/SKILL.md and nothing else. A review opened on a clean install writes to .vstack/local/review/<name>/.

Rounds already under .vstack/local/wireframe/ keep working. workdir.mjs holds a LEGACY map of what a tool used to be called, reads a subject from whichever directory already has it, and creates new ones under the current name — so watch --all still finds a review opened before the rename. Nothing is migrated behind your back.

The project-planning tools — spec, start, phase-build, phase-preview and the go alias — move to experimental/, where no host discovers them. review and user-story-map are what ships.

Three ways a comment could go missing

  • A save deleted what it did not mention. A save reports what one tab holds, which is never the whole review: comments carried from an earlier version are absent from the payload, and a second tab knows nothing of what the first just wrote. The server merged those saves field by field but replaced them set-wise. Merging is now a union — removing a comment is dismissed, a field, not an absence.
  • A reply went to whichever version still had the comment. It scanned every review file and took the highest, so once the delete above had pruned the comment from the current version, the reply landed in a stale file nothing renders — and the command reported success. A reply now targets the version the workspace has open, copying the comment forward when it exists only in an earlier file.
  • A question did not survive the next version. Open and addressed comments were carried onto a new version; question was not. A question is the one status waiting on you, so Claude's question left the screen at the next publication with nobody able to answer it.

Regression tests cover the first two, and fail without the fixes.

In the workspace

  • Comments anchor to what you clicked on a page that scrolls its own window. The overlay gave a position in the frame's window and everything downstream read it as a position in the document; the two agree only while the page never scrolls.
  • Addressed comments read green across the mark, the card and the composer, and selecting one brings its mark back to the page.
  • The workspace opens itself, and narrow widths keep the top bar's meaning without its words instead of taking over the window.
  • A review says where its files are rather than assuming.

Underneath

One live-link client and one heartbeat protocol shared by the review server and the JSON bridge. Every server injects the host profile, so no page bakes in a product name — a Codex-served board says Codex. Four bugs found in a deep-review pass, the Grok adapter taught the current protocol, and 1.6M of dead brand and mockup assets removed.

v4.5.0 — .vstack/local/<tool>/

Choose a tag to compare

@DeyangChan DeyangChan released this 03 Aug 06:31

Corrects the layout v4.4.0 shipped a few hours earlier. Machine state and pipeline state now split first; the tool name comes second.

.vstack/
  pipeline.json              ← tracked
  specs/feature.json         ← tracked
  build/phase-1.json         ← tracked
  local/                     ← gitignored, one line
    wireframe/login/
    spec/feature.seq
    user-story-map/map.seq
    phase-build/phase-1.seq

What was wrong with 4.4.0

  • bridge wasn't a tool. It named lib/json-bridge.mjs, an engine that spec, user-story-map and phase-build share — not anything anyone invokes.
  • .vstack/spec/ would have sat one letter from .vstack/specs/ — machine scratch beside a tracked pipeline file, distinguished by a plural.
  • Every new engine meant another .gitignore line.

Splitting on machine-vs-repo first fixes all three: **/.vstack/local/ is the only ignore line needed, ever, and the tool name lives one level down where it can't shadow a tracked directory.

The bridge knows who it serves

json-bridge.mjs takes --tool, so the three skills that share it get their own directories. All three SKILL.md files pass it on every serve, watch and patch.

A skill that passed --tool to serve but forgot it on watch would resolve to a different directory and silently watch nothing — the worst failure this design allows. findWorkDir makes a reader fall back across sibling tool directories, so the link works even when the calls disagree.

Tests

New tests/workdir.mjs covers the resolution rules: state sits beside the artifact, an enclosing .vstack wins over nesting a second one, the tool name is always last, spec is never spelt specs, and the reader fallback works.

Breaking

If you took 4.4.0, the paths moved again. Still no migration — reviews in flight and in-browser comment drafts are orphaned. Finish or discard any open review before updating.

Update

Claude Code:

/plugin marketplace update cavalry-collective
/plugin update vstack@cavalry-collective
/reload-plugins

Codex:

codex plugin marketplace upgrade cavalry-collective
codex plugin add vstack@cavalry-collective

v4.4.0 — one .vstack directory

Choose a tag to compare

@DeyangChan DeyangChan released this 03 Aug 06:25

The tools stop scattering dot-directories. Everything they write for one machine now lives under .vstack/, one subdirectory per tool.

Was Is
.ui-review/<name>/ .vstack/wireframe/<name>/
.vstack-bridge/ .vstack/bridge/

How the path resolves

State still sits beside the artifact it belongs to, so a review of design/login.html lands in design/.vstack/wireframe/login/ and moving the page moves its review with it. lib/workdir.mjs is the one place that decides: the enclosing .vstack when the artifact already lives in one — the spec tree writes .vstack/specs/<feature>.json, and nesting .vstack/specs/.vstack/bridge/ under it would repeat the name — otherwise the .vstack directly beside it.

.gitignore ignores the two tool directories at any depth rather than .vstack/ as a whole, because pipeline.json, specs/ and build/ are the pipeline and belong in the repo:

**/.vstack/wireframe/
**/.vstack/bridge/

Breaking

Reviews in flight under .ui-review/, and comment drafts under the ui-review:* localStorage keys, are orphaned. There is no migration. The files stay on disk; the tools no longer look there. Finish or discard any open review before updating.

The old paths deliberately kept their names for two releases to avoid exactly this. That stopped paying once one product meant three dot-directories in a project.

Update

Claude Code:

/plugin marketplace update cavalry-collective
/plugin update vstack@cavalry-collective
/reload-plugins

Codex:

codex plugin marketplace upgrade cavalry-collective
codex plugin add vstack@cavalry-collective

v4.3.0 — Codex joins the hosts

Choose a tag to compare

@DeyangChan DeyangChan released this 03 Aug 03:51

Visual Stack is no longer Claude-Code-only. Codex runs the wireframe workflow, and the review workspace stops losing work.

Highlights

  • Codex host — install Visual Stack from the Codex marketplace and invoke $wireframe to build or review a UI in the annotation workspace. Wireframe is the only stage with a Codex adapter so far; the rest of the pipeline stays Claude Code (and Grok Build).
  • Host contract, filled inhosts/codex.json carries Codex's labels, capabilities and update commands; skills/wireframe/hosts/codex.md maps the Host ops onto Codex tools. Skills still depend only on the contract, never on a particular agent product.
  • Clear all asks first — clearing a review used to arm a button for three seconds. It now opens a confirm dialog that says how many comments go and that the wireframe and version history stay.
  • The panel keeps its own edge — the comments panel and its handle sit on real grid lines, so the handle tracks the panel under browser zoom. Below 720px comments become their own full-width view instead of a drawer covering the page under review.
  • No more rolled-back edits — merging server state no longer undoes a local dismissal, reply or reopen that is still inside the autosave window.

Also in this release

  • tests/host-profiles.mjs validates every host profile against the schema
  • The review-lifecycle test serves under --host codex and asserts the workspace gets the right host identity
  • README and CONTRIBUTING cover the Codex install and how to test a Codex change

Install / update

Claude Code:

/plugin marketplace add Cavalry-Collective/visual-stack
/plugin install vstack@cavalry-collective

Already installed:

/plugin marketplace update cavalry-collective
/plugin update vstack@cavalry-collective
/reload-plugins

Codex:

codex plugin marketplace add Cavalry-Collective/visual-stack
codex plugin add vstack@cavalry-collective

v4.2.0 — phase-preview, live review, shared shell

Choose a tag to compare

@DeyangChan DeyangChan released this 01 Aug 06:36

The workspaces share one shell, wireframe reviews real apps, and every push to main is a release.

Highlights

  • Shared shell — one top bar, palette, theme, and scrubber for every tool page. Theme and language sit behind a settings cog so the bar only carries the tool and its work.
  • /vstack:phase-preview (was phase-wireframe) — drag through release phases on the same scrubber; each stop is the approved design with later work taken out.
  • Live wireframe review — point the workspace at a localhost app or a public site; it proxies the real screens so comments land on them, not a mockup.
  • Update check — each local server asks once whether main has moved on (install SHA vs head), and shows one dismissable line when it has. No version in plugin.json; every push to main is the release. Opt out with VSTACK_NO_UPDATE_CHECK=1.

Also in this release

  • Spec, start, story map, and phase-build follow the quieter bar and shared chrome
  • Handoff footers on wireframe, story map, and phase-preview so the pipeline reads end to end
  • README rebuilt around interactive specs and how updates work

Install / update

/plugin marketplace add Cavalry-Collective/visual-stack
/plugin install vstack@cavalry-collective

Already installed:

/plugin marketplace update cavalry-collective
/plugin update vstack@cavalry-collective
/reload-plugins

Or turn on auto-update under /pluginMarketplacescavalry-collective.