แนวคิด
คู่มือนี้อธิบายแนวคิดหลักเบื้องหลัง OpenSpec และวิธีที่แนวคิดเหล่านี้เชื่อมโยงกัน สำหรับการใช้งานจริง โปรดดูที่ เริ่มต้นใช้งาน และ ขั้นตอนการทำงาน
ปรัชญา
OpenSpec สร้างขึ้นจากหลักการสี่ประการ:
fluid not rigid — no phase gates, work on what makes sense
iterative not waterfall — learn as you build, refine as you go
easy not complex — lightweight setup, minimal ceremony
brownfield-first — works with existing codebases, not just greenfieldทำไมหลักการเหล่านี้จึงสำคัญ
Fluid not rigid (ยืดหยุ่น ไม่แข็งทื่อ). ระบบข้อกำหนดแบบดั้งเดิมจะล็อคคุณให้อยู่ในขั้นตอน: ขั้นแรกวางแผน จากนั้นจึงนำไปปฏิบัติ แล้วก็เสร็จ OpenSpec มีความยืดหยุ่นมากกว่า — คุณสามารถสร้างผลลัพธ์ในลำดับใดก็ได้ที่เหมาะสมกับงานของคุณ
Iterative not waterfall (ทำซ้ำ ไม่ใช่วอเตอร์ฟอล). ข้อกำหนดมีการเปลี่ยนแปลง ความเข้าใจลึกซึ้งยิ่งขึ้น สิ่งที่ดูเหมือนเป็นแนวทางที่ดีในตอนเริ่มต้นอาจไม่สามารถใช้ได้หลังจากที่คุณเห็นโค้ดเบส OpenSpec ยอมรับความเป็นจริงนี้
Easy not complex (ง่าย ไม่ซับซ้อน). บางกรอบงานข้อกำหนดต้องมีการตั้งค่าอย่างกว้างขวาง รูปแบบที่เข้มงวด หรือกระบวนการที่หนัก OpenSpec ไม่เข้ามาขวางทางคุณ เริ่มต้นใช้งานได้ในไม่กี่วินาที เริ่มทำงานได้ทันที ปรับแต่งเฉพาะเมื่อจำเป็น
Brownfield-first (ให้ความสำคัญกับระบบเดิมก่อน). งานซอฟต์แวร์ส่วนใหญ่ไม่ใช่การสร้างจากศูนย์ — แต่เป็นการปรับเปลี่ยนระบบที่มีอยู่ แนวทางแบบเดลต้าของ OpenSpec ทำให้ง่ายต่อการระบุการเปลี่ยนแปลงพฤติกรรมที่มีอยู่ ไม่ใช่แค่การอธิบายระบบใหม่
ภาพรวมทั้งหมด
OpenSpec จัดระเบียบงานของคุณออกเป็นสองพื้นที่หลัก:
┌────────────────────────────────────────────────────────────────────┐
│ openspec/ │
│ │
│ ┌─────────────────────┐ ┌───────────────────────────────┐ │
│ │ specs/ │ │ changes/ │ │
│ │ │ │ │ │
│ │ แหล่งข้อมูลจริง │◄─────│ การแก้ไขที่เสนอ │ │
│ │ ระบบของคุณทำงาน │ merge│ แต่ละการเปลี่ยนแปลง = โฟลเดอร์เดียว │ │
│ │ อย่างไรในปัจจุบัน │ │ มีสิ่งประดิษฐ์ + เดลต้า │ │
│ │ │ │ │ │
│ └─────────────────────┘ └───────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘ข้อกำหนด (Specs) คือแหล่งข้อมูลจริง — อธิบายว่าระบบของคุณทำงานอย่างไรในปัจจุบัน
การเปลี่ยนแปลง (Changes) คือการแก้ไขที่เสนอ — เก็บไว้ในโฟลเดอร์แยกจนกว่าคุณจะพร้อมรวมเข้าด้วยกัน
การแยกส่วนนี้เป็นกุญแจสำคัญ คุณสามารถทำงานกับหลายการเปลี่ยนแปลงพร้อมกันได้โดยไม่ขัดแย้ง คุณสามารถตรวจสอบการเปลี่ยนแปลงก่อนที่จะส่งผลต่อข้อกำหนดหลัก และเมื่อคุณเก็บถาวรการเปลี่ยนแปลง เดลต้าของมันจะรวมเข้ากับแหล่งข้อมูลจริงอย่างราบรื่น
พื้นที่ทำงานประสานงาน
การรองรับพื้นที่ทำงานอยู่ระหว่างการพัฒนาอย่างแข็งขันและยังไม่พร้อมใช้งาน อย่าสร้างระบบอัตโนมัติภายนอก การบูรณาการ หรือเวิร์กโฟลว์ที่มีอายุยาวนานบนพฤติกรรมของพื้นที่ทำงาน คำสั่ง ไฟล์สถานะ และเอาต์พุต JSON อาจเปลี่ยนแปลงได้ตลอดเวลา
คำสั่งด้านล่างนี้ให้ขั้นตอนการตั้งค่าเบื้องต้นสำหรับการวางแผนข้าม repos หรือโฟลเดอร์ที่เชื่อมโยง
โปรเจกต์ OpenSpec ที่อยู่ใน repo เป็นค่าเริ่มต้นที่เหมาะสมเมื่อ repo เดียวเป็นเจ้าของขั้นตอนการวางแผน การดำเนินการ และการเก็บถาวร บางงานครอบคลุมหลาย repos หรือโฟลเดอร์ สำหรับกรณีนั้น พื้นที่ทำงานประสานงานของ OpenSpec คือบ้านวางแผนที่ยั่งยืน
โมเดลทางจิตของพื้นที่ทำงานคือ:
text
workspace = ที่ที่การเปลี่ยนแปลงข้าม repo ที่เกี่ยวข้องอยู่
link = ชื่อที่เสถียรสำหรับ repo หรือโฟลเดอร์ที่พื้นที่ทำงานสามารถวางแผนได้
change = คุณลักษณะ การแก้ไข โปรเจกต์ หรือส่วนงานที่วางแผนไว้อื่นๆ หนึ่งรายการพื้นที่ทำงานมีรูปร่างที่แตกต่างจากโปรเจกต์ที่อยู่ใน repo:
text
workspace-folder/
├── changes/ # การวางแผนระดับพื้นที่ทำงาน
└── .openspec-workspace/
├── workspace.yaml # ตัวตนพื้นที่ทำงานที่ใช้ร่วมกันและชื่อลิงก์
└── local.yaml # เส้นทางท้องถิ่นของเครื่องนี้สถานะ OpenSpec ที่อยู่ใน repo ยังคงรูปร่างเดิม:
text
repo-root/
└── openspec/
├── specs/
└── changes/ความแตกต่างนี้มีความสำคัญ โฟลเดอร์พื้นที่ทำงานเป็นพื้นผิวประสานงานสำหรับการวางแผนข้าม repos หรือโฟลเดอร์ที่เชื่อมโยง ไดเรกทอรี openspec/ ของแต่ละ repo ยังคงเป็นบ้านสำหรับข้อกำหนดที่ repo เป็นเจ้าของ การเปลี่ยนแปลงที่อยู่ใน repo และการวางแผนการดำเนินการ ผู้ใช้ไม่จำเป็นต้องรัน openspec init ที่อยู่ใน repo ภายในโฟลเดอร์พื้นที่ทำงาน
ชื่อลิงก์ที่เสถียรคือวิธีที่การวางแผนพื้นที่ทำงานอ้างถึง repos และโฟลเดอร์ สถานะพื้นที่ทำงานที่ใช้ร่วมกันเก็บชื่อเช่น api, web หรือ checkout แต่ละเครื่องแมปชื่อเหล่านั้นไปยังเส้นทางท้องถิ่นของตัวเองใน .openspec-workspace/local.yaml
yaml
# .openspec-workspace/workspace.yaml
version: 1
name: platform
links:
api: {}
web: {}yaml
# .openspec-workspace/local.yaml
version: 1
paths:
api: /repos/api
web: /repos/webพื้นที่ทำงานที่สร้างโดย OpenSpec จะไม่รวม .openspec-workspace/local.yaml ออกจากสถานะการพกพาสำหรับการทำงานร่วมกันโดยค่าเริ่มต้น .openspec-workspace/workspace.yaml ยังคงพกพาได้เนื่องจากเก็บชื่อพื้นที่ทำงานและชื่อลิงก์ที่เสถียร ไม่ใช่เส้นทาง checkout แบบสัมบูรณ์ของผู้ใช้รายใดรายหนึ่ง
เส้นทางที่เชื่อมโยงอาจเป็น repos เต็มรูปแบบ โฟลเดอร์ภายใน monorepo ขนาดใหญ่ หรือโฟลเดอร์ที่มีอยู่อื่นๆ ไม่จำเป็นต้องมีสถานะ openspec/ ที่อยู่ใน repo ก่อนจึงจะเข้าร่วมการวางแผนพื้นที่ทำงานได้ เวิร์กโฟลว์การดำเนินการ การตรวจสอบ หรือการเก็บถาวรในภายหลังอาจต้องการความพร้อมของ repo มากขึ้น แต่การมองเห็นในการวางแผนเริ่มต้นจากลิงก์
text
multi-repo:
api -> /repos/api
web -> /repos/web
large monorepo:
billing -> /repos/platform/services/billing
checkout -> /repos/platform/apps/checkoutพื้นที่ทำงานที่จัดการอยู่ภายใต้ไดเรกทอรีข้อมูล OpenSpec มาตรฐาน:
text
getGlobalDataDir()/workspacesซึ่งหมายความว่า $XDG_DATA_HOME/openspec/workspaces เมื่อตั้งค่า XDG_DATA_HOME, ~/.local/share/openspec/workspaces บน fallback แบบ Unix และ %LOCALAPPDATA%\openspec\workspaces บน fallback ดั้งเดิมของ Windows เชลล์ดั้งเดิมของ Windows, PowerShell และ WSL2 แต่ละตัวเก็บสตริงเส้นทางสำหรับรันไทม์ที่รัน OpenSpec พื้นฐานนี้ไม่แปลงระหว่าง D:\repo, /mnt/d/repo และเส้นทาง UNC WSL
OpenSpec ยังเก็บรีจิสทรีเฉพาะเครื่องที่:
text
getGlobalDataDir()/workspaces/registry.yamlรีจิสทรีแมปชื่อพื้นที่ทำงานไปยังตำแหน่งพื้นที่ทำงาน เพื่อให้คำสั่งทั่วไปในภายหลังสามารถแสดงรายการหรือเลือกพื้นที่ทำงานที่รู้จักจากที่ใดก็ได้ เป็นเพียงดัชนีเท่านั้น โฟลเดอร์พื้นที่ทำงานแต่ละแห่งยังคงมีอำนาจสูงสุดสำหรับ .openspec-workspace/workspace.yaml และ .openspec-workspace/local.yaml ของตัวเอง ดังนั้นบันทึกรีจิสทรีที่ล้าสมัยสามารถรายงานและซ่อมแซมได้โดยไม่ต้องกำหนดพื้นที่ทำงานใหม่
การมองเห็นพื้นที่ทำงานไม่ใช่ความมุ่งมั่นในการเปลี่ยนแปลง ตั้งค่าพื้นที่ทำงานเมื่อ OpenSpec ควรรู้ว่า repos หรือโฟลเดอร์ใดเกี่ยวข้อง สร้างการเปลี่ยนแปลงในภายหลังเมื่อคุณพร้อมที่จะวางแผนคุณลักษณะ การแก้ไข โปรเจกต์ หรือส่วนงานอื่นๆ
คำสั่งที่เป็นประโยชน์:
bash
# การตั้งค่าแบบมีคำแนะนำ
openspec workspace setup
# การตั้งค่าที่เป็นมิตรกับระบบอัตโนมัติ
openspec workspace setup --no-interactive --name platform --link /repos/api --link web=/repos/web
openspec workspace setup --no-interactive --name platform --link /repos/api --opener codex
# ดูพื้นที่ทำงานที่รู้จักจากรีจิสทรีท้องถิ่น
openspec workspace list
openspec workspace ls
# เพิ่มหรือซ่อมแซมลิงก์สำหรับพื้นที่ทำงานที่เลือก
openspec workspace link /repos/api
openspec workspace link api-service /repos/api
openspec workspace relink api-service /new/path/to/api
# ตรวจสอบว่าเครื่องนี้สามารถแก้ไขอะไรได้บ้าง
openspec workspace doctor
openspec workspace doctor --workspace platform
# เปิดชุดงานที่เชื่อมโยง
openspec workspace open
openspec workspace open platform --agent github-copilot
openspec workspace open --editorworkspace setup เสมอสร้างพื้นที่ทำงานในตำแหน่งพื้นที่ทำงานมาตรฐาน บันทึกในรีจิสทรีท้องถิ่น แสดงตำแหน่งพื้นที่ทำงาน และต้องมี repo หรือโฟลเดอร์ที่เชื่อมโยงอย่างน้อยหนึ่งรายการ การตั้งค่าแบบโต้ตอบถามหาตัวเปิดที่ต้องการ การตั้งค่าแบบไม่โต้ตอบเก็บตัวเปิดเมื่อระบุ --opener codex, --opener claude, --opener github-copilot หรือ --opener editor เท่านั้น
OpenSpec ยังคงรักษาไฟล์เปิดพื้นที่ทำงานราก: บล็อกคำแนะนำที่จัดการโดย OpenSpec ใน AGENTS.md, ไฟล์ <workspace-name>.code-workspace เฉพาะเครื่องสำหรับ VS Code และ GitHub Copilot-in-VS-Code เปิด และรายการละเว้นเฉพาะสำหรับไฟล์ .code-workspace ที่ดูแลรักษา ไฟล์ *.code-workspace ที่ผู้ใช้สร้างขึ้นยังคงติดตามได้เนื่องจากกฎการละเว้นกำหนดเป้าหมายเฉพาะไฟล์ที่ดูแลรักษาเท่านั้น
พื้นที่ทำงาน VS Code ที่ดูแลรักษารวมรากประสานงานเป็น . พร้อม repos หรือโฟลเดอร์ที่เชื่อมโยงที่ถูกต้องเป็นรากเพิ่มเติม VS Code แสดงรายการเหล่านั้นเป็นพื้นที่ทำงานหลายราก
workspace open เปิดชุดงานที่เชื่อมโยงด้วยตัวเปิดที่ต้องการที่เก็บไว้ เว้นแต่จะส่ง --agent <tool> หรือ --editor สำหรับเซสชันนั้น การส่งทั้งสองตัวเลือกตัวเปิดถือเป็นข้อผิดพลาด การเปิดพื้นที่ทำงานรากทำให้ repos และโฟลเดอร์ที่เชื่อมโยงมองเห็นได้สำหรับการสำรวจและการวางแผน การดำเนินการเริ่มต้นหลังจากที่ผู้ใช้ร้องขออย่างชัดเจน
workspace link และ workspace relink บันทึกเฉพาะโฟลเดอร์ที่มีอยู่เท่านั้น ไม่สร้าง คัดลอก ย้าย เริ่มต้น หรือแก้ไข repo หรือโฟลเดอร์ที่เชื่อมโยง หลังจากลิงก์หรือลิงก์ใหม่สำเร็จ OpenSpec จะรีเฟรชคำแนะนำที่จัดการ ไฟล์พื้นที่ทำงาน VS Code และกฎการละเว้น
คำสั่งพื้นที่ทำงานที่ต้องการพื้นที่ทำงานหนึ่งแห่งสามารถรันจากที่ใดก็ได้ด้วย --workspace <name> หากคุณรันคำสั่งภายในโฟลเดอร์พื้นที่ทำงานหรือไดเรกทอรีย่อย OpenSpec จะใช้พื้นที่ทำงานปัจจุบันนั้น หากมีพื้นที่ทำงานที่รู้จักหลายแห่งและคุณไม่ได้ส่ง --workspace <name> คำสั่งของผู้ใช้จะแสดงตัวเลือก --json และ --no-interactive จะล้มเหลวด้วยข้อผิดพลาดสถานะที่มีโครงสร้างแทนการแจ้งเตือน
คำสั่งพื้นที่ทำงานโดยตรงรองรับเอาต์พุต JSON สำหรับสคริปต์ การตอบกลับ JSON เก็บข้อมูลหลักในอ็อบเจกต์ workspace, workspaces หรือ link และรายงานคำเตือนหรือข้อผิดพลาดในอาร์เรย์ status อ็อบเจกต์ที่แข็งแรงใช้ status: []
ข้อกำหนด (Specs)
ข้อกำหนดอธิบายพฤติกรรมของระบบของคุณโดยใช้ข้อกำหนดและสถานการณ์ที่มีโครงสร้าง
โครงสร้าง
openspec/specs/
├── auth/
│ └── spec.md # พฤติกรรมการยืนยันตัวตน
├── payments/
│ └── spec.md # การประมวลผลการชำระเงิน
├── notifications/
│ └── spec.md # ระบบการแจ้งเตือน
└── ui/
└── spec.md # พฤติกรรม UI และธีมจัดระเบียบข้อกำหนดตามโดเมน — การจัดกลุ่มเชิงตรรกะที่สมเหตุสมผลสำหรับระบบของคุณ รูปแบบทั่วไป:
- ตามพื้นที่คุณลักษณะ:
auth/,payments/,search/ - ตามส่วนประกอบ:
api/,frontend/,workers/ - ตามบริบทที่มีขอบเขต:
ordering/,fulfillment/,inventory/
รูปแบบข้อกำหนด
ข้อกำหนดประกอบด้วยข้อกำหนด และแต่ละข้อกำหนดมีสถานการณ์:
markdown
# ข้อกำหนดการยืนยันตัวตนวัตถุประสงค์
การยืนยันตัวตนและการจัดการเซสชันสำหรับแอปพลิเคชัน
ข้อกำหนด
ข้อกำหนด: การยืนยันตัวตนผู้ใช้
ระบบ SHALL ออกโทเค็น JWT เมื่อเข้าสู่ระบบสำเร็จ
สถานการณ์: ข้อมูลรับรองที่ถูกต้อง
- GIVEN ผู้ใช้ที่มีข้อมูลรับรองที่ถูกต้อง
- WHEN ผู้ใช้ส่งแบบฟอร์มเข้าสู่ระบบ
- THEN โทเค็น JWT จะถูกส่งคืน
- AND ผู้ใช้จะถูกเปลี่ยนเส้นทางไปยังแดชบอร์ด
สถานการณ์: ข้อมูลรับรองไม่ถูกต้อง
- GIVEN ข้อมูลรับรองที่ไม่ถูกต้อง
- WHEN ผู้ใช้ส่งแบบฟอร์มเข้าสู่ระบบ
- THEN ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น
- AND ไม่มีโทเค็นถูกออก
ข้อกำหนด: การหมดอายุของเซสชัน
ระบบ MUST ทำให้เซสชันหมดอายุหลังจากไม่มีการใช้งาน 30 นาที
สถานการณ์: หมดเวลาเนื่องจากไม่มีการใช้งาน
- GIVEN เซสชันที่ผ่านการยืนยันตัวตนแล้ว
- WHEN ผ่านไป 30 นาทีโดยไม่มีกิจกรรม
- THEN เซสชันจะถูกทำให้ไม่ถูกต้อง
- AND ผู้ใช้ต้องยืนยันตัวตนใหม่
**องค์ประกอบหลัก:**
| องค์ประกอบ | วัตถุประสงค์ |
|------------|--------------|
| `## Purpose` | คำอธิบายระดับสูงของโดเมนข้อกำหนดนี้ |
| `### Requirement:` | พฤติกรรมเฉพาะที่ระบบต้องมี |
| `#### Scenario:` | ตัวอย่างที่เป็นรูปธรรมของข้อกำหนดในการดำเนินการ |
| SHALL/MUST/SHOULD | คำสำคัญ RFC 2119 ที่บ่งบอกความแข็งแกร่งของข้อกำหนด |
### เหตุใดจึงจัดโครงสร้างข้อกำหนดในลักษณะนี้
**ข้อกำหนดคือ "สิ่งที่"** — ข้อกำหนดระบุว่าระบบควรทำอะไรโดยไม่ระบุการนำไปใช้
**สถานการณ์คือ "เมื่อใด"** — สถานการณ์ให้ตัวอย่างที่เป็นรูปธรรมซึ่งสามารถตรวจสอบได้ สถานการณ์ที่ดี:
- สามารถทดสอบได้ (คุณสามารถเขียนการทดสอบอัตโนมัติสำหรับมันได้)
- ครอบคลุมทั้งเส้นทางที่ดีและกรณีขอบ
- ใช้รูปแบบ Given/When/Then หรือรูปแบบที่มีโครงสร้างคล้ายกัน
**คำสำคัญ RFC 2119** (SHALL, MUST, SHOULD, MAY) สื่อสารเจตนา:
- **MUST/SHALL** — ข้อกำหนดสัมบูรณ์
- **SHOULD** — แนะนำ แต่มีข้อยกเว้น
- **MAY** — ไม่บังคับ
### สิ่งที่ข้อกำหนดเป็น (และไม่เป็น)
ข้อกำหนดคือ **สัญญาพฤติกรรม** ไม่ใช่แผนการนำไปใช้
เนื้อหาข้อกำหนดที่ดี:
- พฤติกรรมที่สังเกตได้ซึ่งผู้ใช้หรือระบบปลายน้ำพึ่งพา
- อินพุต เอาต์พุต และเงื่อนไขข้อผิดพลาด
- ข้อจำกัดภายนอก (ความปลอดภัย ความเป็นส่วนตัว ความน่าเชื่อถือ ความเข้ากันได้)
- สถานการณ์ที่สามารถทดสอบหรือตรวจสอบอย่างชัดเจน
สิ่งที่ควรหลีกเลี่ยงในข้อกำหนด:
- ชื่อคลาส/ฟังก์ชันภายใน
- ทางเลือกไลบรารีหรือเฟรมเวิร์ก
- รายละเอียดการนำไปใช้ทีละขั้นตอน
- แผนการดำเนินงานโดยละเอียด (สิ่งเหล่านั้นอยู่ใน `design.md` หรือ `tasks.md`)
การทดสอบอย่างรวดเร็ว:
- หากการนำไปใช้สามารถเปลี่ยนแปลงได้โดยไม่เปลี่ยนแปลงพฤติกรรมที่มองเห็นจากภายนอก ก็อาจไม่ควรอยู่ในข้อกำหนด
### รักษาความเบา: ความเข้มงวดแบบก้าวหน้า
OpenSpec มุ่งหวังที่จะหลีกเลี่ยงระบบราชการ ใช้ระดับที่เบาที่สุดที่ยังคงทำให้การเปลี่ยนแปลงสามารถตรวจสอบได้
**ข้อกำหนดแบบ Lite (ค่าเริ่มต้น):**
- ข้อกำหนดที่เน้นพฤติกรรมสั้นๆ
- ขอบเขตและเป้าหมายที่ไม่ชัดเจน
- การตรวจสอบการยอมรับที่เป็นรูปธรรมไม่กี่ข้อ
**ข้อกำหนดแบบเต็ม (สำหรับความเสี่ยงที่สูงกว่า):**
- การเปลี่ยนแปลงข้ามทีมหรือข้ามที่เก็บ
- การเปลี่ยนแปลงสัญญา API การโยกย้าย ข้อกังวลด้านความปลอดภัย/ความเป็นส่วนตัว
- การเปลี่ยนแปลงที่ความคลุมเครืออาจทำให้ต้องทำงานซ้ำที่มีค่าใช้จ่ายสูง
การเปลี่ยนแปลงส่วนใหญ่ควรอยู่ในโหมด Lite
### ความร่วมมือระหว่างมนุษย์และเอเจนต์
ในหลายทีม มนุษย์สำรวจและเอเจนต์ร่างเอกสาร ลูปที่ตั้งใจไว้คือ:
1. มนุษย์ให้เจตนา บริบท และข้อจำกัด
2. เอเจนต์แปลงสิ่งนี้เป็นข้อกำหนดและสถานการณ์ที่เน้นพฤติกรรม
3. เอเจนต์เก็บรายละเอียดการนำไปใช้ไว้ใน `design.md` และ `tasks.md` ไม่ใช่ `spec.md`
4. การตรวจสอบยืนยันโครงสร้างและความชัดเจนก่อนการนำไปใช้
สิ่งนี้ทำให้ข้อกำหนดอ่านง่ายสำหรับมนุษย์และสอดคล้องสำหรับเอเจนต์
## การเปลี่ยนแปลง
การเปลี่ยนแปลงคือข้อเสนอการแก้ไขระบบของคุณ ซึ่งถูกจัดรูปแบบเป็นโฟลเดอร์ที่มีทุกสิ่งที่จำเป็นเพื่อความเข้าใจและการนำไปใช้งาน
### โครงสร้างการเปลี่ยนแปลงopenspec/changes/add-dark-mode/ ├── proposal.md # เหตุผลและเนื้อหา ├── design.md # วิธีการ (แนวทางทางเทคนิค) ├── tasks.md # รายการตรวจสอบการนำไปใช้ ├── .openspec.yaml # เมตาดาต้าการเปลี่ยนแปลง (ไม่บังคับ) └── specs/ # ข้อกำหนดเดลต้า └── ui/ └── spec.md # สิ่งที่เปลี่ยนแปลงใน ui/spec.md
การเปลี่ยนแปลงแต่ละรายการมีความสมบูรณ์ในตัวเอง ประกอบด้วย:
- **เอกสารประกอบ** — เอกสารที่บันทึกเจตนา การออกแบบ และงาน
- **ข้อกำหนดเดลต้า** — ข้อกำหนดสำหรับสิ่งที่ถูกเพิ่ม แก้ไข หรือลบ
- **เมตาดาต้า** — การกำหนดค่าเพิ่มเติมสำหรับการเปลี่ยนแปลงเฉพาะนี้
### เหตุใดการเปลี่ยนแปลงจึงเป็นโฟลเดอร์
การจัดรูปแบบการเปลี่ยนแปลงเป็นโฟลเดอร์มีข้อดีหลายประการ:
1. **รวมทุกอย่างไว้ด้วยกัน** ข้อเสนอ การออกแบบ งาน และข้อกำหนดอยู่ในที่เดียว ไม่ต้องค้นหาจากหลายที่
2. **ทำงานแบบขนาน** การเปลี่ยนแปลงหลายรายการสามารถมีอยู่พร้อมกันได้โดยไม่ขัดแย้ง ทำงานกับ `add-dark-mode` ในขณะที่ `fix-auth-bug` ก็อยู่ในระหว่างดำเนินการ
3. **ประวัติที่ชัดเจน** เมื่อเก็บถาวร การเปลี่ยนแปลงจะย้ายไปที่ `changes/archive/` พร้อมบริบทที่สมบูรณ์ คุณสามารถย้อนดูและเข้าใจไม่เพียงแค่ว่ามีการเปลี่ยนแปลงอะไร แต่ยังรวมถึงเหตุผลด้วย
4. **สะดวกต่อการตรวจสอบ** โฟลเดอร์การเปลี่ยนแปลงง่ายต่อการตรวจสอบ — เปิดมัน อ่านข้อเสนอ ตรวจสอบการออกแบบ ดูข้อกำหนดเดลต้า
## เอกสารประกอบ
เอกสารประกอบคือเอกสารภายในโฟลเดอร์การเปลี่ยนแปลงที่ช่วยนำทางการทำงาน
### กระแสเอกสารประกอบproposal ──────► specs ──────► design ──────► tasks ──────► implement │ │ │ │ why what how steps
- scope changes approach to take
เอกสารประกอบสร้างขึ้นจากกันและกัน เอกสารประกอบแต่ละชิ้นให้บริบทสำหรับชิ้นถัดไป
### ประเภทเอกสารประกอบ
#### ข้อเสนอ (`proposal.md`)
ข้อเสนอจะบันทึก **เจตนา** **ขอบเขต** และ **แนวทาง** ในระดับสูง
```markdown
# ข้อเสนอ: เพิ่มโหมดมืด
## เจตนา
ผู้ใช้ร้องขอตัวเลือกโหมดมืดเพื่อลดความเมื่อยล้าของดวงตา
ระหว่างการใช้งานในเวลากลางคืนและตรงกับความต้องการของระบบ
## ขอบเขต
อยู่ในขอบเขต:
- ตัวสลับธีมในการตั้งค่า
- การตรวจจับความต้องการของระบบ
- บันทึกความต้องการใน localStorage
อยู่นอกขอบเขต:
- ธีมสีที่กำหนดเอง (งานในอนาคต)
- การแทนที่ธีมต่อหน้า
## แนวทาง
ใช้คุณสมบัติ CSS ที่กำหนดเองสำหรับธีมด้วย React context
สำหรับการจัดการสถานะ ตรวจจับความต้องการของระบบเมื่อโหลดครั้งแรก
อนุญาตให้แทนที่ด้วยตนเองเมื่อใดควรอัปเดตข้อเสนอ:
- ขอบเขตเปลี่ยนแปลง (แคบลงหรือกว้างขึ้น)
- เจตนาชัดเจนขึ้น (เข้าใจปัญหาดีขึ้น)
- แนวทางเปลี่ยนแปลงอย่างมีนัยสำคัญ
ข้อกำหนด (ข้อกำหนดเดลต้าใน specs/)
ข้อกำหนดเดลต้าอธิบาย สิ่งที่เปลี่ยนแปลง เมื่อเทียบกับข้อกำหนดปัจจุบัน ดู ข้อกำหนดเดลต้า ด้านล่าง
การออกแบบ (design.md)
การออกแบบจะบันทึก แนวทางทางเทคนิค และ การตัดสินใจทางสถาปัตยกรรม
markdown
# การออกแบบ: เพิ่มโหมดมืด
## แนวทางทางเทคนิค
สถานะธีมจัดการผ่าน React Context เพื่อหลีกเลี่ยง prop drilling
คุณสมบัติ CSS ที่กำหนดเองช่วยให้สลับได้ในเวลาทำงานโดยไม่ต้องสลับคลาส
## การตัดสินใจทางสถาปัตยกรรม
### การตัดสินใจ: Context แทน Redux
ใช้ React Context สำหรับสถานะธีมเพราะ:
- สถานะไบนารีง่าย (สว่าง/มืด)
- ไม่มีการเปลี่ยนสถานะที่ซับซ้อน
- หลีกเลี่ยงการเพิ่มการพึ่งพา Redux
### การตัดสินใจ: คุณสมบัติ CSS ที่กำหนดเอง
ใช้ตัวแปร CSS แทน CSS-in-JS เพราะ:
- ทำงานกับ stylesheet ที่มีอยู่
- ไม่มีค่าใช้จ่ายเพิ่มเติมในเวลาทำงาน
- โซลูชันที่เบราว์เซอร์รองรับโดยธรรมชาติ
## การไหลของข้อมูล
```
ThemeProvider (context)
│
▼
ThemeToggle ◄──► localStorage
│
▼
CSS Variables (applied to :root)
```
## การเปลี่ยนแปลงไฟล์
- `src/contexts/ThemeContext.tsx` (ใหม่)
- `src/components/ThemeToggle.tsx` (ใหม่)
- `src/styles/globals.css` (แก้ไข)เมื่อใดควรอัปเดตการออกแบบ:
- การนำไปใช้พบว่าแนวทางใช้ไม่ได้
- ค้นพบโซลูชันที่ดีกว่า
- การพึ่งพาหรือข้อจำกัดเปลี่ยนแปลง
งาน (tasks.md)
งานคือ รายการตรวจสอบการนำไปใช้ — ขั้นตอนที่เป็นรูปธรรมพร้อมช่องทำเครื่องหมาย
markdown
# งาน
## 1. โครงสร้างพื้นฐานธีม
- [ ] 1.1 สร้าง ThemeContext พร้อมสถานะสว่าง/มืด
- [ ] 1.2 เพิ่มคุณสมบัติ CSS ที่กำหนดเองสำหรับสี
- [ ] 1.3 ดำเนินการบันทึกใน localStorage
- [ ] 1.4 เพิ่มการตรวจจับความต้องการของระบบ
## 2. คอมโพเนนต์ UI
- [ ] 2.1 สร้างคอมโพเนนต์ ThemeToggle
- [ ] 2.2 เพิ่มตัวสลับไปยังหน้าการตั้งค่า
- [ ] 2.3 อัปเดต Header เพื่อรวมตัวสลับด่วน
## 3. การจัดรูปแบบ
- [ ] 3.1 กำหนดจานสีธีมมืด
- [ ] 3.2 อัปเดตคอมโพเนนต์เพื่อใช้ตัวแปร CSS
- [ ] 3.3 ทดสอบอัตราส่วนคอนทราสต์เพื่อการเข้าถึงแนวปฏิบัติที่ดีที่สุดสำหรับงาน:
- จัดกลุ่มงานที่เกี่ยวข้องภายใต้หัวข้อ
- ใช้ลำดับเลขชั้น (1.1, 1.2 เป็นต้น)
- รักษางานให้เล็กพอที่จะทำให้เสร็จในหนึ่งเซสชัน
- ทำเครื่องหมายงานเมื่อทำเสร็จ
ข้อกำหนดเดลต้า
ข้อกำหนดเดลต้าเป็นแนวคิดหลักที่ทำให้ OpenSpec ใช้งานได้สำหรับการพัฒนาแบบบราวน์ฟิลด์ พวกเขาอธิบาย สิ่งที่เปลี่ยนแปลง แทนที่จะระบุข้อกำหนดทั้งหมดซ้ำ
รูปแบบ
markdown
# เดลต้าสำหรับ Auth
## ข้อกำหนดที่เพิ่ม
### ข้อกำหนด: การยืนยันตัวตนสองปัจจัย
ระบบต้องรองรับการยืนยันตัวตนสองปัจจัยแบบ TOTP
#### สถานการณ์: การลงทะเบียน 2FA
- กำหนดให้ผู้ใช้ที่ยังไม่ได้เปิดใช้งาน 2FA
- เมื่อผู้ใช้เปิดใช้งาน 2FA ในการตั้งค่า
- จากนั้นจะแสดงรหัส QR สำหรับตั้งค่าแอปยืนยันตัวตน
- และผู้ใช้ต้องยืนยันด้วยรหัสก่อนเปิดใช้งาน
#### สถานการณ์: การเข้าสู่ระบบด้วย 2FA
- กำหนดให้ผู้ใช้ที่เปิดใช้งาน 2FA แล้ว
- เมื่อผู้ใช้ส่งข้อมูลรับรองที่ถูกต้อง
- จากนั้นจะแสดงคำท้า OTP
- และการเข้าสู่ระบบจะเสร็จสมบูรณ์หลังจาก OTP ที่ถูกต้องเท่านั้น
## ข้อกำหนดที่แก้ไข
### ข้อกำหนด: การหมดอายุเซสชัน
ระบบต้องทำให้เซสชันหมดอายุหลังจากไม่มีกิจกรรม 15 นาที
(ก่อนหน้า: 30 นาที)
#### สถานการณ์: หมดเวลาเนื่องจากไม่มีกิจกรรม
- กำหนดให้เซสชันที่ผ่านการยืนยันตัวตนแล้ว
- เมื่อเวลาผ่านไป 15 นาทีโดยไม่มีกิจกรรม
- จากนั้นเซสชันจะถูกยกเลิก
## ข้อกำหนดที่ลบ
### ข้อกำหนด: จดจำฉัน
(เลิกใช้เพื่อสนับสนุน 2FA ผู้ใช้ควรยืนยันตัวตนใหม่ทุกเซสชัน)ส่วนเดลต้า
| ส่วน | ความหมาย | สิ่งที่เกิดขึ้นเมื่อเก็บถาวร |
|---|---|---|
## ข้อกำหนดที่เพิ่ม | พฤติกรรมใหม่ | เพิ่มต่อท้ายข้อกำหนดหลัก |
## ข้อกำหนดที่แก้ไข | พฤติกรรมที่เปลี่ยนแปลง | แทนที่ข้อกำหนดที่มีอยู่ |
## ข้อกำหนดที่ลบ | พฤติกรรมที่เลิกใช้ | ลบออกจากข้อกำหนดหลัก |
เหตุใดจึงใช้เดลต้าแทนข้อกำหนดเต็ม
ความชัดเจน เดลต้าแสดงให้เห็นอย่างชัดเจนว่ามีการเปลี่ยนแปลงอะไร การอ่านข้อกำหนดเต็ม คุณจะต้องเปรียบเทียบทางจิตใจกับเวอร์ชันปัจจุบัน
หลีกเลี่ยงความขัดแย้ง การเปลี่ยนแปลงสองรายการสามารถแตะต้องไฟล์ข้อกำหนดเดียวกันได้โดยไม่ขัดแย้ง ตราบใดที่พวกเขาแก้ไขข้อกำหนดที่ต่างกัน
ประสิทธิภาพในการตรวจสอบ ผู้ตรวจสอบเห็นการเปลี่ยนแปลง ไม่ใช่บริบทที่ไม่เปลี่ยนแปลง มุ่งเน้นไปที่สิ่งที่สำคัญ
เหมาะกับบราวน์ฟิลด์ งานส่วนใหญ่แก้ไขพฤติกรรมที่มีอยู่ เดลต้าทำให้การดัดแปลงเป็นสิ่งสำคัญ ไม่ใช่สิ่งที่คิดทีหลัง
สคีมา
สคีมาจะกำหนดประเภทของสิ่งประดิษฐ์ (artifacts) และการพึ่งพาอาศัยกันสำหรับเวิร์กโฟลว์
วิธีการทำงานของสคีมา
yaml
# openspec/schemas/spec-driven/schema.yaml
name: spec-driven
artifacts:
- id: proposal
generates: proposal.md
requires: [] # ไม่มีการพึ่งพา สามารถสร้างได้ก่อน
- id: specs
generates: specs/**/*.md
requires: [proposal] # ต้องการ proposal ก่อนจึงจะสร้างได้
- id: design
generates: design.md
requires: [proposal] # สามารถสร้างพร้อมกับ specs ได้
- id: tasks
generates: tasks.md
requires: [specs, design] # ต้องการทั้ง specs และ design ก่อนสิ่งประดิษฐ์จะสร้างกราฟการพึ่งพาอาศัยกัน:
proposal
(โหนดหลัก)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(ต้องการ: (ต้องการ:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(ต้องการ:
specs, design)การพึ่งพาเป็นตัวเปิดใช้งาน ไม่ใช่ตัวปิดกั้น มันแสดงให้เห็นว่าสิ่งใดที่สามารถสร้างได้ ไม่ใช่สิ่งที่คุณต้องสร้างต่อไป คุณสามารถข้าม design ได้หากไม่ต้องการ คุณสามารถสร้าง specs ก่อนหรือหลัง design ก็ได้ — ทั้งสองขึ้นอยู่กับ proposal เท่านั้น
สคีมาที่มีมาในตัว
spec-driven (ค่าเริ่มต้น)
เวิร์กโฟลว์มาตรฐานสำหรับการพัฒนาแบบขับเคลื่อนด้วยสเปก:
proposal → specs → design → tasks → implementเหมาะสำหรับ: งานฟีเจอร์ส่วนใหญ่ที่คุณต้องการตกลงในสเปกก่อนการนำไปใช้งาน
สคีมาที่กำหนดเอง
สร้างสคีมาที่กำหนดเองสำหรับเวิร์กโฟลว์ของทีมคุณ:
bash
# สร้างจากศูนย์
openspec schema init research-first
# หรือแยกมาจากที่มีอยู่แล้ว
openspec schema fork spec-driven research-firstตัวอย่างสคีมาที่กำหนดเอง:
yaml
# openspec/schemas/research-first/schema.yaml
name: research-first
artifacts:
- id: research
generates: research.md
requires: [] # ทำวิจัยก่อน
- id: proposal
generates: proposal.md
requires: [research] # ข้อเสนออิงจากผลวิจัย
- id: tasks
generates: tasks.md
requires: [proposal] # ข้าม specs/design ไปที่ tasks โดยตรงดูรายละเอียดเพิ่มเติมเกี่ยวกับการสร้างและใช้งานสคีมาที่กำหนดเองได้ที่ การปรับแต่ง
การจัดเก็บ
การจัดเก็บจะทำการเปลี่ยนแปลงให้สมบูรณ์โดยการรวมสเปกเดลต้าเข้ากับสเปกหลัก และเก็บรักษาการเปลี่ยนแปลงไว้เพื่อเป็นประวัติศาสตร์
เกิดอะไรขึ้นเมื่อคุณจัดเก็บ
ก่อนจัดเก็บ:
openspec/
├── specs/
│ └── auth/
│ └── spec.md ◄────────────────┐
└── changes/ │
└── add-2fa/ │
├── proposal.md │
├── design.md │ รวม
├── tasks.md │
└── specs/ │
└── auth/ │
└── spec.md ─────────┘
หลังจัดเก็บ:
openspec/
├── specs/
│ └── auth/
│ └── spec.md # ตอนนี้รวมข้อกำหนด 2FA แล้ว
└── changes/
└── archive/
└── 2025-01-24-add-2fa/ # เก็บรักษาไว้เพื่อประวัติศาสตร์
├── proposal.md
├── design.md
├── tasks.md
└── specs/
└── auth/
└── spec.mdกระบวนการจัดเก็บ
รวมเดลต้า ส่วนของสเปกเดลต้าแต่ละส่วน (ADDED/MODIFIED/REMOVED) จะถูกนำไปใช้กับสเปกหลักที่สอดคล้องกัน
ย้ายไปยังที่จัดเก็บ โฟลเดอร์การเปลี่ยนแปลงจะถูกย้ายไปที่
changes/archive/โดยมีคำนำหน้าเป็นวันที่เพื่อเรียงลำดับตามเวลารักษาบริบท สิ่งประดิษฐ์ทั้งหมดยังคงอยู่ครบถ้วนในที่จัดเก็บ คุณสามารถย้อนกลับไปดูเพื่อทำความเข้าใจว่าเหตุใดจึงมีการเปลี่ยนแปลงนั้น
ทำไมการจัดเก็บจึงสำคัญ
สถานะที่สะอาด การเปลี่ยนแปลงที่ทำงานอยู่ (changes/) จะแสดงเฉพาะงานที่กำลังดำเนินการ งานที่เสร็จสมบูรณ์จะถูกย้ายออกไป
เส้นทางตรวจสอบ ที่จัดเก็บจะรักษาบริบททั้งหมดของการเปลี่ยนแปลงทุกครั้ง — ไม่ใช่แค่ว่ามีอะไรเปลี่ยนแปลง แต่รวมถึงข้อเสนอที่อธิบายเหตุผล การออกแบบที่อธิบายวิธีการ และงานที่แสดงให้เห็นถึงสิ่งที่ทำสำเร็จ
วิวัฒนาการของสเปก สเปกจะเติบโตอย่างเป็นธรรมชาติเมื่อมีการจัดเก็บการเปลี่ยนแปลง ที่จัดเก็บแต่ละแห่งจะรวมเดลต้าของมัน สร้างข้อกำหนดที่ครอบคลุมเมื่อเวลาผ่านไป
ทุกสิ่งทำงานร่วมกันอย่างไร
┌──────────────────────────────────────────────────────────────────────────────┐
│ โฟลว์ OPENSPEC │
│ │
│ ┌────────────────┐ │
│ │ 1. เริ่มต้น │ /opsx:propose (หลัก) หรือ /opsx:new (ขยาย) │
│ │ การเปลี่ยนแปลง│ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 2. สร้าง │ /opsx:ff หรือ /opsx:continue (เวิร์กโฟลว์ขยาย) │
│ │ สิ่งประดิษฐ์│ สร้าง proposal → specs → design → tasks │
│ │ │ (อิงตามการพึ่งพาของสคีมา) │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 3. นำไปใช้ │ /opsx:apply │
│ │ งาน │ ทำงานตามรายการงาน ทำเครื่องหมายว่าเสร็จ │
│ │ │◄──── อัปเดตสิ่งประดิษฐ์เมื่อคุณเรียนรู้ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 4. ตรวจสอบ │ /opsx:verify (ไม่บังคับ) │
│ │ งาน │ ตรวจสอบว่าการนำไปใช้ตรงกับสเปก │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
│ │ 5. จัดเก็บ │────►│ สเปกเดลต้ารวมเข้ากับสเปกหลัก │ │
│ │ การเปลี่ยนแปลง│ │ โฟลเดอร์การเปลี่ยนแปลงย้ายไปที่ archive/ │ │
│ └────────────────┘ │ สเปกเป็นแหล่งข้อมูลจริงที่อัปเดตแล้ว │ │
│ └──────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘วงจรแห่งคุณธรรม:
- สเปกอธิบายพฤติกรรมปัจจุบัน
- การเปลี่ยนแปลงเสนอการแก้ไข (ในรูปแบบเดลต้า)
- การนำไปใช้ทำให้การเปลี่ยนแปลงเป็นจริง
- การจัดเก็บรวมเดลต้าเข้ากับสเปก
- สเปกอธิบายพฤติกรรมใหม่แล้ว
- การเปลี่ยนแปลงครั้งถัดไปต่อยอดจากสเปกที่อัปเดต
อภิธานศัพท์
| คำศัพท์ | คำจำกัดความ |
|---|---|
| สิ่งประดิษฐ์ (Artifact) | เอกสารภายในหนึ่งการเปลี่ยนแปลง (proposal, design, tasks หรือสเปกเดลต้า) |
| การจัดเก็บ (Archive) | กระบวนการที่ทำให้การเปลี่ยนแปลงสมบูรณ์และรวมเดลต้าของมันเข้ากับสเปกหลัก |
| การเปลี่ยนแปลง (Change) | การแก้ไขที่เสนอต่อระบบ จัดเป็นแพ็กเกจในรูปแบบโฟลเดอร์ที่มีสิ่งประดิษฐ์ |
| สเปกเดลต้า (Delta spec) | สเปกที่อธิบายการเปลี่ยนแปลง (ADDED/MODIFIED/REMOVED) เมื่อเทียบกับสเปกปัจจุบัน |
| โดเมน (Domain) | การจัดกลุ่มเชิงตรรกะสำหรับสเปก (เช่น auth/, payments/) |
| ข้อกำหนด (Requirement) | พฤติกรรมเฉพาะที่ระบบต้องมี |
| สถานการณ์ (Scenario) | ตัวอย่างที่เป็นรูปธรรมของข้อกำหนด โดยทั่วไปอยู่ในรูปแบบ Given/When/Then |
| สคีมา (Schema) | คำจำกัดความของประเภทสิ่งประดิษฐ์และการพึ่งพาอาศัยกัน |
| สเปก (Spec) | ข้อกำหนดที่อธิบายพฤติกรรมของระบบ ประกอบด้วยข้อกำหนดและสถานการณ์ |
| แหล่งข้อมูลจริง (Source of truth) | ไดเรกทอรี openspec/specs/ ที่มีพฤติกรรมที่ตกลงกันไว้ในปัจจุบัน |
ขั้นตอนถัดไป
- เริ่มต้นใช้งาน - ขั้นตอนแรกเชิงปฏิบัติ
- เวิร์กโฟลว์ - รูปแบบทั่วไปและเวลาที่ควรใช้แต่ละแบบ
- คำสั่ง - อ้างอิงคำสั่งทั้งหมด
- การปรับแต่ง - สร้างสคีมาที่กำหนดเองและกำหนดค่าโปรเจกต์ของคุณ