diff --git a/.amazonq/rules/triage-findings.md b/.amazonq/rules/triage-findings.md index 4b65ce1..b25f7ad 100644 --- a/.amazonq/rules/triage-findings.md +++ b/.amazonq/rules/triage-findings.md @@ -11,4 +11,3 @@ When the task is to triage review findings, follow this workflow: 7. Add or update tests when behavior changes. 8. Re-check the issue after each fix. -Use the repo-local `triage-findings` skill for the same workflow when running in Codex. diff --git a/.antigravity/skills/triage-findings/SKILL.md b/.antigravity/skills/triage-findings/SKILL.md new file mode 100644 index 0000000..2422e52 --- /dev/null +++ b/.antigravity/skills/triage-findings/SKILL.md @@ -0,0 +1,46 @@ +--- +name: triage-findings +description: Merge code-review findings, sort and renumber them by severity, resolve real issues, and move false positives into exclusions. +--- + +# Triage Findings + +## When To Use + +Use this skill when you receive multiple review findings, screenshots, comments, or issue lists that need to become one final triaged list. +It is also used when some findings are false positives and should be moved into the exclusions list. + +## Workflow + +1. Collect all findings into one list. +2. Merge duplicates into a single finding when they describe the same issue. +3. Sort the final list by severity: + - critical + - warning + - info +4. Renumber the sorted list from 1 upward. +5. Rewrite each finding concisely so the final list reads cleanly and consistently. +6. If a finding is a false positive, do not keep it in the final list. +7. Add false positives to the exclusions list as a top-level JSON array in `.gitea/ai-review/exclusions.json`, and preserve the original finding wording as much as possible, including language and semantics. Do not wrap the array in `exclusions` or `excluded_findings`. + +## Resolution Flow + +After the list is merged and ordered, resolve the remaining findings one by one. + +1. Start from the highest severity item. +2. Identify the root cause in the relevant file or context. +3. Apply the smallest safe change that fixes the issue. +4. Add or update tests when behavior changes. +5. Re-check the issue after the change. +6. If the item is confirmed false positive, move it to exclusions instead of changing code. +7. Continue until the list is either fixed or explicitly excluded. + +## Output Rules + +- Keep the final findings list in severity order, then by any stable secondary order needed to make it readable. +- Keep numbering contiguous after filtering and merging. +- Preserve useful details like file path, location, and suggested fix. +- Keep exclusions entries minimal and consistent with the project schema. +- When writing exclusions, always output a top-level JSON array. +- When writing exclusions, prefer the original issue text and language; only paraphrase if needed to fit the schema. +- If the source already provides a severity or title, keep it unless it conflicts with the final ordering. diff --git a/.claude/skills/triage-findings/SKILL.md b/.claude/skills/triage-findings/SKILL.md index 2bfa16f..2422e52 100644 --- a/.claude/skills/triage-findings/SKILL.md +++ b/.claude/skills/triage-findings/SKILL.md @@ -1,30 +1,46 @@ --- name: triage-findings -description: Triage findings, fix real issues, and exclude false positives. +description: Merge code-review findings, sort and renumber them by severity, resolve real issues, and move false positives into exclusions. --- # Triage Findings -## Use +## When To Use -直接輸入:`triage-findings 問題原始檔(文字或截圖)` +Use this skill when you receive multiple review findings, screenshots, comments, or issue lists that need to become one final triaged list. +It is also used when some findings are false positives and should be moved into the exclusions list. ## Workflow -1. Merge all findings. -2. Sort by severity: +1. Collect all findings into one list. +2. Merge duplicates into a single finding when they describe the same issue. +3. Sort the final list by severity: - critical - warning - info -3. Renumber from 1. -4. Fix real issues. -5. Put false positives into `.gitea/ai-review/exclusions.json` as a top-level JSON array, preserving the original wording, language, and semantics as much as possible. Do not wrap the array in `exclusions` or `excluded_findings`. -6. Add tests when behavior changes. +4. Renumber the sorted list from 1 upward. +5. Rewrite each finding concisely so the final list reads cleanly and consistently. +6. If a finding is a false positive, do not keep it in the final list. +7. Add false positives to the exclusions list as a top-level JSON array in `.gitea/ai-review/exclusions.json`, and preserve the original finding wording as much as possible, including language and semantics. Do not wrap the array in `exclusions` or `excluded_findings`. + +## Resolution Flow + +After the list is merged and ordered, resolve the remaining findings one by one. + +1. Start from the highest severity item. +2. Identify the root cause in the relevant file or context. +3. Apply the smallest safe change that fixes the issue. +4. Add or update tests when behavior changes. +5. Re-check the issue after the change. +6. If the item is confirmed false positive, move it to exclusions instead of changing code. +7. Continue until the list is either fixed or explicitly excluded. ## Output Rules -- Keep the final list short. -- Keep numbering contiguous. -- Preserve file path, location, and fix. +- Keep the final findings list in severity order, then by any stable secondary order needed to make it readable. +- Keep numbering contiguous after filtering and merging. +- Preserve useful details like file path, location, and suggested fix. +- Keep exclusions entries minimal and consistent with the project schema. - When writing exclusions, always output a top-level JSON array. -- When writing exclusions, prefer the original issue text over paraphrased rewrites. +- When writing exclusions, prefer the original issue text and language; only paraphrase if needed to fit the schema. +- If the source already provides a severity or title, keep it unless it conflicts with the final ordering. diff --git a/.gemini/skills/triage-findings/SKILL.md b/.gemini/skills/triage-findings/SKILL.md index 2bfa16f..2422e52 100644 --- a/.gemini/skills/triage-findings/SKILL.md +++ b/.gemini/skills/triage-findings/SKILL.md @@ -1,30 +1,46 @@ --- name: triage-findings -description: Triage findings, fix real issues, and exclude false positives. +description: Merge code-review findings, sort and renumber them by severity, resolve real issues, and move false positives into exclusions. --- # Triage Findings -## Use +## When To Use -直接輸入:`triage-findings 問題原始檔(文字或截圖)` +Use this skill when you receive multiple review findings, screenshots, comments, or issue lists that need to become one final triaged list. +It is also used when some findings are false positives and should be moved into the exclusions list. ## Workflow -1. Merge all findings. -2. Sort by severity: +1. Collect all findings into one list. +2. Merge duplicates into a single finding when they describe the same issue. +3. Sort the final list by severity: - critical - warning - info -3. Renumber from 1. -4. Fix real issues. -5. Put false positives into `.gitea/ai-review/exclusions.json` as a top-level JSON array, preserving the original wording, language, and semantics as much as possible. Do not wrap the array in `exclusions` or `excluded_findings`. -6. Add tests when behavior changes. +4. Renumber the sorted list from 1 upward. +5. Rewrite each finding concisely so the final list reads cleanly and consistently. +6. If a finding is a false positive, do not keep it in the final list. +7. Add false positives to the exclusions list as a top-level JSON array in `.gitea/ai-review/exclusions.json`, and preserve the original finding wording as much as possible, including language and semantics. Do not wrap the array in `exclusions` or `excluded_findings`. + +## Resolution Flow + +After the list is merged and ordered, resolve the remaining findings one by one. + +1. Start from the highest severity item. +2. Identify the root cause in the relevant file or context. +3. Apply the smallest safe change that fixes the issue. +4. Add or update tests when behavior changes. +5. Re-check the issue after the change. +6. If the item is confirmed false positive, move it to exclusions instead of changing code. +7. Continue until the list is either fixed or explicitly excluded. ## Output Rules -- Keep the final list short. -- Keep numbering contiguous. -- Preserve file path, location, and fix. +- Keep the final findings list in severity order, then by any stable secondary order needed to make it readable. +- Keep numbering contiguous after filtering and merging. +- Preserve useful details like file path, location, and suggested fix. +- Keep exclusions entries minimal and consistent with the project schema. - When writing exclusions, always output a top-level JSON array. -- When writing exclusions, prefer the original issue text over paraphrased rewrites. +- When writing exclusions, prefer the original issue text and language; only paraphrase if needed to fit the schema. +- If the source already provides a severity or title, keep it unless it conflicts with the final ordering. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f1a77ef..ca2d3a9 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -11,4 +11,4 @@ Use the triage-finding workflow for review issue lists: 7. Add or update tests when behavior changes. 8. Re-check after each fix. -The full reusable skill lives in `.claude/skills/triage-findings/SKILL.md`. +The full reusable skill lives in `.github/skills/triage-findings/SKILL.md`. diff --git a/.github/skills/triage-findings/SKILL.md b/.github/skills/triage-findings/SKILL.md index 42932fc..d747008 100644 --- a/.github/skills/triage-findings/SKILL.md +++ b/.github/skills/triage-findings/SKILL.md @@ -1,14 +1,41 @@ # Triage Findings -Use the triage-finding workflow for review issue lists: +## When To Use -1. Merge findings into one list. -2. Remove duplicates. -3. Sort by severity: `critical` -> `warning` -> `info`. -4. Renumber from 1. -5. Fix real issues with the smallest safe change. -6. Put false positives into `.gitea/ai-review/exclusions.json` as a top-level JSON array, preserving the original wording, language, and semantics as much as possible. Do not wrap the array in `exclusions` or `excluded_findings`. -7. Add or update tests when behavior changes. -8. Re-check after each fix. +Use this skill when you receive multiple review findings, screenshots, comments, or issue lists that need to become one final triaged list. +It is also used when some findings are false positives and should be moved into the exclusions list. -The reusable skill lives in `.gemini/skills/triage-findings/SKILL.md`. +## Workflow + +1. Collect all findings into one list. +2. Merge duplicates into a single finding when they describe the same issue. +3. Sort the final list by severity: + - critical + - warning + - info +4. Renumber the sorted list from 1 upward. +5. Rewrite each finding concisely so the final list reads cleanly and consistently. +6. If a finding is a false positive, do not keep it in the final list. +7. Add false positives to the exclusions list as a top-level JSON array in `.gitea/ai-review/exclusions.json`, and preserve the original finding wording as much as possible, including language and semantics. Do not wrap the array in `exclusions` or `excluded_findings`. + +## Resolution Flow + +After the list is merged and ordered, resolve the remaining findings one by one. + +1. Start from the highest severity item. +2. Identify the root cause in the relevant file or context. +3. Apply the smallest safe change that fixes the issue. +4. Add or update tests when behavior changes. +5. Re-check the issue after the change. +6. If the item is confirmed false positive, move it to exclusions instead of changing code. +7. Continue until the list is either fixed or explicitly excluded. + +## Output Rules + +- Keep the final findings list in severity order, then by any stable secondary order needed to make it readable. +- Keep numbering contiguous after filtering and merging. +- Preserve useful details like file path, location, and suggested fix. +- Keep exclusions entries minimal and consistent with the project schema. +- When writing exclusions, always output a top-level JSON array. +- When writing exclusions, prefer the original issue text and language; only paraphrase if needed to fit the schema. +- If the source already provides a severity or title, keep it unless it conflicts with the final ordering. diff --git a/ANTIGRAVITY.md b/ANTIGRAVITY.md new file mode 100644 index 0000000..70b8f1d --- /dev/null +++ b/ANTIGRAVITY.md @@ -0,0 +1,14 @@ +# Triage Findings + +Use the triage-finding workflow for review issue lists: + +1. Merge findings into one list. +2. Remove duplicates. +3. Sort by severity: `critical` -> `warning` -> `info`. +4. Renumber from 1. +5. Fix real issues with the smallest safe change. +6. Put false positives into `.gitea/ai-review/exclusions.json`, preserving the original wording, language, and semantics as much as possible. +7. Add or update tests when behavior changes. +8. Re-check after each fix. + +The reusable skill lives in `.antigravity/skills/triage-findings/SKILL.md`. diff --git a/CLAUDE.md b/CLAUDE.md index fa2403d..e1c3938 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,6 @@ When the task is to triage review findings, follow this workflow: 7. Add or update tests when behavior changes. 8. Re-check the issue after each fix. -Use the repo-local `triage-findings` skill for the same workflow when running in Codex. +Use the repo-local `triage-findings` skill for the same workflow when running in Claude. Trigger it with `/triage-findings`. diff --git a/README.md b/README.md index 0442546..e04b31a 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ 4. 盡量將應用程式放在 ./app,修改 entrypoint.sh 與 Dockerfile 讓程式可以正常運行 5. 將提示詞放到 ./app/prompts 內供程式讀取 6. API Key 支援逗號分隔傳入多個,隨機順序各嘗試一次,全部失敗則 exit 1 -7. 讀取 Git Diff 時排除 `.gitea/`、`.amazonq/`、`.claude/`、`.codex/`、`.gemini/`、`.github/` 資料夾,以及 `CLAUDE.md`、`GEMINI.md`、`TODO.md`、`README.md`,避免 AI 分析 workflow 設定、skill 入口與文件等非業務程式碼 +7. 讀取 Git Diff 時排除 `.gitea/`、`.amazonq/`、`.antigravity/`、`.claude/`、`.codex/`、`.gemini/`、`.github/` 資料夾,以及 `ANTIGRAVITY.md`、`CLAUDE.md`、`GEMINI.md`、`TODO.md`、`README.md`,避免 AI 分析 workflow 設定、skill 入口與文件等非業務程式碼 8. 階段七驗證來源分支中的 `findings.json` 與 `exclusions.json` 是否為合法 JSON 格式,格式錯誤時先嘗試透過 AI 修正內容,再重新驗證;修正後仍不合法才 exit 1;之後才檢查檔案是否存在,不存在則建立並寫入 `[]` 9. 傳給 AI 的 findings 只保留必要欄位(level、role、location、suggestion),排除 `is_new` 等內部欄位;system prompt 精簡為指令核心;exclusions hint 只傳 location 與 suggestion,減少 token 用量 10. 執行時會額外記錄來源分支狀態、`findings.json` / `exclusions.json` 的檔案路徑、大小、mtime 與 raw/normalized 筆數,方便追查讀檔與分支內容不一致的問題 @@ -235,6 +235,7 @@ Copilot:`/triage-findings 問題原始檔(文字或截圖)` Claude:直接輸入 `triage-findings 問題原始檔(文字或截圖)` Gemini:直接輸入 `triage-findings 問題原始檔(文字或截圖)` Amazon Q:直接輸入 `triage-findings 問題原始檔(文字或截圖)` +Antigravity:直接輸入 `triage-findings 問題原始檔(文字或截圖)` ### 適用情境 diff --git a/TODO.md b/TODO.md index f0e8ec7..05dba85 100644 --- a/TODO.md +++ b/TODO.md @@ -6,7 +6,7 @@ - 已驗收:`code-review` job 的 log 已完整出現 `Step1` 到 `Step8`,並以 `Pipeline 完成` 結束。 ## 階段二:Git Diff 排除 .gitea/ 資料夾 -- 目標:讀取 Git Diff 時排除 `.gitea/` 資料夾內的所有檔案,以及 `.amazonq/`、`.claude/`、`.codex/`、`.gemini/`、`.github/`、`CLAUDE.md`、`GEMINI.md`、`TODO.md`、`README.md`,避免 AI 分析 workflow 設定、skill 入口與文件等非業務程式碼。 +- 目標:讀取 Git Diff 時排除 `.gitea/` 資料夾內的所有檔案,以及 `.amazonq/`、`.antigravity/`、`.claude/`、`.codex/`、`.gemini/`、`.github/`、`ANTIGRAVITY.md`、`CLAUDE.md`、`GEMINI.md`、`TODO.md`、`README.md`,避免 AI 分析 workflow 設定、skill 入口與文件等非業務程式碼。 - 驗收:PR 中有上述路徑或檔案的變更時,diff 內容不包含該區塊,AI 分析結果不含這些路徑相關問題。 - 已驗收:`app/gitea.js` 已在取得 diff 時過濾 `.gitea/` 區塊,且相關單元測試已覆蓋。 diff --git a/app/git.js b/app/git.js index 36a06f6..9d00444 100644 --- a/app/git.js +++ b/app/git.js @@ -11,21 +11,25 @@ const remoteUrl = `${GITEA_SERVER_URL.replace(/\/$/, '')}/${GITEA_REPOSITORY}.gi export const BOT_COMMIT_MARKER = '[ai-review-bot]'; export const SYNC_PATHS = [ '.amazonq/rules/triage-findings.md', + '.antigravity/skills/triage-findings/SKILL.md', '.codex/skills/triage-findings/SKILL.md', '.codex/skills/triage-findings/agents/openai.yaml', '.claude/skills/triage-findings/SKILL.md', '.gemini/skills/triage-findings/SKILL.md', '.github/copilot-instructions.md', '.github/skills/triage-findings/SKILL.md', + 'ANTIGRAVITY.md', 'CLAUDE.md', 'GEMINI.md', ]; const FORCE_SYNC_FILE_PATHS = [ '.github/copilot-instructions.md', + 'ANTIGRAVITY.md', 'CLAUDE.md', 'GEMINI.md', ]; const SYNC_TREE_PATHS = [ + '.antigravity/skills/triage-findings', '.codex/skills/triage-findings', '.claude/skills/triage-findings', '.gemini/skills/triage-findings', diff --git a/app/git.test.js b/app/git.test.js index f70d2c5..9d919b5 100644 --- a/app/git.test.js +++ b/app/git.test.js @@ -132,8 +132,10 @@ describe('commitAndPush', () => { assert.ok(skillAddCall.args.includes('.codex/skills/triage-findings/agents/openai.yaml')); assert.ok(skillAddCall.args.includes('.claude/skills/triage-findings/SKILL.md')); assert.ok(skillAddCall.args.includes('.gemini/skills/triage-findings/SKILL.md')); + assert.ok(skillAddCall.args.includes('.antigravity/skills/triage-findings/SKILL.md')); assert.ok(skillAddCall.args.includes('.github/copilot-instructions.md')); assert.ok(skillAddCall.args.includes('.amazonq/rules/triage-findings.md')); + assert.ok(skillAddCall.args.includes('ANTIGRAVITY.md')); assert.ok(skillAddCall.args.includes('CLAUDE.md')); assert.ok(skillAddCall.args.includes('GEMINI.md')); assert.ok(!skillAddCall.args.includes('README.md')); @@ -158,6 +160,7 @@ describe('commitAndPush', () => { it('overwrites existing repo copies with workspace files', async () => { const repoDir = path.join(workspace, 'repo'); fs.writeFileSync(path.join(repoDir, '.github/skills/triage-findings/SKILL.md'), 'stale'); + fs.writeFileSync(path.join(repoDir, 'ANTIGRAVITY.md'), 'stale'); fs.writeFileSync(path.join(repoDir, 'CLAUDE.md'), 'stale'); fs.writeFileSync(path.join(repoDir, 'GEMINI.md'), 'stale'); fs.writeFileSync(path.join(repoDir, '.github/copilot-instructions.md'), 'stale'); @@ -165,6 +168,7 @@ describe('commitAndPush', () => { await commitAndPush(workspace, repoDir, makeSpawn(), sourceRoot); assert.equal(fs.readFileSync(path.join(repoDir, '.github/skills/triage-findings/SKILL.md'), 'utf8'), '.github/skills/triage-findings/SKILL.md'); + assert.equal(fs.readFileSync(path.join(repoDir, 'ANTIGRAVITY.md'), 'utf8'), 'ANTIGRAVITY.md'); assert.equal(fs.readFileSync(path.join(repoDir, 'CLAUDE.md'), 'utf8'), 'CLAUDE.md'); assert.equal(fs.readFileSync(path.join(repoDir, 'GEMINI.md'), 'utf8'), 'GEMINI.md'); assert.equal(fs.readFileSync(path.join(repoDir, '.github/copilot-instructions.md'), 'utf8'), '.github/copilot-instructions.md'); diff --git a/app/gitea.js b/app/gitea.js index 66b484c..65c2025 100644 --- a/app/gitea.js +++ b/app/gitea.js @@ -26,11 +26,13 @@ export async function getPRDiff() { const resp = await axios.get(api(`/repos/${GITEA_REPOSITORY}/pulls/${PR_NUMBER}.diff`), { headers: headers(), timeout: 60000, httpsAgent }); return filterDiff(resp.data, [ '.amazonq/', + '.antigravity/', '.claude/', '.codex/', '.gemini/', '.gitea/', '.github/', + 'ANTIGRAVITY.md', 'CLAUDE.md', 'GEMINI.md', 'README.md',