The "Where & Why": ก้าวข้าม Vendor-Lock สู่ Universal Single-Source Distribution
ปัญหาคอขวดที่พบในระดับองค์กร 1,000+ คน: วิศวกรในองค์กรไม่ได้ใช้เครื่องมือตัวเดียวกัน วิศวกรสาย Frontend อาจใช้ Cursor, สาย Backend ใช้ GitHub Copilot ใน IntelliJ, และสาย Infra/Platform ใช้ Claude Code ใน CLI การคัดลอกคำสั่งแยกเป็น
.cursorrules, CLAUDE.md, และ Copilot Prompts จะทำให้เกิด Configuration Drift และสูญเสีย Single Source of Truthเป้าหมายของ Day 12: ติดตั้ง Universal Packaging & Transpilation Pipeline (
package-cross-host.py) ที่แปลง canonical SKILL.md ตัวเดียวให้กลายเป็น Native Adapter ของ GitHub Copilot, Cursor Rules (.mdc), และ Claude Code Commands พร้อมแจกจ่ายผ่าน Central Repository
┌────────────────────────────────────────────────────────────────────────┐
│ CANONICAL SOURCE OF TRUTH (agentskills Standard Specification) │
│ .github/skills/spring-boot-unit-tester/SKILL.md │
│ [YAML Frontmatter + Invariants + PRS Exemplars + Deterministic Tools] │
└───────────────────────────────────┬────────────────────────────────────┘
│
▼ (tools/package-cross-host.py Compiler)
┌────────────────────────────────────────────────────────────────────────┐
│ 🎯 CROSS-HOST PACKAGING & ADAPTER TRANSPILATION PIPELINE │
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ ┌────────────┐ │
│ │ GITHUB COPILOT ADAPTER │ │ CURSOR AI RULES ADAPTER │ │ CLAUDE │ │
│ │ Target: .github/skills/ │ │ Target: .cursor/rules/ │ │ CODE CLI │ │
│ │ - Preserves Frontmatter │ │ - Converts to .mdc spec │ │ Target: │ │
│ │ - Verifies scripts CLI │ │ - Configures glob masks │ │ CLAUDE.md │ │
│ │ - Injects Copilot tags │ │ - Sets alwaysApply:false│ │ Injection │ │
│ └─────────────────────────┘ └─────────────────────────┘ └────────────┘ │
└───────────────────────────────────┬────────────────────────────────────┘
│
▼ (Enterprise Distribution Matrix)
┌────────────────────────────────────────────────────────────────────────┐
│ CENTRAL MONOREPO DISTRIBUTION / SUBMODULE HYDRATION │
│ Guaranteed 100% Behavioral Consistency across IDEs, Terminals & Clouds │
└────────────────────────────────────────────────────────────────────────┘
Single Source of Truth
เขียนคำสั่งและ Invariant ใน SKILL.md จุดเดียว แล้วใช้สคริปต์คอมไพล์แปลงร่างส่งต่อไปยังทุก Host Agent โดยไม่มีข้อขัดแย้ง
Native Feature Mapping
แปลง Metadata ให้เข้ากับฟีเจอร์เฉพาะของแต่ละ Host เช่น แปลง Negative Guards เป็น globs ใน Cursor และ Tool Declarations ใน Claude Code
100% Behavioral Parity
รันการทดสอบและ Invariants แบบเดียวกันทุกแพลตฟอร์ม ไม่ว่านักพัฒนาจะนั่งทำงานอยู่บน IntelliJ, VS Code หรือ Bash Terminal
วิศวกรรม Cross-Host Compatibility: การประสานความแตกต่างของ Host Agent Runtimes
ในโลกของ Software Development สถาปัตยกรรมแบบ Cross-Platform (เช่น Java Virtual Machine หรือ WebAssembly) ประสบความสำเร็จได้เพราะมี Standard Bytecode ที่ทำงานผ่าน Runtime Adapter ในโลกของ AI Engineering มาตรฐาน agentskills/agentskills ทำหน้าที่เป็น Canonical Spec ขณะที่แต่ละ Host Agent มีไวยากรณ์และกลไกการรับรู้คำสั่งที่แตกต่างกันอย่างมีนัยสำคัญ
| มิติสถาปัตยกรรม (Dimension) | GitHub Copilot | Cursor AI | Claude Code (Anthropic CLI) |
|---|---|---|---|
| Config Location | .github/skills/<skill>/SKILL.md | .cursor/rules/<skill>.mdc | CLAUDE.md / .claude/tools/ |
| Triggering Mechanism | Semantic Cosine Router บน YAML description |
File glob pattern matching + Context Embeddings | Slash commands (/skill) + CLI Tool Declarations |
| Tool Invocation Protocol | Host Terminal agent runs scripts relative to repo root | Cursor Bash command execution in workspace terminal | Native sub-process tool execution with exit code capture |
| Context Degradation Risk | ต่ำ: โหลดคำสั่งเฉพาะเมื่อ Intent ตรง | ปานกลาง: หากตั้ง alwaysApply: true จะบวม |
ต่ำ: โหลดแบบ Project-level Context Guide |
แทนที่จะเขียนและอัปเดตไฟล์คอนฟิกทั้ง 3 ค่ายด้วยมือ เรานำแนวคิด Compiler Shim มาใช้:
สคริปต์จะแปลงฟิลด์ YAML Metadata ของ standard agentskills ให้กลายเป็น Header ที่ Cursor เข้าใจ (เช่น globs: ["src/test/kotlin/**/*Test.kt"]) และแปลง Tool Call Syntax ให้เข้ากับ CLI ของ Claude Code โดยอัตโนมัติ
เมื่อแพ็กเกจ Skill พร้อมส่งมอบให้ทีมงาน 1,000+ คน องค์กรสามารถเลือกใช้กลยุทธ์การแจกจ่ายได้ 3 รูปแบบ:
- 1. Central Git Submodule: เก็บ Skills ใน repository กลาง (เช่น
enterprise-agent-skills) แล้วดึงเข้ามาเป็น Git Submodule ในทุก Microservice - 2. CI Sync GitHub Action: มี Automated Bot ยิง Pull Request อัปเดต Skills ไปยังทุกโปรเจกต์เมื่อเวอร์ชันในคลังกลางขยับขึ้น
- 3. Monorepo Native Symlinks: ในระบบ Monorepo วาง Skill ไว้ที่ Root และสร้าง POSIX Symlink เข้าไปยังโฟลเดอร์ของแต่ละทีม
Production Artifact: The Universal Multi-Host Transpiler
ชุดเครื่องมือแปลงสภาพแพ็กเกจมาตรฐาน agentskills/agentskills ให้กลายเป็น Native Rules ของ Cursor AI และ Claude Code อัตโนมัติ พร้อมสคริปต์ตรวจสอบความสอดคล้อง 100%
repo-root/
├── .github/skills/spring-boot-unit-tester/ ◄── [CANONICAL SPECIFICATION]
│ ├── SKILL.md
│ └── scripts/run-unit-tests.sh
├── .cursor/rules/ ◄── [AUTOGENERATED BY TRANSPILER]
│ └── spring-boot-unit-tester.mdc ◄── Native Cursor Rules with Globs
├── CLAUDE.md ◄── [AUTOGENERATED/UPDATED]
└── tools/
└── package-cross-host.py ◄── [TODAY'S ARTIFACT: UNIVERSAL TRANSPILER]
#!/usr/bin/env python3
"""
package-cross-host.py
Standard: agentskills Standard v1.0 (Phase 4 Final Distribution)
Compiles canonical .github/skills//SKILL.md into:
1. Native Cursor Rules (.cursor/rules/.mdc)
2. Native Claude Code Architecture Guide (CLAUDE.md)
Ensures zero configuration drift across all developer IDEs.
"""
import sys
import os
import re
from pathlib import Path
# // [TODAY'S LESSON PLUGS IN HERE: MULTI-HOST TRANSPILATION & PACKAGING]
def parse_canonical_skill(skill_file: Path) -> dict:
"""Parses Frontmatter and Markdown instruction body from canonical SKILL.md."""
raw = skill_file.read_text(encoding="utf-8")
fm_match = re.search(r"^---\s*([\s\S]*?)\s*---([\s\S]*)$", raw)
if not fm_match:
raise ValueError(f"Malformed SKILL.md in {skill_file}: No valid YAML frontmatter delimiters.")
fm_raw = fm_match.group(1)
body = fm_match.group(2).strip()
name_m = re.search(r"^name:\s*(.+)$", fm_raw, re.MULTILINE)
desc_m = re.search(r"description:\s*>?-?\s*([\s\S]*?)(?=\n[a-zA-Z0-9_-]+:|$)", fm_raw)
return {
"name": name_m.group(1).strip() if name_m else skill_file.parent.name,
"description": " ".join(desc_m.group(1).split()) if desc_m else "",
"body": body,
"skill_dir": skill_file.parent
}
def generate_cursor_rule(skill_data: dict, out_dir: Path) -> Path:
"""
Generates native Cursor MDC Rule with optimized globs and alwaysApply: false
to prevent context flooding while preserving exact architectural invariants.
"""
out_dir.mkdir(parents=True, exist_ok=True)
target_file = out_dir / f"{skill_data['name']}.mdc"
cursor_content = f"""---
description: {skill_data['description']}
globs: ["src/test/kotlin/**/*Test.kt", "src/test/java/**/*Test.java"]
alwaysApply: false
---
{skill_data['body']}
"""
target_file.write_text(cursor_content, encoding="utf-8")
return target_file
def update_claude_code_manifest(skill_data: dict, repo_root: Path) -> Path:
"""
Injects or updates modular skill block inside project-level CLAUDE.md.
Maintains clean boundaries using sentinel comment tags.
"""
claude_file = repo_root / "CLAUDE.md"
start_tag = f""
end_tag = f""
block = f"""{start_tag}
## 🤖 Skill Integration: {skill_data['name']}
> {skill_data['description']}
### Verification Command:
`bash .github/skills/{skill_data['name']}/scripts/run-unit-tests.sh `
### Invariants:
- Pure isolated JVM memory execution (MockK + AssertJ).
- NEVER boot @SpringBootTest or Testcontainers for pure unit tests.
{end_tag}"""
if claude_file.exists():
content = claude_file.read_text(encoding="utf-8")
pattern = re.compile(rf"{re.escape(start_tag)}[\s\S]*?{re.escape(end_tag)}")
if pattern.search(content):
new_content = pattern.sub(block, content)
else:
new_content = content.rstrip() + f"\n\n{block}\n"
else:
new_content = f"# Project Architecture & Claude Code Instructions\n\n{block}\n"
claude_file.write_text(new_content, encoding="utf-8")
return claude_file
def main():
root = Path(__file__).resolve().parent.parent
canonical_skill = root / ".github" / "skills" / "spring-boot-unit-tester" / "SKILL.md"
if not canonical_skill.exists():
sys.stderr.write(f"Error: Canonical skill file not found at: {canonical_skill}\n")
sys.exit(1)
print("================================================================================")
print("📦 UNIVERSAL AGENT SKILL CROSS-HOST PACKAGING (Day 12)")
print("================================================================================")
print(f"Reading Canonical Spec: {canonical_skill}")
skill_data = parse_canonical_skill(canonical_skill)
# 1. Transpile to Cursor Rules
cursor_file = generate_cursor_rule(skill_data, root / ".cursor" / "rules")
print(f"✅ Generated Cursor Native Rule: {cursor_file.relative_to(root)}")
# 2. Update Claude Code Manifest
claude_file = update_claude_code_manifest(skill_data, root)
print(f"✅ Synchronized Claude Code Guide: {claude_file.relative_to(root)}")
print("--------------------------------------------------------------------------------")
print("🏆 SUCCESS: Single-Source-of-Truth published to Copilot, Cursor & Claude Code!")
sys.exit(0)
if __name__ == "__main__":
main()
---
description: Generates and refactors isolated JVM unit tests for Kotlin and Spring Boot 3.x using JUnit 5, MockK, AssertJ, and Coroutines Test.
globs: ["src/test/kotlin/**/*Test.kt", "src/test/java/**/*Test.java"]
alwaysApply: false
---
# Spring Boot Unit Test Architect Specification
## 1. Architectural Invariants (RFC 2119 Mandates)
- **MUST NOT** import `org.mockito.*` or `org.springframework.boot.test.mock.mockito.*`.
- **MUST NOT** annotate test classes with `@SpringBootTest`, `@DataJpaTest`, or `@WebMvcTest`.
- **MUST** execute strictly in-memory (< 50ms per method) without Spring ApplicationContext.
- **MUST** wrap all `suspend` methods inside `kotlinx.coroutines.test.runTest` using `coEvery`.
## 🤖 Skill Integration: spring-boot-unit-tester
> Generates and refactors isolated JVM unit tests for Kotlin and Spring Boot 3.x using JUnit 5, MockK, AssertJ, and Coroutines Test.
### Verification Command:
`bash .github/skills/spring-boot-unit-tester/scripts/run-unit-tests.sh `
### Invariants:
- Pure isolated JVM memory execution (MockK + AssertJ).
- NEVER boot @SpringBootTest or Testcontainers for pure unit tests.
Enterprise Incident: The "Works on Cursor, Fails on Claude Code" Drift
สถานการณ์จริงระดับองค์กร: เมื่อ 2 สัปดาห์ก่อน ทีมงานเขียน Rule ใน Cursor (.cursorrules) ห้ามใช้ Mockito แต่ไม่ได้อัปเดตไฟล์คอนฟิกของ GitHub Copilot และ Claude Code ส่งผลให้วิศวกรที่ทำงานผ่าน Terminal CLI ได้รับโค้ดที่มี Mockito ปนเปื้อนเข้ามาใน Pull Request เกิดข้อถกเถียงและเสียเวลาแก้ไขซ้ำซ้อน สถาปัตยกรรมที่ขาด Single-Source Transpilation ก่อให้เกิดต้นทุนความสูญเปล่ามหาศาล
- ยุบรวมไฟล์คอนฟิกที่กระจัดกระจาย ให้เหลือเพียง
.github/skills/spring-boot-unit-tester/SKILL.mdเป็น Single Source of Truth - รันสคริปต์
python3 tools/package-cross-host.pyเพื่อทำการคอมไพล์และกระจายสเปกไปยัง Cursor MDC และ Claude Code - ตรวจสอบความสอดคล้องของ Relative Script Paths เพื่อการันตีว่าคำสั่ง CLI รันผ่านได้จริง 100% จากทุกตำแหน่งไดเรกทอรี
$ python3 tools/package-cross-host.py
================================================================================
📦 UNIVERSAL AGENT SKILL CROSS-HOST PACKAGING (Day 12)
================================================================================
Reading Canonical Spec: /workspace/.github/skills/spring-boot-unit-tester/SKILL.md
✅ Generated Cursor Native Rule: .cursor/rules/spring-boot-unit-tester.mdc
✅ Synchronized Claude Code Guide: CLAUDE.md
--------------------------------------------------------------------------------
🏆 SUCCESS: Single-Source-of-Truth published to Copilot, Cursor & Claude Code!
$ echo $?
0
$ bash .github/skills/spring-boot-unit-tester/scripts/run-unit-tests.sh src/test/kotlin/com/enterprise/trading/settlement/SettlementReconciliationServiceTest.kt
{"status": "SUCCESS", "class": "SettlementReconciliationServiceTest", "verified": true}
$ echo $?
0
ทดสอบสถาปัตยกรรม Cross-Host Packaging & Distribution (Day 12)
ตอบคำถามเชิงสถาปัตยกรรมระดับองค์กรทั้ง 12 ข้อด้านล่าง ระบบจะตรวจคำตอบและให้ Feedback ทันทีเมื่อคลิกเลือกช้อยส์ พร้อมแสดงคำอธิบายเชิงลึก