Chapter 22 — Safe Sandbox Execution with Git Worktrees
ทำไมต้องชื่อนี้และเรียนไปเพื่ออะไร?
ใน Week 1 (Day 15–21) เราได้สร้าง "สมองกลและดวงตาอัจฉริยะ" (Dynamic Skills, AST Parser, Call Graph, Hybrid Retrieval) จนมองเห็นสถาปัตยกรรมทั้งระบบได้แม่นยำ แต่วันนี้เมื่อเข้าสู่ Week 2 เรากำลังจะปล่อยให้ Agent "ลงมือแก้ไขโค้ดจริง (Execution)" ปัญหาระดับวิกฤตของวิศวกรซอฟต์แวร์ทุกคนคือ: "ถ้า Agent แอบแก้โค้ดขณะที่เรากำลังเปิดหน้าต่าง VS Code หรือกำลังเขียนฟีเจอร์ค้างอยู่ หน้าจอและ Git index ของเราจะพังยับเยินทันที!"
ใน Day 22 เราจึงต้องสร้าง Safe Sandbox Execution โดยใช้ฟีเจอร์ระดับเทพของ Git ที่ชื่อว่า "Git Worktrees" เพื่อเปิดมิติคู่ขนานให้ AI แอบแยกไปทดลองแก้โค้ดในอีกโฟลเดอร์หนึ่งอย่างเงียบเชียบ ปลอดภัย 100% โดยไม่แตะต้อง Workspace หลักบน Mac M3 ของคุณแม้แต่น้อย!
ใน Day 22 เราจะสร้างโมดูลจัดการ Git Worktree เพื่อแยกสภาพแวดล้อมการทำงานของ Agent ออกจาก Workspace หลักอย่างปลอดภัย:
สร้างและจัดการโฟลเดอร์ทำงานแยกย่อย (Isolated Worktree) ผ่านคำสั่ง Git เพื่อให้ Agent สามารถแก้ไขไฟล์ ทดลองรันโค้ด และลบห้องทดลองทิ้งได้โดยไม่กระทบกับ Branch หลักของผู้ใช้งาน
สคริปต์จำลองการสั่งเปิด Sandbox, เขียนไฟล์จำลองลงไป, ตรวจสอบสถานะ Git Diff, และทดสอบการทำความสะอาด (Cleanup Worktree) หลังจบงาน
โฟลเดอร์งานหลักที่คุณเปิดใน VS Code (เช่น ~/projects/payment-api) ปลอดภัย 100% ไม่ถูกรบกวนขณะที่ AI กำลังทำงาน
กองกลางข้อมูล Git ที่แชร์ร่วมกันอย่างมีประสิทธิภาพ
โฟลเดอร์ชั่วคราวบน /tmp ที่แตก branch แยกเฉพาะกิจให้ Agent แก้ไขและรันเทส หากพังสามารถลบทิ้งได้ทันที
import subprocess
import uuid
import shutil
from pathlib import Path
class GitWorktreeSandbox:
"""
ตัวจัดการห้องทดลองลับด้วย Git Worktree (Python Context Manager)
รับประกันว่าทุกการแก้ไขและรันเทสของ AI Agent จะเกิดขึ้นในโฟลเดอร์แยกส่วนตัว
โดยไม่รบกวน Workspace หลักของผู้ใช้บน MacBook M3
"""
def __init__(self, repo_root: str, base_commit: str = "HEAD"):
self.repo_root = Path(repo_root).resolve()
# ตรวจสอบว่าพิกัดเป็น Git Repository จริง
if not (self.repo_root / ".git").exists():
raise ValueError(f"พิกัด {self.repo_root} ไม่ใช่ Git Repository ที่ถูกต้อง!")
# สร้างรหัสไอดีสุ่ม 8 ตัวอักษร เพื่อป้องกันชื่อโฟลเดอร์และ branch ชนกัน
self.unique_id = uuid.uuid4().hex[:8]
self.branch_name = f"agent/sandbox-{self.unique_id}"
self.sandbox_path = Path("/tmp") / f"agent-worktree-{self.unique_id}"
self.base_commit = base_commit
def __enter__(self) -> Path:
"""
[Spawn Phase]: ทำงานอัตโนมัติเมื่อเข้าสู่บล็อก 'with'
สั่งรันคำสั่ง git worktree add เพื่อแตกโฟลเดอร์แยกคู่ขนาน
"""
cmd = [
"git", "-C", str(self.repo_root),
"worktree", "add",
"-b", self.branch_name,
str(self.sandbox_path),
self.base_commit
]
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
return self.sandbox_path
except subprocess.CalledProcessError as e:
raise RuntimeError(f"ไม่สามารถสร้าง Git Worktree Sandbox ได้: {e.stderr}")
def __exit__(self, exc_type, exc_val, exc_tb):
"""
[Cleanup Phase]: ทำงานอัตโนมัติเมื่อหลุดจากบล็อก 'with' (ปลอดภัยแม้เกิด Error)
ถอด Worktree ลบโฟลเดอร์ใน /tmp และลบ Branch ชั่วคราวทิ้งสะอาดหมดจด
"""
# 1. ถอด Worktree ออกจากสารบัญ Git
subprocess.run(
["git", "-C", str(self.repo_root), "worktree", "remove", "--force", str(self.sandbox_path)],
check=False,
capture_output=True,
text=True
)
# 2. บังคับลบโฟลเดอร์ชั่วคราวซ้ำเพื่อความมั่นใจ
if self.sandbox_path.exists():
shutil.rmtree(self.sandbox_path, ignore_errors=True)
# 3. ลบ Branch ชั่วคราวทิ้ง
subprocess.run(
["git", "-C", str(self.repo_root), "branch", "-D", self.branch_name],
check=False,
capture_output=True,
text=True
)
from pathlib import Path
from core.sandbox import GitWorktreeSandbox
def main():
print("=" * 70)
print("🚀 เริ่มทดสอบ Day 22: Safe Sandbox Execution with Git Worktrees")
print("=" * 70)
# สมมติใช้โฟลเดอร์โปรเจกต์ปัจจุบันเป็น Git Repo หลัก
repo_root = Path.cwd().resolve()
print(f"📁 พิกัด Repository หลัก: {repo_root}")
try:
# ทดลองเปิดใช้งาน Context Manager ของ Sandbox
with GitWorktreeSandbox(str(repo_root)) as sandbox_dir:
print(f"✨ เข้าสู่ห้องทดลองลับสำเร็จที่: {sandbox_dir}")
# 1. ทดลองสร้างไฟล์ใหม่ข้างใน Sandbox
test_file = sandbox_dir / "agent_experiment.txt"
test_file.write_text("Hello from Isolated Sandbox!", encoding="utf-8")
print(f"✍️ Agent เขียนไฟล์ทดลองใน Sandbox สำเร็จ: {test_file.name}")
# 2. ตรวจสอบว่าไฟล์นี้ไม่มีอยู่ใน Repo หลัก (Zero Interference)
main_repo_file = repo_root / "agent_experiment.txt"
assert not main_repo_file.exists(), "❌ ผิดพลาด: ไฟล์รั่วไหลเข้ามาใน Repo หลัก!"
print("🛡️ ยืนยันความปลอดภัย: โฟลเดอร์หลักของมนุษย์สะอาด ไม่ถูกแตะต้อง 100%!")
# 3. เมื่อหลุดจากบล็อก with โฟลเดอร์ต้องถูกทำลายทิ้ง
print(f"\n🧹 ตรวจสอบหลังออกจาก with-block:")
print(f" 👉 โฟลเดอร์ Sandbox ยังอยู่ไหม? : {sandbox_dir.exists()} (ต้องเป็น False)")
assert not sandbox_dir.exists(), "❌ ล้มเหลว: โฟลเดอร์ใน /tmp ไม่ยอมลบตัวเอง!"
print("✅ การันตีความสะอาด: Sandbox ถูกทำลายทิ้งและคืนพื้นที่สมบูรณ์แบบ!")
print("\n" + "=" * 70)
print("🏆 ผ่านการทดสอบ Git Worktrees Sandbox สมบูรณ์แบบ 100%!")
print("🚀 คุณพร้อมเข้าสู่ Day 23: Autonomous Branching & Auto-Rollback แล้ว!")
print("=" * 70)
except Exception as err:
print(f"❌ เกิดข้อผิดพลาดในการทดสอบ Sandbox: {err}")
if __name__ == "__main__":
main()
ชำแหละไวยากรณ์สำคัญใน core/sandbox.py
uuid.uuid4().hex[:8]
Unique ID Generation: สร้างรหัสสุ่ม 8 ตัวอักษรเพื่อรับประกันว่าชื่อ Branch ชั่วคราวและโฟลเดอร์ใน `/tmp` จะไม่มีทางชนกัน แม้จะรัน Agent พร้อมกันหลายตัวขนานกัน
with GitWorktreeSandbox(...) as sandbox_path:
Python Context Manager Protocol: เมธอด __enter__ และ __exit__ ทำงานร่วมกับบล็อก with การันตีความสะอาด 100% ไม่ให้มีขยะโฟลเดอร์ค้างบนเครื่อง Mac M3
["git", "-C", str(self.repo_root), "worktree", "add", ...]
Safe Subprocess Execution: ส่งคำสั่งแบบ List ป้องกัน Command Injection พร้อมอาร์กิวเมนต์ -C เพื่อบอกให้ Git ไปทำงานที่พิกัดรากอย่างแม่นยำ
เปิด Terminal บน MacBook M3 แล้วทำตาม 5 ขั้นตอนนี้เพื่อติดตั้งและทดสอบ Git Worktree Sandbox ทันที:
cd ~/se_agent
source .venv/bin/activate
touch core/sandbox.py test_sandbox.py
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 1) ไปวางใน core/sandbox.py
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 2) ไปวางใน test_sandbox.py
python test_sandbox.py
🎉 ผลลัพธ์: Terminal จะรายงานการสร้าง Worktree ใน /tmp การเขียนไฟล์ทดลอง ยืนยันว่าโฟลเดอร์หลักไม่ถูกแตะต้อง และการล้างทำความสะอาดอัตโนมัติเมื่อจบการทำงานอย่างสมบูรณ์แบบ!
ข้อที่ 1: วัตถุประสงค์หลักของการนำ "Git Worktrees" มาใช้เป็น Sandbox ใน Day 22 คืออะไร?
ข้อที่ 2: หาก AI Agent ใช้คำสั่ง `git checkout -b new-branch` ในโฟลเดอร์โปรเจกต์หลักของมนุษย์โดยตรง จะเกิดปัญหาใดตามมา?
ข้อที่ 3: ข้อได้เปรียบที่สำคัญที่สุดของ `git worktree add` เมื่อเทียบกับการใช้ `git clone` โปรเจกต์ใหม่ทั้งก้อนคืออะไร?
ข้อที่ 4: คำสั่ง Git ใดที่ใช้สำหรับสร้าง Worktree ใหม่พร้อมแตก Branch แยกออกมาในโฟลเดอร์เป้าหมาย?
ข้อที่ 5: เหตุใดเราจึงนิยมชี้ตำแหน่ง Worktree ชั่วคราวของ Agent ไปไว้ที่โฟลเดอร์ `/tmp/` บนระบบ macOS/Linux?
ข้อที่ 6: การใช้โครงสร้าง `with GitWorktreeSandbox(...) as sandbox:` (Context Manager) ใน Python มีข้อดีอย่างไร?
ข้อที่ 7: คำสั่ง Git ใดที่ใช้สำหรับถอดและลบ Worktree ออกจากสารบัญระบบอย่างถูกต้อง?
ข้อที่ 8: สมมติว่า Agent สั่งแก้โค้ดใน Worktree แล้วรันคำสั่ง Build/Test ปรากฏว่าพังยับเยิน ผลกระทบต่อโปรเจกต์หลักของมนุษย์คืออะไร?
ข้อที่ 9: บนเครื่อง MacBook M3 (16GB RAM) การเปิด Git Worktree ใหม่ใช้เวลาและความจุประมาณเท่าใด?
ข้อที่ 10: คำสั่ง Git ใดที่ช่วยตรวจสอบรายชื่อ Worktrees ทั้งหมดที่กำลังเปิดใช้งานอยู่ใน Repository ปัจจุบัน?
ข้อที่ 11: หากมีคนไปลบโฟลเดอร์ Worktree ใน /tmp ทิ้งด้วยคำสั่ง `rm -rf` โดยไม่ผ่านคำสั่ง Git เราควรใช้คำสั่งใดเพื่อคลีนสารบัญ Git ให้กลับมาเป็นปกติ?
ข้อที่ 12: กฎเหล็กของ Git ข้อใดที่ป้องกันไม่ให้เราเผลอ Checkout Branch เดียวกันใน 2 Worktrees พร้อมกัน?
ข้อที่ 13: ในระบบ Dynamic Skill ที่เราสร้างในสัปดาห์ที่ 1 เราสามารถห่อหุ้ม `GitWorktreeSandbox` ไปเป็นอะไรได้?
ข้อที่ 14: หลังจากที่เราสร้าง Safe Sandbox ด้วย Git Worktree สำเร็จใน Day 22 แล้ว ใน Day 23 พรุ่งนี้เราจะก้าวไปสู่เรื่องใด?
ข้อที่ 15: ในฐานะสถาปนิกผู้ออกแบบระบบใน Day 22 คุณรู้สึกอย่างไรต่อการนำ Git Worktrees มาสร้างเป็น Sandbox?
🏁 สรุปหมุดเชื่อมโยง (Chapter Wrap-up)
เนื้อหาใน Day 22 — Safe Sandbox Execution with Git Worktrees ได้มอบเกราะคุ้มกันระดับ Enterprise ให้แก่ระบบของคุณ ช่วยให้ AI Agent สามารถแยกตัวไปแก้ไขโค้ด คอมไพล์ และรันเทสในโลกคู่ขนาน (Parallel Sandbox) ในเสี้ยววินาทีโดยไม่รบกวนหน้าจอ VS Code หรือกระทบงานหลักของคุณแม้แต่น้อย พร้อมก้าวเข้าสู่ Day 23: Autonomous Branching, Verification Loops & Auto-Rollback เพื่อวางระบบตรวจสอบอัตโนมัติแล้วครับ!