Summary
`@stackbilt/blast` picks up `.claude/worktrees/agent-*/` directories when scanning, which pollutes the reverse-dependency graph with ghost copies of real source files. Most visible in the `hotFiles` output, where a single canonical file like `web/src/types.ts` appears multiple times with fractional importer counts split across the worktree clones.
Context
Claude Code (the CLI agent tool) uses git worktrees under `.claude/worktrees/agent-/` for parallel agent isolation. Each worktree is a full checkout of the repo, so from a filesystem scan's perspective there can be hundreds or thousands of ghost `.ts` files that are bit-identical copies of the canonical tree. Any project using Claude Code will have these, and they grow linearly with concurrent agent sessions.
This is the same class of exclude that `@stackbilt/blast` already handles for `node_modules/`, `.git/`, `tests/`, and `.test.`.
Reproduction
From a repo that has one or more active Claude Code worktrees:
```
$ charter --version
charter v0.10.0
$ find .claude/worktrees -name '*.ts' | wc -l
886
$ charter blast web/src/kernel/router.ts --format json | jq '.hotFiles[:5]'
[
{"file": "web/src/types.ts", "importers": 65},
{"file": ".claude/worktrees/agent-a60fd4fb/web/src/types.ts", "importers": 45},
{"file": "web/src/kernel/dispatch.ts", "importers": 45},
{"file": ".claude/worktrees/agent-a60fd4fb/web/src/kernel/dispatch.ts", "importers": 31},
{"file": ".claude/worktrees/agent-a60fd4fb/web/src/kernel/memory/index.ts", "importers": 27}
]
```
`web/src/types.ts` and its worktree ghost are counted as separate nodes. The importer counts should sum together (110 instead of being split 65/45), and the second entry shouldn't exist at all.
Observed impact
- `hotFiles` gets polluted most visibly — the top-N popularity list shows ghost duplicates
- `affected` appears unaffected for the seed I tested (router.ts yielded zero ghost entries), but this is probably because the seed's reverse-dep walk starts from canonical paths and doesn't naturally cross into worktree trees. Other seeds might behave differently.
- `fileCount` includes worktree files in the total scan budget, so large worktree trees inflate the total and may affect performance on big projects
Expected behavior
`charter blast` should exclude `.claude/worktrees/**` from graph construction by default, matching the existing exclusion posture for `node_modules/`, `.git/`, test fixtures, etc.
Suggested fix
In `@stackbilt/blast` (presumably in the graph builder's directory walk): add `.claude/worktrees` to the default ignore list alongside `node_modules`, `.git`, `dist`, `build`, `coverage`. A one-liner.
Optional enhancement: add `.charterignore` or a `blast.exclude` field in `.charter/config.json` for project-specific overrides, though that's scope creep for this fix.
Related
- charter 0.10.0 first publish of `@stackbilt/blast`
- Discovered while dogfooding `charter blast` in Stackbilt-dev/aegis after bumping the repo's `@stackbilt/cli` dep from 0.9.2 to ^0.10.0
- Downstream consumer: `scripts/taskrunner.sh` in aegis uses `charter blast --format json` as the signal source for the self-improvement blast-radius gate. Ghost-count inflation there would make the `CC_BLAST_BLOCK` (default 50-file) threshold trip incorrectly on mid-size refactors.
Summary
`@stackbilt/blast` picks up `.claude/worktrees/agent-*/` directories when scanning, which pollutes the reverse-dependency graph with ghost copies of real source files. Most visible in the `hotFiles` output, where a single canonical file like `web/src/types.ts` appears multiple times with fractional importer counts split across the worktree clones.
Context
Claude Code (the CLI agent tool) uses git worktrees under `.claude/worktrees/agent-/` for parallel agent isolation. Each worktree is a full checkout of the repo, so from a filesystem scan's perspective there can be hundreds or thousands of ghost `.ts` files that are bit-identical copies of the canonical tree. Any project using Claude Code will have these, and they grow linearly with concurrent agent sessions.
This is the same class of exclude that `@stackbilt/blast` already handles for `node_modules/`, `.git/`, `tests/`, and `.test.`.
Reproduction
From a repo that has one or more active Claude Code worktrees:
```
$ charter --version
charter v0.10.0
$ find .claude/worktrees -name '*.ts' | wc -l
886
$ charter blast web/src/kernel/router.ts --format json | jq '.hotFiles[:5]'
[
{"file": "web/src/types.ts", "importers": 65},
{"file": ".claude/worktrees/agent-a60fd4fb/web/src/types.ts", "importers": 45},
{"file": "web/src/kernel/dispatch.ts", "importers": 45},
{"file": ".claude/worktrees/agent-a60fd4fb/web/src/kernel/dispatch.ts", "importers": 31},
{"file": ".claude/worktrees/agent-a60fd4fb/web/src/kernel/memory/index.ts", "importers": 27}
]
```
`web/src/types.ts` and its worktree ghost are counted as separate nodes. The importer counts should sum together (110 instead of being split 65/45), and the second entry shouldn't exist at all.
Observed impact
Expected behavior
`charter blast` should exclude `.claude/worktrees/**` from graph construction by default, matching the existing exclusion posture for `node_modules/`, `.git/`, test fixtures, etc.
Suggested fix
In `@stackbilt/blast` (presumably in the graph builder's directory walk): add `.claude/worktrees` to the default ignore list alongside `node_modules`, `.git`, `dist`, `build`, `coverage`. A one-liner.
Optional enhancement: add `.charterignore` or a `blast.exclude` field in `.charter/config.json` for project-specific overrides, though that's scope creep for this fix.
Related