Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,16 @@ migrate_working_dir/
CLAUDE.local.md
.sync-agents-cache.json

# Worktrees Claude Code creates for parallel sessions and isolated subagents.
# Only this subdirectory: the rest of `.claude/` is tracked, because the rules
# under it are part of the repository.
#
# They sit inside the working tree rather than beside it. `git clean -xdf` leaves them
# alone: git's nested-repository guard resolves a gitfile too, so it reports "Skipping
# repository .claude/worktrees/<slug>" and the contents survive. `git clean -xdff` does
# not skip them, and wipes a live worktree while `.git/worktrees/<slug>` survives,
# leaving a registration that `git worktree prune` then has to clear.
.claude/worktrees/

# Local sibling-package path wiring (dev only)
pubspec_overrides.yaml
30 changes: 30 additions & 0 deletions .worktreeinclude
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Gitignored files copied into every worktree Claude Code creates, for `--worktree`,
# for `EnterWorktree`, and for a subagent with `isolation: worktree`.
#
# A worktree is a fresh checkout, so `pubspec_overrides.yaml` is absent from it, and
# its absence fails silently rather than loudly: the siblings resolve from pub.dev
# instead of the working trees beside this one, `flutter pub get` succeeds, and the
# suite then passes against the PUBLISHED packages while the diff under review is of
# the local ones. An unreleased sibling API is where that bites.
#
# `.gitignore` syntax, and only files that match AND are gitignored are copied, so a
# tracked file can never be duplicated by this list.
#
# The paths inside `pubspec_overrides.yaml` have to be ABSOLUTE for this to work.
# Worktrees live under `.claude/worktrees/<slug>`, so a relative `../magic` resolves
# to `.claude/worktrees/magic`, which does not exist, and version solving fails on
# the first path dependency.
#
# One thing this layout costs, which no file here can fix because the rule lives
# upstream in artisan: `sessionOwnershipError` treats a working directory INSIDE
# `projectRoot` as owning the session (`state_file.dart:262`, `_isWithin` at `:282`),
# and a worktree now sits under the main checkout. So a `dusk:*` call from a worktree
# that has no session of its own falls back to the main checkout's app, drives THAT,
# and reports success. The old sibling layout tripped the guard instead. Run
# `artisan start` in the worktree, or pass `--state=<path>`, before any dusk command
# there.
#
# NOT processed when a WorktreeCreate hook replaces the default git logic; such a
# hook has to copy these itself.

pubspec_overrides.yaml
2 changes: 2 additions & 0 deletions doc/commands/dusk-doctor.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Compares `state.json`'s `projectRoot` against the directory the command is runni

WARN, naming both paths. Skipped when no `projectRoot` is recorded. Paths are compared after resolving symlinks, so a worktree checkout does not read as a mismatch on the same directory.

That last property cuts the other way now that worktrees live at `<repo>/.claude/worktrees/<slug>` rather than beside the checkout. A worktree is INSIDE `projectRoot`, so the check reads it as the owner and stays silent, while a `dusk:*` call from a worktree with no session of its own drives the app started from the main checkout and succeeds. The layout that used to trip this check no longer exists, so the check no longer covers the case it was written for. Start a session in the worktree, or pass `--state=<path>`.

### 7. CDP session health

Probes the `cdpPort` recorded in state for three failures. They matter together because they present as one symptom, a capture that never changes, and nothing else in the output distinguishes them:
Expand Down