[PF-1992] Migration orchestrator#4924
Conversation
|
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
📖 Storybook Preview 🚀 Your Storybook preview is ready: View Storybook 📍 Preview URL: This preview is updated automatically when you push changes to this PR. |
|
🗑️ Storybook preview cleaned up The preview deployment has been automatically removed since this PR was closed. |
[FX-NNNN]
Description
PF-1992 — Migration orchestrator + supporting docs
Closes the PF-1992 ticket: ships the autonomous-migration orchestrator, gate scripts, diff helpers, locked decision docs, per-component plan files, prompt pack, manifest, and reference materials for the upcoming PF-1994 / PF-2024 / PF-2025 / PF-2020-2023 batches.
TL;DR
A workflow-agnostic orchestrator that drives Claude Code subprocess invocations through a 14-step per-component loop: agent migrates source → gate (build/tsc/lint/jest/cypress/happo) → push → poll CI → classify failures → auto-fix or feed-to-agent → on green flip to
awaiting_review→ separate--review-sweepmode handles human reviews on its own cadence. Validated by 12+ canaries on Note + Form + Container + Button across the Tier 0/1 surface; per-canary cost ~$0.30-1.00 in Anthropic API.The orchestrator is single-workflow today (migration); the
Workflowinterface is built for extension to future workflows (Figma → component, bug-fix, etc.) without touching the core loop.This PR is infrastructure-only. Per-component migrations land as separate PRs against
feature/picasso-modernization(already created), driven byyarn orchestrate.Scope
bin/lib/orchestrator-core.tsbin/lib/workflow.tsbin/lib/failure-classifier.tsbin/lib/review-classifier.tscost.jsonper canary)bin/lib/token-telemetry.tsbin/migration-orchestrator.tsbin/migration-gate.shbin/migration-diff.shclassesprop compatibility shimpackages/base/Utils/src/utils/with-classes.ts+ testsdocs/migration/manifest.json+ schemadocs/migration/components/*.mddocs/migration/decisions/*.mddocs/migration/PROMPT-*.mddocs/migration/rules/*.mddocs/migration/tokens/picasso-tailwind-tokens.mddocs/migration/references/*.mddocs/migration/ORCHESTRATOR.mdTotal: ~5,400 LOC (code) + ~3,500 LOC (markdown docs). Most documentation files are templated content, not contentious code.
Reviewer guide — what to read in what order
This PR is large but has a clear priority hierarchy. Pick a slice based on your role; you don't need to read everything.
Highest value (please review thoroughly)
Engineering reviewer — focus here:
bin/lib/orchestrator-core.ts— the 14-steprun()loop,runBatch,runReviewSweep+sweepOne, Phase 3.3 CI iteration, workspace-overlay fix, per-item locks.bin/migration-gate.sh— gate stage flow + the new strict Happo REST API gate (per migration plan v4 §6.3).bin/lib/failure-classifier.ts— pure-function CI-failure classifier; 10-step heuristic decision tree.bin/lib/review-classifier.ts— pure-function review classifier with confidence scoring.packages/base/Utils/src/utils/with-classes.ts—classesprop compatibility shim (consumer-API impact across 23 downstream repos).Domain / Picasso reviewer — focus here:
docs/migration/decisions/(4 docs):backdrop-replacement.md— custom<div>+ scroll-lock (no@base-ui/reactanalog)popper-replacement.md—@floating-ui/reactdirect dependency (preserves position-anchored API)classes-shim.md— Tailwind-routing shim policy (walks back v3-era "removeclasses" plan)integration-branch.md—feature/picasso-modernizationlong-lived branchdocs/migration/components/*.md— 19 per-component plan files. Slot-keys section is canonical for the upcoming agent runs; corrections welcome.docs/migration/PROMPT-light.md+PROMPT-heavy.md— agent system prompts. Tier 0 (light) =@mui/base→@base-ui/reactpackage swap; Tier 1+ (heavy) = full rewrite.docs/migration/manifest.json— 28 component-migration units across 6 tiers per migration plan v4 §3.9.Designer — review one Tier 0 canary PR's Happo diffs once those land (intentional pixel changes from MUI v4 →
@base-ui/reactDOM cleanup are expected).Medium value (skim)
bin/lib/workflow.ts—Workflowdescriptor interface. Note: critique flagged this as premature abstraction (only 1 consumer today). Documented decision: leave as-is until 2nd workflow lands; inline post-migration if no 2nd workflow surfaces.bin/lib/orchestrator-core.ts— retry logic forgh.viewPR/gh.createPR/gh.fetchJobLog(3 similar 4-attempt exp-backoff blocks), Phase 3.3 iteration loop, token telemetry hooks,.envrcauto-load.bin/lib/token-telemetry.ts— reads Claude Code session jsonl (~/.claude/projects/<encoded-cwd>/<session-id>.jsonl), aggregates token usage, computes USD estimates at Sonnet 4.5 list pricing, writesmigration-runs/<date>/<id>/cost.json.docs/migration/rules/api-preservation.md— preservedclassesprop policy (per migration plan v4 §2.3).Lowest value (template / reference)
bin/migration-diff.sh— diff snapshot/report shell helper.docs/migration/tokens/picasso-tailwind-tokens.md— token reference (auto-generated content).docs/migration/rules/jss-to-tailwind-crib.md+styling.md— JSS → Tailwind transformation table.docs/migration/references/lessons-learned.md— auto-accumulated by the orchestrator post-each-successful-PR; will grow during PF-1994.Architecture decisions (locked, May 2026)
Per
docs/modernization/PI-4318-PF-1992-design-decisions.md+ migration plan v4. Each has a decision doc:feature/picasso-modernizationintegration branch (renamed frompicasso-modernizationto fit Picasso CI'smaster+feature/**trigger config)decisions/integration-branch.md<div>+ Tailwind + scroll-lockdecisions/backdrop-replacement.md@base-ui/react; preserves external consumer API@floating-ui/reactdirect depdecisions/popper-replacement.md@base-ui/react/popoveris trigger-anchored; would force every consumer to refactorclassesprop preserved via Tailwind-routing shimdecisions/classes-shim.mdclasses" plan; preserves ~80% of consumer usage in 23-repo portfoliobin/migration-gate.sh; design captured in migration plan v4 §6.3)bin/lib/orchestrator-core.ts)migration-runs/.locks/<id>(stale-PID detection)Validation evidence
The orchestrator is validated end-to-end by 12+ canary runs on Note (sandbox), Form, Container, and Button against
feature/picasso-modernization:migration-runs/<date>/<id>/report.json--batchmulti-component sequential[batch] [1] ... [batch] [2] ... [batch] --max-items=2 cap reached--review-sweepno-work[sweep] no items in awaiting_review state — nothing to sweepOut of scope (separate tickets)
--batchis adequate for one operator + Anthropic singleton; revisit post-migration if parallelism is needed.@toptal/picasso-codemodv53+) — feeds PF-1995.picasso@nextdist-tag publishing during Phase 2 — design decision §9.9 still open.Known critique acknowledgments (deferred refactors)
A fresh-eyes architectural review surfaced four legitimate over-engineering hotspots. Each is left as-is for this PR because none ship migration value and all are low-risk to defer:
Workflowinterface (bin/lib/workflow.ts) — premature abstraction with one consumer (migration). Inline asMigrationWorkflowpost-migration if no 2nd workflow lands.gh.*retry loops (createPR,viewPR,fetchJobLog) — collapse to awithRetry<T>helper. Cosmetic refactor; ~40 LOC saved.--with-mcpflag (Playwright integration) never validated by any canary. Documented as experimental; enable for first Tier 2/3 component.{ iteration, costUsd }per snapshot.Verification — how to test this PR locally
Prerequisites
claudesubprocess auth lives in~/.claude/).direnvwith~/Projects/.envrcexportingHAPPO_API_KEY+HAPPO_API_SECRET(or equivalent shell env). Orchestrator auto-loads from.envrcif direnv hook isn't active.Smoke tests (no API spend)
Real canary (~$0.30-0.50, ~12 min wall-clock)
# Pick a Tier 1 already-clean component and run end-to-end yarn orchestrate --component=Note --no-merge --max-iterations=5 --ci-timeout-minutes=25Watch the log for:
[loop] selected: Note (tier=1, status=queued, ...)[loop] gates pass on iteration 1[cost] iter 1: total $0.NN (in=N, out=N, cache_read=N)[loop] polling CI on https://github.com/toptal/picasso/pull/<N>After completion, check:
migration-runs/<date>/Note/cost.json— per-iter token + USD breakdownmigration-runs/<date>/Note/report.json— structured gate reportdocs/migration/manifest.json—Note.statusshould beawaiting_reviewVerification of decision docs
Each decision doc is internally consistent and matches the in-code implementation:
decisions/backdrop-replacement.md⟷ Backdrop'starget_path: 'none'in manifestdecisions/popper-replacement.md⟷ Popper's plan file incomponents/Popper.mddecisions/classes-shim.md⟷packages/base/Utils/src/utils/with-classes.tsimplementationdecisions/integration-branch.md⟷migrationWorkflow.baseBranchinbin/migration-orchestrator.tsTest plan
yarn workspace @toptal/picasso-utils build:package(compileswithClasses+ tests)yarn jest packages/base/Utils/src/utils/__tests__/with-classes.test.ts(8/8 passing)yarn typecheck(full repo)yarn eslint --ext=.ts bin/(0 errors; warnings are pre-existing or acceptable)yarn orchestrate --component=Note --dry-run(planned 14 steps print correctly)yarn orchestrate --review-sweep(no-op when noawaiting_reviewitems)decisions/*.mdand confirms each decision matches the in-code implementationNote.md) + a Tier 0 plan file (e.g.Button.md) to verify Slot keys + acceptance criteria are sensiblebin/lib/orchestrator-core.ts:run()flowFollow-ups (separate PRs after this lands)
yarn orchestrate --tier=1 --batch --no-merge.*/30 * * * * yarn orchestrate --review-sweep(or operator-driven cadence).gh.*retries, inlineWorkflow, slim telemetry.Acknowledgments
docs/modernization/PI-4318-P1-MOD-01-migration-plan.md+PI-4318-PF-1992-design-decisions.md.@base-ui/react) — the calibration baseline for Tier 0 light path.migration-runs/.Refs: PF-1992
How to test
Screenshots
Development checks
picasso-tailwind-mergerequires major update (check itsREADME.md)propsin component with documentationexamplesfor componentBreaking change
Alpha packages
Manually trigger the publish.yml workflow to publish alpha packages. Specify pull request number as a parameter (only digits, e.g.
123).PR Review Guidelines
When to approve? ✅
You are OK with merging this PR and
nit:to your comment. (ex.nit: I'd rename this variable from makeCircle to getCircle)When to request changes? ❌
You are not OK with merging this PR because
When to comment (neither ✅ nor ❌)
You want your comments to be addressed before merging this PR in cases like:
How to handle the comments?