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
# 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:
# 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:
- "!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 shep's written Rust style, docs/idiomatic-rust.md in
the shep repository, rules IR-1 through IR-46. That file is NOT in this
repository, so the load-bearing rules 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: >-
This file is the security surface of the crate and has 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"