Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 18 additions & 34 deletions .agents/skills/code-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
name: code-review
description: >
Performs thorough code reviews on GitHub PRs and submits the review directly to GitHub via the gh CLI.
Use this agent when you want an automated, structured code review submitted as a PR comment.
Reviews GitHub PRs and submits code-specific findings as inline review comments, with an overall review summary.
Use when you want a structured code review posted directly to GitHub.
Invoke with a PR number (e.g., "Review PR #123").
argument-hint: '<PR-number>'
---
Expand Down Expand Up @@ -60,13 +60,15 @@ Parse the output to understand the scope, author, and target branch.
- Also fetch existing comments and review threads on the PR itself:
```
gh pr view <number> --repo <repo> --json comments,reviews
gh api repos/{owner}/{repo}/pulls/{number}/comments --paginate
```
- Use this context to understand the original requirements, prior discussion, decisions already made, and any concerns raised by other reviewers. Avoid repeating feedback that has already been addressed.
- Use this context to understand the original requirements, prior discussion, decisions already made, and any concerns raised by other reviewers. Avoid repeating feedback that has already been addressed in inline threads.

### 3. Read project conventions

Look for project convention files in common locations and read whatever exists:

- `AGENTS.md` (root and relevant package directories)
- `CLAUDE.md` (root)
- `.claude/` directory (settings, skills, hooks)
- `docs/` or `docs/conventions.md`
Expand Down Expand Up @@ -131,57 +133,39 @@ Evaluate the changes for:

### 8. Write the review

Write the review body to a file called `pr_review_body.md` at the project root. Use this format:
Attach each distinct code-specific finding to the smallest relevant changed line or range in the PR diff. Post one inline comment per affected code block, not a list of file and line references in the review body. Mark its severity clearly (Must Fix, Should Consider, or Optional), explain the consequence, and give a concrete correction when possible. Use a multi-line range for a finding that spans one block. Check anchors against `gh api repos/{owner}/{repo}/pulls/{number}/files --paginate`: `line` must fall inside a hunk's new-side range for `RIGHT` (context lines count), or its old-side range for `LEFT`; `position` is a diff offset, not a file line number. If a file's patch is unavailable or truncated, do not guess an anchor.

```markdown
### Issues (Must Fix)
Write a concise overall review body in `pr_review_body.md`. Put only the verdict and cross-cutting observations that cannot be attached to a diff block there. Do not duplicate the inline findings in that body.

1. **[File:Line]** Description of the bug/security issue/breaking change
2. **[File:Line]** …
### 9. Submit the review with inline comments

### Suggestions (Should Consider)
Build `pr_review_payload.json` with a JSON serializer so multi-line text is escaped correctly. Get the PR author from step 1 and your login from `gh api user --jq .login`. Set `event` to `COMMENT` on your own PR (GitHub rejects self-approval and self-requested changes); otherwise use `REQUEST_CHANGES` if any Must Fix finding exists or `APPROVE` if not. Set `body` to the review body and `comments` to the code-specific findings. Each comment needs `path`, `line`, `side` (`RIGHT` for the new side or `LEFT` for the old side), and `body`. Add `start_line` and `start_side` for a multi-line range. Use one review submission so the body and inline comments are posted together:

3. **[File:Line]** Description of the improvement opportunity
4. **[File:Line]** …

### Nitpicks (Optional)

5. **[File:Line]** Minor style or preference notes
```bash
gh api repos/{owner}/{repo}/pulls/{number}/reviews \
--method POST --input pr_review_payload.json
```

Number items **continuously across all sections** β€” do not restart at 1 for each section.
Omit any section that has no items (e.g., if there are no Issues, skip that section entirely).

### 9. Submit the review

Choose the appropriate flag based on the review outcome:

- If there are **no Issues (Must Fix)** items β†’ approve:
```
gh pr review <number> --repo <repo> --approve --body-file pr_review_body.md
```
- If there are **any Issues (Must Fix)** items β†’ request changes:
```
gh pr review <number> --repo <repo> --request-changes --body-file pr_review_body.md
```
If a finding has no valid anchor in the current diff, keep it in the overall body instead of inventing a line. Review submission is atomic: if GitHub returns 422 for an invalid anchor, no part of that review was posted. Move all unposted inline findings into the body, regenerate the payload without inline comments, and retry body-only; report which findings could not be anchored. For other errors, report the failure rather than claiming the review was posted. Check the submitted review and inline comments on GitHub before reporting completion.

### 10. Clean up

Delete both temporary files, whether the submission succeeded or failed:
Delete all temporary files, whether submission succeeded or failed:

- `tmp_pr_diff.txt`
- `pr_review_body.md`
- `pr_review_payload.json`

### 11. Confirm

Report back to the user that the review was submitted, including the PR URL.

## Important Rules

- **Write all review content in English** β€” `pr_review_body.md` must be in English regardless of the conversation language.
- **Write all review content in English** β€” both `pr_review_body.md` and inline comments must be in English regardless of the conversation language.
- **NEVER** present the review as chat text. The review MUST be submitted to GitHub.
- **ALWAYS** use temporary files for multi-line CLI content (the `--body-file` pattern). Never pass review content inline.
- **ALWAYS** use temporary files for multi-line review text and JSON payloads. Never pass review content inline on the command line.
- **ALWAYS** clean up temporary files after submission, even if it failed.
- **Be thorough but respectful.** Critique the code, not the author. Use phrases like "Consider..." or "This might..." rather than "You should..." or "This is wrong."
- **Reference specific files and line numbers** whenever possible so the author can locate issues quickly.
- **Anchor code-specific findings to their diff lines** rather than naming their locations in the review body.
- **Check steering files first** β€” don't flag something as a convention violation unless it actually violates the project's documented conventions.
55 changes: 37 additions & 18 deletions .agents/skills/fix-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: fix-review
description: Given a PR number, find the latest change-request comment from someone else, judge whether it's worth applying, fix what's relevant, push, and reply on the PR explaining what was fixed and what wasn't (and why).
description: Given a PR number, address actionable reviewer feedback across review summaries, general comments, and inline threads; fix relevant asks, push, and reply in each thread or on the PR.
argument-hint: "<pr-number>"
---

Expand Down Expand Up @@ -40,21 +40,45 @@ gh api repos/{owner}/{repo}/pulls/{pr-number}/reviews --paginate # review
gh api repos/{owner}/{repo}/pulls/{pr-number}/comments --paginate # inline review comments (path/line/diff_hunk)
```

Merge all entries by `created_at`/`submitted_at`, drop anything authored by your own login (from step 0).
Merge entries by `created_at`/`submitted_at`. Group inline comments with their replies using `in_reply_to_id`, and check whether each thread is resolved (GitHub GraphQL exposes `reviewThreads.isResolved`). Keep your own replies as context, but do not treat them as reviewer asks. Paginate all sources; a newer summary does not replace inline threads.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should Consider β€” the resolved check has no command, unlike every other source in this step.

Step 3 depends on it ("Skip resolved, superseded, or already addressed asks"), but reviewThreads.isResolved is not reachable from the two REST calls above, and the parenthetical is the only pointer. Consider giving the query outright so the step is executable:

gh api graphql -f query='
  query($owner:String!,$repo:String!,$pr:Int!){
    repository(owner:$owner,name:$repo){
      pullRequest(number:$pr){
        reviewThreads(first:100){
          nodes{ isResolved isOutdated comments(first:1){ nodes{ databaseId } } }
        }
      }
    }
  }' -F owner=... -F repo=... -F pr=...

The first comment's databaseId is also the top-level comment ID that step 7 needs for /comments/{id}/replies, so one query covers both.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed: fix-review now includes an executable GraphQL query returning isResolved, isOutdated, and each thread's top-level databaseId, with explicit cursor pagination guidance.


## 3. Identify the target comment
To map REST comments to thread state, query GraphQL for each thread's top-level
comment ID. Paginate the query if `hasNextPage` is true, using `endCursor` as
the next `$cursor`; an outdated thread is not necessarily resolved:

Walk backward from the most recent non-self entry. Pick the most recent one that is **actually actionable** β€” a review with `state: CHANGES_REQUESTED`, an inline comment pointing at specific code, or a general comment with a concrete ask. Skip over comments that are just acknowledgements, questions with no ask, or approvals β€” don't stop at the newest comment just because it's newest if it has nothing to act on.
```bash
gh api graphql -f query='
query($owner:String!, $repo:String!, $pr:Int!, $cursor:String) {
repository(owner:$owner, name:$repo) {
pullRequest(number:$pr) {
reviewThreads(first:100, after:$cursor) {
nodes {
isResolved
isOutdated
comments(first:1) { nodes { databaseId } }
}
pageInfo { hasNextPage endCursor }
}
}
}
}' -F owner=<owner> -F repo=<repo> -F pr=<pr-number>
```

## 3. Identify all feedback to address

If no qualifying comment exists at all, tell the user and stop β€” do not invent work.
- Read every unresolved, actionable inline thread from another reviewer, including comments on older commits. Check its replies and the current code before treating it as outstanding.
- Read review bodies and general PR comments for concrete asks. Use the latest actionable comment as the complete checklist **only if it explicitly summarizes all points**. Otherwise include earlier, independent asks too.
- Group duplicate asks so each fix is implemented once, but keep track of every thread that needs an answer. Skip resolved, superseded, or already addressed asks only after verifying their status and current code.

If no actionable feedback exists, tell the user and stop β€” do not invent work.

## 4. Evaluate relevance before touching anything

A comment may bundle several distinct asks β€” treat each one separately. For each:

- Read the referenced code (inline comments carry `path` + `line`/`diff_hunk` β€” read the current state of that file, not just the diff hunk, since the PR may have moved on).
- Judge it against this project's conventions (`AGENTS.md`) and the actual current code β€” not against how easy it is to apply.
- If an ask is ambiguous, conflicts with a documented convention, requires a product/design call, or its intent doesn't survive contact with the current code β€” **stop and ask the user** (`AskUserQuestion` or plain text) instead of guessing. Never silently skip an ask without recording why, and never silently implement a guess for something unclear.
- If an ask is ambiguous, conflicts with a documented convention, requires a product/design call, or its intent doesn't survive contact with the current code, ask the user instead of guessing while continuing independent asks. Never silently skip an ask without recording why.

## 5. Fix what's relevant

Expand All @@ -72,29 +96,24 @@ git push

Keep it in one commit unless the fixes are clearly unrelated to each other.

## 7. Reply on the PR

Write in English (project convention). For each ask from the target comment, state the outcome plainly β€” no filler:

- βœ… Fixed β€” what changed, in a sentence.
- ⏭️ Not fixed β€” the specific reason (out of scope, conflicts with `<convention>`, needs a decision, etc.).
## 7. Reply where each ask was made

If the target was an **inline review comment**, reply inside its thread so context is preserved:
Write in English (project convention). For each inline thread, reply with what changed or why the ask was not applied. Reply to the **top-level comment ID**, even when the latest message is a reply, using a JSON file containing `{"body": "<reply>"}`:

```bash
gh api repos/{owner}/{repo}/pulls/{pr-number}/comments \
-f body="<reply>" -F in_reply_to=<original_comment_id> --method POST
gh api repos/{owner}/{repo}/pulls/{pr-number}/comments/{top-level-comment-id}/replies \
--method POST --input reply.json
```

If it was a **general comment** or a **review body** with no single inline comment to thread on, post a normal PR comment instead:
For a general PR comment or review body, post a normal PR comment that addresses its distinct asks. A summary comment may report the overall result, but it does not replace replies in the relevant inline threads:

```bash
gh pr comment <pr-number> --body-file reply_body.md
```

Clean up any temp body file afterward.
State each outcome plainly: fixed and how, or not fixed and the specific reason. Clean up temporary reply files afterward.

## Notes

- If nothing in the target comment is actually actionable after evaluation (all asks rejected), still commit nothing, skip step 6, and post the reply explaining why each ask was declined.
- If none of the asks survives evaluation, commit nothing, skip step 6, and reply where each ask was made with its reason.
- Never touch comments authored by the user themselves, and never treat their own follow-up remarks as something to "resolve."
47 changes: 40 additions & 7 deletions .agents/skills/github-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ gh auth status
> - Windows: `winget install --id GitHub.cli`
> - Linux: https://github.com/cli/cli/blob/trunk/docs/install_linux.md

- If `gh` is **not authenticated**, stop and tell the user to run `gh auth login`.
- On Windows, credentials may be hidden inside the sandbox. Run commands
sandboxed first; if an authenticated `gh` command or Git network operation
fails due to an auth or credential error, retry that command with escalated
permissions before asking.
- If `gh` is still **not authenticated**, stop and tell the user to run
`gh auth login`.
- Do not print remote URLs: `git remote -v` and
`git config --get remote.origin.url` may expose an embedded token.
Use `gh repo view` to identify the repository.

## Language

Expand All @@ -30,9 +38,9 @@ All generated content (PR titles, PR bodies, issue comments) must be written in

Format: `type(scope): description`

Types: `feat` `fix` `refactor` `test` `docs` `chore` `style` `ci`
Scope: domain area β€” `cave`, `entrance`, `massif`, `auth`, `search`, `deps`, …
Example: `feat(massif): add area validation`
Use the types and scope casing in the repository's `AGENTS.md`.

Example: `feat(Massif): add area validation`

## Branching

Expand All @@ -53,18 +61,43 @@ In the `## πŸ§ͺ Testing` section, write every test or verification as a GitHub
checklist item. Use `- [x]` only for checks that were actually run and passed,
and `- [ ]` for checks that are pending or were not run.

**2. Show and confirm** β€” display the title and the **actual content of `pr_body.md`** to the user and **wait for explicit approval before proceeding**. Do not push or create the PR until the user confirms. The file must already exist on disk before asking for confirmation.
**2. Show and confirm** β€” display the title and the **actual content of
`pr_body.md`** to the user. If the user has already explicitly authorized
pushing and creating the PR, proceed. Otherwise wait for explicit approval.
The file must already exist on disk before asking for confirmation.

**3. Push and create:**

Identify the authenticated account with `gh api user --jq .login` before
creating the PR or requesting reviews. If the command fails or returns an
empty login, stop after the authentication recovery above; do not continue
with an unknown author. Compare reviewer logins to the author
case-insensitively.

The commands below work in bash and PowerShell. Create and assign the PR
first, then request each eligible reviewer separately. Omit a reviewer
command if that login is the PR author or already has a pending request.
If creation fails, stop; if it succeeds, use the returned PR number for
the review requests. If a reviewer request fails, report it and continue
with the other eligible reviewer and the verification below.

```bash
git push origin <branch-name>
gh pr create --title "<type(scope): description>" --body-file pr_body.md --base develop --repo <repo>
gh pr create --title "<type(scope): description>" --body-file pr_body.md --base develop --repo <repo> --assignee "@me"
gh pr edit <pr-number> --repo <repo> --add-reviewer ClemRz
gh pr edit <pr-number> --repo <repo> --add-reviewer urien
```

Where `<repo>` is detected via `gh repo view --json nameWithOwner -q .nameWithOwner`.

**3. Clean up:**
For an existing PR, add only missing reviewers
other than the PR author with `gh pr edit <pr-number> --add-reviewer <login>
--add-assignee "@me"`; avoid re-requesting a review from someone already
requested. Verify the result with
`gh pr view <pr-number> --repo <repo> --json reviewRequests,assignees`.
Report any GitHub rejection instead of silently leaving the PR unassigned.

**4. Clean up:**

```bash
# bash/zsh
Expand Down
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,15 @@ yarn translations:sync-with-en # Do or check sync with en.json
yarn outdated # Check outdated dependencies
```

On Windows PowerShell, use `yarn.cmd` if execution policy blocks `yarn.ps1`.
If Node reports `EPERM` while reading the user profile inside the sandbox,
retry the same verification outside the sandbox before treating it as a code
failure. If Vitest reaches its default timeout on a slow machine, rerun the
affected test first; for a loaded full suite, limit workers and raise the
timeout explicitly, for example with
`yarn.cmd test --run --maxWorkers=2 --testTimeout=15000`. Report the command
used so a longer timeout does not hide a failing test.

---

## πŸ€– AI Agent Checklist
Expand Down
Loading