{"slug": "spec-driven-development-let-the-spec-drive-the-code-with-a-real-example", "title": "Spec-Driven Development: Let the Spec Drive the Code (With a Real Example)", "summary": "Sergio Colque Ponce, a software engineering student at Universidad Privada de Tacna, proposes Spec-Driven Development (SDD) as a methodology to improve AI coding agent accuracy by writing specifications before code. He demonstrates the approach with a URL shortener project using GitHub's Spec Kit and an OpenAPI contract, where tests validate the implementation against the spec automatically.", "body_md": "By\n\nSergio Colque Ponce— Software Engineering, Universidad Privada de Tacna.\n\nFull source code:[github.com/srg-cp/spec-driven-development]\n\nIf you have used an AI coding agent — Copilot, Claude Code, Gemini CLI — you have probably lived this moment: you describe a feature, the agent produces code that compiles and *looks* right, and then it quietly does the wrong thing. The agent is not weak; the **input** was ambiguous. We have been treating coding agents like search engines when they behave more like very literal pair programmers.\n\n**Spec-Driven Development (SDD)** is the answer to that problem: instead of jumping straight to code, you write down *what* you want and *why*, refine it, and only then let the implementation follow. The specification — not the code — becomes the center of the project.\n\nThe idea is old (anyone who has written a Product Requirements Document will recognize it), but it has become practical again thanks to tools like GitHub's open-source [Spec Kit](https://github.com/github/spec-kit). Spec Kit organizes the work into a small set of Markdown artifacts, each feeding the next:\n\nThe workflow is usually summarized as **Spec → Plan → Tasks → Implement**, and the same process is meant to work regardless of language, framework, or which of the 30+ supported agents you use.\n\nThe real shift is not \"more documents.\" It is this: when requirements change, you **update the spec, regenerate the plan, and let the implementation follow** — instead of patching code and hoping the intent survives. The spec is a *living* artifact, not a dusty Word file nobody opens.\n\nYou do not need Spec Kit to practice SDD. The underlying principle is simple and tool-agnostic:\n\nThe specification is the single source of truth. The code and the tests are derived from it — never the reverse.\n\nThe most powerful version of this is an **executable specification**: a machine-readable contract that your tests and CI can check the implementation against automatically. If the code drifts away from the spec, the build fails. That is what turns a spec from documentation into a guardrail.\n\nLet me show exactly that with a small, real project you can run yourself.\n\nWe want a `/shorten`\n\nendpoint: send a long URL, get back a short code. The SDD move is to **write the contract first**, before any logic. Here it is as an OpenAPI document (`spec/openapi.yaml`\n\n):\n\n```\ncomponents:\n  schemas:\n    ShortenRequest:\n      type: object\n      required: [url]\n      additionalProperties: false\n      properties:\n        url:\n          type: string\n          format: uri\n          minLength: 1\n    ShortenResponse:\n      type: object\n      required: [original_url, short_code]\n      additionalProperties: false\n      properties:\n        original_url:\n          type: string\n        short_code:\n          type: string\n          description: Exactly 7 lowercase hex characters.\n          pattern: '^[0-9a-f]{7}$'\n```\n\nNotice we already decided the *shape* of success: a response must contain `original_url`\n\nand a `short_code`\n\nof exactly seven hex characters. No code exists yet, but the rules are unambiguous.\n\nNow the code simply honors the contract. Its job is to satisfy `ShortenResponse`\n\n, not to invent its own format:\n\n``` python\nimport hashlib\n\nclass InvalidURLError(ValueError):\n    \"\"\"Raised when the input violates the ShortenRequest schema.\"\"\"\n\ndef shorten(url: str) -> dict:\n    if not isinstance(url, str) or not url:\n        raise InvalidURLError(\"url is required and must be a non-empty string\")\n    short_code = hashlib.sha256(url.encode(\"utf-8\")).hexdigest()[:7]\n    return {\"original_url\": url, \"short_code\": short_code}\n```\n\nThis is where SDD stops being a slogan. The tests **load the spec** and validate the implementation against it. The assertions are not hand-copied from the code — they come straight from the contract:\n\n``` python\nimport yaml, jsonschema\nfrom openapi_spec_validator import validate as validate_openapi\nfrom shortener import shorten, InvalidURLError\n\nSPEC = yaml.safe_load(open(\"spec/openapi.yaml\").read())\n\ndef schema(name):\n    return SPEC[\"components\"][\"schemas\"][name]\n\ndef test_spec_is_a_valid_openapi_document():\n    validate_openapi(SPEC)              # the contract itself must be valid\n\ndef test_response_conforms_to_the_spec():\n    result = shorten(\"https://upt.edu.pe/admision/2026\")\n    jsonschema.validate(instance=result, schema=schema(\"ShortenResponse\"))\n```\n\nIf someone later changes `shorten()`\n\nto return, say, an 8-character code, the `pattern`\n\nin the spec no longer matches and `test_response_conforms_to_the_spec`\n\nfails immediately. The spec is now *enforced*.\n\nA small GitHub Actions workflow validates the contract and runs the tests on every push. The spec is checked by a machine, on every change, forever:\n\n```\nname: CI\non: [push, pull_request]\njobs:\n  spec-and-tests:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v5\n        with:\n          python-version: '3.12'\n      - run: pip install -r requirements.txt\n      - run: python -c \"import yaml; from openapi_spec_validator import validate; validate(yaml.safe_load(open('spec/openapi.yaml')))\"\n      - run: pytest -v\n```\n\nRunning the suite locally is just as honest:\n\n```\ntests/test_contract.py::test_spec_is_a_valid_openapi_document PASSED\ntests/test_contract.py::test_response_conforms_to_the_spec PASSED\ntests/test_contract.py::test_short_code_matches_the_specified_pattern PASSED\ntests/test_contract.py::test_invalid_request_is_rejected PASSED\n```\n\nSpec-Driven Development shines on **greenfield** work (starting from zero, where it is tempting to just start typing), on features with **real consequences** where \"looks right\" is not good enough, and on any project handed to an AI agent that needs unambiguous intent rather than a vague prompt. It is overkill for a throwaway script — but for anything you will maintain, the spec pays for itself the first time a requirement changes.\n\nOne honest caveat: keep a **human in the loop**. SDD with AI does not mean blind trust. You still review the spec, the plan, and the generated code at the critical steps.\n\nSpec-Driven Development is less about a specific tool and more about reversing the usual order: decide *what* is correct, write it down where machines can check it, and let the code and tests follow. Whether you adopt the full Spec → Plan → Tasks → Implement workflow with Spec Kit, or just keep an OpenAPI contract that your CI enforces, the payoff is the same — your software does what you actually meant, and it keeps doing it after the next change.\n\nThe complete, runnable project is here: ** github.com/srg-cp/spec-driven-development**. Clone it, change the\n\n`short_code`\n\npattern in the spec, run the tests, and watch the contract catch you.Thanks for reading!", "url": "https://wpnews.pro/news/spec-driven-development-let-the-spec-drive-the-code-with-a-real-example", "canonical_source": "https://dev.to/sergiocolqueponce/spec-driven-development-let-the-spec-drive-the-code-with-a-real-example-589n", "published_at": "2026-06-17 18:26:46+00:00", "updated_at": "2026-06-17 18:51:43.339306+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "ai-agents", "large-language-models", "mlops"], "entities": ["Sergio Colque Ponce", "Universidad Privada de Tacna", "GitHub", "Spec Kit", "Copilot", "Claude Code", "Gemini CLI", "OpenAPI"], "alternates": {"html": "https://wpnews.pro/news/spec-driven-development-let-the-spec-drive-the-code-with-a-real-example", "markdown": "https://wpnews.pro/news/spec-driven-development-let-the-spec-drive-the-code-with-a-real-example.md", "text": "https://wpnews.pro/news/spec-driven-development-let-the-spec-drive-the-code-with-a-real-example.txt", "jsonld": "https://wpnews.pro/news/spec-driven-development-let-the-spec-drive-the-code-with-a-real-example.jsonld"}}