# Configuration Reference
Mr Milchick now resolves application configuration from one place:
1. compiled capabilities from Cargo features
2. an optional `mr-milchick.toml` file
3. a small env layer for secrets and config-path selection
CI review context is separate. `context/` still reads `CI_*`, `GITHUB_*`, and the review-context override vars. `config/` does not.
## Sources And Precedence
- Cargo features decide which platform connector and notification sinks exist in the binary.
- `mr-milchick.toml` is the canonical source for non-secret runtime configuration.
- TOML supports env interpolation before parsing:
- `${VAR}` for required env vars
- `${VAR:-default}` for optional env vars with a fallback
- Env is limited to:
- `MR_MILCHICK_CONFIG_PATH`
- `GITLAB_TOKEN`
- `GITHUB_TOKEN`
- `MR_MILCHICK_SLACK_BOT_TOKEN`
- `MR_MILCHICK_SLACK_WEBHOOK_URL`
- Removed env-driven runtime config is rejected with an error. That includes the old reviewer, CODEOWNERS, dry-run, Slack, LLM, and `MR_MILCHICK_FLAVOR_PATH` variables.
## Default File
- Default path: `mr-milchick.toml`
- Override path: `MR_MILCHICK_CONFIG_PATH`
If the file is missing, Milchick uses defaults:
- platform kind: compiled platform
- platform base URL: GitLab `https://gitlab.com/api/v4`, GitHub `https://api.github.com`
- notification policy: `always`
- dry run: `false`
- reviewers: empty list, `max_reviewers = 2`
- CODEOWNERS: enabled with auto-discovery
- inference: disabled
- Slack sinks: disabled
- templates: built-in defaults
## TOML Interpolation
Mr Milchick expands interpolation markers before it hands the file to the TOML parser.
- `${VAR}` requires `VAR` to be present and non-empty.
- `${VAR:-default}` falls back to `default` when `VAR` is missing or empty.
- Interpolation happens before TOML parsing, so scalar values can be injected directly:
- `enabled = ${MILCHICK_LLM_ENABLED:-false}`
- String values should still be quoted in TOML:
- `model_path = "${CI_PROJECT_DIR}/models/${MILCHICK_LLM_MODEL}"`
This syntax is intentionally Milchick-specific and is not part of standard TOML. Generic TOML tooling and IDE plugins may flag it even though Milchick resolves it successfully at runtime.
## Example Config
```toml
[platform]
kind = "gitlab"
base_url = "https://gitlab.com/api/v4"
[execution]
dry_run = false
notification_policy = "always"
[reviewers]
max_reviewers = 2
[[reviewers.definitions]]
username = "milchick-duty"
fallback = true
[[reviewers.definitions]]
username = "principal-reviewer"
mandatory = true
[[reviewers.definitions]]
username = "alice"
areas = ["frontend", "packages"]
[[reviewers.definitions]]
username = "carol"
areas = ["backend"]
[codeowners]
enabled = true
[inference]
enabled = ${MR_MILCHICK_LLM_ENABLED:-false}
model_path = "${CI_PROJECT_DIR}/models/review.gguf"
timeout_ms = 15000
max_patch_bytes = 32768
context_tokens = 4096
trace = false
[notifications.slack_app]
enabled = true
channel = "C0ALY38CW3X"
base_url = "https://slack.com/api"
[notifications.slack_app.user_map]
"principal-reviewer" = "U01234567"
"alice" = "U07654321"
[notifications.slack_workflow]
enabled = false
channel = "C0ALY38CW3X"
[notifications.pipeline_status]
enabled = true
search_root = "${CI_PROJECT_DIR}"
[templates.gitlab]
summary = """## {{summary_title}}
{{tone_message}}
{{findings_block}}
{{actions_block}}
_{{closing_tone_message}}_"""
```
## TOML Surface
### `[platform]`
| `kind` | No | compiled platform | Must match the compiled binary if present. |
| `base_url` | No | platform default | GitLab or GitHub API base URL. |
### `[platform.gitlab]`
| `all_pipelines_pass_label` | No | none | Adds this GitLab MR label only when parsed `milchick-status` entries exist and every entry is `Passed`. |
If `all_pipelines_pass_label` is configured but Milchick does not find any `*/milchick-status/*.json` data, Milchick emits a warning and does not plan the label action.
### `[execution]`
| `dry_run` | No | `false` | Only affects `refine`. |
| `notification_policy` | No | `always` | `always` or `on-applied-action`. |
### `[reviewers]` and `[[reviewers.definitions]]`
| `max_reviewers` | No | `2` | Caps only non-mandatory area-routed reviewers. |
| `username` | Yes | none | Reviewer username. |
| `areas` | No | `[]` | Area keys such as `frontend`, `backend`, `packages`, `devops`, `docs`, `tests`, `unknown`. |
| `fallback` | No | `false` | Marks fallback reviewer. |
| `mandatory` | No | `false` | Always prepend this reviewer when eligible. |
### `[codeowners]`
| `enabled` | No | `true` | Enables CODEOWNERS planning. |
| `path` | No | auto-discovery | Overrides lookup path. |
Auto-discovery order:
- `CODEOWNERS`
- `.github/CODEOWNERS`
- `.gitlab/CODEOWNERS`
- `.CODEOWNERS`
### `[inference]`
| `enabled` | No | `false` | Enables advisory local review. |
| `model_path` | No | none | Required when `enabled = true`. |
| `timeout_ms` | No | `15000` | Must be greater than zero. |
| `max_patch_bytes` | No | `32768` | Must be greater than zero. |
| `context_tokens` | No | `4096` | Must be greater than zero. |
| `trace` | No | `false` | Prints detailed inference output in CLI flows. |
### `[notifications.slack_app]`
| `enabled` | No | `false` | Must be `true` to activate the sink. |
| `channel` | No | none | Default Slack destination. |
| `base_url` | No | `https://slack.com/api` | Useful for tests and local mocks. |
`[notifications.slack_app.user_map]` is optional and maps GitLab or GitHub usernames to Slack user IDs.
### `[notifications.slack_workflow]`
| `enabled` | No | `false` | Must be `true` to activate the sink. |
| `channel` | No | none | Sent in workflow payloads as `mr_milchick_talks_to`. |
### `[notifications.pipeline_status]`
| `enabled` | No | `false` | Enables Slack notification enrichment from local status JSON files. |
| `search_root` | No | current working directory | Milchick recursively scans below this path for `*/milchick-status/*.json`. |
This feature is optional and primarily intended for internal CI setups that already emit job result snapshots into the workspace before Milchick runs.
It also powers the optional GitLab success-label flow under `[platform.gitlab]`. Without parsed status entries, Milchick will not attempt that label action.
Milchick accepts a tolerant JSON shape and currently looks for fields such as:
- label/name: `label`, `name`, `job`, `task`, `step`
- state: `status`, `state`, `success`, `passed`, `ok`
- detail: `summary`, `message`, `detail`, `details`, `description`
Example:
```json
{
"job": "unit_tests",
"status": "success",
"summary": "All tests passed",
"blocking": true,
"job_url": "https://gitlab.example.com/.../jobs/123",
"pipeline_url": "https://gitlab.example.com/.../pipelines/456"
}
```
Unknown extra fields are ignored. Today `blocking`, `job_url`, and `pipeline_url` are preserved in the file format but are not rendered into notifications by default.
### `[templates.*]`
Template overrides stay field-by-field and keep built-in defaults when omitted.
- `[templates.gitlab].summary`
- `[templates.github].summary`
- `[templates.slack_app].first_root`
- `[templates.slack_app].first_thread`
- `[templates.slack_app].update_root`
- `[templates.slack_app].update_thread`
- `[templates.slack_workflow].first_title`
- `[templates.slack_workflow].first_thread`
- `[templates.slack_workflow].update_title`
- `[templates.slack_workflow].update_thread`
Useful notification placeholders include:
- `pipeline_status_block`
- `pipeline_status_count`
- `pipeline_status_passed_count`
- `pipeline_status_failed_count`
- `pipeline_status_unknown_count`
Template placeholder validation still happens at render time. Invalid placeholders warn and fall back to the built-in field template.
## Supported Env Vars
### Application Config
| `MR_MILCHICK_CONFIG_PATH` | No | Alternate config file path. |
| `GITLAB_TOKEN` | GitLab live runs | GitLab API token. |
| `GITHUB_TOKEN` | GitHub live runs | GitHub API token. |
| `MR_MILCHICK_SLACK_BOT_TOKEN` | Slack app only | Slack bot token. |
| `MR_MILCHICK_SLACK_WEBHOOK_URL` | Slack workflow only | Slack Workflow webhook URL. |
### Review Context
These still belong to the CI context layer, not the app config layer:
| `CI_PROJECT_ID`, `CI_MERGE_REQUEST_IID`, `CI_PIPELINE_SOURCE`, `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME`, `CI_MERGE_REQUEST_TARGET_BRANCH_NAME`, `CI_MERGE_REQUEST_LABELS` | GitLab review context |
| `GITHUB_ACTIONS`, `GITHUB_EVENT_NAME`, `GITHUB_EVENT_PATH`, `GITHUB_REPOSITORY`, `GITHUB_HEAD_REF`, `GITHUB_BASE_REF` | GitHub review context |
| `MR_MILCHICK_PROJECT_KEY`, `MR_MILCHICK_REVIEW_ID`, `MR_MILCHICK_PIPELINE_SOURCE`, `MR_MILCHICK_SOURCE_BRANCH`, `MR_MILCHICK_TARGET_BRANCH`, `MR_MILCHICK_LABELS` | Explicit review-context overrides |
## Notes
- `observe` and `explain` are already non-mutating. `dry_run` only changes `refine`.
- Slack notifications are planned from resolved config but only sent during real `refine`.
- Config validation is strict. Unknown TOML fields fail parsing, and legacy app-config env vars fail startup.
- Platform and sink configuration must agree with compiled capabilities.