`vp run --plan`: print what a run would do, without running it

Aberta
#2,848 0 comentários 0 reações 1 responsável Ver no GitHub

Mantenedores costumam responder em até 1 dia

@wan9chi já está trabalhando nisso.

Desde 2/10/2026.

Avaliação

Dificuldade
5/5
Tempo estimado
Mais de uma semana
Facilidade para iniciantes
35/100
Tipo de issue
Funcionalidade
Clareza
Razoavelmente clara
Status de atividade
Ativa
Stack de tecnologia
rust
Domínio
cli, tooling

Direção de pesquisa

Start at the vp run CLI entry point and trace the existing selection, dependency resolution, compound splitting, ordering, and cache-status handling. Done means --plan performs the usual resolution, prints the requested text or JSON plan, exits without executing tasks, and writes no cache.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

enhancement

Summary

vp run resolves a lot before it executes anything: which packages the selection
picks, each package's task, the commands after compound splitting, the dependsOn
edges and their order, and whether a task would replay from cache. None of it can be
asked for. A --plan flag would print that resolution and exit, in text or JSON, the
way pip install --dry-run --report -, make -n, turbo run --dry=json and
bazel aquery do for their runs.

Motivation

Anything built around a task runner eventually needs to know what a run would do:

  • a pre-tool hook for coding agents that decides whether a shell command is about to
    start something expensive (a type checker, a browser suite) before letting it run;
  • CI that picks jobs from the task graph instead of from path globs;
  • a repository doctor or lint rule that checks task wiring ("does this dependsOn
    reach the task it means to?", "which packages drop out of -r for this task?");
  • a person or an agent asking "what does vp run -r test actually run, in what order?"

Today the only route is to load every vite.config.* yourself and re-implement the
selection rules, the dependsOn forms (task, pkg#task, { task, from }), compound
splitting and ordering, then keep that copy in step with Vite+. The existing surfaces
do not cover it: -v and --last-details describe a run after it ran, the interactive
selector is for a person choosing one task, and loadConfigFromFile resolves one
config with no selection, no edges and no cache status.

Prior art

  • pip install --dry-run --report -: resolve, print the JSON report, install nothing.
  • make -n / --dry-run: print the commands that would run.
  • just --dry-run, gradle --dry-run: list the recipes / tasks that would execute.
  • turbo run <task> --dry / --dry=json: per task, taskId, package, command,
    hash, inputs, outputs, dependencies, dependents, cache status.
  • bazel aquery: the actions (commands) a build would execute.
  • nx run-many -t <task> --graph=stdout: the task graph the command would execute.

Proposal

vp run --plan [--json] <the usual selection: -r | -t | -w | --filter … | [pkg#]task> [--ignore-depends-on]

Same resolution as a real run, then print and exit 0; execute nothing, write no cache.

Text output: one line per task in execution order, package task: command, with
← dep markers for edges. JSON output:

{
  "selection": { "packages": ["@acme/app", "@acme/core"], "task": "build" },
  "tasks": [
    {
      "id": "@acme/core#build",
      "package": "@acme/core",
      "task": "build",
      "commands": ["tsdown", "node scripts/emit-types.mjs"],
      "dependsOn": [],
      "cache": "replay"
    },
    {
      "id": "@acme/app#build",
      "package": "@acme/app",
      "task": "build",
      "commands": ["vp build"],
      "dependsOn": [{ "id": "@acme/core#build", "kind": "topological" }],
      "cache": "execute"
    }
  ]
}
  • commands are the sub-tasks after compound splitting (&& or array form), since
    those are what Vite Task runs and caches.
  • dependsOn entries carry kind: explicit (a dependsOn entry) or topological
    (package-graph order), because the two are what a wiring check needs to tell apart.
  • cache is replay, execute or disabled when the plan already knows it; if input
    hashing is too costly to do just to answer --plan, unknown is fine and an opt-in
    --plan=hash can come later.

Non-goals: not a visualisation (#1182 asks for that; --plan --json is an input it
could consume), and not a change to --last-details.

How we hit it

In a 128-package workspace we wrote an agent hook that needed one bit: does this
vp run … start a TypeScript compiler? Answering it faithfully meant loading all 128
configs (about 1.8 s per call) and carrying ~500 lines that re-implemented selection
and dependsOn. We replaced that with a hard-coded list of task names, which is exactly
what --plan would retire; a lint rule in the same repo reads run.tasks out of the
config AST for the same reason. Happy to test a preview against that workspace.

Related

  • #1182 (dependency graph visualisation) and #1167 (consolidated recursive output)
    need the same resolved list; --plan is its static, machine-readable form.
  • #1231 (hint when config load exceeds 500 ms) is the same gap from the timing side.
  • voidzero-dev/vite-task#738 (dependsOn object form cannot reach a task behind a
    package that lacks it) is the kind of wiring fact a plan with labelled edges shows
    directly.
Linguagem predominante
Rust
Estrelas
6.5k
Forks
297
Merge médio
20h 56min
PRs com merge (30d)
234

Preparar o ambiente

Abrir no Codespaces

Inicia o contêiner de desenvolvimento do projeto no navegador, com a sua própria conta do GitHub.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de voidzero-dev/vite-plus

Todas as issues de voidzero-dev/vite-plus

Issues semelhantes

Mais issues de Rust

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.