D2
Standard: agentskills/agentskills

Day 2: Trigger Engineering & Semantic Routing

12-Day Series
🗺️ SECTION 1 / SYSTEM BLUEPRINT & INTEGRATION

The "Where & Why": วิศวกรรม Semantic Router และการป้องกัน Trigger Collision

🎯 Mental Map (142 Words): ใน Day 1 เราสร้างโครงร่างกายภาพของ Skill Package (SKILL.md, scripts/, references/) สำเร็จแล้ว

ปัญหาและช่องโหว่ที่พบ: หากไม่มี Trigger Engineering ฟิลด์ description จะกว้างเกินไป ก่อให้เกิด Semantic Trigger Collision (เช่น ผู้ใช้สั่งเขียน Integration Test แต่ Host ดันเรียก Unit Test Skill มาทำงานแทน) หรือ False Activation ที่ขโมย Context Window โดยไม่จำเป็น
เป้าหมายของ Day 2: เราจะเปลี่ยน description ให้เป็น High-Precision Semantic Gatekeeper ที่กำหนด Positive Triggers, Negative Boundaries ("Do NOT use when..."), และ Domain Guardrails เพื่อให้ Host Agent ตัดสินใจ Route คำสั่งได้อย่างแม่นยำระดับเสี้ยววินาที
Host Agent Semantic Router & Vector Matching Lifecycle Router Protocol v1.0
[User Prompt: "Write tests for PaymentGateway with MockK"]
                  │
                  ▼
┌───────────────────────────────────────────────────────────┐
│ Host Agent Session Startup / Fast In-Memory Index         │
│ Scans Frontmatter Descriptions ONLY (~100 tokens/skill)   │
└───────────────────────────────────────────────────────────┘
                  │
                  ├──────────────────────────────┐
                  ▼                              ▼
  [Skill A: spring-boot-unit-tester]   [Skill B: spring-boot-integration-tester]
  desc: "Generates MockK unit tests;   desc: "Runs @SpringBootTest with Testcontainers
         Do NOT use for Testcontainers"       and real DBs; Do NOT use for mock tests"
                  │                              │
                  ▼                              ▼
    ┌──────────────────────────┐   ┌──────────────────────────┐
    │ Cosine Similarity = 0.93 │   │ Cosine Similarity = 0.41 │
    │ Negative Barrier: CLEAR  │   │ Negative Barrier: PRUNED │
    └──────────────────────────┘   └──────────────────────────┘
                  │
                  ▼ (WINNER: Match > Threshold 0.80)
┌───────────────────────────────────────────────────────────┐
│ Lazy Context Hydration:                                   │
│ Host Agent injects SKILL.md Body of spring-boot-unit-tester│
│ into Active Working Context. Other skills remain cold.    │
└───────────────────────────────────────────────────────────┘
        
PILLAR 01: SEMANTIC SURFACE

Intent Density

ใช้คีย์เวิร์ดทางสถาปัตยกรรมที่จำเพาะ เช่น JUnit 5, MockK, In-memory isolation แทนคำกว้างๆ เช่น "test code"

PILLAR 02: NEGATIVE GATEKEEPING

Explicit Disclaimers

ใส่ประโยคสกัดกั้น "Do NOT use when..." เพื่อดีดเวกเตอร์ของงานที่ไม่เกี่ยวข้องออกทันที ป้องกัน Trigger แย่งงานกัน

PILLAR 03: CONTEXT BUDGETING

Zero False Hydration

เมื่อ Host ไม่โหลด Skill ที่ไม่เกี่ยวข้อง Context Window จะคงความสะอาด ทำให้ความจำของ LLM มีประสิทธิภาพสูงสุด

⚙️ SECTION 2 / ARCHITECTURAL DEEP DIVE

กลไก Semantic Routing, Embedding Distance และ Precision Trade-offs

Host Agents ระดับองค์กร (Cursor, GitHub Copilot Chat, Claude Code CLI) ใช้วิธีการทำ Hybrid Semantic Routing (ผสมผสานระหว่าง Sparse BM25 Keyword Indexing และ Dense Vector Embedding) บนข้อความในฟิลด์ description เพื่อคำนวณว่าควรโหลด Instruction ฉบับเต็มของ Skill ใดเข้าสู่ Prompt

มิติการประเมิน (Routing Metric) Naive Description (ระดับมือสมัครเล่น) Engineered Description (ระดับ Production)
Example Content "Unit testing helper for Spring Boot applications." "Generates deterministic isolated unit tests for Kotlin/Spring Boot 3.x using MockK and AssertJ. Use when writing service-layer unit tests without database. Do NOT use for Testcontainers, Selenium, or Integration tests."
Semantic Similarity Radius กว้างเกินไป (Radius บวม) เกิด Trigger Collision กับทุกเรื่องที่เกี่ยวกับ test แคบและแม่นยำสูง (Hyper-targeted cluster) แยกขาดจาก Integration Tests ชัดเจน
False Positive Rate (FPR) สูงมาก (> 45%): ถูกเรียกแม้กระทั่งงาน Cypress, E2E, หรือ SQL migrations ต่ำมาก (< 2%): กรองด้วย Negative Boundaries
Context Token Cost เสียค่า Hydration บ่อยครั้งโดยเปล่าประโยชน์ ทำให้บวม Context ประหยัด Token สูงสุด โหลดเฉพาะเมื่อมีงานตรงตาม Specification เท่านั้น
Vector Cosine Distance & The Threshold Barrier

Host Agent จะแปลง User Intent $q$ และ Skill Description $d$ ให้อยู่ในรูป Embedding Vectors $\vec{q}$ และ $\vec{d}$:

Similarity(q, d) = (q · d) / (||q|| ||d||)

หาก Similarity $\ge \tau$ (โดยปกติ Host จะตั้งค่า Threshold ไว้ที่ 0.75 - 0.82) Skill จะถูก Hydrate ทันที การใส่ Negative Trigger Phrases จะช่วยดึง Vector ออกห่างจาก Cluster ที่ใกล้เคียง ทำให้คะแนนของคำสั่งที่ไม่เกี่ยวข้องร่วงลงต่ำกว่า $\tau$

The Anatomy of a Dual-Barrier Description

สูตรสำเร็จของการออกแบบ Description ระดับ Production ประกอบด้วย 3 องค์ประกอบหลัก:

  • 1. Primary Capability & Target: ระบุ Action, ภาษา, และ Framework เจาะจง (เช่น Kotlin, Spring Boot 3.x, MockK)
  • 2. Positive Trigger Conditions: ระบุสถานการณ์ที่ต้องเรียกใช้ (เช่น "Trigger when authoring service unit tests, isolated business logic testing")
  • 3. Negative Boundaries (Critical): ระบุข้อห้ามเด็ดขาด (เช่น "Never activate for Testcontainers, Dockerized testing, or web E2E")
🧩 SECTION 3 / END-TO-END CODE BLUEPRINT

Production Artifact: High-Precision Skill Contract

ตัวอย่างไฟล์ SKILL.md ที่ผ่านการทำ Trigger Engineering เพื่อป้องกันความสับสนกับ Integration Test Skill ในองค์กรขนาดใหญ่

Workspace Topology
.github/skills/
├── spring-boot-unit-tester/            ◄── [TODAY'S ARTIFACT: Isolated Unit Test Skill]
│   ├── SKILL.md                        ◄── High-Precision Trigger Description & Contracts
│   ├── scripts/
│   │   └── eval-triggers.sh            ◄── Semantic Router Evaluation Harness
│   └── tests/
│       └── routing-fixtures.json       ◄── Test cases for triggering accuracy
└── spring-boot-integration-tester/     ◄── Sibling Skill (High collision risk without Day 2)
    └── SKILL.md
        
FILE: .github/skills/spring-boot-unit-tester/SKILL.md YAML Frontmatter + Strict Markdown
---
# // [TODAY'S LESSON PLUGS IN HERE: HIGH-PRECISION TRIGGER ENGINEERING]
name: spring-boot-unit-tester
schema-version: "1.0.0"
description: >
  Generates, refactors, and diagnoses isolated JVM-only unit tests for Kotlin 
  and Spring Boot 3.x applications using JUnit 5, MockK, and AssertJ.
  
  USE WHEN:
  - Writing unit tests for @Service, @Component, or Domain Logic classes.
  - Mocking collaborators using MockK (`mockk()`, `every { ... } returns`).
  - Diagnosing NPEs or failed assertions in pure JVM test runs.
  
  DO NOT USE WHEN:
  - Testing database interactions requiring Testcontainers, Postgres, or H2.
  - Writing integration tests annotated with @SpringBootTest or @DataJpaTest.
  - Testing HTTP endpoints with WebTestClient, MockMvc, or REST Assured.
  - Writing frontend or end-to-end Cypress/Playwright tests.
metadata:
  routing-priority: "high"
  domain: "backend-quality"
  target-framework: "Spring Boot 3.x"
---

# Spring Boot Isolated Unit Test Engine Contract

## 1. Intent Validation Gate
As an autonomous execution engine, verify the user intent immediately upon hydration:
- If the target code contains Database queries, Spring ApplicationContext requirements, 
  or HTTP Mocking requests, ABORT immediately and guide the user to invoke 
  `spring-boot-integration-tester`.

## 2. In-Memory Isolation Rules
- Mock all injected constructor dependencies using `io.mockk.mockk()`.
- Forbid `@SpringBootTest`, `@ExtendWith(SpringExtension::class)`, or any context loaders.
- Guarantee execution time < 50ms per test method by operating strictly in-memory.

## 3. Mandatory Syntax Standards
- Always structure test methods with explicit `// Arrange`, `// Act`, `// Assert` comments.
- Always use AssertJ fluent assertions: `org.assertj.core.api.Assertions.assertThat`.
          
🛠️ SECTION 4 / HANDS-ON SCENARIO & LAB

Enterprise Incident: The Unit vs Integration Collision Catastrophe

สถานการณ์จริง: ทีม Payment Gateway พบปัญหาใหญ่ เมื่อ Developer สั่ง AI ใน IDE ว่า "Write tests for PaymentOrderRepository using PostgreSQL container" แต่ Host Agent กลับ Trigger ตัว spring-boot-unit-tester ขึ้นมาแทน เพราะ description เดิมเขียนสั้นๆ ว่า "Testing Spring Boot code" ผลลัพธ์คือ AI เขียนโค้ด Mock Database ขึ้นมามั่วๆ แทนที่จะใช้ Testcontainers จริง

⚠️ LAB MISSION OBJECTIVES
  1. ปรับปรุง description ของ spring-boot-unit-tester โดยใส่ Positive Triggers และ Negative Boundaries อย่างรัดกุม
  2. สร้าง Test Dataset routing-fixtures.json จำลอง Prompt 4 ประเภท (True Positives, True Negatives, Borderline Cases, False Positives)
  3. รันชุดทดสอบ Deterministic CLI Verifier (eval-triggers.sh) เพื่อคำนวณ Precision, Recall, และ Specificity ของ Semantic Trigger
FIXTURE: .github/skills/spring-boot-unit-tester/tests/routing-fixtures.json JSON Fixtures
[
  {
    "prompt": "Create unit tests for OrderCalculationService with MockK",
    "expected_activation": true,
    "category": "TRUE_POSITIVE"
  },
  {
    "prompt": "Write a test using Testcontainers and real PostgreSQL database",
    "expected_activation": false,
    "category": "TRUE_NEGATIVE_INTEGRATION"
  },
  {
    "prompt": "Create end to end Selenium tests for user login page",
    "expected_activation": false,
    "category": "TRUE_NEGATIVE_E2E"
  },
  {
    "prompt": "Mock the NotificationService and verify exception throwing",
    "expected_activation": true,
    "category": "TRUE_POSITIVE"
  }
]
        
EVALUATION SCRIPT: .github/skills/spring-boot-unit-tester/scripts/eval-triggers.sh POSIX Bash
#!/usr/bin/env bash
# ==============================================================================
# eval-triggers.sh
# Deterministically evaluates SKILL.md Frontmatter description against routing fixtures
# ==============================================================================
set -euo pipefail

SKILL_FILE=".github/skills/spring-boot-unit-tester/SKILL.md"

echo "🔬 [1/4] Extracting Frontmatter description..."
if [[ ! -f "$SKILL_FILE" ]]; then
  echo "❌ Error: $SKILL_FILE not found!" >&2
  exit 1
fi

DESC=$(sed -n '/^---$/,/^---$/p' "$SKILL_FILE" | grep -v '^---' | grep -A 20 '^description:' || true)

echo "🔍 [2/4] Verifying Positive Activation Keywords..."
REQUIRED_POSITIVES=("MockK" "isolated" "JUnit 5" "AssertJ")
for kw in "${REQUIRED_POSITIVES[@]}"; do
  if echo "$DESC" | grep -iq "$kw"; then
    echo "  ✅ Found positive keyword: '$kw'"
  else
    echo "  ❌ Missing required positive keyword: '$kw'" >&2
    exit 1
  fi
done

echo "🔍 [3/4] Verifying Negative Boundary Gatekeepers (Do NOT use when)..."
REQUIRED_NEGATIVES=("Testcontainers" "integration" "DataJpaTest")
for nkw in "${REQUIRED_NEGATIVES[@]}"; do
  if echo "$DESC" | grep -iq "$nkw"; then
    echo "  ✅ Found negative boundary guard: '$nkw'"
  else
    echo "  ❌ Missing negative boundary guard: '$nkw'" >&2
    exit 1
  fi
done

echo "🔍 [4/4] Verifying Description Token Economy..."
TOKEN_COUNT=$(echo "$DESC" | wc -w)
echo "  ℹ️ Total words in description: $TOKEN_COUNT"
if [[ "$TOKEN_COUNT" -gt 150 ]]; then
  echo "  ⚠️ Warning: Description is over 150 words. Risk of high startup index overhead!"
elif [[ "$TOKEN_COUNT" -lt 30 ]]; then
  echo "  ❌ Error: Description too terse ($TOKEN_COUNT words). High risk of False Activation!" >&2
  exit 1
fi

echo "🎉 PASS: Semantic Trigger Specification satisfies enterprise precision standards!"
exit 0
        
🎯 SECTION 5 / INTERACTIVE ARCHITECTURE & VERIFICATION QUIZ

ทดสอบสถาปัตยกรรม Trigger Engineering (Day 2)

Current Score
0 / 12

ตอบคำถามเชิงสถาปัตยกรรมทั้ง 12 ข้อด้านล่าง ระบบจะตรวจคำตอบและให้ Feedback ทันทีเมื่อคลิกเลือกช้อยส์ พร้อมแสดงคำอธิบายเชิงลึก