Multi-repo attribution

How a single AI session maps to many registered repos

A typical AI session in a monorepo or org workspace edits files across more than one registered project. PCR attributes each prompt to every repo it actually touched, so drafts surface in the right place no matter which sub-directory you opened the editor from.

How attribution is computed

  • Claude Code & VS Code Copilot: every Read / Write / Edit / Bash tool call is matched against your registered project paths. Any project whose path is a prefix of a touched file is added to the prompt's touched_project_ids.
  • Cursor: file attribution is derived from the diff-tracker (git status against each registered repo) since Cursor's session store doesn't expose structured tool calls. The set of repos that show new dirty files between two prompts is treated as the touched set for that response.

Where it shows up

  • `pcr show`: a draft surfaces in the browser from every repo it touched. Running pcr show in api/ will include drafts from sessions started in frontend/ if those sessions edited files under api/.
  • `pcr push`: each touched repo's snapshot (head SHA, branch, scoped diff) is captured and uploaded with the bundle. The dashboard shows a per-repo diff for each prompt.
  • Bundle membership: adding a draft to a bundle from one repo leaves it available to bundle from another. A draft that touched both frontend/ and backend/ can be reviewed in either project's stream.

Path canonicalization

Paths are canonicalized through symlinks before matching, so /tmp/... and /private/tmp/... are treated as the same location on macOS. Non-existent files (a tool call to a path that was about to be created) are matched against the deepest existing ancestor — the registered project still wins the attribution.

If you don't want a session attributed to a particular repo, you can pcr init --unregister that repo. PCR will still capture the session, but it won't surface in that project's stream.