[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CSY57NSXY4RY8Q2GD5C561":3,"skill-same:01M6CSY57NSXY4RY8Q2GD5C561":69},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":32,"linkOnly":33,"markdownContent":34,"markdownBody":35,"frontMatter":36,"refName":39,"commitSha":40,"skillDirectory":41,"forksCount":14,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":44,"ownerDescription":6,"updatedAt":45,"install":46,"resources":58},"01M6CSY57NSXY4RY8Q2GD5C561","pr-audit",null,"Deep reviewer-side audit of an open PR (by number\u002FURL) — clone+build, cross-file caller tracing, compare with Copilot, post inline + summary review.","goffity\u002Fdev-km","goffity","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F778547?v=4","01M6CSW9QQ32YQYTRKQWVKYCAY","Goffity","01M6CSW9VQFVZ3QS6RB4VYJGE6",0,"MIT","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fpr-audit\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31],"pr","audit","pr audit","review","copilot","open pr","file","tracing","open","reviewer","repo","build","summary","2026-11-10 10:12:30",false,"---\nname: pr-audit\ndescription: Deep reviewer-side audit of an open PR (by number\u002FURL) — clone+build, cross-file caller tracing, compare with Copilot, post inline + summary review.\nargument-hint: \"[pr-number|url] [--mode] [--lang] [--repo owner\u002Fname]\"\nuser-invocable: true\n---\n\n# PR Audit (Reviewer-Side Deep Review)\n\nรีวิว PR ที่เปิดค้างอยู่ **ในฐานะ reviewer** แบบเชิงลึก — clone + build จริง, ไล่ caller ข้ามไฟล์,\nเทียบกับ Copilot\u002Freviewer อื่น แล้วโพสต์ inline conversation + summary review ขึ้น GitHub\n\n> ต่างจาก `\u002Fpr` (สร้าง PR ใหม่), `\u002Fpr-review` (จัดการ feedback บน PR **ของตัวเอง**), `\u002Freview` (รีวิว local diff ก่อน push)\n> `\u002Fpr-audit` = ออกรีวิว PR ของคนอื่นฝั่ง reviewer\n\n## Usage\n\n```\n\u002Fpr-audit 351                       # รีวิว PR #351 ใน repo ปัจจุบัน (ถามโหมดตอนเริ่ม)\n\u002Fpr-audit https:\u002F\u002Fgithub.com\u002Fo\u002Fr\u002Fpull\u002F351\n\u002Fpr-audit 642 --repo owner\u002Fname     # รีวิวข้าม repo\n\u002Fpr-audit 351 --mode=comment --lang=th   # โพสต์ลง PR เป็นภาษาไทย\n\u002Fpr-audit 351 --mode=review              # ดูอย่างเดียว ไม่โพสต์\n```\n\n## Options\n\n| Option | ค่า | Default | ความหมาย |\n|--------|-----|---------|----------|\n| `--mode` | `review` \\| `comment` | ถามตอนเริ่ม | `review` = ดู\u002Fรายงานใน chat อย่างเดียว, `comment` = โพสต์ inline + summary ลง PR |\n| `--lang` | `th` \\| `en` | `th` | ภาษาของ comment ที่โพสต์ (เทียบ `references\u002Flanguage-guide.md`) |\n| `--repo` | `owner\u002Fname` | repo ปัจจุบัน | รีวิว PR ข้าม repo |\n\n## Instructions\n\n### Language Setting\n\n> Default `--lang=th`. ถ้าไม่ระบุ ตรวจ `LANGUAGE` ใน `docs\u002Fcurrent.md` ด้วย แล้ว fallback เป็น `th`.\n> แปล output ที่ผู้ใช้เห็น\u002Fcomment ที่โพสต์ตาม `references\u002Flanguage-guide.md`.\n> **คงเป็น English เสมอ:** code, commit hash, file path, line number, technical terms\n\n### Step 0: Parse Arguments & Resolve PR\n\n```bash\n# แยก pr-number \u002F url \u002F flags จาก $ARGUMENTS\n# ตั้ง REPO_FLAG=\"--repo owner\u002Fname\" ถ้ามี --repo หรือ url ข้าม repo\nPR=\u003Cpr-number>\nREPO_FLAG=\"\"   # เช่น \"--repo owner\u002Fname\"\n\n# ดึง metadata\ngh pr view $PR $REPO_FLAG --json number,title,url,headRefName,baseRefName,headRepository,headRepositoryOwner,state,author,additions,deletions,changedFiles,mergeable\n```\n\nถ้า `--mode` ไม่ระบุ → **ถาม user** ก่อนว่าจะ `review` (ดูอย่างเดียว) หรือ `comment` (โพสต์ลง PR)\n\n### Step 1: Fetch Diff & File List (กรอง noise)\n\n```bash\n# รายชื่อไฟล์ที่เปลี่ยน\ngh pr diff $PR $REPO_FLAG --name-only\n\n# ดู diff เต็ม (ข้าม lock\u002Fgenerated\u002Fvendor)\ngh pr diff $PR $REPO_FLAG\n```\n\n**กรองออกจากการ deep-review** (แต่ยังนับว่ามีการเปลี่ยน): `*.lock`, `go.sum`, `package-lock.json`,\n`*_gen.go`, `*.pb.go`, `dist\u002F`, `vendor\u002F`, `node_modules\u002F`, generated\u002Fsnapshot files\n\n### Step 2: Clone \u002F Worktree the PR Branch (ไม่แตะ working tree หลัก)\n\n> **Safety:** ห้ามแตะ branch ปัจจุบัน — ใช้ worktree แยก และ cleanup เสมอ (ดู Step 8)\n\n```bash\n# stash ของหลักไว้ก่อน (กันพลาด) — ถ้ามี uncommitted\ngit stash push -m \"pr-audit-autostash\" 2>\u002Fdev\u002Fnull || true\n\n# สร้าง worktree แยกสำหรับ branch ของ PR\nWT=$(mktemp -d -t pr-audit-$PR-XXXX)\ngit fetch origin pull\u002F$PR\u002Fhead:pr-audit-$PR 2>\u002Fdev\u002Fnull \\\n  || gh pr checkout $PR $REPO_FLAG --branch pr-audit-$PR   # cross-repo fallback\ngit worktree add \"$WT\" pr-audit-$PR\necho \"Worktree: $WT\"\n```\n\n> ข้าม repo (`--repo`): ถ้า PR มาจาก fork ใช้ `gh pr checkout` ซึ่งจัดการ remote ของ fork ให้\n\n### Step 3: Build + Test — **ทำทุกครั้ง (ไม่ optional)**\n\nใช้ **`build-validator`** subagent บน worktree — ห้ามเขียน build heuristic ซ้ำ\n\n```\nใช้ Task tool subagent_type=\"build-validator\":\n\"Detect project type in \u003CWT> and run build + tests + lint.\nReport PASS\u002FFAIL per check with logs. Working dir: \u003CWT>.\"\n```\n\n- ถ้า build\u002Ftest **ไม่ผ่าน** → บันทึกเป็น finding ระดับ **CRITICAL** พร้อม log (ไม่หยุด flow — รายงานต่อ)\n- ผลลัพธ์ build\u002Ftest ใช้ยืนยัน finding (ดู KB-first ข้อ Step 5 — เช่น dup-import ที่ build ผ่าน)\n\n### Step 4: Deep Review — ไล่ caller ข้ามไฟล์ + cross-layer wiring\n\nใช้ **`code-reviewer`** subagent หา bug\u002Fsecurity\u002Fperf — ห้ามเขียน heuristic ซ้ำ\n\n```\nใช้ Task tool subagent_type=\"code-reviewer\":\n\"Review the diff of PR #\u003CPR> at \u003CWT> vs base \u003CbaseRef>.\nBeyond per-file issues, trace cross-file wiring:\n- caller → callee across files (signature\u002Fcontract drift)\n- cross-layer flow (e.g. CI workflow → Dockerfile ARG → app env → runtime)\n- config\u002Fproto\u002Fschema changes vs their consumers\nReturn findings with severity (CRITICAL\u002FWARNING\u002FINFO), file:line, evidence, suggested fix.\"\n```\n\nเพิ่มการตรวจ cross-layer ที่ subagent มักพลาด (ไล่เองด้วย grep ใน worktree):\n- workflow\u002FCI → Dockerfile (`ARG`\u002F`ENV`) → app — ค่าที่ส่งผ่านครบไหม (เช่น `ARG SITE` หาย → multi-site ไม่สลับธีม)\n- migration\u002Fschema → repository\u002Fquery layer\n- proto\u002Finterface → ทั้ง server และ client implementations\n\n### Step 5: KB-First Policy (ก่อน flag known-pattern)\n\nก่อนจะ flag finding ที่เป็น \"known pattern\" ให้ค้น KB ก่อน:\n\n```bash\ngrep -ri \"\u003Ckeyword>\" kb\u002F02-patterns\u002F kb\u002F03-bugs\u002F kb\u002F02-patterns\u002Fanti-patterns\u002F 2>\u002Fdev\u002Fnull\n```\n\n- **มี entry ตรง** → ทำตาม KB (ปรับ severity\u002Fคำแนะนำตามที่ KB สรุปไว้)\n- **ไม่มี entry** → **หยุดถาม user** + เสนอแนะ แล้วบันทึกเป็น memory\u002FKB ใหม่หลังจบ (Step 9)\n\n**Known-pattern ที่ต้องระวัง** (ดู [known-patterns.md](known-patterns.md)):\n- **dup-import**: import module path เดียวกันคนละ alias → Go **คอมไพล์ได้** อย่า flag เป็น compile error\n  จนกว่าจะ build ยืนยัน (Step 3) — ดู known-patterns.md\n- **money-flow-false-critical**: ก่อน flag CRITICAL double-credit\u002Fdouble-spend\u002Fidempotency บน money flow\n  (deposit\u002Fwithdraw\u002Ftransfer) → ตรวจ DB constraint จริงรวม **child partition indexes** (partial unique index\n  บน partition ไม่โผล่ที่ parent `pg_indexes` และไม่มีใน ORM tag; ใช้ readonly DB MCP ถ้ามี) + ไล่ atomicity\n  ชั้นล่างสุด (tx wrapper รอบ credit+history-insert → rollback ทำ ordering ปลอดภัย) ก่อนโพสต์ — ดู known-patterns.md\n\n### Step 6: Compare with Copilot \u002F Other Reviews\n\n```bash\n# ดึง reviews + review comments ที่มีอยู่\ngh pr view $PR $REPO_FLAG --json reviews,comments\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F$PR\u002Fcomments --jq '.[] | {id, path, line, user: .user.login, body}'\n```\n\n- **ตัด finding ที่ซ้ำ** กับ Copilot\u002Freviewer อื่น (ไม่โพสต์ซ้ำ)\n- **ที่ไม่เห็นด้วย** → reply ที่ comment นั้นโดยตรงพร้อม **หลักฐาน** (build log \u002F file:line \u002F KB entry)\n\n### Step 6.5: Resolve Verified-Fixed Threads (re-audit — เมื่อ author แก้ตามรอบก่อนแล้ว)\n\nเมื่อ **re-audit** PR ที่เคย audit ไปแล้ว (มี inline thread ของเราค้าง) และ author ตอบ `Fixed in \u003Ccommit>`:\n\n1. **Delta-first** — audit เฉพาะส่วนที่เปลี่ยนตั้งแต่ SHA ที่ audit รอบก่อน (`git diff \u003Cprev_audited_sha>..HEAD --stat`) แทน re-run ทั้ง PR; แต่ยัง build\u002Ftest บน HEAD ปัจจุบันเสมอ (Step 3)\n2. **Verify ทุก thread กับโค้ด HEAD ก่อนเสมอ** — อย่าเชื่อคำเคลม \"Fixed\" ลอยๆ; อ่านโค้ด\u002Fรัน test ยืนยันว่า fix นั้นแก้ finding เดิมจริง (money-flow → ยังต้องผ่าน DB check ของ Step 5)\n3. **Resolve เฉพาะที่พิสูจน์ได้** ผ่าน GraphQL `resolveReviewThread` (REST ไม่มี resolve)\n4. **ห้าม resolve** thread ที่ author แค่ `Acknowledged \u002F deferred \u002F by-design \u002F จะแยก ticket` — พวกนี้เป็น **open decision\u002Flimitation ไม่ใช่ fix**; ปล่อย unresolved ไว้ให้เห็น แล้วสรุปเป็น follow-up ใน summary\n\n```bash\n# 1) list unresolved threads + author replies (แยก resolved จริง vs ค้าง)\ngh api graphql -f query='\n{ repository(owner:\"\u003Cowner>\", name:\"\u003Crepo>\") {\n    pullRequest(number:\u003CPR>) {\n      reviewThreads(first:50){ nodes{\n        id isResolved isOutdated path line\n        comments(first:10){ nodes{ author{login} body } }\n      }}}}}' --jq '.data.repository.pullRequest.reviewThreads.nodes[]\n        | select(.isResolved==false)\n        | {id, path, line, finding: .comments.nodes[0].body[0:120],\n           replies: [.comments.nodes[1:][] | \"(\\(.author.login)) \\(.body[0:160])\"]}'\n\n# 2) resolve เฉพาะ thread ที่ verify แล้ว — เรียกแยกทีละ id\ngh api graphql -f query='mutation($id: ID!){\n  resolveReviewThread(input:{threadId:$id}){ thread{ id isResolved } }\n}' -f id=\"\u003CPRRT_thread_id>\"\n```\n\n> **Shell caveat:** อย่าใช้ loop `for x in $VAR` กับ thread id หลายตัว — fish\u002Fbash word-split ต่างกัน ทำให้ id ทั้งชุดถูกส่งเป็น id เดียว (`NOT_FOUND`); เรียก mutation แยกทีละ id ปลอดภัยสุด\n> สรุปใน chat\u002Fsummary ว่า resolve อันไหนบ้าง (พร้อมหลักฐาน) + คงอันไหนไว้ (เพราะเป็น open item) เพื่อ trace\n\n### Step 7: Output\n\n#### Mode = review (ดูอย่างเดียว)\nแสดง report ใน chat:\n\n```markdown\n## PR Audit #[number]: [title]   ([owner\u002Frepo])\n\n**Build\u002FTest:** PASS \u002F FAIL (รายละเอียด)\n**Findings:** [N] CRITICAL · [N] WARNING · [N] INFO  (ตัดซ้ำ Copilot [N] รายการ)\n\n### CRITICAL\n- `file:line` — [issue] · evidence: [...] · fix: [...]\n\n### WARNING \u002F INFO\n- ...\n\n### vs Copilot\n- เห็นด้วย: [...]\n- ไม่เห็นด้วย: [comment_id] — [เหตุผล + หลักฐาน]\n```\n\n#### Mode = comment (โพสต์ลง PR)\n1. **Inline conversation** ต่อจุดโค้ด (ผูก commit_id + path + line):\n\n```bash\nHEAD_SHA=$(gh pr view $PR $REPO_FLAG --json headRefOid --jq .headRefOid)\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F$PR\u002Fcomments \\\n  -f body=\"[finding + suggested fix]\" \\\n  -f commit_id=\"$HEAD_SHA\" \\\n  -f path=\"\u003Cfile>\" \\\n  -F line=\u003Cline> \\\n  -f side=\"RIGHT\"\n```\n\n2. **Summary review comment** รวมทุกอย่าง (ภาษาตาม `--lang`):\n\n```bash\ngh pr review $PR $REPO_FLAG --comment --body \"$(cat \u003C\u003C'EOF'\n## PR Audit Summary\n- Build\u002FTest: [PASS\u002FFAIL]\n- CRITICAL: [N] · WARNING: [N] · INFO: [N]\n- [สรุป findings สำคัญ + cross-file issues]\nEOF\n)\"\n```\n\n> เลือก `--comment` (ไม่ block) เป็น default. ใช้ `--request-changes` เฉพาะเมื่อมี CRITICAL และ user ยืนยัน\n> **หมายเหตุ:** submitted review **ลบไม่ได้** (แก้ body ได้), inline comment ลบได้ — โพสต์อย่างระมัดระวัง\n\n### Step 8: Cleanup (เสมอ — แม้ flow ล้มเหลว)\n\n```bash\ngit worktree remove \"$WT\" --force 2>\u002Fdev\u002Fnull\ngit branch -D pr-audit-$PR 2>\u002Fdev\u002Fnull\nrm -rf \"$WT\" 2>\u002Fdev\u002Fnull\ngit stash pop 2>\u002Fdev\u002Fnull || true   # คืน working tree เดิม\n```\n\n### Step 9: Update KB (pattern ใหม่)\n\nถ้าเจอ pattern\u002Fanti-pattern ใหม่ที่ยังไม่มีใน KB (Step 5) → บันทึก:\n- เป็น learning: `kb\u002F05-ai-reviewed\u002Flearnings\u002FYYYY-MM\u002FDD\u002FHH.MM_[slug].md` หรือ\n- เป็น anti-pattern entry ใน `kb\u002F02-patterns\u002Fanti-patterns\u002F`\n\n## Safety Rules (ตาม workspace rules)\n\n| Rule | Detail |\n|------|--------|\n| ห้ามลบไฟล์ผู้ใช้ | review เท่านั้น |\n| ห้าม force push \u002F ห้ามแก้ branch ของ PR | reviewer ไม่ push |\n| stash ก่อนสลับ\u002Fcleanup | คืน working tree เดิมเสมอ |\n| ห้าม commit ลง main\u002Fdevelop | ไม่มี commit ในการ audit |\n| cleanup worktree เสมอ | แม้ build ล้มเหลว (Step 8) |\n| GitHub comments | submitted review ลบไม่ได้ (แก้ body ได้), inline ลบได้ |\n| resolve thread ต้อง verify ก่อน | resolve เฉพาะ thread ที่พิสูจน์ว่าแก้จริงในโค้ด HEAD (Step 6.5); ห้าม resolve open item ที่ author แค่ acknowledge\u002Fdefer\u002Fby-design |\n\n## Reuse (ห้ามเขียน heuristic ซ้ำ)\n\n| ต้องการ | เรียก |\n|---------|-------|\n| หา bug\u002Fsecurity\u002Fperf | `code-reviewer` subagent |\n| build\u002Ftest\u002Flint | `build-validator` subagent |\n| ภาษา output | `references\u002Flanguage-guide.md` |\n\n## Related Commands\n\n| Command | Purpose |\n|---------|---------|\n| `\u002Fpr` | สร้าง PR ใหม่ (ฝั่ง author) |\n| `\u002Fpr-review` | จัดการ feedback บน PR ของตัวเอง |\n| `\u002Freview` | รีวิว local diff ก่อน push |\n| `\u002Fpr-audit` | รีวิว PR คนอื่นเชิงลึกฝั่ง reviewer (คุณอยู่ที่นี่) |\n","# PR Audit (Reviewer-Side Deep Review)\n\nรีวิว PR ที่เปิดค้างอยู่ **ในฐานะ reviewer** แบบเชิงลึก — clone + build จริง, ไล่ caller ข้ามไฟล์,\nเทียบกับ Copilot\u002Freviewer อื่น แล้วโพสต์ inline conversation + summary review ขึ้น GitHub\n\n> ต่างจาก `\u002Fpr` (สร้าง PR ใหม่), `\u002Fpr-review` (จัดการ feedback บน PR **ของตัวเอง**), `\u002Freview` (รีวิว local diff ก่อน push)\n> `\u002Fpr-audit` = ออกรีวิว PR ของคนอื่นฝั่ง reviewer\n\n## Usage\n\n```\n\u002Fpr-audit 351                       # รีวิว PR #351 ใน repo ปัจจุบัน (ถามโหมดตอนเริ่ม)\n\u002Fpr-audit https:\u002F\u002Fgithub.com\u002Fo\u002Fr\u002Fpull\u002F351\n\u002Fpr-audit 642 --repo owner\u002Fname     # รีวิวข้าม repo\n\u002Fpr-audit 351 --mode=comment --lang=th   # โพสต์ลง PR เป็นภาษาไทย\n\u002Fpr-audit 351 --mode=review              # ดูอย่างเดียว ไม่โพสต์\n```\n\n## Options\n\n| Option | ค่า | Default | ความหมาย |\n|--------|-----|---------|----------|\n| `--mode` | `review` \\| `comment` | ถามตอนเริ่ม | `review` = ดู\u002Fรายงานใน chat อย่างเดียว, `comment` = โพสต์ inline + summary ลง PR |\n| `--lang` | `th` \\| `en` | `th` | ภาษาของ comment ที่โพสต์ (เทียบ `references\u002Flanguage-guide.md`) |\n| `--repo` | `owner\u002Fname` | repo ปัจจุบัน | รีวิว PR ข้าม repo |\n\n## Instructions\n\n### Language Setting\n\n> Default `--lang=th`. ถ้าไม่ระบุ ตรวจ `LANGUAGE` ใน `docs\u002Fcurrent.md` ด้วย แล้ว fallback เป็น `th`.\n> แปล output ที่ผู้ใช้เห็น\u002Fcomment ที่โพสต์ตาม `references\u002Flanguage-guide.md`.\n> **คงเป็น English เสมอ:** code, commit hash, file path, line number, technical terms\n\n### Step 0: Parse Arguments & Resolve PR\n\n```bash\n# แยก pr-number \u002F url \u002F flags จาก $ARGUMENTS\n# ตั้ง REPO_FLAG=\"--repo owner\u002Fname\" ถ้ามี --repo หรือ url ข้าม repo\nPR=\u003Cpr-number>\nREPO_FLAG=\"\"   # เช่น \"--repo owner\u002Fname\"\n\n# ดึง metadata\ngh pr view $PR $REPO_FLAG --json number,title,url,headRefName,baseRefName,headRepository,headRepositoryOwner,state,author,additions,deletions,changedFiles,mergeable\n```\n\nถ้า `--mode` ไม่ระบุ → **ถาม user** ก่อนว่าจะ `review` (ดูอย่างเดียว) หรือ `comment` (โพสต์ลง PR)\n\n### Step 1: Fetch Diff & File List (กรอง noise)\n\n```bash\n# รายชื่อไฟล์ที่เปลี่ยน\ngh pr diff $PR $REPO_FLAG --name-only\n\n# ดู diff เต็ม (ข้าม lock\u002Fgenerated\u002Fvendor)\ngh pr diff $PR $REPO_FLAG\n```\n\n**กรองออกจากการ deep-review** (แต่ยังนับว่ามีการเปลี่ยน): `*.lock`, `go.sum`, `package-lock.json`,\n`*_gen.go`, `*.pb.go`, `dist\u002F`, `vendor\u002F`, `node_modules\u002F`, generated\u002Fsnapshot files\n\n### Step 2: Clone \u002F Worktree the PR Branch (ไม่แตะ working tree หลัก)\n\n> **Safety:** ห้ามแตะ branch ปัจจุบัน — ใช้ worktree แยก และ cleanup เสมอ (ดู Step 8)\n\n```bash\n# stash ของหลักไว้ก่อน (กันพลาด) — ถ้ามี uncommitted\ngit stash push -m \"pr-audit-autostash\" 2>\u002Fdev\u002Fnull || true\n\n# สร้าง worktree แยกสำหรับ branch ของ PR\nWT=$(mktemp -d -t pr-audit-$PR-XXXX)\ngit fetch origin pull\u002F$PR\u002Fhead:pr-audit-$PR 2>\u002Fdev\u002Fnull \\\n  || gh pr checkout $PR $REPO_FLAG --branch pr-audit-$PR   # cross-repo fallback\ngit worktree add \"$WT\" pr-audit-$PR\necho \"Worktree: $WT\"\n```\n\n> ข้าม repo (`--repo`): ถ้า PR มาจาก fork ใช้ `gh pr checkout` ซึ่งจัดการ remote ของ fork ให้\n\n### Step 3: Build + Test — **ทำทุกครั้ง (ไม่ optional)**\n\nใช้ **`build-validator`** subagent บน worktree — ห้ามเขียน build heuristic ซ้ำ\n\n```\nใช้ Task tool subagent_type=\"build-validator\":\n\"Detect project type in \u003CWT> and run build + tests + lint.\nReport PASS\u002FFAIL per check with logs. Working dir: \u003CWT>.\"\n```\n\n- ถ้า build\u002Ftest **ไม่ผ่าน** → บันทึกเป็น finding ระดับ **CRITICAL** พร้อม log (ไม่หยุด flow — รายงานต่อ)\n- ผลลัพธ์ build\u002Ftest ใช้ยืนยัน finding (ดู KB-first ข้อ Step 5 — เช่น dup-import ที่ build ผ่าน)\n\n### Step 4: Deep Review — ไล่ caller ข้ามไฟล์ + cross-layer wiring\n\nใช้ **`code-reviewer`** subagent หา bug\u002Fsecurity\u002Fperf — ห้ามเขียน heuristic ซ้ำ\n\n```\nใช้ Task tool subagent_type=\"code-reviewer\":\n\"Review the diff of PR #\u003CPR> at \u003CWT> vs base \u003CbaseRef>.\nBeyond per-file issues, trace cross-file wiring:\n- caller → callee across files (signature\u002Fcontract drift)\n- cross-layer flow (e.g. CI workflow → Dockerfile ARG → app env → runtime)\n- config\u002Fproto\u002Fschema changes vs their consumers\nReturn findings with severity (CRITICAL\u002FWARNING\u002FINFO), file:line, evidence, suggested fix.\"\n```\n\nเพิ่มการตรวจ cross-layer ที่ subagent มักพลาด (ไล่เองด้วย grep ใน worktree):\n- workflow\u002FCI → Dockerfile (`ARG`\u002F`ENV`) → app — ค่าที่ส่งผ่านครบไหม (เช่น `ARG SITE` หาย → multi-site ไม่สลับธีม)\n- migration\u002Fschema → repository\u002Fquery layer\n- proto\u002Finterface → ทั้ง server และ client implementations\n\n### Step 5: KB-First Policy (ก่อน flag known-pattern)\n\nก่อนจะ flag finding ที่เป็น \"known pattern\" ให้ค้น KB ก่อน:\n\n```bash\ngrep -ri \"\u003Ckeyword>\" kb\u002F02-patterns\u002F kb\u002F03-bugs\u002F kb\u002F02-patterns\u002Fanti-patterns\u002F 2>\u002Fdev\u002Fnull\n```\n\n- **มี entry ตรง** → ทำตาม KB (ปรับ severity\u002Fคำแนะนำตามที่ KB สรุปไว้)\n- **ไม่มี entry** → **หยุดถาม user** + เสนอแนะ แล้วบันทึกเป็น memory\u002FKB ใหม่หลังจบ (Step 9)\n\n**Known-pattern ที่ต้องระวัง** (ดู [known-patterns.md](known-patterns.md)):\n- **dup-import**: import module path เดียวกันคนละ alias → Go **คอมไพล์ได้** อย่า flag เป็น compile error\n  จนกว่าจะ build ยืนยัน (Step 3) — ดู known-patterns.md\n- **money-flow-false-critical**: ก่อน flag CRITICAL double-credit\u002Fdouble-spend\u002Fidempotency บน money flow\n  (deposit\u002Fwithdraw\u002Ftransfer) → ตรวจ DB constraint จริงรวม **child partition indexes** (partial unique index\n  บน partition ไม่โผล่ที่ parent `pg_indexes` และไม่มีใน ORM tag; ใช้ readonly DB MCP ถ้ามี) + ไล่ atomicity\n  ชั้นล่างสุด (tx wrapper รอบ credit+history-insert → rollback ทำ ordering ปลอดภัย) ก่อนโพสต์ — ดู known-patterns.md\n\n### Step 6: Compare with Copilot \u002F Other Reviews\n\n```bash\n# ดึง reviews + review comments ที่มีอยู่\ngh pr view $PR $REPO_FLAG --json reviews,comments\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F$PR\u002Fcomments --jq '.[] | {id, path, line, user: .user.login, body}'\n```\n\n- **ตัด finding ที่ซ้ำ** กับ Copilot\u002Freviewer อื่น (ไม่โพสต์ซ้ำ)\n- **ที่ไม่เห็นด้วย** → reply ที่ comment นั้นโดยตรงพร้อม **หลักฐาน** (build log \u002F file:line \u002F KB entry)\n\n### Step 6.5: Resolve Verified-Fixed Threads (re-audit — เมื่อ author แก้ตามรอบก่อนแล้ว)\n\nเมื่อ **re-audit** PR ที่เคย audit ไปแล้ว (มี inline thread ของเราค้าง) และ author ตอบ `Fixed in \u003Ccommit>`:\n\n1. **Delta-first** — audit เฉพาะส่วนที่เปลี่ยนตั้งแต่ SHA ที่ audit รอบก่อน (`git diff \u003Cprev_audited_sha>..HEAD --stat`) แทน re-run ทั้ง PR; แต่ยัง build\u002Ftest บน HEAD ปัจจุบันเสมอ (Step 3)\n2. **Verify ทุก thread กับโค้ด HEAD ก่อนเสมอ** — อย่าเชื่อคำเคลม \"Fixed\" ลอยๆ; อ่านโค้ด\u002Fรัน test ยืนยันว่า fix นั้นแก้ finding เดิมจริง (money-flow → ยังต้องผ่าน DB check ของ Step 5)\n3. **Resolve เฉพาะที่พิสูจน์ได้** ผ่าน GraphQL `resolveReviewThread` (REST ไม่มี resolve)\n4. **ห้าม resolve** thread ที่ author แค่ `Acknowledged \u002F deferred \u002F by-design \u002F จะแยก ticket` — พวกนี้เป็น **open decision\u002Flimitation ไม่ใช่ fix**; ปล่อย unresolved ไว้ให้เห็น แล้วสรุปเป็น follow-up ใน summary\n\n```bash\n# 1) list unresolved threads + author replies (แยก resolved จริง vs ค้าง)\ngh api graphql -f query='\n{ repository(owner:\"\u003Cowner>\", name:\"\u003Crepo>\") {\n    pullRequest(number:\u003CPR>) {\n      reviewThreads(first:50){ nodes{\n        id isResolved isOutdated path line\n        comments(first:10){ nodes{ author{login} body } }\n      }}}}}' --jq '.data.repository.pullRequest.reviewThreads.nodes[]\n        | select(.isResolved==false)\n        | {id, path, line, finding: .comments.nodes[0].body[0:120],\n           replies: [.comments.nodes[1:][] | \"(\\(.author.login)) \\(.body[0:160])\"]}'\n\n# 2) resolve เฉพาะ thread ที่ verify แล้ว — เรียกแยกทีละ id\ngh api graphql -f query='mutation($id: ID!){\n  resolveReviewThread(input:{threadId:$id}){ thread{ id isResolved } }\n}' -f id=\"\u003CPRRT_thread_id>\"\n```\n\n> **Shell caveat:** อย่าใช้ loop `for x in $VAR` กับ thread id หลายตัว — fish\u002Fbash word-split ต่างกัน ทำให้ id ทั้งชุดถูกส่งเป็น id เดียว (`NOT_FOUND`); เรียก mutation แยกทีละ id ปลอดภัยสุด\n> สรุปใน chat\u002Fsummary ว่า resolve อันไหนบ้าง (พร้อมหลักฐาน) + คงอันไหนไว้ (เพราะเป็น open item) เพื่อ trace\n\n### Step 7: Output\n\n#### Mode = review (ดูอย่างเดียว)\nแสดง report ใน chat:\n\n```markdown\n## PR Audit #[number]: [title]   ([owner\u002Frepo])\n\n**Build\u002FTest:** PASS \u002F FAIL (รายละเอียด)\n**Findings:** [N] CRITICAL · [N] WARNING · [N] INFO  (ตัดซ้ำ Copilot [N] รายการ)\n\n### CRITICAL\n- `file:line` — [issue] · evidence: [...] · fix: [...]\n\n### WARNING \u002F INFO\n- ...\n\n### vs Copilot\n- เห็นด้วย: [...]\n- ไม่เห็นด้วย: [comment_id] — [เหตุผล + หลักฐาน]\n```\n\n#### Mode = comment (โพสต์ลง PR)\n1. **Inline conversation** ต่อจุดโค้ด (ผูก commit_id + path + line):\n\n```bash\nHEAD_SHA=$(gh pr view $PR $REPO_FLAG --json headRefOid --jq .headRefOid)\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F$PR\u002Fcomments \\\n  -f body=\"[finding + suggested fix]\" \\\n  -f commit_id=\"$HEAD_SHA\" \\\n  -f path=\"\u003Cfile>\" \\\n  -F line=\u003Cline> \\\n  -f side=\"RIGHT\"\n```\n\n2. **Summary review comment** รวมทุกอย่าง (ภาษาตาม `--lang`):\n\n```bash\ngh pr review $PR $REPO_FLAG --comment --body \"$(cat \u003C\u003C'EOF'\n## PR Audit Summary\n- Build\u002FTest: [PASS\u002FFAIL]\n- CRITICAL: [N] · WARNING: [N] · INFO: [N]\n- [สรุป findings สำคัญ + cross-file issues]\nEOF\n)\"\n```\n\n> เลือก `--comment` (ไม่ block) เป็น default. ใช้ `--request-changes` เฉพาะเมื่อมี CRITICAL และ user ยืนยัน\n> **หมายเหตุ:** submitted review **ลบไม่ได้** (แก้ body ได้), inline comment ลบได้ — โพสต์อย่างระมัดระวัง\n\n### Step 8: Cleanup (เสมอ — แม้ flow ล้มเหลว)\n\n```bash\ngit worktree remove \"$WT\" --force 2>\u002Fdev\u002Fnull\ngit branch -D pr-audit-$PR 2>\u002Fdev\u002Fnull\nrm -rf \"$WT\" 2>\u002Fdev\u002Fnull\ngit stash pop 2>\u002Fdev\u002Fnull || true   # คืน working tree เดิม\n```\n\n### Step 9: Update KB (pattern ใหม่)\n\nถ้าเจอ pattern\u002Fanti-pattern ใหม่ที่ยังไม่มีใน KB (Step 5) → บันทึก:\n- เป็น learning: `kb\u002F05-ai-reviewed\u002Flearnings\u002FYYYY-MM\u002FDD\u002FHH.MM_[slug].md` หรือ\n- เป็น anti-pattern entry ใน `kb\u002F02-patterns\u002Fanti-patterns\u002F`\n\n## Safety Rules (ตาม workspace rules)\n\n| Rule | Detail |\n|------|--------|\n| ห้ามลบไฟล์ผู้ใช้ | review เท่านั้น |\n| ห้าม force push \u002F ห้ามแก้ branch ของ PR | reviewer ไม่ push |\n| stash ก่อนสลับ\u002Fcleanup | คืน working tree เดิมเสมอ |\n| ห้าม commit ลง main\u002Fdevelop | ไม่มี commit ในการ audit |\n| cleanup worktree เสมอ | แม้ build ล้มเหลว (Step 8) |\n| GitHub comments | submitted review ลบไม่ได้ (แก้ body ได้), inline ลบได้ |\n| resolve thread ต้อง verify ก่อน | resolve เฉพาะ thread ที่พิสูจน์ว่าแก้จริงในโค้ด HEAD (Step 6.5); ห้าม resolve open item ที่ author แค่ acknowledge\u002Fdefer\u002Fby-design |\n\n## Reuse (ห้ามเขียน heuristic ซ้ำ)\n\n| ต้องการ | เรียก |\n|---------|-------|\n| หา bug\u002Fsecurity\u002Fperf | `code-reviewer` subagent |\n| build\u002Ftest\u002Flint | `build-validator` subagent |\n| ภาษา output | `references\u002Flanguage-guide.md` |\n\n## Related Commands\n\n| Command | Purpose |\n|---------|---------|\n| `\u002Fpr` | สร้าง PR ใหม่ (ฝั่ง author) |\n| `\u002Fpr-review` | จัดการ feedback บน PR ของตัวเอง |\n| `\u002Freview` | รีวิว local diff ก่อน push |\n| `\u002Fpr-audit` | รีวิว PR คนอื่นเชิงลึกฝั่ง reviewer (คุณอยู่ที่นี่) |\n",{"name":5,"description":7,"argument-hint":37,"user-invocable":38},"[pr-number|url] [--mode] [--lang] [--repo owner\u002Fname]",true,"main","835c1f754a3eab31c2e7eb408d21431a98c633ee","skills\u002Fpr-audit","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km","https:\u002F\u002Fgithub.com\u002Fgoffity","www.narongwate.com","2026-11-10 01:34:18",{"source":8,"skillName":5,"commands":47,"prompt":57,"zipAvailable":38},[48,51,54],{"tool":49,"command":50},"npx","npx skills add goffity\u002Fdev-km --skill pr-audit",{"tool":52,"command":53},"bunx","bunx skills add goffity\u002Fdev-km --skill pr-audit",{"tool":55,"command":56},"pnpm","pnpm dlx skills add goffity\u002Fdev-km --skill pr-audit","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fpr-audit\u002FSKILL.md",[59,65],{"path":60,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":63,"sourceHtmlUrl":64},"known-patterns.md","REFERENCE","参考文档",6467,"https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fpr-audit\u002Fknown-patterns.md",{"path":66,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":67,"sourceHtmlUrl":68},"scene-blueprint.schema.yaml",4698,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Fscene-expander\u002Fscene-blueprint.schema.yaml",[70,81,114,126,133,147],{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":32},"01M6CSZ9DKT0CG5Y2HE8F5D9KX","wait-what","Stop. That last message did not land: re-pitch it.","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fwait-what\u002FSKILL.md",[],[77,78,79,80],"wait what","land","stop","message",{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":95,"publishedAt":32},"01M6CSZ6B0GH2N75WNPPESCDHX","tdd","Test-driven development loop (red-green-refactor) with commit-based phase state and Jira traceability. Use when the user wants to build a feature or fix a bug test-first, mentions \"tdd\", \"red-green-refactor\", or \"test-first\". Replaces the tdg plugin — combines its commit\u002Fphase discipline with seam-based test quality rules from kb Testing Standards.","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Ftdd\u002FSKILL.md",[87,92],{"categoryNo":88,"categoryName":89,"taxonomyType":90,"taxonomyTypeDesc":91},"01JBSEEDCAT000000000000007","代码审查","SCENARIO","使用场景",{"categoryNo":93,"categoryName":94,"taxonomyType":90,"taxonomyTypeDesc":91},"01JBSEEDCAT000000000000008","测试与质量",[83,96,97,98,99,100,101,102,103,104,105,106,107,108,30,109,110,111,112,113],"discipline","development","state","first","loop","quality","Rules","fix","kb","use","test","standards","red-green-refactor","green","jira","testing","commit","plugin",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":120,"publishedAt":32},"01M6CSZ3PNYFR2K5GB197TA7GP","td","Creates post-task retrospectives with Before\u002FAfter context and session documentation.","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Ftd\u002FSKILL.md",[],[116,121,122,123,124,125],"documentation","context","session","task","done",{"skillNo":127,"name":31,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":32},"01M6CSZ1TZKVNHS07B4EBQEKFQ","Generates weekly or monthly session summaries from retrospectives and activity logs.","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fsummary\u002FSKILL.md",[],[31,132,123],"logs",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":137,"categories":138,"keywords":142,"publishedAt":32},"01M6CSYZQHMHJT9ZV8FYY06XZN","share","Shares knowledge across projects by copying to shared-knowledge directory with cross-project metadata.","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fshare\u002FSKILL.md",[139],{"categoryNo":140,"categoryName":141,"taxonomyType":90,"taxonomyTypeDesc":91},"01JBSEEDCAT000000000000021","资料检索与研究",[135,143,144,25,145,146],"directory","metadata","knowledge","projects",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":153,"publishedAt":32},"01M6CSYXFZ7D7EKEFXCQE8QW7S","session-analyzer","Analyzes git changes and creates retrospective drafts with Before\u002FAfter context.","https:\u002F\u002Fgithub.com\u002Fgoffity\u002Fdev-km\u002Fblob\u002Fmain\u002Fskills\u002Fsession-analyzer\u002FSKILL.md",[],[123,154,155,122,156],"session analyzer","git","retrospective"]