Skip to content
43 changes: 42 additions & 1 deletion .github/workflows/claude-code-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ jobs:
issues: write
actions: read
checks: read
# 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:
Comment on lines 66 to 73

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding administration: write here will only affect the job-scoped GITHUB_TOKEN. In this job the action later receives github_token: ${{ secrets.GH_PAT_WORKFLOWS }} (a separate PAT), so unless that PAT is guaranteed to be present and to have equivalent admin capabilities, the new permission may not actually enable label/ruleset/discussions changes. Consider having the action default to ${{ secrets.GH_PAT_WORKFLOWS || github.token }} (or documenting that the PAT must include admin-level scopes) so the permission grant is effective.

Copilot uses AI. Check for mistakes.
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -82,11 +86,48 @@ 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:*),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"
# yamllint enable rule:line-length
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/<file>.yml --jq '.content' | base64 -d`

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new prompt suggests fetching workflow templates via the contents API and piping through base64 -d, but base64 isn't included in --allowedTools (only gh api is). Either allow Bash(base64:*) (and likely redirection) or change the suggested fetch command to use gh api -H "Accept: application/vnd.github.raw" ... > .github/workflows/<file>.yml so it works with the current tool allowlist.

Suggested change
`gh api repos/petry-projects/.github/contents/standards/workflows/<file>.yml --jq '.content' | base64 -d`
`gh api -H "Accept: application/vnd.github.raw" repos/petry-projects/.github/contents/standards/workflows/<file>.yml > .github/workflows/<file>.yml`

Copilot uses AI. Check for mistakes.
Adapt only when the file genuinely needs repo-specific content.
Comment on lines +100 to +105

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, this prompt lists claude.yml as one of the standards/workflows/ templates to copy verbatim, but standards/workflows/claude.yml is not currently a thin caller (it runs the Claude action directly). That makes the instruction ambiguous for repos trying to follow the new “template-first” rule; align the prompt with the actual template, or update the template to match the reusable-workflow delegation model.

Suggested change
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/<file>.yml --jq '.content' | base64 -d`
Adapt only when the file genuinely needs repo-specific content.
you're adding, use that template instead of 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/<file>.yml --jq '.content' | base64 -d`
For `claude.yml`, copy the standard thin caller template and keep
it delegating to the reusable Claude workflow rather than running
the Claude action inline. Adapt templates only when the file
genuinely needs repo-specific content.

Copilot uses AI. Check for mistakes.

- **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.
Expand Down
22 changes: 22 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ 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.
Expand Down
71 changes: 71 additions & 0 deletions standards/ci-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Comment on lines +19 to +26

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude.yml is described here as a “thin caller delegating to the org-level reusable Claude Code workflow”, but the actual standards/workflows/claude.yml file currently contains the full workflow (it runs anthropics/claude-code-action directly rather than uses: .../claude-code-reusable.yml). This mismatch will confuse consumers and undermines the new “copy templates verbatim” rule; either update the template to match the thin-caller model or adjust this description to match reality.

Copilot uses AI. Check for mistakes.

**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/<file>.yml \
--jq '.content' | base64 -d > .github/workflows/<file>.yml
```

---

## Required Workflows

Every repository MUST have these 7 workflows. Reusable templates for Dependabot
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -580,6 +638,19 @@ For single-job workflows, top-level least-privilege permissions are acceptable
| CodeQL | `actions: read`, `security-events: write`, `contents: read` |
| Dependabot auto-merge | `contents: read`, `pull-requests: read` (+ app token for merge) |

> **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`.

---

## Organization-Level Secrets for Standard CI
Expand Down
Loading