info-workshop-spec-anchored-spec-as-source-tessl-openspec

เป้าหมาย: เปลี่ยนการทำงานแบบ “AI เขียนโค้ดแล้วค่อยตรวจ” เป็น “กำหนดพฤติกรรมใน Spec → สร้างโค้ดและทดสอบ → บังคับตรวจสอบ Spec/Code/Test ก่อนรวมงาน”

#เนื้อหาที่จะได้เรียนรู้

  • แยกความหมายระหว่าง Spec-anchored กับ Spec-as-source
  • ใช้ openspec init และ workflow ของ AI Coding Agent (/opsx:propose → /opsx:apply → /opsx:archive)
  • เขียน Capability Spec ที่กำหนดพฤติกรรมชัดเจนด้วย SHALL/MUST, Scenario, Verified by
  • ใช้ Tessl เพื่อเพิ่ม Skill/Rule และตรวจความสัมพันธ์ของ Spec → Target Source → Tests
  • ทดลองสร้าง Todo REST API ด้วย Python/FastAPI และรัน Automated Tests
  • สาธิตการตรวจจับ drift ใน CI และวิธีแก้โดยเริ่มจาก Spec

เวลาแนะนำ: 2–3 ชั่วโมง • ระดับ: Intermediate • ตัวอย่าง: Todo REST API (ข้อมูลในหน่วยความจำ ไม่มีฐานข้อมูล)

#1. แนวคิด: 2 ระดับของ Spec-Driven Development

ประเด็น Spec-anchored Spec-as-source
บทบาทของ Spec จุดอ้างอิงเพื่อวางแผนและสร้างโค้ด แหล่งอ้างอิงที่ใช้ควบคุมการเปลี่ยนแปลงโค้ด
การสร้างฟีเจอร์ เขียน Spec ก่อนแล้วให้ Agent implement เช่นเดียวกัน แต่ต้องมี ownership และ verification
ความสัมพันธ์กับ Tests อาจเชื่อมโยงผ่านงาน/การรีวิว เชื่อมข้อกำหนดกับไฟล์ทดสอบที่ตรวจสอบได้
เมื่อแก้ Source Code ควรย้อนกลับไปดู Spec ตรวจว่า Target ที่เปลี่ยนมี Spec เจ้าของที่อัปเดตตาม
CI Test/Build ตามทั่วไป Test + Spec Link + Ownership/Manifest Checks
ความเสี่ยง Spec กับโค้ดอาจค่อย ๆ แยกจากกัน ลด drift ด้วยกฎและเครื่องมือตรวจสอบ (ไม่ใช่การพิสูจน์เชิงความหมาย 100%)
flowchart TD
    A[User Story / Requirements] --> B[OpenSpec: Proposal + Spec + Tasks]
    B --> C[AI Coding Agent]
    C --> D[Implementation]
    C --> E[Automated Tests]
    B --> F[Tessl Community Tile: spec-as-source]
    F --> G[Ownership + Link + Manifest Checks]
    D --> G
    E --> G
    G --> H{Verification ผ่านหรือไม่?}
    H -->|ไม่ผ่าน| B
    H -->|ผ่าน| I[Code Review + CI + Merge]

ข้อควรแยก: Tessl เป็นระบบ Registry/CLI สำหรับแจกจ่ายบริบท เช่น Skills, Rules, Docs; OpenSpec ทำหน้าที่จัดการวงจร Specification; และ Tile spec-driven-development/spec-as-source เป็นองค์ประกอบเสริมจากบุคคลภายนอกที่ผสานทั้งสองเข้ากับกระบวนการตรวจสอบ

#2. เตรียมสภาพแวดล้อม

ต้องมี Node.js รุ่นใหม่ (เอกสาร Tessl แนะนำ Node.js 22.17+), Python 3.11+ สำหรับตัวอย่างนี้, Git, AI Coding Agent เช่น Claude Code/Cursor/Copilot/Codex และเทอร์มินัล Bash

ระบบปฏิบัติการ: macOS/Linux เหมาะกับคำสั่งด้านล่าง; สำหรับ Windows แนะนำ WSL2 เพราะการรองรับ Tessl บน Windows ผ่าน WSL ยังระบุว่าเป็นแบบทดลอง

#2.1 ติดตั้ง Tessl CLI

บน Linux/WSL/macOS:

curl -fsSL https://get.tessl.io | sh
tessl --help

หากใช้ macOS + Homebrew:

brew install tesslio/tap/tessl

ตรวจสอบสคริปต์ติดตั้งและแหล่งที่มาก่อนเรียกผ่าน curl | sh เสมอ; การล็อกอิน Tessl อาจจำเป็นตามสิทธิ์ของ Registry/บัญชี

tessl login

#2.2 ติดตั้ง OpenSpec

npm install -g @fission-ai/openspec
openspec --version

#2.3 สร้างโครงการ

mkdir tessl-todo-workshop
cd tessl-todo-workshop
git init
mkdir -p app tests
touch app/__init__.py

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install 'fastapi>=0.115' 'pydantic>=2' 'uvicorn>=0.30' 'httpx>=0.27' 'pytest>=8' 'PyYAML>=6'
python -m pip freeze > requirements.txt

# ตั้งค่า Tessl ให้เชื่อมกับ Claude Code (เปลี่ยน agent ได้)
tessl init --agent claude-code --project-dependencies skip

# ตั้งค่า OpenSpec และเลือก AI Coding Agent ที่ใช้งานจริง
openspec init

ขณะ openspec init ให้เลือกเครื่องมือ AI ตามที่ปรากฏ ถ้า Agent ไม่เห็นคำสั่งใหม่ให้ปิดและเปิด session ของ Agent อีกครั้ง

ตรวจสอบ:

tessl list
openspec list
python -m pytest --version

#3. กำหนดขอบเขต Workshop ก่อนสร้างโค้ด

ระบบ Todo API จะมี endpoint สามรายการ:

Method Endpoint ผลลัพธ์ที่คาดหวัง
POST /todos สร้าง Todo โดยคืน HTTP 201 และสถานะเริ่มต้น done=false
GET /todos แสดง Todos ทั้งหมดตามลำดับการสร้าง คืน HTTP 200
PATCH /todos/{id}/complete ปรับ done=true; ถ้าไม่พบ ID คืน HTTP 404

Business Rules / Acceptance Criteria

  1. title ต้องมีอักขระจริงหลังตัดช่องว่างหัวท้าย และยาวไม่เกิน 120 ตัวอักษร มิฉะนั้นคืน 422 (การตรวจข้อมูลด้วย FastAPI/Pydantic)
  2. Todo ใหม่มี id เป็นจำนวนเต็มที่ไม่ซ้ำภายในโปรเซส และ done=false
  3. สามารถแสดงรายการได้ตามลำดับการสร้าง
  4. การ complete สำเร็จทำให้ done=true; ID ที่ไม่มีอยู่คืน 404
  5. ข้อมูลถูกเก็บไว้ในหน่วยความจำเพื่อเน้นกระบวนการ Spec; รีสตาร์ตแล้วข้อมูลหาย (ไม่ใช่ตัวอย่าง production persistence)

#พรอมป์ต์สำหรับ AI Coding Agent (ขั้น Spec-anchored)

พิมพ์ข้อความนี้ ในช่องสนทนาของ AI Coding Agent ไม่ใช่ใน Terminal:

/opsx:propose create-todo-api
Create a Todo REST API using Python FastAPI.
Requirements:
- POST /todos returns 201 with id, trimmed title, done=false.
- Empty/blank title and title length over 120 return 422.
- GET /todos returns all todos in insertion order.
- PATCH /todos/{id}/complete returns updated todo; unknown id returns 404.
- Store data in memory for this workshop only.
- Include pytest tests and explain acceptance criteria.
Do not implement yet; review the proposal, spec, design, and tasks first.

หมายเหตุ: /opsx:propose และ /opsx:apply เป็นคำสั่ง ภายใน Agent Chat ของ OpenSpec ไม่ใช่คำสั่ง Shell; รูปแบบการเรียกอาจต่างกัน เช่น Cursor/Copilot ใช้ /opsx-propose และ Codex ใช้ Skill แทน slash command ให้ยึดข้อความที่ openspec init สร้างสำหรับ Agent นั้น

ทบทวนเอกสารใน openspec/changes/<ชื่อ-change>/ โดยเฉพาะ proposal, specs และ tasks จากนั้นจึงสั่ง:

/opsx:apply

เมื่องานผ่าน Test/Review ให้สั่ง:

/opsx:archive

หรือใช้ CLI ตรวจสอบรายละเอียดก่อน archive:

openspec list
openspec validate --help
openspec view

หลัง archive ตัว Spec หลักจะอยู่ในลักษณะ openspec/specs/todo-api/spec.md (ชื่อ capability ขึ้นกับที่ Agent สร้างจริง)

#4. เขียน Capability Spec ให้ตรวจสอบได้

ในขั้น Spec-anchored คุณอาจมีข้อกำหนดแต่ยังไม่มี metadata ครบสำหรับการบังคับใช้ Spec-as-source ต่อไปนี้คือตัวอย่างไฟล์ที่เราจะใช้เป็น canonical spec หลังจัดระเบียบแล้ว:

ไฟล์: openspec/specs/todo-api/spec.md

---
targets:
  - app/main.py
---

# Todo API Specification

## Purpose

Provide a minimal API to create, list, and complete todos.

## Requirements

### Requirement: Create todo
The system SHALL create a todo with a unique integer id,
trimmed title, and done=false, responding with HTTP 201.

**Verified by**: [@test] tests/test_todos.py

#### Scenario: Valid creation
- **WHEN** the client POSTs a valid title to /todos
- **THEN** the response is HTTP 201 with id, title, and done=false

### Requirement: Reject invalid title
The system MUST reject a blank title or title exceeding
120 characters with HTTP 422.

**Verified by**: [@test] tests/test_todos.py

#### Scenario: Blank or overlong title
- **WHEN** the client POSTs an invalid title
- **THEN** the response is HTTP 422 and no todo is created

### Requirement: List todos
The system SHALL return all todos in insertion order via GET /todos.

**Verified by**: [@test] tests/test_todos.py

#### Scenario: List after creation
- **WHEN** the client requests GET /todos after creating two todos
- **THEN** the response is HTTP 200 with both todos in order

### Requirement: Complete todo
The system SHALL mark a todo done via PATCH /todos/{id}/complete
and MUST return HTTP 404 if the id does not exist.

**Verified by**: [@test] tests/test_todos.py

#### Scenario: Existing todo
- **WHEN** the client completes a known todo id
- **THEN** the response contains done=true

#### Scenario: Unknown todo
- **WHEN** the client completes an unknown todo id
- **THEN** the response is HTTP 404

อธิบายไวยากรณ์ที่สำคัญ:

  • targets: ระบุ source files ที่ Spec เป็นเจ้าของ โดยใช้พาธอิง root ของ repo
  • ### Requirement: ... เป็นหัวข้อ Requirement ในไวยากรณ์ OpenSpec รุ่นปัจจุบัน ไม่ใช้รูปแบบเก่า REQ-XXX เป็นหัวข้อ
  • SHALL/MUST ระบุพฤติกรรมเชิงบังคับที่ทดสอบได้
  • **Verified by**: [@test] ... เชื่อม Requirement กับไฟล์ทดสอบที่มีอยู่จริง
  • #### Scenario: และ WHEN/THEN กำหนด Acceptance Criteria ให้ชัดเจน

หาก OpenSpec สร้าง canonical spec ใหม่โดยไม่มี targets: ให้เติมผ่าน Skill spec-writer หลังการรวม Spec ตามแนวทาง Tile ที่ติดตั้ง

#5. Reference Implementation: FastAPI

ถ้าต้องการเปรียบเทียบโค้ดที่ AI สร้างกับตัวอย่างที่ทดสอบได้ ให้ใช้ implementation ต่อไปนี้ ทั้งนี้ ในกระบวนการจริง ให้ Agent สร้าง/แก้โค้ดจาก Spec อย่าใช้การคัดลอกโค้ดเพื่อข้ามกระบวนการทบทวน Spec

ไฟล์: app/main.py

# GENERATED FROM SPEC: openspec/specs/todo-api/spec.md
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field, field_validator


class TodoCreate(BaseModel):
    title: str = Field(min_length=1, max_length=120)

    @field_validator("title")
    @classmethod
    def normalize_title(cls, value: str) -> str:
        value = value.strip()
        if not value:
            raise ValueError("title must not be empty")
        return value


class Todo(BaseModel):
    id: int
    title: str
    done: bool = False


def create_app() -> FastAPI:
    app = FastAPI(title="Spec-Driven Todo API")
    todos: dict[int, Todo] = {}
    next_id = 1

    @app.post("/todos", response_model=Todo, status_code=201)
    def create_todo(payload: TodoCreate) -> Todo:
        nonlocal next_id
        todo = Todo(id=next_id, title=payload.title)
        todos[next_id] = todo
        next_id += 1
        return todo

    @app.get("/todos", response_model=list[Todo])
    def list_todos() -> list[Todo]:
        return list(todos.values())

    @app.patch("/todos/{todo_id}/complete", response_model=Todo)
    def complete_todo(todo_id: int) -> Todo:
        todo = todos.get(todo_id)
        if todo is None:
            raise HTTPException(status_code=404, detail="Todo not found")
        updated = todo.model_copy(update={"done": True})
        todos[todo_id] = updated
        return updated

    return app


app = create_app()

#รัน API

uvicorn app.main:app --reload

เปิด http://127.0.0.1:8000/docs เพื่อทดลองผ่าน Swagger UI หรือทดสอบด้วย curl (เปิด Terminal อีกหน้าต่าง):

curl -i -X POST http://127.0.0.1:8000/todos \
  -H 'Content-Type: application/json' \
  -d '{"title":"Learn Spec-Driven Development"}'

curl -i http://127.0.0.1:8000/todos
curl -i -X PATCH http://127.0.0.1:8000/todos/1/complete

ผลลัพธ์ที่คาดหวัง: การสร้างครั้งแรกได้ 201 และออบเจ็กต์ที่มี id: 1, done: false; หลัง PATCH จะเป็น done: true

#6. Automated Tests: เชื่อม Spec กับพฤติกรรมจริง

ไฟล์: tests/test_todos.py

from fastapi.testclient import TestClient
from app.main import create_app


def client() -> TestClient:
    return TestClient(create_app())


def test_create_todo_returns_201() -> None:
    with client() as c:
        response = c.post("/todos", json={"title": "Write a spec"})
        assert response.status_code == 201
        assert response.json() == {"id": 1, "title": "Write a spec", "done": False}


def test_rejects_blank_or_whitespace_title() -> None:
    with client() as c:
        for title in ["", "  "]:
            assert c.post("/todos", json={"title": title}).status_code == 422


def test_rejects_overlong_title() -> None:
    with client() as c:
        assert c.post("/todos", json={"title": "x" * 121}).status_code == 422


def test_list_todos() -> None:
    with client() as c:
        c.post("/todos", json={"title": "First"})
        c.post("/todos", json={"title": "Second"})
        response = c.get("/todos")
        assert response.status_code == 200
        assert [t["title"] for t in response.json()] == ["First", "Second"]


def test_complete_todo() -> None:
    with client() as c:
        todo_id = c.post("/todos", json={"title": "Finish workshop"}).json()["id"]
        response = c.patch(f"/todos/{todo_id}/complete")
        assert response.status_code == 200
        assert response.json()["done"] is True


def test_complete_unknown_todo_is_404() -> None:
    with client() as c:
        assert c.patch("/todos/999/complete").status_code == 404

รันทดสอบที่ root ของ repo:

python -m pytest -q

สำหรับ reference implementation ข้างต้น ตรวจสอบแล้วว่าชุดทดสอบ 6 cases ผ่านทั้งหมด บนสภาพแวดล้อมทดสอบของบทความ (ผลในเครื่องผู้เรียนอาจต่างกันเมื่อใช้เวอร์ชันแพ็กเกจ/โค้ดที่ AI สร้างต่างออกไป)

หมายเหตุการออกแบบ: Test แยก state ด้วย create_app() ทุกครั้ง เพื่อไม่ให้ Todo จาก test หนึ่งส่งผลต่อ test ถัดไป

#7. ยกระดับจาก Spec-anchored สู่ Spec-as-source ด้วย Tessl

เราจะติดตั้ง Tile ที่ให้กฎและ Skills สำหรับ ownership, test-link checking และ CI enforcement โดยไม่สับสนกับการใช้งาน Tessl Spec Registry สำหรับ library-usage documentation ตามปกติ

#7.1 ติดตั้ง Tile ชุมชน

ตรวจสอบรายละเอียด, เวอร์ชัน, และ Security Scan ที่หน้า Registry ก่อนติดตั้ง:

https://tessl.io/registry/spec-driven-development/spec-as-source

จาก root ของโปรเจ็กต์:

tessl search spec-as-source
tessl install spec-driven-development/spec-as-source
tessl list

สำคัญ: เคยมี namespace สะกดผิดเป็น spec-driven-devlopment ในรุ่นเก่า และผู้พัฒนาย้ายไป spec-driven-development ตั้งแต่สาย 3.x; ไม่ควรคัดลอกคำสั่งเก่าจากบทความก่อนหน้านั้นโดยตรง

#7.2 ให้ Agent เตรียมระบบ Enforcement

หลังติดตั้ง Tile และเปิด Session ของ Agent ใหม่ หาก Agent มองเห็น Skills ของ Tile ให้ส่งข้อความต่อไปนี้ ใน Agent Chat:

Use spec-as-source-setup.
Inspect the installed skill and set up the OpenSpec spec-as-source schema,
verification scripts, and CI for this repository. Report which files were
created or modified. Do not overwrite existing custom CI without review.

คาดว่าจะมีโครงสร้างลักษณะนี้หลังขั้น setup (ขึ้นกับรุ่นของ Tile):

openspec/
  schemas/spec-as-source/
  specs/todo-api/spec.md
scripts/
  check-spec-links.sh
  check-target-ownership.sh
  build-spec-manifest.py
  check-plan-gate.sh
  verify.sh
.github/workflows/
  spec-verification.yml

อย่าสับสน: ตัวอย่างนี้เป็นผลลัพธ์ที่ คาดหวังจาก Skill setup ไม่ใช่สิ่งที่คำสั่ง tessl install สร้างทั้งหมดทันที และไม่ใช่คำสั่งที่ทดลองรันจริงในบทความ

#7.3 สร้าง Plan ที่ผ่าน Approval Gate

Tile นี้มี Skill plan-mode และกติกาอนุมัติแผนก่อนสร้าง change ใหม่ ใช้ใน Agent Chat:

Use plan-mode.
Prepare openspec/PLAN.md for extending the Todo API with delete-todo.
Show the planned change and request human approval before implementation.

เมื่อแผนได้รับอนุมัติตามขั้นตอนของ Skill จึงเข้าสู่การเสนอ Change ใหม่ผ่าน openspec-propose หรือ OpenSpec workflow ที่ติดตั้งจริง อย่าถือว่าแค่สร้างไฟล์ PLAN.md แปลว่าได้รับอนุมัติแล้ว

#7.4 ตรวจ Spec, Source และ Tests

หลัง setup สร้างสคริปต์แล้ว ให้รัน:

bash scripts/check-spec-links.sh
bash scripts/check-target-ownership.sh
python scripts/build-spec-manifest.py
bash scripts/verify.sh

หรือสั่ง Agent:

Use spec-verify.
Review the todo-api spec, declared targets, linked tests,
and potential semantic drift. Give file-and-line evidence.

การตรวจสอบหลักมีดังนี้:

Check ตรวจเรื่องอะไร ตัวอย่างข้อผิดพลาด
Spec Links [@test] ชี้ไปยังไฟล์ที่มีจริง เขียน tests/test_create.py แต่ไม่มีไฟล์
Target Ownership การเปลี่ยนไฟล์ target สอดคล้องกับ Spec เจ้าของ แก้ app/main.py โดยไม่แก้ Spec ตาม policy
Manifest อ่าน/เชื่อม metadata ของ Spec ได้ YAML frontmatter ผิดรูปแบบ
Test Suite โค้ดทำตามพฤติกรรมที่ทดสอบ POST คืน 200 แทน 201
Semantic Review ความหมายของ Code และ Spec ตรงกัน มี rule ใหม่ในโค้ดแต่ไม่มี requirement หรือ test

ข้อจำกัด: Shell checks ตรวจรูปแบบ/ความสัมพันธ์/ประวัติการเปลี่ยนแปลงได้ แต่ไม่สามารถพิสูจน์ความถูกต้องของพฤติกรรมทั้งหมดโดยลำพัง จึงยังจำเป็นต้องทำ Review และเพิ่ม Tests ที่มีคุณภาพ

#8. ทดลองทำ Spec Drift ให้ตรวจจับได้

#Exercise A: ทำให้ Test ล้มเหลว

  1. แก้ app/main.py จาก status_code=201 เป็น status_code=200 โดย ไม่แก้ Spec
  2. รัน python -m pytest -q
  3. ดูว่ากรณี test_create_todo_returns_201 ล้มเหลว เพราะพฤติกรรมจริงขัดกับ Spec ที่กำหนด HTTP 201
  4. กลับไปแก้ status_code=201 เพื่อคืนสภาพระบบ

สิ่งที่เรียนรู้: Tests ตรวจ behavioral drift ที่มี Assertion ครอบคลุม แม้ไฟล์ test ยังมีอยู่ครบ

#Exercise B: ทำให้ Spec Link หายไป

  1. สำรอง Spec ใน branch ทดลอง
  2. เปลี่ยนลิงก์ **Verified by**: [@test] tests/test_todos.py เป็น **Verified by**: [@test] tests/missing_test.py
  3. รัน bash scripts/check-spec-links.sh
  4. คาดหวัง Check ไม่ผ่าน เพราะไฟล์อ้างอิงไม่มีจริง
  5. คืนพาธเดิมแล้วรันตรวจอีกครั้ง

#Exercise C: ทดสอบ Ownership Gate ผ่าน Git Diff

  1. Commit baseline เมื่อ Spec, Source และ Tests ผ่านทุก Check แล้ว
  2. สร้าง branch ทดลอง แก้ app/main.py โดยไม่ปรับ Spec เจ้าของ
  3. เรียก Ownership Check ตามวิธีเทียบ base branch/commit ที่สคริปต์เวอร์ชันติดตั้งรองรับ หรือเปิด PR เพื่อให้ CI เป็นผู้ตรวจ
  4. คาดหวัง CI แจ้ง policy violation เมื่อมีการเปลี่ยน Target โดยไม่มีการอัปเดต Spec ที่เกี่ยวข้อง
  5. ปรับ Spec และ Tests ให้เป็นเหตุเป็นผลก่อนรวม PR

คำเตือน: Ownership check ต้องมี baseline/การเปรียบเทียบ Git ที่เหมาะสม จึงไม่ควรตีความการรันบน working tree เปล่า ๆ ว่าตรวจประวัติ PR ได้ครบ และการแก้ Spec แบบไม่มีสาระเพื่อหลบ Gate ก็ยังต้องถูกปฏิเสธในการ Review

#9. CI/CD: บังคับ Spec-as-source ใน GitHub Actions

โดยปกติ spec-as-source-setup สามารถสร้าง workflow สำหรับ CI ให้อยู่แล้ว ควรเปิดอ่านและปรับให้ตรง repository ก่อนใช้ ตัวอย่างต่อไปนี้เป็น แนวทางสำหรับ repo ตัวอย่างเมื่อมี scripts/verify.sh อยู่จริง ไม่ใช่ไฟล์ CI ที่ Tessl สร้างโดยตรง:

ไฟล์: .github/workflows/spec-checks.yml

name: Spec Verification
on:
  pull_request:
  push:
    branches: [main]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - name: Install dependencies
        run: |
          python -m pip install -r requirements.txt
          npm install -g @fission-ai/openspec
      - name: Run spec validation and tests
        run: bash scripts/verify.sh

ก่อนนำขึ้น Production: ตรวจ script จริงของ Tile, สิทธิ์ของ Workflow, การเปรียบเทียบ base branch, dependencies และ Security Scan; หลีกเลี่ยงการกำหนดสิทธิ์ write ถ้า Check อ่านอย่างเดียว

#10. ขั้นตอนพัฒนาฟีเจอร์ใหม่แบบ Spec-as-source

ตัวอย่าง Requirement ใหม่: ลบ Todo ด้วย DELETE /todos/{id}

sequenceDiagram
    participant Dev as Developer
    participant Spec as OpenSpec / Plan
    participant AI as Coding Agent
    participant CI as Verify + CI
    Dev->>Spec: เสนอ Change และ Acceptance Criteria
    Spec-->>Dev: แสดง Plan/Spec ให้ตรวจและอนุมัติ
    Dev->>AI: Implement ตาม Spec ที่อนุมัติ
    AI->>AI: แก้ Target และเขียน Tests
    AI->>CI: Run links / ownership / tests
    alt มี drift หรือ tests fail
      CI-->>AI: Report mismatch
      AI->>Spec: ปรับงานให้ตรงข้อกำหนด
    else ผ่านการตรวจ
      CI-->>Dev: Ready for human review
    end

Prompt ตัวอย่างใน Agent Chat:

Use prompt-loop.
Plan a DELETE /todos/{id} capability.
Constraints: existing id returns HTTP 204, missing id returns HTTP 404.
First update proposal and the capability spec including scenarios,
target ownership, and linked tests. Do not change source code until the
change and acceptance criteria are reviewed and approved.

เมื่อผ่านการอนุมัติ จึงให้ Agent Apply → Verify → Work Review → Sync/Archive ตาม workflow ที่ Tile/Agent ติดตั้งกำหนด

#11. แบบฝึกหัดท้าย Workshop

  1. เพิ่ม GET /todos/{id}: กำหนด 200 เมื่อพบ และ 404 เมื่อไม่พบ พร้อม Scenario และ Tests
  2. เพิ่ม DELETE /todos/{id}: ยืนยันว่า HTTP 204 ไม่มี response body พร้อม Negative Test
  3. เพิ่ม priority: ยอมรับค่า low, medium, high เท่านั้น สร้าง Requirement ใหม่และตรวจ Validation
  4. ทดลอง CI Gate: เปิด PR ที่แก้ Target แต่ไม่อัปเดต Spec บันทึกผล แล้วแก้ไขให้ผ่านอย่างถูกต้อง
  5. ทำ Traceability Matrix: ออกรายงาน Requirement → Target → Test → Result จาก Manifest ที่สร้างได้

#Checklist ก่อนส่งงาน

  • [ ] มี OpenSpec proposal/spec/tasks ที่ผ่านการรีวิว
  • [ ] canonical Spec อยู่ใต้ openspec/specs/<capability>/spec.md
  • [ ] ระบุ targets: ถูกต้องในทุก Capability ที่ต้องควบคุม Source
  • [ ] ทุก Requirement มี Scenario และ [@test] ที่ชี้ไฟล์จริง
  • [ ] สร้าง/ปรับ Source จาก Spec และมี Test สำหรับกรณีปกติและผิดพลาด
  • [ ] python -m pytest -q ผ่าน
  • [ ] bash scripts/verify.sh ผ่านหลัง Tile setup (ถ้าติดตั้ง)
  • [ ] ทดลองทำให้ CI ล้มเหลวได้จริงเมื่อเกิด Drift
  • [ ] มี Human Review ก่อน Merge ไม่พึ่งผล AI อย่างเดียว

#12. ปัญหาที่พบบ่อย

อาการ สาเหตุที่เป็นไปได้ แนวทางแก้
tessl: command not found ติดตั้ง CLI ไม่สำเร็จ/PATH ไม่ถูก ตรวจวิธีติดตั้งตาม OS และ tessl --help
/opsx:propose ไม่ทำงานใน Terminal เป็นคำสั่ง Agent Chat เรียกใน Agent หรือใช้รูปแบบที่ openspec init แจ้ง
Skill spec-as-source-setup ไม่ปรากฏ Agent ไม่โหลด Skill หลังติดตั้ง ตรวจ tessl list, ไฟล์ Tile ที่ติดตั้ง และ restart Agent
scripts/verify.sh ไม่มี ยังไม่ได้ run Skill setup ให้ Agent ดำเนินการ setup และดูรายงานไฟล์ที่สร้าง
check-spec-links ไม่ผ่าน ไฟล์ [@test] ไม่อยู่ตาม path เพิ่มไฟล์ทดสอบหรือแก้ลิงก์ให้ถูกต้อง
Ownership check แปลก ๆ ไม่ได้กำหนด base commit/branch หรือ spec ownership ตรวจ git history, frontmatter และ script version
OpenSpec Spec รูปแบบต่างจากบทความ ใช้ schema/profile/plugin คนละรุ่น ดู openspec --version, schema และ Skill ที่ติดตั้งจริง
Windows เรียก shell script ไม่ได้ ใช้ PowerShell แทน Bash ใช้ WSL2 หรือ shell ที่รองรับ Bash

#บทสรุป

Spec-anchored ทำให้ AI Coding Agent มีขอบเขตและข้อกำหนดชัดเจนก่อนพัฒนา ส่วน Spec-as-source เพิ่มหลักฐานและกลไกควบคุมความสัมพันธ์ของ Spec, Source, Tests และ CI เพื่อป้องกันไม่ให้โค้ดค่อย ๆ เปลี่ยนไปโดยไม่มี Spec รองรับ

สำหรับโครงการที่ต้องการเริ่มใช้อย่างมีประสิทธิภาพ ควรเริ่มจาก Capability เล็ก ๆ, เขียน Acceptance Criteria ที่ทดสอบได้, ทบทวนผลที่ Agent เสนอ แล้วจึงเพิ่ม Ownership Gate ใน CI เมื่อทีมพร้อม การมี [@test] หรือ Target Manifest ไม่ได้รับประกัน ว่าระบบถูกต้องเชิงธุรกิจทั้งหมด: Human Review, Security Testing และ Test Coverage ยังจำเป็น

#แหล่งอ้างอิง (เข้าถึง 15 ตุลาคม 2026)

  1. Tessl — CLI Commands
  2. Tessl — Supported platforms
  3. Tessl — Installing the CLI
  4. Tessl Registry — spec-driven-development/spec-as-source (community Tile, authored by Giuseppe Di Canosa)
  5. Tessl Registry — Spec Writer Skill
  6. OpenSpec — How Commands Work
  7. OpenSpec — CLI Reference
  8. OpenSpec — Slash Commands
  9. Tessl Blog — Tessl Launches Spec-Driven Framework and Registry

หมายเหตุเชิงปฏิบัติ: ตัวอย่าง FastAPI และ pytest ในบทความนี้ถูกทดสอบแยกในสภาพแวดล้อม Python แล้ว ส่วนคำสั่ง Tessl / OpenSpec / Tile setup เป็นขั้นตอนจากเอกสารอ้างอิงซึ่งต้องเรียกในเครื่องที่ติดตั้งเครื่องมือและ Agent จริง