From 16b0f25b00c9bde409675885ed799b236f07adc5 Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:23:59 -0700 Subject: [PATCH 1/7] fix(claude-action): grant administration:write, allow gh api/label create, add standards-conformance prompt rules --- .github/workflows/claude-code-reusable.yml | 38 +++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/claude-code-reusable.yml b/.github/workflows/claude-code-reusable.yml index d767037c0..70cdf4295 100644 --- a/.github/workflows/claude-code-reusable.yml +++ b/.github/workflows/claude-code-reusable.yml @@ -66,6 +66,7 @@ jobs: issues: write actions: read checks: read + administration: write steps: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -83,10 +84,45 @@ jobs: actions: read checks: read claude_args: | - --allowedTools "Bash(gh pr create:*),Bash(gh pr view:*),Bash(gh pr comment:*),Bash(gh issue comment:*),Bash(gh run view:*),Bash(gh run watch:*),Edit,Write" + --allowedTools "Bash(gh pr create:*),Bash(gh pr view:*),Bash(gh pr comment:*),Bash(gh issue comment:*),Bash(gh run view:*),Bash(gh run watch:*),Bash(gh api:*),Bash(gh label create:*),Edit,Write" prompt: | Implement a fix for issue #${{ github.event.issue.number }}. + **Standards-conformance rules — read these before writing any code:** + + - **For workflow files** (`.github/workflows/*.yml`): if a template + exists in `petry-projects/.github/standards/workflows/` for what + you're adding, **copy it verbatim** rather than writing from + scratch. Available templates: `agent-shield.yml`, `claude.yml`, + `dependabot-automerge.yml`, `dependabot-rebase.yml`, + `dependency-audit.yml`, `feature-ideation.yml`. Fetch via: + `gh api repos/petry-projects/.github/contents/standards/workflows/.yml --jq '.content' | base64 -d` + Adapt only when the file genuinely needs repo-specific content. + + - **For org standards** (labels, settings, rulesets, CODEOWNERS): + read `petry-projects/.github/standards/` first via `gh api`. + Match colors, names, and structure exactly. The full standards + tree is at `petry-projects/.github/tree/main/standards/`. + + - **For SHA pinning** (Action Pinning Policy in + `standards/ci-standards.md`): never guess or fabricate SHAs. + Always look them up: + * Tags: `gh api repos/{owner}/{repo}/git/refs/tags/{tag} --jq '.object.sha'` + * Branches: `gh api repos/{owner}/{repo}/branches/{branch} --jq '.commit.sha'` + If the lookup fails, do not pin — open the PR with the action + still using its tag and clearly explain the blocker in the PR + body so a human can complete the fix. + + - **For CodeQL** (`codeql.yml`): all ecosystems present in the repo + MUST be configured as CodeQL languages. Repos with + `.github/workflows/*.yml` files MUST scan the `actions` + ecosystem. Use a matrix strategy for multi-language repos. + + - **Do not skip the work** if previous comments say "blocked": the + prior infrastructure issues that produced those comments may + have been resolved. Attempt the fix; if you hit a *new* error, + report the actual error message rather than referring to history. + After implementing: 1. Create a pull request with a clear title and description. Include "Closes #${{ github.event.issue.number }}" in the PR body. 2. Self-review your own PR — look for bugs, style issues, missed edge cases, and test gaps. If you find problems, push fixes. From 11c14500519566ac90f41a2eb988331ab2951006 Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:24:05 -0700 Subject: [PATCH 2/7] docs(ci-standards): add 'Using Templates' section, SHA lookup procedure, document administration:write --- standards/ci-standards.md | 69 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/standards/ci-standards.md b/standards/ci-standards.md index 7d46fbfea..d117e3adc 100644 --- a/standards/ci-standards.md +++ b/standards/ci-standards.md @@ -6,6 +6,39 @@ repository must implement. --- +## Using Templates from `standards/workflows/` + +> **Rule:** When fixing a compliance finding by adding a workflow file, **copy +> the template from [`standards/workflows/`](workflows/) verbatim.** Do not +> generate the file from scratch, even if the change seems trivial. The +> templates are the source of truth — anything generated from scratch is, by +> definition, drift. + +Available templates: + +| Template | Purpose | +|----------|---------| +| [`agent-shield.yml`](workflows/agent-shield.yml) | Deep agent-config security scan via `ecc-agentshield` | +| [`claude.yml`](workflows/claude.yml) | Thin caller delegating to the org-level reusable Claude Code workflow | +| [`dependabot-automerge.yml`](workflows/dependabot-automerge.yml) | Auto-approve and squash-merge eligible Dependabot PRs | +| [`dependabot-rebase.yml`](workflows/dependabot-rebase.yml) | Rebase Dependabot PRs on demand | +| [`dependency-audit.yml`](workflows/dependency-audit.yml) | Multi-ecosystem audit (npm, pnpm, gomod, cargo, pip) | +| [`feature-ideation.yml`](workflows/feature-ideation.yml) | BMAD Method ideation pipeline (BMAD-enabled repos only) | + +**Adapt only when the template genuinely requires repo-specific content** (e.g., a +project name in a comment, a different cron schedule for a known reason). Anything +beyond surface adaptation indicates either a missing template or a missing standard +— file an issue against `petry-projects/.github` rather than diverging silently. + +**Fetching a template programmatically** (e.g., from a Claude Code automation run): + +```bash +gh api repos/petry-projects/.github/contents/standards/workflows/.yml \ + --jq '.content' | base64 -d > .github/workflows/.yml +``` + +--- + ## Required Workflows Every repository MUST have these 7 workflows. Reusable templates for Dependabot @@ -544,6 +577,31 @@ version for human readability. Dependabot keeps pinned SHAs up to date via the `github-actions` ecosystem entry in `dependabot.yml`. +### Looking Up the Correct SHA + +> **Never guess or fabricate a SHA.** A SHA that doesn't exist in the upstream +> repo will fail at runtime — and worse, may "pass CI" if the job that uses it +> is conditionally skipped, leaving a latent failure waiting to bite the next +> developer. + +Use the GitHub API to resolve a tag or branch to its current commit SHA: + +```bash +# For a tag (e.g., v6.0.2) +gh api repos/actions/checkout/git/refs/tags/v6.0.2 --jq '.object.sha' + +# For a branch (e.g., stable) +gh api repos/dtolnay/rust-toolchain/branches/stable --jq '.commit.sha' + +# Verify a SHA exists in the upstream repo before pinning +gh api repos/actions/checkout/commits/de0fac2e4500dabe0009e67214ff5f5447ce83dd --jq '.sha' +``` + +**If the lookup fails or the network is unavailable, do not pin.** Leave the +action with its tag reference and document the blocker in the PR body so a +human can complete the fix. A correct unpinned reference is better than an +incorrect pinned one. + > **Note on examples in this document:** The "Workflow Patterns by Tech Stack" > section uses tag references (e.g., `@v4`) for readability since those are > illustrative patterns, not copy-paste templates. The "Required Workflows" @@ -576,10 +634,19 @@ For single-job workflows, top-level least-privilege permissions are acceptable |----------|------------| | CI (build/test) | `contents: read` | | SonarCloud | `contents: read`, `pull-requests: read` | -| Claude Code | `contents: write`, `id-token: write`, `pull-requests: write`, `issues: write`, `actions: read`, `checks: read` | +| Claude Code | `contents: write`, `id-token: write`, `pull-requests: write`, `issues: write`, `actions: read`, `checks: read`, `administration: write` | | CodeQL | `actions: read`, `security-events: write`, `contents: read` | | Dependabot auto-merge | `contents: read`, `pull-requests: read` (+ app token for merge) | +> **Note on Claude Code `administration: write`:** Required so the +> `claude-issue` job can autonomously create labels, repository rulesets, and +> enable settings like Discussions. Without it, compliance fixes that touch +> repo-level configuration (Discussions, code-quality ruleset, missing +> labels) require manual human action. The grant only takes effect on the +> `claude-issue` job in the reusable workflow — repo-level callers don't +> need to set it themselves because they use `secrets: inherit` and inherit +> the called workflow's permission shape via the intersection rule. + --- ## Organization-Level Secrets for Standard CI From 80e54a5d738f2afe4e525e8cd029c1163bcb5e21 Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:24:11 -0700 Subject: [PATCH 3/7] docs(AGENTS): link standards root and per-topic standards files at top of file --- AGENTS.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 836f0e571..1a98265e7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,24 @@ It follows the [AGENTS.md convention](https://agents.md/) and is intended to be --- +## Organization Standards + +The full set of org standards lives at +**[`petry-projects/.github/tree/main/standards/`](https://github.com/petry-projects/.github/tree/main/standards)**. +Read the relevant standard *before* making changes that touch CI, repo settings, agent configuration, or labels. + +| Topic | Standard | What it covers | +|-------|----------|----------------| +| **CI/CD workflows** | [`standards/ci-standards.md`](https://github.com/petry-projects/.github/blob/main/standards/ci-standards.md) | Required workflows, action pinning, permissions, job naming, tech-stack patterns | +| **Workflow templates** | [`standards/workflows/`](https://github.com/petry-projects/.github/tree/main/standards/workflows) | Copy-paste-ready templates: `agent-shield.yml`, `claude.yml`, `dependabot-automerge.yml`, `dependabot-rebase.yml`, `dependency-audit.yml`, `feature-ideation.yml` | +| **Agent configuration** | [`standards/agent-standards.md`](https://github.com/petry-projects/.github/blob/main/standards/agent-standards.md) | CLAUDE.md / AGENTS.md / SKILL.md required structure, frontmatter rules, cross-references | +| **Repo settings + labels** | [`standards/github-settings.md`](https://github.com/petry-projects/.github/blob/main/standards/github-settings.md) | Required settings, label set with exact colors, code-quality ruleset, branch protection | +| **Dependabot config** | [`standards/dependabot-policy.md`](https://github.com/petry-projects/.github/blob/main/standards/dependabot-policy.md) and [`standards/dependabot/`](https://github.com/petry-projects/.github/tree/main/standards/dependabot) | Per-ecosystem dependabot.yml templates and policy | + +**When fixing a compliance finding, the rule is: read the standard, then copy the template — do not generate from scratch.** Anything generated from scratch is, by definition, drift from the standard. If a needed standard or template is missing, file an issue against `petry-projects/.github` rather than diverging silently. + +--- + ## Project Context - **Assume brownfield.** When exploring a repo, check for existing source code before assuming it is greenfield. From 714a589e400dc63a884a3b25be7ff455fda1427d Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:29:17 -0700 Subject: [PATCH 4/7] docs(AGENTS): wrap standards-rule paragraph to satisfy MD013 line-length --- AGENTS.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 1a98265e7..59a29cd69 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,7 +21,11 @@ Read the relevant standard *before* making changes that touch CI, repo settings, | **Repo settings + labels** | [`standards/github-settings.md`](https://github.com/petry-projects/.github/blob/main/standards/github-settings.md) | Required settings, label set with exact colors, code-quality ruleset, branch protection | | **Dependabot config** | [`standards/dependabot-policy.md`](https://github.com/petry-projects/.github/blob/main/standards/dependabot-policy.md) and [`standards/dependabot/`](https://github.com/petry-projects/.github/tree/main/standards/dependabot) | Per-ecosystem dependabot.yml templates and policy | -**When fixing a compliance finding, the rule is: read the standard, then copy the template — do not generate from scratch.** Anything generated from scratch is, by definition, drift from the standard. If a needed standard or template is missing, file an issue against `petry-projects/.github` rather than diverging silently. +**When fixing a compliance finding, the rule is: read the standard, then copy +the template — do not generate from scratch.** Anything generated from scratch +is, by definition, drift from the standard. If a needed standard or template +is missing, file an issue against `petry-projects/.github` rather than +diverging silently. --- From 57dae289209c2c11593af905a27272e2f1fa249d Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:34:09 -0700 Subject: [PATCH 5/7] fix(claude-action): yamllint disable for long allowedTools line --- .github/workflows/claude-code-reusable.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/claude-code-reusable.yml b/.github/workflows/claude-code-reusable.yml index 70cdf4295..2e620d522 100644 --- a/.github/workflows/claude-code-reusable.yml +++ b/.github/workflows/claude-code-reusable.yml @@ -83,8 +83,10 @@ jobs: additional_permissions: | actions: read checks: read + # yamllint disable rule:line-length claude_args: | --allowedTools "Bash(gh pr create:*),Bash(gh pr view:*),Bash(gh pr comment:*),Bash(gh issue comment:*),Bash(gh run view:*),Bash(gh run watch:*),Bash(gh api:*),Bash(gh label create:*),Edit,Write" + # yamllint enable rule:line-length prompt: | Implement a fix for issue #${{ github.event.issue.number }}. From 65d0f17aae31a407e7e8588c719b936e3365fdaa Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:38:59 -0700 Subject: [PATCH 6/7] fix(claude-action): remove invalid 'administration' permission scope; document GH_PAT_WORKFLOWS as the actual mechanism --- .github/workflows/claude-code-reusable.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/claude-code-reusable.yml b/.github/workflows/claude-code-reusable.yml index 2e620d522..029998752 100644 --- a/.github/workflows/claude-code-reusable.yml +++ b/.github/workflows/claude-code-reusable.yml @@ -66,7 +66,10 @@ jobs: issues: write actions: read checks: read - administration: write + # Note: GitHub Actions does NOT expose an "administration" permission scope. + # Admin operations (create rulesets, enable Discussions, etc.) work via the + # GH_PAT_WORKFLOWS token below, which must be a classic PAT with `repo` scope + # (or fine-grained with Administration:write) for those calls to succeed. steps: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From e94809ed49e66df5b3ddf4e4ceb55f8ee36ce4b6 Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:39:00 -0700 Subject: [PATCH 7/7] docs(ci-standards): replace bogus 'administration: write' note with explanation of how admin ops actually work via GH_PAT_WORKFLOWS --- standards/ci-standards.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/standards/ci-standards.md b/standards/ci-standards.md index d117e3adc..499ac48d9 100644 --- a/standards/ci-standards.md +++ b/standards/ci-standards.md @@ -634,18 +634,22 @@ For single-job workflows, top-level least-privilege permissions are acceptable |----------|------------| | CI (build/test) | `contents: read` | | SonarCloud | `contents: read`, `pull-requests: read` | -| Claude Code | `contents: write`, `id-token: write`, `pull-requests: write`, `issues: write`, `actions: read`, `checks: read`, `administration: write` | +| Claude Code | `contents: write`, `id-token: write`, `pull-requests: write`, `issues: write`, `actions: read`, `checks: read` | | CodeQL | `actions: read`, `security-events: write`, `contents: read` | | Dependabot auto-merge | `contents: read`, `pull-requests: read` (+ app token for merge) | -> **Note on Claude Code `administration: write`:** Required so the -> `claude-issue` job can autonomously create labels, repository rulesets, and -> enable settings like Discussions. Without it, compliance fixes that touch -> repo-level configuration (Discussions, code-quality ruleset, missing -> labels) require manual human action. The grant only takes effect on the -> `claude-issue` job in the reusable workflow — repo-level callers don't -> need to set it themselves because they use `secrets: inherit` and inherit -> the called workflow's permission shape via the intersection rule. +> **Note on admin operations from Claude Code:** GitHub Actions does **not** +> expose an `administration` permission scope. The valid set is documented at +> [docs.github.com](https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs). +> Admin-level operations the `claude-issue` job needs — creating repository +> rulesets, enabling Discussions, modifying repo settings — must be performed +> with a token that already carries the right scope. The reusable workflow +> passes `GH_PAT_WORKFLOWS` to `claude-code-action` for exactly this reason: +> as long as that org-level secret is a classic PAT with `repo` scope (which +> includes admin capability for the authenticated user's repos) or a +> fine-grained PAT with `Administration: Read and write`, admin calls +> succeed. Granting a non-existent workflow permission has no effect and +> will fail `actionlint`. ---