Use when syncing upstream vercel/next.js changes into this repository's next.js submodule, especially changes under the upstream turbopack/ subtree, resolving rebase conflicts, adapting local Rust crates to upstream API changes, fixing utoo-web wasm builds, updating snapshots, or committing submodule and local follow-up fixes.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Use when syncing upstream vercel/next.js changes into this repository's next.js submodule, especially changes under the upstream turbopack/ subtree, resolving rebase conflicts, adapting local Rust crates to upstream API changes, fixing utoo-web wasm builds, updating snapshots, or committing submodule and local follow-up fixes.
Utoo Upstream Sync
This skill helps sync upstream vercel/next.js changes into this repository's next.js submodule. Keep the skill in this repository, not inside the next.js submodule, because submodule changes are committed to the utooland/next.js fork and should stay as close to upstream as possible.
In this workflow, next.js is the submodule directory and may also be used locally as a remote name; turbopack/ is a subtree inside upstream vercel/next.js, not a separate upstream repository.
Repository Model
Current repository: the working tree where this skill is installed
List upstream commits after the merge base and filter for Turbopack/TurboTasks related changes.
Start with keywords such as turbo, turbopack, and task, but do not rely on keywords alone. Read commit titles and, for suspicious commits, inspect the diff or commit message to decide whether it affects turbopack/, turbo-tasks, shared Rust APIs, runtime output, wasm, or local utoo patches.
Mark risky upstream commits before rebasing. The goal is to choose rebase breakpoints where each stop is likely caused by one upstream commit or one coherent module/API change.
Risk signals:
touches high-risk areas listed below
changes public Rust APIs used by local crates/pack-*
changes generated runtime output or snapshot-sensitive behavior
changes Cargo dependencies, toolchains, wasm, or CI assumptions
overlaps known utoo patches in next.js
appears to implement behavior that an existing utoo patch already carries
Before rebasing, print the Turbopack-related upstream history and mark the selected breakpoints.
The user does not need to approve every breakpoint, but they should be able to see the plan. Include enough context to show why each breakpoint was selected.
Example format:
Turbopack-related upstream commits after <merge-base>:
[breakpoint] 0070514701 Turbopack: make available_modules an OperationVc ...
1b77dba691 Turbopack: Fix unsound IntoIterator for ReadRef<T>
[breakpoint] 5ee7005200 Turbopack: use module graph for NFT
...
Rebase in stages using the selected breakpoints, not as one large jump.
At each breakpoint:
resolve conflicts caused by that upstream commit/module change
run the smallest verification that covers the touched area
for conflicts, build failures, or snapshot failures, identify the causing upstream update, explain why it broke, propose a fix, and wait for user confirmation before editing
if an existing utoo patch is now implemented upstream, drop that patch commit only after explaining which patch is covered, which upstream commit covers it, and why the local patch is no longer needed
prefer fixes that are easy for a human to review as one feature/module adaptation
Keep utoo-specific behavior when it is intentional:
wasm guards
lightningcss fork usage
pack-core / pack-api public API behavior
utoo-web wasm build requirements
Prefer upstream semantics for shared Turbopack/TurboTasks APIs.
Make the smallest compatible local adapter change.
Verify the exact path that failed.
Commit only related files.
User Confirmation Gate
Do not silently fix these cases:
rebase conflicts
compile failures after a rebase breakpoint
snapshot test failures
CI failures that imply code or snapshot changes
dependency or lockfile conflicts
For these, first report:
which upstream commit or upstream change likely caused it
what changed upstream
why local utoo code, patches, snapshots, or CI assumptions broke
the proposed fix and why it is the right direction
any alternatives or risk if the fix is not obvious
Only edit files after the user confirms the proposed direction.
High-Risk Upstream Areas
Set rebase breakpoints or inspect carefully around commits touching:
Upstream turbopack code targets native platforms. New std calls that work on native may panic or fail to compile on wasm32-unknown-unknown. During sync, grep newly added or modified files for the APIs below and gate or replace them.
Incompatible std APIs — comprehensive list:
Category
API
Behavior on wasm32-unknown-unknown
Replacement / Workaround
Time
std::time::Instant::now()
panics at runtime (unsupported platform)
Use tokio::time::Instant from our forked tokio (which delegates to performance.now() in wasm)
Time
std::time::SystemTime::now()
panics at runtime
Use js_sys::Date::now() or forked tokio equivalent behind #[cfg]
Threads
std::thread::spawn
panics — no native thread support
Gate with #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]; use wasm_bindgen_futures or single-threaded path
Threads
std::thread::JoinHandle, std::thread::Builder
unavailable at runtime
Same as above
Threads
std::thread::available_parallelism
returns Err or 1
Provide a wasm-aware fallback
Threads
std::thread::sleep
panics
Use async sleep (tokio::time::sleep or gloo_timers)
Threads
std::thread::park / unpark
panics
Avoid; restructure to async
Sync
std::sync::Condvar
panics (requires thread parking)
Avoid on wasm; use async channels
Sync
std::sync::Barrier
panics (requires threads)
Avoid on wasm
Sync
std::sync::mpsc::channel
compiles but deadlocks in single-threaded context
Use futures::channel or tokio::sync
Sync
std::sync::OnceLock (with blocking init)
may deadlock or panic if init blocks
Use once_cell::sync::Lazy with wasm-safe init, or std::sync::LazyLock with non-blocking init
Filesystem
std::fs::* (read, write, metadata, etc.)
compile error or runtime panic
Gate with #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]; provide virtual FS or no-op
Filesystem
std::path::Path::canonicalize
panics
Avoid; use path normalization without syscalls
Networking
std::net::TcpStream, UdpSocket, TcpListener
compile error / unavailable
Gate or remove; not applicable in browser wasm
Process
std::process::Command, exit, abort
compile error or panic
Gate with #[cfg]
Environment
std::env::var, current_dir, args
panics or returns error
Gate; provide wasm-specific defaults
Environment
std::env::current_exe
panics
Gate
I/O
std::io::stdin, stdout, stderr (direct use)
stubs that return errors
Use web_sys::console for logging behind #[cfg]
Random
std::collections::HashMap (random state)
compiles, but RandomState needs getrandom
Ensure getrandom crate has "js" feature enabled, or use FxHashMap
If any match is found in code reachable from the utoo-wasm build:
Report the call site, the upstream commit that introduced it, and why it breaks wasm.
Propose one of:
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] gate with a wasm-compatible alternative
Replacement with a forked-tokio or wasm-compatible equivalent
Upstream conditional compilation if the code already has platform gates
Wait for user confirmation before editing.
Third-party crate wasm compatibility
Upstream turbopack may introduce new third-party crate dependencies. Not all crates compile or run correctly on wasm32-unknown-unknown.
Detection during sync:
# After rebasing, diff Cargo.toml files for new dependencies
git -C next.js diff <merge-base>..HEAD -- '**/Cargo.toml' | rg '^\+.*=.*\{' | rg -v '\[dev-dependencies\]'
Evaluation checklist for each newly introduced crate:
Check crate metadata: Does the crate list wasm32-unknown-unknown as a supported target? Check Cargo.toml for [target.'cfg(...)'.dependencies] gates.
Check transitive deps: Does the crate pull in known wasm-incompatible crates (ring, native-tls, openssl-sys, mio with epoll/kqueue, tokio with rt-multi-thread, rayon, etc.)?
Check for C/system deps: Does the crate use cc, cmake, pkg-config, or links = "..." in its build script? These typically fail on wasm.
Check for std::thread / std::net / std::fs: Does the crate internally use APIs from the incompatible list above?
Quick smoke test:
# Try compiling the crate alone for wasm
cargo check --target wasm32-unknown-unknown -p <crate-name>
If a new crate is wasm-incompatible:
Report the crate name, which upstream commit introduced it, and what makes it incompatible.
Propose one of:
Feature-gate the dependency: [target.'cfg(not(all(target_family = "wasm", target_os = "unknown")))'.dependencies]
Find a wasm-compatible alternative crate
Fork or patch the crate if a small fix is sufficient
Gate the consuming code path with #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
Flag for user review — do not silently add wasm-incompatible dependencies.
Known wasm-incompatible crate patterns:
Pattern
Examples
Why
System TLS / crypto
ring, native-tls, openssl-sys, rustls (with ring backend)
Identify the upstream commit/change that caused the output change.
Explain why JS/CSS/runtime output changed and whether it follows upstream semantics.
Propose either code adaptation or snapshot update, then wait for user confirmation.
Update only affected snapshots when the change is expected and confirmed.
Do not bulk-update snapshots without explaining why the output changed.
Cargo.lock Conflicts
Do not blindly regenerate Cargo.lock.
First identify whether the conflicting side is:
upstream dependency graph
utoo fork dependency
stale stash/local lockfile
If the user does not want the stash Cargo.lock during stash pop:
git checkout --ours Cargo.lock
git add Cargo.lock
Commit Policy
Submodule
Inside next.js, commit or amend actual submodule code changes.
Commit message should mention the upstream change that required the adaptation when known.
If a utoo patch commit becomes redundant because upstream now implements equivalent behavior, it can be dropped during the rebase. Before doing so, explicitly report:
the local patch commit being dropped
the upstream commit/change that supersedes it
why the upstream implementation is equivalent or preferable
any remaining difference, if one exists
Current repository
Commit separately when possible:
submodule pointer updates
local Rust API adaptations
CI/toolchain updates
wasm configuration updates
snapshot updates
Do not include unrelated local files or generated artifacts.