home
diamond Go Premium
Data Engineering Path  ·  Data & AI
AWS CORE PLATFORM CASE STUDY

Case Study, Part 4 of 5: Construction Phase

Where we are: Inception ended with a plan — one unit (synth-data-cli), one Bolt, walking skeleton = schema parsing + row generation + CSV export first. Construction now builds it, for real, in reviewable slices.

In plain English: Three quick terms this page uses a lot: a Unit is one buildable piece of the product (here, everything is small enough to be just one). A Bolt is one complete build-and-test pass over a unit. A walking skeleton is the smallest possible version that actually runs end to end — not the whole product, just enough of a "skeleton" to prove the core idea works, before fleshing out the rest.

Every prompt we actually type is highlighted like this.

Starting the first Bolt now: one build pass over the code, tests and
checks for synth-data-cli. First step is Functional Design.

Stage 3.1: Functional Design (architect agent)

Claude Code: Schema.from_yaml(path) parses and validates the schema, raising a clear error on an unknown type or malformed constraint. generate(schema, n) yields n Faker-backed rows matching each column's type and constraint. One exporter function per format, each taking the same row list. Approve

Stage 3.2: NFR Requirements (devsecops agent)

NFR = Non-Functional Requirement — a rule about how well the software behaves (how fast, how much memory, how safely it fails), as opposed to a functional requirement, which is about what it does. Rather than "no significant NFRs," this project actually has two worth naming:

Claude Code: Two non-functional requirements: (1) generating 100,000 rows must not exceed 500MB of memory — ruling out building the entire result as one giant in-memory structure before writing it out; (2) an invalid schema must fail before any file is written, not partway through. Written to nfr-requirements.md. Approve

Stage 3.3: NFR Design (architect agent)

Claude Code: Answering both: rows generate as a Python generator, consumed by each exporter in batches of 1,000 rather than materialized as one list — satisfies the memory bound. Schema validation runs to completion before generate() is ever called — satisfies fail-before-write. Written to nfr-design.md. Approve

Stage 3.4: Infrastructure Design (aws-platform agent)

Claude Code: No servers — this ships as a pip-installable package. Build as a wheel + sdist, publish to PyPI under the name synth-data. Written to infrastructure-design.md. Approve


Stage 3.5: Code Generation (subagent) — Plan, Then Code

This is the walking skeleton gate — the first Construction stage is always reviewed before the rest of Construction runs, even in autonomous mode. Claude Code writes the plan first, before touching any code:

# code-generation-plan
- [ ] src/schema.py — Schema, Column, Constraint (dataclasses), from_yaml()
- [ ] src/generate.py — generate(schema, n) — generator, Faker-backed
- [ ] src/exporters.py — to_csv, to_json, to_parquet, to_sql — batch-consuming
- [ ] src/cli.py — click CLI wiring it together
- [ ] tests/test_generate.py — constraint compliance, row count, format round-trips
▸ Approve Plan? [Yes / Request Changes]

You: Approve Plan

Only now does Claude Code generate code — the plan-approval-guard hook (below) physically blocks it from writing source files before this point. A slice of src/exporters.py, showing the batch-consuming design from NFR Design above:

def to_csv(rows: Iterator[dict], path: str, batch_size: int = 1000) -> None:
    with open(path, "w", newline="") as f:
        writer = None
        for batch in chunked(rows, batch_size):
            if writer is None:
                writer = csv.DictWriter(f, fieldnames=batch[0].keys())
                writer.writeheader()
            writer.writerows(batch)
Code generation complete — 4 files created, 9 tests written, all passing.
▸ [Approve / Request Changes]

You: Approve

The walking skeleton just shipped. Because our Delivery Plan has only one Unit, the ladder prompt — a follow-up question the AI would normally ask here, letting us choose "Continue autonomously" vs. "Gate every Bolt" (i.e., keep approving each step, or let it run ahead on its own) — has nothing further to apply to. With more than one Unit, this is the moment we'd make that choice for the remaining Bolts.

Behind the scenes: aidlc-plan-approval-guard is a PreToolUse hook — a script that runs automatically before a tool is allowed to act, and can block it. Here, it deterministically blocks any code-writing tool call for this stage until it sees a recorded "Approve Plan" decision, so the plan-before-code ordering can't be talked around. aidlc-deliver-stage-rules runs alongside it, making sure the exact same stage rules reach a delegated subagent as reached the conductor (the main orchestrating agent). Had our Delivery Plan split this into several independent Units, the ones with no dependency on each other would run as a parallel batch — multiple Task calls issued in a single turn, i.e. worked on at the same time instead of one after another.


Stage 3.6: Build and Test (once, for the whole solution)

Claude Code runs these commands itself — it has shell access as one of its tools, so nobody types pytest by hand — and reports what came back:

pip install -e . → entry point `synth-data` registered
pytest tests/ -v → 9 passed in 0.31s

You: Approve

Stage 3.7: CI Pipeline (once, for the whole solution)

Claude Code: Writes .github/workflows/test.yml — runs pytest and ruff check on every push, across a Python 3.10 / 3.11 / 3.12 matrix, so a change that works on our machine is checked on the versions we claim to support before it ever reaches Operation.

▸ Approve? [Yes / Request Changes]

You: Approve

Behind the scenes: Progress: 23/33 overall | 7/7 CONSTRUCTION stages complete. synth-data now exists, tested, in the project's src/, with a CI workflow that will run on every future push — including whatever Operation is about to do.


‹ Back to: Part 3 — Inception Phase Continue to: Part 5 — Operation Phase

Find this content helpful? ☕ Buy me a coffee

Entity Details

Create New Item

help

Submit Technical Query

Have a question or run into an issue? Describe it below, upload an optional screenshot, and our engineering team will answer it!

image Attach image (optional)

Submit Feedback

build Free Developer Utility Free Tool
gavel

Privacy & Legal Disclaimer

1. Client-Side Browser Processing

All utility tools on DeepEngineerHub (including Image to PDF, Text Formatters, JSON Converters, and Encryptors) execute 100% locally within your client browser using WebAssembly and JavaScript. No uploaded images, text, or documents are transmitted, collected, or stored on remote servers.

2. Limitation of Liability ("As-Is" Provision)

Tools and services are provided free of charge for convenience and educational purposes "as-is" without warranties of any kind. DeepEngineerHub shall not be held liable for any data loss, formatting inconsistencies, or indirect damages resulting from tool usage.

3. Open Source & Third-Party Software

Certain utilities utilize open-source client libraries (such as jsPDF, Mermaid.js, Pyodide) licensed under MIT, Apache, or BSD open licenses. All intellectual property remains with their respective copyright holders.