Skip to content

xtask: run per-checkout commands against the invoking worktree; fix switch-task --from - #932

Merged
cscheid merged 2 commits into
mainfrom
feature/bd-cvk7jb11-xtask-stage-doc-examples
Oct 27, 2026
Merged

cscheid merged 2 commits into
mainfrom
feature/bd-cvk7jb11-xtask-stage-doc-examples

Conversation

@cscheid

@cscheid cscheid commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Fixes bd-cvk7jb11, which turned up during bd-73lilznv (#929).

Commands that wrote to the main checkout from a worktree

create_worktree::repo_root() returns the main checkout, the parent of --git-common-dir. That is the right root for placing new worktrees, but four commands also used it to find the files they work on. Run from .worktrees/<x>/, each of them read or wrote the main checkout instead:

  • stage-doc-examples rendered the main checkout's examples/ and staged into its docs/examples/. The worktree's own q2 render docs then failed with "Declared resource …/docs/examples does not exist on disk".
  • check-noop-rebuild built the main checkout's q2.
  • gen-math-spec read and rewrote the main checkout's commands.json.
  • braid-snapshot wrote the main checkout's .braid/snapshot.jsonl.

They now use switch_task::current_worktree_root() (--show-toplevel). The capture-*, pandoc-check, render-corpus-diff and pull-extension-subtree commands already used it. repo_root() is renamed main_checkout_root() so the next caller can see what it returns. Its two remaining callers, create-worktree and render-corpus-diff's reference copy, want the main checkout on purpose.

switch-task --from <branch> branched off a stale tip

It fetched origin/<branch> but then branched off the local <branch>, while printing "after pull". The local branch is usually checked out, and stale, in another worktree; main in the main checkout is the common case. It now chooses the start point like this:

  • It uses whichever of the local branch and origin/<branch> is newer.
  • It stops if the two have diverged.
  • It passes --no-track, so the topic branch never tracks the integration branch.

.claude/rules/worktrees.md is updated to match.

Excluded crates walked up into the main checkout's workspace

cargo finds a crate's workspace by walking up parent directories. It skips, rather than stops at, a workspace that excludes the crate. In a worktree under .worktrees/, the walk therefore continues past the worktree's root Cargo.toml into the main checkout's, which doesn't list the crate. The three excluded crates without a [workspace] of their own were affected:

  • crates/wasm-qmd-parser could not be built from a worktree at all.
  • crates/pampa/fuzz and crates/tree-sitter-language-wasm-shim failed cargo metadata. This broke check_feature_sets::discovers_the_wasm_consumers_in_this_repo in every worktree.

Each now declares an empty [workspace]. That is what cargo's error message suggests and what wasm-quarto-hub-client already does for the same reason. A note at the root exclude list states the rule. Nothing changes in the main checkout or CI.

Verification

  • Run from a worktree, cargo xtask stage-doc-examples now stages into that worktree, and the main checkout stays untouched and clean.
  • 6 new tests cover the start-point choice (behind, equal, ahead, diverged, local-only and remote-only) and check that the two root helpers differ in a linked worktree.
  • cargo nextest run -p xtask passes 250/250 from a worktree; it was 249/250 before the [workspace] change.
  • From the worktree, cargo metadata succeeds for all three excluded crates and npm run build:wasm passes; hub-client builds through the shim. wasm-qmd-parser now gets past workspace lookup. Its full wasm-pack build was not run locally; CI's WASM jobs cover it.
  • cargo clippy -p xtask --all-targets -- -D warnings passes on the host and with --target x86_64-pc-windows-msvc.
  • q2 render --strict claude-notes is clean.

🤖 Generated with Claude Code

…k7jb11)

create_worktree::repo_root() resolves the *main* checkout (the parent of
--git-common-dir), which is right for placing new worktrees but wrong for
commands that work on the caller's files. Four commands used it, so from a
linked worktree they read and wrote the main checkout instead:

- stage-doc-examples rendered the main checkout's examples/ and staged into
  its docs/examples/, so the worktree's own `q2 render docs` then failed on
  the missing resource (found in bd-73lilznv);
- check-noop-rebuild built the main checkout's q2;
- gen-math-spec read and (re)wrote the main checkout's commands.json;
- braid-snapshot wrote the main checkout's .braid/snapshot.jsonl.

They now use switch_task::current_worktree_root() (--show-toplevel), as
the capture-*, pandoc-check, render-corpus-diff and pull-extension-subtree
commands already did. repo_root() is renamed main_checkout_root() so the
next caller sees what it returns; its remaining callers (create-worktree,
render-corpus-diff's reference copy) want the main checkout on purpose.

Also fix `switch-task --from <branch>`: it fetched origin/<branch> but
then branched off the *local* <branch>, which is usually checked out (and
stale) in another worktree, while claiming it had pulled. It now branches
off the newer of the two, refuses if they have diverged, and passes
--no-track so the topic branch does not track the integration branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

cargo looks for a crate's workspace by walking up the directory tree, and
skips (rather than stops at) a workspace that excludes the crate. In the
main checkout there is nothing above the repo root, so the excluded crates
end up standalone. A worktree lives inside the main checkout under
.worktrees/, so cargo walks past the worktree's root Cargo.toml into the
main checkout's, which does not list them, and fails with "current package
believes it's in a workspace when it's not". From any worktree:

- crates/wasm-qmd-parser could not be built at all;
- crates/pampa/fuzz and crates/tree-sitter-language-wasm-shim failed
  `cargo metadata`, breaking xtask's
  check_feature_sets::discovers_the_wasm_consumers_in_this_repo.

Add an empty [workspace] to each, as wasm-quarto-hub-client already has
for the same reason (and as `cargo fuzz init` generates), and note the
rule at the root `exclude` list. Nothing changes in the main checkout or
CI, where these crates were already standalone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cscheid
cscheid merged commit b2a0163 into main Oct 27, 2026
12 checks passed
@cscheid
cscheid deleted the feature/bd-cvk7jb11-xtask-stage-doc-examples branch October 27, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants