feat: smart file resolution for plannotator annotate#237
Merged
backnotprop merged 2 commits intobacknotprop:mainfrom Mar 7, 2026
Merged
feat: smart file resolution for plannotator annotate#237backnotprop merged 2 commits intobacknotprop:mainfrom
backnotprop merged 2 commits intobacknotprop:mainfrom
Conversation
Add case-insensitive file resolution so users can open markdown files without typing exact paths. Applies to both the CLI (`plannotator annotate`) and the `/api/doc` endpoint for linked documents. Resolution strategies (tried in order): 1. Exact path — absolute or relative to cwd (existing behavior) 2. Case-insensitive relative path — `docs/setup.md` matches `docs/SETUP.md` 3. Bare filename search — `setup.md` searches the entire project tree Ambiguity handling: - 1 match → opens the file, prints "Resolved: /full/path" - 0 matches → "File not found: <input>" - 2+ matches → "Ambiguous filename: found N matches" with full paths Skips node_modules, .git, dist, build, .next, __pycache__, .obsidian, .trash during search. Restricts results to .md/.mdx/.markdown files and enforces project root boundary (no path traversal). Extracted shared resolveMarkdownFile() into packages/server/resolve-file.ts and refactored /api/doc handler to use it, removing ~40 lines of inline resolution logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Owner
Code reviewFound 1 issue:
plannotator/apps/hook/server/index.ts Lines 120 to 123 in a29ab58 The fix from #233 that this reverts: plannotator/apps/hook/server/index.ts Lines 121 to 140 in c762bbe Note: the PR branch also appears to be based on a pre-#233 version of 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
…ry and extension mismatch - Resolve merge conflict with backnotprop#233: keep @ prefix stripping and PLANNOTATOR_CWD support before calling resolveMarkdownFile() - Fix dead ternary in resolve-file.ts: bare filenames glob **/name, relative paths with dirs glob the pattern directly - Align extension regex with rest of codebase (.md/.mdx only, not .markdown) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dgrissen2
added a commit
to dgrissen2/plannotator_ext
that referenced
this pull request
Mar 9, 2026
…esolution Add capture-phase paste listener to AttachmentsButton so users can Cmd+V / Ctrl+V images directly into per-annotation attachments when the popover is open. Uses stopPropagation to prevent the global paste handler in App.tsx from also processing the event. Adds a platform-aware keyboard shortcut hint in the drop zone. Also fixes a regression from backnotprop#237 where resolveMarkdownFile rejected absolute paths outside the project root. The original behavior allowed any absolute path the user explicitly provided; the security boundary should only apply to relative path / bare filename search. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 tasks
backnotprop
pushed a commit
that referenced
this pull request
Mar 9, 2026
…esolution (#255) Add capture-phase paste listener to AttachmentsButton so users can Cmd+V / Ctrl+V images directly into per-annotation attachments when the popover is open. Uses stopPropagation to prevent the global paste handler in App.tsx from also processing the event. Adds a platform-aware keyboard shortcut hint in the drop zone. Also fixes a regression from #237 where resolveMarkdownFile rejected absolute paths outside the project root. The original behavior allowed any absolute path the user explicitly provided; the security boundary should only apply to relative path / bare filename search. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds case-insensitive file resolution to
/plannotator-annotateso users can open markdown files without typing exact paths or full absolute paths.Before: Only exact paths work. Typo in casing or forgetting the full path →
File not found.After: Three resolution strategies, tried in order:
docs/guides/SETUP.mddocs/guides/setup.mddocs/guides/SETUP.mdunique-file.mdAmbiguity handling
If a bare filename matches multiple files, the command errors with the full list so the user can pick the right one:
Ignored directories
Search skips:
node_modules/,.git/,dist/,build/,.next/,__pycache__/,.obsidian/,.trash/Security
.md,.mdx, and.markdownfiles are matchedImplementation
Extracted a shared
resolveMarkdownFile(input, projectRoot)function intopackages/server/resolve-file.ts. This is now used by:plannotator annotateCLI (apps/hook/server/index.ts) — printsResolved: /pathon success, error with match list on ambiguity/api/docendpoint (packages/server/reference-handlers.ts) — refactored to use the shared resolver, removing ~40 lines of inline resolution logicapps/opencode-plugin/index.ts) — same smart resolution for OpenCode usersFiles changed
packages/server/resolve-file.tsresolveMarkdownFile()functionpackages/server/package.json./resolve-fileexportpackages/server/reference-handlers.tshandleDoc()to use shared resolverapps/hook/server/index.tsapps/opencode-plugin/index.tsTesting
Tested locally with the following scenarios:
docs/guides/SETUP.md) → opens correctlydocs/guides/setup.md) → resolves toSETUP.mdunique-file.md) → finds and opens the single matchSETUP.mdexisting in two directories) → errors with both paths listednonexistent.md) → clean error message🤖 Generated with Claude Code