AI-Assisted Greenfield Software Development, Part 1: Business Requirements
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.

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.

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:
Each Academic has exactly one EmpName.
It is possible that more than one Academic has the same EmpName.
Reference Scheme: Dept has Dept_name.
Reference Mode: .name.
Data Type: Text: Variable Length (15).
Fact Types:
Dept has Dept_name.
Academic works for Dept.
Dept has head with home PhoneNr.
Dept has teaching budget of MoneyAmt.
Dept has research budget of MoneyAmt.
Professor heads Dept.
Each Academic works for exactly one Dept.
It is possible that more than one Academic works for the same Dept.
Reference Scheme: Date has mdy.
Reference Mode: mdy.
Data Type: Temporal: Date.
Fact Types:
Date has mdy.
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.
that Academic is tenured;
that Academic is contracted until some Date.
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.
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'.
Each Academic has exactly one Rank.
It is possible that more than one Academic has the same Rank.
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.
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.
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.
Reference Scheme: Subject has Subject_code.
Reference Mode: .code.
Data Type: Text: Fixed Length (0).
Fact Types:
Subject has Subject_code.
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.
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.
Each Teaching gets at most one Rating.
It is possible that more than one Teaching gets the same Rating.
Each Dept has head with home exactly one PhoneNr.
It is possible that more than one Dept has head with home the same PhoneNr.
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.
Each Dept has teaching budget of exactly one MoneyAmt.
It is possible that more than one Dept has teaching budget of the same MoneyAmt.
Each Dept has research budget of exactly one MoneyAmt.
It is possible that more than one Dept has research budget of the same MoneyAmt.
Each Professor heads at most one Dept.
For each Dept, at most one Professor heads that Dept.
Reference Scheme: Chair has Chair_name.
Reference Mode: .name.
Data Type: Text: Variable Length (0).
Fact Types:
Chair has Chair_name.
Professor holds Chair.
Each Professor holds exactly one Chair.
For each Chair, at most one Professor holds that Chair.
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.
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.
Reference Scheme: Committee has Committee_name.
Reference Mode: .name.
Data Type: Text: Variable Length (0).
Fact Types:
Committee has Committee_name.
Teaching Prof serves on Committee.
Reference Scheme: Academic has empNr.
Reference Mode: empNr.
Data Type: Text: Fixed Length (6).
Fact Types:
Teaching Prof serves on Committee.
Each Teaching Prof is an instance of Teacher.
Each Teaching Prof is an instance of Professor.
It is possible that some Teaching Prof serves on more than one Committee
and that for some Committee, more than one Teaching Prof serves on that Committee.
In each population of Teaching Prof serves on Committee, each Teaching Prof, Committee combination occurs at most once.
This association with Teaching Prof, Committee provides the preferred identification scheme for TeachingProfServesOnCommittee.
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'.
Each Rank ensures exactly one AccessLevel.
It is possible that more than one Rank ensures the same AccessLevel.
Reference Scheme: Extension has extNr.
Reference Mode: extNr.
Data Type: Numeric: Decimal.
Fact Types:
Extension has extNr.
Academic uses Extension.
Each Academic uses exactly one Extension.
Each Extension is used by at most one Academic.
Reference Scheme: Room is in Building; Room has RoomNr.
Fact Types:
Academic occupies Room.
Room has RoomNr.
Room is in Building.
Each Academic occupies exactly one Room.
It is possible that more than one Academic occupies the same Room.
Each Room has exactly one RoomNr.
It is possible that more than one Room has the same RoomNr.
Reference Scheme: Building has bldgNr.
Reference Mode: bldgNr.
Data Type: Numeric: Decimal.
Fact Types:
Building has bldgNr.
Room is in Building.
Building has BldgName.
Each Room is in exactly one Building.
It is possible that more than one Room is in the same Building.
at most one Room is in that Building and
has that RoomNr.
This association with Building, RoomNr provides the preferred identification scheme for Room.
Each Building has exactly one BldgName.
For each BldgName, at most one Building has that BldgName.
Reference Scheme: Academic has empNr.
Reference Mode: empNr.
Data Type: Text: Fixed Length (6).
Fact Types:
Academic has empNr.
Academic has EmpName.
Academic works for Dept.
Academic is tenured.
Academic is contracted until Date.
Each Professor is an instance of Academic.
Academic has Rank.
Academic obtained Degree from University.
Academic teaches Subject.
Each Teacher is an instance of Academic.
Academic uses Extension.
Academic occupies Room.
</html>
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 ir-refexive 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 sub-type 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 AIP@pdata.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?
Original post