Skip to content

Commit df26396

Browse files
committed
Merge branch 'main' into paulnjs-fix/78264
2 parents 2a1697f + a152afa commit df26396

430 files changed

Lines changed: 7837 additions & 2781 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/agents/code-inline-reviewer.md

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
name: code-inline-reviewer
44
description: Reviews code and creates inline comments for specific rule violations.
5-
tools: Glob, Grep, Read, TodoWrite, Bash, BashOutput, KillBash
5+
tools: Glob, Grep, Read, Bash, BashOutput
66
model: inherit
77
---
88

@@ -41,49 +41,26 @@ Each rule file contains:
4141
- **For large files (>5000 lines):** Use the Grep tool with Search Patterns from each rule's Review Metadata to locate potential violations. Focus on changed portions shown in the diff.
4242
- **For smaller files:** You may read the full file using the Read tool
4343
- **If a Read fails with token limit error:** Immediately switch to using Grep with targeted patterns for the rules you're checking
44-
- For each rule: evaluate the Condition and "DO NOT flag" exceptions. Mark the rule as checked on the checklist. A single rule **can produce multiple violations** — flag each separately.
45-
5. **For each violation found, immediately create an inline comment** using the available GitHub inline comment tool. Do not batch — create the comment as soon as you confirm a violation.
46-
6. **Required parameters for each inline comment:**
47-
- `path`: Full file path (e.g., "src/components/ReportActionsList.tsx")
44+
3. **Search strategy for large files:** Use the search patterns defined in each rule's "Search patterns" field to efficiently locate potential violations with Grep.
45+
4. **Return your findings as structured JSON output.** Your response must be a JSON object matching this schema:
46+
```json
47+
{ "violations": [ { "ruleId": "...", "path": "...", "line": ..., "body": "..." } ] }
48+
```
49+
- `ruleId`: The rule ID (e.g., `PERF-1`, `CONSISTENCY-2`)
50+
- `path`: Full file path (e.g., `src/components/ReportActionsList.tsx`)
4851
- `line`: Line number where the issue occurs
49-
- `body`: Concise and actionable description of the violation and fix, following the below Comment Format
50-
7. **Each comment must reference exactly one Rule ID.**
51-
8. **Output must consist exclusively of calls to createInlineComment.sh in the required format.** No other text, Markdown, or prose is allowed.
52-
9. **If no violations are found, add a reaction to the PR**:
53-
Add a +1 reaction to the PR using the `addPrReaction` script (available in PATH from `.claude/scripts/`). The script takes ONLY the PR number as argument - it always adds a "+1" reaction, so do NOT pass any reaction type or emoji.
54-
10. **Add reaction if and only if**:
55-
- You examined EVERY changed line in EVERY changed file (via diff + targeted grep/read)
56-
- You checked EVERY changed file against ALL rules
57-
- You found ZERO violations matching the exact rule criteria
58-
- You verified no false negatives by checking each rule systematically
59-
If you found even ONE violation or have ANY uncertainty do NOT add the reaction - create inline comments instead.
60-
11. **DO NOT invent new rules, stylistic preferences, or commentary outside the listed rules.**
61-
12. **DO NOT describe what you are doing, create comments with a summary, explanations, extra content, comments on rules that are NOT violated or ANYTHING ELSE.**
62-
Only inline comments regarding rules violations are allowed. If no violations are found, add a reaction instead of creating any comment.
63-
EXCEPTION: If you believe something MIGHT be a Rule violation but are uncertain, err on the side of creating an inline comment with your concern rather than skipping it.
64-
13. **Reality check before posting**: Before creating each inline comment, re-read the specific code one more time and confirm the violation is real. If upon re-reading you realize the code is actually correct, **do NOT post the comment** — silently skip it and move on. Never post a comment that flags a violation and then concludes it is not actually a problem.
65-
66-
## Tool Usage Example
67-
68-
For each violation, call the createInlineComment.sh script like this:
69-
70-
```bash
71-
createInlineComment.sh 'src/components/ReportActionsList.tsx' '<Body of the comment according to the Comment Format>' 128
72-
```
73-
74-
**IMPORTANT**: Always use single quotes around the body argument to properly handle special characters and quotes.
75-
76-
If ZERO violations are found, use the Bash tool to add a reaction to the PR body:
77-
78-
```bash
79-
addPrReaction.sh <PR_NUMBER>
80-
```
81-
82-
**IMPORTANT**: Always use the `addPrReaction.sh` script (available in PATH from `.claude/scripts/`) instead of calling `gh api` directly.
52+
- `body`: Concise and actionable description of the violation and fix, formatted per the Comment Format below
53+
5. **Each violation must reference exactly one Rule ID.**
54+
6. **If no violations are found, return an empty violations array:** `{ "violations": [] }`
55+
7. **Do NOT post comments, call scripts, or add reactions.** Only return the structured JSON.
56+
8. **DO NOT invent new rules, stylistic preferences, or commentary outside the listed rules.**
57+
9. **DO NOT describe what you are doing or add extra content.**
58+
EXCEPTION: If you believe something MIGHT be a Rule violation but are uncertain, err on the side of including it in the violations array rather than skipping it.
59+
10. **Reality check before posting**: Before creating each inline comment, re-read the specific code one more time and confirm the violation is real. If upon re-reading you realize the code is actually correct, **do NOT post the comment** — silently skip it and move on. Never post a comment that flags a violation and then concludes it is not actually a problem.
8360

8461
## Comment Format
8562

86-
Build the docs link by mapping the ruleId to its rule filename:
63+
Use this format for the `body` field of each violation:
8764

8865
```
8966
### ❌ <Rule ID> [(docs)](https://github.com/Expensify/App/blob/main/.claude/skills/coding-standards/rules/<rule-filename>.md)
@@ -92,8 +69,3 @@ Build the docs link by mapping the ruleId to its rule filename:
9269
9370
<Suggested, specific fix preferably with a code snippet>
9471
```
95-
96-
For example, a PERF-1 violation links to:
97-
`https://github.com/Expensify/App/blob/main/.claude/skills/coding-standards/rules/perf-1-no-spread-in-renderitem.md`
98-
99-
**CRITICAL**: You must actually call the createInlineComment.sh script for each violation. Don't just describe what you found - create the actual inline comments!

.claude/commands/review-code-pr.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
allowed-tools: Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(addPrReaction.sh:*),Bash(createInlineComment.sh:*)
2+
allowed-tools: Bash(gh pr diff:*),Bash(gh pr view:*)
33
description: Review a code contribution pull request
44
---
55

@@ -8,10 +8,13 @@ Perform a comprehensive PR review using a specialized subagent:
88
## Inline Review
99
Use the code-inline-reviewer agent to:
1010
- Scan all changed source code files
11-
- Create inline comments for specific review rule violations
12-
- Focus on line-specific, actionable feedback
11+
- Detect review rule violations with line-specific, actionable feedback
1312

14-
Run the agent and ensure its feedback is posted to the PR.
13+
Run the agent. It will return structured JSON with any violations found.
14+
15+
## Output
16+
Return the subagent's violations JSON as your structured output unchanged.
17+
Do NOT post comments or reactions yourself - the workflow handles that.
1518

1619
<important>
1720
Keep feedback concise.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"violations": {
5+
"type": "array",
6+
"items": {
7+
"type": "object",
8+
"properties": {
9+
"ruleId": {
10+
"type": "string"
11+
},
12+
"path": {
13+
"type": "string"
14+
},
15+
"line": {
16+
"type": "integer"
17+
},
18+
"body": {
19+
"type": "string"
20+
}
21+
},
22+
"required": ["ruleId", "path", "line", "body"]
23+
}
24+
}
25+
},
26+
"required": ["violations"]
27+
}

.github/actions/javascript/authorChecklist/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16018,6 +16018,20 @@ class GithubUtils {
1601816018
})
1601916019
.then(({ data: pullRequestComment }) => pullRequestComment.body);
1602016020
}
16021+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
16022+
const { data: pullRequest } = await this.octokit.pulls.get({
16023+
owner: CONST_1.default.GITHUB_OWNER,
16024+
repo: CONST_1.default.APP_REPO,
16025+
pull_number: pullRequestNumber,
16026+
});
16027+
const { data: comparison } = await this.octokit.repos.compareCommits({
16028+
owner: CONST_1.default.GITHUB_OWNER,
16029+
repo: CONST_1.default.APP_REPO,
16030+
base: pullRequest.base.ref,
16031+
head: pullRequest.head.sha,
16032+
});
16033+
return comparison.merge_base_commit.sha;
16034+
}
1602116035
static getAllReviewComments(pullRequestNumber) {
1602216036
return this.paginate(this.octokit.pulls.listReviews, {
1602316037
owner: CONST_1.default.GITHUB_OWNER,

.github/actions/javascript/awaitStagingDeploys/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12796,6 +12796,20 @@ class GithubUtils {
1279612796
})
1279712797
.then(({ data: pullRequestComment }) => pullRequestComment.body);
1279812798
}
12799+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
12800+
const { data: pullRequest } = await this.octokit.pulls.get({
12801+
owner: CONST_1.default.GITHUB_OWNER,
12802+
repo: CONST_1.default.APP_REPO,
12803+
pull_number: pullRequestNumber,
12804+
});
12805+
const { data: comparison } = await this.octokit.repos.compareCommits({
12806+
owner: CONST_1.default.GITHUB_OWNER,
12807+
repo: CONST_1.default.APP_REPO,
12808+
base: pullRequest.base.ref,
12809+
head: pullRequest.head.sha,
12810+
});
12811+
return comparison.merge_base_commit.sha;
12812+
}
1279912813
static getAllReviewComments(pullRequestNumber) {
1280012814
return this.paginate(this.octokit.pulls.listReviews, {
1280112815
owner: CONST_1.default.GITHUB_OWNER,

.github/actions/javascript/checkAndroidStatus/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737539,6 +737539,20 @@ class GithubUtils {
737539737539
})
737540737540
.then(({ data: pullRequestComment }) => pullRequestComment.body);
737541737541
}
737542+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
737543+
const { data: pullRequest } = await this.octokit.pulls.get({
737544+
owner: CONST_1.default.GITHUB_OWNER,
737545+
repo: CONST_1.default.APP_REPO,
737546+
pull_number: pullRequestNumber,
737547+
});
737548+
const { data: comparison } = await this.octokit.repos.compareCommits({
737549+
owner: CONST_1.default.GITHUB_OWNER,
737550+
repo: CONST_1.default.APP_REPO,
737551+
base: pullRequest.base.ref,
737552+
head: pullRequest.head.sha,
737553+
});
737554+
return comparison.merge_base_commit.sha;
737555+
}
737542737556
static getAllReviewComments(pullRequestNumber) {
737543737557
return this.paginate(this.octokit.pulls.listReviews, {
737544737558
owner: CONST_1.default.GITHUB_OWNER,

.github/actions/javascript/checkDeployBlockers/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12063,6 +12063,20 @@ class GithubUtils {
1206312063
})
1206412064
.then(({ data: pullRequestComment }) => pullRequestComment.body);
1206512065
}
12066+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
12067+
const { data: pullRequest } = await this.octokit.pulls.get({
12068+
owner: CONST_1.default.GITHUB_OWNER,
12069+
repo: CONST_1.default.APP_REPO,
12070+
pull_number: pullRequestNumber,
12071+
});
12072+
const { data: comparison } = await this.octokit.repos.compareCommits({
12073+
owner: CONST_1.default.GITHUB_OWNER,
12074+
repo: CONST_1.default.APP_REPO,
12075+
base: pullRequest.base.ref,
12076+
head: pullRequest.head.sha,
12077+
});
12078+
return comparison.merge_base_commit.sha;
12079+
}
1206612080
static getAllReviewComments(pullRequestNumber) {
1206712081
return this.paginate(this.octokit.pulls.listReviews, {
1206812082
owner: CONST_1.default.GITHUB_OWNER,

.github/actions/javascript/checkSVGCompression/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20588,6 +20588,20 @@ class GithubUtils {
2058820588
})
2058920589
.then(({ data: pullRequestComment }) => pullRequestComment.body);
2059020590
}
20591+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
20592+
const { data: pullRequest } = await this.octokit.pulls.get({
20593+
owner: CONST_1.default.GITHUB_OWNER,
20594+
repo: CONST_1.default.APP_REPO,
20595+
pull_number: pullRequestNumber,
20596+
});
20597+
const { data: comparison } = await this.octokit.repos.compareCommits({
20598+
owner: CONST_1.default.GITHUB_OWNER,
20599+
repo: CONST_1.default.APP_REPO,
20600+
base: pullRequest.base.ref,
20601+
head: pullRequest.head.sha,
20602+
});
20603+
return comparison.merge_base_commit.sha;
20604+
}
2059120605
static getAllReviewComments(pullRequestNumber) {
2059220606
return this.paginate(this.octokit.pulls.listReviews, {
2059320607
owner: CONST_1.default.GITHUB_OWNER,

.github/actions/javascript/createOrUpdateStagingDeploy/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12479,6 +12479,20 @@ class GithubUtils {
1247912479
})
1248012480
.then(({ data: pullRequestComment }) => pullRequestComment.body);
1248112481
}
12482+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
12483+
const { data: pullRequest } = await this.octokit.pulls.get({
12484+
owner: CONST_1.default.GITHUB_OWNER,
12485+
repo: CONST_1.default.APP_REPO,
12486+
pull_number: pullRequestNumber,
12487+
});
12488+
const { data: comparison } = await this.octokit.repos.compareCommits({
12489+
owner: CONST_1.default.GITHUB_OWNER,
12490+
repo: CONST_1.default.APP_REPO,
12491+
base: pullRequest.base.ref,
12492+
head: pullRequest.head.sha,
12493+
});
12494+
return comparison.merge_base_commit.sha;
12495+
}
1248212496
static getAllReviewComments(pullRequestNumber) {
1248312497
return this.paginate(this.octokit.pulls.listReviews, {
1248412498
owner: CONST_1.default.GITHUB_OWNER,

.github/actions/javascript/formatCodeCovComment/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12250,6 +12250,20 @@ class GithubUtils {
1225012250
})
1225112251
.then(({ data: pullRequestComment }) => pullRequestComment.body);
1225212252
}
12253+
static async getPullRequestMergeBaseSHA(pullRequestNumber) {
12254+
const { data: pullRequest } = await this.octokit.pulls.get({
12255+
owner: CONST_1.default.GITHUB_OWNER,
12256+
repo: CONST_1.default.APP_REPO,
12257+
pull_number: pullRequestNumber,
12258+
});
12259+
const { data: comparison } = await this.octokit.repos.compareCommits({
12260+
owner: CONST_1.default.GITHUB_OWNER,
12261+
repo: CONST_1.default.APP_REPO,
12262+
base: pullRequest.base.ref,
12263+
head: pullRequest.head.sha,
12264+
});
12265+
return comparison.merge_base_commit.sha;
12266+
}
1225312267
static getAllReviewComments(pullRequestNumber) {
1225412268
return this.paginate(this.octokit.pulls.listReviews, {
1225512269
owner: CONST_1.default.GITHUB_OWNER,

0 commit comments

Comments
 (0)