From a56a73e0a1853239c6bac89c483510610c904098 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Thu, 30 Apr 2026 09:41:28 -0700 Subject: [PATCH] docs: add follow-up plans for template-inheritance gaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three plans addressing the gaps surfaced by the question of how reusable workflows propagate from this repo through `/.github` to consumer repos: 1. bulk-install-smartwatermelon-fleet — workaround for the fact that `smartwatermelon` is a user account, so workflow-templates never appear in the picker UI for `smartwatermelon/*` repos. Script-based opt-in install across the existing fleet. 2. create-nightowlstudiollc-github-defaults — stand up the org's `.github` repo so workflow-templates do work for new repos in that org, plus mirror community defaults. 3. required-workflows-nightowlstudiollc — force-enforcement via Repository Rulesets (GitHub deprecated the standalone Required Workflows feature in 2023; Rulesets are the live mechanism). Audit-only first, escalate to active. Plans cross-reference each other and call out the order/dependency between them. Smartwatermelon→org migration is explicitly out of scope per current direction. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...4-30-bulk-install-smartwatermelon-fleet.md | 115 +++++++++++ ...reate-nightowlstudiollc-github-defaults.md | 127 ++++++++++++ ...30-required-workflows-nightowlstudiollc.md | 194 ++++++++++++++++++ 3 files changed, 436 insertions(+) create mode 100644 docs/plans/2026-04-30-bulk-install-smartwatermelon-fleet.md create mode 100644 docs/plans/2026-04-30-create-nightowlstudiollc-github-defaults.md create mode 100644 docs/plans/2026-04-30-required-workflows-nightowlstudiollc.md diff --git a/docs/plans/2026-04-30-bulk-install-smartwatermelon-fleet.md b/docs/plans/2026-04-30-bulk-install-smartwatermelon-fleet.md new file mode 100644 index 0000000..403f4c0 --- /dev/null +++ b/docs/plans/2026-04-30-bulk-install-smartwatermelon-fleet.md @@ -0,0 +1,115 @@ +# Bulk-install script for existing smartwatermelon repos + +Adds a script to this repo that installs (or refreshes) the `claude-blocking-review` caller workflow across all eligible repos under the `smartwatermelon` user account. Closes the gap left by GitHub's workflow-templates feature being **organization-only** — `smartwatermelon` is a user account, so `smartwatermelon/.github/workflow-templates/` is decorative; the templates never appear in the "New workflow" picker for `smartwatermelon/*` repos. + +## Goal + +A repeatable, idempotent way to roll the current pinned version (today: `@v3.0.0`) into every `smartwatermelon/*` repo that doesn't yet have it, without per-repo manual work. + +## Non-goals + +- Installing into archived repos. +- Installing into repos listed in `.claude-review-ignore`. +- Force-overwriting an existing caller workflow that's already on the pinned version (idempotent skip). +- Touching `nightowlstudiollc/*` — that's covered by [the org defaults plan](2026-04-30-create-nightowlstudiollc-github-defaults.md) plus the [org-wide enforcement plan](2026-04-30-required-workflows-nightowlstudiollc.md) (Repository Rulesets). + +## Preconditions + +- `gh` CLI authenticated as a user with write access to all targets. +- `claude-review-audit.sh` already exists in this repo and enumerates the fleet correctly. The new script reuses its repo-discovery logic. +- A canonical caller-stub file exists somewhere we can copy from. Two options (Phase 0 chooses): + - **A:** Pull from `smartwatermelon/.github/workflow-templates/claude-blocking-review.yml` at HEAD (single source of truth — same file the workflow-template feature would have used in an org). + - **B:** Inline the stub in the script itself. + + Recommend **A** so the stub-and-the-script can't drift. + +## Phases + +### Phase 0 — Decide caller stub source and pin policy + +- Confirm the canonical stub file path (`smartwatermelon/.github/workflow-templates/claude-blocking-review.yml`). +- Confirm pin policy: specific semver from the stub (e.g. `@v3.0.0`), not floating. Matches the release-strategy convention; lets Dependabot drive future bumps. +- If the stub references a tag that doesn't have a GitHub Release yet (currently true for `v3.0.0`), publish the release first so consumers have something to reference in their UI. + +### Phase 1 — Write `bulk-install-claude-review.sh` + +Lives next to `claude-review-audit.sh` at the repo root. Modeled on the audit script's repo-discovery + ignore-list handling. + +Behavior: + +1. Discover candidate repos: all non-archived repos owned by `smartwatermelon`, minus those in `.claude-review-ignore`. +2. For each candidate, classify state: + - **MISSING** — no `claude-code-review.yml` (or any equivalent) under `.github/workflows/`. + - **STALE** — present, but pin doesn't match the current target (`@v3.0.0`). + - **CURRENT** — present and on target. Skip silently. + - **CUSTOMIZED** — present, on target, but with non-trivial caller-side modifications (e.g. `paths-ignore`, `extra_instructions`). Skip with warning; flag for human review. +3. For MISSING repos: open a PR adding `.github/workflows/claude-code-review.yml` with the canonical stub. Branch name: `claude/install-blocking-review-`. +4. For STALE repos: open a PR bumping the pin. Branch name: `claude/bump-blocking-review-to-`. +5. Report: per-repo status summary at end. + +Idempotency: re-running the script when nothing's changed should produce zero PRs and a clean report. + +Flags: + +- `--dry-run` — classify and print intended action; open no PRs. **Default**. +- `--apply` — actually open PRs. +- `--only ` — single-repo mode for testing. +- `--verbose` — verbose logging (matches audit script convention). + +PR body should: + +- Link to `github-workflows` release notes for the target version. +- Link to this plan. +- Include `[skip-claude-review: bulk-install]` in the body so the PR doesn't recursively trigger blocking review on itself before being merged. + +### Phase 2 — Bellwether + +Pick 2-3 actively-developed `smartwatermelon/*` repos (non-archived, recent commits) and run with `--apply --only `. Watch each PR through CI before continuing. + +Acceptance for moving to Phase 3: + +- Bellwether PRs CI-green. +- Caller stub renders correctly (no schema errors). +- The `claude-review / run-review` check appears on subsequent PRs in the bellwether repos. + +### Phase 3 — Fleet rollout + +Run `--apply` against the full eligible set. Expect 5-15 PRs (most repos either already have it from prior `claude-review-audit.sh`-driven manual installs, or are in `.claude-review-ignore`). + +Auto-merge: don't enable. Each install PR should land via the normal review path. If volume becomes a problem, this is where we'd consider scripted self-merge — but on a one-time rollout, manual review is fine. + +### Phase 4 — Wire up Dependabot in newly-installed repos + +Only matters for MISSING-class repos that didn't have `dependabot.yml` for `github-actions`. Defer this to a follow-up — same pattern that already shipped to existing fleet. + +Two sub-options: + +- **A:** Bundle Dependabot config into the install PR. Risk: makes the install PR more invasive. +- **B:** Separate "add github-actions Dependabot" PR after the install PR merges. + +Recommend **B** — smaller, easier to review, and identical to the pattern used in Phase 4c of the v2 rollout playbook. + +## Risks and rollback + +| Risk | Mitigation | +|---|---| +| Free-tier repos silently reject parts of the install (per [github billing tier](../../../../../../Users/andrewrich/.claude/projects/-Volumes-extra-vieille-Workspaces-github-workflows/memory/github-billing-fleet.md) — not relevant for the install itself, but Phase 4 auto-merge wouldn't work) | Don't enable auto-merge on free-tier repos; surface the limitation in the report | +| Repo has bespoke caller workflow we don't recognize | CUSTOMIZED classifier flags it; human reviews | +| Repo branch protection blocks PR merge until checks pass — and `claude-review / run-review` is a required check that can't run yet because the workflow's not installed | The install PR adds the workflow; first run is on the install PR itself. Tested in bellwether. If branch protection wedge happens, temporarily relax via gh API | +| `.github/workflows/claude-code-review.yml` filename clashes with an existing unrelated workflow | Classifier checks for *any* file referencing `smartwatermelon/github-workflows/.github/workflows/claude-blocking-review.yml@`, not just the canonical filename | + +Rollback: PR-based, so `gh pr close --delete-branch` per-PR if needed. No commits to main. + +## Acceptance criteria + +- Script lives at `bulk-install-claude-review.sh` in repo root. +- Shellcheck (`-S info`) clean, including no `# shellcheck disable` directives. +- `--dry-run` is default and produces no side effects. +- Re-running after a successful rollout produces an all-CURRENT report. +- README updated with a "Bulk install" section pointing at the new script. +- Audit script (`claude-review-audit.sh`) updated if its CURRENT-version constant moves to `@v3.0.0`. (Verify both scripts read from the same constant or comment-block to prevent drift.) + +## Open questions + +- Should the canonical stub source be the `.github` repo, or should we move it into this repo (e.g. `templates/claude-code-review.yml`) and have `.github` reference *this* repo as the source? Slight DX win — keeps everything about this tool in one repo. Decide in Phase 0. +- Do we want a parallel `bulk-uninstall` mode for emergencies (mass-remove the workflow if a v4 has a critical bug)? Probably not — the existing `[skip-claude-review]` escape hatch already lets individual PRs bypass without removal. Skip unless evidence demands it. diff --git a/docs/plans/2026-04-30-create-nightowlstudiollc-github-defaults.md b/docs/plans/2026-04-30-create-nightowlstudiollc-github-defaults.md new file mode 100644 index 0000000..3c5bd0e --- /dev/null +++ b/docs/plans/2026-04-30-create-nightowlstudiollc-github-defaults.md @@ -0,0 +1,127 @@ +# Create `nightowlstudiollc/.github` with org-level defaults + +`nightowlstudiollc` is an actual GitHub organization (team plan, 9 private repos, created 2026-01-22) — unlike `smartwatermelon`, which is a user account. This means the full `.github` community-defaults + workflow-templates feature set works, including the **workflow picker** that surfaces stub workflows in "Actions → New workflow" for every repo in the org. + +## Goal + +Stand up `nightowlstudiollc/.github` mirroring the structure of `smartwatermelon/.github`, so: + +1. New repos in the org get FUNDING.yml, profile/README.md, and dependabot config fallbacks automatically. +2. The Claude blocking review and Dependabot auto-merge templates appear in the Actions picker for every repo in the org. +3. The `claude-review-audit.sh` script (which already audits both orgs) stays accurate as templates spread. + +This addresses the "new repos automatically inherit" half of the original question for the org side. Existing repos still need bulk-install (separate plan). + +## Non-goals + +- Forcing the workflow on every repo (that's the [org-wide enforcement plan](2026-04-30-required-workflows-nightowlstudiollc.md) using Repository Rulesets — separate decision). +- Mirroring **everything** from `smartwatermelon/.github`. Only mirror what's still load-bearing — drop or refresh anything stale. + +## Preconditions + +- Org admin access to `nightowlstudiollc`. +- `CLAUDE_CODE_OAUTH_TOKEN` already provisioned at the org level, OR plan to add it during this rollout. Check before starting: `gh secret list --org nightowlstudiollc`. +- The `smartwatermelon/.github` template fix (PR currently open at `smartwatermelon/.github#7`) merged. The mirror should land at `@v3.0.0`, not stale `@v2.0.1`. + +## Phases + +### Phase 0 — Inventory and decisions + +- Enumerate what's in `smartwatermelon/.github`: + - `.github/FUNDING.yml` + - `.github/dependabot.yml` + - `.github/workflows/claude.yml` ← only applies to the .github repo itself + - `profile/README.md` + - `workflow-templates/claude-blocking-review.yml` + `.properties.json` + - `workflow-templates/dependabot-auto-merge.yml` +- Decisions to make before creating files: + - **FUNDING.yml** — does NightOwl Studio want sponsor links visible on every public repo? Probably no for an LLC. Either omit or include with appropriate links. Default: omit. + - **profile/README.md** — yes, this becomes the org landing page at . Worth investing 30min on a real page. + - **claude.yml** (the `@claude` mention handler) — yes, mirror it. Same security `if:` guard. + - **claude-blocking-review template** — yes. Same content as smartwatermelon's, pinned `@v3.0.0`. + - **dependabot-auto-merge template** — yes. Identical content; the workflow doesn't reference org-specific paths. + - **dependabot.yml in .github itself** — yes, same minimal config. + +### Phase 1 — Create the repo + +```bash +gh repo create nightowlstudiollc/.github \ + --private \ # or --public if you want the profile page indexed + --description "Organization-level defaults: workflow templates, community files" \ + --clone +``` + +Decision: **private vs public**. The org's other repos are private (9/9). `.github` repos that hold a `profile/README.md` need to be public for the profile to render publicly — but `.github` *workflow-templates* work fine in a private `.github` repo. Three sub-options: + +- **All-private**: profile README won't render publicly. Internal-only org. Reasonable if NightOwl doesn't need a public landing page. +- **All-public**: profile renders, but FUNDING/SECURITY/etc become public defaults. Fine, just be deliberate. +- **Two repos**: separate `.github-private` for workflow-templates if you want the public/private split. GitHub supports both: `.github-private` is the org-internal-only equivalent, surfaced only to org members. + +Recommend **all-public** unless there's an explicit reason not to. Match the `smartwatermelon/.github` pattern. + +### Phase 2 — Mirror files + +Copy from `smartwatermelon/.github`: + +| Source | Destination | Modifications | +|---|---|---| +| `workflow-templates/claude-blocking-review.yml` | same path | none (already at `@v3.0.0` after PR #7) | +| `workflow-templates/claude-blocking-review.properties.json` | same path | none | +| `workflow-templates/dependabot-auto-merge.yml` | same path | none | +| `.github/workflows/claude.yml` | same path | none | +| `.github/dependabot.yml` | same path | none | +| `profile/README.md` | same path | rewrite for NightOwl | +| `CLAUDE.md` | same path | rewrite for the new repo's purpose | +| `README.md` | same path | rewrite | + +Skip `.github/FUNDING.yml` unless decided otherwise in Phase 0. + +### Phase 3 — Provision org-level secret + +```bash +gh secret set CLAUDE_CODE_OAUTH_TOKEN --org nightowlstudiollc --visibility all +``` + +Without this, every workflow scaffolded from the template will fail on first run. Check `gh secret list --org nightowlstudiollc` before declaring done. + +### Phase 4 — Bellwether + +Pick one existing `nightowlstudiollc/*` repo. Use the Actions UI: New workflow → "By Night Owl Studio" section → select Claude Blocking Review. Verify: + +- Template populates with `@v3.0.0` pin. +- Commit it via the UI. +- Open a test PR. The `claude-review / run-review` check fires. +- Result is sane. + +If the template doesn't show up in the picker: check that the `.github` repo is the org's actual `.github` repo (not `nightowlstudiollc/dot-github` or similar), and that the `workflow-templates/` directory has the right structure (`*.yml` + `*.properties.json` pairs, not nested folders). + +### Phase 5 — Document and close out + +- Update this repo's README to mention NightOwl scaffolding works via the org workflow picker. +- Update `claude-review-audit.sh` if it doesn't already cover NightOwl repos. (It does — verified at script line ~30.) +- Close out: the original question's "do new repos inherit?" is now **yes for nightowlstudiollc**, **no for smartwatermelon** (and won't change without org migration). + +## Risks and rollback + +| Risk | Mitigation | +|---|---| +| Template appears in picker but secret missing → first run fails | Phase 3 explicit; verify with `gh secret list --org nightowlstudiollc` | +| Free-tier features (auto-merge, branch protection rules) silently no-op on the `.github` repo if it lands on the wrong tier | NightOwl is on `team` plan per `gh api orgs/nightowlstudiollc`; no concern. Cross-check anyway | +| `profile/README.md` placeholder gets indexed before real content lands | Land Phase 2 commits in one PR or one direct push, not piecemeal | +| Existing nightowl repos with bespoke claude-review configs collide with the new template at install time | The template only affects *new* installs. Existing repos are bulk-install territory and untouched by this plan | + +Rollback: `gh repo delete nightowlstudiollc/.github` removes everything cleanly. No fleet-wide impact since this only adds opt-in scaffolding for new workflows. + +## Acceptance criteria + +- `nightowlstudiollc/.github` exists, public, with the file inventory above. +- `CLAUDE_CODE_OAUTH_TOKEN` accessible to all org repos. +- Picker test from Phase 4 produces a working PR with green `claude-review / run-review`. +- `profile/README.md` renders at . +- README in this repo (github-workflows) mentions both org sources. + +## Open questions + +- Should NightOwl have a different `extra_instructions` block in its template (e.g. domain-specific guidance for the LLC's product code)? Probably yes eventually — leave as comment placeholder, fill in once a NightOwl repo accumulates feedback patterns. +- Public vs private profile decided in Phase 1. +- Once this lands, do we want to split `claude-config`-style automation (an `install.sh` for `.github` repos)? Probably not — two orgs is the entire fleet; manual sync is fine. diff --git a/docs/plans/2026-04-30-required-workflows-nightowlstudiollc.md b/docs/plans/2026-04-30-required-workflows-nightowlstudiollc.md new file mode 100644 index 0000000..335c8f4 --- /dev/null +++ b/docs/plans/2026-04-30-required-workflows-nightowlstudiollc.md @@ -0,0 +1,194 @@ +# Org-wide enforcement of `claude-blocking-review` on `nightowlstudiollc` via Repository Rulesets + +GitHub's "Required Workflows" feature, the obvious-sounding answer, was **deprecated and removed** — the functionality moved into **Repository Rulesets** in 2023, and the standalone Required Workflows API/UI is gone. This plan uses Rulesets, the current mechanism, to force `claude-blocking-review` to run (and optionally pass) on every PR in selected NightOwl repos. + +References: + +- [GitHub Changelog: Required Workflows moved to Rules](https://github.blog/changelog/2023-08-02-github-actions-required-workflows-will-move-to-repository-rules/) +- [REST API endpoints for organization rules](https://docs.github.com/en/rest/orgs/rules) + +## Goal + +Decide whether to enforce `claude-blocking-review` on every NightOwl repo via an org-level Repository Ruleset with a `workflows` rule, and if so, roll it out safely. + +## Background + +Three competing mechanisms for spreading a workflow across an org: + +| Mechanism | Coverage | Live updates? | Per-repo opt-out? | Status | +|---|---|---|---|---| +| `workflow-templates/` in `.github` repo | New repos via picker, opt-in only | No (one-time copy) | n/a | Live | +| Bulk-install script + `uses:` reference | Existing repos opt-in via PR | Yes (via Dependabot bumps) | Yes (delete the file) | Plan: [bulk-install](2026-04-30-bulk-install-smartwatermelon-fleet.md) | +| **Repository Ruleset with `workflows` rule** | All repos in scope, mandatory | Yes (org-config edit) | Only by admin removing the rule or granting bypass | Live (replaces deprecated Required Workflows) | + +Rulesets are org-or-repo scoped, support targeting all/selected repos, support **bypass actors** (specific users or teams), can be run in **evaluation mode** (audit-only, no enforcement) before turning on, and integrate with branch protection rather than competing with it. + +This is org-only — useful for NightOwl, irrelevant to smartwatermelon (user account; no rulesets). + +## Goal qualifiers + +How strong should the gate be? + +- **Strong** → ruleset enforced + the `claude-review / run-review` check is required. PR cannot merge without Claude pass. Trade: every PR pays review cost; depends on Claude OAuth uptime/quota. +- **Moderate** → ruleset enforced (workflow runs), but check not coupled to merge. Trade: zero blocked-merge risk, but humans can ignore the verdict. +- **Audit-only** → ruleset in **evaluation mode** for a calibration window. No enforcement; you collect data on cost, false positives, and blast radius before deciding. + +Recommend **Audit-only first**, then **Moderate**, escalating to **Strong** only after a clean window. + +## Preconditions + +- `nightowlstudiollc/.github` exists. (See [defaults plan](2026-04-30-create-nightowlstudiollc-github-defaults.md).) +- The reusable workflow being enforced is reachable from NightOwl repos. Two sub-options: + - **A:** Reference `smartwatermelon/github-workflows` directly. Cross-org reference works only if that repo is **public** (it is today). + - **B:** Mirror the reusable workflow into a NightOwl-owned repo (e.g. `nightowlstudiollc/github-workflows-internal`). Adds a sync step; gains independence. + + Recommend **A** until smartwatermelon goes private or NightOwl needs divergent thresholds. + +- `CLAUDE_CODE_OAUTH_TOKEN` provisioned at org level (Phase 3 of the defaults plan). +- Org admin permission to create rulesets (`admin:org` scope on `gh` token; check with `gh auth status`). +- Decision recorded: which gate strength tier to start at. + +## Phases + +### Phase 0 — Decide gate strength and bypass policy + +- Choose starting tier: **Audit-only** unless there's a strong reason to skip the calibration window. +- Decide **bypass actors**: + - You (org admin) — yes, always. + - Bots (`dependabot[bot]`, `claude[bot]`, `github-actions[bot]`) — case-by-case. The current `dependabot-auto-merge.yml` workflow expects to merge Dependabot PRs without further gates; if it's coupled to a check, decide whether to bypass for `dependabot[bot]` or to leave the dep-bump path going through full review. + - Specific users for emergency bypass — yes, document who. +- Capture decisions inline in the ruleset's description so they're discoverable later. + +### Phase 1 — Create the caller stub + +The ruleset references a workflow file by path. The file lives in a designated repo (typically `.github`). Create: + +`nightowlstudiollc/.github/.github/workflows/claude-required-review.yml`: + +```yaml +name: Claude Required Review + +on: + pull_request: + types: [opened, synchronize, ready_for_review, reopened] + +permissions: + contents: read + pull-requests: write + issues: write + id-token: write + +jobs: + claude-review: + uses: smartwatermelon/github-workflows/.github/workflows/claude-blocking-review.yml@v3.0.0 + with: + pr_number: ${{ github.event.pull_request.number }} + secrets: + claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} +``` + +Same content as the workflow-templates stub. Difference is *how* it gets invoked — via ruleset config, not per-repo file. + +### Phase 2 — Create the ruleset (audit mode) + +Via UI: `Settings → Rules → Rulesets → New ruleset → New organization ruleset` with a `Require workflows to pass before merging` rule, **enforcement status: Evaluate**. Or via REST: + +```bash +gh api -X POST orgs/nightowlstudiollc/rulesets \ + --input ruleset.json +``` + +Where `ruleset.json` is a payload along the lines of: + +```json +{ + "name": "Claude blocking review (eval)", + "target": "branch", + "enforcement": "evaluate", + "conditions": { + "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] }, + "repository_name": { "include": ["~ALL"], "exclude": [], "protected": true } + }, + "rules": [ + { + "type": "workflows", + "parameters": { + "workflows": [ + { + "repository_id": , + "path": ".github/workflows/claude-required-review.yml", + "ref": "refs/heads/main" + } + ] + } + } + ], + "bypass_actors": [] +} +``` + +Field names taken from [GitHub's ruleset REST docs](https://docs.github.com/en/rest/orgs/rules); confirm exact shape before applying. Validate with `--method GET` against an existing ruleset on a personal account first if uncertain. + +`enforcement: evaluate` means the ruleset runs but does not block. Insights tab shows what *would* have happened. + +### Phase 3 — Bellwether (1 repo, 1 week, audit mode) + +Restrict the ruleset's `conditions.repository_name.include` to a single bellwether repo for the first week. Watch: + +- PRs opened during the week trigger the workflow via the ruleset. +- The Insights → Rule insights view shows pass/fail counts. +- No silent self-collision with existing per-repo `claude-code-review.yml` — the ruleset and a per-repo file produce **two runs** of the same review. Decide: remove per-repo files (preferred) or accept double-runs. +- Quota cost and run duration are reasonable. + +Acceptance for moving to Phase 4: + +- Clean week, no surprises. +- Claude OAuth quota intact. +- Verdict pass-rate matches expectations. + +### Phase 4 — Expand scope (audit) → Active + +Two-axis expansion: + +1. **Scope axis:** bellwether repo → 3 active repos → all repos. Spread over 2-3 weeks. +2. **Enforcement axis:** `evaluate` → `active` once the audit data looks clean. + +If gate strength = **strong**, after `enforcement: active` lands, also wire branch protection to require the `claude-review / run-review` check via a *second* ruleset rule (`required_status_checks`) or per-repo branch protection. + +### Phase 5 — Reconcile with bulk-install + +Once the ruleset covers `~ALL` NightOwl repos in `active` mode, the [bulk-install script](2026-04-30-bulk-install-smartwatermelon-fleet.md) becomes redundant for NightOwl — every repo is gated automatically. Action items: + +- Bulk-install script should accept `--owner` and default to `smartwatermelon` only. +- Per-repo `claude-code-review.yml` files in NightOwl repos are deletable (the ruleset replaces them). Optional cleanup PR per repo. +- Document in this repo's README that NightOwl uses the ruleset, smartwatermelon uses per-repo files. + +## Risks and rollback + +| Risk | Mitigation | +|---|---| +| Strong gate blocks merges org-wide during a Claude OAuth outage | Audit-only first; stay moderate (no branch-protection coupling) until quota+uptime confidence is high; `bypass_actors` includes admin | +| Quota burn surprise — every PR in every repo runs Claude | Audit week measures empirically. Set org-level budget; switch to `evaluate` if breaching | +| Double-runs in repos that already have per-repo `claude-code-review.yml` | Phase 3 acceptance gate; cleanup PRs as part of Phase 5 | +| Cross-org reference (`smartwatermelon/github-workflows@v3.0.0`) breaks if that repo is taken private | Move to mirror (option B in Preconditions). Ruleset references the workflow file by path in the *NightOwl* `.github` repo — the cross-org dep is in the stub's `uses:` line, swappable later without touching the ruleset | +| Ruleset misconfiguration silently no-ops (e.g. wrong workflow path) | Audit week catches this — Insights tab shows zero runs | +| Dependabot PRs blocked by the gate | Phase 0 bypass-actors decision; alternatively, ensure the auto-merge workflow uses an authorized actor that can satisfy the gate | +| GitHub keeps iterating on Rulesets — payload shape may shift | Pin to a documented API version (`X-GitHub-Api-Version` header) when scripting; UI configuration insulates you from API changes | + +Rollback at any phase: set `enforcement: disabled` on the ruleset, or delete it via `gh api -X DELETE orgs/nightowlstudiollc/rulesets/`. Per-PR check disappears immediately. No code changes required. + +## Acceptance criteria + +- Decision recorded (strong/moderate/audit-only/skip) with timestamp in the ruleset description. +- If `audit-only` (calibration phase): ruleset active in `evaluate` mode org-wide, Insights data captured. +- If `moderate`: `enforcement: active`, no branch-protection coupling. +- If `strong`: `enforcement: active` + `required_status_checks` rule on the same ruleset (or paired branch protection). +- Audit/bellwether window written up as a postscript to this plan. +- Bulk-install script's owner-scoping confirmed not to overlap NightOwl. +- README in this repo updated with a "Org-wide enforcement (NightOwl)" subsection if the rollout proceeds. + +## Open questions + +- Does NightOwl want different BLOCK thresholds than smartwatermelon? If yes, that's a fork of `claude-blocking-review.yml` (or a new `extra_instructions` knob) — not a Ruleset decision. Note for follow-up. +- Should the ruleset target `~DEFAULT_BRANCH` only (default), or also include long-lived release branches if NightOwl uses them? Decide once branch conventions stabilize. +- Worth a parallel conversation: are there other rules NightOwl wants org-wide (e.g. linear history, signed commits, required reviewers)? Bundling them into one ruleset is cheaper than discovering them piecemeal. Out of scope for this plan, but flag it during Phase 0.