Skip to content

v2 regression: skill discovery walks past a git worktree into the parent checkout, shadowing the worktree's own copy of a skill #39871

Closed

Description

@luisherranz

Setup. A repo has a skill at .agents/skills/<name>, and a v2 session is seated in a git worktree inside that repo (e.g. <repo>/.worktrees/<wt>), so the skill exists in both the main checkout and the worktree.

Observed. The skill record's location points at the main checkout's copy. An agent following it reads outside its session directory, raising an external_directory permission ask; in a headless/child session nobody can answer, so the read blocks indefinitely (we hit two ~15-minute stalls in an automated run). The winning copy can also be stale — the main checkout is often on a different branch than the worktree.

Mechanism (from the sources bundled with @opencode-ai/cli 0.0.0-next-15772): Config.discover (core/src/config.ts) collects .agents/.claude/.opencode directories with fs.up({ targets, start: location.directory }) — no stop boundary — so a worktree seat discovers both the worktree's .agents and the parent checkout's. SkillV2.list() (core/src/skill.ts) then merges all sources into a Map keyed by skill id — skills.set(skill.id, skill) — so the last-registered source silently wins; with nearest-first registration, the parent checkout's copy overwrites the worktree's own.

v1 comparison. v1 is not affected, on both counts: its discovery stops at the worktree boundary (packages/opencode/src/skill/index.ts @ v1.18.10: fsys.up({ targets: externalDirs, start: directory, stop: worktree })), and it logs a duplicate skill name warning on collision instead of overwriting silently.

Expected. When the same skill id is discovered from multiple sources, the source nearest the session's directory should win — the worktree's own copy — keeping reads inside the session boundary and honoring the checked-out branch's version, matching v1's boundary behavior.

Repro.

  1. In a repo with .agents/skills/demo/ (SKILL.md + a references/ file): git worktree add .worktrees/wt
  2. Run a v2 session with --dir .worktrees/wt
  3. Invoke the skill
  4. The reference read targets the parent checkout's copy and raises an external_directory permission ask

Activity

  1. opencode-agent commented on Aug 12, 2026

    @opencode-agent
    Contributor

    Addressed by #41788. Ancestor .claude and .agents skill sources are now registered farthest-to-nearest, so existing later-source precedence selects the worktree-local duplicate instead of the parent checkout copy. The exact nested-worktree regression failed before the change and passes afterward. Closing as resolved on the v2 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions