backnotprop / backnotprop/plannotator
Open docs linked from a plan
- Dominant language
- TypeScript
- Stars
- 8.7k
- Forks
- 649
- Avg merge
- 11h 12m
- Merged PRs (30d)
- 109
Description
A plan often links supporting documents beside it, like `[evidence](foo-evidence.md)`. Clicking one in plan review returns 404. The link resolves against the review root, which is the working directory, while the plan itself lives in `~/.claude/plans/`.
## Cause
Claude Code's `ExitPlanMode` input carries both `plan` and `planFilePath`, and `planFilePath` is an absolute path under `~/.claude/plans/`. The file is written about a second before the hook fires and matches the inline plan exactly. `apps/hook/server/index.ts` reads only Gemini's `plan_filename` and `plan_path` and drops the Claude Code field.
## Proposal
Thread `planFilePath` into `ServerOptions`, trusted only when the file on disk holds the plan under review. The path is model-generated tool input. Without that content check an injected agent could name `~/.ssh/plan.md` and pick its own containment root.
Then let `getTrustedBaseDir` accept the attested plan directory as a `base` without promoting it to a root. Sibling documents the plan names become readable. The rest of `~/.claude/plans/` stays unreachable.
#1437 moves containment into `isPathAllowed` in `packages/shared/doc-resolve.ts`. Part of the intent there was to enable this feature by consolidating duplicate path authorization checks.
Contributor guide
Assessment
This issue has not been assessed yet.