พบระหว่างลงมือทำ devfactory-core#5
(Governance Decision Interface) — ฝั่งเราจะ implement ตาม approval/v1 แล้วพบว่ามี guarantee
ข้อหนึ่งที่ schema ไม่มี field ให้ทำตาม
ช่องว่าง
contracts/approval/v1/approval.schema.yaml · บล็อก guarantees (🔒 frozen) ข้อแรก:
"decision เป็น immutable — แก้ไม่ได้หลังบันทึก · การเปลี่ยนใจคือ approval ใบใหม่ที่อ้างใบเดิม"
แต่ใน properties ไม่มี field ไหนให้ "อ้างใบเดิม" ได้เลย — ไล่ครบทุกตัวแล้ว
(approval_id tenant_id workspace_id subject execution_id agent_id decision reason
authority decided_at policy_id action_risk expires_at escalation_target)
· grep -rn supersede contracts/ ทั้งโฟลเดอร์ได้ 0 ผลลัพธ์
ผลคือ consumer ที่ทำตาม guarantee นี้จะเขียน approval ใบใหม่ที่ ไม่มีทางบอกได้ว่ามันแทนใบไหน
ห่วงโซ่การเปลี่ยนใจจึงขาดใน audit trail ทั้งที่ guarantee บังคับให้มีอยู่
เสนอ
เพิ่ม property ที่ไม่บังคับ:
supersedes_approval_id:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/Id
description: >-
approval ใบที่ใบนี้มาแทน — ต้องมีเมื่อเป็นการเปลี่ยนใจ (ดู guarantee ข้อแรก)
ใบเดิมยังคงอยู่และห้ามแก้ · ห่วงโซ่นี้คือหลักฐานว่าใครเปลี่ยนใจเมื่อไหร่
เป็นการ เพิ่ม optional property ไม่แตะ required ไม่แตะบล็อก guarantees ที่ frozen ไว้
· ตามที่ contract-semantics.yaml ฝั่งเราเขียนไว้ นี่อยู่ในกลุ่ม platform_may_add_freely
ซึ่งทำผ่าน ADR ฝั่งท่านได้เลย ไม่ต้องมี RFC ที่ devfactory-core
ระหว่างนี้ฝั่งเราทำอะไรไปก่อน
ใส่ supersedes_decision_id ใน payload ของเราเอง (schema ไม่ได้ปิด additionalProperties)
พร้อมคอมเมนต์กำกับว่าเป็นการเติมช่องที่สัญญายังไม่มี — ถ้าท่านรับข้อเสนอนี้ เราจะเปลี่ยนไปใช้ชื่อ
ที่ท่านกำหนดแทนทันที ขอชื่อที่จะใช้จริงด้วยครับ จะได้ไม่ต้อง migrate สองรอบ
เรื่องที่สอง — REQUIRE_CHANGES ไม่มีใครบอกว่าไปสถานะไหน
พ่วงมาในอิชูเดียวกันเพราะมาจากงานเดียวกันและกระทบ approval/v1 ตัวเดียวกัน
guarantee ข้อสี่ (🔒 frozen) บอกว่า:
"REQUIRE_CHANGES ไม่ใช่ REJECT — งานยังมีชีวิตและกลับมายื่นใหม่ได้"
ซึ่งบอกชัดว่ามัน ไม่ใช่อะไร แต่ไม่มีที่ไหนบอกว่ามัน คืออะไร ในเชิง lifecycle
· ผมไล่ฝั่งท่านแล้ว REQUIRE_CHANGES ปรากฏใน approval.schema.yaml (enum + guarantee),
decisions/0006, decisions/0010, planes/policy.md — ทุกที่พูดถึงมันในฐานะ vocabulary
ของคำตัดสิน ไม่มีที่ไหนผูกกับสถานะของงาน
ฝั่ง devfactory-core state machine ปัจจุบัน GOVERNANCE_ANALYSIS มีทางออกแค่
APPROVED กับ REJECTED เท่านั้น — REQUIRE_CHANGES จึงไม่มีปลายทางให้ลง
เรารู้ว่าการเลือกปลายทางเป็นของเรา (บล็อก guarantees ระบุว่า frozen เพราะเป็นของ
devfactory-core RFC-0002) และจะทำเป็น RFC ที่ repo เรา · ที่ถามคือ ก่อนเราเคาะ
มีอะไรฝั่งท่านที่สมมติพฤติกรรมบางอย่างไว้แล้วหรือเปล่า จะได้ไม่เลือกทางที่ทำสัญญาอื่นพัง
ทางเลือกที่เราเห็นตอนนี้:
|
ทาง |
ผลต่อสัญญา |
| ก |
เพิ่ม edge GOVERNANCE_ANALYSIS → DRAFT |
ตรงกับ "งานยังมีชีวิตและกลับมายื่นใหม่ได้" มากที่สุด · ไม่เพิ่ม vocabulary ใหม่ |
| ข |
ใช้ทาง REJECTED → DRAFT เดิม |
❌ ขัด guarantee ข้อสี่ตรง ๆ ตัดทิ้ง |
| ค |
เพิ่ม state ที่ 14 (เช่น CHANGES_REQUESTED) |
ชัดที่สุดใน audit trail แต่เป็น vocabulary ใหม่ที่ท่านต้องรับรู้ด้วย (RFC-0009) |
ระหว่างที่ยังไม่เคาะ ฝั่งเราจะไม่เดา — engine จะรับ REQUIRE_CHANGES เป็นค่าที่ถูกต้อง
ตาม vocabulary แต่ ปฏิเสธการใช้งานด้วย error เฉพาะ ที่ชี้กลับมาที่คำถามนี้
ดีกว่าปล่อยให้โค้ดเลือกกฎ lifecycle เอง แล้วเอกสารตามไม่ทัน — ซึ่งเป็นเรื่องที่เพิ่งเกิดกับเราใน
#14 มาแล้วรอบหนึ่ง
พบระหว่างลงมือทำ devfactory-core#5
(Governance Decision Interface) — ฝั่งเราจะ implement ตาม
approval/v1แล้วพบว่ามี guaranteeข้อหนึ่งที่ schema ไม่มี field ให้ทำตาม
ช่องว่าง
contracts/approval/v1/approval.schema.yaml· บล็อกguarantees(🔒 frozen) ข้อแรก:แต่ใน
propertiesไม่มี field ไหนให้ "อ้างใบเดิม" ได้เลย — ไล่ครบทุกตัวแล้ว(
approval_idtenant_idworkspace_idsubjectexecution_idagent_iddecisionreasonauthoritydecided_atpolicy_idaction_riskexpires_atescalation_target)·
grep -rn supersede contracts/ทั้งโฟลเดอร์ได้ 0 ผลลัพธ์ผลคือ consumer ที่ทำตาม guarantee นี้จะเขียน approval ใบใหม่ที่ ไม่มีทางบอกได้ว่ามันแทนใบไหน
ห่วงโซ่การเปลี่ยนใจจึงขาดใน audit trail ทั้งที่ guarantee บังคับให้มีอยู่
เสนอ
เพิ่ม property ที่ไม่บังคับ:
เป็นการ เพิ่ม optional property ไม่แตะ
requiredไม่แตะบล็อกguaranteesที่ frozen ไว้· ตามที่
contract-semantics.yamlฝั่งเราเขียนไว้ นี่อยู่ในกลุ่มplatform_may_add_freelyซึ่งทำผ่าน ADR ฝั่งท่านได้เลย ไม่ต้องมี RFC ที่
devfactory-coreระหว่างนี้ฝั่งเราทำอะไรไปก่อน
ใส่
supersedes_decision_idใน payload ของเราเอง (schema ไม่ได้ปิดadditionalProperties)พร้อมคอมเมนต์กำกับว่าเป็นการเติมช่องที่สัญญายังไม่มี — ถ้าท่านรับข้อเสนอนี้ เราจะเปลี่ยนไปใช้ชื่อ
ที่ท่านกำหนดแทนทันที ขอชื่อที่จะใช้จริงด้วยครับ จะได้ไม่ต้อง migrate สองรอบ
เรื่องที่สอง —
REQUIRE_CHANGESไม่มีใครบอกว่าไปสถานะไหนพ่วงมาในอิชูเดียวกันเพราะมาจากงานเดียวกันและกระทบ
approval/v1ตัวเดียวกันguarantee ข้อสี่ (🔒 frozen) บอกว่า:
ซึ่งบอกชัดว่ามัน ไม่ใช่อะไร แต่ไม่มีที่ไหนบอกว่ามัน คืออะไร ในเชิง lifecycle
· ผมไล่ฝั่งท่านแล้ว
REQUIRE_CHANGESปรากฏในapproval.schema.yaml(enum + guarantee),decisions/0006,decisions/0010,planes/policy.md— ทุกที่พูดถึงมันในฐานะ vocabularyของคำตัดสิน ไม่มีที่ไหนผูกกับสถานะของงาน
ฝั่ง
devfactory-corestate machine ปัจจุบันGOVERNANCE_ANALYSISมีทางออกแค่APPROVEDกับREJECTEDเท่านั้น —REQUIRE_CHANGESจึงไม่มีปลายทางให้ลงเรารู้ว่าการเลือกปลายทางเป็นของเรา (บล็อก
guaranteesระบุว่า frozen เพราะเป็นของdevfactory-coreRFC-0002) และจะทำเป็น RFC ที่ repo เรา · ที่ถามคือ ก่อนเราเคาะมีอะไรฝั่งท่านที่สมมติพฤติกรรมบางอย่างไว้แล้วหรือเปล่า จะได้ไม่เลือกทางที่ทำสัญญาอื่นพัง
ทางเลือกที่เราเห็นตอนนี้:
GOVERNANCE_ANALYSIS → DRAFTREJECTED → DRAFTเดิมCHANGES_REQUESTED)ระหว่างที่ยังไม่เคาะ ฝั่งเราจะไม่เดา — engine จะรับ
REQUIRE_CHANGESเป็นค่าที่ถูกต้องตาม vocabulary แต่ ปฏิเสธการใช้งานด้วย error เฉพาะ ที่ชี้กลับมาที่คำถามนี้
ดีกว่าปล่อยให้โค้ดเลือกกฎ lifecycle เอง แล้วเอกสารตามไม่ทัน — ซึ่งเป็นเรื่องที่เพิ่งเกิดกับเราใน
#14 มาแล้วรอบหนึ่ง