autonomous-variations · git:20261103.5dc815c · 2026-11-03 · sha256 3ad99212e683cd93
autonomous-variations git:20261103.5dc815cA
Immutable. This exact content never changes and is served at /api/v1/blob/3ad99212e683cd93.
---
name: autonomous-variations
description: "Autonomous: Variations. Run variation labs unsupervised for one part of a product: exactly the count asked for, genuinely different ideas plus today's version as a baseline, in real context with real content, one lab per decision with its own worktree, branch and port. Covers the shared lab conventions (?v=, [ and ], a switcher pill, ?motion=off, ?embed=1, manifest.json, stills), every variation finished at desktop, tablet, phone and reduced motion, headless checks and contact sheets before reporting, briefs that carry the user's visual and copy rules, rounds built on named winners, porting the pick verbatim from its commit, coordinating many labs, labs across dev boxes that run on their own, and one review page that ends in a prompt naming each pick. Use for 'make N variations', 'explore options', 'a lab for X', 'more of these two', 'pick one and port it', 'run the lab on dev boxes', or 'one page to review all the labs'. Pairs with autonomous-prototypes and autonomous-runs."
---
# Autonomous: Variations
Turn "show me N ways to do X" into a set the user can judge in minutes, and a pick that ships
without rework. Each decision gets a lab: one part of the product, shown in its real context, with N
genuinely different variations and today's version, built to shared conventions so one page can
review every lab and the pick ports verbatim. The bar: the user steps through the lab with `[` and
`]` at any size, with motion on or off, and decides without hitting anything broken, cramped or
invented.
Building inside the real product follows
[`autonomous-prototypes`](../autonomous-prototypes/SKILL.md) (in Code OSS a lab is a set of
Component Explorer fixtures or a setting enum; the rules here still apply). Videos of the variations
use the variant matrix profile in [`autonomous-demos`](../autonomous-demos/SKILL.md). Overnight runs
with many labs also follow [`autonomous-runs`](../autonomous-runs/SKILL.md). Web gotchas
(CSS leaking between pieces, syncing from a working tree, local servers without CORS) are in
[`labs-and-pages.md`](../autonomous-runs/references/labs-and-pages.md) in autonomous-runs.
## Standing rules
1. **One lab per decision, in real context.** Scope the lab to the part being decided (a hero
animation, a homepage section, how a panel's details open), never a rebuild. Show it with the
real surrounding UI, content and assets, and hold everything else at today's version, so only the
decision changes.
2. **Exactly the count asked for, genuinely different.** Different ideas, not parameter tweaks of
one idea. Each gets an id, a short name and a one-line idea, and today's version is the baseline
(`?v=0`) whenever there is one.
3. **The same conventions in every lab.** `?v=<id>`, `[` and `]`, a switcher pill, `?motion=off`,
`?embed=1`, a README with the variations table, `manifest.json` and stills. Then one review page
can frame any lab.
4. **Finished everywhere.** Every variation works at desktop (1440x900, 1280x800), tablet
(820x1180), phone (390x844, touch, 44px targets, nothing hover-only) and with reduced motion. No
variation is desktop-only by accident.
5. **Real content only.** Never invent posts, people, quotes, data or product UI. Use the real thing
or leave it out, and say so.
6. **Verify headlessly before reporting.** Zero errors, nothing overlapping or cropped, no sideways
scroll on phones, smooth frames, and contact sheets you actually looked at and iterated on. This
is the full check; it never holds back the review link (rule 11).
7. **Every brief carries the rules.** Paste the user's standing visual and copy rules (palette,
accent, case, punctuation, real content only) and the hard rules (worktree, branch, port, never
push, never touch other agents' work or processes, headless only) into each lab brief, and save
the brief to a file before starting the lab.
8. **Rounds build on named winners.** A new round carries the user's notes; earlier rounds stay
reachable.
9. **The pick ports verbatim.** The lab documents the port; the integration copies files from the
named commit with a sync script and never edits the copies.
10. **Ambiguity gets a decision, not a question.** When the framing is ambiguous (the order of the
sections, how the families split), pick a reading, say so in the README, and fix it fast when
the user corrects it.
11. **The link comes first.** Seeing the UI matters more to the user than tests. Send the review
link as soon as the lab loads without errors, then run the full checks, fix, and send the
updated link. Every report lists every lab's link; when some labs are not ready, send the
ready ones now instead of waiting for all of them.
## 1. Scope the lab
- Write the question in one sentence (it becomes the manifest's `question`) and keep the user's
words verbatim (the README opens with them).
- Show the part where it lives: the real header, the sections just above and below, the real assets
and type. Load the integration's own files, or generate the lab page from them, rather than
redrawing them.
- Name what is out of scope. When a neighbouring decision belongs to another lab, keep that part as
today and say so. When one lab's variation sits inside another lab's section, note the dependency
in both READMEs.
- **Count.** When the user names a number, make exactly that many. When they don't, make as many as
are meaningfully different; spikes from research findings follow the one to three rule in
[`autonomous-research`](../autonomous-research/references/synthesis.md).
- **Families.** When the ask has two directions (two orders, two winners), split it into families
with prefixed ids (`A1` to `A6`, `B1` to `B6`). Align them so the same number makes the same
choice in each family; then every row compares exactly one thing.
## 2. Set up the worktree
```bash
git -C <repo> worktree add -b lab-<slug> <repo>.worktrees/lab-<slug> <integration branch>
cd <repo>.worktrees/lab-<slug> && mkdir -p labs/<slug>/work && echo '*' > labs/<slug>/work/.gitignore
```
- One worktree, branch and local port per lab, made from the integration branch. Record lab, branch,
worktree, port, owner (chat or agent) and scope in the run ledger and the integration's handoff.
- Serve the worktree root on the lab's port, started detached so it survives turns and restarts.
Never start a second server for the same lab, and never stop a server you did not start.
- Keep the lab in its own folder (`labs/<slug>/`) and change nothing the integration owns. If a
variation truly needs a hook in a shared file, add the smallest hook and say so in the README.
- Scratch screenshots and tools go in the git-ignored `work/` folder, deleted at the end.
- Commit as soon as the page loads, then after every variation, so a restart never costs more than
minutes. Commit only on the lab's branch, and never push unless the user asks.
## 3. Design the set
- **Write the list first.** N names and one-line ideas before building anything. Each should change
how the thing works or reads, not a duration, a color or an offset. If two lines read alike,
replace one.
- **Order it on purpose**, for example from subtle to expressive, or in the order the user listed
directions, and say which.
- **One interface, one kit.** Define the small contract every variation implements before building
any: a spec with layout and frame hooks, a `mount(section, data, options)` that returns
`{ destroy() }`, or a pure function of scroll progress. Shared behavior lives in one kit. Then any
pick ports the same way: the kit plus one variation file.
- **Isolate the variable.** Everything except the decision is identical across variations: the same
content, neighbours and timing. The baseline replays today faithfully, pixel for pixel at rest
where possible.
- **Second axes are toggles, not more variations.** When a choice is orthogonal (a text style, an
arrangement, a light or dark widget), give it its own key and parameter (`T` and `&text=`, `A` and
`&arr=`) that persists while stepping.
## 4. Build to the lab conventions
Every lab works the same way (`?v=` ids with `?v=0` as today, `[` and `]` to step through, the switcher
pill, `?motion=off`, `?embed=1`, and the sizes): see
[`references/lab-conventions.md`](references/lab-conventions.md).
## 5. Verify before reporting
Write a check script per lab: headless Chrome through an existing Playwright install, never visible
windows. Load every variation at every size, with motion on, `?motion=off` and the system setting
(`reducedMotion: 'reduce'`), embedded and not; phones with `isMobile` and `hasTouch`. Exit non-zero
on:
- any page error, console error or failed request;
- text overlapping text or images (compare the client rects of visible text runs and images), or
content past the screen's sides;
- a page wider than the viewport (`scrollWidth > innerWidth`), on phones above all;
- anything cropped or resized that the design keeps whole;
- touch targets under 44px on touch devices;
- with motion off, a running animation or a frame that changes at rest.
Then check what the variations promise:
- **Frames** while scrolling and interacting: under about 25 ms, no long animation frames. Headless
numbers only compare with each other; record when and where they were taken.
- **Behavior:** the keyboard flow, Esc returning focus, clicks only where the variation says the
page is live, reversibility (the same styles at a scroll position reached going down or up),
movement in one axis when that is the rule, and `]` then `[` returning to the identical frame.
- **Contact sheets:** one labeled row per variation, a column per state or moment, plus phone and
reduced-motion sheets. Open them and look. Fix what is cramped, misaligned, clipped or noisy, and
iterate: the user reviews visually, so the quality on screen matters more than anything.
- **Earlier rounds** get rechecked whenever the shared kit changes.
- Record the last results in the README with the date, the machine and the counts ("all 12 at four
sizes, motion on and off, zero errors").
## 6. The README, manifest and stills
What the README says and in which order, the manifest, and the stills: see
[`references/lab-conventions.md`](references/lab-conventions.md).
## 7. Rounds
- When the user names winners ("these two are the winners"), make the next round: N variations of
each winner, a family per winner, that carry their notes. Put the notes verbatim at the top of the
README and say how each is answered.
- Read vague notes explicitly and record the reading ("a bit longer" means longer than round one,
shorter than today).
- Keep earlier rounds reachable: by id on the same page, on a sub-page (`v2/`), or by a commit
listed in the README.
- When one lab's pick sets a look (the details' type, a hover style), other labs showing related UI
adopt it token for token, so the page stays one piece.
- When shared content changes upstream (the user rejects an example), every lab that shows it merges
the integration branch and retakes its stills.
## 8. Port the pick
The lab side:
1. Write a porting section: the files to copy, the interface, numbered wiring steps against the
integration's real functions, load order and dependencies, gotchas (state the integration sets
differently today), what not to port (lab chrome, `?embed=1`, the manifest, review-only
shortcuts), and the checks to run afterwards.
2. Add a port reference page: the pick on its own, with only the files it needs, mounted exactly as
the integration will mount it.
3. Prove the steps on a scratch copy of the integration's file, never the real one. Commit, then
send the integration side a self-contained message: the commit, the file list, where it goes and
what changed.
The integration side:
1. Copy the files verbatim from the named commit with a sync script that records the source:
`<this skill>/scripts/sync-pick.sh lab-<slug> labs/<slug> <dst> <files...>` reads from the commit
(never a working tree) and writes `SOURCE.md` with the ref, commit and file list. Never hand-edit
the copies: change the lab, commit, sync.
2. Wire it per the README. Verify at every size and motion setting, and that the rest of the page
did not move (compare its layout against the previous commit).
3. Commit, deploy the preview if that is the flow, reply to the lab with the integration commit, and
record the pick in the lab's README and manifest (`picked`).
4. A link the team already has stays frozen (a tag or its own environment); republish it only when
the user asks.
Stay current: labs merge the integration branch to pick up shared changes. A lab generated from
integration files anchors each hook on text that appears exactly once, so the build stops by name
when the integration moves it; edit the lab's template, never the generated page.
## 9. Many labs at once
One brief per lab, new chats on the top model, one owner per asset, and the one review page that
walks every lab and ends in a prompt naming each pick: see
[`references/many-labs.md`](references/many-labs.md). Labs across dev boxes add
[`references/distributed-labs.md`](references/distributed-labs.md).
## Taste notes worth carrying
The user's recurring visual, motion and layout taste lives in
[`autonomous-prototypes/references/design-taste.md`](../autonomous-prototypes/references/design-taste.md).
Paste the notes that apply into every lab brief as examples of the user's taste, not as universal
law; the user's latest word wins.
## Scripts
| Script | Purpose |
|--------|---------|
| `sync-pick.sh` | copy a pick's files verbatim from a lab commit into the integration and write `SOURCE.md` |
| `check-manifest.mjs` | check a lab's `manifest.json` and stills against the contract; `--live` checks its server |
| `make-briefs.py` | one brief and one short start prompt per variation, from a template, the variations table and per-host notes |
| `drop-server.mjs` | the hub's file drop for labs across dev boxes: key-gated, write-once bundles, text and review media, published through a dev tunnel |
| `drop.mjs` | the drop's client: send and receive bundles, put and get files, wait on files, mirror, and an outbox with a flush loop |
| `drop-sync.sh` | merge the kit and every delivered variation from the drop into a review worktree, then run the manifest tool |
| `drop-watch.sh` | keep that review worktree synced and its server up, detached, with nobody watching |
`sync-pick.sh` needs only bash and git; `check-manifest.mjs`, `drop-server.mjs` and `drop.mjs` need Node 22 or
newer; `drop-sync.sh` and `drop-watch.sh` need bash (3.2 is fine, and Git Bash on Windows), git and curl;
`make-briefs.py` needs Python 3. Each one documents its options at the top of the file.
## Maintaining this skill
Add reusable lessons here or in the autonomous-runs references, fix wrong steps in place, keep the description under
1024 characters, and never use em or en dashes.