1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# yaml-language-server: $schema=https://storage.googleapis.com/coderabbit_public_assets/schema.v2.json
#
# CodeRabbit review settings, adapted from shep's own .coderabbit.yaml. Rules
# that only make sense in a workspace with a documentation site and five crates
# are not here; what is left is the part that applies to a single-crate dog.
#
# Everything here is a deviation from a default, so a key that is absent is
# deliberate: it means the default is right.
language: en-US
# 250 characters, which is the cap. Spent on the two habits that produce
# comments nobody here will act on: rewriting prose that is deliberate, and
# repeating a lint CI already fails on.
tone_instructions: >-
Be direct and specific. Prose in this repo is hand-written in a deliberate
voice: flag factual drift, never style or wording. Do not repeat lints that
CI already enforces as a required check.
reviews:
# Assertive rather than the `chill` default. The label on this setting is
# "may feel nitpicky", which is the trade: this dog runs a build command
# taken from the repository it deploys, and swaps a live app onto the
# result. A false positive costs a dismissed comment. A missed one costs an
# operator their service, or runs someone else's code as root.
profile: assertive
auto_review:
# Off by default, and a pull request opts in by carrying the `review
# please` label. That is as close as this file can get to "review our own
# branches, not a stranger's fork": CodeRabbit's schema has nine keys
# under auto_review and not one of them knows what a fork is.
#
# What it buys, on a plan that includes one review an hour: a drive-by
# pull request no longer spends the slot the branch behind it was waiting
# for. Three arrived on 2026-09-16, within three hours of the first
# `good first issue` labels going on.
#
# What it costs: nothing is reviewed until someone labels it. That is one
# click on the pull request page, and `@coderabbitai review` still works
# on any pull request regardless of this flag. It also stops any pull
# request whose description is written by a bot, release pull requests
# included, since nobody labels those.
#
# ## Why a label and not the description keyword
#
# `description_keyword` was here first and did the same job through an
# HTML comment in the body. The label replaces it, as it did in shep,
# because kelpie asks for a review by adding `review please`. Under the
# keyword, CodeRabbit answered every kelpie pull request with "automatic
# reviews are disabled" and reviewed none of them. One gate also avoids
# the question the schema leaves open, whether two positive gates OR
# together or AND.
#
# The label also reaches a fork's pull request without editing prose
# someone else wrote, which is the case this whole setting exists for.
enabled: false
# Still a second gate under `enabled: false`: a negative label stays an
# exclusion filter, it just no longer carries the job alone. Kept because
# the two mechanisms ruled out below are the two anyone would try first.
#
# release-plz opens these and merging one IS the release. The diff is a
# version bump plus a changelog section generated from commits that were
# each reviewed on their own pull request, so there is nothing here a
# human will act on.
#
# Matched on a LABEL, which release-plz attaches through `pr_labels` in
# release-plz.toml. `!release` means "review everything except a pull
# request carrying this label".
#
# Two mechanisms that look right and are not, both learned in shep:
# `ignore_usernames` fails because release-plz posts under the
# maintainer's PAT, the same account as every other pull request here. And
# `ignore_title_keywords` was tried there and did not hold: release-plz
# force-pushes its branch on every push to main, each force-push starts an
# incremental review, and the title gate is not re-evaluated on those. A
# label is checked per review, so it survives the force-push.
#
# The label has to EXIST in the repository or release-plz opens the pull
# request unlabelled. Created here on 2026-08-28. Renaming or deleting it
# silently un-skips every release pull request, because this file matches
# the name and nothing checks the two still agree.
labels:
- "review please"
- "!release"
path_filters:
- "!Cargo.lock"
# Half generated by release-plz, half hand-written. Neither half wants a
# review comment.
- "!**/CHANGELOG.md"
path_instructions:
- path: "src/**/*.rs"
instructions: >-
This crate follows the shep-pm/rust-house-style repository's written
Rust style, rules IR-1 through IR-48. Those rules are NOT in this
repository, so the load-bearing ones are restated here rather than
cited: no panicking constructor; `core::error::Error`, never
`std::error::Error`; every fallible public function carries a `# Errors`
section; a `# Panics` section requires `#[track_caller]`; every new
public item needs documentation and a deliberate `Debug` decision,
redacted for anything carrying environment or secrets and proven by an
exact-string test.
`#![forbid(unsafe_code)]` holds at src/main.rs. That is why users are
resolved by shelling out to `id` rather than calling `getpwnam`, and why
`O_NOFOLLOW` is spelled as a numeric constant per platform.
Do not suggest widening an input grammar past what the code refuses. A
refusal here is usually deliberate and says so in its own error: a
top-level `[build]` block, an artifact path that leaves the release, a
`retention` below 2.
- path: "src/build/**/*.rs"
instructions: >-
These files are the security surface of the crate and have had seven review
rounds. A build command comes from the repository being deployed, so
whoever can land a commit on the tracked branch chooses code that runs
on the operator's host, at the dog's own uid unless the app sets `user`.
Three bounds exist and each has a precise edge: the uid/gid drop bounds
the CHILD only, so anything the parent does afterwards on paths the
child chose is outside it; the cleared environment bounds what a build
inherits from this process; and `user` is the only one that also covers
what a build can READ.
`copy_artifact` runs in the parent at the dog's own uid. Treat any
change to its containment checks, its `O_NOFOLLOW` open, or the order
of check and use as security-critical. Past escapes were a `..` in an
artifact path, a committed `target` symlink, a `CARGO_TARGET_DIR`
pointing outside, and a symlinked parent directory.
- path: "**/*.md"
instructions: >-
Prose here is hand-written and hand-wrapped in a deliberate voice. Do
not suggest rewording, tightening, or rewrapping. Flag only factual
drift: a claim about behaviour the diff makes false, a command that no
longer exists, a sample that will not parse. A copy-pasteable sample in
README.md that has gone stale is a real finding.
Terminology is fixed by shep's docs/terminology.md, which is not in this
repository. A `sheep` is one managed process and the word is singular
only; the plural is `flock`, never "sheeps" and never bare "sheep".
`dogs` are plugin processes, this crate being one, and the daemon is
only ever "the shepherd".
- path: ".github/workflows/**"
instructions: >-
Every job needs `timeout-minutes`; GitHub's default is 360.
The two release-plz workflows hold RELEASE_PLZ_TOKEN and
CARGO_REGISTRY_TOKEN, and every action in them is pinned by commit SHA
on purpose. test.yml holds no secrets and uses moving tags. Flag a
moving tag introduced into either release workflow; do not flag the
tags in test.yml.
tools:
# CI runs clippy with `-D warnings` as a required check on every push and
# pull request. A second clippy here reports the same findings later.
clippy:
enabled: false
# No JavaScript or CSS in this repository at all.
eslint:
enabled: false
biome:
enabled: false
oxc:
enabled: false
stylelint:
enabled: false
# Unlike shep, this repository runs no `typos` check, so disabling
# LanguageTool does leave spelling unchecked by any tool. Disabled anyway:
# what it actually produces on this prose is style opinions about wording
# that is deliberate, which is the one thing tone_instructions above asks
# for less of. A misspelling here is cheaper than that noise.
languagetool:
enabled: false
markdownlint:
enabled: false
# No issue has ever been opened on this repository and the label set is
# GitHub's untouched default, so each of these spends a section of the
# walkthrough on a question with no answer.
assess_linked_issues: false
related_issues: false
suggested_labels: false
# One maintainer.
suggested_reviewers: false
knowledge_base:
code_guidelines:
# An explicit list replaces the defaults rather than adding to them, so the
# default pattern this repository actually uses is restated.
filePatterns:
- "**/CLAUDE.md"
- "**/AGENTS.md"