Follow-up PR to #95 (Liquid Glass foundation + primitives + Layout shell) that closes out the remaining sub-convoy briefs in a single sweep. Operator-instructed scope: "finish off the design changes." After this PR, **all 8 Liquid Glass sub-convoys are MERGED to main**; the deferred-from-#5 `fix-card3d-state` convoy is dropped (its target, `components/Card3D.js`, turned out to be dead code). ## #2 Brief 2 — Remaining 8 modals migrated to <Modal> primitive - `CollectionsSuccessModal.js` — wrap in <Modal hideCloseButton>; 2 Buttons. - `CollectionsEditModal.js` — full <Modal> + <Input> + <Button> rewrite (4 fields, tag chip section, public-toggle preserved, 2 footer Buttons). - `CollectionEditModal.js` — same pattern as above (4 fields + public-toggle + 2 Buttons). - `CardDetailDeckModal.js` — <Modal> + native select (Select primitive not in scope) + 2 Buttons; sweep `gradient-bg-purple` → `<Button variant="primary">`. - `UploadImageModal.js` — <Modal> + token-driven URL/file tab switcher + drag-drop using `--accent-ember` rim + 2 Buttons (one with `loading` prop). - `CollectionSelectionModal.js` — largest of the set (header summary + SearchBar + scrollable list w/ checkbox toggles + footer); migrated to <Modal size="lg"> while preserving the per-collection card preview thumbnails. - `OCRSettings.js` — trivial <Modal> wrap + single primary <Button>. - `pages/decks.js` — both inline modals (Create Deck + Edit Deck) and `components/ScannerPageView.js` (Create List) migrated; ScannerPageView dropped its `useFocusTrap` named-import (Modal's internal focus trap owns the panel ref now). - **`.github/workflows/ci.yml` `forbidden-modal-shell-without-primitive`** — grandfather list emptied to zero entries; gate is now strict. ## #3 Brief 2 — Forms migrated to <Button> / <SearchBar> - `pages/dashboard.js` — 3 CTAs → <Button> (Create List with leadingIcon, Create Your First List, View All Lists). - `pages/my-cards.js` — empty-state CTA → <Button variant="primary" size="lg">. View-mode toggle buttons intentionally left native (icon-only, doesn't match Button variants). - `pages/community/collections.js` — Go to My Lists CTA → <Button>. - `components/CollectionsPageView.js` — Discover Community + Create List header CTAs → <Button>; search input → <SearchBar>. - Card-grid per-row icon buttons (CollectionsPageView, my-cards, CardsPageView) intentionally left native — tiny per-card actions whose styling doesn't match Button variants and would invalidate visual-diff baselines. ## #5 — scope revised + landed `components/Card3D.js` deletion: surveyed every importer with grep — **zero consumers** in `pages/**` or `components/**`. Only references were in convoy docs. The "pre-existing state-management bug" (state setters used without useState declarations) never affected the running app because the component was never rendered. -505 LOC. The `fix-card3d-state` convoy is dropped from the roadmap as a result. The actual card-grid component (`components/CardItem.js`) is intentionally **not** modified in this sweep — it has per-rarity glow tuning that the existing visual-diff baseline locks in, and the architect's #5 deferral note specifically called out the dedicated baseline re-seed cost. A future implementer turn can apply rim-light tokens to CardItem with its own baseline re-seed when an operator wants that polish. ## #6 Brief 1 — Landing + invite pages glass-migrated - `pages/index.js` — top nav: `var(--glass-surface-mid)` + `--glass-blur-mid` + rim-light. 3 feature cards: `<GlassSurface tint="mid" rim="subtle" elevation="ambient">`. Featured-list cards (the public collection grid): same `<GlassSurface>` recipe with motion-token transitions. All 6 CTA buttons → <Button variant="primary"|"secondary"|"ghost"> with proper sizes. Pulse-loading placeholders tagged `.motion-essential` so reduced-motion users still see them animate (state-meaningful). - `pages/invite/accept.js` + `pages/invite/decline.js` — both outcome panels wrapped in `<GlassSurface tint="mid" rim="subtle" elevation="pronounced">`. Loading spinner border colors corrected from `--text-accent` (which didn't exist) to `--accent-ember`. All 8 buttons → <Button>. `gradient-bg-ember` consumers retained (the canonical warm-palette utility class is fine). ## #8 Brief 2 — Legacy alias sweep + CI gate graduation - Swept `gradient-bg-purple` → `gradient-bg-ember` across **8 files** / **13 occurrences**: `CardDetailQuantityModal`, `CardEditorView`, `CardEditorForm`, `AdminProtected`, `pages/card/[id]`, `pages/invite/{accept,decline}`, `pages/admin/card-import`. `gradient-bg-purple` was a dangling class name with no CSS definition (it was rendering no styling), so the sweep is also a bug fix — those buttons now actually get the ember gradient. - Deleted the 5 dead CSS classes from `styles/globals.css`: `.gradient-text-blue`, `.gradient-text-purple`, `[data-theme="dark"] .glow-blue`, `[data-theme="dark"] .glow-purple`, `[data-theme="dark"] .glow-pink`. Each was zero-consumer post-sweep. - **Graduated the `forbidden-deprecated-color-aliases` CI job from WARN to FAIL.** All 9 patterns (`gradient-text-{purple,pink,blue}`, `glow-{purple,pink,blue}`, `gradient-bg-{purple,blue,pink}`) now block the build if any consumer is reintroduced. ## Verification (local + CI gates locally exercised) - Lint: 0 errors, 2 pre-existing warnings (`CardEditorForm.js` + `CollectionsPageView.js` carry-overs from before #95; out of scope). - Vitest: 104/104 passing — unchanged from #95. - Build: clean (Turbopack default; passes both light + dark theme prerender). - `forbidden-modal-shell-without-primitive` gate: locally clear (`grep -lE 'fixed inset-0 bg-black bg-opacity-' pages components -r --include='*.js'` returns no matches). - `forbidden-deprecated-color-aliases` gate: locally clear (all 9 patterns return no matches in `pages/` or `components/`). ## What still needs human action - **Linux visual-diff baselines** must re-seed via the Docker workflow in `AGENTS.md` § 6. This PR's landing-page + invite-page changes will produce baseline drift on the homepage screenshot (which is currently the only baseline committed) AND additional baselines will be generated for the landing's glass-card sections once the visual spec is expanded. Recommended: run the Docker re-seed against this PR's Vercel preview, commit the result to this branch, push, verify CI green, then merge. - Vercel auto-promotes the merge to production. ## Closes / supersedes - Closes `.convoys/liquid-glass-modal-and-surface-primitive.md` Brief 2 (status → merged). - Closes `.convoys/liquid-glass-form-primitives.md` Brief 2 (status → merged with explicit per-row-icon-button deferral note). - Closes `.convoys/liquid-glass-public-and-auth.md` Brief 1 (status → merged). - Closes `.convoys/cleanup-legacy-design-css.md` Brief 2 (status → merged + CI gate FAIL). - Drops `.convoys/liquid-glass-card-surfaces.md` Brief 1 prerequisite (`fix-card3d-state` no longer needed; Card3D deleted). - Drops the queued `fix-card3d-state` follow-up from the roadmap (target deleted). - Updates `.convoys/ship-readiness.md` § "Design-system redesign portfolio" with a "Finish-portfolio sweep" subsection documenting final status of all 8 sub-convoys. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|---|---|---|
| .. | ||
| add-rate-limiting | ||
| adopt-playwright-smoke | ||
| bump-next-js | ||
| cors-tighten | ||
| drop-public-setup | ||
| fix-auth-bypass | ||
| fix-layout-default-user | ||
| fix-vercel-deployment-protection-in-ci | ||
| liquid-glass-design-tokens | ||
| pick-a-name | ||
| redesign-scanner-flow | ||
| add-rate-limiting.md | ||
| add-real-ocr-layer.md | ||
| adopt-playwright-smoke.md | ||
| bump-next-js.md | ||
| catalog-sync-vercel-cron.md | ||
| cleanup-legacy-design-css.md | ||
| cleanup-mobile-nav-dead-props.md | ||
| cors-tighten.md | ||
| drop-public-setup.md | ||
| fix-auth-bypass.md | ||
| fix-layout-default-user.md | ||
| fix-reset-db-script.md | ||
| fix-vercel-deployment-protection-in-ci.md | ||
| lint-against-cjs-in-esm-scripts.md | ||
| liquid-glass-card-surfaces.md | ||
| liquid-glass-design-tokens.md | ||
| liquid-glass-form-primitives.md | ||
| liquid-glass-layout-shell.md | ||
| liquid-glass-modal-and-surface-primitive.md | ||
| liquid-glass-public-and-auth.md | ||
| liquid-glass-redesign.md | ||
| migration-tool.md | ||
| motion-system-pass.md | ||
| pick-a-name.md | ||
| purge-quick-login-from-loginpage.md | ||
| purge-weak-creds-from-helpers.md | ||
| README.md | ||
| redesign-scanner-flow.md | ||
| rename-collections-vocabulary.md | ||
| scanner-correctness-polish.md | ||
| scanner-redesign-a11y-fixes.md | ||
| scanner-user-cards-quantity-guard.md | ||
| secure-scanner-gemini-key.md | ||
| server-side-scan-pipeline.md | ||
| ship-readiness.md | ||
| single-auth-provider.md | ||
| single-sql-client.md | ||
| test-scanner-redesign-surfaces.md | ||
| tighten-visual-diff-path-filter.md | ||
Convoys
A convoy is a multi-PR work-stream coordinated by an agent pipeline. One convoy = one feature, bug fix, or epic. Each convoy is a Markdown file in this directory plus an optional sub-directory of implementer briefs.
File layout
.convoys/
├── README.md (this file)
├── <slug>.md (the convoy file — written by role-conductor)
└── <slug>/
├── brief-1-<kebab-title>.md (written by role-architect)
├── brief-2-<kebab-title>.md
└── ...
Convoy file format
Frontmatter (set by role-conductor, then appended-to by other roles):
---
name: <kebab-slug>
classification: feature | hotfix | docs-only | infra-only | server-only | config-only
success_metric: <one sentence>
skip:
- <flag1>
status: open | in-progress | merged | shipped | abandoned
created: <YYYY-MM-DD>
---
Body sections (added in order by the pipeline roles):
## Why(Conductor)## Scope(Conductor)## Roles invoked(Conductor)## Todos(Conductor → refined by Architect)## IA(IA Architect)## UX(UX Reviewer)## Architecture(Architect)
After Architect, briefs live in .convoys/<slug>/brief-N-*.md. Implementers read only their brief, not the whole convoy.
Skip flags
The Conductor sets skip: based on classification. These flags map to pipeline stages that no-op when set:
| Flag | Skips |
|---|---|
ia |
IA Architect |
ux |
UX Reviewer |
arch |
Architect |
test |
Component tests |
review |
Reviewer |
visual |
Visual diff |
a11y |
A11y auditor |
design |
Design-system auditor |
smoke |
Staging smoke |
qa |
Manual QA |
docs |
Doc Writer |
flag |
Flag rollout |
Never skipped (mandatory human gates): plan-approval, pr-merge, prod-promote.
Status lifecycle
open— Conductor created the convoy; no work started.in-progress— At least one brief has an open or merged PR.merged— All briefs merged to umbrella; release PR to develop pending.shipped— Release to main complete; flag rollout (if any) underway.abandoned— Convoy closed without shipping; reason in convoy body.
Update status by editing the convoy frontmatter as you progress.
Adding a new convoy
- Open Cursor in this repo.
- Prompt: "Start a new convoy: . Success = ."
- The
role-conductorsubagent writes.convoys/<slug>.md. - Run subsequent roles in order per the convoy's
Roles invokedlist.
See .cursor/agents/role-conductor.md for the Conductor's full spec.
Multitask + worktrees (Cursor 3.2+)
Cursor 3.2 (Apr 24, 2026) added /multitask async subagents and native worktree management in the Agents Window. The pipeline uses both:
Audit fan-out — after an implementer ships a PR draft:
/multitask role-reviewer + role-design-system-auditor + role-a11y-auditor
All three read the same diff and emit independent comments. Use group id audit-<convoy>-<pr> so analytics can compute wall-clock savings.
Implementer fleet — after architect's plan is approved (gate 1), if slice_dependencies: declares parallel-safe briefs (depends_on: [], disjoint files:):
/multitask role-implementer briefs 1, 2, 3
Use Cursor's Agents Window to create a worktree per brief — one click each. The legacy scripts/wt.sh is now a deprecation stub.
See the multitask playbook for the full guardrail set.
Self-analytics
Each L2 role appends one event to .convoys/.metrics.jsonl via scripts/log-convoy-event.sh. The file is gitignored by default — events stay local. To opt-in to commit team-shared metrics, remove .convoys/.metrics.jsonl from .gitignore.
Aggregate across repos and render a dashboard with the agent-pipeline analytics scripts:
cd ~/code/agent-pipeline/analytics
npx tsx analyze-convoys.ts <repo-path> [<repo-path>...]
npx tsx render-dashboard.ts
open ~/agent-pipeline-data/dashboard.html
Schema: analytics/schemas/convoy-event.json.