Anthony Shew
90d · built 2026-07-24
90-day totals
- Commits
- 462
- Grow
- 38.3
- Maintenance
- 23.6
- Fixes
- 52.6
- Total ETV
- 114.5
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 6 %
- By Growth share
- Top 61 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
↑+77.0 %
vs 100 prior
↑+47.3 pp
recent vs prior
↓-18.8 pp
recent vs prior
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 7.6ETVfeat: Migrate TUI virtual terminals from vt100 to Ghostty (#13135) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ### Description Migrates Turborepo's TUI task output panes from the vendored `turborepo-vt100` crate to [Ghostty](https://ghostty.org)'s `libghostty-vt` terminal emulator. **Why Ghostty?** Ghostty's VT library is actively maintained, supports modern terminal features, and is the same engine powering the Ghostty terminal. This replaces the older in-repo vt100 implementation and removes the `tui-term` dependency. #### Architecture - **`turborepo-ghostty-sys`** — In-repo FFI against `libghostty-vt`. `build.rs` fetches a pinned Ghostty commit and compiles via Zig 0.15.2; `bindings.rs` is checked in for docs.rs. - **`turborepo-ghostty`** — Safe Rust wrappers (adapted from [libghostty-rs](https://github.com/Uzaaft/libghostty-rs)) plus Turborepo-specific `Parser` and ratatui `TerminalWidget` (adapted from [ratatui-ghostty](https://codeberg.org/jint/ratatui-ghostty)). - **`turborepo-ui`** — Task pane rendering, scroll, and selection updated to use the Ghostty-backed widget. TUI dependencies are gated behind a `tui` feature so lightweight consumers (e.g. `turborepo-telemetry`, `@turbo/repository`) don't pull in Ghostty/Zig. **Removed:** `crates/turborepo-vt100`, `tui-term` dependency. #### Notable fixes included - **Selection/copy** — Ghostty selection grid refs go stale as output streams; viewport endpoints are now persisted and refreshed before render/copy. Selected cells are highlighted during drag. - **`Send` for tokio** — Static Ghostty allocator objects are marked `Send + Sync` so the TUI `App` can be moved into `tokio::task::spawn`. - **CI / Zig** — `setup-zig` detects host arch (`aarch64` vs `x86_64`), uses the correct Windows `.zip`, and sets isolated `ZIG_GLOBAL_CACHE_DIR` to avoid stale linker failures on reused macOS runners. - **`@turbo/repository`** — Gating Ghostty behind `turborepo-ui`'s `tui` feature prevents the NAPI package from building `libghostty-vt` unnecessarily. #### Build requirements Zig 0.15.2+ is now required to build the `turbo` binary (documented in `CONTRIBUTING.md`). CI installs it via `.github/actions/setup-zig`. Optional env vars for local Ghostty development: `GHOSTTY_SOURCE_DIR`, `GHOSTTY_ZIG_SYSTEM_DIR`, `TURBOREPO_GHOSTTY_SYS_OPTIMIZE`. #### Attribution Vendored code is documented in the crate READMEs. Most safe wrappers and FFI patterns come from libghostty-rs; ratatui integration from ratatui-ghostty; `Parser` and Turborepo UI glue are original. ### Testing Instructions 1. Build and run the TUI: `cargo build` then `turbo run <tasks> --ui=tui` in a monorepo with long-running tasks. 2. **Selection/copy** — Click-drag across task output; verify highlight appears and copied text is correct after more output streams in. 3. **Scroll** — Mouse wheel and keyboard scrolling through task scrollback. 4. **Stdin** — Interactive tasks that read from stdin still work in the focused pane. 5. **Resize** — Resize the terminal while the TUI is open; panes should reflow cleanly. 6. **Non-TUI paths** — `turbo run` without `--ui=tui` and `@turbo/repository` tests should work without requiring a Zig build. <!-- CURSOR_AGENT_PR_BODY_END --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Anthony Shew <anthonyshew@users.noreply.github.com>github.com-vercel-turborepo · b22d3b43 · 2026-06-25
- 4.6ETVfix: Refactor `turbo watch` (#13423) ## Summary - replace the shared raw filesystem event broadcast with scoped, demand-driven subscriptions for package changes, hashing, outputs, discovery, cookies, devtools, and daemon root monitoring - model inherited and nested Git ignores, global excludes, tracked exceptions, dynamic Git controls, and explicit ignored input/output interests - prune ordinary ignored trees from Linux inotify coverage while preserving explicit coverage, and route non-mutating backends directly after readiness - add scoped recovery for backend rescans/errors and document the watcher architecture Closes #13402 ## Validation - `cargo test -p turborepo-filewatch --lib` focused and platform-independent coverage - Linux all-feature filewatch test binary in Docker: 68/68 passed - `cargo test -p turborepo-lib package_changes_watcher::test` - `cargo clippy -p turborepo-filewatch --all-targets --all-features -- -D warnings` - `cargo clippy -p turborepo-lib -p turborepo-daemon -p turborepo-devtools --all-targets -- -D warnings` - `cargo check -p turborepo-filewatch --target x86_64-pc-windows-gnu` - original Linux reproduction with three repeated 100,000-file bursts: zero package/hash lag, one package build each, and one web-server start ## Notes Native macOS FSEvents stress was limited by local stream exhaustion after repeated test runs; focused FSEvents path/rescan tests and macOS compilation pass.github.com-vercel-turborepo · 328b99f4 · 2026-07-21
- 2.7ETVrefactor: Split process child module (#13014) ## Why The process child module mixed public process management, platform-specific handle internals, IO, shutdown semantics, and tests in one large file. Splitting those responsibilities reduces context needed to review future process changes. ## What Moves child handle internals, IO helpers, shutdown types and processing, state manager/channel logic, PTY test guard, and tests into sibling modules under `crates/turborepo-process/src/child/` while preserving the public API from `child.rs`. ## How This is intended as a mechanical refactor. Verified with `cargo fmt -p turborepo-process`, targeted child tests, `cargo test -p turborepo-process -- --test-threads=1`, `git diff --check`, and the repository pre-push hook.github.com-vercel-turborepo · 24dd7c1f · 2026-06-03
- 2.6ETVfix: Hardening for daemon IPC endpoints (#12742) - Prevent cross-user access to local daemon RPCs by moving daemon IPC into per-user paths and enforcing owner-only socket permissions. - Reject unauthorized Unix peers and validate Windows socket ownership before clients trust a daemon endpoint.github.com-vercel-turborepo · 13a9a8b1 · 2026-05-07
- 2.1ETVperf: Overhaul pnpm lockfile parsing and dependency closure computation (#13228) ## Why On large pnpm monorepos, the bulk of `turbo run` startup — the window between invocation and the first task starting — is spent parsing `pnpm-lock.yaml` and computing per-workspace transitive dependency closures. Profiling a 1191-package internal monorepo (43k tracked files, 5.4MB lockfile) showed the closure walk dominated by string allocation, hashing, and map probes rather than actual resolution work, and YAML parsing spending ~75% of its time inside a general-purpose scanner that pnpm's rigid machine-generated output doesn't need. ## What This PR has grown into the full pnpm startup overhaul: five stacked changes, each merged into this branch after independent review and verification. **1. Closure walk interning + FxHash.** Resolved packages are interned to dense `u32` ids behind the existing caches: resolve-cache hits become a refcount bump instead of cloning two `String`s per closure edge, visited sets hash a `u32` instead of two heap strings, and the deps cache is keyed by id. Cache maps use FxHash — lockfile content is developer tooling input, not a hash-flooding vector. **2. pnpm hash index** (#13229). The post-parse `dependency_index` becomes an `FxHashMap` carrying membership flags and versions, making `has_package`/`package_version`/`all_dependencies` O(1) probes instead of `BTreeMap` walks over long keys. Entry dependency maps stay `BTreeMap` so closure iteration order remains deterministic. Also fixes `subgraph()` returning pruned lockfiles with an empty index. **3. Fast pnpm parse on saphyr events** (#13230). An event-driven parser (pure Rust, ~2x libyaml scanner throughput) builds `PnpmLockfile` without serde on the hot path. Deliberately conservative: multi-document input, anchors/aliases, tags, duplicate keys, and exotic numeric forms bail to the unchanged serde path. Observable serde quirks (untagged variant order, `lockfileVersion` float formatting, plain-scalar typing, unknown-field dropping) are mirrored exactly and enforced differentially. **4. Structural line scanner** (#13238). pnpm-lock.yaml is line-oriented machine-generated YAML, so a `memchr`-driven scanner specialized to exactly that subset replaces the general YAML state machine as tier 1, emitting the same event stream the semantic layer from (3) consumes — quirk handling is shared, not duplicated. Tier order: scanner → saphyr → serde; the scanner also declines anything a general parser would *reject*, so it can never fabricate a lockfile from invalid input. Roughly halves parse time again on every corpus measured. **5. Shared bitset closure DP** (#13239). Closures were recomputed per workspace, so shared dependencies were re-walked once per workspace reaching them. When the lockfile can prove every transitive edge resolves identically across workspaces (pnpm importers can shadow transitive resolution, so this is proven per edge via importer equivalence classes, not assumed), closures are computed once globally: iterative Tarjan SCC condensation, then a bottom-up bitset DP where set unions are word-parallel `u64` ORs, processed in bounded-memory chunks. Any sensitive edge, non-pnpm lockfile, or single-workspace call falls back to the unchanged legacy walk. ## Results Interleaved A/B against current `main`, 4-core Linux, telemetry disabled, on the 1191-package monorepo. Time-to-first-task is measured in-process (invocation to first task dispatch in the chrome profile). | Benchmark | main | this PR | delta | |---|---|---|---| | time-to-first-task (real run) | 1117ms | 472ms | **−58%** | | `turbo run build --dry=json` end-to-end | 1481ms | 871ms | **−41%** | | lockfile parse (5.4MB, `from_bytes`) | ~285ms | 56ms | **−80%** | | peak RSS (dry) | — | −27MB vs branch base | bitsets beat per-workspace set churn | Parse deltas hold on public corpora too: next.js lockfile (1.29MB) 30.9→15.0ms, this repo's (707KB) 15.3→8.0ms for the scanner tier alone. ## How to verify - Full `--dry=json` output diffed against current main on the internal benchmark monorepo and this repo — byte-identical modulo run id and version string. - 20 differential parse tests assert scanner == saphyr == serde (`Eq`-identical lockfiles, byte-identical `encode()` round-trips) across v5/v6/v9 fixtures, folded/literal block scalars with chomping/blank-line edges, quoting, flow collections, catalogs, patches, and this repo's own `pnpm-lock.yaml` — with scanner acceptance *required* on mainline shapes so regressions can't silently fall through to slower tiers. Each unsupported construct has explicit fallback coverage. - The closure DP is differentially tested against the legacy walk (an independent oracle — the single-workspace entry point never uses the DP), including a crafted divergent-edge fixture proving the fallback triggers. 220 crate tests pass.github.com-vercel-turborepo · 669676d2 · 2026-07-04
- 1.8ETVfix: Prevent cache archive symlink reads (#12813) ## Summary - Prevent cache archive creation from reading through symlink/reparse-point races before archiving task outputs. - On Unix, resolve archive inputs with fd-relative traversal so symlinked parent directories and final-component symlink swaps are rejected before reads. - On Windows, open final files with reparse-point no-follow behavior and verify the opened handle still resolves under the cache anchor before reading. Linear: TURBO-5574github.com-vercel-turborepo · ab90c81e · 2026-05-16
- 1.8ETVrefactor: Split CLI module (#13013) ## Why The CLI module had grown large enough to make command parsing and execution flow hard to review in one file. Splitting type definitions and tests away from the runtime flow keeps the entrypoint focused. ## What Moves clap argument and command type definitions into `cli/args.rs`, moves CLI tests into `cli/test.rs`, and leaves `cli/mod.rs` focused on command resolution, telemetry/version setup, and execution. ## How This is intended as a mechanical refactor. Verified with `cargo fmt -p turborepo-lib`, `cargo check -p turborepo-lib`, `cargo test -p turborepo-lib cli::test`, `cargo test -p turborepo-lib`, `git diff --check`, and the repository pre-push hook.github.com-vercel-turborepo · 7bd88416 · 2026-06-03
- 1.7ETVfeat: Add deferred hashing for task inputs (#13125) ## Why Some task inputs are not reliable when `turbo` starts. Generated code, generated CSS, API types, and other materialized files may be missing or stale until an upstream task runs, which can produce a cache key that does not represent the files the task actually consumes. Deferred hashing gives power users a way to finalize a task hash after its dependencies complete. Simple examples: Hashes normal package inputs at startup, using defaults while excluding `dist`: ```json { "inputs": [ { "mode": "startup", "withDefaults": true, "globs": ["!dist/**"] } ] } ``` Waits for `codegen`, then hashes generated files before checking cache: ```json { "dependsOn": ["codegen"], "inputs": [ { "mode": "startup", "withDefaults": true, "globs": ["!src/generated/**"] }, { "mode": "jit", "globs": ["src/generated/**"] } ] } ``` Hashes declared outputs from the selected `codegen` task after it runs, without also hashing generated files at startup: ```json { "dependsOn": ["codegen"], "inputs": [ { "mode": "startup", "withDefaults": true, "globs": ["!src/generated/**"] }, { "mode": "dependencyOutputs", "from": ["codegen"], "globs": ["src/generated/**"] } ] } ``` ## What Adds deferred hashing support through `startup`, `jit`, and `dependencyOutputs` input modes, including validation, hashing, dry-run summaries, schema/bindings, architecture docs, user-facing docs, and regression coverage. ## How Ton of test coverage added, and did a lot of manual testing.github.com-vercel-turborepo · 4ebb50ff · 2026-06-23
- 1.6ETVfix: Disable unresolved Cargo artifact caching (#13362) ## Why Cargo artifact caching must fail closed when task outputs depend on layout inputs Turborepo cannot safely resolve. Otherwise, cache restores can reuse or omit the wrong artifacts. This is stack 2/4 and depends on #13360. ## What Unsupported Cargo arguments, manifests, configuration, compiler overrides, and paths that escape the workspace now disable inferred artifact caching. Supported default and profile-only builds retain wildcard output discovery. ## How Validated the repository, engine, and library test suites; all 24 Cargo workspace end-to-end tests; `cargo lint`; `cargo fmt --check`; and `git diff --check`. Reviewers can focus on fail-closed classification in `cargo.rs` and the hermetic cases in `cargo_workspace_test.rs`.github.com-vercel-turborepo · d76aa276 · 2026-07-13
- 1.4ETVfeat: Toggle between the TUI and streamed logs (#13203) ## Why The TUI's alternate screen is great for watching many tasks, but it takes away things developers rely on from plain streamed output: native terminal scrollback, text selection, and a persistent log trail. Today you must choose one mode for the whole run. This PR lets you switch between them freely, mid-run, without losing any output. ## What Within a single `turbo run` / `turbo watch`: - **`s`** leaves the alternate screen and streams **all tasks'** logs with the usual per-task colored prefixes. Pressing `s` again returns to the TUI. - **`h`** leaves the alternate screen and streams **only the selected task's** logs, verbatim — no prefixes, exactly as the TUI pane renders them. Pressing `h` again returns. - The sidebar toggle moves from `h` to `Shift+H`. - On every switch to streaming, the output produced while the TUI owned the screen is backfilled first, so the stream shows the full history — repeated toggles only replay what's new (per-task byte watermarks). - Returning to the TUI restores the complete view: the ratatui terminal and full per-task scrollback survive stream excursions. - A grey banner line (respects `--no-color`) marks each switch and tells you which key returns to the TUI. ## How - The render loop tracks an explicit display state (`Inactive` / `Tui` / `Streaming`); startup/cleanup are split into reusable `enable_input` / `enter_alt_screen` / `leave_alt_screen` / `final_cleanup` helpers. - Raw mode is enabled once and stays on for the whole run, decoupled from the alternate screen, so the toggle hotkey is always catchable. Mouse capture is dropped while streaming so native scrollback/selection works. The panic handler restores raw mode even when the alternate screen is not active. - `TerminalSink` gains a raw-mode flag (normalizes lone `\n` to `\r\n` to avoid staircased output) and a single-task stream filter. Task output routes through a `StreamDisposition` (`Suppress` / `Verbatim` / `Prefixed`): the selected task's bytes are written raw, other tasks are dropped, no filter means the normal prefixed path. The TUI holds an `Arc<TerminalSink>` (threaded through `start_ui`) to flip the sink on toggle. - End-of-run task failures are now emitted with `Source::task(id)` and a cause-only message, instead of a run-level source with the task id baked into the string. This lets the single-task filter drop other tasks' errors and renders consistently with existing task-scoped warnings (`task: ERROR ...`). ## Testing Unit tests cover the key bindings, replay watermark logic, and stream disposition. To try it manually: 1. Build `turbo` from this branch and run several persistent/long tasks with the TUI enabled. 2. Press `s` — the alt screen closes and all tasks stream with prefixes, including everything printed before the switch. Scrollback/selection work natively. 3. Press `s` to return — the TUI comes back with full scrollback intact. 4. Select a task, press `h` — only that task's logs stream, verbatim, no prefixes. Fail a *different* task and confirm its error does not leak into this view. 5. Toggle repeatedly and confirm no duplicated log history. --------- Co-authored-by: Claude <noreply@anthropic.com>github.com-vercel-turborepo · 13254551 · 2026-07-02
- 1.4ETVperf: Compute transitive closures and external dependency hashes concurrently with run setup (#13250) ## Why Transitive closure computation sat on the critical path of every `turbo run`, even though its results are only consumed by task hashing and change detection — well after graph construction. Worse, task hashing paid for closures twice more after that: materialization cloned two `String`s per closure member per workspace into `HashSet`s, and `hash_scope` re-sorted and capnp-hashed every workspace's closure. On a 1191-package monorepo this held back time-to-first-task by roughly 100ms and contended for cores with file hashing. ## What Two stacked changes (second was #13253, merged into this branch): **Deferred closures.** `PackageGraphBuilder::defer_transitive_closures` moves closure computation to a background thread so microfrontends config, turbo.json preloading, and engine construction overlap with it. `PackageGraph::ensure_transitive_closures` joins (idempotent); `RunBuilder` joins before package filtering only when `--affected` or a git-range `--filter` may read closures, and unconditionally before constructing `Run`. Only `RunBuilder` opts in; other consumers keep inline behavior. `PackageGraph.lockfile` becomes `Arc<dyn Lockfile>` so the thread can share it. **Hash where closures are computed.** Closures leave the lockfile layer as `Vec<Arc<Package>>` sorted by `(key, version)` (`Package`'s derived `Ord`, identical to the old sort comparator); the closure DP emits sorted rows via a one-time u32 rank permutation, eliminating per-member `String` clones at materialization. An injected closure hasher (injected because `turborepo-hash` transitively depends on `turborepo-repository`) computes each workspace's external dependency hash on the same background thread, straight from the pre-sorted rows. Task hashing, run summaries, and the root global-hash input read the precomputed `PackageInfo::external_deps_hash`, each with a linear-hash fallback for graphs built without a hasher. ## How to verify - Differential tests: deferred-vs-inline graphs must produce identical closures and hashes; the DP oracle test asserts sortedness against the legacy walk; `turborepo-task-hash` proves the linear hash of a sorted closure is byte-identical to the legacy collect-sort-hash path. - Measured on a 1191-package monorepo (interleaved A/B, 6 runs, medians): time-to-first-task 371.5ms → 266.8ms (−28%) vs main. Within `hash_scope`: `compute_external_deps_hashes` 44.4ms → 0.3ms, and the concurrent file-hash leg dropped 45ms → 15ms from reduced core contention. `--dry=json` output is byte-identical. Note: precomputing the hash as a field subsumes the run-summary recompute that #13249 avoids; if this lands, #13249 reduces to a trivial rebase or can be closed.github.com-vercel-turborepo · b305fe26 · 2026-07-06
- 1.3ETVfix: Preserve non-UTF-8 Git path boundaries (#12826) Why: - Valid Unix Git paths may contain non-UTF-8 bytes, and strict UTF-8 parsing at SCM boundaries could make unrelated packages fail to hash. - SCM parsing now keeps unsupported raw Git paths explicit, defers errors until a queried package actually includes one, and avoids falling back to manual hashing for unsupported Git paths.github.com-vercel-turborepo · 85ba4877 · 2026-05-18
- 1.2ETVfeat: Add aube package manager support (#13183) ## Why Aube can run Turborepo workspaces using existing package-manager lockfiles or aube-native lockfiles. Supporting it lets projects that use aube get correct package discovery, lockfile parsing, pruning, codemod guidance, and create-turbo scaffolding instead of being rejected as an unknown package manager. ## What - Adds aube as a package-manager identity in Rust package-manager resolution and daemon serialization. - Delegates aube lockfile behavior to the underlying lockfile format, including aube-native and pnpm-family workspace metadata. - Updates create-turbo, turbo-workspaces, turbo-utils, and turbo-codemod to recognize and use aube commands. - Adds focused Rust and JS test coverage for aube detection and package-manager mocks.github.com-vercel-turborepo · 0f780067 · 2026-06-30
- 1.1ETVfix: Enforce cache filesystem boundaries (#12743) ## Summary - Keep cache restore and storage anchored to repository/restore boundaries so symlinks and output globs cannot redirect work outside the intended tree. - Preserve supported in-repository symlink cases while rejecting outside-repo outputs and workspace packages earlier. - Document that cached outputs must resolve inside the repository root. ## Testing - `cargo test -p turborepo-cache restore_ --lib` - `cargo test -p turborepo-run-cache save_outputs_ --lib` - `cargo test -p turborepo-lib can_cache_ --lib` - `cargo test -p turbopath strip_prefix --lib` - `cargo test -p turborepo-repository symlink_workspace_discovery --lib`github.com-vercel-turborepo · a50e8637 · 2026-05-07
- 1.1ETVfix: Filter microfrontend proxy environments (#12732) - Prevent microfrontend proxy tasks from inheriting undeclared parent environment variables. - Cover both custom proxy scripts and `@vercel/microfrontends` proxy binaries with regressions for strict env filtering.github.com-vercel-turborepo · 9b28a75e · 2026-05-05
- 1.1ETVchore: Add examples maintenance agent (#13136) An agent for keeping examples up to date. Just an internal experiment, doesn't actually work yet.github.com-vercel-turborepo · 05ac7b5b · 2026-06-25
- 1.1ETVfeat: Execute Cargo crate tasks via cargo (#13261) ## Why Third functional PR of the Cargo workspace series (#13227 flag, #13235 abstraction, #13248 discovery). Crates are in the package graph but their tasks are no-ops — this PR makes them execute. Per the series design, command resolution becomes a `Toolchain` trait surface shipping with **both real implementations**: the JavaScript package.json script lookup moves behind the trait (production path, not a facade), and Cargo maps task names to cargo verbs. ## What - `Toolchain::task_command` (plain command data: program/args/cwd/serial group) and `Toolchain::task_display_command` — display derives from the same tables as execution so dry-run/summaries cannot drift from what runs - `ToolchainCommandProvider` replaces `PackageGraphCommandProvider`: one adapter for every toolchain, applying non-toolchain concerns (task env, stdin, MFE proxy decorations). MFE proxy stays its own provider - Cargo mapping: entrypoints get `build`/`run|dev` as `cargo <verb> --package=<crate>` (single token — hostile crate names cannot inject flags); the synthetic `cargo` package hosts `test`/`check`/`lint`/`doc`/`bench` at `--workspace` scope; libraries stay no-ops (Cargo builds them implicitly). Workspace-wide `build` is deliberately absent — it would duplicate entrypoint builds - Serial groups: a new `turborepo-process::Command` capability, honored by the executor — at most one command per group at a time. All cargo verbs except `run` share the `cargo` group (they serialize on Cargo's build-dir lock anyway; this removes the "Blocking waiting for file lock" noise while each cargo uses all cores). `cargo run` is exempt: dev servers outlive their build phase and would starve the group - `PackageGraph` carries the `ToolchainRegistry` so post-build consumers use the single lookup path; the builder records the resolved package manager on the JS toolchain (command resolution is synchronous) - Dry-run/summaries show `cargo build --package=<crate>` instead of `<NONEXISTENT>`; JS summaries still show script text (unchanged) ## How Flag off: JS commands are byte-identical to before — same script gate, same pm binary resolution (incl. the Windows npm.cmd workaround, which moved with the JS code), same arg separators, same MFE decorations; the full existing suite passes. Flag on, verified live on a mixed npm+Cargo fixture: `turbo build` compiles the crate closure via one cargo invocation while the JS package runs its script; `turbo test --filter=cargo` runs `cargo test --workspace`; `--dry` prints the real cargo commands. Unit coverage: JS command shape/no-op/display semantics, Cargo verb mapping incl. pass-through separator rules and serial-group exemption for `run`.github.com-vercel-turborepo · ee813491 · 2026-07-06
- 1.0ETVfeat: Select runnable task entrypoints (#13452) ## Summary - Fixes #937 - Add the `futureFlags.strictTaskEntrypointSelection` opt-in - Use command-bearing package tasks as requested entrypoints while retaining internal transit tasks - Preserve scriptless orchestration graphs and prune orchestration branches that cannot reach runnable work - Support task-level filter traversal, implicit Cargo tasks, command overrides, and proxy tasks - Update schemas, types, docs, and architecture notes ## Enable the flag ```jsonc { "$schema": "https://turborepo.dev/schema.json", "futureFlags": { "strictTaskEntrypointSelection": true }, "tasks": { "build": { "dependsOn": ["^build"] }, "test": { "dependsOn": ["build"] } } } ``` ## Behavior examples ### Requested tasks start where they can run Given `app` has a `test` script and `lib` does not: ```console $ turbo run test --dry ``` Before enabling the flag, both `app#test` and `lib#test` can be task entrypoints. With the flag enabled, only `app#test` is an entrypoint. Its configured dependencies, including scriptless transit tasks needed for ordering and hashing, remain in the graph. ### Scriptless orchestration reaches runnable work Given this configuration: ```jsonc { "tasks": { "package-checks": { "dependsOn": ["package:types"] }, "package:types": {} } } ``` If only `pkg-a` defines a `package:types` command, then: ```console $ turbo run package-checks --dry ``` retains `pkg-a#package-checks -> pkg-a#package:types` and removes package branches that cannot reach runnable work. If no package defines a command anywhere in the requested graph, the fully scriptless orchestration graph is preserved. ### Filters do not manufacture missing entrypoints If `@repo/types` has no `test` command: ```console $ turbo run test --filter=@repo/types --dry ``` selects no tasks. Explicit dependency traversal can still cross a missing requested task: ```console $ turbo run test --filter=@repo/types... --dry ``` and retain runnable dependencies reached through it. ## Testing - `cargo lint` - `cargo fmt --all -- --check` - `cargo check -p turborepo-lib -p turborepo-engine -p turbo --tests` - `cargo test -p turborepo-lib run::task_filter::tests` - `cargo test -p turbo --test task_entrypoints_test` - `cargo test -p turbo --test cargo_workspace_test cargo_verification` - `pnpm --filter @turbo/types verify-schema` - local-binary dry runs for `test`, `package-checks`, `package:types`, `topo`, `quality`, and filtered mixed-task runsgithub.com-vercel-turborepo · 0a9cb5b0 · 2026-07-23
- 1.0ETVrefactor: Use upstream libghostty-vt crates instead of vendored bindings (#13205) ## Summary Switches Turborepo's Ghostty integration from vendored `turborepo-ghostty-sys` bindings to the upstream [`libghostty-vt`](https://crates.io/crates/libghostty-vt) / [`libghostty-vt-sys`](https://crates.io/crates/libghostty-vt-sys) crates, with a local patch for Windows MSVC static linking. ## Changes - Remove `crates/turborepo-ghostty-sys/` and ~10k lines of vendored FFI wrappers - Slim `turborepo-ghostty` down to Turborepo-specific glue (`Parser`, `TerminalWidget`, style conversion) - Add `[patch.crates-io]` for `libghostty-vt-sys` with MSVC `ghostty-vt-static` linking fix - **CI fix:** run the TUI on a dedicated OS thread — upstream Ghostty terminal types are `!Send`, so `tokio::task::spawn` no longer compiles ## Windows static linking Upstream `libghostty-vt-sys` 0.2.0 links `static=ghostty-vt`, which on MSVC resolves to the DLL import library. The patched crate links `ghostty-vt-static` instead, matching the prior `turborepo-ghostty-sys` fix (#13171). ## Notes - Zig is still required at build time (`libghostty-vt-sys` runs `zig build` against Ghostty sources) - Once upstream merges the MSVC static-link fix, we can drop the local `crates/libghostty-vt-sys/` patch --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Anthony Shew <anthonyshew@users.noreply.github.com>github.com-vercel-turborepo · c2115dc2 · 2026-07-03
- 0.9ETVfix: Remove `turborepo-filewatch`'s `expect()` usage (#12903) ## Why `turborepo-filewatch` still carried a crate-level `.expect()` allowance across production watcher paths. That hid panics in filesystem event handling, package discovery updates, and debounce/SCM coordination. Closes TURBO-5612 ## What Replaces implementation `.expect()` calls with ignored send failures, poisoned-lock recovery, malformed-path filtering, and no-op handling for missing watcher state, then narrows the crate-level lint allowance to the separate unwrap cleanup. ## How - `cargo fmt -p turborepo-filewatch` - `cargo test -p turborepo-filewatch` - `cargo clippy -p turborepo-filewatch --all-targets -- -D warnings` - Pre-push hook passed with format, check:toml, and Rust checksgithub.com-vercel-turborepo · d1dff11d · 2026-05-20