# Design: doc-map input for path-scoped design doc injection (Issue #137) ## Problem review-bot can inject context via `patterns-repo` (external VCS repos) and `conventions-file` (a single file from the reviewed repo). There is no mechanism to inject local repo documentation files scoped to the paths changed in a PR. First consumer: `grgl/gargoyle#778` needs a "doc adherence" reviewer that checks code against the module's governing design doc, without injecting every doc in the tree. ## Approach ### New: `doc-map` input A `.review-bot/doc-map.yml` config file in the reviewed repo maps source path globs to governing design docs. review-bot reads the map, intersects it with changed PR paths, and injects only the relevant docs into the system prompt. ### Config format ```yaml mappings: - paths: - "lib/gargoyle/engine/signal_risk/**" docs: - docs/domain/contexts/risk/risk-controls.md - paths: - "lib/gargoyle/trading/**" docs: - docs/domain/contexts/trading/ ``` - `paths` — glob patterns (including `**`) matched against changed file paths in the PR - `docs` — file paths or directory paths (all `.md` files under a directory) to inject - Docs are deduplicated across mappings ### Architecture | Component | Description | |-----------|-------------| | `review/docmap.go` | YAML parsing, glob matching with `**` support, doc loading via VCS | | `cmd/review-bot/main.go` | Step 6c: parses config, intersects with changed files, calls LoadMatchingDocs | | `budget/budget.go` | New `DesignDocs` section — injected after Conventions in system prompt | | `action.yml` | `doc-map` and `doc-map-max-bytes` inputs, wired to `DOC_MAP_FILE`/`DOC_MAP_MAX_BYTES` | ### Doc file loading - The `doc-map` YAML file is read from the local workspace (like `system-prompt-file`). - Doc files listed in the config are fetched via VCS API (same as `conventions-file`), enabling them to be loaded from any branch without a local checkout. - `GetAllFilesInPath` is tried first; if it returns files, they are treated as a directory listing. If it returns empty, `GetFileContent` is tried as a fallback (single file). ### Glob matching `**` is implemented by splitting patterns and paths on `/`, then matching segment-by-segment. A `**` segment consumes zero or more path segments (not just one level like `*`). ### Budget integration `DesignDocs` is added to `budget.Sections` between `Conventions` and `FileContext`. Trim order: Patterns → Conventions → DesignDocs → FileContext → Diff. Design docs appear in the system prompt under `## Design Documents`. ### Context size guard Default: 100 KB. Configurable via `--doc-map-max-bytes` / `DOC_MAP_MAX_BYTES`. Truncation is noted inline with a `⚠️` message. ## Error handling | Situation | Behavior | |-----------|----------| | `--doc-map` file not found | Fatal error (like `--system-prompt-file`) | | `--doc-map` file invalid YAML | Fatal error with descriptive message | | Unknown YAML keys | Log warning, continue | | Doc file not found in VCS | Log warning, skip | | Doc directory empty or no `.md` files | Log debug, skip | | Total size exceeds limit | Truncate with notice, log warning | | No changed paths match any mapping | No docs injected, review runs normally | | `paths` or `docs` list empty in a mapping | Skip that mapping |