สมอง BC

คลังความรู้ / ระบบงานในชุด BC

#systems#scripts#issuemate#watcher#uat#python

ตัวเฝ้าใบงาน IssueMate (wait_for_issue.py)

scripts/wait_for_issue.py เป็นสคริปต์ Python ไฟล์เดียว (ใช้เฉพาะไลบรารีมาตรฐาน, PDF อ่านได้เมื่อมี pypdf/PyPDF2) ทำหน้าที่เป็น "ตัวคอยดูใบงานแทน AI" ระหว่างรอ มันวนถามเซิร์ฟเวอร์ IssueMate เองโดยไม่เรียก LLM (ไม่เสียโทเคน) พอมีใบงานที่ต้องทำก็พิมพ์ JSON สรุปงานออกทาง stdout แล้ว จบโปรเซส เพื่อให้ผู้ช่วย AI ที่รันมันเบื้องหลังตื่นมาทำต่อ เมื่อทำเสร็จก็สั่งรันตัวเฝ้ารอบใหม่ วิธีใช้ตามขั้นตอนงานอยู่ที่ เฝ้าและตอบใบงาน IssueMate BCAIACC (wait_for_issue.py, reply-batch, คำถาม PDF) ส่วนฝั่งที่เปิดใบงานให้ (บอท UAT เปิด ticket อัตโนมัติ) อยู่ที่ การทำงานอัตโนมัติของ UAT Tester: คิว ticket ตรวจซ้ำ รอบกลางคืน MCP (UAT Swarm Operations) บันทึกนี้อธิบายกลไกภายในของตัวสคริปต์ ภาพรวมโฟลเดอร์สคริปต์ดู สคริปต์ประจำโปรเจกต์ ภาพรวม: ดีพลอยเว็บ ประทับรุ่น สร้างฐานข้อมูล และตัวเฝ้า ticket (Scripts Overview)

ตัวเลือกบรรทัดคำสั่ง (:1092-1108)

ตัวเลือก หน้าที่
(ไม่ใส่) วนเฝ้าจนมีงาน แล้วพิมพ์ JSON และจบ
--once ตรวจรอบเดียว พิมพ์ JSON แม้ไม่มีงาน (wakeup_reason = no_pending_issues)
--interval N ความถี่ถาม (ค่าเริ่มต้น 60 วินาที)
--settle-seconds N รอให้ใบงานชุดเดียวกันมาครบ (ค่าเริ่มต้น 15)
--batch-size N จำนวนใบงานสูงสุดต่อครั้ง (ค่าเริ่มต้น 50)
--project KEY กรองโปรเจกต์ (ค่าเริ่มต้นจาก env ISSUEMATE_PROJECT_KEY ถ้าไม่ตั้งใช้ BCAIACC)
--state-file ไฟล์สถานะ (ค่าเริ่มต้นจาก env ISSUE_WATCHER_STATE มิฉะนั้น .audit/issuemate_watcher_state.json)
--review-batch f.json ส่งผลรีวิวและรับงานซ่อมก่อนแก้โค้ด
--reply-batch f.json ตอบและปิดใบงานเป็นชุด
--mark CODE... --status S --note T บันทึกว่าจัดการใบงานแล้ว (ใช้กับสถานะ deployed/wont_fix จะตอบจริงด้วย)
--verify ด่านตรวจก่อนดีพลอย
--stamp-version เขียนเลขรุ่นลง buildInfo.ts แบบเดียวกับ stamp-build-info.mjs
--dump-md f.md เขียนสรุปใบงานที่รอทำเป็น markdown แล้วจบ

การเชื่อมต่อ IssueMate (:57-158)

  • เรียกแบบ JSON-RPC 2.0 tools/call ผ่าน HTTP POST ไปยังเซิร์ฟเวอร์ MCP ของ IssueMate ด้วย Bearer token และหัว X-MCP-Project timeout 20 วินาที ทุกคำเรียกพ่วง projectKey ให้อัตโนมัติ ยกเว้นเครื่องมือ list_projects กับ create_project
  • ที่อยู่เซิร์ฟเวอร์ โทเคน และ project key อ่านตามลำดับ: env (ISSUEMATE_MCP_URL, ISSUEMATE_TOKEN, ISSUEMATE_PROJECT_KEY) → ไฟล์ตั้งค่า MCP mcp_config.json ของเครื่องมือ AI ที่ผู้ใช้ตั้งไว้ (รายการ issuemate) → ไฟล์ .audit/issuemate.json ถ้าไม่มีโทเคนเลยจะพิมพ์ error แล้วไม่เรียกอะไร ค่าลับไม่อยู่ในโค้ด
  • ดึงรายการใบงานด้วย list_issues 2 ครั้ง (สถานะ all และ open, ครั้งละ 200 รายการ) รวมตามรหัส แล้วถาม ready_to_fix ที่ aiApproval=approved เพิ่มเพื่อติดป้าย _ai_approved ให้ใบงานที่คนอนุมัติให้ AI แก้ (:247-281)

กติกาตัดสินว่าใบงานใดต้องปลุก AI (needs_processing, :294-353)

AI ถือว่าเป็นผู้ตอบล่าสุดเมื่อผู้เขียนคอมเมนต์เป็นชื่อกลุ่มเครื่องมือ AI ที่รู้จัก, ข้อความขึ้นต้นด้วยข้อความรายงานผลตรวจซ้ำ/ปิดแบบไม่แก้ หรือมีเครื่องหมายตอบของ AI (<!-- bc-ai-replied --> และข้อความตอบมาตรฐานอีกหลายรูปแบบ, :40-47, :284-291) ใบงานแต่ละสถานะตัดสินดังนี้

สถานะบนเซิร์ฟเวอร์ ปลุกเมื่อ
deployed, wont_fix มีคอมเมนต์ล่าสุดจากคน และต่างจากคอมเมนต์ที่ state เคยบันทึก (new_user_reply_on_<สถานะ>)
ready_to_fix มีคอมเมนต์ใหม่จากคน หรือใบงานถูกอนุมัติให้ AI แก้และ state ยังไม่เคยบันทึกว่าอนุมัติ (ai_fix_approved) ถ้ารอคนอนุมัติอยู่ให้หลับต่อ
open, reviewing, fixing ไม่มีบันทึกใน state (new_issue), มีคอมเมนต์ใหม่จากคน, state บอก deployed/fixed แต่เซิร์ฟเวอร์ยังไม่ปิด, หรือสถานะกลับมาเป็น open/ready_to_fix; แต่ถ้าคอมเมนต์ล่าสุดเป็นของ AI และ state จำนวนคอมเมนต์เท่าเดิม จะข้าม

ใบงานที่เข้าเกณฑ์จะถูกดึงรายละเอียดเต็มด้วย get_issue (คอมเมนต์และไฟล์แนบ) ก่อนสรุป (scan_pending, :741-768)

สรุปใบงานให้ AI (extract_compact_issue, :464-517)

  • ตัดปัญหาเหลือ 3 บรรทัดแรก ไม่เกิน 300 ตัวอักษร, หาไฟล์เป้าหมายจากข้อความ [frontend/...]/[backend/...] ในเนื้อหา (หรือ reviewMeta.targetFiles), หารหัสเมนูจากหัวข้อหรือเนื้อหา และใส่คอมเมนต์ล่าสุดของผู้ใช้ไม่เกิน 300 ตัวอักษร
  • ดาวน์โหลดไฟล์แนบลง .audit/attachments/<รหัสใบงาน>/ ถ้าเป็นข้อความหรือ PDF จะถอดข้อความล่วงหน้า (4,000 ตัวอักษรแรก, PDF อ่าน 10 หน้าแรกและเก็บเป็น .extracted.txt) เพื่อไม่ให้ AI ต้องดูภาพ/อ่านไฟล์ซ้ำ และตั้ง must_read_attachments_before_review เมื่อมีไฟล์แนบ (:161-228)
  • ถามความรู้ที่เกี่ยวข้องจาก ask_brain ของ BC Brain (env BCBRAIN_MCP_URL, timeout 5 วินาที) แล้วแนบ slug ที่ตรง (สูงสุด 4) เส้นทางไฟล์ต้นทางที่พบในคำตอบ (สูงสุด 8) และข้อความย่อ 600 ตัวอักษร ล้มเหลวก็ข้ามเงียบ (:411-461)
  • แนบกฎให้ AI อ้างโค้ดจริงพร้อมแหล่งที่มาทุกครั้ง

ผลลัพธ์เป็น JSON ที่มี wakeup_reason, จำนวนใบงานทั้งหมด/เสร็จแล้ว/ค้าง, pending_codes, grouped_by_file (จัดกลุ่มตามไฟล์หลักเพื่อแก้ทีเดียว) และ next_batch (:952-965)

วงเฝ้า (wait_loop, :891-988)

  1. เขียนรหัสโปรเซสลง .audit/issue_watcher.lock และอัปเดต .audit/issue_watcher_heartbeat.json (pid, project, เวลาถามล่าสุด, จำนวนใบงานทั้งหมด/ที่รอ) ทุกรอบ ไฟล์ล็อกเป็นเพียงบันทึก pid ไม่ได้ตรวจกันรันซ้อน (:735-738)
  2. สแกนใบงาน ถ้ามีงานและไม่ใช่ --once จะ รอให้คลื่นใบงานนิ่ง: ตราบที่ใบงานใหม่สุดอายุน้อยกว่า --settle-seconds ให้หลับ (สูงสุด 15 วินาที) แล้วสแกนซ้ำ ออกจากการรอเมื่อรายการรหัสไม่เปลี่ยนเลย
  3. มีงาน (หรือ --once) พิมพ์ JSON source: issuemate_mcp แล้วจบ
  4. ไม่มีงาน จะตรวจ ตัวเฝ้า UAT พอร์ต 3050 (:788-888): ขอ /api/runs?limit=80 จากแอป Tester Swarm บนเครื่อง ปลุก AI ด้วย source: localhost_3050_watchdog เมื่อพบ (ก) สคริปต์ที่สถานะ running นานเกิน max(360, จำนวนขั้นตอน x 0.5 + 120) วินาที หรือ (ข) สคริปต์ที่รอบล่าสุดไม่ผ่านภายใน 15 นาที และไม่ผ่านติดกันตั้งแต่ 2 รอบ หรือรอบล่าสุดจบมาแล้วอย่างน้อย 45 วินาที แล้วรายงานขั้นตอนแรกที่พัง
  5. ถ้าเกิดข้อผิดพลาดชั่วคราว พิมพ์คำเตือนลง stderr หลับ 15 วินาทีแล้วลองใหม่ ถ้าไม่มีอะไรให้ทำก็หลับตาม --interval (รอบแรกหลับสั้น ๆ ไม่เกิน 5 วินาที)

ตอบและปิดใบงานเป็นชุด

--review-batch (:1014-1089) อ่านไฟล์ JSON (รูปแบบรหัสใบงาน → reviewReason/fixInstructions/targetFiles/subtasks) แล้วทำขนาน 6 งานพร้อมกัน ใบงานละหนึ่งงาน: เรียก submit_claude_review (ค่าเริ่มต้น decision = fix) แล้วตามด้วย claim_for_fix เฉพาะเมื่อ decision เป็น fix ใช้ หลังอ่านไฟล์แนบแล้ว ก่อนแก้โค้ด

--reply-batch (:520-678) รับ JSON ได้ทั้งแบบ {รหัส: ข้อความ} และแบบรายการ [{code, summary, status, files}] ต่อ 1 ใบงานทำตามนี้ (ขนาน 6 งาน):

  1. ถ้าสถานะบนเซิร์ฟเวอร์ยังเป็น open/reviewing และจะปิดเป็น deployed จะส่งรีวิวแล้วรับงานให้ก่อนอัตโนมัติ
  2. สร้างข้อความตอบ: หัวข้อ สรุปที่แก้ เลขรุ่นกับ commit สั้นที่อ่านจาก frontend/src/config/buildInfo.ts ลิงก์หน้าตรวจและเครื่องหมาย <!-- bc-ai-replied --> (เครื่องหมายนี้เองที่ทำให้รอบถัดไปรู้ว่าเป็นคอมเมนต์ของ AI)
  3. สถานะ deployed เรียก mark_deployed (สั่งปิดงานย่อยทั้งหมด) แล้ว converse_on_issue ส่วนสถานะอื่นเรียก converse_on_issue อย่างเดียว ไฟล์แนบผลตรวจ (รูปภาพ ข้อความ) ถูกเข้ารหัสแนบไปกับคอมเมนต์
  4. ใบงานที่สำเร็จถูกบันทึกลง state เป็น deployed จบแล้วคืนค่า 0 ถ้าไม่มีล้มเหลว

--mark กับสถานะ deployed/wont_fix ใช้เส้นทางเดียวกันนี้ผ่านไฟล์ชั่วคราว ส่วนสถานะอื่นแค่บันทึกลง state พร้อมจำนวนคอมเมนต์และรหัสคอมเมนต์ล่าสุด เพื่อไม่ให้ปลุกซ้ำโดยไม่มีคอมเมนต์ใหม่ (mark_issue, :356-385)

ด่านตรวจก่อนดีพลอย (--verify, :681-732)

ทำ 3 ขั้นตามลำดับ หยุดทันทีที่ขั้นใดไม่ผ่าน (คืนค่า 1)

  1. สแกนบรรทัดที่เพิ่มในผลต่างเทียบ HEAD หา pattern ต้องห้าม ได้แก่ ชื่อฐานข้อมูลลูกค้า ชื่อบริษัทลูกค้า private key และ Google API key (:49-54) คำสั่งที่ใช้คือ diff เทียบ HEAD จึงไม่รวมไฟล์ใหม่ที่ยังไม่ถูกเพิ่มเข้า index
  2. go test ./internal/application/process/... ในโฟลเดอร์ backend
  3. npx tsc --noEmit ในโฟลเดอร์ frontend

ข้อจำกัด

  • ค่าเริ่มต้นของ --repo เป็นพาธโฟลเดอร์โปรเจกต์บนเครื่องผู้พัฒนาที่ฮาร์ดโค้ดไว้ (:31) เครื่องอื่นต้องส่ง --repo เอง ส่วนไฟล์สถานะ ล็อก และไฟล์แนบอยู่ใต้ .audit/ ของค่าเริ่มต้นนั้นเสมอ
  • ข้อความตอบและชื่อผู้ตอบ (agentName, reviewedBy) เป็นค่าคงที่ในโค้ด
  • --review-batch คืน 0 เสมอ แม้บางใบงานล้มเหลว (ดูบรรทัด [REVIEW FAIL])
  • ตัวเฝ้า 3050 ทำงานเฉพาะเมื่อไม่มีใบงานค้าง และถ้าแอป Swarm ปิดอยู่จะคืนรายการว่างเงียบ ๆ

ที่มาในโค้ด