بنقرة واحدة
enforce-contract
單元測試與代碼提交前觸發。掃描並驗證方法的 pre-conditions、post-conditions 與 invariants,透過契約式設計減少 AI 幻覺。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
單元測試與代碼提交前觸發。掃描並驗證方法的 pre-conditions、post-conditions 與 invariants,透過契約式設計減少 AI 幻覺。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Automated code review that checks code quality, Clean Architecture compliance, DDD patterns, coding standards, and spec traceability.
從規格目錄的 acceptance.yaml 生成/維護 BDD/ezSpec 測試。使用類似 Gherkin 語法,AI 自動產生 step definition(開發人員不需要手寫),驗收測試規格即為 Executable Specification。
在單元測試通過後觸發。透過引入人工錯誤(Mutants)來「測試你的測試」,確保測試案例具有足夠的錯誤偵測能力,建立對驗證機制的信任(Trust the Verification)。
驗證規格檔案的完整性與一致性,確保所有必要的規格元素都已定義且符合標準格式。
Replace with description of the skill and when Claude should use it.
協調多個 AI 模型(ChatGPT、Gemini、Codex、QWEN、Claude)進行三角驗證,確保「Specification == Program == Test」一致性。過濾假警報後輸出報告,大幅減少人工介入時間。
| name | enforce-contract |
| description | 單元測試與代碼提交前觸發。掃描並驗證方法的 pre-conditions、post-conditions 與 invariants,透過契約式設計減少 AI 幻覺。 |
analyze-frame 產出的規格時透過 Design by Contract 明確定義每個方法的邊界條件,極大化減少 AI 幻覺。
/**
* 建立新訂單
*
* @param input 建立訂單的輸入參數
* @return 建立成功的訂單資訊
*
* @pre input != null
* @pre input.getCustomerId() != null
* @pre input.getItems() != null && !input.getItems().isEmpty()
* @pre 所有 items 的 quantity > 0
* @pre 所有 items 的 productId 對應的商品存在
*
* @post result != null
* @post result.getOrderId() != null
* @post result.getStatus() == OrderStatus.CREATED
* @post 訂單已持久化到資料庫
* @post OrderCreatedEvent 已發布
*
* @throws CustomerNotFoundException 當 customerId 對應的客戶不存在
* @throws ProductNotFoundException 當 productId 對應的商品不存在
* @throws InsufficientInventoryException 當庫存不足
*/
public Output execute(Input input) {
// 實作
}
public Output execute(Input input) {
// ===== Pre-conditions =====
Objects.requireNonNull(input, "input must not be null");
Objects.requireNonNull(input.getCustomerId(), "customerId must not be null");
if (input.getItems() == null || input.getItems().isEmpty()) {
throw new IllegalArgumentException("items must not be empty");
}
for (OrderItemRequest item : input.getItems()) {
if (item.getQuantity() <= 0) {
throw new IllegalArgumentException(
"quantity must be positive, got: " + item.getQuantity()
);
}
}
// ===== 主要邏輯 =====
// ...
// ===== Post-conditions (assert in development) =====
assert result != null : "result must not be null";
assert result.getOrderId() != null : "orderId must not be null";
return result;
}
public class Order {
private OrderId id;
private CustomerId customerId;
private List<OrderItem> items;
private OrderStatus status;
private Money totalAmount;
/**
* Order 的不變量:
* @invariant id != null
* @invariant customerId != null
* @invariant items != null && !items.isEmpty()
* @invariant totalAmount != null && totalAmount.isPositive()
* @invariant status != null
* @invariant 當 status == CANCELLED 時,不能再修改訂單內容
*/
// 建構子必須建立有效狀態
public Order(OrderId id, CustomerId customerId, List<OrderItem> items) {
// Pre-conditions
Objects.requireNonNull(id, "id must not be null");
Objects.requireNonNull(customerId, "customerId must not be null");
if (items == null || items.isEmpty()) {
throw new IllegalArgumentException("items must not be empty");
}
this.id = id;
this.customerId = customerId;
this.items = new ArrayList<>(items);
this.status = OrderStatus.CREATED;
this.totalAmount = calculateTotal();
// 驗證 invariants
assertInvariants();
}
public void addItem(OrderItem item) {
// Pre-conditions
Objects.requireNonNull(item, "item must not be null");
if (this.status == OrderStatus.CANCELLED) {
throw new IllegalStateException("Cannot modify cancelled order");
}
// 執行變更
this.items.add(item);
this.totalAmount = calculateTotal();
// Post-conditions & Invariants
assertInvariants();
}
public void cancel() {
// Pre-conditions
if (this.status == OrderStatus.SHIPPED) {
throw new IllegalStateException("Cannot cancel shipped order");
}
// 執行變更
this.status = OrderStatus.CANCELLED;
// Invariants
assertInvariants();
}
private void assertInvariants() {
assert id != null : "Invariant violated: id is null";
assert customerId != null : "Invariant violated: customerId is null";
assert items != null && !items.isEmpty() : "Invariant violated: items is empty";
assert totalAmount != null && totalAmount.isPositive() :
"Invariant violated: totalAmount is invalid";
assert status != null : "Invariant violated: status is null";
}
}
| 項目 | 描述 | 嚴重度 |
|---|---|---|
| Null Check | 所有物件參數是否有 null 檢查 | 🔴 嚴重 |
| Empty Collection | 集合參數是否檢查 empty | 🟡 中度 |
| Positive Numbers | 數量、金額等是否檢查正數 | 🟡 中度 |
| Valid State | 狀態轉換是否合法 | 🔴 嚴重 |
| Return Value | 回傳值是否可能為 null | 🟡 中度 |
contract_rules:
pre_conditions:
- rule: null_check_for_objects
description: "物件型別參數必須有 null 檢查"
pattern: "public.*\\(.*[A-Z]\\w+\\s+\\w+"
check: "Objects.requireNonNull|!= null"
- rule: empty_check_for_collections
description: "集合型別必須檢查是否為空"
applies_to: ["List", "Set", "Collection"]
check: "isEmpty()|!.*\\.isEmpty()"
- rule: positive_check_for_quantities
description: "數量類型必須檢查大於零"
applies_to: ["quantity", "amount", "count", "size"]
check: "> 0|>= 1|isPositive"
post_conditions:
- rule: non_null_return
description: "標註 @NonNull 的回傳值必須確保不為 null"
- rule: state_consistency
description: "狀態變更後 invariants 必須成立"
invariants:
- rule: aggregate_validity
description: "Aggregate 必須定義 assertInvariants() 方法"
applies_to: "Aggregate"
class CreateOrderUseCaseTest {
// ===== Pre-condition 測試 =====
@Test
@DisplayName("當 input 為 null 時,應拋出 NullPointerException")
void should_throw_when_input_is_null() {
// Given
CreateOrderUseCase useCase = createUseCase();
// When & Then
assertThrows(NullPointerException.class, () -> {
useCase.execute(null);
});
}
@Test
@DisplayName("當 items 為空時,應拋出 IllegalArgumentException")
void should_throw_when_items_is_empty() {
// Given
Input input = new Input(customerId, Collections.emptyList(), address);
// When & Then
assertThrows(IllegalArgumentException.class, () -> {
useCase.execute(input);
});
}
// ===== Post-condition 測試 =====
@Test
@DisplayName("成功建立訂單後,應回傳有效的 OrderId")
void should_return_valid_orderId_on_success() {
// Given
Input input = createValidInput();
// When
Output output = useCase.execute(input);
// Then - 驗證 post-conditions
assertNotNull(output);
assertNotNull(output.getOrderId());
assertEquals(OrderStatus.CREATED, output.getStatus());
}
@Test
@DisplayName("成功建立訂單後,應發布 OrderCreatedEvent")
void should_publish_event_on_success() {
// Given
Input input = createValidInput();
// When
useCase.execute(input);
// Then - 驗證 post-condition
verify(eventPublisher).publish(any(OrderCreatedEvent.class));
}
}
透過契約式設計,可以有效減少 AI 幻覺:
契約完整度 ∝ 1 / AI 幻覺發生率