Skip to content

Commit f9124f0

Browse files
committed
Merge origin/main into claude/hookdeck-gateway-mcp-Xe6WQ
Made-with: Cursor
2 parents 65bcd77 + bd35f40 commit f9124f0

48 files changed

Lines changed: 7084 additions & 101 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Issue auto-implement — local development
2+
# Copy to .env and fill in secrets. Do not commit .env.
3+
4+
# Required for assess and implement. Get from https://console.anthropic.com/
5+
# Implement passes this to Claude Code CLI (claude on PATH).
6+
AUTO_IMPLEMENT_ANTHROPIC_API_KEY=
7+
8+
# Required for implement; optional for assess (redirect-to-PR, fetch comments). Run: gh auth token
9+
GITHUB_TOKEN=
10+
11+
# Required for implement. Example: hookdeck/hookdeck-cli
12+
GITHUB_REPOSITORY=
13+
14+
# Required for implement. Issue number to implement.
15+
# ISSUE_NUMBER=
16+
17+
# Optional. Repo root; default inferred from cwd when run from assess/.
18+
# GITHUB_WORKSPACE=
19+
20+
# Optional. Comma-separated paths (relative to repo root) for Claude context.
21+
# CONTEXT_FILES=AGENTS.md,REFERENCE.md
22+
23+
# Optional. Passed from assess step into implement prompt.
24+
# VERIFICATION_NOTES=
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Workflow artifacts written by implement script (read by action, never commit)
2+
.commit_msg
3+
.pr_title
4+
.pr_body
5+
# PR comment body when implement makes no code changes (no-change rationale or request for clarification; workflow reads, then discards)
6+
.comment_body
7+
8+
# Local env (secrets); do not commit
9+
.env
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# AGENTS.md — Issue auto-implement action
2+
3+
For agents making changes to this action. This file summarizes flows, design decisions, and implementation details.
4+
5+
## Flows
6+
7+
### 1. Issue to first PR
8+
9+
- **Triggers:** `issues.labeled` (prefixed trigger label), `issue_comment.created` on a labeled issue when **no PR exists yet**.
10+
- **Flow:** Normalize event → assess (enough info?) → if `request_info`: post comment, add needs-info label, exit. If `implement`: implement step (push to branch `auto-implement-issue-<N>`) → verify → on fail retry (cap `max_implement_retries`); on pass create PR with "Closes #N", add pr-created label, optional comment.
11+
12+
### 2. Issue comment when PR already exists
13+
14+
- **Trigger:** `issue_comment.created` on an issue that **already has an open PR** for that issue.
15+
- **Flow:** Post a short reply on the issue directing the user to the PR; exit. No assessment or implement.
16+
17+
### 3. PR review or PR conversation comment → iteration
18+
19+
- **Triggers:** `pull_request_review.submitted`, `pull_request_review_comment.created`, or `issue_comment.created` **on a PR** (when `issue.pull_request` is set) when the PR is from an automation branch or body contains "Closes #N".
20+
- **Flow:** Resolve issue number from PR (body "Closes #N"/"Fixes #N" or head branch `auto-implement-issue-<N>`) → assess with issue + review/comment content → implement ("address review feedback"), push to same branch → verify → on pass: do **not** create PR; post comment on the PR summarizing the new commit(s).
21+
22+
## Event normalization
23+
24+
From the workflow event payload, derive:
25+
26+
- **Issue number:** For `issues` or `issue_comment`: `event.issue.number`. For `pull_request_review` or `pull_request_review_comment`: parse PR body for "Closes #N" or "Fixes #N", or PR head branch for `auto-implement-issue-<N>`.
27+
- **PR exists for issue (issue_comment only):** Check whether an open PR exists for that issue (e.g. head branch `auto-implement-issue-<N>` or body "Closes #<N>").
28+
29+
## Request more info vs comment body from implement
30+
31+
- **Request more info (assess):** The **assess** step decides there is **not enough information** to implement. It returns `action: request_info` and a `comment_body`. The workflow posts that on the issue (or on the PR when the trigger was a PR review/comment), adds the `needs-info` label, and **exits without running implement**.
32+
- **Comment body from implement (no change or need clarification):** The assess step said **implement**. The **implement** step ran (Claude Code CLI with full repo context). When Claude **chose not to make code changes** — e.g. the feedback is a question, the current approach is preferred, or it needs clarification — it **must** write `.comment_body` with the text to post on the PR (one or two sentences). The workflow posts that on the **PR** (review iteration path). If `.comment_body` is missing, the workflow falls back to a generic message. The implement prompt requires Claude to always write `.comment_body` when making no code changes so reviewers get a useful reply. Use for: (a) no-change scenarios (thank the reviewer, briefly explain), or (b) when more information is requested (e.g. "Could you clarify whether you want X or Y?").
33+
34+
If a reviewer's comment is ambiguous, assess might still return **implement** (optimistic). Then implement runs; Claude can either make a best-effort change, or write `.comment_body` asking for clarification. That clarification is posted on the PR.
35+
36+
## Assess script
37+
38+
- **Path:** `assess/src/index.ts` (TypeScript), run with `npx tsx src/index.ts` from the assess directory (no build).
39+
- **Input:** Reads event from `GITHUB_EVENT_PATH`; optional context files from input.
40+
- **Output:** JSON with `action` (`implement` | `request_info`), `comment_body` (if request_info), `verification_notes` (optional), `review_feedback` (when trigger is PR review or comment on PR — exact text for implement to address). Written to file or GITHUB_OUTPUT.
41+
- **When triggered by PR review:** Include PR review body and review comments in the payload sent to Claude. Assess also sets `review_feedback` from the review/comment so the implement step receives it.
42+
43+
## Implement script
44+
45+
- **Path:** `assess/src/implement.ts`, run with `npx tsx src/implement.ts` from the assess directory.
46+
- **Env:** `ISSUE_NUMBER`, `GITHUB_REPOSITORY`, `GITHUB_TOKEN`, `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` (required); `VERIFICATION_NOTES`, `REVIEW_FEEDBACK`, `GITHUB_WORKSPACE`, `CONTEXT_FILES`, `IMPLEMENT_COMMIT_MSG_FILE`, `PREVIOUS_VERIFY_OUTPUT` (optional).
47+
- **Flow:** Fetches issue title/body from GitHub API, loads context files, then runs **Claude Code CLI** (`claude` on PATH) in the repo root with a prompt; the script passes `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` to the CLI as `ANTHROPIC_API_KEY`. When `REVIEW_FEEDBACK` is set (PR review or comment iteration), the prompt includes a "Review feedback to address (you must implement this)" section so the CLI addresses the reviewer's ask (e.g. add tests). The CLI implements in-repo (Read/Edit/Bash). When Claude makes code changes it writes `.commit_msg`, `.pr_title`, `.pr_body`; when it makes no code changes it writes `.comment_body` (no-change rationale or request for clarification). The script ensures commit/PR meta files exist only when Claude did not write `.comment_body`. When `PREVIOUS_VERIFY_OUTPUT` is set (e.g. after a failed verify run), it is included in the prompt so the CLI can fix the implementation. In CI, the action installs the CLI (`npm install -g @anthropic-ai/claude-code`) before the implement step when the assess outcome is `implement`.
48+
49+
## Implement–verify loop
50+
51+
- **Single step** `implement_verify_loop`: for each attempt from 1 to `max_implement_retries`, run implement (with `PREVIOUS_VERIFY_OUTPUT` from the previous failure, if any), commit and push, then run `verify_commands`. If verify passes, exit success. If it fails, set the verify output as `PREVIOUS_VERIFY_OUTPUT` and retry. After all attempts, fail. When this step succeeds: if trigger was `pull_request_review`, `pull_request_review_comment`, or `issue_comment` on a PR (`issue.pull_request` set), post a comment on the existing PR (no new PR); otherwise create PR.
52+
53+
## Branch and PR
54+
55+
- Branch name: `auto-implement-issue-<issue_number>`.
56+
- PR title or body must include "Closes #N" (or "Fixes #N") so merging auto-closes the issue.
57+
- On iteration (PR already exists): do not create a new PR; post a comment on the PR summarizing the new commit(s).
58+
59+
## Restricting who can trigger
60+
61+
The first step enforces one of two gates (exactly one must be configured; no bypass):
62+
63+
1. **Permission check** — If `github_allowed_trigger_min_permission` is set (repo variable `AUTO_IMPLEMENT_ALLOWED_TRIGGER_MIN_PERMISSION`: `triage`, `push`, `maintain`, or `admin`), the action calls the repo collaborator permission API and requires the actor to have at least that permission. Works with the default `GITHUB_TOKEN`.
64+
2. **Team check** — Otherwise, if `github_allowed_trigger_team` is set (repo variable `AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`, e.g. `org/team`), the action checks `github.actor` against that team; if unset or not a member, fail. Token must have `read:org` (PAT if `GITHUB_TOKEN` lacks it).
65+
66+
If neither variable is set, the step fails. When both are set, the permission check is used and the team value is ignored.
67+
68+
## Labels
69+
70+
All automation labels use `label_prefix` (default `automation`): `{prefix}/auto-implement`, `{prefix}/needs-info`, `{prefix}/pr-created`. Create via API if missing.
71+
72+
## Local development
73+
74+
Scripts load a `.env` file from the action root or cwd (see README **Local runs**). Key env: `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`, `GITHUB_TOKEN`, `GITHUB_REPOSITORY`, `ISSUE_NUMBER` (implement). Copy `.env.example` to `.env` and fill; optional `./scripts/setup-local-env.sh --with-gh` to set `GITHUB_TOKEN` from `gh auth token`.
75+
76+
## Verification
77+
78+
When changing this action or the assess script:
79+
80+
1. **Run the assess unit tests locally** before committing: `cd .github/actions/issue-auto-implement/assess && npm ci && npm test`. Do not rely on CI alone—catch failures locally first, then push.
81+
2. **CI** runs the same tests in `.github/workflows/issue-auto-implement-test.yml` when you push or open a PR that touches `.github/actions/issue-auto-implement/**`.
82+
3. **Optional:** Run the assess script with a fixture and `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` for end-to-end assessment behavior.
83+
4. **Full workflow:** Trigger manually on a test issue (trigger label or comment). Ensure repo secrets/variables are set. Inspect the Actions run and the issue/PR; re-run after changes to the implement or verify loop.
84+
85+
## Next steps (implementation backlog)
86+
87+
Possible future improvements:
88+
89+
1. **Fetch all issue comments** — For `issues` and `issue_comment` events, optionally call the GitHub API to list all comments on the issue and include them in the assessment payload (not only the single comment from the event).
90+
2. **Optional comment when PR is created** — Input `post_pr_comment` exists; when true, post a short comment on the issue linking to the new PR when one is created.
91+
3. **Local run with fixture and Claude**`npm run assess:fixture` exists; optional end-to-end testing with real `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`.
92+
93+
Done: context files in assess, implement step (Claude Code CLI), implement–verify loop with re-implement on failure, PR review iteration (comment on PR, no new PR), comment when retries exhausted, secrets/variables and README docs, local assess script.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Diagnosis: PR #261 — Bot replied "Verification passed" instead of adding tests
2+
3+
## What happened
4+
5+
- **PR #261** added `--local` to `login` and `ci` (auto-implement from issue #215).
6+
- **Reviewer comment:** "Could we add some unit and acceptance test coverage for this change?"
7+
- **Bot response:** "The --local flag has already been implemented... Verification passed." — no new tests were added.
8+
9+
## Root cause: review feedback never reaches the implement step
10+
11+
The pipeline has two steps that use Claude:
12+
13+
1. **Assess** (`assess/src/index.ts`) — decides `implement` vs `request_info`, outputs `verification_notes`.
14+
2. **Implement** (`assess/src/implement.ts`) — runs Claude Code CLI in the repo to make changes.
15+
16+
**Assess** receives the full event payload. For a comment on the PR (`issue_comment` on the PR, or `pull_request_review`), the prompt includes:
17+
- Issue (for a PR comment: the PR title and body),
18+
- "All issue comments" (PR comments from the API),
19+
- "Latest event comment" or "PR review (address this feedback):" with the reviewer's text.
20+
21+
So assess **does** see "Could we add some unit and acceptance test coverage for this change?" and correctly returns `action: implement`.
22+
23+
**Implement** only receives:
24+
- `ISSUE_NUMBER` (215),
25+
- Issue title/body **fetched from the GitHub API for issue #215** (the original issue about `--local`),
26+
- `VERIFICATION_NOTES` (from assess: generic "run test suite" style notes),
27+
- Context files, `PREVIOUS_VERIFY_OUTPUT`.
28+
29+
So implement **never** sees the PR comment or review body. The Claude Code CLI prompt is built from the **original issue** only. It has no instruction to "add unit and acceptance tests" — so it reasonably treats the issue as already done and writes `.comment_body` ("Verification passed") instead of making code changes.
30+
31+
## Why it wasn't "enough coverage"
32+
33+
The bot didn't decide there was "enough coverage." It never had the reviewer's ask in the implement prompt. So it didn't consider coverage at all; it only had the original issue text.
34+
35+
## Design gap
36+
37+
AGENTS.md says: *"assess with issue + review/comment content → implement ('address review feedback')"*. The **assess** step does get review/comment content, but that content is **not** passed through to **implement**. So "address review feedback" is not possible with the current wiring.
38+
39+
## Fix (implemented in this worktree)
40+
41+
1. **Assess** — When the trigger is PR review or a comment on a PR, derive the review/comment text from the payload and add it to the assessment JSON output as `review_feedback` (so the workflow can pass it on).
42+
2. **Action** — Expose `review_feedback` from the assess step and pass it to the implement step as `REVIEW_FEEDBACK`.
43+
3. **Implement** — Read `REVIEW_FEEDBACK`; when set, add a clear section to the Claude Code CLI prompt: **"Review feedback to address (you must implement this):"** so the CLI actually implements the reviewer's request (e.g. add unit and acceptance tests).
44+
45+
After this change, a comment like "Could we add some unit and acceptance test coverage for this change?" will be passed into the implement prompt, and the implement step will be instructed to address it, so the bot should add tests instead of replying with "Verification passed."

0 commit comments

Comments
 (0)