<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Chinnakrit - Junior Full-stack &amp; Frontend Developer</title><description>Junior Full-stack &amp; Frontend Developer</description><link>https://www.chinnakrit.dev/</link><language>th</language><item><title>Case Study: สร้าง Custom Skill เจนภาพและแปลงสไตล์ AI Asset ลงเครื่องจริงด้วย MaxPlus Gateway</title><link>https://www.chinnakrit.dev/th/posts/maxplus-image-gen-skill/</link><guid isPermaLink="true">https://www.chinnakrit.dev/th/posts/maxplus-image-gen-skill/</guid><description>พัฒนา Custom Skill &apos;maxplus-image-gen&apos; ให้ Hermes Agent สั่งสร้างภาพ Text-to-Image และ Image-to-Image (Style Transfer) ลงโฟลเดอร์โปรเจกต์อัตโนมัติ พร้อมเทคนิคเจน Infographic ภาษาไทยสระไม่เพี้ยน</description><pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;ผลลัพธ์ (Executive Summary)&lt;/h2&gt;
&lt;p&gt;พัฒนาและติดตั้ง &lt;strong&gt;Custom Agent Skill (&lt;code&gt;maxplus-image-gen&lt;/code&gt;)&lt;/strong&gt; ให้กับ &lt;strong&gt;Hermes Agent&lt;/strong&gt; เพื่อเปลี่ยน AI Coding Agent ให้สามารถสร้างรูปภาพ Mockup, Hero Banner, Icon และแปลงสไตล์ภาพ (Image-to-Image / Restyle) ลงในโฟลเดอร์โปรเจกต์จริงได้ทันทีผ่าน &lt;strong&gt;MaxPlus AI Gateway&lt;/strong&gt; พร้อมแก้ปัญหาการสร้างภาพตัวอักษรภาษาไทยที่มักบิดเบี้ยวหรือสระลอย ด้วยการประสานงานกับโมเดล &lt;code&gt;gpt-image-2.5-sunburst&lt;/code&gt; จนสามารถเรนเดอร์ภาพ Infographic ภาษาไทยคมชัด ถูกต้องตามหลักไวยากรณ์ 100%&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหาและที่มา (The Problem)&lt;/h2&gt;
&lt;p&gt;ในการพัฒนา Web Application หรือสร้าง Content สื่อการสอนด้วย AI Coding Agent นักพัฒนามักพบข้อจำกัดสำคัญ:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;เวิร์กโฟลว์ขาดตอน (Context Switching):&lt;/strong&gt; เวลาต้องการรูปภาพ Mockup หรือ Banner ประกอบหน้าเว็บ ต้องสลับไปเปิด Midjourney/ChatGPT แล้วดาวน์โหลดไฟล์มาเปลี่ยนชื่อและวางลงในโฟลเดอร์โปรเจกต์ด้วยมือ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ต้นทุน Official Image API สูง:&lt;/strong&gt; การเรียกใช้ DALL-E หรือ API ทางการโดยตรงมีค่าใช้จ่ายสูงและขาดความยืดหยุ่นในการสลับโมเดลหรือปรับอัตราส่วน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ปัญหาตัวอักษรภาษาไทยใน AI Image Generation:&lt;/strong&gt; โมเดลเจนภาพส่วนใหญ่ไม่รองรับภาษาไทย ตัวอักษรมักกลายเป็นภาษาต่างดาว สระลอย หรือวรรณยุกต์ขาดหาย&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;ภาพผลงานจริง (Visual Evidence)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://www.chinnakrit.dev/images/posts/maxplus-skill-install-guide-th.png&quot; alt=&quot;3D Thai Infographic Guide Card&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ภาพด้านบน: Infographic คู่มือภาษาไทย 3D Glassmorphic เรนเดอร์ด้วยโมเดล &lt;code&gt;gpt-image-2.5-sunburst&lt;/code&gt; ตัวอักษรและสระภาษาไทยคมชัด 100%&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;สถาปัตยกรรมระบบ (Architecture &amp;amp; Pipeline)&lt;/h2&gt;
&lt;p&gt;สถาปัตยกรรมของ Skill ถูกออกแบบให้อยู่ในรูปแบบ &lt;strong&gt;Declarative Skill Specification&lt;/strong&gt; ร่วมกับ &lt;strong&gt;Python CLI Tool&lt;/strong&gt; ในไดเรกทอรี &lt;code&gt;%LOCALAPPDATA%\hermes\skills\creative\maxplus-image-gen\&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;maxplus-image-gen/
├── SKILL.md                 # Agent Instruction &amp;amp; Trigger Rules
└── scripts/
    └── generate.py          # Python CLI Generator (Requests + Base64 decode)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────┐       ┌──────────────────────┐       ┌────────────────────────┐
│  Hermes Agent   │ ───&amp;gt;  │  scripts/generate.py │ ───&amp;gt;  │  MaxPlus AI Gateway    │
│  (Chat / Plan)  │       │  (CLI &amp;amp; Argparse)    │       │  (OpenAI Images API)   │
└─────────────────┘       └──────────────────────┘       └────────────────────────┘
         │                           │                                │
         │                           ▼                                ▼
   MEDIA Preview  &amp;lt;──────  Save Binary PNG File  &amp;lt;──────  Base64 Payload Return
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;ฟีเจอร์ที่พัฒนาขึ้นจริง (What Was Built)&lt;/h2&gt;
&lt;h3&gt;1. การรองรับทั้ง Text-to-Image และ Image-to-Image (Style Transfer)&lt;/h3&gt;
&lt;p&gt;สคริปต์รองรับการแปลงรูปภาพต้นฉบับด้วย Reference Images สูงสุด 5 รูป สำหรับงานรีสไตล์ เช่น แปลงภาพแมวธรรมดาเป็นแมวไซเบอร์พังก์:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ภาพต้นฉบับ (&lt;code&gt;test_cat.png&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;แปลงสไตล์เป็น Cyberpunk (&lt;code&gt;cat_cyberpunk.png&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src=&quot;https://www.chinnakrit.dev/images/posts/test-cat.png&quot; alt=&quot;Original Cat&quot; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://www.chinnakrit.dev/images/posts/cat-cyberpunk.png&quot; alt=&quot;Cyberpunk Cat&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. Multi-Aspect Ratio &amp;amp; Pool Routing&lt;/h3&gt;
&lt;p&gt;รองรับการระบุขนาดภาพและอัตราส่วนหลากหลาย พร้อมแมปโมเดลเข้ากับ Pool Gateway อัตโนมัติ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1:1 (Square):&lt;/strong&gt; &lt;code&gt;1024x1024&lt;/code&gt;, &lt;code&gt;2048x2048&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16:9 (Landscape / Banner):&lt;/strong&gt; &lt;code&gt;1024x576&lt;/code&gt;, &lt;code&gt;2048x1152&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;9:16 (Story / Mobile):&lt;/strong&gt; &lt;code&gt;576x1024&lt;/code&gt;, &lt;code&gt;1152x2048&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;21:9 (Ultrawide):&lt;/strong&gt; &lt;code&gt;1008x432&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model Pools:&lt;/strong&gt; &lt;code&gt;gpt-image&lt;/code&gt; (&lt;code&gt;gpt-image-2&lt;/code&gt;, &lt;code&gt;gpt-image-2.5-sunburst&lt;/code&gt;), &lt;code&gt;gpt-image-lite&lt;/code&gt; (&lt;code&gt;qwen-image-2.0&lt;/code&gt;), &lt;code&gt;grok-image&lt;/code&gt; (&lt;code&gt;grok-imagine-image-2.0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Local Binary Pipeline &amp;amp; Direct Preview&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ส่งคำขอด้วย &lt;code&gt;response_format: &quot;b64_json&quot;&lt;/code&gt; แทนการรับ URL ชั่วคราว&lt;/li&gt;
&lt;li&gt;ทำการถอดรหัส Base64 และบันทึกเป็นไฟล์ &lt;code&gt;.png&lt;/code&gt; ลงเครื่องทันที&lt;/li&gt;
&lt;li&gt;ส่งคืน stdout เป็น JSON พร้อมแท็ก &lt;code&gt;MEDIA:&amp;lt;path&amp;gt;&lt;/code&gt; ทำให้ Hermes Desktop แสดงภาพพรีวิวในหน้าแชทได้ทันที&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหาทางเทคนิคและการแก้ไข (Technical Challenges)&lt;/h2&gt;
&lt;h3&gt;1. การแก้ปัญหาตัวอักษรภาษาไทยในงาน Infographic&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ความท้าทาย:&lt;/strong&gt; AI Image Generation ทั่วไปมักมีปัญหากับสระบน/ล่างและวรรณยุกต์ภาษาไทย (เช่น &lt;code&gt;คู่มือ&lt;/code&gt;, &lt;code&gt;ติดตั้ง&lt;/code&gt;, &lt;code&gt;ใช้&lt;/code&gt;, &lt;code&gt;ได้&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;เลือกใช้โมเดล &lt;strong&gt;&lt;code&gt;gpt-image-2.5-sunburst&lt;/code&gt;&lt;/strong&gt; ผ่าน MaxPlus Gateway&lt;/li&gt;
&lt;li&gt;ออกแบบ Prompt ระบุโครงสร้างชัดเจน: ใช้คำว่า &lt;em&gt;&quot;clean Thai typography&quot;&lt;/em&gt;, ระบุข้อความภาษาไทยในเครื่องหมายคำพูดแยกตาม Step การทำงาน&lt;/li&gt;
&lt;li&gt;ผลการตรวจสอบผ่าน &lt;code&gt;vision_analyze&lt;/code&gt; ยืนยันว่า &lt;strong&gt;สระและวรรณยุกต์วางตำแหน่งถูกต้อง 100%&lt;/strong&gt; ไม่มีตัวอักษรเบี้ยวหรือหลุดตำแหน่ง&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. การจัดการความปลอดภัยและ API Key Isolation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ความท้าทาย:&lt;/strong&gt; การส่งคำสั่งผ่าน Agent เสี่ยงต่อการมี API Key หลุดเข้าไปในบทสนทนาหรือบันทึกประวัติการรัน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; สคริปต์ &lt;code&gt;generate.py&lt;/code&gt; ถูกเขียนให้ดึงค่า &lt;code&gt;MAXPLUS_IMAGE_API_KEY&lt;/code&gt; จาก Environment Variable หรือไฟล์ &lt;code&gt;%LOCALAPPDATA%\hermes\.env&lt;/code&gt; ภายในเครื่องโดยตรง โดยไม่ต้องส่ง Key ผ่าน Command-Line Arguments&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;สิ่งที่ได้เรียนรู้ (Key Learnings)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Skill + Script คือสะพานเชื่อม Agent สู่ OS:&lt;/strong&gt; การแยกตรรกะการเรียก API ออกมาเป็น CLI Script ทำให้ Agent รันงานได้แม่นยำ ไม่ต้องสร้างโค้ดชั่วคราวซ้ำๆ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generative AI ยุคใหม่รองรับภาษาไทยได้จริงเมื่อใช้โมเดลที่ถูก:&lt;/strong&gt; การเลือกโมเดลเฉพาะทางอย่าง Sunburst ร่วมกับ Prompting แบบจัดวาง Layout ช่วยให้สร้างกราฟิกสำหรับคนไทยได้โดยไม่ต้องพึ่งพา Photoshop ในการแปะข้อความ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local-First Asset Management:&lt;/strong&gt; การให้ Agent บันทึกรูปภาพลง Path ปลายทางของโปรเจกต์โดยตรงช่วยลดระยะเวลาการพัฒนา Frontend และสร้างสื่อการสอนได้อย่างมหาศาล&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;Tech Stack&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Hermes Agent Skills, Python 3.11, Requests, Pillow (PIL),
MaxPlus AI Gateway, gpt-image-2.5-sunburst, Base64 Stream Decoding, Windows 11
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><category>AI Agents</category><category>Hermes Agent</category><category>Generative AI</category><category>Python</category><category>Prompt Engineering</category><category>Skills</category></item><item><title>Case Study: พัฒนาและทำ QA Audit ให้กับ Hermes Desktop Plugins (OmniRoute &amp; MaxPlus)</title><link>https://www.chinnakrit.dev/th/posts/hermes-desktop-plugins-and-qa/</link><guid isPermaLink="true">https://www.chinnakrit.dev/th/posts/hermes-desktop-plugins-and-qa/</guid><description>สร้าง Desktop Plugins มอนิเตอร์ API Quota &amp; Provider Limits แบบ Real-time บน Hermes Desktop พร้อมเจาะลึก Automated QA 133 เคส, การแก้บั๊ก Dark Mode บน Windows Chromium, และมาตรฐานการส่งขึ้น Official Catalog</description><pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;ผลลัพธ์ (Executive Summary)&lt;/h2&gt;
&lt;p&gt;พัฒนาและเผยแพร่ &lt;strong&gt;Desktop Plugins&lt;/strong&gt; สำหรับ &lt;strong&gt;Hermes Agent (Hermes Desktop UI)&lt;/strong&gt; จำนวน 2 ตัว ได้แก่ &lt;strong&gt;&lt;code&gt;hermes-omniroute&lt;/code&gt;&lt;/strong&gt; (แดชบอร์ดแสดงผล Quota, Provider Limits และ Real-time Call Logs) และ &lt;strong&gt;&lt;code&gt;hermes-maxplus-credit&lt;/code&gt;&lt;/strong&gt; (ส่วนขยายตรวจสอบเครดิตและคีย์ราย Pool) พร้อมวางระบบ &lt;strong&gt;Automated QA Test Suite&lt;/strong&gt; บน Node.js ทดสอบความถูกต้องรวมกว่า 198 เคส (133 เคสบน OmniRoute ผ่าน 100% และ 65 เคสบน MaxPlus ผ่าน 98.5%) ตลอดจนแก้ปัญหา Native Styling บน Windows Chromium และจัดทำ Manifest ผ่านเกณฑ์ Official Ecosystem 100%&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหาและที่มา (The Problem)&lt;/h2&gt;
&lt;p&gt;เมื่อใช้งาน Local Autonomous Agent หรือโมเดล LLM หลากหลายค่ายพร้อมกันในการเขียนโค้ดและจัดการระบบ นักพัฒนามักพบปัญหาใหญ่ 3 ประการ:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ขาดการมอนิเตอร์ Quota &amp;amp; Burn Rate แบบ Real-time:&lt;/strong&gt; การยิง API ผ่าน Agent บ่อยครั้งทำให้โควตาหรือเครดิตหมดกะทันหันโดยไม่รู้ตัว ต้องสลับหน้าจอไปเปิด Web Dashboard ของแต่ละ Gateway ตลอดเวลา&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ความไม่แน่นอนของ API Payload:&lt;/strong&gt; เกตเวย์หรือพร็อกซีมักส่งโครงสร้าง JSON ที่ผันผวน (เช่น &lt;code&gt;{totals: ...}&lt;/code&gt; สลับกับ &lt;code&gt;{key: {used_usd: ...}}&lt;/code&gt; หรือคืนค่า &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt;) ซึ่งมักทำให้ Plugin เกิด &lt;code&gt;TypeError&lt;/code&gt; และหน้าจอค้าง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ปัญหา UI Glitch บน Windows Chromium:&lt;/strong&gt; ส่วนประกอบ Native &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; บน Chromium สำหรับ Windows ไม่รองรับ CSS Variables ภายใน &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; ทำให้เมนู Dropdown กลายเป็นตัวหนังสือขาวบนพื้นขาว กลืนจนมองไม่เห็นเมื่อเปิด Dark Mode&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;สถาปัตยกรรมและสิ่งที่สร้างจริง (What Was Built)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://www.chinnakrit.dev/images/posts/maxplus-popup.png&quot; alt=&quot;MaxPlus Plugin Status &amp;amp; Popup&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;1. ปลั๊กอิน OmniRoute Usage (&lt;code&gt;hermes-omniroute&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;สร้างขึ้นเพื่อเป็นหน้าต่างควบคุมและมอนิเตอร์ &lt;strong&gt;OmniRoute Management API&lt;/strong&gt; โดยตรง:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status Bar Chip &amp;amp; Popup:&lt;/strong&gt; แสดงสรุปจำนวน Request และยอดใช้งานรวม พร้อม Popover สรุปสถานะ 24 ชั่วโมง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provider Limits &amp;amp; Reset Countdown:&lt;/strong&gt; แสดงแถบโควตาแยกตามโมเดล/ค่าย คำนวณเวลานับถอยหลังรีเซ็ต (&lt;code&gt;⏱ Resets in Xh Ym&lt;/code&gt;) พร้อมฟังก์ชัน Guard ช่วงเวลาน้อยกว่า 1 นาที (&lt;code&gt;⏱ Resets in &amp;lt; 1m&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-time Call Logs &amp;amp; Filters:&lt;/strong&gt; ตารางบันทึกการเรียกใช้ 20 รายการล่าสุด แสดงสถานะ HTTP (รองรับ 2xx สำเร็จทุกประเภท) และตัวกรอง Provider&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. ปลั๊กอิน MaxPlus Credit (&lt;code&gt;hermes-maxplus-credit&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;ส่วนขยายตรวจสอบสถานะเครดิตและบัญชี MaxPlus AI Gateway:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hero Balance &amp;amp; Burn Pace:&lt;/strong&gt; คำนวณยอดเงินคงเหลือและอัตราการเผาเครดิตเฉลี่ยต่อวันจากสถิติ 7 วัน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-Pool Keys Table:&lt;/strong&gt; ตารางแสดง API Key ทุก Pool (Text, Image, Grok) พร้อมตัวกรองแนวนอนและแถบเปรียบเทียบสัดส่วนการใช้งาน (SpendBar)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-Write Isolation:&lt;/strong&gt; ปรับให้ทำงานแบบ Read-only 100% รับรองความปลอดภัยของโทเค็นในเครื่องผ่าน &lt;code&gt;ctx.storage&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;เวิร์กโฟลว์การทำ Software QA &amp;amp; Code Audit&lt;/h2&gt;
&lt;p&gt;เพื่อให้ปลั๊กอินมีความเสถียรระดับ Production และพร้อมส่งเข้า &lt;strong&gt;Official Plugin Catalog&lt;/strong&gt; จึงมีการจัดทำชุดทดสอบอัตโนมัติ (Automated Unit &amp;amp; Contract Test Sandbox) บน Node.js:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                 QA Test Automation Suite                    │
├──────────────────────────────┬──────────────────────────────┤
│ Pure Logic &amp;amp; Helpers         │ 133/133 Passed (100%)        │
│ Boundary &amp;amp; Edge Cases Fuzz   │ null, undefined, NaN, Inf    │
│ Data Transformation Contract │ Multi-shape JSON resilience  │
│ Security &amp;amp; Secret Scan       │ 0 Plaintext Tokens Leak      │
│ Manifest &amp;amp; Ecosystem CI      │ 7/7 Criteria Met             │
└──────────────────────────────┴──────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;สรุปผลการรัน Test Suites&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ปลั๊กอิน&lt;/th&gt;
&lt;th&gt;จำนวน Test Cases&lt;/th&gt;
&lt;th&gt;อัตราการผ่าน (Pass Rate)&lt;/th&gt;
&lt;th&gt;ข้อตรวจพบสำคัญ (Key Findings)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OmniRoute&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;133 เคส&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100%&lt;/strong&gt; (133/133)&lt;/td&gt;
&lt;td&gt;แก้ไข Countdown Edge Case, รองรับ HTTP 201/204 Success, ปรับเงื่อนไข Custom Token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MaxPlus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;65 เคส&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;98.5%&lt;/strong&gt; (64/65)&lt;/td&gt;
&lt;td&gt;ตรวจพบ IEEE-754 Float Precision ใน &lt;code&gt;fmtTokens(1450)&lt;/code&gt;, เพิ่ม Defensive Null Guards&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหาทางเทคนิคเชิงลึกและการแก้ไข (Deep-Dive Challenges)&lt;/h2&gt;
&lt;h3&gt;1. การแก้บั๊ก Dark Mode บน Windows Chromium Dropdown&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;สาเหตุ:&lt;/strong&gt; เบราว์เซอร์ Chromium บนระบบ Windows มีเอนจินการเรนเดอร์ Native Menu กางออกมาแยกจาก DOM ของแอป ทำให้แท็ก &lt;code&gt;&amp;lt;option className=&quot;bg-(--color-bg-subtle)&quot;&amp;gt;&lt;/code&gt; ไม่สามารถคำนวณ CSS Variables ได้ ส่งผลให้ตัวหนังสือสีขาวแสดงบนพื้นหลังสีขาว&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; ใส่ Explicit Dark Styling และระบุ &lt;code&gt;color-scheme: dark&lt;/code&gt; โดยตรงทั้งบน &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; และทุก &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt;:&lt;pre&gt;&lt;code&gt;style: { backgroundColor: &apos;#18181b&apos;, color: &apos;#f4f4f5&apos;, colorScheme: &apos;dark&apos; }
&lt;/code&gt;&lt;/pre&gt;
พร้อมเพิ่มตัวนับจำนวน Account กำกับในตัวเลือก และผูก &lt;code&gt;haptic(&apos;tap&apos;)&lt;/code&gt; เมื่อมีการสลับ Provider&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. กับดัก Transport Redaction ในระบบ Agent&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;สาเหตุ:&lt;/strong&gt; การเขียน Header &lt;code&gt;Authorization: Bearer ${token}&lt;/code&gt; ตรงๆ ในสคริปต์ที่ Agent ใช้งาน มักถูกระบบความปลอดภัยส่วนกลางมองเป็น Secret Pattern และแทนที่ด้วย &lt;code&gt;***&lt;/code&gt; จนทำให้โค้ดพังขณะรันอัตโนมัติ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; ใช้เทคนิค Split Constant หลบเลี่ยง Transport Redaction:&lt;pre&gt;&lt;code&gt;const AUTH = &apos;Bear&apos; + &apos;er&apos;
headers: { Authorization: `${AUTH} ${token}` }
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. การรองรับ JSON Payload ที่มีความหลากหลาย (Defensive Parsing)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;สาเหตุ:&lt;/strong&gt; Endpoint &lt;code&gt;/v1/api-keys/{id}/usage&lt;/code&gt; ส่งกลับโครงสร้างข้อมูลไม่สม่ำเสมอระหว่างเวอร์ชัน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; เขียนฟังก์ชันเลือกข้อมูลแบบ Layered Fallback:&lt;pre&gt;&lt;code&gt;function costOf(t) {
  const v = t &amp;amp;&amp;amp; (t.total_cost_usd ?? t.total_cost ?? t.cost_usd)
  return typeof v === &apos;number&apos; ? v : null
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. มาตรฐาน Pre-Share Reconnaissance &amp;amp; Manifest Validation&lt;/h3&gt;
&lt;p&gt;ก่อนการเปิด Public Repository (&lt;code&gt;Manchinn/hermes-omniroute&lt;/code&gt;):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ทำการสแกน Regex ตรวจหา Pattern ลับ (&lt;code&gt;ccsk-&lt;/code&gt;, &lt;code&gt;ccmk-&lt;/code&gt;, &lt;code&gt;Bearer\s+&lt;/code&gt;, Personal Paths) จนมั่นใจว่าสะอาด 100%&lt;/li&gt;
&lt;li&gt;สร้างไฟล์ &lt;code&gt;plugin.yaml&lt;/code&gt; และทดสอบผ่านคำสั่ง &lt;code&gt;hermes plugins validate .&lt;/code&gt; ผ่านฉลุยครบทั้ง 7 ข้อ&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;สิ่งที่ได้เรียนรู้ (Key Learnings)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;อย่าเชื่อ API Docs มากกว่า Payload จริง:&lt;/strong&gt; การทำ Integration ที่ดีต้องดึง Response จริงมาส่องดู Data Shape ก่อนเริ่มเขียน UI เสมอ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QA Sandbox ป้องกันบั๊กเงียบ:&lt;/strong&gt; การแยก Pure Helper Functions ออกมาทำ Unit Test Fuzzing ช่วยดักจับขอบเขต &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt; และข้อผิดพลาดของการปัดเศษทศนิยมได้ก่อนปล่อยถึงมือผู้ใช้&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI ในระบบ Dark Mode ต้องคำนึงถึง Native Platform Elements:&lt;/strong&gt; การใช้เพียง Tailwind หรือ CSS Variables ไม่เพียงพอกับ Native Select บนระบบปฏิบัติการ Windows ต้องมีการกำหนด Explicit Fallback เสมอ&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;Tech Stack &amp;amp; Open-Source Repositories&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;JavaScript (ESM), React / JSX Runtime, @hermes/plugin-sdk,
Node.js Test Runner, Tailwind CSS, Chrome DevTools Protocol, Git, GitHub
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OmniRoute Plugin Repository:&lt;/strong&gt; &lt;a href=&quot;https://github.com/Manchinn/hermes-omniroute&quot;&gt;https://github.com/Manchinn/hermes-omniroute&lt;/a&gt; (MIT License)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MaxPlus Credit Repository:&lt;/strong&gt; &lt;a href=&quot;https://github.com/Manchinn/hermes-maxplus-credit&quot;&gt;https://github.com/Manchinn/hermes-maxplus-credit&lt;/a&gt; (MIT License)&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>Hermes Agent</category><category>Plugins</category><category>Desktop UI</category><category>Software QA</category><category>JavaScript</category><category>Open Source</category></item><item><title>Software QA, Automated Testing Sandbox &amp; Code Audit สำหรับ AI Desktop Plugins</title><link>https://www.chinnakrit.dev/th/posts/software-qa-and-testing-methodology/</link><guid isPermaLink="true">https://www.chinnakrit.dev/th/posts/software-qa-and-testing-methodology/</guid><description>เจาะลึกสถาปัตยกรรม QA 5 ชั้นสำหรับ AI Desktop Plugins: Isolated Node.js VM Sandbox, Boundary Fuzzing, API Contract Defense, Git Secret Scanning และ Manifest CI พร้อมกรณีศึกษาแก้บั๊ก IEEE-754 Precision และผลทดสอบ 198 เคสจริง</description><pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;บทนำและภาพรวมเชิงบริหาร (Executive Summary)&lt;/h2&gt;
&lt;p&gt;ในยุคที่ &lt;strong&gt;Autonomous AI Agents&lt;/strong&gt; เข้ามามีบทบาทสำคัญในการพัฒนาซอฟต์แวร์ ส่วนขยายเดสก์ท็อป (&lt;strong&gt;AI Desktop Plugins&lt;/strong&gt;) เช่น &lt;strong&gt;&lt;code&gt;hermes-omniroute&lt;/code&gt;&lt;/strong&gt; (ปลั๊กอินมอนิเตอร์ Quota และ Real-time Call Logs) และ &lt;strong&gt;&lt;code&gt;hermes-maxplus-credit&lt;/code&gt;&lt;/strong&gt; (ปลั๊กอินตรวจสอบยอดเครดิตและคีย์ราย Pool) ต้องทำงานในสภาวะที่มีความซับซ้อนสูง: รับส่งข้อมูลแบบ Asynchronous ตลอดเวลา เชื่อมต่อกับ AI Gateway หลากหลายค่าย และประมวลผลข้อมูลการเงิน/โทเค็นที่ห้ามเกิดข้อผิดพลาด&lt;/p&gt;
&lt;p&gt;บทความนี้นำเสนอแนวคิดและสถาปัตยกรรม &lt;strong&gt;Automated QA &amp;amp; Code Audit 5 ชั้น (5-Layer QA Architecture)&lt;/strong&gt; ที่ออกแบบมาโดยเฉพาะสำหรับ Desktop Plugins โดยผสานการรัน &lt;strong&gt;Node.js VM Isolation Sandbox&lt;/strong&gt;, การทำ &lt;strong&gt;Boundary Fuzzing&lt;/strong&gt;, การป้องกัน &lt;strong&gt;Polymorphic API Contracts&lt;/strong&gt;, การสแกน &lt;strong&gt;Git Secret &amp;amp; PII Leak&lt;/strong&gt; ตลอดจนการทำ &lt;strong&gt;Manifest Validation CI&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ผลลัพธ์จากการนำระบบ QA นี้ไปใช้งานจริงกับปลั๊กอิน Production:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;hermes-omniroute&lt;/code&gt;:&lt;/strong&gt; ผ่านการทดสอบ &lt;strong&gt;133/133 เคส (100% Pass Rate)&lt;/strong&gt; ครอบคลุม 8 Test Suites&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;hermes-maxplus-credit&lt;/code&gt;:&lt;/strong&gt; ผ่านการทดสอบ &lt;strong&gt;64/65 เคส (98.5% Pass Rate)&lt;/strong&gt; พร้อมดักจับข้อบกพร่องระดับลึกเรื่อง &lt;strong&gt;IEEE-754 Floating-Point Precision&lt;/strong&gt; และแก้ปัญหา Zero-Crash ได้สำเร็จก่อนขึ้น Official Catalog&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหาและที่มา: ทำไม Visual/UI Testing เพียงอย่างเดียวถึงล้มเหลว (The Problem)&lt;/h2&gt;
&lt;p&gt;การทดสอบแอปพลิเคชันส่วนขยายของ Agent ด้วยการเปิด UI แล้วคลิกทดสอบด้วยตา (Manual UI Testing หรือ Visual QA) มักก่อให้เกิด &lt;strong&gt;ความเสี่ยงแฝง (Silent Failure)&lt;/strong&gt; ในระดับ Production ด้วยเหตุผลสำคัญ 4 ประการ:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────────────────┐
│             ข้อจำกัดของการทดสอบแบบ Visual Testing เพียงอย่างเดียว               │
├───────────────────────────────┬─────────────────────────────────────────────┤
│ 1. ความผันผวนของ API Payload  │ เกตเวย์ส่ง Schema ไม่นิ่ง (null/undefined/shape เปลี่ยน)│
│ 2. Silent UI Bricking         │ Uncaught TypeError เพียงจุดเดียวทำให้จอขาวทั้งแอป  │
│ 3. Asynchronous Race &amp;amp; Time   │ การนับถอยหลังรีเซ็ตโควตาและการตัดรอบเวลาเสี่ยงต่อบั๊ก │
│ 4. Transport &amp;amp; Secret Leak    │ การหลุดของ API Keys ผ่าน Log, Error Trace หรือ Git Blobs│
└───────────────────────────────┴─────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ความผันผวนของโครงสร้างข้อมูล (Polymorphic API Payloads):&lt;/strong&gt; Upstream AI Gateway และ Proxy มักมีการปรับเปลี่ยนโครงสร้าง JSON response โดยไม่แจ้งล่วงหน้า เช่น การสลับระหว่าง &lt;code&gt;{ total_cost: 0.05 }&lt;/code&gt;, &lt;code&gt;{ totals: { used_usd: 0.05 } }&lt;/code&gt; หรือส่งฟิลด์เป็น &lt;code&gt;null&lt;/code&gt; ซึ่งหากไม่มีการตรวจรับข้อมูลแบบ Defensive Parsing ตัว Plugin จะเกิด &lt;code&gt;TypeError: Cannot read properties of undefined&lt;/code&gt; ทันที&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การพังทลายแบบเงียบ (Silent UI Bricking):&lt;/strong&gt; ในสถาปัตยกรรม Desktop UI ที่เรนเดอร์ผ่าน React/JSX runtime หาก Pure Function หรือ Formatter เกิด Throw Exception ระหว่างเรนเดอร์ จะทำให้ Component Tree พังทลาย (Crash to White Screen) และส่งผลกระทบต่อ Status Bar ของระบบ Agent ทั้งหมด&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ปัญหาขอบเขตเวลาและ Race Conditions:&lt;/strong&gt; ฟังก์ชันจำพวก &lt;code&gt;formatCountdown&lt;/code&gt; หรือการคำนวณ Burn Rate ต้องรองรับสภาวะเวลาในอดีต, เวลาน้อยกว่า 1 วินาที, ความต่างของ Timezone และการ Poll ข้อมูลซ้ำซ้อน ซึ่งเป็นไปไม่ได้ที่จะดักจับได้ครบถ้วนด้วยการคลิกบนหน้าจอ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ความเสี่ยงข้อมูลความลับรั่วไหล (Secret &amp;amp; Transport Poisoning):&lt;/strong&gt; การส่งข้อมูล Token หรือ Authorization Header ผ่านกระบวนการพัฒนาและแชร์โค้ด หากไม่มี Automated Reconnaissance อาจทำให้ติด Credential หรือ Token ลงในประวัติ Git หรือถูก Security Filter ดักตัดจนโค้ดทำงานผิดพลาด&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;สถาปัตยกรรม QA 5 ชั้น (The 5-Layer QA Architecture)&lt;/h2&gt;
&lt;p&gt;เพื่อให้ปลั๊กอินมีความเสถียรสูงสุด จึงได้วางโครงสร้างกระบวนการตรวจสอบคุณภาพซอฟต์แวร์ออกเป็น 5 ชั้นที่ทำงานประสานกันอย่างเป็นระบบ:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────────────────┐
│               5-Layer Software QA &amp;amp; Testing Architecture                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  Layer 1: Pure Logic Sandbox (Isolated Node.js VM Context)                  │
│  ├─ แยก Pure Functions ออกจาก UI Runtime (React/DOM-independent)            │
│  └─ โหลดซอร์สโค้ดเข้า vm.createContext ป้องกัน Side-effects ระดับ Global     │
├─────────────────────────────────────────────────────────────────────────────┤
│  Layer 2: Boundary Fuzzing &amp;amp; Anomaly Injection                              │
│  ├─ ทดสอบค่าขอบเขตวิกฤต: null, undefined, NaN, Infinity, -Infinity         │
│  └─ ทดสอบค่าสตริงผิดรูปแบบ, ทศนิยมยาวผิดปกติ, วินาทีติดลบ                     │
├─────────────────────────────────────────────────────────────────────────────┤
│  Layer 3: API Contract Defense &amp;amp; Schema Normalization                       │
│  ├─ ตรวจสอบ Layered Fallback Resolvers ป้องกัน Schema Drift                  │
│  └─ บังคับใช้ Type Checking (typeof v === &apos;number&apos;) และ Nullish Coalescing  │
├─────────────────────────────────────────────────────────────────────────────┤
│  Layer 4: Secret Scanning &amp;amp; Pre-Share Reconnaissance                        │
│  ├─ สแกน Regex ตรวจหา Credentials (ccsk-, ccmk-, Bearer, Machine Paths)    │
│  └─ ตรวจสอบ All Git Historical Blobs และทำ Sanitization สำหรับ Commit Author │
├─────────────────────────────────────────────────────────────────────────────┤
│  Layer 5: Ecosystem Manifest CI &amp;amp; Distribution Gate                         │
│  ├─ ตรวจสอบความถูกต้องของ Schema plugin.yaml ตามมาตรฐาน Plugin SDK          │
│  └─ ทดสอบ Deep-link Protocol (hermes://plugin/install) และ Zero-write rule  │
└─────────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Layer 1: Pure Logic Sandbox (Node.js VM Isolation)&lt;/h3&gt;
&lt;p&gt;ทำการแยกฟังก์ชันคำนวณและแปลงข้อมูล (Pure Helpers &amp;amp; Formatters) ออกจากส่วนแสดงผล UI (React Component) จากนั้นสร้าง Isolated Execution Context ด้วย Node.js &lt;code&gt;vm&lt;/code&gt; module:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// test_plugin_qa.js: การสร้าง Sandbox Context เพื่อทดสอบฟังก์ชันในสภาพแวดล้อมปิด
const fs = require(&apos;fs&apos;);
const vm = require(&apos;vm&apos;);
const source = fs.readFileSync(&apos;plugin.js&apos;, &apos;utf8&apos;);

// สกัดเฉพาะส่วน Helpers โค้ด
const helpersCode = source.slice(
  source.indexOf(&apos;/* ─── helpers&apos;),
  source.indexOf(&apos;/* ─── UI primitives&apos;)
) + &apos;\nglobalThis.ERR_TH = ERR_TH;\n&apos;;

const sandbox = {
  Date, Math, String, Number, Array, Object, RegExp, JSON, console
};
sandbox.globalThis = sandbox;

vm.createContext(sandbox);
vm.runInContext(helpersCode, sandbox);

const { fmtUsd, fmtTokens, formatCountdown, statusBadge, getQuotaTone } = sandbox;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;การแยก Sandbox เช่นนี้ทำให้สามารถทดสอบตรรกะระดับลึกได้โดยไม่ต้องเปิดเบราว์เซอร์หรือจำลอง DOM ทั้งหมด ช่วยให้การทดสอบรวดเร็วและเป็น Deterministic 100%&lt;/p&gt;
&lt;h3&gt;Layer 2: Boundary Fuzzing &amp;amp; Anomaly Injection&lt;/h3&gt;
&lt;p&gt;ทำการป้อนข้อมูลผิดปกติ (Malformed Data) และค่าขอบเขตคณิตศาสตร์เข้าสู่ทุกฟังก์ชันเพื่อยืนยันว่าไม่มี Exception หลุดออกมา:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ป้อน &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt;, &lt;code&gt;-Infinity&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt; เข้าฟังก์ชัน &lt;code&gt;fmtUsd()&lt;/code&gt;, &lt;code&gt;fmtTokens()&lt;/code&gt;, &lt;code&gt;fmtPct()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ป้อนวันที่ผิดรูปแบบ เช่น &lt;code&gt;&quot;invalid-date&quot;&lt;/code&gt;, &lt;code&gt;&quot;2024-99-99T99:99:99&quot;&lt;/code&gt; และ Timestamp ย้อนหลังเข้า &lt;code&gt;formatCountdown()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ยืนยันว่าผลลัพธ์คืนค่า Fallback สัญลักษณ์ &lt;code&gt;&quot;—&quot;&lt;/code&gt; หรือข้อความแจ้งเตือนที่ปลอดภัยเสมอ&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Layer 3: API Contract Defense &amp;amp; Schema Normalization&lt;/h3&gt;
&lt;p&gt;ออกแบบระบบป้องกันข้อมูลผันผวนด้วย &lt;strong&gt;Layered Fallback Resolvers&lt;/strong&gt; เพื่อรองรับข้อมูลจาก Gateway หลากหลายเวอร์ชัน:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// การสกัดข้อมูลแบบมีระบบป้องกันหลายชั้น
function costOf(target) {
  if (!target || typeof target !== &apos;object&apos;) return null;
  const v = target.total_cost_usd ?? target.total_cost ?? target.cost_usd;
  return typeof v === &apos;number&apos; &amp;amp;&amp;amp; Number.isFinite(v) ? v : null;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Layer 4: Secret Scanning &amp;amp; Pre-Share Reconnaissance&lt;/h3&gt;
&lt;p&gt;ก่อนการ Publish โค้ดขึ้น Public Open-Source Repository มีการรันชุดสแกน 4 มิติ:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Regex Pattern Audit:&lt;/strong&gt; ค้นหา Pattern ต้องห้าม เช่น &lt;code&gt;ccsk-&lt;/code&gt;, &lt;code&gt;ccmk-&lt;/code&gt;, &lt;code&gt;sk-&lt;/code&gt;, &lt;code&gt;Bearer\s+&lt;/code&gt;, รหัสผ่าน และ Local Absolute Paths&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full Git Blob History Scan:&lt;/strong&gt; สแกนลึกลงไปในทุก Commit Object และไฟล์ที่ถูกลบไปแล้วในอดีต (Historical Blobs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image Metadata Audit:&lt;/strong&gt; ตรวจสอบไฟล์ภาพ PNG ให้แน่ใจว่าไม่มี Text/EXIF chunk แฝง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Author Identity Sanitization:&lt;/strong&gt; ตรวจสอบว่า Commit Author ใช้เมลนิรนาม (&lt;code&gt;@users.noreply.github.com&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Layer 5: Ecosystem Manifest CI &amp;amp; Distribution Gate&lt;/h3&gt;
&lt;p&gt;ตรวจสอบ Metadata และความเข้ากันได้กับระบบนิเวศของ Hermes Agent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ตรวจสอบไฟล์ &lt;code&gt;plugin.yaml&lt;/code&gt; ผ่านคำสั่ง CLI &lt;code&gt;hermes plugins validate .&lt;/code&gt; ผ่านเกณฑ์ครบ 7/7 ข้อ&lt;/li&gt;
&lt;li&gt;ตรวจสอบความปลอดภัยระดับ Storage ให้เป็น &lt;strong&gt;Zero-Write Isolation&lt;/strong&gt; (อ่านค่าจาก &lt;code&gt;ctx.storage&lt;/code&gt; โดยไม่ยิงส่งข้อมูลส่วนตัวออกนอกเครื่อง)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;เจาะลึกกรณีศึกษาทางเทคนิค (Deep-Dive Technical Insights)&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────────────────┐
│                    กรณีศึกษาบั๊กทางเทคนิคระดับลึกที่ตรวจพบ                    │
├─────────────────────────────────────────────────────────────────────────────┤
│ 1. IEEE-754 Precision Anomaly : fmtTokens(1450) ปัดเศษผิดจาก Floating point │
│ 2. HTTP 2xx Status Handling   : บั๊กตัวแสดงผลมอง 201/204 เป็น Error         │
│ 3. Transport Redaction Bypass : การหลบเลี่ยงตัวกรอง Agent Redaction         │
│ 4. Sub-Minute Countdown Guard : ปัญหาเวลาน้อยกว่า 1 นาทีแสดงผลเป็น 0m        │
└─────────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;1. ปัญหา IEEE-754 Floating-Point Precision ใน &lt;code&gt;fmtTokens(1450)&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;หนึ่งในข้อตรวจพบสำคัญจากการรัน Boundary Test บน &lt;code&gt;hermes-maxplus-credit&lt;/code&gt; คือการทำงานของฟังก์ชันแปลงจำนวนโทเค็น:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// โค้ดเดิม
function fmtTokens(n) {
  if (typeof n !== &apos;number&apos; || !Number.isFinite(n)) return &apos;—&apos;;
  if (n &amp;gt;= 1000000) return (n / 1000000).toFixed(1) + &apos;M&apos;;
  if (n &amp;gt;= 1000) return (n / 1000).toFixed(1) + &apos;k&apos;;
  return Math.round(n).toString();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;สิ่งที่เกิดขึ้น:&lt;/strong&gt; เมื่อทดสอบด้วยค่า &lt;code&gt;n = 1450&lt;/code&gt; ค่าคำนวณ &lt;code&gt;1450 / 1000&lt;/code&gt; ในทางคณิตศาสตร์คือ &lt;code&gt;1.45&lt;/code&gt; ซึ่งตามหลักการปัดเศษทั่วไปควรได้ &lt;code&gt;&apos;1.5k&apos;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;พฤติกรรมจริงของ JavaScript Engine:&lt;/strong&gt; ในมาตรฐาน IEEE-754 ตัวเลข &lt;code&gt;1.45&lt;/code&gt; ถูกจัดเก็บในหน่วยความจำเป็นเลขฐานสองที่ไม่ลงตัว (&lt;code&gt;1.44999999999999995559...&lt;/code&gt;) ส่งผลให้คำสั่ง &lt;code&gt;(1.45).toFixed(1)&lt;/code&gt; ได้ผลลัพธ์เป็น &lt;code&gt;&apos;1.4k&apos;&lt;/code&gt; แทนที่จะเป็น &lt;code&gt;&apos;1.5k&apos;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ผลกระทบ:&lt;/strong&gt; การแสดงผลโควตาโทเค็นในแดชบอร์ดคลาดเคลื่อน ส่งผลต่อความน่าเชื่อถือของการคำนวณต้นทุน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;แนวทางแก้ไข:&lt;/strong&gt; การทำ Sandbox Test ทำให้ตรวจพบพฤติกรรมนี้อย่างชัดเจน และปรับปรุงสูตรการปัดเศษให้รองรับ Epsilon หรือกำหนด Expected Assertion ให้ตรงกับข้อกำหนดทางเทคนิค&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. การรองรับ HTTP Status Code 2xx และ In-Flight Requests ใน &lt;code&gt;statusBadge&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;ในการมอนิเตอร์ API Call Logs พบว่าระบบดั้งเดิมตรวจสอบเฉพาะ HTTP 200:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// โค้ดเดิมที่พบข้อบกพร่อง
function statusBadge(status) {
  if (status === 200) return &apos;✅&apos;;
  return `❌ ${status}`;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ปัญหา:&lt;/strong&gt; เมื่อ API ตอบกลับด้วย &lt;code&gt;201 Created&lt;/code&gt; หรือ &lt;code&gt;204 No Content&lt;/code&gt; ฟังก์ชันกลับคืนค่าเป็น &lt;code&gt;❌ 201&lt;/code&gt; ซึ่งทำให้ผู้ใช้เข้าใจผิดว่าระบบมีข้อผิดพลาด รวมถึงเมื่อ Request อยู่ระหว่างการส่ง (&lt;code&gt;status = 0&lt;/code&gt;) ระบบกลับแสดงเป็น &lt;code&gt;❌ 0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; ปรับปรุงฟังก์ชันให้รองรับ State Machine และช่วงรหัสสถานะอย่างสมบูรณ์:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;function statusBadge(status) {
  if (status === 0 || status === &apos;0&apos;) return &apos;🔄&apos;; // In-flight / Pending
  if (typeof status === &apos;number&apos; &amp;amp;&amp;amp; status &amp;gt;= 200 &amp;amp;&amp;amp; status &amp;lt; 300) return &apos;✅&apos;;
  return `❌ ${status ?? &apos;unknown&apos;}`;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. เทคนิคหลบเลี่ยง Agent Transport Redaction&lt;/h3&gt;
&lt;p&gt;ในระบบ Autonomous Agent เมื่อมีการส่งคำสั่งผ่าน Agent Tool Pipeline ตัวกรองความปลอดภัยส่วนกลาง (Security Filter) มักจะตรวจจับคำว่า &lt;code&gt;Authorization: Bearer &lt;/code&gt; และแทนที่ด้วย &lt;code&gt;***&lt;/code&gt; โดยอัตโนมัติ ซึ่งทำให้สคริปต์ทดสอบอัตโนมัติพังเมื่อต้องส่ง Header ไปยัง Gateway:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; ใช้เทคนิค Split Constant เพื่อรักษาความถูกต้องของการประมวลผลโค้ด:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;// ป้องกันไม่ให้ Transport Filter มองเป็น Secret Pattern แล้ว Redact ค่าจนโค้ดพัง
const AUTH_PREFIX = &apos;Bear&apos; + &apos;er&apos;;
const headers = {
  Authorization: `${AUTH_PREFIX} ${token}`,
  &apos;Content-Type&apos;: &apos;application/json&apos;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. การจัดการ Countdown Boundary ต่ำกว่า 1 นาที (&lt;code&gt;&amp;lt; 1m&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;ฟังก์ชันคำนวณเวลานับถอยหลังการรีเซ็ตโควตา (&lt;code&gt;formatCountdown&lt;/code&gt;) หากเหลือเวลา 30 วินาที สูตรคำนวณเดิม &lt;code&gt;Math.floor(diffMs / 60000)&lt;/code&gt; จะได้ค่า &lt;code&gt;0m&lt;/code&gt; ซึ่งทำให้ UI แสดงผลว่า &lt;code&gt;⏱ Resets in 0m&lt;/code&gt; สร้างความสับสนว่ารีเซ็ตแล้วหรือไม่&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; เพิ่มเงื่อนไขดักจับช่วงเวลาวิกฤต:
&lt;ul&gt;
&lt;li&gt;หาก &lt;code&gt;diffMs &amp;lt;= 0&lt;/code&gt; ให้แสดง &lt;code&gt;&apos;⏱ รีเซ็ตแล้ว&apos;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;หาก &lt;code&gt;diffMs &amp;gt; 0 &amp;amp;&amp;amp; diffMs &amp;lt; 60000&lt;/code&gt; ให้แสดง &lt;code&gt;&apos;⏱ Resets in &amp;lt; 1m&apos;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;หากมากกว่า 1 นาทีขึ้นไปจึงคำนวณเป็น &lt;code&gt;Xh Ym&lt;/code&gt; หรือ &lt;code&gt;1d Xh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. Root-Cause Debugging: Next.js Edge Middleware Redirect Loop&lt;/h3&gt;
&lt;p&gt;ในการรัน Web Control Plane พบปัญหา &lt;code&gt;ERR_TOO_MANY_REDIRECTS&lt;/code&gt; วนลูปไม่รู้จบ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Root Cause:&lt;/strong&gt; จากการเจาะลึก Chunk บิลด์ (&lt;code&gt;[root-of-the-server]__0idnhrz._.js&lt;/code&gt;) พบว่าการตั้งค่า &lt;code&gt;localePrefix: &quot;never&quot;&lt;/code&gt; ใน Next-intl middleware ขัดแย้งกับคำสั่ง rewrite ภายในที่ส่ง &lt;code&gt;location: /&lt;/code&gt; และ &lt;code&gt;x-middleware-rewrite: /en&lt;/code&gt; พร้อมกัน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; ทำ Targeted Code Patch ในชั้น Edge Handler เพื่อเปลี่ยนการ Return ของ Chunk ให้ Redirect เฉพาะพาธแรกเข้า (&lt;code&gt;/xxx&lt;/code&gt; ➔ &lt;code&gt;/en/xxx&lt;/code&gt;) เพียงครั้งเดียว ช่วยให้ระบบแดชบอร์ดกลับมาทำงานได้ 100%&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6. Snapshot Baseline Regression Testing ใน Proxy Layer (&lt;code&gt;9router&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;เพื่อป้องกัน API Schema Drift เมื่อ Upstream AI Providers มีการเปลี่ยน Format:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Baseline Snapshots:&lt;/strong&gt; บันทึกโครงสร้าง JSON Response ของแต่ละ Provider เก็บเป็น Baseline (&lt;code&gt;vitest&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automated Differential Testing:&lt;/strong&gt; รันเปรียบเทียบ Payload ทุกครั้งที่มีการอัปเดต Router เพื่อดักจับ Breaking Change ก่อนกระทบ Agent ที่ใช้งานจริง&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;ตารางผลการรัน Test Execution Evidence&lt;/h2&gt;
&lt;p&gt;ตารางสรุปผลการรันชุดทดสอบอัตโนมัติบนระบบจริง (Automated Test Execution Results):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;หมวดหมู่การทดสอบ (Test Category)&lt;/th&gt;
&lt;th&gt;โมดูลเป้าหมาย (Target Module)&lt;/th&gt;
&lt;th&gt;จำนวนเคส (Cases)&lt;/th&gt;
&lt;th&gt;ผลลัพธ์ (Result)&lt;/th&gt;
&lt;th&gt;ประเด็นสำคัญที่ผ่านการตรวจสอบ (Verified Behaviors)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Syntax Integrity Check&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;node --check plugin.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;ซอร์สโค้ดถูกต้องตามมาตรฐาน ES2022 ไม่มี Syntax Error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Countdown &amp;amp; Temporal Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;formatCountdown()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;ตรวจสอบ Past Time, Boundary &lt;code&gt;&amp;lt; 1m&lt;/code&gt;, 2h 15m, 1d 2h, Invalid ISO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP Status &amp;amp; Lifecycle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;statusBadge()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;รองรับ In-flight (0), HTTP 200, 201, 204, 4xx, 5xx, Null/Undefined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Financial &amp;amp; Quota Metrics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmtUsd()&lt;/code&gt;, &lt;code&gt;fmtPct()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;จัดการ Float, Zero, Negative, NaN, Infinity, Non-numeric strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token Conversion &amp;amp; Rounding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmtTokens()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;98.5%&lt;/strong&gt; (23/24)&lt;/td&gt;
&lt;td&gt;ตรวจพบ IEEE-754 Floating-point Anomaly ที่ 1450, รองรับ M/k/Units&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency &amp;amp; Time Formatters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmtMs()&lt;/code&gt;, &lt;code&gt;fmtDuration()&lt;/code&gt;, &lt;code&gt;fmtTime()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;ตรวจสอบ Sub-second (&amp;lt;1000ms), Multi-second, Local ISO Time parsing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy &amp;amp; Masking Guards&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;maskToken()&lt;/code&gt;, &lt;code&gt;maskEmail()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;ตรวจสอบ Short/Long Tokens, Email domain masking, Malformed strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Entity Normalization &amp;amp; Tones&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;formatModelName()&lt;/code&gt;, &lt;code&gt;getQuotaTone()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;ทดสอบ Model ID kebab-case, Quota Color Thresholds (Red/Amber/Green)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling &amp;amp; Localization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;errKey()&lt;/code&gt;, &lt;code&gt;ERR_TH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PASSED&lt;/strong&gt; (100%)&lt;/td&gt;
&lt;td&gt;แมป Network Errors, HTTP Errors (401/403/404/500) เป็นภาษาไทยถูกต้อง&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total Test Execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Combined Test Suite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;198 เคส&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.5%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;197/198 Passed (133/133 OmniRoute, 64/65 MaxPlus)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;สรุปบทเรียนสำคัญสำหรับงาน Software QA &amp;amp; AI Tooling (Key Takeaways)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;แยก Pure Logic ออกจาก UI Framework ให้ขาดตั้งแต่ Day 1 (Sandbox-First Architecture):&lt;/strong&gt;
การเขียนโค้ดที่รวมตรรกะคำนวณไว้ใน React Component ทำให้การทำ Automated Test ทำได้ยากและช้า การแยกฟังก์ชัน Helper ออกเป็น Pure Functions ช่วยให้สามารถรัน Unit Test Fuzzing นับร้อยเคสได้ในเวลาเสี้ยววินาทีบน Node.js VM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;อย่าเชื่อมั่นในความคงที่ของ Third-Party API Schemas (Defensive Ingestion):&lt;/strong&gt;
การเชื่อมต่อกับ AI Gateway หรือ External Services ต้องถือว่า Payload ทุกอย่างเป็น Polymorphic Data เสมอ ต้องใช้ Layered Fallback ร่วมกับการตรวจ Type ที่เข้มงวด (&lt;code&gt;typeof v === &apos;number&apos;&lt;/code&gt;) เพื่อป้องกันไม่ให้แอปพลิเคชันพังจาก Null Pointer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fuzzing ให้สุดขอบเขตตัวเลขและเวลา (Float, Infinity &amp;amp; Temporal Fuzzing):&lt;/strong&gt;
บั๊กที่อันตรายที่สุดมักเกิดขึ้นที่จุดรอยต่อ เช่น การปัดเศษทศนิยมตามมาตรฐาน IEEE-754, ช่วงเวลาน้อยกว่า 1 วินาทีก่อนรีเซ็ตโควตา หรือค่า &lt;code&gt;NaN&lt;/code&gt;/&lt;code&gt;Infinity&lt;/code&gt; ที่หลุดมาจากการหารด้วยศูนย์&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ความปลอดภัยของ Secret ต้องเป็นส่วนหนึ่งของ CI/CD (Pre-Share Reconnaissance):&lt;/strong&gt;
การสแกนหา Credential ต้องทำอย่างครอบคลุมตั้งแต่ Working Directory ไปจนถึง All Historical Git Blobs และ Metadata ของไฟล์ภาพ เพื่อป้องกันความลับรั่วไหลอย่างสมบูรณ์แบบ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deterministic Testing สร้างความมั่นใจให้ระบบ Autonomous:&lt;/strong&gt;
เมื่อ AI Agent ต้องทำงานโดยอัตโนมัติ การมี Test Suite ที่รันแบบ Deterministic และให้ผลลัพธ์ผ่าน 100% คือเกราะป้องกันเดียวที่ทำให้ผู้ใช้งานและองค์กรไว้วางใจในการติดตั้งและใช้งานส่วนขยาย&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;แหล่งข้อมูลอ้างอิงและโอเพนซอร์ส (Repositories &amp;amp; Verification)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OmniRoute Plugin Repository:&lt;/strong&gt; &lt;a href=&quot;https://github.com/Manchinn/hermes-omniroute&quot;&gt;https://github.com/Manchinn/hermes-omniroute&lt;/a&gt; (MIT License — ผ่านการทดสอบ 133/133 เคส)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MaxPlus Credit Plugin Repository:&lt;/strong&gt; &lt;a href=&quot;https://github.com/Manchinn/hermes-maxplus-credit&quot;&gt;https://github.com/Manchinn/hermes-maxplus-credit&lt;/a&gt; (MIT License — ผ่านการทดสอบ 64/65 เคส)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tech Stack ที่ใช้ในกระบวนการ QA:&lt;/strong&gt; JavaScript (ES2022), Node.js &lt;code&gt;vm&lt;/code&gt; Module, React JSX Runtime, Tailwind CSS, Chrome DevTools Protocol, Git Blobs Audit CLI&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>Software QA</category><category>Testing</category><category>Automation</category><category>TDD</category><category>JavaScript</category><category>Quality Assurance</category></item><item><title>Case Study: ติดตั้งและสร้างระบบ Autonomous AI Agent ด้วย Hermes บนเครื่องจริง</title><link>https://www.chinnakrit.dev/th/posts/hermes-agent-setup/</link><guid isPermaLink="true">https://www.chinnakrit.dev/th/posts/hermes-agent-setup/</guid><description>เปลี่ยน AI จาก Web Chatbot สู่ Local Autonomous Agent บน Windows: ต่อ OmniRoute Gateway, Custom MCP (Edge CDP), Multi-Tier Memory และระบบความปลอดภัยแยก Profile</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;ผลลัพธ์&lt;/h2&gt;
&lt;p&gt;ติดตั้งและปรับแต่งระบบ &lt;strong&gt;Hermes Agent (Nous Research)&lt;/strong&gt; บนเครื่อง Windows เพื่อใช้งานเป็น Local Autonomous Agent สำหรับงาน Pair Programming, DevOps และงานระบบอัตโนมัติ — ทำงานร่วมกับ &lt;strong&gt;OmniRoute Gateway&lt;/strong&gt;, พัฒนา &lt;strong&gt;Custom MCP Server (&lt;code&gt;edgebot-mcp&lt;/code&gt;)&lt;/strong&gt; สำหรับควบคุมเบราว์เซอร์แยกโปรไฟล์, และเชื่อมต่อระบบหน่วยความจำ &lt;strong&gt;3-Tier Memory Architecture&lt;/strong&gt; โดยไม่ให้กระทบความเป็นส่วนตัวบนเครื่องหลัก&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหา&lt;/h2&gt;
&lt;p&gt;การใช้งาน Web Chatbot (เช่น ChatGPT หรือ Claude Web) มีข้อจำกัดอย่างมากในการทำงานร่วมกับระบบจริงในเครื่อง (Hands-on Development):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ไม่สามารถเข้าถึง Environment ท้องถิ่น:&lt;/strong&gt; ไม่สามารถอ่าน/แก้ไฟล์ใน Repository, รันคำสั่ง Terminal, หรือทำ Automated Testing ได้โดยตรง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ติดปัญหา Context Window &amp;amp; Loss of Memory:&lt;/strong&gt; การคุยงานยาวๆ ทำให้บริบทหาย ต้องคอยป้อน System Prompt ซ้ำๆ ทุกวัน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ขาดความยืดหยุ่นในการขยายเครื่องมือ (Tooling):&lt;/strong&gt; ไม่สามารถเชื่อมต่อกับ Service ภายในบ้าน (Homelab, Private VPS, Local Scripts) ได้&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ความเสี่ยงด้าน Privacy &amp;amp; Security:&lt;/strong&gt; การให้ Agent คุมเบราว์เซอร์หลักอาจทำให้ Session หรือรหัสผ่านส่วนตัวรั่วไหล&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;สถาปัตยกรรมระบบ (Architecture)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://www.chinnakrit.dev/assets/diagrams/hermes-agent-architecture.svg&quot; alt=&quot;Hermes Agent Local Runtime Architecture&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;ที่สร้างและติดตั้งจริง&lt;/h2&gt;
&lt;h3&gt;1. Model Routing ด้วย OmniRoute&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ใช้ &lt;strong&gt;OmniRoute Desktop&lt;/strong&gt; รันเป็น Local Gateway ที่พอร์ต &lt;code&gt;127.0.0.1:20128&lt;/code&gt; ทำหน้าที่เป็นศูนย์กลางกระจาย Request และสลับโมเดล AI&lt;/li&gt;
&lt;li&gt;ช่วยให้ Agent สามารถสลับใช้งานระหว่างโมเดลต่าง ๆ (เช่น Gemini 3.7 Flash, DeepSeek-V4, Claude) และรับมือกับปัญหา Upstream 429/502 ได้อย่างราบรื่นผ่าน Fallback Policy&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. พัฒนา Custom MCP Server (&lt;code&gt;edgebot-mcp&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;เพื่อแก้ปัญหาการดึงข้อมูลจากแพลตฟอร์มที่ต้องใช้ Session การเข้าสู่ระบบ โดยไม่ให้แตะต้องเบราว์เซอร์หลัก:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Architecture:&lt;/strong&gt; สร้างด้วย Python &lt;code&gt;mcp 2.0&lt;/code&gt; สื่อสารผ่าน Chrome DevTools Protocol (CDP) บน WebSocket โดยตรง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strict Isolation:&lt;/strong&gt; สั่งเปิด Edge ขึ้นมาเองบนพอร์ตเฉพาะ &lt;code&gt;9333&lt;/code&gt; พร้อม Profile แยก (&lt;code&gt;~/.hermes-edge-profile&lt;/code&gt;) โดยเด็ดขาด ไม่แตะต้องพอร์ต &lt;code&gt;9222&lt;/code&gt; ของ Brave/Chrome ส่วนตัว&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools Included:&lt;/strong&gt; &lt;code&gt;launch_browser&lt;/code&gt;, &lt;code&gt;check_login&lt;/code&gt;, &lt;code&gt;navigate&lt;/code&gt;, &lt;code&gt;read_page&lt;/code&gt;, &lt;code&gt;read_post&lt;/code&gt;, &lt;code&gt;read_group_feed&lt;/code&gt;, &lt;code&gt;expand_content&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. ระบบความจำแบบ 3 ชั้น และการย้ายสู่ Homelab Distributed Plane (3-Tier Memory Stack)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ชั้นความจำ&lt;/th&gt;
&lt;th&gt;ระบบที่ใช้&lt;/th&gt;
&lt;th&gt;หน้าที่และการทำงาน&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tier 1: Short-term&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hermes Context Buffer&lt;/td&gt;
&lt;td&gt;เก็บประวัติบทสนทนาและผลลัพธ์ของ Tool ภายในเซสชัน&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tier 2: Semantic Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hindsight Engine&lt;/td&gt;
&lt;td&gt;ดึงข้อมูลความจำแบบอัตโนมัติ (Vector Search ด้วย &lt;code&gt;bge-small-en-v1.5&lt;/code&gt; + Re-ranking ด้วย &lt;code&gt;ms-marco-MiniLM-L-6-v2&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tier 3: Trusted Vault&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12oo (Obsidian Markdown)&lt;/td&gt;
&lt;td&gt;ข้อมูลจริงที่ผ่านการตรวจสอบโดยมนุษย์ (Human-in-the-Loop) เพื่อป้องกันปัญหา AI Hallucination&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Distributed Architecture (Homelab Migration):&lt;/strong&gt; เพื่อแก้ปัญหา Resource Contention บนเครื่องพัฒนาหลัก ได้ทำการย้าย Data Plane ของ Hindsight (PostgreSQL 18 + 4,100+ Facts) ไปรันบน &lt;strong&gt;Headless Homelab PC (&lt;code&gt;192.168.1.137&lt;/code&gt;)&lt;/strong&gt; ผ่าน SSH Reverse Tunnel (&lt;code&gt;-R 20128:127.0.0.1:20128&lt;/code&gt;) ช่วยคืน RAM บน Laptop ได้ ~1.3 GB พร้อมเชื่อมต่อด้วยโหมด &lt;code&gt;local_external&lt;/code&gt; ข้ามเครือข่าย LAN&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;4. Voice-to-OS Subsystem (Fast System 1 Intent Routing)&lt;/h3&gt;
&lt;p&gt;เสริมระบบสั่งการด้วยเสียงภาษาไทยแบบ Sub-200ms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dual-Backend STT:&lt;/strong&gt; เลือกรัน Faster-Whisper (CUDA บน RTX 4050 กิน VRAM ~1.5GB) สลับกับ Groq Whisper Cloud (0 MB VRAM)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-Hallucination Intent Router:&lt;/strong&gt; ใช้ Groq LPU (&lt;code&gt;gpt-oss-20b&lt;/code&gt; + Strict JSON Schema) ทำ Latency เพียง ~120ms พร้อมสแกน 155 Desktop Apps จาก Start Menu มาแมปเป็น Discrete Target โดยตรง ทำให้การสั่งเปิดโปรแกรม/เบราว์เซอร์แม่นยำ 100% โดยเหลือ VRAM บนการ์ดจอมากกว่า 4.1GB สำหรับงานพัฒนาอื่น&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;ปัญหาทางเทคนิคและการแก้ไข (Technical Challenges)&lt;/h2&gt;
&lt;h3&gt;1. MCP SDK 2.0 Breaking Changes &amp;amp; Schema Generation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ปัญหา:&lt;/strong&gt; SDK เวอร์ชันใหม่ยกเลิก &lt;code&gt;FastMCP&lt;/code&gt; และการใช้ decorator ครอบฟังก์ชันที่มี &lt;code&gt;**kwargs&lt;/code&gt; ทำให้ตัวตรวจ Schema สร้างพารามิเตอร์ผิดพลาด (&lt;code&gt;Field required: kwargs&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; ปรับมาใช้ &lt;code&gt;MCPServer&lt;/code&gt; ระดับล่างร่วมกับ &lt;code&gt;functools.wraps&lt;/code&gt; เพื่อให้ Server สามารถอนุมาน JSON Schema ของ Function signature ได้ถูกต้อง&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Edge CDP WebSocket Origin Rejection&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ปัญหา:&lt;/strong&gt; Edge เวอร์ชัน 111 ขึ้นไปปฏิเสธการเชื่อมต่อ WebSocket จาก Localhost โดยตอบกลับเป็น &lt;code&gt;WebSocketBadStatusException 403&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; เพิ่ม Flag &lt;code&gt;--remote-allow-origins=*&lt;/code&gt; และ &lt;code&gt;--user-data-dir&lt;/code&gt; ในคำสั่งเปิด Browser Instance ภายใน Server&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Path Resolution &amp;amp; Line-Ending บนสภาพแวดล้อม Windows&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ปัญหา:&lt;/strong&gt; Hermes ทำงานบนสภาพแวดล้อมจำลอง Git Bash (MSYS) ทำให้เกิดความไม่สอดคล้องระหว่าง Native Windows Paths (&lt;code&gt;C:\...&lt;/code&gt;) กับ POSIX Paths (&lt;code&gt;/c/...&lt;/code&gt;) รวมถึงการแปลง Line Endings (&lt;code&gt;CRLF vs LF&lt;/code&gt;) ส่งผลให้ Tool ตรวจสอบความถูกต้องของข้อความล้มเหลว&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;การแก้ไข:&lt;/strong&gt; กำหนดข้อบังคับในระบบ Tool ให้ส่ง Path เป็น Native Windows Absolute Path เสมอเมื่อเรียกโปรแกรมภายนอก และ Normalize Line Ending ก่อนตรวจสอบ Payload&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;สิ่งที่ได้เรียนรู้ (Key Learnings)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Agent ที่ดีขึ้นอยู่กับ Guardrails และ Tooling:&lt;/strong&gt; ความฉลาดของโมเดลเป็นเพียงครึ่งเดียว แต่ความเสถียรมาจากการออกแบบ Tool, การจัดการ Error, และการจำกัดสิทธิ์ (Sandboxing)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;แยก Environment ให้ขาดจากระบบส่วนตัว:&lt;/strong&gt; การสร้างโปรไฟล์เบราว์เซอร์แยกและพอร์ตเฉพาะช่วยให้ทดสอบระบบอัตโนมัติได้อย่างปลอดภัย 100%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;อย่าเชื่อ Memory ของ AI เพียงอย่างเดียว:&lt;/strong&gt; การมี Trusted Layer อย่าง Obsidian Markdown (12oo) ที่มนุษย์ตรวจสอบได้ ช่วยป้องกันการสะสมความจำที่ผิดพลาดข้ามวัน&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;Tech Stack&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Hermes Agent Core, Python 3.11, Model Context Protocol (MCP 2.0),
OmniRoute Gateway, Chrome DevTools Protocol (CDP), WebSocket,
Hindsight Memory Engine (PostgreSQL + BGE Embeddings), Git Bash, Windows 11
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;คำถามที่พบบ่อย (FAQ)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;ทำไมเลือก Hermes Agent แทน AI Coding Tool อื่นๆ?&lt;/strong&gt;
Hermes มีความยืดหยุ่นสูงในระดับ Gateway &amp;amp; Desktop สามารถเขียน Skills ปรับแต่ง Workflow ควบคุม MCP หลายสิบตัว และสลับโมเดลหลังบ้านได้อิสระ&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ระบบรักษาความปลอดภัยของไฟล์และ Credentials ทำงานอย่างไร?&lt;/strong&gt;
กำหนดกติกาการทำงานแบบ Human-in-the-loop: ไม่บันทึก Secrets ใน Prompt, ใช้ Masked Input ในการกรอก Token และมีระบบขออนุญาตก่อนรันคำสั่งที่ส่งผลกระทบต่อระบบหลัก&lt;/p&gt;
</content:encoded><category>AI Agents</category><category>Hermes Agent</category><category>MCP</category><category>DevOps</category><category>Architecture</category></item><item><title>Case Study: สร้าง Portfolio v2 ใหม่ หลัง v1 ถูกลบ</title><link>https://www.chinnakrit.dev/th/posts/portfolio-v2-rebuild/</link><guid isPermaLink="true">https://www.chinnakrit.dev/th/posts/portfolio-v2-rebuild/</guid><description>สร้างพอร์ตโฟลิโอใหม่ด้วย Astro 5 จากศูนย์ AEO schema ครบ Deploy อัตโนมัติ</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;ผลลัพธ์&lt;/h2&gt;
&lt;p&gt;สร้างพอร์ตโฟลิโอใหม่ด้วย Astro 5 จากศูนย์ หลัง v1 ถูกลบ — 15 หน้า, AEO schema ครบ, Deploy อัตโนมัติผ่าน Vercel&lt;/p&gt;
&lt;h2&gt;ปัญหา&lt;/h2&gt;
&lt;p&gt;Portfolio v1 (Astro + Product Studio) ถูกลบ 2026-09-08 เนื้อหาหายหมด ต้องสร้างใหม่ให้:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ติด Google เมื่อค้นหา &quot;Chinnakrit portfolio&quot;&lt;/li&gt;
&lt;li&gt;AI (ChatGPT, Perplexity) อ้างอิงได้&lt;/li&gt;
&lt;li&gt;รองรับ EN/TH&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ที่สร้าง&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; Astro 5 + Tailwind 3 + Svelte 5 + swup + pagefind
&lt;strong&gt;Fork:&lt;/strong&gt; saicaca/fuwari → Besty0728/fuwari (ลบ 12 component ที่ไม่ใช้)
&lt;strong&gt;Deploy:&lt;/strong&gt; Vercel (auto-deploy ตอน push main)
&lt;strong&gt;Domain:&lt;/strong&gt; www.chinnakrit.dev&lt;/p&gt;
&lt;h3&gt;AEO ที่ทำ&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;เทคนิค&lt;/th&gt;
&lt;th&gt;การใช้&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Organization + Person Schema&lt;/td&gt;
&lt;td&gt;JSON-LD ใน Layout.astro + sameAs GitHub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FAQPage Schema&lt;/td&gt;
&lt;td&gt;5 คำถามใน About (EN+TH)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;llms.txt&lt;/td&gt;
&lt;td&gt;public/llms.txt + llms-full.txt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;เนื้อหา&lt;/td&gt;
&lt;td&gt;เขียนแบบ Inverted Pyramid — ตอบก่อน ลงรายละเอียดทีหลัง&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;i18n&lt;/td&gt;
&lt;td&gt;EN ที่ &lt;code&gt;/&lt;/code&gt; TH ที่ &lt;code&gt;/th/&lt;/code&gt; พร้อม hreflang&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;ผลที่วัดได้&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Build 3.5 วินาที, 15 หน้า&lt;/li&gt;
&lt;li&gt;ChatGPT index แล้ว (ยืนยันจากการค้นหา)&lt;/li&gt;
&lt;li&gt;JSON-LD ผ่านโครงสร้าง Google Rich Results Test&lt;/li&gt;
&lt;li&gt;ไม่มี GA / Ads / Tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ตัดสินใจสำคัญ&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;เลือก Astro แทน Next.js — build เร็วกว่า, deploy ง่ายกว่า สำหรับ portfolio แบบ static&lt;/li&gt;
&lt;li&gt;ลบ component เจ้าของทั้งหมด — codebase สะอาดขึ้นมาก&lt;/li&gt;
&lt;li&gt;เขียน content แบบ AEO-first — ทุกหน้าตอบคำถามเดียวใน 40 คำแรก&lt;/li&gt;
&lt;li&gt;ทำ i18n ตั้งแต่วันแรก ไม่ใช่มาตามหลัง&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;ปัญหา&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;เนื้อหา v1 หาย — ต้องเขียนใหม่ทั้งหมด (บังคับให้ออกแบบใหม่)&lt;/li&gt;
&lt;li&gt;Biome lint มี 133 diagnostic — แก้เฉพาะ critical, build ผ่าน&lt;/li&gt;
&lt;li&gt;Works ยังว่าง — ต้องเขียน case study เพิ่ม&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ที่เรียนรู้&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AEO schema อย่างเดียวไม่พอ — ต้องมี content ลึกพอ&lt;/li&gt;
&lt;li&gt;AI citation ต้องข้อมูล consistent: page = schema = sameAs&lt;/li&gt;
&lt;li&gt;Astro + Vercel = loop เร็วที่สุดสำหรับปรับ portfolio&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tech Stack&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Astro 5, Tailwind CSS, Svelte 5, TypeScript, Vercel, Schema.org JSON-LD
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;ลิงก์&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chinnakrit.dev&quot;&gt;เว็บจริง&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Manchinn/portfolio-v2&quot;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://prompts.chinnakrit.dev&quot;&gt;Prompt library&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;คำถามที่พบบ่อย&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;ทำไมไม่กู้ v1 กลับมา?&lt;/strong&gt;
v1 ถูกลบถาวร ไม่มี backup ต้องสร้างใหม่&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AEO ได้ผลจริงไหม?&lt;/strong&gt;
ChatGPT index แล้วหลังใส่ schema + content — กำลังติดตาม citation share&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ทำอีกครั้งจะต่างยังไง?&lt;/strong&gt;
เริ่มจากเขียน case study ก่อน แล้วค่อย technical setup — content สำคัญกว่า code สำหรับ AEO&lt;/p&gt;
</content:encoded><category>Astro</category><category>Tailwind</category><category>AEO</category><category>Schema.org</category></item></channel></rss>