The "Where & Why": รวมพลัง Phase 1-3 สู่ Enterprise-Grade Polyglot Capstone Package
ความท้าทายของ Capstone: ชิ้นส่วนที่กระจัดกระจายเหล่านี้ต้องถูกเชื่อมร้อยเป็น Production-Ready Unified Package เดียวกันที่ทำงานประสานกัน 100% โดยไม่มีข้อขัดแย้งของ Interface สัญญาณ หรือขอบเขต Token Budget
เป้าหมายของ Day 10: ประกอบร่าง Polyglot Backend Unit Test Skill (Spring Boot 3.x / Kotlin / Coroutines / MockK / Maven) ที่สมบูรณ์แบบที่สุด พร้อม Pre-flight Pipeline, Closed-Loop Remediation, Dynamic Slicing และ Zero-Dependency Execution พร้อมส่งมอบสู่ Production จริง
┌──────────────────────────────────────────────────────────────────────────────────┐
│ HOST AGENT INVOCATION (GitHub Copilot / Cursor / Claude Code) │
│ Target Task: "Write pure unit tests for SettlementReconciliationService.kt" │
└────────────────────────────────────────┬─────────────────────────────────────────┘
│
▼ (Phase 1: Dual-Barrier Semantic Gate)
┌──────────────────────────────────────────────────────────────────────────────────┐
│ 🎯 SKILL.MD FRONTMATTER ROUTER [DAY 1-3] │
│ Match Intent: Similarity > 0.85 • Negative Guard: DB & E2E Pruned │
└────────────────────────────────────────┬─────────────────────────────────────────┘
│
▼ (Phase 2 & 3: Pre-flight Dynamic Harvest)
┌──────────────────────────────────────────────────────────────────────────────────┐
│ 🎯 AUTOMATED PRE-FLIGHT PIPELINE │
│ 1. scripts/extract-target-ast.py ──► Slices Constructor dependencies & suspend │
│ 2. scripts/harvest-exemplars.py ──► Mines Top-1 Golden Test from local repo │
│ 3. scripts/query-reference.sh ──► Hydrates canonical DTOs on demand (< 95tok)│
└────────────────────────────────────────┬─────────────────────────────────────────┘
│
▼ (Code Synthesis with Invariants)
┌──────────────────────────────────────────────────────────────────────────────────┐
│ HOST GENERATES ISOLATED KOTLIN TEST SUITE │
│ AAA Structure • MockK & coEvery • AssertJ • Zero Spring ApplicationContext │
└────────────────────────────────────────┬─────────────────────────────────────────┘
│
▼ (Phase 2: Closed-Loop Verification Gate)
┌──────────────────────────────────────────────────────────────────────────────────┐
│ 🎯 SCRIPTS/RUN-UNIT-TESTS.SH │
│ - Stage 1: Fast-fail AST regex scan (Exit 2 if Mockito / @SpringBootTest) │
│ - Stage 2: Sandboxed Maven runner with 45s Timeout Guard (Exit 124) │
│ - Stage 3: Python triage noise reduction to Stderr (Exit 3=Compile, 4=Assert) │
└────────────────────────────────────────┬─────────────────────────────────────────┘
│
┌────────────────────────┴────────────────────────┐
▼ (Non-zero Exit Code) ▼ (Exit Code 0)
┌──────────────────────────────────────────────┐ ┌─────────────────────────────────┐
│ CLOSED-LOOP REPAIR LOOP (Max 3 Retries) │ │ 🏆 DELIVER CLEAN ARTIFACT │
│ Host reads triage stderr & corrects target │ │ 100% Deterministic Verification │
└──────────────────────────────────────────────┘ └─────────────────────────────────┘
Cohesive Lifecycle
ร้อยเรียง AST Analysis, Dynamic Exemplar Mining และ Sandbox Execution ให้เป็น Workflow ที่ราบรื่นและเชื่อถือได้ 100%
Multi-Tier Defense
ผสานทั้ง In-Context RFC 2119 Invariants และ Fast-Fail Bash Regex Linters ป้องกัน Anti-pattern รั่วไหลสู่ Git Repository
< 1,200 Token Working Footprint
แม้เป็น Enterprise Skill เต็มรูปแบบ แต่วิศวกรรม Slicing รักษาพื้นที่ Context Window ให้เหลือพื้นที่ให้ LLM คิดตรรกะสูงสุด
สถาปัตยกรรมระดับ Production: การประสานส่วนประกอบ (Component Cohesion) และ Execution Lifecycle
ในระบบ Enterprise Software ทั่วไป การมี Unit Component ที่ดีไม่ได้รับประกันว่าระบบจะทำงานร่วมกันได้อย่างราบรื่น หากขาด Interface Contract ที่ชัดเจน ในโลกของ Agent Skills การเชื่อมต่อระหว่าง Markdown Instructions, POSIX Shell Scripts, Python Parsers, และ JSON Schemas ต้องมีลำดับการส่งมอบข้อมูล (Handoff Sequence) ที่ชัดเจนและทนทานต่อสภาวะขัดข้อง (Fault-Tolerant)
| มิติสถาปัตยกรรม (Architectural Dimension) | Casual Prompting (Prompt ทั่วไป) | Single Script Runner (รันสคริปต์เดี่ยว) | Enterprise Capstone Package (Day 10) |
|---|---|---|---|
| Execution Determinism | Probabilistic: หวังว่าจะคอมไพล์ผ่าน | ปานกลาง: รันเทสต์ได้แต่ไม่รู้สาเหตุละเอียด | 100% Deterministic: ปิดลูป Triage 4 ระดับ |
| Repository Alignment | ต่ำ: ใช้ Standard Libs ทั่วไป | ปานกลาง: ต้องเขียนบอกใน Prompt ทุกรอบ | สูงสุด: ทำ Dynamic Mining ดึง Custom DSL สด |
| Constructor Precision | เดาสุ่ม (Blind Hallucination) | เดาสุ่มจนกว่าคอมไพเลอร์จะด่า | แม่นยำตั้งแต่รอบแรกผ่าน AST Inspection |
| Token Economy | แปรปรวน: บวมตามขนาดการแชท | พังทลาย: Maven Log 80KB กลืน Context | ควบคุมเคร่งครัด: Stderr < 350t, Slice < 250t |
ลำดับการทำงานที่เชื่อมต่อทุก Component ใน Day 1-9 ถูกจัดเรียงเป็น Three-Phase State Machine:
หากเกิดความผิดพลาดใน Phase 3 ตัว Agent จะไม่รีสตาร์ทกระบวนการใหม่ทั้งหมด แต่ใช้ Diagnostic Payload ที่ Triage Parser สกัดได้มาทำการแก้ไขเฉพาะจุดแบบ In-place Self-Correction
กฎเหล็กสำหรับ Enterprise Skill ที่ส่งมอบให้กับทีมพัฒนาขนาด 500+ คน:
- 1. POSIX & Pure Python: สคริปต์ทุกตัวใน
scripts/ต้องรันผ่าน Python 3 Standard Library หรือ Bash ดั้งเดิม ห้ามบังคับpip install - 2. Fail-Safe Temp Cleansing: ใช้คำสั่ง
trapทำลาย log ชั่วคราว ป้องกันปัญหา disk space รั่วไหลบน CI Runner - 3. Deterministic Exit Codes: แยกแยะ Environment Error (Exit 1) ออกจาก Invariant Violation (Exit 2) เพื่อความปลอดภัย
Complete Production Artifact: The Enterprise Unit Test Architect
ชุดโครงสร้างแพ็กเกจระดับ Production เต็มรูปแบบตามมาตรฐาน agentskills/agentskills ที่ประกอบร่างทุกส่วนประกอบอย่างสมบูรณ์แบบ
.github/skills/spring-boot-unit-tester/
├── SKILL.md ◄── [CAPSTONE MANIFEST: Fully Integrated Execution Protocol]
├── scripts/
│ ├── run-unit-tests.sh ◄── Sandbox Execution & Timeout Orchestrator
│ ├── triage-test-failure.py ◄── Stderr Diagnostic & Noise Stripping Parser
│ ├── extract-target-ast.py ◄── AST Constructor & Suspend Symbol Extractor
│ ├── harvest-exemplars.py ◄── Local Repo Golden Test Miner
│ └── query-reference.sh ◄── On-Demand Heavy Schema Slicer
└── references/
└── billing-domain-contracts.json ◄── Canonical DTO Fixture Schemas
---
name: spring-boot-unit-tester
schema-version: "1.0.0"
description: >
Generates and refactors isolated JVM unit tests for Kotlin and Spring Boot 3.x
using JUnit 5, MockK, AssertJ, and Coroutines Test.
USE WHEN:
- Authoring unit tests for @Service, @Component, or Domain Logic classes.
- Mocking suspend functions using MockK (`coEvery { ... }`, `runTest`).
- Diagnosing failed Maven unit test runs.
DO NOT USE WHEN:
- Testing database interactions requiring Testcontainers, Postgres, or H2.
- Writing integration tests annotated with @SpringBootTest or @DataJpaTest.
- Writing frontend or end-to-end Cypress/Playwright tests.
tools:
- name: extract-target-ast
description: Extracts concise AST skeleton (constructor dependencies and suspend methods) from target source file.
file: scripts/extract-target-ast.py
- name: harvest-exemplars
description: Dynamically harvests idiomatic golden unit test exemplars from the local repository.
file: scripts/harvest-exemplars.py
- name: query-reference
description: Queries on-demand domain DTO schemas and fixtures from references/ directory.
file: scripts/query-reference.sh
- name: run-unit-tests
description: Runs sandboxed Maven test execution with automatic stderr triage and timeout guards.
file: scripts/run-unit-tests.sh
metadata:
domain: "backend-quality"
target-framework: "Spring Boot 3.x / Kotlin 1.9+"
---
# 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 NOT** use Reflection (`ReflectionTestUtils`). All dependencies MUST be injected via constructor.
- **MUST** execute strictly in-memory (< 50ms per method) without Spring ApplicationContext.
- **MUST** wrap all `suspend` methods inside `kotlinx.coroutines.test.runTest` using `coEvery` and `coVerify`.
- **MUST** follow explicit AAA phases marked with single-line comments: `// Arrange`, `// Act`, `// Assert`.
## 2. Sequential Execution Lifecycle
### Phase 1: Pre-flight Context Harvesting
Before writing any unit test code, the Host Agent MUST execute this sequential pre-flight:
1. **Extract AST Skeleton**: Run `python3 scripts/extract-target-ast.py <TARGET_FILE>` to harvest constructor dependencies.
2. **Mine Repo Exemplar**: Run `python3 scripts/harvest-exemplars.py <TARGET_FILE>` to identify local assertion DSLs.
3. **Query References (Conditional)**: If target uses complex DTOs, query `scripts/query-reference.sh`.
### Phase 2: Test Scaffolding
- Instantiate dependencies using `private val dep = mockk<Dep>()`.
- Implement clean Arrange-Act-Assert testing structure adhering to mined exemplar conventions.
### Phase 3: Sandboxed Verification & Remediation
1. Trigger validation runner: `bash scripts/run-unit-tests.sh <TARGET_TEST_FILE>`.
2. Inspect exit code:
- **Exit 0**: Complete. Return test code to user.
- **Exit 2**: Invariant failure. Purge Mockito or Spring runner immediately.
- **Exit 3**: Compilation error. Parse line number and type mismatch from stderr.
- **Exit 4**: Assertion error. Adjust mock stubs or expected values.
- **Exit 124**: Execution timeout. Purge blocking operations or heavy context loaders.
3. Max Retries: Limit autonomous self-correction loop to 3 iterations.
#!/usr/bin/env bash
# ==============================================================================
# scripts/run-unit-tests.sh
# Standard: agentskills Standard v1.0 (Phase 3 Capstone Release)
# Complete Orchestrator: Fast-Fail Static Linter, 45s Timeout Sandbox & Triage
# ==============================================================================
set -euo pipefail
TARGET_FILE="${1:-}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TRIAGE_SCRIPT="${SCRIPT_DIR}/triage-test-failure.py"
LOG_FILE=$(mktemp /tmp/capstone_mvn.XXXXXX.log)
# Safe Cleanup Hook
trap 'rm -f "${LOG_FILE}"' EXIT
# 1. Parameter Verification
if [[ -z "${TARGET_FILE}" ]] || [[ ! -f "${TARGET_FILE}" ]]; then
echo "### 🚨 DETERMINISTIC TRIAGE REPORT" >&2
echo "- **Category**: \`ENVIRONMENT_ERROR\`" >&2
echo "- **Error**: Target test file '${TARGET_FILE}' does not exist or was not specified." >&2
exit 1
fi
CLASS_NAME=$(basename "${TARGET_FILE}" .kt)
# 2. Stage 1: Fast-Fail Negative Boundary Gate (< 50ms)
if grep -En "org\.mockito" "${TARGET_FILE}" >&2; then
echo "### 🚨 DETERMINISTIC TRIAGE REPORT" >&2
echo "- **Category**: \`STATIC_INVARIANT_VIOLATION\`" >&2
echo "- **Error**: Forbidden Mockito import detected. Pure unit tests MUST use io.mockk." >&2
exit 2
fi
if grep -En "@SpringBootTest|@DataJpaTest|@WebMvcTest" "${TARGET_FILE}" >&2; then
echo "### 🚨 DETERMINISTIC TRIAGE REPORT" >&2
echo "- **Category**: \`STATIC_INVARIANT_VIOLATION\`" >&2
echo "- **Error**: Spring ApplicationContext runner detected. Unit tests must execute in pure memory." >&2
exit 2
fi
# 3. Stage 2: Sandboxed Maven Execution with Timeout Guard (Max 45s)
set +e
timeout 45s mvn test -B --no-transfer-progress -Dtest="${CLASS_NAME}" > "${LOG_FILE}" 2>&1
BUILD_STATUS=$?
set -e
if [[ ${BUILD_STATUS} -eq 124 ]]; then
echo "### 🚨 DETERMINISTIC TRIAGE REPORT" >&2
echo "- **Category**: \`EXECUTION_TIMEOUT\`" >&2
echo "- **Error**: Test execution exceeded 45s limit. Potential deadlock or heavy context initialization." >&2
exit 124
elif [[ ${BUILD_STATUS} -ne 0 ]]; then
# Pipeline raw noisy log into Python triage parser and output strictly to stderr
python3 "${TRIAGE_SCRIPT}" "${LOG_FILE}"
if grep -q "Compilation failure" "${LOG_FILE}"; then
exit 3
else
exit 4
fi
fi
# 4. Success Path: Clean Structured JSON to stdout, zero stderr
echo "{\"status\": \"SUCCESS\", \"class\": \"${CLASS_NAME}\", \"verified\": true}"
exit 0
#!/usr/bin/env python3
"""
scripts/triage-test-failure.py
Extracts compiler and assertion failures from noisy build logs.
Emits a compact diagnostic markdown card strictly to stderr (< 350 tokens).
"""
import sys
import re
def parse_build_diagnostics(raw_log: str) -> dict:
diagnostics = {
"category": "BUILD_FAILURE",
"file": "Unknown",
"line": "0",
"message": "Unclassified build or test failure.",
"root_cause_snippet": []
}
lines = raw_log.splitlines()
kt_pattern = re.compile(r"\[ERROR\]\s+(/.+?\.kt):(\d+):(\d+):\s+error:\s+(.+)")
mockk_pattern = re.compile(r"io\.mockk\.MockKException:\s+(.+)")
assert_pattern = re.compile(r"org\.opentest4j\.AssertionFailedError:\s+(.+)")
for line in lines:
match_kt = kt_pattern.search(line)
if match_kt:
diagnostics["category"] = "COMPILATION_FAILURE"
diagnostics["file"] = match_kt.group(1).split("/")[-1]
diagnostics["line"] = match_kt.group(2)
diagnostics["message"] = match_kt.group(4)
diagnostics["root_cause_snippet"].append(line.strip())
return diagnostics
match_mockk = mockk_pattern.search(line)
if match_mockk:
diagnostics["category"] = "MOCKK_CONTRACT_VIOLATION"
diagnostics["message"] = match_mockk.group(1)
diagnostics["root_cause_snippet"].append(line.strip())
return diagnostics
match_assert = assert_pattern.search(line)
if match_assert:
diagnostics["category"] = "ASSERTION_FAILURE"
diagnostics["message"] = match_assert.group(1)
diagnostics["root_cause_snippet"].append(line.strip())
return diagnostics
error_tail = [l.strip() for l in lines if "[ERROR]" in l][-3:]
if error_tail:
diagnostics["root_cause_snippet"] = error_tail
return diagnostics
def format_agent_card(diag: dict) -> str:
return f"""### 🚨 DETERMINISTIC TRIAGE REPORT
- **Category**: `{diag['category']}`
- **Location**: `{diag['file']}:{diag['line']}`
- **Error**: {diag['message']}
- **Action Required**: Resolve the violation indicated above and re-execute runner.
```text
{chr(10).join(diag['root_cause_snippet'][:3])}
```"""
def main():
raw_input = open(sys.argv[1], "r", encoding="utf-8", errors="ignore").read() if len(sys.argv) > 1 else sys.stdin.read()
diag = parse_build_diagnostics(raw_input)
sys.stderr.write(format_agent_card(diag) + "\n")
if __name__ == "__main__":
main()
Capstone Enterprise Incident: The Triple-Failure Settlement Engine Refactor
สถานการณ์จริงระดับ Mission-Critical: ทีมวิศวกรรมการเงินมอบหมายให้ AI สร้าง Unit Test ให้กับ SettlementReconciliationService.kt คลาสนี้มี 3 Constructor Dependencies, เมธอดหลักเป็น suspend fun, รับ Nested Billing DTO ที่มี 40 ฟิลด์, และทีมมี Custom Assertion DSL ชื่อ assertThatSettlement(result).isFullyReconciled()
- Pre-flight Phase: สั่งรัน
extract-target-ast.pyเพื่อดึง Constructor Dependencies และharvest-exemplars.pyเพื่อดึง Custom Assertion จากคลาสพี่น้อง - On-Demand Reference: สั่งรัน
query-reference.shเพื่อสกัด Schema ของSettlementInstructionโดยไม่ทำให้ Context Window บวม - Verification & Triage: รัน
run-unit-tests.shเพื่อยืนยันว่าการทดสอบรันผ่านบน JVM Isolated Heap จริง (Exit Code 0) โดยไม่โหลด Spring ApplicationContext
package com.enterprise.trading.settlement
import com.enterprise.testing.assertions.assertThatSettlement
import io.mockk.*
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import java.math.BigDecimal
import java.util.UUID
class SettlementReconciliationServiceTest {
// 1. Dependencies harvested via extract-target-ast.py
private val clearingClient: ClearingGatewayClient = mockk()
private val ledgerRepo: SettlementLedgerRepository = mockk()
private val auditLogger: FinancialAuditLogger = mockk(relaxed = true)
private val service = SettlementReconciliationService(
clearingClient = clearingClient,
ledgerRepo = ledgerRepo,
auditLogger = auditLogger
)
@AfterEach
fun tearDown() {
confirmVerified(clearingClient, ledgerRepo)
}
@Test
fun `should successfully reconcile settlement batch and emit completed state`() = runTest {
// Arrange: Fixture created using on-demand schema from query-reference.sh
val instructionId = UUID.randomUUID()
val instruction = SettlementInstruction(
instructionId = instructionId.toString(),
accountNumber = "ACC-9988221100",
settlementAmount = BigDecimal("1250000.50"),
currency = "USD",
clearingRail = "SWIFT"
)
coEvery { clearingClient.verifyClearing(instructionId) } returns ClearingStatus.CLEARED
coEvery { ledgerRepo.updateReconciliationStatus(instructionId, any()) } returns true
// Act
val result = service.reconcile(instruction)
// Assert: Adheres to team Custom DSL mined via harvest-exemplars.py
assertThatSettlement(result).isFullyReconciled()
coVerify(exactly = 1) { clearingClient.verifyClearing(instructionId) }
coVerify(exactly = 1) { ledgerRepo.updateReconciliationStatus(instructionId, "RECONCILED") }
}
}
$ 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
ทดสอบสถาปัตยกรรม Enterprise Capstone Skill (Day 10)
ตอบคำถามเชิงสถาปัตยกรรมระดับ Capstone ทั้ง 12 ข้อด้านล่าง ระบบจะตรวจคำตอบและให้ Feedback ทันทีเมื่อคลิกเลือกช้อยส์ พร้อมแสดงคำอธิบายเชิงลึก