Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ All notable changes to the claude-plugins project will be documented in this fil

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Entries are listed newest-first; each plugin section is treated as released when merged to `main`.

### vibe v1.0.53

#### Added
- A startup version check (operator ruling, 2026-10-16). Every `$vibe` start, new or resume, runs `scripts/plugin-version.mjs`, which compares the running plugin's own manifest (`.codex-plugin` in Codex, `.claude-plugin` in Claude Code) with the same manifest on claude-plugins `main`. When the install is older, the person is asked "keep going with this one, or update now?"; on update the orchestrator runs the harness's update commands (`claude plugin marketplace update closedloop-ai` and `claude plugin update vibe@closedloop-ai`; in Codex `plugin marketplace upgrade closedloop-ai` then `plugin add` for vibe and closedloop-core, or a `git pull --ff-only` of a local folder marketplace, as `INSTALL.md` describes) and asks them to reopen the app. The check never blocks: no network, a refused, slow (5 second limit) or garbled answer, or a missing manifest prints status `unknown`, exit 0, and the session carries on and says so. `guardrails.md` ("Plugins and tooling") allows exactly this person-chosen update and nothing else.
- A precedent check before any product question (operator ruling, 2026-10-16). When the graph does not settle how the product should behave in a situation, how a mature app handles it is the default answer: Asana first, then another established app with the same flow (for example Linear, or GitHub's own authorization screens), then their public help centers. `scripts/precedent-check.mjs` holds the research brief and its safety rules once: in Claude Code it starts a separate headless `claude -p --chrome` run limited to the Chrome tools, web search and fetch (a session's Chrome tools are bound when it starts); in Codex it prints the brief the orchestrator follows in its own in-app Browser tab or with Computer Use, and `vibe-requirements-worker` gains a precedent mode for the help centers when no browser can look. The brief never touches existing data, keeps test data in one private `zz vibe precedent check (temp)` project with `zz test` tasks that is deleted and confirmed gone, cancels any connect, invite, share, pay or settings flow at its confirmation step, verifies every state before recording it, separates direct observation from help-center material and reports `undocumented` rather than guessing. The answer and its source (`Asana, observed <date>`, a help-center URL or a ticket slug) are recorded in the session decision table as a default, never a human ruling or user-visible words; only when nothing settles it is the person asked.
- Visual QA during the session (operator ruling, 2026-10-16). `quality-loop.md` gains "Visual QA during the session": at each visible milestone (a user-visible change first ready to look at, or a later major visible change, never a small edit) the ready message offers visual QA through `session-questions.mjs` (key `visual-qa:<request ID>`), and "looks good, make it polished" runs it before handoff without asking, unless the change shows nothing visible or the person declined it for that version. It runs the repository's design pack visual QA skill (`/visual-qa`, `$visual-qa`) between requests after a deploy: against the session's acceptance criteria when the ticket or its PRD has them, otherwise as the design pack's best-practice review against `.claude/design/soul.md`. Findings go to the same writer as one fix request.

#### Changed
- The build loop is otherwise unchanged: visual QA still never runs inside a request's build or holds a deploy back, and the reference check stays the loop's one exception. The vibe skill (sections 1, 5 and 6, "Questions are asked once"), `guardrails.md`, the handoff skill (its visual QA now uses the same criteria-or-design-pack basis, and its question gate includes the precedent check), the change and requirements workers, `INSTALL.md` and the README follow, and sentences saying visual QA runs only at handoff are reworded.

#### Tests
- `plugin-version.test.mjs` (8 cases): outdated with each harness's commands (Git and local Codex marketplaces), current and newer, each harness reading its own manifest, unreachable, 404, garbled, unversioned and slow marketplaces all `unknown` with exit 0, a missing manifest or runtime, and quoting of paths with spaces. `precedent-check.test.mjs` (6 cases): the brief's order and every safety and evidence rule, the headless Claude arguments and stdin, and failed, empty, slow and missing runs never counting as an answer.
- `test_vibe_visual_qa_precedent_version_contract.py` (11 cases) pins the prose in the skills, references and workers; all 11 fail on 1.0.52. `test_vibe_test_repair_lean_loop_contract.py` now pins "run at `$handoff`, never during the loop" and keeps the QA skill names out of the lean loop section, since visual QA may now also run outside the loop.
- 15 eval cases tagged `precedent`, `visual-qa` and `version-check` (Claude, and Codex through the runner; the Codex count test moves to 48). With Sonnet in Claude and the runner's default model in Codex, all 15 pass in both harnesses here. On 1.0.52 the four visual QA offer and polish cases, the outdated and unreachable version cases and the Asana-first case fail in both harnesses; the update-done case fails there in Claude (no reopen step) and in Codex only on its tool-call cap. The graph-answered, no-precedent, small-edit, declined and current-version cases pass on 1.0.52 too, as expected, since they guard behavior 1.0.52 already had or never offered; so do the two Codex precedent follow-up cases, whose session state already describes the precedent steps (the recorded-answer one failed one of two Claude runs on 1.0.52).

### vibe v1.0.52

#### Fixed
Expand Down
2 changes: 1 addition & 1 deletion plugins/vibe/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vibe",
"description": "Vibe sessions, handoff, seed refresh, and ClosedLoop ticket workflows",
"version": "1.0.52",
"version": "1.0.53",
"dependencies": ["closedloop-core"],
"author": {"name": "ClosedLoop", "email": "support@closedloop.ai"}
}
2 changes: 1 addition & 1 deletion plugins/vibe/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vibe",
"version": "1.0.52",
"version": "1.0.53",
"description": "Vibe sessions, handoff, seed refresh, and ClosedLoop ticket workflows",
"author": {"name": "ClosedLoop", "email": "support@closedloop.ai"},
"homepage": "https://github.com/closedloop-ai/claude-plugins",
Expand Down
54 changes: 47 additions & 7 deletions plugins/vibe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,18 @@ commit, deploy, and showing the person. Each finished change deploys to the
session's Vercel preview without the person asking ("redeploy" still works),
and changes that arrive during a deploy go out together in the next one.
The plan gets no review, and browser
E2E, visual QA, logical QA, product-contract QA, the guardrails and adversarial
reviews and other heavy validation run only at handoff. Before saying a
E2E, logical QA, product-contract QA, the guardrails and adversarial
reviews and other heavy validation run only at handoff. Visual QA runs at
handoff too, and during the session only when the person wants it (operator
ruling, 2026-10-16): at each visible milestone (a user-visible change first
ready to look at, or a later major visible change, never a small edit) the
ready message offers it, and "looks good, make it polished" runs it before
handoff unless the change shows nothing visible or the person already
declined it for that version. It runs between requests after a deploy,
through the repository's design pack (`/visual-qa`, `$visual-qa`):
against the acceptance criteria when the ticket or its PRD has them, and as
the design pack's best-practice review against `.claude/design/soul.md`
otherwise. Its findings go to the same writer as a fix. Before saying a
change is ready, the writer checks every acceptance criterion it touches
(from the linked ticket, its PRD and the person's own words, kept in the
session decision table) with an existing test, a quick script, one control
Expand All @@ -52,7 +62,8 @@ it read before building, and every visual and UX property it shows becomes an
acceptance criterion mapped to a design token or catalog component. Only when
there is a reference image, the writer screenshots each touched screen before
saying it's ready and fixes every difference from the reference, the one
exception to the lean loop's no-visual-QA rule (operator ruling, 2026-10-15).
exception inside the lean loop to its no-visual-QA rule (operator ruling,
2026-10-15).

Every request also uses `$decision-table` or `/closedloop-core:decision-table`
before code, including frontend-only, prototype and trivial edits. One living
Expand Down Expand Up @@ -143,9 +154,28 @@ only from the successful discard receipt.
Technical plans, questions, and upfront summaries remain internal. Updates
identify only completed requested features and next work in the person's own
words. Product questions are researched through closedloop-graph and live
decision evidence first, then raised one at a time with full context only
when an unresolved answer is absolutely necessary. Existing product and design
approvals remain intact.
decision evidence first, then through how a mature app handles the same
situation (operator ruling, 2026-10-16): Asana first, then another
established app with the same flow (Linear, or GitHub's own screens), then
their public help centers when no browser can look. `scripts/precedent-check.mjs`
holds the research brief and its safety rules: a separate headless
`claude -p --chrome` run in Claude Code, the orchestrator's own in-app Browser
or Computer Use in Codex; nothing that exists is touched, test data lives
only in a `zz vibe precedent check (temp)` private project that is deleted
afterwards, and every state is verified before it is recorded. The answer
and its source (`Asana, observed <date>`, a help-center URL, or the ticket
slug) go into the session decision table. A question is raised, one at a
time with full context, only when none of these settles it and the answer
is absolutely necessary. Existing product and design approvals remain intact.

Every `$vibe` start checks the installed vibe against the version on
claude-plugins `main` (`scripts/plugin-version.mjs`). When it is older, the
person chooses to keep going or update now; on update the orchestrator runs
the harness's update commands (`claude plugin marketplace update` and
`claude plugin update` in Claude Code, `codex plugin marketplace upgrade`
and `codex plugin add` for vibe and closedloop-core in Codex) and asks them
to reopen the app. When the check cannot reach GitHub the session carries
on and says so.

Two notices reach the person without waiting for a reply. When a request names
an outside product as its reference, or gives a screenshot of one, the
Expand Down Expand Up @@ -274,7 +304,7 @@ The plugin bundles the ClosedLoop ticket automation skill pack: `cl-policy`, `cl
| Agent | Model | Responsibility |
|---|---|---|
| `vibe-setup-worker` | sonnet | Machine preflight, worktree bootstrap, owned local processes, and confirmed session discard |
| `vibe-requirements-worker` | sonnet | Read-only ticket, requirements, overlap, and owning-route discovery |
| `vibe-requirements-worker` | sonnet | Read-only ticket, requirements, overlap, and owning-route discovery, reference-product research and help-center precedent research |
| `vibe-ticket-worker` | sonnet | Live ticket creation, next-owner lookup, handoff grading, assignment, and cancellation |
| `vibe-environment-worker` | sonnet | Vercel environment creation, redeploy, flag snapshots, Desktop setup, deployment records, and opening a pull request the person asked for at handoff |
| `vibe-change-worker` | sonnet | Sole persistent implementation writer for local planning, full-stack changes, stories, fixes, the handoff missing tests list and serialized recording |
Expand Down Expand Up @@ -351,6 +381,16 @@ check that also fails on the captured main is recorded on the ticket's
Engineering checklist and the handoff goes on, and a session-caused failure
goes back to the writer.

The cases tagged `precedent`, `visual-qa` and `version-check` rehearse the
2026-10-16 operator rulings: a product question the graph or a precedent
already answers is not asked, Asana is checked before another app and a
question is asked only when neither settles it; visual QA is offered at a
visible milestone and not on a small edit, a polish request runs it before
handoff (against the criteria, or the design pack's review without them)
and skips it after the person declined; and the startup version check asks
"keep going or update" when outdated, says nothing when current, carries on
when GitHub cannot be reached, and asks for a reopen after updating.

## Runtime Files

Version `1.0.14` contains 10 skills and 16 agents. It has no standalone
Expand Down
12 changes: 10 additions & 2 deletions plugins/vibe/agents/vibe-change-worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,13 @@ Research any product uncertainty through graph and live prior decisions first.
Apply a settled ruling, never ask it again; settled means traced to a human
statement (`quality-loop.md`, "Communication and product questions"). Only an
absolutely necessary unresolved product question returns `NEEDS_PERSON`, with
sources checked and full context. Resolve technical ownership/backend/adapter
sources checked and full context; before asking, the orchestrator checks how
Asana or another established app handles it (`quality-loop.md`, "Precedent
before asking"). A precedent answer it returns is the default you build to:
record it in the session decision table as the decision for the affected
rows with its source (`Asana, observed <date>`, `<app>, observed <date>` or
the help-center URL), never as a human ruling, and never take its words as
copy. Resolve technical ownership/backend/adapter
questions yourself from source and read-only advice, never by shrinking
requested scope.

Expand Down Expand Up @@ -258,7 +264,9 @@ fixture your change broke, repair it under "Tests: repair, don't author"
below. Fix your implementation, never suppress or weaken a check. Browser E2E,
visual QA, logical QA, product-contract QA, existing test suites, Storybook footprint
and independent guardrails, adversarial and core workflow reviews run only at
handoff; do not run or request them in the loop. The publication gate's own
handoff; do not run or request them in the loop. Visual QA the person accepts
during the session runs outside your turns (`quality-loop.md`, "Visual QA
during the session"); its confirmed findings reach you as a fix request. The publication gate's own
fixed validation (`environment.md`) is separate and unchanged. At handoff apply their
confirmed corrections here and have the changed result rechecked. Automated
browser checks there are headless; Electron uses the supported displayless
Expand Down
26 changes: 24 additions & 2 deletions plugins/vibe/agents/vibe-requirements-worker.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: vibe-requirements-worker
description: Turns a ClosedLoop ticket or a plain description into vibe-session requirements for symphony-alpha. Reads the ticket with its PRD, plan, and related tickets through closedloop-graph and the ClosedLoop MCP, checks for existing or overlapping work, locates the route and FEATURE_MAP id where the relevant code lives (for change workers), and returns a short brief plus any questions only the person can answer. In reference mode, researches an outside product the person named or showed in a reference screenshot, reads the image itself, and returns the behaviors plus the visual and UX requirements to build, mapped to the design system. Read-only.
description: Turns a ClosedLoop ticket or a plain description into vibe-session requirements for symphony-alpha. Reads the ticket with its PRD, plan, and related tickets through closedloop-graph and the ClosedLoop MCP, checks for existing or overlapping work, locates the route and FEATURE_MAP id where the relevant code lives (for change workers), and returns a short brief plus any questions only the person can answer. In reference mode, researches an outside product the person named or showed in a reference screenshot, reads the image itself, and returns the behaviors plus the visual and UX requirements to build, mapped to the design system. In precedent mode, finds from public help centers how Asana, or another established app with the same flow, handles a situation a product question asks about. Read-only.
model: sonnet
tools: Read, Grep, Glob, Bash, WebSearch, WebFetch
---
Expand All @@ -10,7 +10,8 @@ You prepare the start of a vibe session. You never edit files.
## Inputs

The repo path, and either a ticket reference (ISS-, PRD-, PLN- slug or URL) or
the person's description in their own words.
the person's description in their own words, or in precedent mode a
product question.
Before the private session exists, this is the validated remembered checkout
in mode `request` with `sessionless: {kind: "startup"}` and only exact graph/live
read capabilities. Never fabricate a session, register a source writer or grant
Expand Down Expand Up @@ -99,6 +100,27 @@ list to the person and keeps building without waiting, so the list is never a
question. It names behaviors, not wording: never propose the product's labels
as our copy. End with the Graph block.

## Precedent mode

The brief carries a product question the graph and live decisions did not
settle, about how the product should behave in a situation, because no
browser could look at another app (`../skills/vibe/references/quality-loop.md`,
"Precedent before asking"), and the brief that
`../skills/vibe/scripts/precedent-check.mjs prompt` printed for it. Follow
that brief's order, evidence rules and report shape, from public material
only, with the harness's web search and fetch tools:
Asana's help center and documentation first; when Asana does not have the
situation, another established app with the same flow (for example Linear,
or GitHub's own documentation for a GitHub authorization). Never sign in,
create an account or type credentials.

Return `DONE` with the brief's report: the behavior the precedent shows in
one plain line, its source (the app and the exact help-center or
documentation URL), and each app checked that does not have the situation.
Behavior only, never its wording as our copy. When no public material
settles it, the answer is `undocumented`, with every URL checked; the
orchestrator then asks the person. End with the Graph block.

## Return (under 200 words, not counting the quoted acceptance criteria)

`DONE` with: a two or three sentence summary in plain words, which the
Expand Down
2 changes: 1 addition & 1 deletion plugins/vibe/evals/codex/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Visual cases (tag `visual-cues`) use the same stand-in repository and Pillow
renderer as Claude, which renders light and dark (`--theme dark`) from the
stand-in tokens' `:root` and `.dark` blocks. They attach the same PNGs with
Codex's image option and save history text in the prompt. No browser, Electron
window, actual app or external ticket is started. The 27 other cases rehearse
window, actual app or external ticket is started. The 42 other cases rehearse
one reply or decision from supplied session state in read-only mode. This is
behavior coverage, not a substitute for live app validation.

Expand Down
2 changes: 1 addition & 1 deletion plugins/vibe/evals/codex/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

def test_one_case_per_claude_prompt_and_role_names() -> None:
found = runner.cases()
assert len(found) == 33
assert len(found) == 48
assert len({c["name"] for c in found}) == len(found)
assert all(c["name"].startswith(("executive-", "product-manager-")) for c in found)
for case in found:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: regex
match: contains
flags: i
pattern: 'NEXT:[^\n]*(Linear|GitHub|another app)'
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: regex
match: contains
flags: i
pattern: 'REPLY:\s*NONE\b'
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: regex
match: contains
flags: i
pattern: 'ROUTE:\s*research-further\b'
---
Loading
Loading