diff --git a/decisions/0028-versioning-for-tool-response-contracts.md b/decisions/0028-versioning-for-tool-response-contracts.md index c6326ad..2f69435 100644 --- a/decisions/0028-versioning-for-tool-response-contracts.md +++ b/decisions/0028-versioning-for-tool-response-contracts.md @@ -1,7 +1,7 @@ # ADR-0028: contract ที่ส่งผ่าน tool response — กฎ versioning สำหรับช่องทางที่ประกาศไปไม่ถึงผู้รับ **Status:** **Accepted** (2026-09-07) -**อัปเดต:** 2026-09-07 — บันทึกนาฬิกาเรือนที่สาม (ข้อเท็จจริงที่ผู้ขอวัดได้หลัง deploy) · ปิดข้อค้างเรื่องคีย์ที่ถูกลบไปแล้ว · กติกาถูก implement และยืนยันจากฝั่งผู้ใช้แล้ว +**อัปเดต:** 2026-09-07 — บันทึกนาฬิกาเรือนที่สาม (ข้อเท็จจริงที่ผู้ขอวัดได้หลัง deploy) · ปิดข้อค้างเรื่องคีย์ที่ถูกลบไปแล้ว · กติกาถูก implement และยืนยันจากฝั่งผู้ใช้แล้ว · **หดคำกล่าวอ้างเรื่องหน้าต่าง rollout ให้เท่ากับหลักฐาน** ตามที่ผู้ขอทักมาใน `seq 17` **Date:** 2026-09-07 **Depends on:** [ADR-0006](0006-contract-versioning.md) · [ADR-0011](0011-conformance-automation.md) · [ADR-0027](0027-toolid-transformation-must-be-deterministic.md) **Blocking:** `contracts/mcp/v1` (ยังไม่แตะ) · คำขอจาก [`ai-collaboration-mcp`](https://github.com/monthop-gmail/ai-collaboration-mcp) @@ -33,10 +33,18 @@ waiting_for_you { handoffs, tasks } → waiting_for_you { unaccepted, in ```text ผลลัพธ์ของ tool สร้างสด → เปลี่ยนเมื่อ isolate ที่รับคำขอนั้นเป็นตัวใหม่ description/schema ค้างที่ client → เปลี่ยนเมื่อ client เชื่อมต่อใหม่ ซึ่งไม่มีใครรู้ว่าเมื่อไหร่ -ช่วง rollout isolate เก่ากับใหม่ตอบพร้อมกัน → สองรูปมีชีวิตพร้อมกันชั่วขณะ +ช่วง rollout หลัง deploy จบ ยังมีคำขอที่ได้รูปเก่า → สองรูปถูกเสิร์ฟพร้อมกันได้ ``` -**เรือนที่สามเพิ่มเข้ามาหลังเคาะ และเป็นการวัดของฝั่งผู้ขอเอง ไม่ใช่ข้อสันนิษฐานของเรา** — เดิม `seq 13` ระบุว่าผลลัพธ์ *"เปลี่ยนพร้อมกันหมดทุก client ตั้งแต่วินาทีที่ deploy จบ"* และ ADR ฉบับแรกอ้างประโยคนั้น · ตอน deploy กติกานี้จริง เขายิง `get_workspace_context` ทันทีหลัง deploy จบแล้ว **ยังไม่มีฟิลด์ `contract`** ยิงซ้ำอีกไม่กี่วินาทีถัดมาจึงได้ครบ แล้วถอนประโยคเดิมของตัวเองใน `seq 15` +**เรือนที่สามเพิ่มเข้ามาหลังเคาะ และเป็นการวัดของฝั่งผู้ขอเอง ไม่ใช่ข้อสันนิษฐานของเรา** — เดิม `seq 13` ระบุว่าผลลัพธ์ *"เปลี่ยนพร้อมกันหมดทุก client ตั้งแต่วินาทีที่ deploy จบ"* และ ADR ฉบับแรกอ้างประโยคนั้น · ตอน deploy กติกานี้จริง เขายิง `get_workspace_context` ทันทีหลัง `wrangler deploy` รายงานว่าจบ แล้ว **ยังไม่มีฟิลด์ `contract`** ยิงซ้ำอีกไม่กี่วินาทีถัดมาจึงได้ครบ แล้วถอนประโยคเดิมของตัวเองใน `seq 15` + +> **ขอบเขตของหลักฐาน — อ่านให้ตรงกับที่วัดมา** (`seq 17`) +> +> สิ่งที่หลักฐานรองรับคือ **หน้าต่างนั้นมีอยู่จริง** เท่านั้น +> +> สิ่งที่ **ยังไม่รู้และ ADR ฉบับนี้ไม่อ้าง**: หน้าต่างกว้างเท่าไหร่ (สังเกตครั้งเดียว ไม่ได้จับเวลา) · ขึ้นกับอะไรบ้าง (ไม่ได้ทำซ้ำหลาย deploy ไม่ได้ยิงจากหลาย region) · เป็นพฤติกรรมของ Workers ทั่วไปหรือของ deployment รูปแบบนี้โดยเฉพาะ · และ **กลไกเบื้องหลังคืออะไร** — คำว่า *isolate* ที่ใช้กันในกระทู้เป็นคำอธิบายที่น่าเชื่อ ไม่ใช่สิ่งที่วัดได้ +> +> ฉบับก่อนหน้าของ ADR นี้เขียนว่า *"isolate เก่ากับใหม่ตอบพร้อมกัน → สองรูปมีชีวิตพร้อมกันชั่วขณะ"* ซึ่ง **ยืนยันกลไกและความกว้างเกินกว่าที่หลักฐานรองรับ** · ผู้ขอทักมาเอง และถูก — ADR ที่ทั้งใบยืนอยู่บนหลักว่าอย่ารายงานสิ่งที่เชื่อว่าจริงแทนสิ่งที่อ่านมาจริง จะละเมิดหลักของตัวเองในย่อหน้าที่ตั้งใจบันทึกความซื่อตรงไม่ได้ **ข้อนี้ไม่ได้ลดน้ำหนักของคำตอบ แต่เพิ่ม** — กติกาที่พึ่งการประกาศต้องถูกทั้งสามเรือนจึงจะรอด ส่วนกฎห้ามลบไม่ต้องถูกสักเรือน เพราะทุกรูปที่มีชีวิตอยู่ในช่วงนั้นมีคีย์เก่าครบเหมือนกัน @@ -143,9 +151,10 @@ ADR นี้ **ขยายกฎของ [ADR-0006](0006-contract-versioning. * **ทะเบียนคีย์ที่รอลบต้องอยู่ฝั่ง server** ไม่ใช่ที่ [`contracts/README.md`](../contracts/README.md) ของเรา เพราะไม่ใช่ contract ที่เราถือ — เราถือแค่กฎ * **ปิดแล้ว — คีย์ที่ถูกลบเมื่อ 7 ก.ย. ไม่คืน · จุดเริ่มของกฎคือ `contract 2`** · เจ้าของ server เคาะไม่คืน และเหตุผลที่ตัดสินคือข้อที่ **ฝั่งเรามองข้าม**: `waiting_for_you.total` เป็นคีย์ที่ *ยังอยู่แต่ความหมายเปลี่ยน* (เดิมนับซ้ำได้ `2` ตอนนี้ไม่นับซ้ำได้ `1`) ซึ่งกฎข้อ 1 ท่อน *ห้ามเปลี่ยนความหมาย* ห้ามไว้เหมือนกัน — **การคืนแค่ `handoffs`/`tasks` จึงไม่ได้ทำให้ถูกกฎ ต้องคืน `total` แบบเดิมด้วย ซึ่งเท่ากับคืนบั๊กที่ทั้งสองทีมเห็นพ้องกันว่าผิด** · ตอนเราเสนอให้คืน เรานับแต่คีย์ที่หายไป ไม่ได้นับคีย์ที่ยังอยู่แต่ความหมายเปลี่ยน ทั้งที่กฎที่เราเขียนเองครอบทั้งสอง · ข้อยกเว้นครั้งเดียวนี้บันทึกไว้ที่ README และ NOTES ของ server แล้ว **ตั้งแต่ `2` เป็นต้นไปกฎมีผลเต็ม** * **กติกาถูก implement และยืนยันจากฝั่งผู้ใช้แล้ว** — `agent-platform` ยิงเทียบเองในฐานะ client ที่ไม่ได้อยู่ในการ deploy: `description` ที่ client ถืออยู่ขึ้นต้นว่า `contract 2` และ `get_workspace_context` ที่ยิงสดคืน `contract: 2` · **ตรงกัน** · ฝั่ง server ทำเป็น wrapper ของ `registerTool` ไม่ใช่เขียนเลขในข้อความของแต่ละ tool — เหตุผลเดียวกับ [ADR-0027](0027-toolid-transformation-must-be-deterministic.md) คือกฎที่ต้องอาศัยความจำของคนเขียนจะถูกละเมิดทันทีที่คนเปลี่ยน +* **ยังไม่ปิด:** **ความกว้างของหน้าต่าง rollout** — `ai-collaboration-mcp` เสนอวัดให้เป็นเรื่องเป็นราวในรอบ deploy ถัดไป (ยิงถี่ตั้งแต่ก่อน deploy จนหลัง) · จนกว่าจะมีผล ข้อนี้เป็น *การมีอยู่* ไม่ใช่ *ปริมาณ* และไม่มีกฎข้อใดใน ADR นี้ขึ้นกับตัวเลขนั้น * **ยังไม่ปิด:** ที่ทางของเลข contract ใน `mcp/v1` — รอ consumer รายแรกที่ pin ตามหลักเดียวกับ mapping record ใน [ADR-0027](0027-toolid-transformation-must-be-deterministic.md) * ยังไม่มีใครตอบได้ว่า **ค่ายไหนถือ schema เวอร์ชันไหนอยู่** — ภายใต้ D ข้อนี้เลิกเป็นเรื่องคอขาดบาดตาย เพราะคนที่ถือของเก่าก็ยังทำงานได้ แต่ยังเป็นข้อจำกัดที่ต้องบันทึก ## Sources -`dis-7c741dbb` ใน [`ai-collaboration-mcp`](https://github.com/monthop-gmail/ai-collaboration-mcp) workspace — `seq 7` (การเปลี่ยนรูป `waiting_for_you`) · `seq 10` (agent-platform ทักว่าเป็น breaking change ที่ไม่มีเวอร์ชัน) · `seq 12` (รับข้อเสนอ + คำถามสามข้อ) · `seq 13` (ข้อจำกัดสามข้อที่วัดมาเอง) · `seq 15` (รับกติกาทั้งชุด · เคาะไม่คืนคีย์ · ถอนประโยคเรื่อง deploy ของตัวเอง) · `seq 16` (agent-platform รับว่ามองข้าม `total`) · [ADR-0006](0006-contract-versioning.md) นิยาม breaking + Deprecation + Compatibility · [`contracts/README.md`](../contracts/README.md) เกณฑ์รับ contract ใหม่ 4 ข้อ · MCP `notifications/tools/list_changed` +`dis-7c741dbb` ใน [`ai-collaboration-mcp`](https://github.com/monthop-gmail/ai-collaboration-mcp) workspace — `seq 7` (การเปลี่ยนรูป `waiting_for_you`) · `seq 10` (agent-platform ทักว่าเป็น breaking change ที่ไม่มีเวอร์ชัน) · `seq 12` (รับข้อเสนอ + คำถามสามข้อ) · `seq 13` (ข้อจำกัดสามข้อที่วัดมาเอง) · `seq 15` (รับกติกาทั้งชุด · เคาะไม่คืนคีย์ · ถอนประโยคเรื่อง deploy ของตัวเอง) · `seq 16` (agent-platform รับว่ามองข้าม `total`) · `seq 17` (ขอบเขตของหลักฐานเรื่องหน้าต่าง rollout · กติกาการขยับเลข) · [ADR-0006](0006-contract-versioning.md) นิยาม breaking + Deprecation + Compatibility · [`contracts/README.md`](../contracts/README.md) เกณฑ์รับ contract ใหม่ 4 ข้อ · MCP `notifications/tools/list_changed`