diff --git a/ai-development/claude-code-plugins.mdx b/ai-development/claude-code-plugins.mdx index a480a4f..f0a0823 100644 --- a/ai-development/claude-code-plugins.mdx +++ b/ai-development/claude-code-plugins.mdx @@ -58,11 +58,14 @@ Workflow logic. Anything that's "how Claude Code should approach a task" lives h The rules layer these plugins operate within. - + + The full skill lifecycle — phases, exit modes, known reliability gaps. + + Scheduled Claude.ai routines — the cron side of the same ecosystem. - - The Copilot equivalent — reusable agentic workflows. + + Reusable GitHub Actions workflows that drive the cloud half of the pipeline. Plugins, hooks, full README. diff --git a/architecture/ai-pipeline.mdx b/architecture/ai-pipeline.mdx index f284263..fdc6ee3 100644 --- a/architecture/ai-pipeline.mdx +++ b/architecture/ai-pipeline.mdx @@ -108,7 +108,7 @@ Every other PAL tool has a native Claude Code equivalent; for single-model calls -See [AI Development · Overview](/ai-development/overview) for what each one does in detail. +See [AI Development · Overview](/ai-development/overview) for what each one does in detail. For the actual triggers, callers, and skill mechanics that drive this pipeline end-to-end, see [Automation · Overview](/automation/overview). ## Observability layer diff --git a/automation/ai-workflows.mdx b/automation/ai-workflows.mdx new file mode 100644 index 0000000..fa8f677 --- /dev/null +++ b/automation/ai-workflows.mdx @@ -0,0 +1,108 @@ +--- +title: "ai-workflows" +description: "Sixteen reusable GitHub Actions workflows that turn issues into draft PRs, fix CI failures automatically, and gate merges. Consumer repos wire thin callers." +tier: 2 +--- + +> One repo of reusable workflows. Every consumer repo writes ten-line callers and inherits the entire pipeline. + +[`JacobPEvans/ai-workflows`](https://github.com/JacobPEvans/ai-workflows) ships 16 reusable GitHub Actions workflows (`on: workflow_call:`) that consumer repos invoke with `uses:` references. The AI orchestration, prompts, and rate guards live in the upstream workflow; the consumer caller declares the trigger and inherits secrets. + +## Event-triggered workflows + +These run on GitHub events. Wire one caller per workflow you want. + +| Workflow | Trigger | What it does | +| --- | --- | --- | +| `issue-triage.yml` | `issues: [opened]` | Categorizes, deduplicates, labels new issues | +| `issue-resolver.yml` | `issues: [opened]` | Creates a draft PR when the issue is well-scoped and not excluded by labels | +| `ci-fix.yml` | `workflow_run` of your CI workflow, `conclusion: failure` | Reads the failed log, pushes a fix commit | +| `final-pr-review.yml` | `pull_request_review: [submitted]` | Final merge-readiness gate before human merge | +| `project-router.yml` | `issues/pull_request: [opened, labeled]` | Routes items to GitHub Projects with smart field assignment | +| `post-merge-docs-review.yml` | `push: [main]` → dispatch | After merge, audits docs touched by the commit, creates fix PRs | +| `post-merge-tests.yml` | `push: [main]` → dispatch | After merge, analyzes the code changes and drafts targeted tests | +| `issue-linker.yml` | `pull_request: [opened, closed]` | Links open issues to PRs on open; closes resolved issues on merge | +| `notify-ai-pr.yml` | `pull_request: [opened]` from a bot | Slack notification when an AI-authored PR opens | + +## Scheduled workflows + +These run on cron — typically called with `schedule:` and a manual `workflow_dispatch:`. + +| Workflow | Default schedule | What it does | +| --- | --- | --- | +| `code-simplifier.yml` | Daily 04:00 UTC | DRY enforcement, dead code removal, drafts PRs | +| `best-practices.yml` | Weekly Wed 03:00 UTC | Audit creating actionable recommendations | +| `next-steps.yml` | Daily 05:00 UTC | Analyzes merge momentum, suggests next logical action | +| `issue-sweeper.yml` | Weekly Mon 06:00 UTC | Scans open issues, comments on progress, closes resolved | +| `issue-hygiene.yml` | Weekly Mon 07:00 UTC | Detects duplicates, links merged PRs, flags stale issues | +| `label-sync.yml` | Weekly Sun 05:00 UTC | Syncs canonical labels from the `.github` repo to consumers | +| `repo-orchestrator.yml` | `workflow_dispatch` | Multi-repo hub-and-spoke dispatcher for ad-hoc operations | + +## What's deprecated or disabled + +| Workflow | Status | Replacement | +| --- | --- | --- | +| `claude-review.yml` | DEPRECATED 2026-04-04. All jobs gated `if: false`. | External Gemini + Copilot PR reviews | +| `pr-issue-linker.yml` | Auto-triggers explicitly disabled (`workflow_dispatch` only) | `issue-linker.yml` | + +Wiring a caller for a deprecated workflow is a no-op — the consumer caller runs, the upstream silently skips. Don't. + +## How a caller looks + +A consumer caller is the smallest YAML that declares a trigger, sets permissions, and forwards to the upstream: + +```yaml +name: Issue Triage +on: + issues: + types: [opened] +permissions: + contents: read + id-token: write + issues: write +jobs: + run: + uses: JacobPEvans/ai-workflows/.github/workflows/issue-triage.yml@main + secrets: inherit +``` + +Permission shape varies per workflow — `issue-resolver` needs `pull-requests: write`, `ci-fix` needs `actions: read`, `post-merge-*` needs `actions: write` for the re-dispatch. The [canonical caller templates](https://github.com/JacobPEvans/ai-workflows/blob/main/docs/GETTING_STARTED.md) list the exact permission block for each. + +## Versioning + +Per [`ci-cd-policy.md`](https://github.com/JacobPEvans/ai-assistant-instructions/blob/main/agentsmd/rules/ci-cd-policy.md), JacobPEvans self-references use `@main` or a major tag like `@v0` — never minor/patch pins. The full SemVer tags exist (`@v0.15.1`) and are tracked by Renovate, but consumers should ride a moving ref so upstream improvements land without a Renovate PR per repo. + +## Authentication + +Every reusable workflow uses [`anthropics/claude-code-action@v1`](https://github.com/anthropics/claude-code-action), authenticated directly against the Anthropic API: + +- `secrets.ANTHROPIC_API_KEY` — Anthropic API key. Spend draws from the Claude Max plan's $200/month automation credits. + +OAuth tokens from a Claude Code subscription session are **explicitly forbidden** in unattended CI — they violate the [Claude Code Terms of Service](https://www.anthropic.com/legal/terms). OpenRouter is supported as a fallback provider (set `secrets.OPENROUTER_API_KEY` and `secrets.OPENROUTER_BASE_URL`) but is no longer the default. The provider matrix lives in [AUTHENTICATION.md](https://github.com/JacobPEvans/ai-workflows/blob/main/docs/AUTHENTICATION.md). + +## Commit signing + +Every AI workflow mints a `JacobPEvans-claude` GitHub App installation token immediately before calling the action, then hands it in as `github_token` with `use_commit_signing: true`. Commits land web-flow-signed and attributed to the bot. The App credentials (`GH_APP_CLAUDE_BOT_PRIVATE_KEY`, `GH_APP_CLAUDE_BOT_ID`) are distributed by `secrets-sync` to every repo in the `_github_app_repos` anchor. + +## Where to go next + + + + Caller templates for every workflow, with the correct permission blocks. + + + The post-merge dispatch pattern, bot guards, and other recurring shapes. + + + Anthropic API key setup, cost controls, fallback providers, why not OAuth. + + + The e2e runbook for checking a freshly-wired repo end to end. + + + Exactly which six callers are wired on `JacobPEvans/docs` and why. + + + How ANTHROPIC_API_KEY and the App credentials land on each consumer repo. + + diff --git a/automation/claude-code-routines.mdx b/automation/claude-code-routines.mdx new file mode 100644 index 0000000..714a007 --- /dev/null +++ b/automation/claude-code-routines.mdx @@ -0,0 +1,103 @@ +--- +title: "claude-code-routines" +description: "Six cron-scheduled Claude Code routines that watch the whole org without per-repo wiring. Pick up loose ends the event-triggered pipeline misses." +tier: 2 +--- + +> Cron, not events. Org-wide, not per-repo. One configuration, scans everything. + +[`JacobPEvans/claude-code-routines`](https://github.com/JacobPEvans/claude-code-routines) ships six prompt files that run on schedule inside Anthropic's cloud-hosted Claude Code sandbox. They discover repos under `$GH_OWNER` via `gh search`, do their work using `gh` CLI calls, and report results to Slack via the official Slack MCP connector. There is no per-repo wiring — drop a repo into the org and the routines pick it up on the next run. + +## The six routines + +| Routine | Schedule (CT) | What it does | +| --- | --- | --- | +| Morning Briefing | Daily 5:00 AM | Read-only activity summary: new PR reviews, opened issues, CI failures, anything that needs attention | +| The Sentinel | Daily 12:33 AM | Param/secret audit; picks one PR to review; flags operator-specific patterns | +| The Custodian | Daily 2:00 AM | Weighted-random maintenance: stale branch cleanup, missing labels, repo health audit | +| Issue Solver | Daily 7:00 AM + 7:00 PM | Picks one open issue, takes it from triage → draft PR in six phases | +| Daily Polish | Daily 11:00 PM | Deep-clean one repo per day: README gaps, missing `.gitignore`, CI config, test coverage | +| Weekly Scorecard | Mondays 5:00 AM | Portfolio health scores: repo count, open-issue median, CI pass rate, test coverage % | + +## How the Issue Solver picks work + +The most ambitious routine. Six phases, all running in the same sandbox session: + + + + Shell-only. `gh search issues` across `$GH_OWNER` for the last 90 days, open + unassigned. Scored via `jq` weights — `bug=+50`, `good-first-issue=+40`, `type:security=-40`, `type:breaking=-40`, recent-activity bonus. + + + Claude Sonnet classifies the top 5 by solvability + complexity (trivial/small/medium/large). + + + A read-only subagent reads the affected code and locates the exact lines that need changes. + + + Pre-flight secret scan (`grep -P` against known patterns). Creates a branch via `gh api repos/.../git/refs`. Pushes file changes via Contents API — the App installation token auto-signs every commit. + + + Best-effort CI polling at 30-second intervals up to 5 minutes. Records the final `ci_status` (passed / failed / pending / none). + + + Opens a **draft PR only** — never `--ready`, never auto-merge. If the issue is too complex, comments on the issue explaining what was tried and gives up cleanly. + + + +## How routines authenticate + +Each routine runs in Anthropic's cloud sandbox with pre-installed `gh` CLI. Authentication is via environment variables set in the cloud routine configuration at [claude.ai/code/routines](https://claude.ai/code): + +| Env var | Purpose | +| --- | --- | +| `GH_TOKEN` | GitHub PAT for `gh` CLI | +| `GH_OWNER` | The org or user to scan (e.g. `JacobPEvans`) | +| `GH_OWNERS` | The Sentinel uses this — a list of orgs to spot-check | + +Slack output goes through the official Slack MCP connector. The full operator-setup walkthrough lives in [`docs/CLOUD_ROUTINES_AUTH.md`](https://github.com/JacobPEvans/claude-code-routines/blob/main/docs/CLOUD_ROUTINES_AUTH.md) in the source repo. + +## Current deploy gotcha + +The native GitHub Actions deploy (`.github/workflows/deploy-routines.yml`) is **disabled** because `anthropics/claude-code-action@v1` does not carry the organization UUID binding that the Routines API requires — `RemoteTrigger` calls fail with `Unable to resolve organization UUID`. + +**Workaround in use today**: a local `deploy-routine-changes` skill (under `.claude/skills/` in the routines repo) drives `RemoteTrigger get/update/create` calls during interactive Claude Code sessions. The interactive harness has the org binding the GHA runner lacks. The fallback is the [`/schedule update`](https://claude.ai/code) CLI flow if `RemoteTrigger` breaks in interactive mode too. + +When Anthropic fixes the OAuth token to carry org UUID, the workflow can be restored. Until then, deploys are manual + interactive. + +## What routines do NOT do + +| Won't | Why | +| --- | --- | +| Merge any PR | Same merge prohibition as `/finalize-pr` | +| Open non-draft PRs | Human review is always the gate | +| Cross org boundaries | Owner derived from current config only | +| Touch archived or fork repos | `gh search` filters them out | +| Run during incidents | No event-driven escape hatch — wait for next cron tick | + +## Where this fits relative to ai-workflows + +| If you want… | Use… | +| --- | --- | +| A PR draft within minutes of opening an issue | `ai-workflows/issue-resolver.yml` event-triggered caller | +| A daily sweep that catches issues the event flow missed | `claude-code-routines` Issue Solver | +| To audit health across the whole org | `claude-code-routines` Sentinel + Weekly Scorecard | +| To fix CI failure on a PR you're iterating on right now | `/ship` from a local Claude Code session | + +The two systems are complementary — ai-workflows handles the per-event reaction, claude-code-routines handles the org-wide sweep. + +## Where to go next + + + + The six prompt files, schedule manifest, deploy notes. + + + Operator setup — env vars, Slack MCP, token strategy. + + + The event-driven half of the same ecosystem. + + + The per-repo cloud flow that runs in parallel. + + diff --git a/automation/codeql-resolution.mdx b/automation/codeql-resolution.mdx new file mode 100644 index 0000000..44877dd --- /dev/null +++ b/automation/codeql-resolution.mdx @@ -0,0 +1,75 @@ +--- +title: "CodeQL resolution" +description: "CodeQL alerts are a separate gate from CI checks. /resolve-codeql is the skill that closes them automatically so /ship can complete." +tier: 2 +--- + +> CodeQL is not in `statusCheckRollup`. If you only check CI, you miss the CodeQL gate. `/resolve-codeql` fixes that. + +CodeQL is GitHub's static-analysis security scanner. It runs on every PR via the `Analyze (actions)` or `Analyze (javascript)` jobs (depending on what's enabled for the repo). When it finds a violation, it posts a **code-scanning alert** that blocks merge — but **does not** show up in `gh pr checks` or in the `statusCheckRollup` of a `gh pr view --json` query. Branch protection treats the alert as a separate signal. + +## Why this matters for `/ship` + +If `/finalize-pr` only queried `statusCheckRollup`, a PR could look ready (`statusCheckRollup.state: SUCCESS`) and still be blocked at merge time by an open CodeQL alert. The skill's Phase 3 explicitly runs a second, separate gate for CodeQL — using the REST code-scanning API, not GraphQL. + +```bash +gh api repos///code-scanning/alerts \ + --jq '[.[] | select(.state == "open")] | length' +``` + +If the result is non-zero, the PR is **not** ready, regardless of what CI says. + +## What `/resolve-codeql` does + +`/resolve-codeql fix` is the auto-resolution skill invoked by `/finalize-pr` Phase 2 when alerts exist: + + + + Lists all open alerts for the repo, with rule ID, severity, and file:line. + + + For each alert: is it a real vulnerability, an intentional pattern that should be suppressed, or a false positive? + + + Real → patch the code with a fix that addresses the rule. Intentional → add a CodeQL inline suppression with a justification comment. False positive → dismiss via the API with `"reason": "false positive"`. + + + Signed via the App installation token, attributed to `JacobPEvans-claude[bot]`. + + + The push triggers a fresh CodeQL run automatically. Wait for it to complete before re-querying alert state. + + + +## Why GraphQL doesn't show CodeQL state + +The GraphQL `pullRequest` schema's `statusCheckRollup` aggregates check runs and status contexts. CodeQL alerts live in a separate `repository.codeScanningAlerts` connection — they're attached to the repo's default branch baseline, not to the PR's check run set. + +A canonical query for the PR-readiness gate (from [`gh-cli-patterns`](https://github.com/JacobPEvans/claude-code-plugins/blob/main/github-workflows/skills/gh-cli-patterns/SKILL.md)) reads `statusCheckRollup` for CI, then does a **separate** REST call for CodeQL. Both must be clean for a PR to be considered ready. + +## Async timing + +CodeQL runs are slower than most CI checks — often 2–5 minutes after a push. This timing mismatch is why `/finalize-pr` Phase 2.6 (the fix in flight) introduces an explicit wait-for-async-checks step: poll at 30-second intervals up to 5 minutes, only advance to Phase 3 when all known check kinds have a terminal status. Without this, `/finalize-pr` could treat a still-running CodeQL run as a hard failure and bail out. + +## What `/resolve-codeql` will NOT do + +- **Won't dismiss real alerts as false positive.** Dismissals require justification and are reserved for genuine FPs. +- **Won't disable a CodeQL query.** Adjusting the CodeQL config is a deliberate human change. +- **Won't loop indefinitely.** Capped at 3 fix attempts per PR per invocation — beyond that, surfaces the unfixed alerts for a human. + +## Where to go next + + + + The orchestrator that invokes `/resolve-codeql` as part of Phase 2. + + + The plugin home for `/resolve-codeql` and the rest of the toolchain. + + + The full plugin source. + + + The upstream CodeQL documentation for query authoring and config. + + diff --git a/automation/issue-to-pr-pipeline.mdx b/automation/issue-to-pr-pipeline.mdx new file mode 100644 index 0000000..4f0fa7a --- /dev/null +++ b/automation/issue-to-pr-pipeline.mdx @@ -0,0 +1,129 @@ +--- +title: "Issue to PR pipeline" +description: "The eight-step cloud flow that turns a new GitHub issue into a draft PR with green CI, AI review, and a merge-readiness comment." +tier: 2 +--- + +> Open issue. Don't open the dashboard. Come back in five minutes to a draft PR ready for your eyes. + +The pipeline on this repo, [`JacobPEvans/docs`](https://github.com/JacobPEvans/docs), uses six thin caller files in `.github/workflows/` that delegate to reusable workflows in [`JacobPEvans/ai-workflows`](https://github.com/JacobPEvans/ai-workflows). Each caller is 10–30 lines; the AI work all lives in the upstream reusable workflow. + +## What runs, in order + +| Step | Trigger | Caller file | Reusable workflow | What it does | +| --- | --- | --- | --- | --- | +| 1 | `issues: [opened]` | `issue-triage.yml` | `ai-workflows/.github/workflows/issue-triage.yml@main` | Categorizes, deduplicates, labels | +| 2 | `issues: [opened]` | `issue-resolver.yml` | `ai-workflows/.github/workflows/issue-resolver.yml@main` | Creates a **draft PR** if the issue is well-scoped and not on the excluded-labels list | +| 3 | `pull_request: opened/synchronize/ready_for_review` | (no caller — handled by upstream reviewers) | external Gemini + Copilot reviews | Posts inline review comments | +| 4 | `workflow_run` on `CI`, `conclusion: failure` | `ci-fix.yml` | `ai-workflows/.github/workflows/ci-fix.yml@main` | Reads the failed CI log, pushes a fix commit (up to 2 attempts per PR, 5 per day) | +| 5 | `pull_request_review: [submitted]` | `final-pr-review.yml` | `ai-workflows/.github/workflows/final-pr-review.yml@main` | Final merge-readiness gate — checks TODOs, debugger artifacts, CI rollup | +| 6 | `issues: [opened, labeled]`, `pull_request: [opened, ready_for_review]` | `project-router.yml` | `ai-workflows/.github/workflows/project-router.yml@main` | Routes the item to the right GitHub Project with smart field assignment | +| 7 | `push: [main]` → re-dispatched as `workflow_dispatch` | `post-merge-docs-review.yml` | `ai-workflows/.github/workflows/post-merge-docs-review.yml@main` | After merge, audits docs touched by the commit and creates fix PRs if needed | +| 8 | Human clicks **Merge** | n/a | n/a | The only manual step | + +The deprecated `claude-review.yml` (removed 2026-04-04 in favor of Gemini + Copilot reviews) and the disabled-auto-trigger `pr-issue-linker.yml` are not wired. See [ai-workflows](/automation/ai-workflows) for the full catalog and what's not active. + +## How the six callers connect + +{/* Shape: hub-and-spokes. 1 hub, 6 leaves stacked via invisible links. */} +{/* Aspect: ~4:3 (LR). Pass. */} + +```mermaid +%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%% +flowchart LR + R([docs repo]) + + subgraph callers[Caller files in .github/workflows/] + direction TB + A([issue-triage]) + B([issue-resolver]) + C([ci-fix]) + D([final-pr-review]) + E([project-router]) + F([post-merge-docs-review]) + A ~~~ B ~~~ C ~~~ D ~~~ E ~~~ F + end + + R --> A + + classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6; + classDef ai fill:#102937,stroke:#E06B4A,stroke-width:2px,color:#F4EFE6; + + class R host + class A,B,C,D,E,F ai +``` + +The hub is the consumer repo; each caller is a one-shot wrapper around an upstream reusable workflow. They run independently when their trigger fires. + +## What each caller actually contains + +A caller is the minimum YAML to declare a trigger, set permissions, and call the upstream: + +```yaml +name: Issue Triage +on: + issues: + types: [opened] +permissions: + contents: read + id-token: write + issues: write +jobs: + run: + uses: JacobPEvans/ai-workflows/.github/workflows/issue-triage.yml@main + secrets: inherit +``` + +Two patterns are slightly larger: + +- **`ci-fix.yml`** passes a `repo_context` and `ci_structure` describing what the repo is and what CI runs, so the AI knows what to fix. +- **`post-merge-docs-review.yml`** uses the [Post-Merge Dispatch Pattern](https://github.com/JacobPEvans/ai-workflows/blob/main/docs/PATTERNS.md#post-merge-dispatch-pattern) — a two-job file because `push` events aren't supported by `claude-code-action@v1`, so the caller re-dispatches as `workflow_dispatch`. + +## Secrets the pipeline needs + +Distributed automatically by [`secrets-sync`](/security/secrets-sync) when a repo is added to the `_github_app_repos` and `_all_repos` anchors in `secrets-config.yml`: + +| Secret / variable | Source | Purpose | +| --- | --- | --- | +| `ANTHROPIC_API_KEY` (secret) | `_all_repos` | Auth for `claude-code-action` to call the Anthropic API directly | +| `GH_APP_CLAUDE_BOT_PRIVATE_KEY` (secret) | `_github_app_repos` | Mints App tokens for signed commits attributed to `JacobPEvans-claude[bot]` | +| `GH_APP_CLAUDE_BOT_ID` (variable) | `_github_app_repos` | App identifier | + +Per [`git-signing.md`](https://github.com/JacobPEvans/ai-assistant-instructions/blob/main/agentsmd/rules/git-signing.md), every AI workflow mints a `JacobPEvans-claude` installation token immediately before calling `claude-code-action@v1`, then hands it in as `github_token` with `use_commit_signing: true`. Commits land web-flow-signed and attributed to the bot. + +## Rate and safety guards + +The reusable workflows enforce conservative defaults so a runaway loop can't burn cloud spend: + +- **`issue-resolver.yml`** — `max_attempts: 1` per issue, `daily_limit: 5` per repo, `excluded_labels: "type:security,type:feature,type:breaking,size:l,size:xl"` won't touch +- **`ci-fix.yml`** — `daily_run_limit: 5` per repo, max 2 fix attempts per PR +- **`final-pr-review.yml`** — `daily_run_limit: 5` +- **All workflows** — fork PRs blocked by `if:` guards, branch protection enforces the final merge gate + +## The pieces this doesn't include + +The cloud pipeline gets a PR to **draft + reviewed**. It does NOT: + +- Mark the PR ready for merge — that's a human decision +- Click the merge button — never automated +- Override branch protection or required reviewers +- Touch repos outside the current org boundary + +For the local iteration loop on a PR you're editing yourself, see [`/ship` and `/finalize-pr`](/automation/ship-and-finalize). + +## Where to go next + + + + The full catalog of 16 reusable workflows, event-triggered + scheduled. + + + The cron half — six routines that scan the org and pick up loose ends. + + + Caller templates and the live workflow catalog. + + + Why direct Anthropic API, not OAuth tokens; cost controls; fallback providers. + + diff --git a/automation/overview.mdx b/automation/overview.mdx new file mode 100644 index 0000000..98618bc --- /dev/null +++ b/automation/overview.mdx @@ -0,0 +1,76 @@ +--- +title: "Automation" +description: "How an issue becomes a merged PR with minimal human touch: ai-workflows in the cloud, claude-code-routines on cron, claude-code-plugins on the laptop." +tier: 1 +--- + +> File an issue. Walk away. Come back to a draft PR with green CI, AI review, and one human merge click left. + +This is the **issue → mergeable PR** pipeline. Three repos collaborate: `ai-workflows` runs on GitHub Actions per consumer repo, `claude-code-routines` runs on Anthropic's cloud cron, `claude-code-plugins` is the local Claude Code escape hatch. + +## The end-to-end shape + +{/* Shape: linear chain. Boundary crossings: 0. Ranks: 6×1. */} +{/* Aspect: ~2.5:1 (LR). Pass. */} + +```mermaid +%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%% +flowchart LR + I([Issue]) + T([AI triage]) + D([Draft PR]) + L([CI and review loop]) + G{Final gate} + M([Merged]) + + I --> T --> D --> L --> G --> M + + classDef src fill:#102937,stroke:#E06B4A,stroke-width:2px,color:#F4EFE6; + classDef ai fill:#102937,stroke:#E06B4A,stroke-width:2px,color:#F4EFE6; + classDef auto fill:#102937,stroke:#F4EFE6,stroke-width:1.5px,color:#F4EFE6; + classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6; + classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2px,color:#F4EFE6; + + class I src + class T,L ai + class D auto + class G gate + class M sink +``` + +A human files the issue and clicks merge. Everything in between runs without supervision. + +## The three layers + +| Layer | Where it lives | When it runs | What it owns | +| --- | --- | --- | --- | +| [ai-workflows](/automation/ai-workflows) | GitHub Actions (per consumer repo) | Event-triggered (issues, PRs, CI failures) | Triage, draft PR creation, CI auto-fix, final review gate, project routing | +| [claude-code-routines](/automation/claude-code-routines) | Anthropic cloud cron | Scheduled (cron 2×/day to weekly) | Org-wide maintenance: daily polish, issue solver, sentinel audit, weekly scorecard | +| [claude-code-plugins](/ai-development/claude-code-plugins) | Your laptop | Interactive (`/ship` from any Claude Code session) | The local escape hatch — finalize a PR you're iterating on | + +## The six moving parts + + + + The eight-step cloud flow on a target repo. Which trigger fires which file, who reviews, what gates merge. + + + The 16 reusable workflows behind the cloud pipeline. Event-triggered and scheduled. + + + Six cron-scheduled Claude routines. Org-wide maintenance, no per-repo wiring. + + + The local skill that closes the loop on a PR you're iterating on. Phases, exit modes, the known reliability gaps. + + + Why CodeQL is fixed separately from CI checks, and how `/resolve-codeql` plugs in. + + + The `/shape-issues` skill that turns rough ideas into well-scoped issues the resolver can act on. + + + +## Source repos + +[`ai-workflows`](https://github.com/JacobPEvans/ai-workflows) · [`claude-code-routines`](https://github.com/JacobPEvans/claude-code-routines) · [`claude-code-plugins`](https://github.com/JacobPEvans/claude-code-plugins). The 30-second pitch lives at [AI pipeline](/architecture/ai-pipeline); this Automation section is the mechanics. diff --git a/automation/shape-issues.mdx b/automation/shape-issues.mdx new file mode 100644 index 0000000..6e0cd04 --- /dev/null +++ b/automation/shape-issues.mdx @@ -0,0 +1,94 @@ +--- +title: "Shape issues" +description: "Raw ideas become well-scoped issues the resolver can act on. The /shape-issues skill applies Shape Up methodology to GitHub issues before they hit the pipeline." +tier: 2 +--- + +> Rough idea in. Clear problem statement, appetite, scope boundaries, and acceptance criteria out. + +`/shape-issues` is a local Claude Code skill that takes raw issue text — a one-line note, a Slack quote, a brain dump — and reshapes it into a structured GitHub issue. The reshaped issue carries enough scope clarity that `issue-resolver.yml` in [`ai-workflows`](/automation/ai-workflows) can draft a sensible PR against it, instead of stalling on ambiguity. + +## Why shaping matters + +[`issue-resolver.yml`](https://github.com/JacobPEvans/ai-workflows/blob/main/.github/workflows/issue-resolver.yml) is conservative by design. It refuses to draft PRs for issues labeled `type:security`, `type:feature`, `type:breaking`, or `size:l/xl` — the situations where AI judgment carries too much risk. Issues that aren't labeled at all default to "don't act." + +That means the difference between an issue that gets a PR and one that sits is often **how the issue is written**, not how clever the AI is. A vague "improve docs structure" stays untouched. A well-shaped "add a `Comparison` table to `infrastructure/lxc-vs-docker.mdx` with columns Memory / Disk / Network / Startup time, fed from the Proxmox cluster benchmark notes" gets a draft PR in five minutes. + +## What Shape Up gives you + +[Shape Up](https://basecamp.com/shapeup) is Basecamp's product-shaping methodology. The relevant elements for `/shape-issues`: + +| Concept | What it means here | +| --- | --- | +| **Problem** | One sentence — the real thing that needs solving, not the symptom | +| **Appetite** | How much time/risk this is worth (1 day, 1 week, 6 weeks) — gates whether the issue should even be opened | +| **Solution sketch** | A 2–4 bullet outline of the approach — enough that a reasonable agent can act, vague enough to leave room for judgment | +| **Rabbit holes** | Things the implementer might fall into and burn time on — explicitly out of scope | +| **No-goes** | What this issue **will not** address (so a follow-up issue can hold those instead) | + +## What the skill outputs + +`/shape-issues` rewrites a draft issue body into this shape: + +```markdown +## Problem +One sentence stating the actual pain or gap. + +## Appetite +1 day | 1 week | 6 weeks + +## Solution sketch +- Bullet 1: the highest-leverage change +- Bullet 2: the supporting change +- Bullet 3: validation step + +## Rabbit holes +- Thing you'll be tempted to rewrite, but don't +- Adjacent system that's broken but out of scope + +## No-goes +- Explicit non-goals +``` + +Plus a recommended label set (`size:s`, `type:enhancement`, etc.) based on appetite + scope. + +## How `/shape-issues` connects to the pipeline + +```text +Raw idea + ↓ +/shape-issues (local) + ↓ +gh issue create + ↓ +ai-workflows/issue-triage.yml ← applies labels +ai-workflows/issue-resolver.yml ← drafts a PR (or skips with reason) + ↓ +Cloud pipeline takes over from here +``` + +The skill itself doesn't open the issue — you review the shaped output, then `gh issue create --title ... --body ...`. The triage workflow takes over once GitHub fires the `issues: [opened]` event. + +## When NOT to use `/shape-issues` + +- **Bug reports with a clear reproduction.** A trace and a stack speak for themselves; shaping adds noise. +- **One-line typo fixes.** Just open the issue. +- **Anything with `type:security` label.** Security issues are handled outside the resolver pipeline; shape them differently. +- **Major architectural decisions.** Those need an [RFC](https://github.com/JacobPEvans/ai-assistant-instructions) or a design doc, not an issue. + +## Where to go next + + + + The downstream consumer — what `/shape-issues` is preparing input for. + + + What happens after a shaped issue is opened. + + + The full methodology Basecamp open-sourced. + + + The plugin home for `/shape-issues`. + + diff --git a/automation/ship-and-finalize.mdx b/automation/ship-and-finalize.mdx new file mode 100644 index 0000000..8db2dc8 --- /dev/null +++ b/automation/ship-and-finalize.mdx @@ -0,0 +1,126 @@ +--- +title: "/ship and /finalize-pr" +description: "The local Claude Code skill that drives a PR to a fully-mergeable state. Phases, exit modes, and the reliability gaps being closed." +tier: 2 +--- + +> One command. Commit, push, open the PR, fix CodeQL, resolve threads, fix CI, verify everything is green. Never merges. That's a human decision. + +`/ship` is the local escape hatch for the cloud pipeline. The cloud pipeline ([ai-workflows](/automation/ai-workflows), [claude-code-routines](/automation/claude-code-routines)) gets a PR opened and reviewed without you. `/ship` is what you run from a Claude Code session when **you** are the one iterating on a PR and want it driven to a ready-to-merge state in one command. + +## What `/ship` does + +`/ship` is a thin orchestrator. It detects uncommitted changes (commits them), discovers recently-created PRs, then for each PR invokes `/finalize-pr` — which is where the real work happens. + +```text +/ship + ├─ Step 0: verify git repo + ├─ Step 1: commit any uncommitted changes; discover PRs in scope + ├─ Step 1.5: build a context brief from the conversation + ├─ Step 2: invoke /finalize-pr per PR, sequentially + └─ Step 3: re-verify each PR with live GitHub state before reporting +``` + +## What `/finalize-pr` does + +`/finalize-pr` is the loop. Five phases per PR: + +{/* Shape: linear chain. Boundary crossings: 0. Ranks: 5×1. */} +{/* Aspect: ~3:1 (LR). Pass. */} + +```mermaid +%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%% +flowchart LR + P1([1. Discover]) + P2([2. Resolve loop]) + P3{3. Verify gate} + P4([4. Update metadata]) + P5([5. Report ready]) + + P1 --> P2 --> P3 --> P4 --> P5 + P3 -.->|gate fails| P2 + + classDef ai fill:#102937,stroke:#E06B4A,stroke-width:2px,color:#F4EFE6; + classDef auto fill:#102937,stroke:#F4EFE6,stroke-width:1.5px,color:#F4EFE6; + classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6; + + class P1,P2,P4 ai + class P5 auto + class P3 gate + + linkStyle 0,1,2,3 stroke:#4FB3A9,stroke-width:2px; + linkStyle 4 stroke:#E06B4A,stroke-width:1.5px,stroke-dasharray:4 3; +``` + +| Phase | What it owns | +| --- | --- | +| 1. Discover | Resolve which PR(s) to act on (current branch, all, or org-wide) | +| 2. Resolve loop | Start CI monitor in background; in parallel: invoke `/resolve-codeql fix`, `/resolve-pr-threads`, merge-conflict resolution; once CI completes, run `/simplify` once on the cumulative changes | +| 3. Verify gate | Re-query live GitHub state — `state`, `mergeable`, `mergeStateStatus`, `reviewDecision`, `statusCheckRollup.state`, all `reviewThreads.isResolved`, CodeQL alert count | +| 4. Update metadata | A subagent updates PR title, description, linked issues | +| 5. Report ready | Emit the canonical PR status block; wait for human merge | + +## What it never does + +- **Never merges.** Merge is always a human decision. +- **Never approves.** No auto-approval of PRs. +- **Never crosses org boundaries** in org-wide mode. +- **Never bypasses branch protection.** + +## Subagents in the call chain + +```text +/ship → /finalize-pr → /resolve-codeql fix + → /resolve-pr-threads → superpowers:receiving-code-review + → /simplify + → haiku subagent (PR metadata update) + → background CI monitor (Task tool) +``` + +Each subagent runs scoped to its task and reports back. The orchestrator re-verifies live state — never trusts a subagent's self-report as ground truth. + +## Known reliability gaps + +`/ship` has been ending prematurely without leaving PRs fully mergeable. Root causes traced to the current `SKILL.md` files: + +| Failure mode | Why it happens | +| --- | --- | +| Exits "blocked" when a fix could have continued | Phase 3 → Phase 2 loop is prose with no enforced iteration counter — subagents treat it as advisory | +| Treats async-pending checks as failures | Phase 3 aborts on `statusCheckRollup.state ≠ SUCCESS`, but Phase 2 can't fix a pending check | +| Silent subagent failure passes through | After `/resolve-codeql` and `/resolve-pr-threads`, skill advances without re-querying state to confirm fixes landed | +| CI monitor dies silently | Background Task agent can fail without propagating | +| All Phase 3 aborts treated identically | Some failures are agent-fixable, some are wait, some require humans (`REVIEW_REQUIRED`) | + +Fix in flight: explicit iteration counter (cap 5), wait-for-async-checks phase, post-fix verification of subagent work, CI-monitor failure fallback, and a failure-mode taxonomy that maps each `mergeStateStatus`/`reviewDecision` to a handler. After the fix, every `/ship` invocation reports one of three categories with a specific reason — never silent half-finalization: + +- **Ready to merge** — all gates clean +- **Ready except human gate** — only `REVIEW_REQUIRED` remaining +- **Ship aborted** — specific gate stuck with manual-action suggestion + +Tracked as a PR against [`claude-code-plugins`](https://github.com/JacobPEvans/claude-code-plugins). + +## When to use `/ship` vs the cloud pipeline + +| Situation | Use | +| --- | --- | +| Issue is filed, you want a PR drafted without thinking | [`ai-workflows`](/automation/ai-workflows) (the cloud pipeline triggered on issue open) | +| You're editing a PR locally and want CI/threads/CodeQL handled in one command | `/ship` from your Claude Code session | +| You want a daily org-wide sweep | [`claude-code-routines`](/automation/claude-code-routines) (cron-scheduled) | +| You want to know if a PR is *really* ready to merge | `/finalize-pr ` directly — gives you the canonical gate output without re-running fixes | + +## Where to go next + + + + Why CodeQL is fixed separately from CI checks, and what `/resolve-codeql` does. + + + The plugin home for `/ship`, `/finalize-pr`, and all the supporting skills. + + + The full skill definition. + + + Phases, gates, and the merge prohibition. + + diff --git a/docs.json b/docs.json index 5b4addd..9d22e4d 100644 --- a/docs.json +++ b/docs.json @@ -134,6 +134,18 @@ "ai-development/claude-code-plugins" ] }, + { + "group": "Automation", + "pages": [ + "automation/overview", + "automation/issue-to-pr-pipeline", + "automation/ai-workflows", + "automation/claude-code-routines", + "automation/ship-and-finalize", + "automation/codeql-resolution", + "automation/shape-issues" + ] + }, { "group": "Conventions", "pages": [ diff --git a/tools/automation.mdx b/tools/automation.mdx index 9591952..34f27de 100644 --- a/tools/automation.mdx +++ b/tools/automation.mdx @@ -77,4 +77,10 @@ These five skills are filed as GitHub issues and tracked in the `enhancement` + The broader plugin ecosystem this skill draws from. + + The other half of the automation story — the issue → mergeable PR pipeline that runs across every JacobPEvans repo. + + + The Claude Code skill that takes a PR through CI, CodeQL, threads, and the final merge gate. +