AI-Assisted Greenfield Software Development, Part 1: Business Requirements

by John Miller | First published: September 21, 2025 - Last Updated: September 30, 2025

This post starts a new series on greenfield software development. The goal is to show the development of a solution starting with the initial context and adding to the solution incrementally. Hopefully you'll get a sense for what it's like to build real-world solutions with the assistance of Copilot.

In this first installment we'll look at the initial context provided to Copilot. This will include the initial instructions and the first prompts submitted to Copilot.

In this series we'll start with a conceptual model of an academic system. The academic system is a standin for any complex enterprise scale system. I'm using it because it's a familiar domain and a publicly available model.

We'll use the conceptual model to generate a domain glossary and a set of instructions for Copilot. We'll then use those instructions to create implementation prompts and the implementation prompts will create the solution. Here is a flowchart that illustrates the process.

AIAGSD1Workflow.png

I'll cover each of these steps, in detail, in subsequent posts. In this post I'll cover the initial context, the conceptual model, and the instructions prompt.

The Academia Conceptual Model

I'll start this project with a conceptual model. The benefit of starting with a conceptual model is that it is implementation agnostic. It describes the concepts that the solution must implement, not how they should be implemented. It allows us to consider the correctness of the concepts without burdening ourselves with implementation details.

The image below is the conceptual model for the academic system I'm intending to build.

Academic-Model.png

This notation is Object Role Modeling (ORM). FWIW, ORM preceded Object Relational Mapping by decades. ORM is offers a compelling set of benefits, especially for conceptual data modeling and communication between technical and non-technical stakeholders.

  • Conceptual Clarity & Expressiveness: ORM offers several advantages over traditional modeling approaches like ER or UML. By aligning with natural language, ORM represents facts using full sentences, making models more intuitive and easier for business users to understand and validate. It also adopts an attribute-free approach, emphasizing roles and relationships rather than attributes, which enhances model stability and adaptability. Furthermore, ORM diagrams provide greater graphical richness, allowing for the clear representation of complex constraints and business rules that might be difficult to capture in ER or UML class diagrams.
  • Data Quality & Governance: ORM enhances data quality and governance by enabling early detection of inconsistencies and modeling errors, which helps prevent issues before they propagate. Its structured and transparent approach also supports the enforcement of data governance policies, making it easier to maintain compliance across systems and teams.
  • Flexibility & Transformation: ORM offers powerful flexibility through model transformation, allowing seamless mapping to and from formats such as ER, UML, XML, OWL, and even logic-based languages like Datalog. This interoperability makes ORM a versatile choice for diverse technical environments. Additionally, ORM excels at capturing a broader range of business rules compared to other modeling approaches, making it particularly well-suited for systems that need to evolve and adapt over time.
  • Validation & Collaboration: ORM enhances collaborative validation by supporting verbalization and example population, allowing stakeholders to review and confirm models using familiar language and concrete instances. Its intuitive structure makes it accessible to both technical and non-technical participants, fostering clearer communication and stronger engagement among developers, analysts, and domain experts throughout the modeling process.

You can create ORM models in Visual Studio with the NORMA (Natural Object-Role Modeling Architect) extension. NORMA ORM models provide natural feedback during model validation.

For our purposes, an ORM model can be verbalized as text that can be used as context for Copilot. This provides Copilot with a rich “understanding” of the problem domain that it can use to assist us in implementing a solution.

Here is the verbalization of the Academia model:

ORM2 Verbalization
EmpName is a value type.
Data Type: Text: Variable Length (15).

Fact Types:
Academic has EmpName.
Academic has EmpName.
Each Academic has exactly one EmpName.
It is possible that more than one Academic has the same EmpName.
Academic works for Dept.
Each Academic works for exactly one Dept.
It is possible that more than one Academic works for the same Dept.
For each Dept and EmpName,
at most one Academic works for that Dept and
has that EmpName.
Academic is tenured.
In each population of Academic is tenured, each Academic occurs at most once.
Date is an entity type.
Reference Scheme: Date has mdy.
Reference Mode: mdy.
Data Type: Temporal: Date.

Fact Types:
Date has mdy.
Academic is contracted until Date.
For each Academic, at most one of the following holds:
that Academic is tenured;
that Academic is contracted until some Date.
Professor is an entity type.
Reference Scheme: Academic has empNr.
Reference Mode: empNr.
Data Type: Text: Fixed Length (6).

Fact Types:
Each Professor is an instance of Academic.
Professor heads Dept.
Professor holds Chair.
Each Teaching Prof is an instance of Professor.
Rank is an entity type.
Reference Scheme: Rank has Rank_code.
Reference Mode: .code.
Data Type: Text: Fixed Length (0).

Fact Types:
Rank has Rank_code.
Academic has Rank.
Rank ensures AccessLevel.

The possible values of Rank are 'P', 'SL', 'L'.
Academic has Rank.
Each Academic has exactly one Rank.
It is possible that more than one Academic has the same Rank.
Degree is an entity type.
Reference Scheme: Degree has Degree_code.
Reference Mode: .code.
Data Type: Text: Fixed Length (0).

Fact Types:
Degree has Degree_code.
Academic obtained Degree from University.
University is an entity type.
Reference Scheme: University has University_code.
Reference Mode: .code.
Data Type: Text: Fixed Length (0).

Fact Types:
University has University_code.
Academic obtained Degree from University.
Academic obtained Degree from University.
For each Academic and Degree,
that Academic obtained that Degree from at most one University.
This association with Academic, Degree provides the preferred identification scheme for AcademicObtainedDegreeFromUniversity.
Each Academic obtained some Degree from some University.
Subject is an entity type.
Reference Scheme: Subject has Subject_code.
Reference Mode: .code.
Data Type: Text: Fixed Length (0).

Fact Types:
Subject has Subject_code.
Academic teaches Subject.
Academic teaches Subject.
It is possible that some Academic teaches more than one Subject
and that for some Subject, more than one Academic teaches that Subject.

In each population of Academic teaches Subject, each Academic, Subject combination occurs at most once.
This association with Academic, Subject provides the preferred identification scheme for Teaching.
Rating is an entity type.
Reference Scheme: Rating has Rating_nr.
Reference Mode: .nr.
Data Type: Numeric: Signed Integer.

Fact Types:
Rating has Rating_nr.
Teaching gets Rating.

The possible values of Rating are at least 1 to at most 7.
Teaching gets Rating.
Each Teaching gets at most one Rating.
It is possible that more than one Teaching gets the same Rating.
PhoneNr is a value type.
Data Type: Numeric: Decimal.

Fact Types:
Dept has head with home PhoneNr.
MoneyAmt is an entity type.
Reference Scheme: MoneyAmt has usd.
Reference Mode: usd.
Data Type: Numeric: Money.

Fact Types:
MoneyAmt has usd.
Dept has teaching budget of MoneyAmt.
Dept has research budget of MoneyAmt.
Professor heads Dept.
Each Professor heads at most one Dept.
For each Dept, at most one Professor heads that Dept.
Chair is an entity type.
Reference Scheme: Chair has Chair_name.
Reference Mode: .name.
Data Type: Text: Variable Length (0).

Fact Types:
Chair has Chair_name.
Professor holds Chair.
Teacher is an entity type.
Reference Scheme: Academic has empNr.
Reference Mode: empNr.
Data Type: Text: Fixed Length (6).

Fact Types:
Teacher is audited by Teacher.
Each Teacher is an instance of Academic.
Each Teaching Prof is an instance of Teacher.
Commitee is an entity type.
Reference Scheme: Commitee has Commitee_name.
Reference Mode: .name.
Data Type: Text: Variable Length (0).

Fact Types:
Commitee has Commitee_name.
Teaching Prof serves on Commitee.
Teaching Prof is an entity type.
Reference Scheme: Academic has empNr.
Reference Mode: empNr.
Data Type: Text: Fixed Length (6).

Fact Types:
Teaching Prof serves on Commitee.
Each Teaching Prof is an instance of Teacher.
Each Teaching Prof is an instance of Professor.
Teaching Prof serves on Commitee.
It is possible that some Teaching Prof serves on more than one Commitee
and that for some Commitee, more than one Teaching Prof serves on that Commitee.

In each population of Teaching Prof serves on Commitee, each Teaching Prof, Commitee combination occurs at most once.
This association with Teaching Prof, Commitee provides the preferred identification scheme for TeachingProfServesOnCommitee.
AccessLevel is an entity type.
Reference Scheme: AccessLevel has AccessLevel_code.
Reference Mode: .code.
Data Type: Text: Fixed Length (0).

Fact Types:
Rank ensures AccessLevel.
AccessLevel has AccessLevel_code.

The possible values of AccessLevel are 'INT', 'NAT', 'LOC'.
Rank ensures AccessLevel.
Each Rank ensures exactly one AccessLevel.
It is possible that more than one Rank ensures the same AccessLevel.
Extension is an entity type.
Reference Scheme: Extension has extNr.
Reference Mode: extNr.
Data Type: Numeric: Decimal.

Fact Types:
Extension has extNr.
Academic uses Extension.
Academic occupies Room.
Each Academic occupies exactly one Room.
It is possible that more than one Academic occupies the same Room.
RoomNr is a value type.
Data Type: Numeric: Decimal.

Fact Types:
Room has RoomNr.
Room has RoomNr.
Each Room has exactly one RoomNr.
It is possible that more than one Room has the same RoomNr.
Building is an entity type.
Reference Scheme: Building has bldgNr.
Reference Mode: bldgNr.
Data Type: Numeric: Decimal.

Fact Types:
Building has bldgNr.
Room is in Building.
Building has BldgName.
Room is in Building.
Each Room is in exactly one Building.
It is possible that more than one Room is in the same Building.
For each Building and RoomNr,
at most one Room is in that Building and
has that RoomNr.

This association with Building, RoomNr provides the preferred identification scheme for Room.
BldgName is a value type.
Data Type: Text: Variable Length (15).

Fact Types:
Building has BldgName.
If some Professor heads some Dept then some Academic that is that Professor works for that Dept.

I'm not going to elaborate on the entire model as this is out scope for this post, but you see that the verbalization is understandable by people not familiar with the notation. We'll assume that the model is correct and has been vetted by the stakeholders. If you're interested in how the model was created, see this ORM White Paper.

By utilizing an existing model, we bypass much of the requirements gathering process. For other problem domains (like yours) you'll want to assemble the requirements in order to provide context to the NLM. You don't have to use ORM, but I've found it to be well suited to the task.

Let's take a look a few of the more interesting constraints in the Academia models.

Teacher is audited by Teacher.
Each Teacher is audited by at most one Teacher.
It is possible that some Teacher audits more than one Teacher.
No Teacher is audited by the same Teacher.

The fact that no teacher is audited by the same teacher is an irrefexive ring constraint. This constraint prevents a teacher from auditing themselves. This is an important business rule that we want to make sure the solution enforces.

If some Professor heads some Dept then some Academic that is that Professor works for that Dept.

This is a subtype constraint that requires that department heads work for the department they head. A professor is a type of academic. Academics work for departments and professors head departments. This constraint ensures that you can't assign a department head to an academic that doesn't work for the department.

Academic is contracted until Date.
Each Academic is contracted until at most one Date.
It is possible that more than one Academic is contracted until the same Date.
For each Academic, at most one of the following holds:
   that Academic is tenured;
   that Academic is contracted until some Date.

The fact that an academic is either tenured or is under contract is an exclusion constraint. Under an exclusion constraint an entity can play either role but not both. When an academic becomes tenured, we'd expect that any contract date be removed.

In addition to these, ORM has a rich set of constraints, uniqueness, equality, inclusive or, exclusive or, frequency, and value comparison.

Workflows

While ORM is very good a expressing facts and constraints, It's also helpful to describe the expected workflows that should be implemented. Workflows are use cases that guide data capture and processing in the application. Below are some expected workflows that should be implemented. The expectation is that in the execution of these workflows the constraints on the facts will be enforced.

Promote a Lecturer to Senior Lecturer
Promote a Senior Lecturer to Associate Professor
Promote an Associate Professor to Professor
Assign a Class to an Academic
Add a new Academic to the faculty capturing all required information and allowing the capture of optional 
information.
Demote a Professor to Associate Professor
Demote an Associate Professor to Senior Lecturer
Demote a Senior Lecturer to Lecturer
Remove an Academic from the faculty.
Transfer an Academic between departments, validating eligibility and updating all related information
Update an Academic's personal or professional information.
Assign administrative roles (e.g., Head of Department) to eligible Academics.

This is the primary context of the problem domain we are going to implement. In subsequent posts I'll add context for the expected architecture, tech stack, and standards. I'll then proceed to systematically implement a solution guided by this context. Next up I'll add a prompt to create instruction files and a custom chat mode in preparation for the implementation.

If you're interested is seeing the files you can find them in the Academia repository. If you want to follow along with your own implementation, fork this repo and use the fork to build you own implementation.

Feedback Loop

Feedback is always welcome. Please direct it to john.miller@codemag.com

Disclaimer

AI contributed to the writing to this blog post, but humans reviewed it, refined it, enhanced it and gave it soul.

Prompts:

  • What are benefits of Object Role Modeling?