Skip to content

docs(multi-agent): symlinked vendor loads the sibling worktree's src - #89

Merged
CybotTM merged 2 commits into
mainfrom
feat/retro-vendor-symlink-hazard
Aug 5, 2026
Merged

docs(multi-agent): symlinked vendor loads the sibling worktree's src#89
CybotTM merged 2 commits into
mainfrom
feat/retro-vendor-symlink-hazard

Conversation

@CybotTM

@CybotTM CybotTM commented Aug 5, 2026

Copy link
Copy Markdown
Member

Came from /retro: yes

Adds Hazard 8 to multi-agent-pitfalls.md.

Giving a second git worktree its own vendor/ costs a full composer install, so symlinking the sibling's looks like a free shortcut. It is not. Composer writes $baseDir = dirname(dirname(__DIR__)) into vendor/composer/autoload_psr4.php, and __DIR__ resolves through the symlink — so $baseDir points at the other worktree and every App\… class loads from that tree's src/.

Nothing errors. Tests and PHPStan run happily against code that is not being edited. In the session this came from, a correct guard was investigated as defective because the test exercising it was executing the sibling worktree's older copy — the symptom reads as a broken fix, not a broken environment, which is what makes it expensive.

The hazard adds a one-line detection (ReflectionClass::getFileName() before trusting any result in a fresh worktree), and ranks the three setups: real composer install per worktree, cp -al hardlinks (cheap, and $baseDir stays local because vendor/ is a real directory), symlink only where nothing is executed. Plus one line in the briefing template.

Sibling of the existing Hazard 4 — that one is the wrong dependency version after a rebase, this one the wrong source tree. Hazard 2 (git checkout -- outside scope) is adjacent but a different mechanism; the general git rule for that goes to git-workflow-skill#138.

No SKILL.md change, so the 500-word budget is untouched.

Composer writes $baseDir into autoload_psr4.php by resolving __DIR__,
which follows a symlink. A worktree whose vendor/ points at a sibling
therefore autoloads that sibling's src/, silently: tests and static
analysis run green or red against code that is not being edited.

The failure presents as a broken fix rather than a broken environment,
so it costs a debugging round before anyone suspects the setup. Adds a
one-line detection via ReflectionClass::getFileName(), the hardlink
alternative that keeps $baseDir local, and a line for the briefing
template.

Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
Copilot AI lite review requested due to automatic review settings August 5, 2026 08:24
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

github-actions[bot]
github-actions Bot previously approved these changes Aug 5, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation skill labels Aug 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new documented pitfall (“Hazard 8”) to the php-modernization skill’s multi-agent guidance, warning that symlinking vendor/ across sibling git worktrees can silently cause the Composer autoloader to resolve the other worktree’s src/, leading to misleading test/static-analysis results.

Changes:

  • Document Hazard 8: how a symlinked vendor/ can make autoloading point at a sibling worktree’s source tree.
  • Provide a quick detection approach and rank safer worktree setups (separate install, hardlinks, symlink-only-when-not-executing).
  • Extend the concise multi-agent briefing template with a one-line “don’t symlink vendor/” warning + verification hint.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread skills/php-modernization/references/multi-agent-pitfalls.md Outdated
The example class read as if it existed; pasted verbatim it throws a
ReflectionException, which undermines a check meant to take one line.
Say to substitute any real class from the project's own src/ — the
probe asks where a class resolves from, so any autoloadable one
answers it — and keep the command on a single line.

Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

@CybotTM
CybotTM requested a lite review from Copilot August 5, 2026 09:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@CybotTM
CybotTM merged commit 1b915a2 into main Aug 5, 2026
22 of 23 checks passed
@CybotTM
CybotTM deleted the feat/retro-vendor-symlink-hazard branch August 5, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation skill

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants