Skip to content

fix(permission): worktree-relative paths fall back to directory in non-git projects#26694

Open
BennD wants to merge 1 commit into
anomalyco:devfrom
BennD:fix/permission-non-git-worktree
Open

fix(permission): worktree-relative paths fall back to directory in non-git projects#26694
BennD wants to merge 1 commit into
anomalyco:devfrom
BennD:fix/permission-non-git-worktree

Conversation

@BennD
Copy link
Copy Markdown

@BennD BennD commented May 10, 2026

Issue for this PR

Closes #24694

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Project.fromDirectory sets worktree: "/" as a sentinel for non-git projects (packages/opencode/src/project/project.ts:210). Tools then do path.relative(instance.worktree, file) to build worktree-relative permission patterns / titles / summary lines. In a non-git project that produces "home/u/proj/src/foo.ts" (the absolute path with the leading / stripped) instead of "src/foo.ts", so a config rule like "src/*" silently never matches and titles read as the absolute path.

This PR adds workspaceRoot(ctx) next to containsPath in src/project/instance-context.ts. It returns ctx.directory when ctx.worktree === "/", otherwise ctx.worktree — i.e. the same sentinel containsPath already inverts. All call sites that compute worktree-relative strings switch to path.relative(workspaceRoot(instance), …):

  • tool/read.ts (permission pattern + title)
  • tool/edit.ts (two permission asks + title)
  • tool/write.ts (permission ask + title)
  • tool/apply_patch.ts (permission ask + per-file relativePath + summary lines + LSP diagnostic header)
  • tool/lsp.ts (title display)
  • reference/reference.ts referencePath (same inline ternary; helper signature widened to Pick<InstanceContext, "directory" | "worktree"> so this caller's plain {directory, worktree, value} shape can use it)

Relationship to #18761

#18761 proposes the same fix and the author has been keeping it actively merged with dev (latest ~5 days ago). It's currently conflicting after #26583 landed; #26583 covers the absolute→relative shift for read.ts in git projects, but the non-git fallback for the four file tools and the title/summary/relativePath call sites still needs to land.

This PR re-does the same idea on a clean baseline with a few differences:

  • Helper goes in src/project/instance-context.ts next to containsPath (both invert the same worktree === "/" sentinel) instead of src/tool/relative.ts.
  • Named workspaceRoot to avoid shadowing path.relative at every call site.
  • Tests mirror the closest existing test in each file rather than mixing legacy Instance.provide with newer provideTmpdirInstance / it.live.
  • Adds a permissions docs note.

How did you verify your code works?

  • bun typecheck from packages/opencode — clean.
  • bun test test/tool/{read,edit,write,apply_patch,lsp}.test.ts — 117/117 pass (one new non-git test per tool).
  • bun test test/permission test/tool — 369/369 pass.
  • Each new test mirrors the closest existing test in its file: read asserts on the captured permission pattern (the file's existing idiom for permission tests), edit / write / lsp assert on result.title, apply_patch asserts on result.output and metadata.files[0].relativePath (the same shape "applies add/update/delete in one patch" already uses). All sites compute their relative path through the new helper, so an assertion on any one of them exercises the fix.
  • Manually tested with a built --single binary in a non-git tmpdir; read and edit rules under src/* now deny as configured (silently passed through before).

Behavior change for users

For non-git projects:

  • Permission rules anchored to the project root (e.g. "read": { "src/*": "deny" }) now actually match — they were silently passing through to the wildcard before.
  • User-visible titles, summary lines, and LSP diagnostic headers show project-relative paths (e.g. src/foo.ts) instead of home/u/proj/src/foo.ts.

For git projects: no change — worktree was already a meaningful root.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential Duplicate Found

PR #18761: "fix(opencode): Use standard resolve function to get proper filePaths for tools"

Why they're related:

This is the original PR that addresses the same issue. According to the current PR description:

The current PR essentially supersedes or duplicates the work of #18761 with refinements, so these two PRs should be reviewed together to determine which approach should be kept.

…n-git projects

Project.fromDirectory uses worktree: "/" as a sentinel for non-git
projects. Tools compute path.relative(instance.worktree, file) for
permission patterns, titles, and summary lines, which in a non-git
project yields "home/u/proj/file.ts" instead of "file.ts" — silently
breaks rules like "src/*" and produces ugly titles.

Add workspaceRoot(ctx) next to containsPath in instance-context.ts
(both invert the same "/" sentinel) and route the four file tools and
agent.ts through it.

Closes anomalyco#24694
@BennD BennD force-pushed the fix/permission-non-git-worktree branch from 81cc9ec to faa501b Compare May 10, 2026 17:33
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.

Non-git projects use "/" as worktree, breaking permission path resolution

1 participant