Building SDD for Real Production Systems (SDD Part 2/2)
Read Part 1 for an overview of why AI-assisted engineering requires robust specifications and how SDD transformed our workflow at Normal.
In Part 1, we introduced spec-driven development (SDD) as Normal's approach to the AI context problem: automatically generating specifications that document system architecture, feature behavior, and invariants. The value proposition is clear: lower barriers to contribution, higher quality AI-generated code, and better alignment between PMs and engineers.
But implementing SDD inside a real, production-grade system turns out to be non-trivial. The challenge isn’t the concept. It is closing the gap between clean SDD principles and the constraints of a mature, multi-repo enterprise architecture.
The Github Spec Kit Experiment
GitHub’s open-source Spec Kit, originally developed for Copilot Workspace, offers promising foundations: structured templates, automation workflows, and a repeatable process for generating specs. In a greenfield environment, Spec Kit works extremely well.
But Normal’s architecture is far from greenfield. Our platform spans multiple tightly coupled repos, shared infrastructure, cross-service contracts, and on-premise deployments. As soon as we tested Spec Kit against our environment, four critical limitations surfaced:
- Single-repo assumptions: Spec Kit expects one workspace, but our system contains several repos. An SDD tool that only sees one cannot infer system-wide constraints.
- Schema-generative approach: Spec Kit encourages AI to design schemas. Ours are bound to production data and migration history and cannot be regenerated or abstracted away.
- Product-heavy specs missing technical boundaries: Spec Kit captures functional requirements but omits architectural invariants, tenancy rules, and integration constraints that AI must respect.
- Cloud-first assumptions: Spec Kit assumes standardized cloud patterns. Normal supports on-prem deployments, custom OIDC, and air-gapped environments.
Spec Kit’s principles fit, but its assumptions don’t.
To make SDD work in our environment, we extend Spec Kit’s ideas along three dimensions:
- Multi-repo, system-wide context: treat specifications as a first-class artifact that spans all services, not just a single repo.
- Hybrid specs: encode both product intent and technical invariants in every specification.
- Integrated workflow: wire SDD into Claude, GitHub, and Linear so specs are part of the entire development lifecycle.
The rest of this post walks through each dimension.
Multi-repo, system-wide context
We create a dedicated eda-sdd repository — the single source of truth for all specifications.
eda-sdd/
├── specs/ # Individual feature specs
├── full-spec/ # Complete system documentation
├── src/
│ ├── scripts/ # Minimal automation (branch mgmt, spec creation)
│ ├── templates/ # Flexible spec templates
│ └── memory/ # Platform knowledge base
│ └── constitution.md # System constraints & standards
└── .claude/ # Claude Code integration
├── commands/ # /specify, /merge workflows
└── skills/ # repo-collector, repo-setup
The constitution is the foundation of SDD. It defines system-level invariants, including:
- Service architecture
- Tech stack standards (Python, Node.js, PostgreSQL)
- Storage and security requirements (S3, secret-management policies)
- Quality gates (linting, typing, test coverage)
We also developed custom Claude skills to automate distributed environment setup. One skill clones and indexes all repos, while another orchestrates Docker Compose, installs dependencies, and performs health checks.
This global context gives AI the same system-level onboarding a human engineer receives on day one.
Hybrid Specs
Once the world model is in place, a PM or engineer provides a natural-language description of the feature:
/specify when user is in the testplan view and searches, highlight the query in the details view
Claude generates a structured spec:
- FR-001: System MUST highlight all instances of search query
within testplan details view
- FR-006: System MUST perform case-insensitive matching
- FR-008: System MUST limit scope to div with testid
"test-case-details"
The spec template rules enforce rigor. Every requirement must be verifiable ("System MUST..."), and ambiguities are annotated with [NEEDS CLARIFICATION: ...] to encourage human resolution before code generation.
Once finalized, the feature spec is integrated into the global full-spec/ directory:
/merge 002-highlight-search-keywords
This updates the authoritative, automatically maintained specification of the entire system. This becomes the context AI references to ensure new features don’t regress on existing behavior.
Integrated Workflow
With complete context — product intent, system boundaries, and invariants — Claude Code can safely assist with implementation while respecting architectural constraints.
Two MCP integrations close the loop:
- Linear MCP: reads issues, updates statuses, links specs
- GitHub MCP: reads PRs, manages branches, ties work to code changes
SDD becomes a full lifecycle system: planning → specification → implementation → review → merge.
Zooming out
SDD is the foundation that makes AI-assisted development real for production-grade software. At Normal, this workflow lowers the barriers to contribution, improves the quality of AI-generated code, and strengthens overall system resilience. As more features move through the workflow, our spec coverage compounds, making the platform progressively easier to evolve and maintain.
Building a custom SDD system isn’t about producing another dev-tool prototype. It is about making SDD practical for complex enterprise environments. Production-grade SDD requires multi-repo system context, hybrid specifications that capture both product intent and technical boundaries, and a workflow that continuously maintains the system’s source-of-truth knowledge base. As that corpus grows, the system becomes easier to evolve and far harder to break. Each new spec expands the semantic footing for the next, and each clarified invariant reduces the surface area for regressions. This is why SDD matters in production environments: it gives AI the context it needs to operate safely, autonomously, and at scale.