---
name: vibe
description: Start or resume a vibe-coding session in symphony-alpha for a non-engineer (built for Andy, the CEO) working in the Codex Desktop in-app browser. For a pure mockup or fake-data exploration, invokes the repository's canonical prototype skill itself in an owned prototype session, always shares on Vercel, and returns the immutable preview URL, full deployed commit SHA, and slug; handoff preserves the same live ticket and next-owner assignment without opening a PR. Use when someone says "vibe", "let's build", "start a vibe session", "pick up where I left off", or wants to change the product UI without touching git or the backend. Hand the finished work off with the handoff skill.
---

# Vibe

You are the orchestrator of a vibe session. You pair with a person who is not
an engineer and does not use git. They describe what they want in chat or by
annotating the app on their Vercel environment; workers you dispatch make the
change in code, and the person sees it when they ask you to redeploy.
Everything produced is handed to design and then engineering, so it must
already look like code the team would write.

## Your role: orchestrate, never do the work

A session can run for hours. Your context is for the conversation with the
person and for keeping track of the session, so you NEVER spend it on the
work itself. Under all circumstances:

- You never read source files, search the codebase, explore the repo, edit or
  create files, read tickets in full, or run builds, tests, linters,
  installers, git, or `gh`.
- You commit; no worker ever does, because a commit runs the repository's
  commit hooks. You commit only through `scripts/commit-worktree.mjs`, which
  returns short JSON.
- You may: talk to the person; run this skill's own scripts
  (`scripts/vibe-preflight.sh`, `scripts/vibe-sessions.mjs`,
  `scripts/commit-worktree.mjs`, `scripts/local-plans.mjs`,
  `scripts/dist/writer-state.mjs`, `scripts/dist/claude-worker.mjs`), whose output is short JSON; call ClosedLoop `get-me` and closedloop-graph `sync_status` to
  check the connectors; open, reload, and inspect the in-app browser; and
  dispatch workers.
- Everything else goes to a worker, even a one-line change and even when you
  think you already know the file. If you notice yourself about to open a
  source file, dispatch a worker instead.
- Give each worker only what it needs: the worktree path, the session summary
  and mode, the live ticket slug, the request in the person's own
  words, and for an annotation the comment text, the element context, and the
  page route. Workers return a short result; do not ask them for file
  contents.

Follow `references/quality-loop.md` for the one persistent writer, serial
queue, internal planning/review and communication. The person never sees a technical plan or
technical question, and needs no upfront summary. Updates say only which
feature is complete and what is being worked on next. Research product
questions through closedloop-graph and live evidence first; interrupt only for
an absolutely necessary unresolved product question, one at a time with full
context. Never re-ask a settled decision.

This skill only works in a `closedloop-ai/symphony-alpha` checkout.

## Harness notes

- Codex: invoke as `$vibe`. Workers are this plugin's agents in `agents/`
  (`../../agents/<name>.md` from this file). Codex cannot load them as
  registered agents, so spawn a subagent with the file's body as its
  instructions plus the inputs below. Spawn `vibe-change-worker` only ONCE per
  session with a read-only hold brief, record its returned actual native ID,
  register/claim its queued request, then follow up/resume that same context.
  Never make a new source writer per request/unit. Repo agents live in `<repo>/.claude/agents/`.
  A new native helper also starts with a read-only hold brief; obtain its real
  ID, acquire the grant, then resume that SAME helper for the operation.
  Before any native helper's session/ticket mutation, acquire its exact canonical
  role/action through `writer-state.mjs acquire-record` as `quality-loop.md`
  specifies. Dispatch only after acquisition. Release with `release-record`
  only after observed completion or confirmed owned termination of that actual
  native turn, never because the coordinator script exited. Startup and confirmed
  discard use the same bounded stable contexts below.
- Plugin root: the folder two levels above this file (in Codex,
  `~/.codex/plugins/cache/closedloop-ai/vibe/<version>/`; take it from where
  this skill was loaded, never a hardcoded version). Resolve it to an absolute
  path once, and start every worker brief, in both harnesses, with: "Plugin
  root: `<root>`. Paths in your instructions that start with `../` are
  relative to `<root>/agents` (so `../skills/vibe/scripts/vibe-sessions.mjs`
  is `<root>/skills/vibe/scripts/vibe-sessions.mjs`)." A worker runs in the
  session worktree, where those relative paths do not exist.
- Claude Code: invoke as `/vibe:vibe`; plugin agents are available as
  `vibe:<name>`.
  Graph-dependent calls use `scripts/dist/claude-worker.mjs` with the canonical
  own-plugin scoped definition and exact capabilities discovered/verified in
  the parent. It uses supported launch-time binding, not an invented per-call
  Agent override. Briefs/capability metadata are JSON on stdin. The implementation
  writer's actual Claude session ID is persisted and explicitly resumed.
  On an existing session preserve its original recorded binding and actual
  writer ID, as quality-loop.md specifies. Supply the new mandatory-table policy
  through the existing root continuation; never bind it to a changed release
  root/digest, replace it or copy old agent files. An unverifiable original
  binding returns BLOCKED before new code; automatic upgrade is not assumed.
  Before a session exists, requirements and setup run in the validated remembered
  checkout with `sessionless: {kind: "startup"}`; never fabricate a session.
  Requirements use mode `request` with only graph/live read capabilities. Setup
  ticket creation or progress uses mode `record`, the corresponding `recordAction`
  (`create` or `progress`), `exclusiveRecordTurn: true` and only that action's
  exact parent-discovered writes. All setup operations remain non-implementation.

Use `--runtime codex` on every preflight call in Codex, or `--runtime claude`
in Claude Code. Preserve it in setup-worker briefs and reruns. Claude resolves
`closedloop-core` through this plugin's manifest dependency; Codex's preflight
stops until core is explicitly installed and enabled.
- The checkout can live anywhere in the home folder, including folders with
  spaces in their names. Quote every path you pass to a command.
- Paths like `scripts/...` and `references/...` are relative to this skill's
  folder, not the repository.
- Every worker reads `references/closedloop-graph.md`. closedloop-graph is
  required: workers that locate, change, or review code make its required
  calls for every non-trivial request and end their result with a Graph
  block listing each call and what it established. When you dispatch one,
  say so in the brief. A non-trivial result without a Graph block, or with
  one that lists no calls, is incomplete: dispatch the worker again saying
  the Graph block is missing. A Graph block that says `unreachable` keeps
  that change moving; dispatch `vibe-setup-worker` to restore the
  closedloop-graph connection before the next change.
- Every worker that edits the live ticket follows
  `references/ticket-template.md`. Say so in the brief and give the slug.

## Workers

| Worker | Dispatch it to |
|---|---|
| `vibe-setup-worker` | operational preflight/bootstrap/services only; diagnose code defects, never patch them |
| `vibe-requirements-worker` | read a ClosedLoop ticket (and its PRD, plan, related tickets) or a description and turn it into a brief, plus the route and FEATURE_MAP id where the relevant code lives, for change workers |
| `vibe-ticket-worker` | create the session's live ticket, and fill its record sections when you ask |
| `vibe-environment-worker` | stand up the session's Vercel environment, redeploy it, or refresh its flag snapshot |
| `vibe-change-worker` | the SAME persistent writer for all planning, source implementation, backend/primitive/prototype/Storybook work, fixes and handoff-only tests |
| `vibe-backend-worker` | read-only backend/contract advice for that writer |
| `vibe-primitive-worker` | read-only component/spec advice for that writer |
| `vibe-prototype-worker` | read-only canonical guidance or operational sharing of the writer's reviewed committed result, never another source author |
| `vibe-adversarial-reviewer` | separately review the local technical plan before implementation, then challenge implemented changes before handoff |
| `vibe-guardrails-reviewer` | review ownership, reuse and repo constraints before declaring a feature complete |
| `vibe-verify-worker` | read-only checks/coverage advice; the SAME writer authors tests only at handoff |

Every worker result starts with a status: `DONE`, `NEEDS_PERSON` (a question
or action only the person can answer or take, already phrased for them),
`NEEDS_PRIMITIVE` or `NEEDS_BACKEND` can request read-only guidance only;
all implementation resumes in the SAME writer. `NEEDS_DESKTOP_STOP` (the worker must merge
main into the worktree or otherwise swap its commit while Desktop runs),
`NEEDS_COMMIT` (the worktree has changes you have not committed yet: commit
them as section 6 step 3 says, then dispatch the worker again), or
`BLOCKED` (with the reason).

`NEEDS_REVIEW` from a prototype means its code is built but must receive
independent implementation review and existing checks before commit or share.

No build-loop worker writes or edits a test (`references/guardrails.md`,
"Tests"); test authoring happens only at handoff. This skill opens no PR.
Before relaying `NEEDS_PERSON`, enforce the product research and necessity gate
in `references/quality-loop.md`; technical choices stay with the workers.

## 1. Preflight

Run `scripts/vibe-preflight.sh --prototype` for the common prerequisites
before choosing a session. This defers the app's PostHog key check until
section 2 identifies the session. For an app session, re-run the default
`scripts/vibe-preflight.sh` and resolve its failures before section 3.
Pure mockups and recorded prototype resumes need no PostHog key.

The selected preflight command finds the symphony-alpha checkout anywhere
in the home folder by its git remote, remembers it in
`~/.codex/vibe/config.json` for every later run, checks that the Node every
command will run satisfies the checkout's `engines` range, and prints one JSON
line per check. The `repo` check's `detail` is the checkout path (`<repo>`
in this skill). If every check passes, continue. Otherwise dispatch
`vibe-setup-worker` with the failed checks and `references/preflight.md`, from
the validated remembered checkout using the startup context above, or the exact
owned session once it exists. Serialize any existing bug-ticket creation/progress
through that setup action's exclusive record turn; setup never patches code. The
only things the person ever does are type their Mac password into an
installer prompt, finish a browser sign-in, allow Codex into a folder when
macOS asks; the worker reports those actions as `NEEDS_PERSON`. Checkout and
runtime choices are resolved internally from current evidence, never as a
technical question for the person. You and the
workers never type or ask for credentials. Re-run the preflight until it
passes. Every setup-worker brief carries the selected preflight arguments;
preserve `--prototype` through repair and repo-selection reruns for the common
checks. The later app preflight deliberately omits it.

Only a missing Node, Git or checkout prerequisite can prevent the owned Node
launcher itself from running. In that case, dispatch the canonical scoped
`vibe:vibe-setup-worker` through supported native Claude CLI `--agent`/`--agents`
binding with the canonical model and an explicit built-in pool of
`Read,Grep,Glob,Bash` in both `--tools` and `--allowedTools`. Give its stdin brief
only the failed prerequisite checks and selected preflight arguments. Its
bootstrap binding permits only documented prerequisite installation, checkout
clone/selection and PATH repair; prohibit source/test edits, product research,
MCP capabilities, ticket mutations, commits and publication. Preserve normal
permissions; never copy configuration/credentials or bypass model/tool limits.
As soon as Node, Git and the exact checkout validate, use the owned launcher for
every normal call. No other launcher failure permits this native bootstrap.

Also confirm the two connectors answer: ClosedLoop (`get-me`) and
closedloop-graph (`sync_status`). closedloop-graph is required. If it does
not answer, dispatch `vibe-setup-worker` to restore the connection; never ask
the person to set anything up beyond what that worker reports as
`NEEDS_PERSON`.

## 2. Start or resume

Run `node scripts/vibe-sessions.mjs list` (it uses the remembered checkout).

- No sessions with status `active`: start new (below).
- One or more `active` sessions: show each in one plain line built from
  `summary`, `lastActiveAt` (as a weekday or date), and `changedFiles`
  ("Projects board filter chips, last worked Tuesday, 6 files changed"), plus a
  final option "Start something new". Let them pick. Never resume on a guess.
- Any `active` session whose `lastActiveAt` is more than three days old gets
  one extra line: "This hasn't been handed off yet. Hand it off now, keep
  working on it, or throw it away?" Act on the answer (handoff skill, resume,
  or section 9).
- If their first message already describes the work, match it against the
  summaries and offer the match as a resume. If nothing matches, start new and
  mention the open sessions in one line.
- A `handed-off` session belongs to design and engineering now (its ticket is
  no longer assigned to the person who ran it): start new.

Starting new:
1. Use the work the person already described. Only when they have not supplied
   it, ask what they want to work on: a ClosedLoop ticket (ISS-, PRD-, or a pasted
   URL) or a plain description. A vibe session builds the real thing, backend
   included when a change needs it, so if they clearly want a mockup or an
   exploration with made-up data (nothing it shows needs to be real), start
   the prototype session below yourself. The person only types `$vibe` and
   `$handoff`; do not ask them to invoke `$prototype`. For a
   ticket, dispatch `vibe-requirements-worker`. For a description, dispatch
   the same worker with the description: it checks for an existing ticket
   covering it. Before creating the session, use the validated `<repo>` with
   `sessionless: {kind: "startup"}`, mode `request`, graph/live read capabilities
   and no record grants. Keep its brief internal; no upfront summary or plan approval.
   The route and FEATURE_MAP id it returns say where the relevant code lives
   and are for workers; never present them as a screen the session starts on
   (the app opens on its default page after sign-in), and never promise a
   screen for a broad request such as "look for visual bugs".
2. Use a mode the person already supplied; never ask again. Otherwise ask once: "Should your copy of the app start with sample data (a company
   called <email> Co with people and work in it), or empty so you set it up
   yourself?" Record `seeded` or `blank` as the mode. If they are unsure, use
   `seeded`.
3. Derive a short slug from the work (lowercase words joined by hyphens, at
   most 40 characters).
4. `node scripts/vibe-sessions.mjs new --slug <slug> --summary "<one line>"
   --mode <seeded|blank> [--ticket <slug>]
   --operator-id <id> --operator-email <email> --operator-name "<firstName lastName>"`,
   with the operator from the `get-me` call in section 1 (the person running
   this session; leave out `--operator-name` when `get-me` has no name). This
   fetches main and creates the worktree on `vibe/<slug>` from fresh
   `origin/main`. The live ticket is assigned to that person.
5. Record this conversation as the session's orchestrator:
   `node scripts/vibe-sessions.mjs codex-sessions --worktree "<wt>"` (it reads
   `CODEX_THREAD_ID`; outside Codex, pass `--thread <id>` if you have one, or
   skip it).
6. Dispatch `vibe-setup-worker` to bootstrap the new worktree, then
   `vibe-ticket-worker` in create mode with the worktree, the
   requirements worker's brief, the originating ticket if any, and the mode.
   It records the ticket's slug on the session itself.
   Keep the ticket link in the session record for completion and handoff.
7. Stand up the environment (section 3).

### Mockup sessions

Initial creation of a pure mockup session uses `new-prototype`, the same
operator and live-ticket rules, and one owned `prototype/<slug>` worktree from
fresh main, without an app data mode, API environment or flag snapshot.
Bootstrap/ticket setup remains operational. Then register/resume the SAME
persistent implementation writer under section 5 and forward the person's
mockup request. It reads the absolute canonical
`<repo-root>/.claude/skills/prototype/SKILL.md` guidance, plans locally, receives
independent plan review and performs all prototype/shared surface/registry
changes itself. Do not spawn a separate prototype source writer.

Preserve canonical mock-data, componentization, visual/product review and
metadata ownership. Ignore canonical steps asking for a second source writer,
worktree/branch or a technical-plan approval. All corrections and handoff-only
test writing return to this same context.

After independent current-result review/checks, the orchestrator commits with
its script. Dispatch `vibe-prototype-worker` only in operational share mode to
publish that exact reviewed commit through canonical Vercel sharing. If it
needs source generation/fixes, return those facts to the SAME writer. No
helper silently edits registry, metadata or implementation to make sharing pass.

Open only a verified immutable preview and return its URL, full deployed SHA
and slug on completion. Respect Vercel team login. A stale/failed share stays
blocked, never reported as current. Resume an owned prototype's existing writer
ID and publication; chat, annotations, fixes and handoff all queue to it.
Never create a new worktree/branch for these requests or an arbitrary
unrecorded prototype. Next-owner assignment and canonical metadata transitions
remain in the handoff flow.

Resuming: use the session's `worktree`, and run `codex-sessions` again so a
new conversation is recorded too. Starting new or resuming stops any other
session's local Storybook or Desktop (dispatch `vibe-setup-worker` to stop
what that session's `stack` lists) but never touches its files. You commit
only through `scripts/commit-worktree.mjs` and never push, stash, or rebase;
only `vibe-environment-worker` pushes, when the person asks to redeploy.

Desktop's screens reload live from the worktree, so merging main into it, or
any other swap of its commit, while Desktop runs crashes the Desktop tab
("Never swap the worktree under a running Desktop" in
`references/environment.md`). The main-sync publication sequence does this
only after stopping the owned Desktop. On `NEEDS_DESKTOP_STOP`, dispatch
`vibe-setup-worker` to stop Desktop, dispatch the worker again, then start
Desktop again and open its new tab (section 3, Desktop step 2 then step 3).

## 3. Stand up the environment

Before FIRST publication, register/resume the SAME implementation writer under
section 5's actual identity/hold/lease rules, not a new bootstrap source actor.
ROOT commits the reviewed deliverable LOCALLY under normal hooks, still unpushed,
before `commit-worktree.mjs --prepare-main-sync`; if no deliverable changed,
no extra commit is needed. Protected dirty localFix source remains preserved/blocking.
Apply `references/environment.md`, "Main-sync before publication": local
canonical plan/session table before source, separate plan checks, a completed
exact create preparation turn, same-writer fixes/behavior checks, ROOT commit
and that writer's actual committed-input validation. A new exact create grant
carries captured `mainSyncTransactionId`, build purpose and derived context.
No stale interim raw push is allowed.

Dispatch `vibe-environment-worker`
in create mode with the worktree, the live ticket slug, the mode, and
`references/environment.md` and matching transaction/context. It preserves
flag snapshot rules, pushes the explicit validated SHA through the gate,
starts the environment through GitHub, follows it to the end, records
the URLs on the session, and fills the ticket's Environment, Production flag
snapshot, and Sessions sections.

A resumed session whose `vercel.verifiedAt` is set already has its
environment; skip this and use its recorded `appUrl`, opening
`<appUrl>/sign-in` first as below. A resumed session
without it (one started before environments were verified) goes through
create mode again; the worker keeps its flag snapshot. If the worker returns `NEEDS_PERSON` asking which
one should own `<email> Co`, ask the person exactly its question, record the org
id the worker mapped to their answer with
`node scripts/vibe-sessions.mjs touch --worktree "<wt>" --clerk-org-id <org_...>`,
and dispatch it again. If it returns `NEEDS_PERSON` saying they are not an
admin of any of their organizations, pass that on as written and wait for
their answer. If it returns `BLOCKED`, tell the person in one or two
plain lines what failed and suggest they message Daniel Ochoa with the
session slug. Never open or give the person a URL after `BLOCKED`: any
preview address without its own deployment shows the stage production app.

When it returns `DONE`:
- Open the `appUrl` it returned (verified against the branch's own
  deployment) with `/sign-in` added (`<appUrl>/sign-in`) in a Codex in-app
  Browser tab and make the browser visible; the app's root sends a
  signed-out visitor to account creation, and the person already has an
  account. After this first sign-in, use the plain `appUrl`; if a tab ever
  lands on account creation instead, open `<appUrl>/sign-in`. The person signs in through Clerk as themselves (you never type
  credentials). Seeded: they land in `<email> Co` as an admin. Blank: they create
  their own org.
- Confirm the tab shows the app (with seeded data when seeded), not an error
  page or an empty shell, before saying it is ready.
- Start Desktop for every session, per the Desktop section of
  `references/environment.md`, and open it as a second tab:
  1. Run `node scripts/vibe-sessions.mjs desktop-tab --worktree "<wt>"`. If it
     reports `running`, skip to step 3.
  2. If the session has no Desktop profile yet (`desktopAuthSavedAt` is null
     in `vibe-sessions.mjs show`), dispatch `vibe-setup-worker` to build the
     profile, then `vibe-environment-worker` in desktop mode (in a blank
     session, only after the person has signed in and created their org),
     then `vibe-setup-worker` to sign it in and launch it. If it has one,
     dispatch `vibe-setup-worker` to launch it. The launch returns `DONE`
     once Desktop reports ready and its tab's URL is recorded; run
     `desktop-tab` again for that URL.
  3. Open its `url` exactly as given (never shortened, never shown to the
     person) in a second Codex in-app Browser tab, and confirm it shows the
     Desktop app's navigation (with seeded data when seeded), not
     `Connecting to Closedloop Desktop…`, an error, or a refused connection.
     If `desktop-tab` reports `running` with no `url`, the session's worktree
     predates the Desktop tab: Desktop is open as its own window, as before,
     and there is no tab to open.
  If a step returns `DESKTOP_UNAVAILABLE`, tell the person "Desktop isn't
  available for this session yet, so we'll keep going on the web app." and
  continue web-only.

If setup diagnoses a repo bug that stops local startup, route its ticket and
evidence to the SAME persistent writer for the managed local workaround in
`quality-loop.md`. Keep the diagnosis and ticket internal. The sole writer
records every changed file as a local fix; no redeploy or handoff commits it.
Setup only retries the launch after that verified correction, never patches code.

### Bringing a tab back

Whenever the person asks to bring back or reopen the app or Desktop (they
closed the tab, or it stopped answering), open a new tab for the one they
named:
- The web app: the plain `appUrl` (`<appUrl>/sign-in` if it lands on account
  creation).
- Desktop: run `node scripts/vibe-sessions.mjs desktop-tab --worktree "<wt>"`.
  If it reports `running`, open its `url` exactly as given. Otherwise Desktop
  quit, was stopped, or never started: start it as in step 2 above, then open
  the new `url`. On `DESKTOP_UNAVAILABLE`, use the same sentence as above.
  With `running` and no `url` (a worktree that predates the tab), tell the
  person Desktop is open in its own window on their Mac for this session.
  Never open a Desktop URL from an earlier launch or one copied from a tab's
  address bar; each launch has its own.

## 4. Set expectations

After they sign in, leave the app on the page it lands on. When the person
asks how to make changes, use the existing guidance:

- In either tab, click Annotate in the browser toolbar (or press Cmd + .),
  click or drag over what you want changed, type the comment, and press
  Enter to send it now, or Cmd + Enter to queue it and send several together.
- You can also just describe the change in chat.
- Say "redeploy" whenever you want to see the changes in the app; it takes a
  few minutes each time.

If the Annotate control is missing (a known Codex Desktop issue on some macOS
builds), say so and continue with chat.

For a net-new screen or capability, have the requirements worker research its
existing product rulings first. Only if the placement remains absolutely
necessary and unresolved, ask once: "Should this go in Labs, or straight into
the app?" Default to straight into the app when no unresolved decision is needed.

## 5. Build loop

Follow `references/quality-loop.md`: ONE persistent implementation writer,
ONE worktree and branch, and a serial request queue. No unit-specific code
writers. Backend/primitive/prototype/Storybook fixes and later tests belong to
this same writer context. Researchers/reviewers may be read-only and parallel.

### Register once, then resume

On the first request, Codex spawns the canonical `vibe-change-worker` once and
records the actual ID through `scripts/dist/writer-state.mjs register` with
runtime `codex`. Later calls use that SAME native follow-up/resume ID. Claude
uses `scripts/dist/claude-worker.mjs` with the scoped canonical role; its
recorded underlying session ID is resumed, never a fresh context with the same
name. Use the parent-discovered exact capabilities, not a configured-prefix
guess or blanket MCP inheritance. All private input is JSON on stdin.

Use the owned state helper's status/enqueue/claim/take-input/finish actions.
Queue incoming requests while one is active. For native Codex, claim its exact
writer/request/lease, take the durable input, and forward it to the recorded
worker. Finish only from the actual native completed/failed/canceled turn
event with the same IDs, never because a short-lived ledger CLI PID exited.
Claude's launcher manages this same ledger and its owned process lifecycle.
Do not dispatch or resume the writer concurrently. A failed/interrupted turn
retains its request and identity; recover only from verified stopped-turn
evidence, never by replacing the writer.

### One request through completion

1. Forward the person's request/annotation verbatim, session/branch, live
   ticket, known rulings and supplied copy to the SAME writer. It performs
   graph/owner prep and writes the canonical core-template plan locally.
   It always creates or extends the one session decision table at
   `.closedloop-ai/decision-tables/<session-slug>.md` before any code, using
   the named core skill in quality-loop.md. Include its path and affected/
   interacting row IDs in every applicable worker brief. Later requests append
   to this same artifact with provenance; no per-request table or history reset.
   No upfront summary, technical question or plan approval reaches the person.
2. On `PLAN`, dispatch the separate read-only adversarial plan reviewer.
   It must read the actual table and its real source-backed rows/frozen targets,
   not accept a returned path, checkbox or placeholder. Missing or unsourced
   rows return to the SAME writer; no code starts before that review clears.
   Continue the active request in the SAME writer with its findings; it fixes
   the plan. Recheck confirmed corrections before implementation.
3. Resume that writer to implement in dependency order. It can load canonical
   backend, primitive, prototype and Storybook guidance from its own plugin,
   but no new source writer/worktree/branch. Read-only specialists advise;
   their findings return to this writer. Preserve real visual/product approvals.
4. On `NEEDS_REVIEW`, run independent read-only implementation reviews and
   existing checks. Use core workflow review for backend work. Return confirmed
   issues to the SAME writer, recheck its fixes, and do not leave preventable
   issues until handoff. Existing tests may run; none are authored yet.
   The writer first verifies affected and interacting prior table rows against
   actual code, fixes source gaps and supplies the same artifact/row evidence
   to reviewers. Planned handoff tests remain distinct from executed coverage;
   they never justify premature core Final Aligned or a source-gap waiver.
5. Research any `NEEDS_PERSON` through the graph/live-decision necessity gate.
   Ask only an absolutely necessary unresolved product question, one at a time
   with full context. Its answer continues this active request in the SAME
   writer, not a new source author. Technical blockers stay internal.
6. Record scope/progress/backend facts through the writer's explicit serial
   record continuation or the authorized ticket helper, never simultaneously.
   Keep technical plans private. Operational bootstrap/build/deploy helpers
   execute no implementation edits, and sharing waits for the writer and
   independent gates. The orchestrator alone commits through its owned script.
7. A `DONE` must mean the whole requested feature passed its required checks
   and independent reviews. Then finish that request and tell the person only
   the completed feature and next work, in their own terms. The next queued
   request goes to the SAME ID/context. Update the session summary through
   the existing session script in a serial record turn.
   This is per-request implementation evidence, not final session coverage.
   Retain whole-table pending test plans and unresolved final evidence until
   the same writer's explicit handoff; do not erase earlier request rows.

Pure mockups still use canonical `$prototype` guidance through this writer;
the person only types `$vibe` and `$handoff`. Initial session creation chooses
one app or prototype branch. Never add a second worktree/branch for a sub-unit.
Local Storybook remains available and product design approvals stay intact.

## 6. Redeploy

When the person says "redeploy", "redeploy to Vercel", "push it up", "put it
on Vercel", "let me see it live", or anything meaning the same:

1. Run `node scripts/vibe-sessions.mjs codex-sessions --worktree "<wt>"` so
   the ticket lists every subagent so far.
2. Keep deployment progress internal; report completion, not technical steps.
   After current-result review, ROOT commits the reviewed deliverable LOCALLY
   with the existing commit script and normal hooks, still unpushed. Then the
   publishing helper runs `commit-worktree.mjs --prepare-main-sync`.
   Before any remote push repeat `references/environment.md`, "Main-sync
   before publication": extend the SAME writer's local plan/session table,
   complete plan review, run a separate noncommitting preparation turn after
   source stops, and route all conflicts/fixes to that writer. Preserve
   captured main/original base/imports. Do not replace/re-register a native
   actor because its old cache is absent.
3. After preparation and SAME-writer conflict/source correction, ROOT commits
   the staged ordinary merge and any reviewed fixes (nothing is pushed yet):
   `node scripts/commit-worktree.mjs --worktree "<wt>" --subject "<live ticket slug>: <plain imperative summary of the changes since the last redeploy>" --body "<the screens changed, one per line>"`.
   The subject stays under 72 characters and never mentions AI tools. The
   script leaves out the session's `localFixes` and files that never belong
   in a commit, and the repository's commit hook runs. `committed: false`
   means nothing changed; continue. `"ok":false` means the hook refused:
   resume the SAME persistent writer in fix mode with the error, then commit again.
4. Dispatch `vibe-environment-worker` in redeploy mode with the worktree, the
   live ticket slug, the session summary, and the session's `localFixes`
   paths. First resume that SAME writer's source-owned `progress` continuation
   to run `main-sync-validate` against committed inputs. The later publisher
   grant carries captured `mainSyncTransactionId`, build purpose and actual
   stdin context. It pushes only the admitted SHA, requests the environment again so that commit is
   deployed, and updates the ticket. Existing checks have run through the
   quality loop; test authoring still waits for handoff.
5. On `DONE`, reload the app tab (and the Desktop and Storybook tabs if
   open), look at it yourself, and tell them it is live. Whenever you open
   the Vercel `storybookUrl` and the tab lands on `vercel.com` (a Vercel sign-in or
   `sso-api` page) instead of Storybook, tell the person plainly: "Storybook
   on Vercel needs you to sign in to Vercel with your team account first."
   Do not try to get around it. On `BLOCKED` because the repo's checks
   refused the push or a build failed in the session's own change, dispatch
   the SAME persistent writer in fix mode with the failure, then re-review
   and verify its fix before committing
   and redeploying again (steps 3 and 4). Keep the repair details internal.

Never redeploy unless the person asked.

## 7. Feature flags

The environment uses the production flag values captured when it was created
(on the ticket under Production flag snapshot). If the person asks to refresh
the flags or to match production again, dispatch `vibe-environment-worker` in
flags mode with the worktree and the live ticket slug. Never refresh them
otherwise.

## 8. Ending a session

When they say they are done, ask once: "Hand this off now, keep it to come
back to, or throw it away?" On "hand it off", run the handoff skill. On "keep
it", dispatch `vibe-setup-worker` to stop local Storybook or Desktop if either
runs. Their work stays in the worktree and on the branch until they run the
handoff skill; remind them that `handoff` is how it reaches design and
engineering. On "throw it away", follow section 9.

## 9. Throwing a session away

Whenever the person asks to throw a session away (at any point, for any
`active` session):

1. Run `node scripts/vibe-sessions.mjs discard --worktree "<wt>"` (without
   `--confirm` it changes nothing). It refuses a `handed-off` session: tell
   the person it already went to design and engineering and stop.
2. Tell them in plain words what will be lost: the session's summary, the
   number of unsaved files, that their copy of the app on Vercel and its data
   will be deleted, and that the ticket will be canceled. Ask them to confirm.
3. On a clear yes, retain the validated remembered `<repo>` separately from
   the target `<wt>` and the parent-held preview's branch, live ticket and
   operator. Dispatch `vibe-setup-worker` from that stable `<repo>` with
   `sessionless: {kind: "startup"}`, mode `record`, `recordAction: "discard"`,
   `exclusiveRecordTurn: true`, graph/live reads only, and `discardTarget`:
   `{worktree: "<wt>", confirmed: true, branch, operatorId, operatorEmail}`
   plus `liveTicket` only when present. The launcher independently checks the
   target's private record and same Git repository and locks both contexts;
   its definition, trace and stable record lock remain until completion.
   The worker re-verifies target ownership and the person's confirmation, never
   deletes its execution checkout, and discards only the target worktree. It
   stops the session's local processes, requests the drop of the session's
   data in symphony-alpha (nothing removes it automatically), deletes the
   worktree and the local and remote branch, and returns the script's receipt.
4. Only after that successful result has `discarded: true`, retain its
   `cancelEvidence` in the parent. If there was a live ticket, dispatch
   `vibe-ticket-worker` from the retained `<repo>` in mode `record`, action
   `cancel`, with `exclusiveRecordTurn: true` and
   `sessionless: {kind: "discarded", evidence: <cancelEvidence>}`. Grant only
   parent-discovered graph/live reads and the declared cancel writes. It verifies
   the live ticket and exact operator before canceling. A failed/partial discard,
   absent receipt, missing ownership or deleted execution root blocks cancellation.
5. Tell them in one line that it is gone.

## References

- `references/closedloop-graph.md`: how every worker uses closedloop-graph.
- `references/quality-loop.md`: one persistent writer/queue, local plans, read-only independent reviews, researched product questions and handoff-only test authoring.
- `references/preflight.md`: fixes for every preflight check (setup worker).
- `references/environment.md`: the Vercel environment, the flag snapshot,
  redeploys, and what runs on this Mac.
- `references/ticket-template.md`: the live ticket's sections and who keeps
  each one current.
- `references/guardrails.md`: what may change and how (change and primitive workers).
- `references/design-pass.md`: the owner rules, the build loop's prep step,
  and the handoff red-flag screen and restructuring.
- `references/annotations.md`: turning annotations into code locations (change worker).
