Skip to content

D1019 — A repository a KB declares is bound to it

Decision. A repository a KB declares in paths.yaml repos: is bound to that KB, for every provider in workspace scope, with no workspace bind run there. sync resolves each declared key with the resolver the placeholders use (the paths: entry, the repo index by the declared remote, the declared default), merges the keys that resolve to one canonical path into one binding with the union of their KBs, and stores the list apart from .cartographer.yaml, in workspace-derived.json beside the repo index cache, recomputed by every sync. The clone is bound by path and the declared remote is the guard: another clone or worktree of the repository is not bound, and a clone whose origin differs is refused. A repos: entry opts out with bind: false. An explicit workspace bind on the same path replaces the derived binding entirely (--no-kb is the local opt-out); otherwise the deepest binding wins across explicit and derived ones. A provider in provider scope is unchanged.

A derived binding never edits a file git tracks. Where the client's instructions file is tracked, the projection writes no instructions and status/doctor say so; Claude Code gets its block in CLAUDE.local.md, owned and excluded. Probe, 2026-10-22, Claude Code 2.1.304: in a repository with a tracked CLAUDE.md, an untracked CLAUDE.local.md holding a unique token is repeated by claude -p.

Trust: paths.yaml is unsigned KB content, so a binding needs a declared remote: and a clone whose origin is non-empty and matches it; an entry without remote: binds nothing and is listed as unresolved. Without that, a default: pointing at any $HOME clone would let one edit of a KB project files into an unrelated checkout.

Why. Declaring a repository is the strongest statement a KB makes about it, yet activating the KB there took a workspace bind per provider and per repository. Binding a folder that contains the repositories is no substitute: probed on five clients, four look for project skills only up to the repository root (harnesses.md), so the repositories below a folder binding get the tools through the bridge (D737) but not the skills or agents. An explicit bind puts the instructions block inside a tracked CLAUDE.md/AGENTS.md (D193); a derived one would do it in every declared repository with no command run there, and a KB name in a tracked file of a public repository is a leak (D259).

Alternatives rejected. Binding every clone of the remote: a worktree or a second clone is another checkout the user did not choose, and the explicit bind covers it. Storing the derived list in .cartographer.yaml: that file is the user's (D169), and a list the next sync rewrites would churn it. Writing the block into a tracked file anyway: a leak by default. Skipping instructions for Claude Code too: the probe shows CLAUDE.local.md is read, so it keeps its instructions.

Consequences. On the first sync a provider already in workspace scope gains a binding, and a projection, in every local clone its KBs declare: KB authors whose repos: lists repositories they only cite add bind: false. A derivation needs the KBs' registries, so sync pulls the KBs a workspace-scoped provider receives (not only the ones its explicit bindings name) and reuses those pulls for the manifests. A KB whose pull fails leaves its providers' derived list as it was. If a repository starts tracking its instructions file after a block was written there, the earlier block stays until the next prune.