Skip to content

feat(scripts): add cousin workflow for opted-in Rust subpaths#11

Merged
sksizer merged 1 commit into
mainfrom
feat/cousin-repos
Apr 7, 2026
Merged

feat(scripts): add cousin workflow for opted-in Rust subpaths#11
sksizer merged 1 commit into
mainfrom
feat/cousin-repos

Conversation

@sksizer

@sksizer sksizer commented Apr 7, 2026

Copy link
Copy Markdown
Owner

Summary

Introduces the concept of cousin repositories — third-party projects that contain Rust code in explicitly whitelisted subpaths but are not forks of this template. Cousins have their own conventions and unrelated tooling (Bazel, custom CI, etc.), so the workflow is hyper-conservative.

Core safety principle: nothing is touched unless explicitly opted-in via `scripts/cousins.json`, and a `forbidden_paths` glob deny list acts as a belt-and-suspenders check.

Schema — `scripts/cousins.json`

```json
{
"cousins": [
{
"name": "acme-monorepo",
"url": "git@github.com:acme/monorepo.git",
"notes": "Bazel-based. CI is Bazel-managed — never touch .github.",
"targets": [
{
"path": "backend/services/auth",
"applies": ["rustfmt.toml", "clippy.toml"],
"check": "bazel test //backend/services/auth/..."
}
],
"global_applies": ["CLAUDE.md"],
"forbidden_paths": [".github/**", "Cargo.toml", "justfile"]
}
]
}
```
A `$example` key inside the JSON documents the schema inline. The shipped file has `cousins: []`.

Scripts

  • `cousin_review.sh` / `cousin_review_all.sh` — read-only. Produces a markdown report classifying every diff as SUGGEST-ADOPT, SUGGEST-NEW-FILE, KEEP-COUSIN, or NOT-APPLICABLE, with an explicit "risk to surrounding project" field per suggestion. Allowed tools: `Read Bash`. Never modifies anything.
  • `cousin_apply.sh` / `cousin_apply_all.sh` — write mode. Clones the cousin fresh into a tempdir, copies template bytes verbatim into opted-in slots only (never `Write`), runs per-target checks, reverts failed targets, opens one PR per cousin containing all surviving changes.

Per-target check resolution

For each `targets[i]` that had changes applied, in priority order:

  1. `targets[i].check` from JSON
  2. `cargo check --manifest-path targets[i].path/Cargo.toml` if a Cargo package exists there
  3. Skip checks and mark the target as "unchecked" in the PR body

Reused infra

justfile

Adds `cousin-review` (`cr`), `cousin-review-all` (`cra`), `cousin-apply` (`ca`), `cousin-apply-all` (`caa`).

Test plan

  • `just cra` / `just caa` with empty cousins array: clean "No cousins defined" exit
  • `just cr --cousin `: clear error
  • Add a real cousin and run `just cr --execute --cousin `: report only examines opted-in slots, explicitly honors forbidden_paths
  • `just ca --execute --cousin `: opens one PR against the cousin, PR diff only touches opted-in slots, per-target checks ran as configured
  • Forbidden path never appears in the PR diff even if Claude's reasoning drifts

…d-party repos

Introduces the concept of 'cousin' repositories — third-party projects
that contain Rust code in explicitly whitelisted subpaths, but are not
forks of this template. Cousins follow their own conventions and may
have unrelated tooling (Bazel, custom CI, etc.), so the workflow is
hyper-conservative: nothing is touched unless it is explicitly opted-in
in scripts/cousins.json, and a 'forbidden_paths' hard deny list acts as
a belt-and-suspenders safety net.

Schema (scripts/cousins.json):
- cousins[].name / url / notes
- cousins[].targets[].path / applies[] / check (per-crate)
- cousins[].global_applies[] (rare; repo-root files)
- cousins[].forbidden_paths[] (glob deny list)

Four new scripts:
- cousin_review.sh / cousin_review_all.sh — read-only, produce a markdown
  report classifying diffs as SUGGEST-ADOPT, SUGGEST-NEW-FILE, KEEP-COUSIN,
  or NOT-APPLICABLE. Allowed tools: Read Bash. Never modifies anything.
- cousin_apply.sh / cousin_apply_all.sh — write mode. Clones the cousin
  fresh into a tempdir, copies template bytes verbatim into opted-in slots
  only (no retyping via Write), runs per-target checks with priority
  1) targets[].check 2) 'cargo check --manifest-path <target>/Cargo.toml'
  3) skip, reverts failed targets, and opens a single PR per cousin.

Reuses scripts/lib/pr_prompt.sh for deferred PR URL prompting. A new
scripts/lib/cousins.sh helper handles jq parsing and cousin lookup.

justfile: adds cousin-review (cr), cousin-review-all (cra),
cousin-apply (ca), cousin-apply-all (caa).
@sksizer
sksizer merged commit bf91452 into main Apr 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant