12 min readAI
OpenSpec: ล็อกสเปกให้ตรงกันก่อน แล้วค่อยให้ AI เขียนโค้ด
Agent เขียนโค้ดได้เร็วจนเราข้ามขั้นตกลงกันว่างานนี้ต้องทำอะไร แล้วไปเจอทีหลังว่าคำเดาของมันถูกล็อกไว้ใน test ที่เขียวแล้ว บันทึกจากเดฟ·PM·PO ที่ลองใช้ workflow ของ OpenSpec ซึ่งแยกการ Explore, Propose และ Review ออกจากการ Apply ว่าทำไมการแก้แผนตอนที่ยังเป็นตัวหนังสือถึงถูกกว่าการแก้โค้ดมาก และงานแบบไหนในบริษัทรับจ้างพัฒนาที่ควรล็อกสเปกก่อนเสมอ

ความเร็วของ agent มีผลข้างเคียงอย่างหนึ่งที่ผมเพิ่งเห็นชัดครับ มันทำให้ขั้น "ตกลงกันก่อนว่าจะทำอะไร" ดูเป็นเรื่องเสียเวลา
เมื่อก่อนถ้า requirement ยังไม่ชัด อย่างน้อยเราก็ต้องคุยกันก่อนสักรอบ เพราะการเขียนโค้ดแพง ไม่มีใครอยากเขียนไปสองวันแล้วรื้อ แต่ตอนนี้พิมพ์สองบรรทัด รอห้านาที ก็ได้ฟีเจอร์ที่รันได้พร้อม test ครบ ความรู้สึกแรกคือ "ทำไปก่อนเลย เดี๋ยวผิดค่อยแก้" ซึ่งฟังมีเหตุผลมาก จนกระทั่งเราต้องไล่อ่าน diff ห้าร้อยบรรทัดเพื่อหาว่าตรงไหนที่ agent ตัดสินใจแทนลูกค้าไป
ผมเป็นทั้ง developer, PM และ PO ที่ Mulberrysoft ดูแลทีม junior ทำงานกับลูกค้าที่ requirement แทบไม่เคยครบ และใช้ Claude, Codex กับ agent อื่น ๆ แทบทุกวัน ซีรีส์นี้เริ่มจากการให้ agent ทำงานแทนโดยไม่ให้มันคิดแทน ต่อด้วยวันที่คำตอบของ agent กลายเป็นความเห็นของเรา หนี้ความเข้าใจที่ไม่ขึ้นบน dashboard เจตนาที่ agent จ่ายแทนไม่ได้ และสีเขียวที่ไม่ได้แปลว่าถูก สองโพสต์หลังจบด้วยคำถามคล้ายกัน คือถ้าปัญหาเกิดจากการที่เราไม่ได้ตกลงกันไว้ก่อน แล้วในทางปฏิบัติจะ "ตกลงกันไว้ก่อน" ยังไงให้ไม่กลายเป็นเอกสารสามสิบหน้าที่ไม่มีใครอ่าน
โพสต์นี้คือคำตอบหนึ่งที่ผมกำลังลองครับ จุดยืนของผมคือ ล็อกสเปกก่อนโค้ด ให้คนกับ agent ตกลงกันให้ได้ว่า "เสร็จ" แปลว่าอะไร ตอนที่ทุกอย่างยังเป็นตัวหนังสือ แล้วค่อยปล่อยให้ agent ลงมือ
จุดเริ่มต้นจากโพสต์สั้น ๆ บน X
ผมเห็น โพสต์ของ nurijanian บน X ที่ลิสต์ทักษะที่เขาคิดว่า PM ทุกคนควรรู้ หนึ่งในนั้นเขียนสั้น ๆ ว่า OpenSpec คือ "agree the spec before code"
สี่คำนี้ตรงกับสิ่งที่ผมพยายามอธิบายมาสองโพสต์แบบพอดีเลยครับ ในโพสต์ Intent Debt ผมพูดถึงคำเดาที่ถูกประทับตรา ในโพสต์ Verify ผมพูดถึง test ที่เขียวบน acceptance ที่ผิด ทั้งสองอาการมีต้นทางเดียวกัน คือ agent เริ่มเขียนโค้ดก่อนที่ใครจะตกลงอะไรกัน และพอโค้ดออกมาแล้ว การตัดสินใจทั้งหมดก็ถูกฝังไว้ในนั้นเรียบร้อย
ผมเลยไปอ่าน OpenSpec ต่อ และอยากเล่าว่ามันคืออะไรจริง ๆ ก่อนจะเล่าว่าผมคิดยังไงกับมัน
Vibe ตรงไปที่โค้ด กับ ล็อกแล้วค่อย Apply
ขอเทียบสองแบบให้เห็นภาพก่อนครับ
แบบแรก vibe ตรงไปที่โค้ด เราเล่า requirement ให้ agent ฟังในแชต มันเริ่มแก้ไฟล์เลย ระหว่างทางเราเห็นอะไรไม่ถูกใจก็พิมพ์แก้ไปเรื่อย ๆ สุดท้ายได้โค้ดที่รันได้ แต่ "สเปก" ของงานนี้กระจายอยู่ในประวัติแชตยาวเหยียด ครึ่งหนึ่งเป็นสิ่งที่เราพูด อีกครึ่งเป็นสิ่งที่ agent เลือกเองโดยไม่ได้พูดออกมา พอปิดแชต สเปกนั้นก็หายไปด้วย
แบบที่สอง ล็อกแล้วค่อย apply ก่อนแตะโค้ด agent ต้องเขียนออกมาก่อนว่าจะทำอะไร ทำไม และอะไรนับว่าเสร็จ เราอ่าน แก้ จนตรงกับที่ต้องการ แล้วค่อยสั่งให้มันทำตามแผนที่ตกลงกันแล้ว ถ้าระหว่างทางพบว่าแผนผิด ก็กลับไปแก้แผนก่อน ไม่ใช่แก้แต่โค้ด
แบบแรกเร็วกว่าในห้านาทีแรกเสมอครับ แต่ผมคิดว่าแบบที่สองเร็วกว่าเมื่อนับถึงวันที่ลูกค้า UAT เพราะสิ่งที่แพงที่สุดในงานรับจ้างพัฒนาไม่ใช่การพิมพ์โค้ด แต่คือการรื้อสิ่งที่ทำไปแล้วเพราะเข้าใจโจทย์ไม่ตรงกัน และยิ่งรื้อช้าเท่าไร ยิ่งมีโค้ดอื่นมาพึ่งมันมากขึ้นเท่านั้น
OpenSpec คืออะไรจริง ๆ
OpenSpec เรียกตัวเองว่า workflow สเปกแบบเบาสำหรับ coding agent ครับ ติดตั้งผ่าน npm ด้วย npm install -g @fission-ai/openspec@latest และใช้ร่วมกับเครื่องมือที่เราใช้อยู่แล้ว เช่น Claude Code, Codex หรือ Cursor ไม่ได้บังคับให้ย้ายไปใช้ agent ตัวใหม่
หัวใจของมันคือ loop ห้าขั้นตามที่เขียนไว้ใน หน้า Quickstart ผมสรุปตามที่เอกสารเขียน ไม่ได้เติมเองนะครับ
1. Explore คิดไปด้วยกันกับ agent ให้มันสำรวจ codebase ถามคำถาม และร่างทางเลือก ขั้นนี้ ไม่เขียนโค้ดเลย ผลลัพธ์ของมันคือไอเดียที่คมขึ้น
2. Propose agent ร่าง change folder ไว้ที่ openspec/changes/<name>/ ข้างในมี
proposal.mdบอกว่าทำไมต้องเปลี่ยน และเปลี่ยนอะไรspecs/บอกว่า "เสร็จ" แปลว่าอะไร ในรูป requirement ที่ทดสอบได้design.mdการตัดสินใจทางเทคนิค มีเฉพาะเมื่อจำเป็นtasks.mdchecklist สำหรับลงมือทำ
ขั้นนี้ก็ยังไม่มีโค้ดครับ Propose หยุดอยู่ที่แผน
3. Review คนแก้แผนตอนที่มันยังเป็นตัวหนังสือ เอกสารแนะนำลำดับการอ่านไว้ว่า proposal.md ก่อน ตามด้วย specs/ ซึ่งเขาบอกว่าเป็นส่วนที่คุ้มค่าที่สุด แล้วค่อย tasks.md จะแก้ไฟล์เองก็ได้ หรือบอก agent ว่าตรงไหนผิดก็ได้
4. Apply agent ลงมือทีละ task ตามแผนที่ล็อกแล้ว และติ๊กใน tasks.md ไปเรื่อย ๆ เอกสารแนะนำให้เปิดแชตใหม่สำหรับขั้นนี้ ถ้าถูกขัดจังหวะ ก็กลับมาทำต่อที่ task แรกที่ยังไม่ได้ติ๊ก และถ้าพบว่าแผนผิด ให้แก้ artifact ก่อนแล้วค่อยทำต่อ
5. Archive รวม delta spec ของ change นั้นเข้าไปใน openspec/specs/ หลัก แล้วย้าย change folder ไปไว้ที่ openspec/changes/archive/YYYY-MM-DD-<name>/
ที่ผมชอบคือมันไม่ได้มีอะไรวิเศษครับ ทุกอย่างเป็นไฟล์ Markdown อยู่ใน repo อ่านได้ด้วยตา แก้ได้ด้วยมือ และ review ใน PR ได้เหมือนโค้ด สิ่งที่ OpenSpec ให้จริง ๆ คือ ลำดับ ที่บังคับว่าคิดก่อน เขียนแผนก่อน ตกลงกันก่อน แล้วค่อยลงมือ
ทำไมการ Review ตอนที่ยังเป็นตัวหนังสือถึงสำคัญกับ PM และ PO
ถ้าให้เลือกขั้นเดียวใน loop นี้ที่ผมคิดว่าเปลี่ยนงานของ PM กับ PO มากที่สุด ผมเลือก Review ครับ
ลองนึกถึงตอนรีวิว PR จาก agent ตามปกติ เรากำลังอ่านโค้ดเพื่อเดาว่ามันตัดสินใจอะไรไปบ้าง ต้องแปลจาก if (user.role !== 'admin') กลับมาเป็นประโยค "เฉพาะ admin ทำได้" แล้วค่อยถามตัวเองว่าลูกค้าตกลงแบบนี้หรือเปล่า งานแปลนี้ช้า เหนื่อย และพลาดง่าย โดยเฉพาะเมื่อ diff ยาว และสำหรับ PO ที่ไม่ได้อ่านโค้ดทุกวัน แทบเป็นไปไม่ได้
แต่ใน specs/ การตัดสินใจเดียวกันถูกเขียนเป็นประโยคตั้งแต่แรก เช่น "ผู้ใช้ role บัญชีและ admin เท่านั้นที่ export ได้" ผมอ่านแล้วรู้ทันทีว่าตรงหรือไม่ตรงกับที่ลูกค้าบอก ถ้าไม่ตรง ผมแก้ประโยคเดียว ไม่ต้องรอให้ agent รื้อโค้ด test และ migration ที่มันเขียนตามความเข้าใจผิดไปแล้ว
ผมคิดว่านี่คือเหตุผลที่เอกสารของ OpenSpec บอกว่า specs/ คือส่วนที่คุ้มที่สุดที่จะอ่านครับ เพราะมันคือจุดที่เจตนาของคนกับความเข้าใจของ agent มาเจอกันในภาษาที่ทั้งสองฝ่ายอ่านออก
อีกเรื่องที่ผมชอบคือ Review ทำให้ PO มีที่ยืนในงานที่ agent ทำครับ เมื่อก่อนผมรู้สึกว่าเวลาน้องสั่ง agent ทำงาน หน้าที่ของผมเริ่มตอนเห็น PR ซึ่งก็คือตอนที่ทุกอย่างถูกตัดสินไปแล้ว พอมีขั้น Review แทรกก่อน Apply ผมได้เข้าไปตอนที่การตัดสินใจยังเปลี่ยนได้ราคาถูก
ต่อจาก Intent Debt และ Verify Paradox
ถ้ามองย้อนกลับไปที่สองโพสต์ก่อน ผมเห็นว่า OpenSpec ไม่ได้แก้ปัญหาใหม่ แต่ให้รูปร่างกับคำแนะนำที่ผมเขียนไว้แล้วครับ
ในโพสต์ Intent Debt ผมบอกว่าช่องว่างใน prompt จะถูกเติมเสมอ คำถามคือใครเติมและรู้ตัวไหม และเจตนาที่อยู่แค่ใน prompt จะหายไปพร้อม session ใน OpenSpec สองปัญหานี้ถูกจับไว้คนละที่ ช่องว่างถูกดึงออกมาให้เห็นใน Explore และ Propose ก่อนจะถูกเติมเงียบ ๆ ในโค้ด ส่วนเจตนาที่ตกลงกันแล้วไม่ได้หายไปกับแชต เพราะมันอยู่ใน proposal.md กับ specs/ และสุดท้ายถูก archive เข้าไปในสเปกหลักของ repo ให้ agent ตัวถัดไปอ่านได้
ในโพสต์ Verify ผมบอกว่าต้องนิยามคำว่า verified ไว้ก่อนเริ่มงาน เพราะหลังเห็นผลเราจะหาเหตุผลให้ตัวเอง และ test ที่เข้ารหัส acceptance ผิดจะปกป้องความผิดนั้นไว้ specs/ คือที่ที่นิยามนั้นอยู่ครับ เมื่อ acceptance ถูกเขียนเป็น requirement ที่ทดสอบได้และมีคนอ่านยืนยันแล้ว test ที่ agent เขียนตอน Apply ก็มีอะไรให้เทียบ แทนที่จะเป็น test ที่ยืนยันคำเดาของมันเอง
ต้องพูดตรง ๆ ด้วยนะครับว่า OpenSpec ไม่ได้รับประกันอะไรเลยถ้าเราไม่อ่าน ถ้าเรากด Propose แล้วกด Apply ต่อทันทีโดยข้าม Review สิ่งที่ได้คือคำเดาของ agent ในรูปแบบที่ดูเป็นทางการขึ้น ซึ่งอาจอันตรายกว่าเดิมด้วย เพราะมันมีหน้าตาเหมือนข้อตกลง ตรงนี้ผมว่าเชื่อมกับโพสต์ Cognitive Surrender พอดี สเปกที่เขียนสวยอ่านลื่นทำให้เราพยักหน้าได้ง่ายมาก เครื่องมือช่วยจัดลำดับให้ได้ แต่การคิดตอน Review ยังต้องเป็นของคน
งานแบบไหนที่ผมจะล็อกสเปกก่อน
ผมไม่คิดว่าทุกงานต้องผ่าน loop นี้ครับ การเปลี่ยนสีปุ่มหรือแก้ typo ไม่ต้องมี proposal.md นี่คือเกณฑ์ที่ผมเรียบเรียงเองจากงานแบบ Mulberrysoft ไม่ได้มาจากเอกสารของ OpenSpec
ควรล็อกสเปกก่อนเสมอ เมื่อ
- งานแตะเงิน สิทธิ์ หรือข้อมูลลูกค้า ส่วนลด การคำนวณยอด role ที่ทำอะไรได้ การ export ข้อมูล คำเดาผิดในหมวดนี้แพงที่สุด และ test ที่ agent เขียนจะไม่ล้มเพราะมัน
- ลูกค้าจะเห็นผลโดยตรง หน้าจอ อีเมลแจ้งเตือน ข้อความ error ถ้าพลาด ลูกค้าจะถามว่า "ทำไมเป็นแบบนี้" และเราควรตอบได้ด้วยข้อตกลง ไม่ใช่ "ระบบออกมาแบบนี้"
- requirement มาไม่ครบ ซึ่งคืองานส่วนใหญ่ของผม ขั้น Explore ช่วยไล่หาคำถามที่ต้องกลับไปถามลูกค้าได้ดีมาก และ
proposal.mdใช้เป็นฐานคุยกับลูกค้าได้เลย - น้อง junior เป็นคนสั่ง agent ผมรีวิว
specs/ของน้องได้ในสิบนาที เร็วกว่าและสอนได้มากกว่ารีวิว diff ยาว ๆ แล้วค่อยบอกว่าโจทย์ผิด - งานใหญ่พอที่จะข้าม session ถ้าทำไม่จบในแชตเดียว การมี
tasks.mdที่ติ๊กไว้ทำให้กลับมาทำต่อได้โดยไม่ต้องเล่าใหม่ ตรงกับที่เอกสารบอกว่าให้ resume ที่ task แรกที่ยังไม่ติ๊ก
ไม่จำเป็น หรือยังไม่คุ้ม เมื่อ
- งานเล็กและย้อนกลับได้ง่าย เช่น แก้ข้อความ ปรับ spacing
- prototype ทิ้งเพื่อให้ลูกค้าเห็นภาพ งานแบบนี้ผมยังให้ agent ทำเร็ว ๆ ได้ แต่ถือว่าผลลัพธ์คือคำถาม ไม่ใช่สเปก ถ้าลูกค้าชอบแล้วจะทำจริง ค่อยเริ่ม Explore จากสิ่งที่เรียนรู้มา
- บั๊กที่สาเหตุชัดและการแก้ไม่เปลี่ยนพฤติกรรมที่ตกลงไว้
ถ้าลังเล ผมใช้คำถามเดียวครับ ถ้า agent เดาผิดในงานนี้ ใครจะเป็นคนเจอ และเจอเมื่อไร ถ้าคำตอบคือ "ลูกค้า ตอน UAT" งานนั้นควรล็อกสเปกก่อน
นิสัยที่ผมจะลองใช้
Explore ก่อนทุกครั้งที่ requirement มีคำว่า "ประมาณ" หรือ "แบบ" เช่น "ขอแบบ dashboard ที่ลูกค้าอีกเจ้ามี" ผมจะให้ agent สำรวจ codebase และลิสต์คำถามที่ต้องตอบก่อน แล้วเอารายการนั้นไปถามลูกค้า แทนที่จะให้มันเลือกคำตอบเอง
อ่าน specs/ ด้วยหมวก PO ไม่ใช่หมวก dev ตอน Review ผมจะถามว่าแต่ละ requirement มาจากลูกค้า มาจากผม หรือ agent คิดเอง ข้อที่ agent คิดเองไม่ได้ผิดเสมอไป แต่ต้องมีคนตัดสินว่ายอมรับ หรือเขียนไว้ว่ารอลูกค้ายืนยัน
เขียน "ยังไม่รู้" ไว้ในสเปกให้ชัด ต่อจากที่เขียนในโพสต์ Intent Debt ว่า "ยังไม่รู้" เป็น intent ที่ใช้ได้ถ้าถูกเขียนไว้ ถ้าเรื่องไหนรอลูกค้า ผมจะให้มันอยู่ใน proposal.md พร้อมสมมติฐานชั่วคราวที่มีเจ้าของ
Apply ในแชตใหม่ ตามที่เอกสารแนะนำ ผมคิดว่าเหตุผลเชิงปฏิบัติคือมันบังคับให้แผนต้องพอในตัวเอง ถ้า agent ในแชตใหม่ทำงานตามไฟล์ไม่ได้ แปลว่าส่วนสำคัญยังอยู่ในแชตเก่าหรือในหัวผม ไม่ได้อยู่ในสเปก
แผนผิดให้แก้แผน ไม่ใช่แก้แต่โค้ด อันนี้ผมคาดว่าจะทำพลาดบ่อยที่สุด เพราะพิมพ์บอก agent ว่า "ตรงนี้เปลี่ยนเป็นแบบนี้" ง่ายกว่ากลับไปแก้ specs/ แต่ถ้าแก้แค่โค้ด สเปกกับระบบจะเริ่มไม่ตรงกันตั้งแต่ change แรก และสเปกที่ไม่ตรงกับระบบอันตรายกว่าไม่มีสเปก
ให้น้องในทีมเริ่มจาก Propose แล้วมาคุยกันก่อน Apply สำหรับงานที่เข้าเกณฑ์ข้างบน ผมจะขอให้น้องเปิด change folder แล้วชวนผมอ่าน proposal.md กับ specs/ ด้วยกัน เป็นการรีวิว intent แบบที่ผมเขียนไว้ในโพสต์ก่อน แต่มีไฟล์จริงให้ชี้ ไม่ใช่แค่คุยปากเปล่า
Archive ให้ครบ ขั้นนี้ดูเหมือนงานเก็บกวาด แต่ผมคิดว่ามันคือการจ่ายหนี้เจตนาให้ถูกที่ เพราะสเปกหลักใน openspec/specs/ คือสิ่งที่ agent ตัวถัดไปและน้องคนถัดไปจะได้อ่าน แทนที่จะต้องเดาจากโค้ด
ท้ายที่สุด
ผมไม่ได้คิดว่า OpenSpec เป็นคำตอบเดียวครับ สิ่งเดียวกันนี้ทำได้ด้วย Markdown ไฟล์เดียวกับวินัยของทีม สิ่งที่ผมได้จากการลองคือ loop ที่ตั้งชื่อชัด ๆ ว่า Explore, Propose, Review, Apply, Archive ทำให้คำถาม "เราตกลงกันหรือยัง" มีจังหวะที่ต้องโผล่ขึ้นมาเสมอ ไม่ต้องรอให้ใครนึกได้
ถ้ามองทั้งซีรีส์ intent คือสิ่งที่เราต้องรู้ว่าต้องการ verification คือสิ่งที่เราใช้ตรวจว่าได้ตามนั้น และการล็อกสเปกก่อนโค้ดคือสะพานระหว่างสองอย่าง มันคือจุดที่เจตนาถูกเขียนออกมาในรูปที่ตรวจได้ ก่อนที่ agent จะเริ่มสร้างอะไรขึ้นมาให้เราต้องตรวจ
Agent ทำให้โค้ดถูกลงมากครับ แต่ไม่ได้ทำให้การเข้าใจโจทย์ผิดถูกลงเลย กลับแพงขึ้นด้วยซ้ำ เพราะความผิดนั้นมาพร้อม test ที่เขียวและ PR ที่อ่านลื่น
ดังนั้นครั้งถัดไปที่ผมอยากพิมพ์ "ทำไปก่อนเลย เดี๋ยวผิดค่อยแก้" ผมจะถามตัวเองก่อนว่า ถ้าผิด เราอยากแก้ตอนที่มันเป็นประโยคในไฟล์ Markdown หรือตอนที่มันเป็นโค้ดห้าร้อยบรรทัดที่ลูกค้าเห็นแล้ว
ถ้าคำตอบคืออย่างแรก ก็ล็อกสเปกก่อนครับ แล้วค่อยให้ agent เขียนโค้ด