一键导入
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 页面并帮你完成安装。
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」一致性。過濾假警報後輸出報告,大幅減少人工介入時間。
基于 SOC 职业分类
| 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 幻覺發生率