Part A — Robust software engineering · Chapter 5

AI-assisted software engineering

~40 min read5 interactive widgets4 plates

In this chapter

  1. AI for software engineering, and the reverse
  2. The AI coding spectrum
  3. Bootstrappers, iterators, pair programmers and validators
  4. Choosing a paradigm, and the knowledge paradox
  5. The intent-driven workflow
  6. Tool categories and the anatomy of an assistant
  7. Context indexing and agentic capabilities
  8. Copilot as a case study, and its RAG architecture
  9. The levels of autonomy
  10. The 70 percent problem
  11. The majority solution effect
  12. Review, refine, own, and test
  13. Prompting strategies and antipatterns
  14. Context engineering
  15. Golden rules, challenges and the evolving role
  16. Lab: Copilot, Connect Four and the human in the loop
  17. Test your knowledge

1. AI for software engineering, and the reverse

The lecture starts by separating two directions that are constantly conflated, and by declaring which one it is about.

AI × Software EngineeringSoftware Engineering × AI
WhatUsing AI to improve the development processUsing software engineering to build and manage AI products
FocusEnhancing developer productivity and output qualityInfrastructure, pipelines and governance for models and agents
HowAutocompletion, code generation, test generation, refactoring, bug detectionRAG pipelines, model serving, observability, agentic orchestration
ExamplesGitHub Copilot, AI test generators, code-review assistantsChatbots, NotebookLMs, new autonomous coding agents
MetricsTime-to-delivery, defect density, test coverageLatency, availability, compliance, operational cost
In one lineOptimizes the how, the development process itselfDefines the what, the AI product itself

This chapter is about the left column: how LLMs can augment the developer across the entire software development lifecycle. The right column is the subject of chapter 15, which builds and then verifies an agentic system. A caveat the deck states up front applies to the whole chapter: this field is evolving rapidly, so the concepts matter more than the specific implementations.

2. The AI coding spectrum

The central organising idea is that the way developers use AI exists on a spectrum of control and rigor, with three named positions.

Vibe coding is defined, quoting Addy Osmani in Beyond Vibe Coding (2025), as a prompt-first, exploratory approach where the developer describes intent in natural language and lets the AI fill in the implementation. Set against it, AI-assisted programming is defined as AI acting as a collaborator under human guidance, augmenting and not replacing engineering skills. The deck contrasts them bullet by bullet.

Development guided solely by natural language, without reading or deeply analyzing the generated code.

  • Chat-based iterations: describe, generate, run, re-describe.
  • The code is a black box: you evaluate if it works, not how.
  • Rapid validation of ideas, MVPs, glue code.
  • Typically solo; the developer is a prompt artist.
  • Risk: technical debt and fragile codebases.

AI acts as a collaborator under human guidance, augmenting and not replacing engineering skills.

  • AI creativity is bounded by specifications and constraints.
  • The developer reviews, refines and owns every line.
  • Systematic and iterative: TDD, context engineering, prompt discipline.
  • Team-based: the developer acts as architect and technical lead.
  • Risk: the overhead of review and process discipline.
Key idea

Note that both columns carry a risk, and that they are opposite risks. Vibe coding risks accumulating debt you did not notice; AI-assisted programming risks spending more on process than the generated code saved. The deck refuses to declare a winner and instead gives selection criteria, which is the subject of section 4.

3. Bootstrappers, iterators, pair programmers and validators

Two orthogonal classifications follow. The first is about where in a project life the AI is used.

BootstrappersIterators
Taking a new project from zero to MVP. Tools: Bolt, Lovable, screenshot-to-code AI. Start with a design or rough concept; the AI generates a complete initial codebase; a working prototype in hours, not weeks; the focus is rapid validation and iteration. Not production-ready, but good enough for early user feedback.Using AI in the daily development workflow. Tools: Cursor, Copilot, Windsurf, Cline. AI for code completion and suggestions, complex refactoring and migrations, test and documentation generation, and as a pair programmer for problem-solving. Less flashy, but potentially more transformative for daily output.

The second is about what role the AI plays.

AI as pair programmerAI as validator
Developer and AI in constant conversation, with tight feedback loops and frequent review. The AI handles repetitive tasks such as boilerplate and test cases while the developer maintains oversight for quality and relevance. It accelerates development and facilitates knowledge acquisition, and is particularly beneficial for solo developers or limited team resources.The AI analyzes code for bugs, vulnerabilities and best practices, with tools such as DeepCode, Snyk and Qodo. It identifies missing input sanitization and insecure configurations, automatically generates test cases for broader coverage, and monitors application performance to detect anomalies. It complements human oversight and handles repetitive QA tasks.
Editor's note

The validator column is where this chapter touches chapter 3 most directly. An AI validator that automatically generates test cases for broader coverage is optimising exactly the metric that chapter 3 warns about: coverage is a necessary but insufficient signal, and parameter value coverage shows why. A generated suite that raises line coverage while leaving the interesting values untested is precisely the kind of technical debt the deck attributes to bad tests.

4. Choosing a paradigm, and the knowledge paradox

Vibe coding works well forAI-assisted programming is needed when
Rapid prototyping and idea validation; one-off scripts and glue code; modern framework scaffolding such as Next.js or FastAPI; repetitive code generation such as CRUD and boilerplate; personal side projects and MVPs; learning a new framework quickly.The failure cost is high, whether financial, safety-related or reputational; technical debt would be unacceptable; the code must integrate with complex existing systems; security and compliance are mandatory; long-term maintainability is required; the team needs a shared understanding of the codebase.

Independently of the paradigm, three areas are named where AI struggles: complex system design, for example distributed algorithms; low-level optimization, for example CPU cache behaviour or real-time constraints; and novel or niche frameworks and creative UX or UI work.

The knowledge paradox

Key idea — the knowledge paradox

"AI tools often benefit experienced developers more than beginners, because seniors have the judgment necessary to guide the AI and catch its mistakes." (Osmani, Beyond Vibe Coding)

Senior engineers use AI to accelerate what they already know, can validate and debug AI output effectively, guide the AI with precise constraints, and think of it as a very eager junior developer. Junior developers risk accepting polished-looking but flawed code, struggle to debug code they did not write, may create fragile systems they do not fully understand, and face the temptation to skip learning fundamentals. The takeaway is stated plainly: the more you know, the better you can guide AI; the tools amplify existing skill, they do not replace it.

This is the same claim the very first lecture of the course made, in different words: highly technical skills will be needed to really exploit all the benefits of generative AI (chapter 1). Here it is given a mechanism: the benefit is proportional to your ability to evaluate the output, and evaluation is exactly the skill the tool does not supply.

5. The intent-driven workflow

Programming is described as evolving from imperative, "how do I do X?", to declarative or intent-driven, "I need X done".

TraditionalIntent-driven
ActivityThe developer writes every lineThe developer specifies what they want
FocusSyntax and implementationClarity of specification
SkillTyping code correctlyArticulating intent precisely

The image used is a shift from prompt artists to orchestra conductors: the role of the developer moves from writing code to directing it.

For the exam

Notice that "clarity of specification" is the same phrase Part B of this course uses for a different purpose. In chapter 6 a specification is made precise by writing it in a strongly typed, highly declarative language so that a compiler can check it; here it is made precise so that a model can implement it. A good answer at the oral connects the two: intent-driven development raises the value of exactly the specification skills the modelling half of the course teaches, because a specification that a type system can check is also a specification an LLM can be held to.

6. Tool categories and the anatomy of an assistant

1. Plugins and extensions2. AI-native IDEs3. Web-based
Integrate AI into your existing IDE. GitHub Copilot (VS Code, JetBrains, Neovim), Amazon Q Developer (multi-IDE), Tabnine, Codeium.
Pros: the full IDE ecosystem is preserved; non-invasive and portable.
Cons: limited by IDE APIs; AI features can feel secondary.
Editors built from the ground up with AI at the centre. Cursor (a VS Code fork, 2022), Windsurf (Codeium, Cascade), Zed (fast plus AI), Replit.
Pros: advanced agentic features; a seamless AI-first user experience.
Cons: editor lock-in; less mature ecosystems.
A full IDE in the browser with AI and instant deploy. Replit (Ghostwriter), StackBlitz (WebContainers), Bolt.new (AI full-stack).
Pros: zero setup, multi-device; instant deploy and sharing.
Cons: web development focus, privacy concerns; not suited for large projects.

Regardless of category, every AI-assisted tool shares three core components: the editor or IDE, providing the development environment, local context awareness, a UI for suggestions and chat, and a real-time feedback loop; the AI model, which generates code from intent, is trained on millions of repositories, understands semantics and patterns, and is model-agnostic so it can be swapped per task; and the integration layer, a plugin or API bridge providing workflow orchestration, bidirectional communication and tool coordination through protocols such as MCP and LSP.

Model selection is itself named as a developer skill. The categories are speed-optimized models for autocomplete and inline suggestions, with low latency and high throughput; deep reasoning models for long-context complex tasks such as architecture, debugging and planning; multi-model powerhouses for prototyping and broad capability; and open source models for local reproducibility, privacy and stability. The selection criteria are the task requirements (multi-modal? deep reasoning? fast completion?), the computational resources available, privacy and security constraints, cost as API pricing versus local inference, and the context window, meaning how much code the model can see.

7. Context indexing and agentic capabilities

Two further capabilities separate a toy assistant from a usable one.

Context indexing and retrieval covers project parsing (abstract syntax trees, symbol tables, dependency graphs), vector embeddings for semantic search, and context retrieval from open files, selections, #codebase and git history. The consequence is stated bluntly: without this, the AI generates generic, disconnected code.

Tool use and agentic capabilities splits tools into passive ones, namely code completion, inline suggestions and chat question answering, and active or agentic ones, namely terminal execution, autonomous codebase navigation, web search, multi-file edits and automated testing. Higher integration means a better developer experience.

Key idea — how agentic tools actually work

"Agentic AI tools can autonomously execute tasks, navigate codebases, and even self-correct based on outcomes. They represent a shift from AI assists to AI acts under human supervision." Mechanically: LLMs still generate only text, but an integration layer allows them to invoke tools such as the terminal, search and code edits as part of their output. Conceptually, all available tools are defined in the prompt, and the LLM decides when to use them based on the task and context. The strongest models learn how to use tools via fine-tuning, not merely through zero-shot prompting, and most recent models inherently support tool calling, which is what enables agentic AI.

8. Copilot as a case study, and its RAG architecture

GitHub Copilot is used as the running example because it spans the entire autonomy spectrum. It is an advanced AI coding assistant by GitHub and Microsoft, released in 2021, with more than 20 million active developers; it uses a family of specialized language models and is mostly model-agnostic, letting you swap between GPT-*, Claude, Gemini and local models. Its key features are real-time code suggestions, context-aware assistance which is RAG-based, inline chat, full chat and agent mode, and IDE integration with VS Code, JetBrains and Neovim.

Inside, the context awareness is retrieval-augmented generation in three stages.

9. The levels of autonomy

The organising table of the whole lecture, illustrated through Copilot because it spans the entire spectrum, and explicitly analogous to the levels of autonomous driving: each step trades human control for AI initiative.

LevelNameCopilot featureHuman role
L0Code completionInline ghost-text suggestions based on immediate contextFull control; accepts or rejects each suggestion
L1Code creationInline chat, the /doc, /test, /fix commands, full chat with #-mentionsSupervises, integrates and iterates
L2Supervised automationAgent mode: plans, edits, runs terminal, monitors outcomesValidates the final result; acts as quality gate
L3Full automationCoding agent: a background agent triggered from GitHub Issues or PRsMonitors; reviews the PR and intervenes on exceptions
L4AI-led autonomyFuture: the AI defines its own goals and strategiesStrategic oversight only

Level by level

L0, code completion. The AI completes single lines or code blocks as you type, based on the immediate context of the file, plus the contextual representation of the codebase. The developer maintains total control of direction, and it acts as an accelerator for repetitive tasks. It was the first feature introduced by Copilot, in 2021, and the default and only model available for it is GPT-4.1. Interactions: Tab to accept, Esc to reject, Ctrl+Right to accept partially, word by word, and F1 to open the completions panel and see alternatives. Best for boilerplate, standard patterns and known idioms; limited by the context window, by limited project awareness, and by having no natural language interaction at all.

L1, code creation. Inline chat (Ctrl+I) lets you describe intent in natural language and get code generated in place, which you accept, reject or refine with a follow-up; you can limit context by selecting specific code, and swap model per interaction. The predefined commands are /doc to generate documentation, /tests to create unit tests and /fix to correct errors; full chat supports #-mentions: #file, #codebase, #selection, #fetch. The developer still reviews and integrates every generated snippet: the AI creates, the human supervises.

L2, supervised automation (agent mode). The agent receives a high-level task in natural language, plans the steps needed to accomplish the goal, executes code edits and tool invocations autonomously, monitors outcomes and iterates on errors; it functions like an autonomous junior developer. Copilot-specific features: runs terminal commands (build, test, lint), navigates and searches the codebase, performs web search and fetches docs, coordinates multi-file edits, and supports custom agents under .github/agents/ for specialised use cases such as planning, TDD or review. The GitHub documentation puts it as: "Agent mode uses a combination of code editing and tool invocation to accomplish the task. As it processes your request, it monitors the outcome of edits and tools, and iterates to resolve any issues that arise."

The contrast with the levels below is the heart of the section. L0 and L1 are reactive: they respond to specific requests, operate on context provided by the user, do not plan autonomously, do not execute changes without explicit input, and do not use external tools. L2 is proactive: it receives a broad goal rather than a single request, plans steps and executes them, uses external tools such as terminal, web and search, self-corrects by monitoring output and iterating, and the human validates the final result rather than each step. The shift is from "AI assists" to "AI drives, under supervision".

L3, full automation (coding agent). The AI handles complex tasks in complete autonomy, triggered from a GitHub Issue or PR rather than from the IDE, without requiring human approval for each change; it navigates codebases, runs tests and submits PRs, operating as a trusted senior engineer. Copilot assigns an Issue to the agent, which works in the background following a plan-execute-verify loop and provides logs and diffs for human audit, with multi-model orchestration using larger LLMs for reasoning and smaller ones for syntax. Agent wrangling is named as a new skill for developers. The key shift: interactive copilots wait for a prompt, background agents receive a goal and work independently. Two warnings follow: this introduces cognitive overload for the reviewer, since large PRs from agents can be harder to audit than human code; and both L2 and L3 require clear context engineering, meaning architecture and guidelines, to steer agent behaviour.

For the exam

Each level adds autonomy and demands more from the developer in terms of review, context engineering and trust calibration. That inversion is the examinable point: naive intuition says more autonomy means less work for the human, whereas the lecture argues that the work changes kind, from writing to reviewing and from reviewing to specifying, and that at L3 the reviewing burden can actually exceed what human-written code would have cost.

10. The 70 percent problem

Increasing autonomy raises a critical question: how do we ensure quality in AI-generated code? Three strategies are named, and the first is the diagnosis.

Watch out — the 70 percent problem

"Honest reflection from coding with AI: It can get you 70% of the way there, but that last 30% is frustrating. It keeps taking one step forward and two steps backward with new bugs and issues." AI gets you most of the way, but the remaining part is often the hardest; it requires disciplined review, testing and refactoring; and the human must own the final output.

Where AI excels (the 70%)Where humans are essential (the 30%)
Boilerplate generation and repetitive patterns; unit test skeleton creation and documentation; legacy code refactoring and migrations; scaffolding projects and standard CRUD logic; mechanical transformations, for example React class components to functional ones.Architecture and system design decisions; complex edge cases and failure modes; business requirement translation; security and performance optimization; integration of components into a cohesive whole.

11. The majority solution effect

AI models trained on vast code repositories tend to produce the most statistically common solution, not necessarily the best one for your context. This single sentence explains most of the failure modes listed next, and it also explains why they are so hard to spot: the output looks like code you have read a thousand times, because it is.

Common issuesMitigation strategies
Off-by-one errors: loop boundaries remain tricky for AI.
Unhandled exceptions: the code assumes happy-path inputs.
Outdated APIs: the model may use deprecated library functions.
Library bloat: importing org.apache.commons.io.FileUtils for basic file operations.
Inconsistencies: the docstring says one thing, the code does another.
Always mentally test edge cases through the logic.
Add the error handling the AI likely missed.
Check library versions against current documentation.
Look for unusual structure: too many classes? too clever?
Inline or simplify where the AI has over-complicated.
Apply the same review rigor as for any untested contribution.
Editor's note

The last mitigation is the one that generalises: apply the same review rigor as for any untested contribution. It reframes AI output as what it actually is in process terms, a patch from a contributor whose track record you do not know. Every practice the course already teaches for such patches, from the CORRECT checklist of chapter 3 to acceptance tests written before the code in chapter 2, applies unchanged.

12. Review, refine, own, and test

Once AI-generated code is functionally correct, refactor it to align with your standards. The deck gives a six-step process.

Then comes ownership through testing, described as the ultimate act of ownership because it locks down behaviour and guards against regression. Unit tests: test each function or module individually, covering the edge cases the AI likely missed; you can ask the AI to generate tests, but use them as a basis and then review them, since human intuition for creative edge cases remains valuable. Integration tests: test the AI code in context with the rest of the codebase, asking whether it stores to the database correctly and whether output chains properly to the next function. End-to-end tests: run full scenarios from start to finish, testing request, route and response in a test environment, and verifying that error handling, format and edge cases hold up.

Key idea

"Once you have tested and fixed any issues, the code is yours: you understand it, trust it, and have tests to guard it." That sentence is the operational definition of ownership used throughout this chapter, and it is why the golden rules below forbid merging code you do not understand. Ownership is not established by having typed the code, but by having a passing suite you wrote and can explain.

13. Prompting strategies and antipatterns

The stated ultimate goal is exacting: write a prompt that consistently generates, across different models, the same correct output aligned with the project. The core principles restate and sharpen those of chapter 4.

The closing observation of the section is the practical stake: a vague prompt like "write a login system" produces insecure code, whereas a structured prompt with data models, error handling and security constraints yields production-ready results.

14. Context engineering

Key idea — context engineering

A systematic approach to providing AI with targeted project information, improving the accuracy and alignment of generated code. "Context is the bridge between the programmer intent and the AI action. Without curated context, the AI generates generic solutions; with targeted context, it becomes a collaborator that understands the project."

Without context engineeringWith context engineering
The AI generates generic code; it does not respect project conventions; it ignores the existing architecture; suggestions are inconsistent; there is repeated back-and-forth to correct.Code is aligned to the project; patterns and conventions are respected; architectural decisions are coherent; knowledge is persistent across sessions; fewer corrections are needed.

Contextual prompting is the in-prompt dimension of context engineering, providing project-specific knowledge at interaction time: share data models and existing patterns, reference project conventions and style guides, use #file, #codebase and #selection references, provide examples of the desired style or logic as few-shot, and remember that modern tools work best with full codebase access. Context comes in two flavours that should be combined: persistent, meaning the Copilot customization layers of instructions, agents, skills and hooks; and per-prompt, meaning #file mentions, selected code and data models, plus ad-hoc styling rules such as naming conventions, formatting and patterns to follow or avoid.

Copilot customization layers

The customization layers are the practical implementation of context engineering: they make project knowledge persistent, structured and automatic. The deck maps each layer onto a step of the workflow.

Always-on contextOn-demand workflowsPersonas and integrations
Custom instructions (copilot-instructions.md, AGENTS.md) added to every request; file-based instructions (.instructions.md) applied when files match a glob.
Maps to: curate project context, so conventions, architecture and style are always available.
Prompt files (.prompt.md): reusable slash commands with variables and model overrides; agent skills (SKILL.md): portable instructions plus scripts plus examples.
Maps to: implementation plan, codifying repeatable tasks and planning personas.
Custom agents (.agent.md): specialized personas with restricted tools and handoffs; MCP servers connecting to APIs, databases and issue trackers; hooks, shell commands for format, lint and audit.
Maps to: implement with AI, orchestrating agents with the right tools.

The deck points at github.com/github/awesome-copilot for examples.

15. Golden rules, challenges and the evolving role

The golden rules of AI-assisted development

Best practices distilled from professional teams using AI tools, credited to Addy Osmani, Beyond Vibe Coding: Mastering AI-Assisted Development:

Known challenges

TechnicalHuman and organizational
Variable output quality, with inconsistent results across prompts; ambiguous prompts giving ambiguous code, garbage in and garbage out; outdated APIs and deprecated patterns; security blind spots, since AI may generate vulnerable code; performance, since the majority solution is often correct but not optimal; context window limits, since large codebases exceed what the model can see.Overreliance and skill atrophy, a documented phenomenon under active study; bias in AI output, since models reflect training data biases; trust and correctness, with the temptation to accept "it compiles" as "it is correct"; job shifting, with roles evolving from coder to orchestrator; licensing risks, since AI may suggest restrictively licensed code; transparency, meaning normalizing AI use as a standard professional skill.

On security, maintainability and reliability: AI-generated code may use outdated patterns or miss recent attack vectors, error handlers may leak stack traces, database queries may be susceptible to injection; AI output must be supplemented with current security knowledge, and specialized AI auditors such as Snyk and DeepCode used as a safety net. Reliability means moving beyond "it runs" to "it is robust": build automated testing that keeps pace with generated code, treat disciplined refactoring and code review as non-negotiable, deploy with gradual rollouts, heavy monitoring and quick rollback, and accept that performance optimization the AI overlooks requires human intervention.

The evolving developer role, and what developers say

Senior engineers transition from code artisan to orchestrator, translating complex requirements into effective prompts, acting as architect and editor-in-chief, mentoring juniors on AI-assisted workflows; their value is system design, judgment and product vision. Mid-level engineers become product-minded engineers, seeing code as a means to an end, specialising in AI-human workflow optimization and bridging business needs and AI capabilities. Junior developers use AI to learn without becoming reliant, must verify AI outputs independently, avoid the hallucination trap and build a foundation in fundamentals alongside AI skills. Professional development is shifting: the human provides direction, depth and values; the AI provides speed and breadth.

The reported experience is mixed, and the deck reports both halves. Perceived benefits: boosting productivity with significant time savings on routine tasks; staying in the flow with fewer context switches; lowering barriers to entry so new developers onboard faster; changing roles and tools as new workflows emerge; a 10x to 100x potential from automating routine coding and boilerplate. Persistent concerns: the 30 percent frustration, since AI gets close but the remaining fix is harder; debugging unfamiliar code, since fixing code you did not write demands different skills; cognitive offloading, the temptation to stop thinking critically; learning versus producing, since it is unclear whether AI accelerates growth or hinders it; and workflow dependency, feeling less productive without AI tools. One developer quote sums up the discomfort: "If I knew how the code worked I could probably fix it myself. But since I don't, I question if I'm actually learning that much."

Looking ahead, the emerging trends listed are natural-language-first development, where the line between writing code and describing systems blurs further; specialized AI roles such as AI wranglers and automation leads; multi-model orchestration, different models for different tasks; and autonomous background agents, from copilot to full agent. The counterweight, called the human linchpin, is that despite extreme automation, human creativity and judgment remain the primary drivers, system design and product vision become the most valuable skills, AI handles execution while humans focus on empathy, system thinking and solving real-world problems, and the future developer does not type perfectly, they explain perfectly what they want to achieve.

For the exam

The summary the lecture itself gives is a good answer skeleton: vibe coding and AI-assisted programming are two paradigms on the same spectrum and each has its place; the levels of autonomy range from inline completion to fully autonomous agents; the 70 percent problem means AI is a powerful first-drafter but humans must own the rest; and prompt engineering and context engineering are essential skills for modern developers. The closing line is worth quoting: your value lies in knowing when to trust them, when to override them, and how to guide them.

16. Lab: Copilot, Connect Four and the human in the loop

Editor's note — the one-slide sum-up

AI coding agents: tools like GitHub Copilot embed LLMs directly in the IDE; they can generate, complete, refactor, test and explain code; output quality depends heavily on context and prompt design; and the human in the loop remains essential, since the developer guides, reviews and owns the code. Key dimensions to explore: prompt engineering, that is explicit instructions shaping the agent behaviour through copilot-instructions.md; context engineering, enriching the project with documentation the agent can leverage; agent specialisation, focused agents for testing, refactoring, debugging and more; and vibe coding versus AI-assisted development, letting the AI drive versus owning the codebase yourself.

References and goals

The general goals are to set up and explore GitHub Copilot in your IDE, to experiment with prompt and context engineering in order to improve code quality, and to practise AI-assisted development with a human-in-the-loop approach.

Operational steps

  1. Step 0, set up Copilot: install the extension for your IDE, activate the GitHub Education benefits, and download and set up the project.
  2. Step 1, baseline: try the vibe. Ask Copilot to implement a Connect Four game with minimal guidance; the interface it.unibo.ConnectFour is provided as a starting point. Evaluate the solution along three axes: code quality, are there code smells, is the code readable and maintainable; correctness, does the game work as expected and are edge cases handled; creativity, are interesting techniques used and is the domain well understood. Try multiple Copilot models if available, save each solution and compare; also try open-source models via Ollama or other providers and compare.
  3. Step 2, prompt engineering: create .github/copilot-instructions.md with explicit coding guidelines and constraints, regenerate the game and evaluate on the same three axes. Is the output more consistent with your instructions? How much did the instructions improve, or change, the solution?
  4. Step 3, context engineering: enrich the project with supporting documentation, for example PRODUCT.md with product vision, features and requirements, and CONTRIBUTING.md with coding standards, conventions and guidelines; update .github/copilot-instructions.md to reference this context, then regenerate and compare.
  5. Step 4, human in the loop: put yourself in the loop alongside Copilot, choosing one or more strategies: test after generation, writing tests to verify the correctness of generated code; TDD, writing tests first and letting Copilot generate the implementation; or iterative refactoring, improving quality through guided incremental changes. Create specialised agents for specific tasks, for example a test agent and a refactor agent. You are the owner of the codebase: guide Copilot as a tool, not a replacement.

R&D tasks

TaskWhat it asks
REENGINEERApply AI-assisted engineering to one of your existing projects. Primary: use Copilot, with appropriate prompt and context engineering, to refactor a module of your project, and reflect on the quality of the result and on the effort needed to guide the agent. Advanced: starting from a README.md, use a requirements agent to structure and formalise the requirements, then implement the system with Copilot assistance; a concrete example is the /src/main/resources/product.md exercise.
AGENT-SPECIALISATIONDesign a multi-agent workflow where specialised Copilot agents collaborate to produce a higher-quality software artefact. Primary: build at least two specialised agents, for example a design agent, a test agent and a refactor agent, and evaluate whether their combination outperforms a single generic agent. The Copilot documentation covers how to create specialised agents.
EVALUATIONSystematically measure how prompt and context engineering affect the quality of AI-generated code. Primary: define a small benchmark of a few programming tasks and compare results across three configurations: no instructions, copilot-instructions.md only, and full context engineering. Advanced: investigate the effect of different Copilot models or providers on the same benchmark.
For the exam

EVALUATION is the task that most obviously begs for a rigorous treatment, and rigour here means borrowing from elsewhere in the course. A benchmark of a few tasks run three times per configuration produces noisy binary outcomes, which is exactly the setting for the pass@k estimator and the LLM-as-a-judge methodology of chapter 15, and for the confidence-versus-accuracy trade-off of approximate model checking in chapter 11. Reporting a single run per configuration is the mistake to avoid.

Test your knowledge

Distinguish AI × Software Engineering from Software Engineering × AI.

AI × SE means using AI to improve the development process: its focus is enhancing developer productivity and output quality, through autocompletion, code generation, test generation, refactoring and bug detection, with examples such as GitHub Copilot and AI test generators, and metrics such as time-to-delivery, defect density and test coverage; it optimizes the how. SE × AI means using software engineering to build and manage AI products: its focus is infrastructure, pipelines and governance for models and agents, through RAG pipelines, model serving, observability and agentic orchestration, with metrics such as latency, availability, compliance and operational cost; it defines the what.

Define vibe coding and AI-assisted programming, and name the risk of each.

Vibe coding, in Osmani's definition, is a prompt-first, exploratory approach where the developer describes intent in natural language and lets the AI fill in the implementation; development is guided solely by natural language, without reading or deeply analyzing the generated code, so the code is a black box evaluated on whether it works rather than how. Its risk is technical debt and fragile codebases. AI-assisted programming has the AI act as a collaborator under human guidance, bounded by specifications and constraints, with the developer reviewing, refining and owning every line, systematically and iteratively via TDD, context engineering and prompt discipline. Its risk is the overhead of review and process discipline.

When is vibe coding appropriate, and when is AI-assisted programming required?

Vibe coding works well for rapid prototyping and idea validation, one-off scripts and glue code, modern framework scaffolding, repetitive code generation such as CRUD and boilerplate, personal side projects and MVPs, and learning a new framework quickly. AI-assisted programming is needed when the failure cost is high, financially, for safety or for reputation; when technical debt would be unacceptable; when the code must integrate with complex existing systems; when security and compliance are mandatory; when long-term maintainability is required; and when the team needs a shared understanding of the codebase.

State the knowledge paradox and explain the mechanism behind it.

AI tools often benefit experienced developers more than beginners, because seniors have the judgment necessary to guide the AI and catch its mistakes. The mechanism is that the benefit is proportional to the ability to evaluate the output, and evaluation is precisely the skill the tool does not supply: seniors can validate and debug AI output and constrain it precisely, treating the model as a very eager junior developer, while juniors risk accepting polished-looking but flawed code, struggle to debug code they did not write and may build fragile systems they do not understand. The takeaway is that the tools amplify existing skill rather than replacing it.

Describe the five levels of autonomy with their Copilot feature and human role.

L0 code completion: inline ghost-text suggestions based on immediate context, with the human in full control, accepting or rejecting each suggestion. L1 code creation: inline chat, the /doc, /test and /fix commands and full chat with #-mentions, with the human supervising, integrating and iterating. L2 supervised automation: agent mode, which plans, edits, runs the terminal and monitors outcomes, with the human validating the final result and acting as quality gate. L3 full automation: the coding agent, a background agent triggered from GitHub Issues or PRs, with the human monitoring, reviewing the PR and intervening on exceptions. L4 AI-led autonomy: a future level where the AI defines its own goals and strategies, with only strategic human oversight.

What changes between L1 and L2, and why is that the important boundary?

L0 and L1 are reactive: they respond to specific requests, operate on context provided by the user, do not plan autonomously, do not execute changes without explicit input and do not use external tools. L2 is proactive: it receives a broad goal rather than a single request, plans steps and executes them, uses external tools such as terminal, web and search, self-corrects by monitoring output and iterating, and the human validates the final result rather than each step. It is the important boundary because it is where the unit of review changes from a snippet to an outcome, and therefore where context engineering stops being optional.

Explain the RAG architecture inside a coding assistant, stage by stage.

Data indexing, offline: parse and chunk the source code, generate vector embeddings, build a searchable vector database, and extract and annotate metadata. Retrieval, per request: embed the user query, for example "how do I implement feature X?" or "what does this function do?", perform similarity searches, rank results by relevance, and select the top-k code snippets. Augmented generation: enrich the prompt with that context, include project-specific APIs, and generate grounded responses, which reduces LLM hallucinations. Without indexing, the assistant sees only the immediate file and produces generic, disconnected code.

What is the 70 percent problem, and what belongs to each part?

AI can get you about 70 percent of the way there, but the remaining 30 percent is frustrating, with one step forward and two steps backward as new bugs appear; the remaining part is often the hardest and requires disciplined review, testing and refactoring, and the human must own the final output. The AI part covers boilerplate and repetitive patterns, unit test skeletons and documentation, legacy refactoring and migrations, project scaffolding and standard CRUD, and mechanical transformations. The human part covers architecture and system design decisions, complex edge cases and failure modes, business requirement translation, security and performance optimization, and the integration of components into a cohesive whole.

What is the majority solution effect and which concrete failures does it produce?

Models trained on vast code repositories tend to produce the most statistically common solution, not necessarily the best one for your context. The concrete failures listed are off-by-one errors, since loop boundaries remain tricky; unhandled exceptions, since the code assumes happy-path inputs; outdated APIs, since deprecated library functions are common in training data; library bloat, such as importing org.apache.commons.io.FileUtils for basic file operations; and inconsistencies where the docstring says one thing and the code does another. The mitigations are mentally testing edge cases, adding the missing error handling, checking library versions against current documentation, looking for unusual structure or over-cleverness, simplifying, and applying the same review rigor as for any untested contribution.

List the six steps of the review, refine, own process.

1. Align with style guidelines: run through your formatter and linter, fix naming, line length and conventions. 2. Improve naming and structure: replace generic names such as helper1 and helper2, inline trivial functions or split large ones. 3. Remove unnecessary parts: strip out unrequested test blocks or main sections and remove dead code the AI generated. 4. Add documentation: ensure docstrings meet your project format and add comments for non-obvious logic. 5. Optimize if needed: check algorithmic complexity and replace naive loops with efficient structures. 6. Simplify: reduce verbosity, for example turning an if-else into a single return, improving readability without sacrificing clarity.

Name the five prompting antipatterns and what each one omits.

Overloaded prompts, asking for too much at once ("Build a REST API, add authentication, write tests, and deploy it") omit the divide-and-conquer step. Vague success criteria ("Refactor this function and improve it") omit the definition of what good means. Missing constraints ("Write a cache for this service") omit key requirements such as error handling or thread safety. Open-ended creative prompts ("Write some Python code to analyze this data") omit scope, language specifics and output shape. Novel-length preambles ("You are a world-class programmer… now write a regex for emails") add noise before the actual task rather than context relevant to it.

Describe the three-step context engineering workflow and where the human gate sits.

Step one, curate project context: create ARCHITECTURE.md with design patterns, principles and dependencies; PRODUCT.md with vision, objectives and user personas; CONTRIBUTING.md with code style, best practices and workflow; and link them from .github/copilot-instructions.md. Step two, generate an implementation plan: use a planning persona in a custom chat mode, analyse requirements and codebase context, produce a structured plan with task breakdown, and pause for human review and feedback. Step three, implement with AI: feed the plan to the AI, using agent mode for complex tasks, follow TDD with tests first then minimal code then refactor, validate against the plan and iterate in a feedback loop. The human gate sits at the end of step two, which is what makes it cheap: rejecting a plan costs far less than auditing a large generated pull request.