As AI-Assisted Programming becomes increasingly prevalent, the core challenge developers face has shifted from “how to write code” to “how to collaborate with AI to achieve deterministic outcomes.” The traditional development model is Requirements -> Human -> Code, while the new paradigm is evolving into Intent -> Spec (OpenSpec) -> AI -> Code & Verification.
This article uses the construction of a small e-commerce system — from scratch to production-grade evolution — as a case study for an in-depth retrospective of the full AI-collaborative development workflow based on OpenSpec. We will demonstrate how OpenSpec serves as a “universal language between humans and machines,” running through every stage of architectural design, system implementation, test verification, and iterative evolution, ensuring that AI-generated code is controllable, trustworthy, and maintainable.
User Input:
/opsx:propose“Build a small e-commerce website MVP with core capabilities for products, cart, orders, and payments.”
AI Thinking and Actions:
At this stage, the AI does not rush to write concrete code. Instead, it first performs domain modeling and spec definition. This is the core of the OpenSpec methodology — think it through first, then act.
openspec/changes/v1-mvp/, generates proposal.md, design.md, specs/, and tasks.md, clearly defining domain boundaries, SLO metrics, and API contracts, including:
POST /api/orders), error code conventions (OUT_OF_STOCK), and non-functional metrics (p99 < 100ms).Value Analysis:
User Input:
/opsx:apply“Please implement the code according to the spec.”
AI Actions:
Based on the confirmed Spec, the AI generated the complete code structure under examples/ecommerce-mini.
Value Analysis:
User Input: (AI proactive action) Verify that the generated code meets expectations.
AI Actions:
The AI not only generates functional code, but also generates companion test scripts to verify that the code behavior meets expectations.
Value Analysis:
User Input:
/opsx:propose“Extend this example to a production-grade implementation (persistence, authentication, idempotency, and observability)…”
AI Actions:
This is the most impressive part of AI-collaborative development — incremental evolution. The AI did not tear everything down and rewrite; instead, it extended the existing Spec architecture.
Bearer Token authentication middleware in server.prod.js (simplified implementation; full HMAC signing logic can be extended here).Idempotency-Key request header parsing entry point in the interface layer (stub; full deduplication logic can be connected to Redis or an in-memory cache).Value Analysis:
Through the case study above, we can summarize three key roles OpenSpec plays in AI software engineering:
In long conversations or cross-session development, AI tends to lose context. The OpenSpec documentation system acts as an external memory:
openspec/config.yaml (since v1.0.0): Project-level persistent context — technology stack, architectural constraints, rules, and other information are automatically injected into every AI planning request, so the AI doesn’t need to re-enter the project background each time. For example, this project’s config.yaml declares:
context: |
Project: ecommerce-mini - A minimal e-commerce system demonstrating OpenSpec Spec-Driven Development.
Architecture: Layered (HTTP -> Service -> Domain -> Repository), single-process monolith.
Storage: In-memory Map (dev), file-based JSON persistence (prod, Node.js only).
rules:
specs:
- Use Given/When/Then (Gherkin) format for all Scenarios
- Every Requirement must include Priority (P0/P1/P2) and Rationale
When the AI executes /opsx:apply, this information is automatically injected, ensuring the generated code conforms to the preset constraints.
Change Documents (Proposal/Design/Spec): The intent, technical approach, and behavioral definitions for individual changes. When the user requests “add persistence,” the AI doesn’t need to re-analyze “what is an order” — it directly references the existing Spec to extend.
AI-generated code often has randomness. The interface contracts (Schema) defined by OpenSpec constrain the AI’s output space. In the case study, regardless of how the backend implementation changes (in-memory vs. file), the JSON structure of the HTTP interface remains consistent, ensuring client compatibility.
One of OpenSpec’s core values is Language Agnostic. To verify this, we documented a complete experiment: using the exact same Spec files as the Node.js version to drive AI in generating a brand-new Python implementation from scratch (based on FastAPI + Pydantic).
ecommerce-mini.openspec/ directory.Interaction Intent: Generate Python data classes based on domain-model/spec.md, ensuring type definitions are consistent with the Spec.
User Prompt:
Please read domain-model/spec.md. Based on this Spec, please define Domain Models using Python’s Pydantic library. Requirements:
- File path: src/domain/models.py
- Strictly follow the field types and constraints in the Spec (e.g., non-negative).
- No business logic — only define data structures.
AI Response (code snippet):
# src/domain/models.py
from pydantic import BaseModel, Field
from typing import List, Literal
class Product(BaseModel):
id: str
name: str
# Corresponds to Spec: Requirement "Product entity definition"
# Use Field(..., ge=0) to enforce non-negative constraint
price_cents: int = Field(..., ge=0, alias="priceCents")
stock: int = Field(..., ge=0)
class CartItem(BaseModel):
id: str
product_id: str = Field(..., alias="productId")
# Corresponds to Spec: Requirement "Cart quantity limit" - quantity <= 99
quantity: int = Field(..., gt=0, le=99)
class OrderItem(BaseModel):
product_id: str = Field(..., alias="productId")
# Corresponds to Spec: Requirement "Order item definition" - records unit price and quantity at time of order
price_cents: int = Field(..., alias="priceCents")
quantity: int
class Order(BaseModel):
id: str
# Corresponds to Spec: Requirement "Order entity definition" - status can only be PENDING_PAYMENT or PAID
status: Literal["PENDING_PAYMENT", "PAID"]
total_cents: int = Field(..., ge=0, alias="totalCents")
items: List[OrderItem]
Note: alias is used to decouple Python naming conventions (snake_case) from the API contract (camelCase), ensuring internal/external consistency.
Interaction Intent: Implement core business rules, such as inventory deduction and order creation.
User Prompt:
Based on src/domain/models.py and design.md, please implement the Service layer. Include three services:
CatalogService: Handles inventory deduction (atomicity simulation).CartService: Handles cart item add/remove.OrderService: Orchestrates the order placement flow (check cart -> deduct stock -> create order -> clear cart). A simpleMemoryReposhould be implemented for data storage.
AI Response (code snippet):
# src/services/order.py
class OrderService:
def create_order(self, user_id: str) -> Order:
# 1. Get cart
cart = self.cart_svc.get_cart(user_id)
if not cart.items:
raise ValueError("CART_EMPTY")
order_items = []
total_cents = 0
# 2. Validate and deduct stock (Stock Check Rule)
for item in cart.items:
product = self.catalog.get_product(item.product_id)
if product.stock < item.quantity:
raise ValueError("OUT_OF_STOCK")
# Execute deduction
self.catalog.deduct_stock(product.id, item.quantity)
# Build order item
order_items.append(OrderItem(
productId=product.id,
priceCents=product.price_cents,
quantity=item.quantity
))
total_cents += product.price_cents * item.quantity
# 3. Create order and clear cart
order = Order(
id=f"order_{uuid.uuid4().hex[:8]}",
status="PENDING_PAYMENT",
totalCents=total_cents,
items=order_items
)
self.repo.save(order.id, order)
self.cart_svc.clear_cart(user_id)
return order
Interaction Intent: Expose business logic as a RESTful API and handle error code mapping.
User Prompt:
Based on
src/services/and capability specs such asspecs/catalog-management/spec.mdandspecs/order-management/spec.md, please implement the web interface using FastAPI. Requirements:
- Map all routes defined in the Spec.
- Handle error code mapping (e.g., return 409 for insufficient stock).
- Initialize test data on startup.
AI Response (code snippet):
# src/api/server.py
@app.post("/api/orders", status_code=201)
def create_order(req: CreateOrderRequest):
try:
order = order_svc.create_order(req.userId)
return order
except ValueError as e:
# Spec requirement: distinguish error types via exception message string
if str(e) == "OUT_OF_STOCK":
# Spec requirement: return 409 Conflict for insufficient stock
raise HTTPException(status_code=409, detail="Out of stock")
# Spec requirement: return 400 Bad Request for empty cart
raise HTTPException(status_code=400, detail=str(e))
Note: String comparison is used here for example brevity; in production it is recommended to define custom exception classes such as OutOfStockError for clearer error semantics and maintainability.
Interaction Intent: Write automated tests to verify that the implementation matches the behavior defined by the Spec.
User Prompt:
Please write tests/test_smoke.py, simulating user behavior using
pytest. Test scenarios:
- Normal order flow: add to cart -> place order -> verify inventory.
- Error scenario: place order when stock is insufficient, expecting a 409 response.
AI Response (code snippet):
# tests/test_smoke.py
def test_out_of_stock():
user_id = "user_2"
# Add product with stock of 5
res = client.post("/api/products", json={
"name": "Limited Item",
"priceCents": 200,
"stock": 5
})
pid = res.json()["id"]
# Attempt to purchase 6 (only 5 in stock)
client.post("/api/cart/items", json={
"userId": user_id,
"productId": pid,
"quantity": 6
})
# Verify that 409 is returned
# This proves the system correctly enforces business rule boundaries
resp = client.post("/api/orders", json={"userId": user_id})
assert resp.status_code == 409
assert "out of stock" in resp.json()["detail"].lower()
Execution Result:
$ pytest examples/ecommerce-mini-python/tests/test_smoke.py
...
examples/ecommerce-mini-python/tests/test_smoke.py .. [100%]
==================== 2 passed in 0.35s ====================
This confirms that the Python implementation fully conforms to the behavioral expectations defined by the Spec.
This case study demonstrates that AI development based on OpenSpec is not simply “prompt engineering” — it is a rigorous engineering methodology. Through:
it achieves a smooth evolution from “toy demo” to “production-grade system.” In future software development, mastering this Spec-Driven AI Collaboration pattern will be a core competency for every engineer.
Quick Navigation: Want to know CLI command details? -> OpenSpec User Manual Want to see how specs become code? -> Practical Guide Want to review the AI collaboration process? -> This document
examples/openspec/config.yaml (tech stack, architectural constraints, and rules, auto-injected into every AI planning request)examples/openspec/changes/v1-mvp/
proposal.md: Change proposaldesign.md: Architectural designspecs/catalog-management/spec.md: Catalog management specspecs/cart-management/spec.md: Cart management specspecs/order-management/spec.md: Order management specspecs/payment/spec.md: Payment specspecs/domain-model/spec.md: Domain model specspecs/error-handling/spec.md: Error handling specexamples/ecommerce-mini/src/{domain,repo,services,http}examples/ecommerce-mini-python/src/{domain,services,api}examples/ecommerce-mini/__tests__/ and examples/ecommerce-mini-python/tests/