{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "display_name": "c#",
      "language": "c#",
      "name": "c#"
    },
    "language_info": {
      "name": "c#",
      "version": "1.0.0"
    },
    "blog_metadata": {
      "topic": "Teaching Copilot team-specific workflows with Agent Skills in Visual Studio",
      "slug": "teaching-copilot-team-specific-workflows-with-agent-skills-i",
      "generated_by": "LinkedIn Post Generator + Azure OpenAI",
      "generated_at": "2026-05-15T16:41:17.618Z"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Teaching Copilot team-specific workflows with Agent Skills in Visual Studio\n",
        "\n",
        "This notebook turns the blog post into a hands-on, repo-oriented validation flow. It focuses on encoding team conventions as guidance, structured context, validation checks, and small C# utilities that simulate how a team-specific Copilot workflow can behave in Visual Studio.\n",
        "\n",
        "The examples here are implementation patterns, not an official Visual Studio Agent Skill schema. The goal is to validate bounded workflows such as PR preparation, endpoint scaffolding, and solution checks while keeping human review mandatory."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "%pip install pythonnet"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import json\n",
        "from pathlib import Path\n",
        "from textwrap import dedent\n",
        "from datetime import datetime"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Create a local working area\n",
        "\n",
        "This cell creates a small repo-like structure so the remaining examples can write guidance, context, prompts, and scripts to disk for inspection."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "from pathlib import Path\n",
        "from textwrap import dedent\n",
        "\n",
        "repo = Path('copilot_team_workflow_demo')\n",
        "(repo / 'docs').mkdir(parents=True, exist_ok=True)\n",
        "(repo / 'eng').mkdir(parents=True, exist_ok=True)\n",
        "(repo / 'src').mkdir(parents=True, exist_ok=True)\n",
        "(repo / 'tests').mkdir(parents=True, exist_ok=True)\n",
        "\n",
        "print(f'Workspace ready at: {repo.resolve()}')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Workflow overview\n",
        "\n",
        "The blog describes a bounded workflow: a developer asks Copilot for help, the workflow loads team guidance, inspects relevant files, and returns team-aligned suggestions. This C# example renders that flow as plain text so it can be validated in a notebook without Mermaid support."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "\n",
        "public static class WorkflowOverview\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var steps = new[]\n",
        "        {\n",
        "            \"Developer asks Copilot in Visual Studio\",\n",
        "            \"Agent Skill selected\",\n",
        "            \"Load team guidance from skill files\",\n",
        "            \"Inspect solution and changed files\",\n",
        "            \"Recommend workflow steps\",\n",
        "            \"Run checks or generate code\",\n",
        "            \"Return team-aligned response\"\n",
        "        };\n",
        "\n",
        "        for (int i = 0; i < steps.Length; i++)\n",
        "        {\n",
        "            Console.WriteLine($\"{i + 1}. {steps[i]}\");\n",
        "        }\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Define an illustrative skill manifest\n",
        "\n",
        "The post uses a JSON example to describe a team workflow with triggers, inputs, and outputs. This C# program models that shape and serializes it to JSON so you can validate the structure."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "using System.Text.Json;\n",
        "\n",
        "public sealed class SkillInputs\n",
        "{\n",
        "    public string solution { get; set; } = \"*.sln\";\n",
        "    public string[] changedFiles { get; set; } = new[] { \"src/**/*.cs\", \"tests/**/*.cs\" };\n",
        "}\n",
        "\n",
        "public sealed class AgentSkill\n",
        "{\n",
        "    public string name { get; set; } = \"dotnet-team-workflow\";\n",
        "    public string description { get; set; } = \"Applies repository conventions for C# services, tests, and pull request readiness.\";\n",
        "    public string[] triggers { get; set; } = new[] { \"create endpoint\", \"prepare pull request\", \"validate solution\" };\n",
        "    public SkillInputs inputs { get; set; } = new SkillInputs();\n",
        "    public string[] outputs { get; set; } = new[] { \"checklist\", \"commands\", \"code-suggestions\" };\n",
        "}\n",
        "\n",
        "public static class Program\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var skill = new AgentSkill();\n",
        "        var json = JsonSerializer.Serialize(skill, new JsonSerializerOptions { WriteIndented = true });\n",
        "        Console.WriteLine(json);\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Persist the illustrative skill manifest to the demo repo\n",
        "\n",
        "This Python cell writes the same manifest to `eng/agent-skill.json` so later cells can treat it like a repo asset."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "agent_skill = {\n",
        "    'name': 'dotnet-team-workflow',\n",
        "    'description': 'Applies repository conventions for C# services, tests, and pull request readiness.',\n",
        "    'triggers': ['create endpoint', 'prepare pull request', 'validate solution'],\n",
        "    'inputs': {\n",
        "        'solution': '*.sln',\n",
        "        'changedFiles': ['src/**/*.cs', 'tests/**/*.cs']\n",
        "    },\n",
        "    'outputs': ['checklist', 'commands', 'code-suggestions']\n",
        "}\n",
        "\n",
        "agent_skill_path = repo / 'eng' / 'agent-skill.json'\n",
        "agent_skill_path.write_text(json.dumps(agent_skill, indent=2), encoding='utf-8')\n",
        "print(agent_skill_path.read_text(encoding='utf-8'))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Create concise team guidance\n",
        "\n",
        "A short, operational guidance file is easier to inject consistently than a long wiki page. This C# example emits the guidance text that a team could keep under `docs/TEAM_GUIDANCE.md`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "\n",
        "public static class TeamGuidancePrinter\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var guidance = string.Join(Environment.NewLine, new[]\n",
        "        {\n",
        "            \"# Team Guidance for C# Services\",\n",
        "            \"\",\n",
        "            \"## Architecture rules\",\n",
        "            \"- Keep controllers thin; move business logic into services.\",\n",
        "            \"- Use async for I/O-bound operations.\",\n",
        "            \"- Register dependencies through IServiceCollection.\",\n",
        "            \"\",\n",
        "            \"## Pull request checklist\",\n",
        "            \"- Run formatting before commit.\",\n",
        "            \"- Add or update unit tests for changed behavior.\",\n",
        "            \"- Document new endpoints in README.md.\"\n",
        "        });\n",
        "\n",
        "        Console.WriteLine(guidance);\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Write TEAM_GUIDANCE.md to disk\n",
        "\n",
        "This Python cell stores the concise guidance in the demo repo so it can be referenced by later validation steps."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "team_guidance = dedent('''\n",
        "# Team Guidance for C# Services\n",
        "\n",
        "## Architecture rules\n",
        "- Keep controllers thin; move business logic into services.\n",
        "- Use `async` for I/O-bound operations.\n",
        "- Register dependencies through `IServiceCollection`.\n",
        "\n",
        "## Pull request checklist\n",
        "- Run formatting before commit.\n",
        "- Add or update unit tests for changed behavior.\n",
        "- Document new endpoints in `README.md`.\n",
        "''').strip() + '\\n'\n",
        "\n",
        "team_guidance_path = repo / 'docs' / 'TEAM_GUIDANCE.md'\n",
        "team_guidance_path.write_text(team_guidance, encoding='utf-8')\n",
        "print(team_guidance_path.read_text(encoding='utf-8'))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Normalize checklist guidance into structured context\n",
        "\n",
        "The blog shows a Python script that converts a checklist into JSON. This C# version does the same so the workflow can consume structured rules instead of free-form text."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "using System.Linq;\n",
        "using System.Text.Json;\n",
        "\n",
        "public sealed class Rule\n",
        "{\n",
        "    public int id { get; set; }\n",
        "    public string text { get; set; } = string.Empty;\n",
        "    public bool required { get; set; }\n",
        "}\n",
        "\n",
        "public sealed class GuidancePayload\n",
        "{\n",
        "    public string skill { get; set; } = \"dotnet-team-workflow\";\n",
        "    public string category { get; set; } = \"pull-request\";\n",
        "    public Rule[] rules { get; set; } = Array.Empty<Rule>();\n",
        "}\n",
        "\n",
        "public static class Program\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var checklist = new[]\n",
        "        {\n",
        "            \"Run formatting before commit\",\n",
        "            \"Add or update unit tests\",\n",
        "            \"Document new endpoints in README.md\"\n",
        "        };\n",
        "\n",
        "        var payload = new GuidancePayload\n",
        "        {\n",
        "            rules = checklist.Select((item, index) => new Rule\n",
        "            {\n",
        "                id = index + 1,\n",
        "                text = item,\n",
        "                required = true\n",
        "            }).ToArray()\n",
        "        };\n",
        "\n",
        "        Console.WriteLine(JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true }));\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Save normalized skill context\n",
        "\n",
        "This Python cell writes a normalized context file to `eng/skill-context.json`. It captures durable architecture and workflow rules that can be reused across prompts."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "skill_context = {\n",
        "    'architecture': {\n",
        "        'controllerRule': 'Controllers delegate to services',\n",
        "        'asyncRule': 'Use async for I/O-bound operations',\n",
        "        'testingRule': 'Changed behavior requires unit tests'\n",
        "    },\n",
        "    'workflow': {\n",
        "        'preCommit': ['dotnet format', 'dotnet build', 'dotnet test'],\n",
        "        'prNotes': ['Update README for endpoint changes']\n",
        "    }\n",
        "}\n",
        "\n",
        "skill_context_path = repo / 'eng' / 'skill-context.json'\n",
        "skill_context_path.write_text(json.dumps(skill_context, indent=2), encoding='utf-8')\n",
        "print(skill_context_path.read_text(encoding='utf-8'))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Example service implementation aligned to team conventions\n",
        "\n",
        "This C# example mirrors the kind of service-layer pattern the workflow should encourage: thin orchestration, async I/O, and repository delegation."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System.Threading;\n",
        "using System.Threading.Tasks;\n",
        "\n",
        "public interface IOrderRepository\n",
        "{\n",
        "    Task<int> SaveAsync(string customerId, CancellationToken cancellationToken);\n",
        "}\n",
        "\n",
        "public sealed class InMemoryOrderRepository : IOrderRepository\n",
        "{\n",
        "    private int _nextId = 1000;\n",
        "\n",
        "    public Task<int> SaveAsync(string customerId, CancellationToken cancellationToken)\n",
        "    {\n",
        "        cancellationToken.ThrowIfCancellationRequested();\n",
        "        return Task.FromResult(_nextId++);\n",
        "    }\n",
        "}\n",
        "\n",
        "public sealed class OrderService\n",
        "{\n",
        "    private readonly IOrderRepository _repository;\n",
        "\n",
        "    public OrderService(IOrderRepository repository) => _repository = repository;\n",
        "\n",
        "    public Task<int> CreateAsync(string customerId, CancellationToken cancellationToken) =>\n",
        "        _repository.SaveAsync(customerId, cancellationToken);\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Validate the service example with a runnable demo\n",
        "\n",
        "This C# cell exercises the service so the pattern is not just static code. It demonstrates the expected call path from service to repository."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "using System.Threading;\n",
        "using System.Threading.Tasks;\n",
        "\n",
        "public interface IOrderRepository\n",
        "{\n",
        "    Task<int> SaveAsync(string customerId, CancellationToken cancellationToken);\n",
        "}\n",
        "\n",
        "public sealed class InMemoryOrderRepository : IOrderRepository\n",
        "{\n",
        "    private int _nextId = 1;\n",
        "\n",
        "    public Task<int> SaveAsync(string customerId, CancellationToken cancellationToken)\n",
        "    {\n",
        "        cancellationToken.ThrowIfCancellationRequested();\n",
        "        return Task.FromResult(_nextId++);\n",
        "    }\n",
        "}\n",
        "\n",
        "public sealed class OrderService\n",
        "{\n",
        "    private readonly IOrderRepository _repository;\n",
        "\n",
        "    public OrderService(IOrderRepository repository) => _repository = repository;\n",
        "\n",
        "    public Task<int> CreateAsync(string customerId, CancellationToken cancellationToken) =>\n",
        "        _repository.SaveAsync(customerId, cancellationToken);\n",
        "}\n",
        "\n",
        "public static class Program\n",
        "{\n",
        "    public static async Task Main()\n",
        "    {\n",
        "        var service = new OrderService(new InMemoryOrderRepository());\n",
        "        var orderId = await service.CreateAsync(\"customer-123\", CancellationToken.None);\n",
        "        Console.WriteLine($\"Created order id: {orderId}\");\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Standard repository validation script as C# output\n",
        "\n",
        "The blog includes a PowerShell validation script. To keep every code example in C#, this cell generates the script content as a string so the notebook can still produce the exact repo asset."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "\n",
        "public static class ValidationScriptEmitter\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var script = string.Join(Environment.NewLine, new[]\n",
        "        {\n",
        "            \"param(\",\n",
        "            \"    [string]$Solution = \\\"TeamApp.sln\\\"\",\n",
        "            \")\",\n",
        "            \"\",\n",
        "            \"dotnet format $Solution --verify-no-changes\",\n",
        "            \"if ($LASTEXITCODE -ne 0) { throw \\\"Formatting check failed.\\\" }\",\n",
        "            \"\",\n",
        "            \"dotnet build $Solution --nologo\",\n",
        "            \"if ($LASTEXITCODE -ne 0) { throw \\\"Build failed.\\\" }\",\n",
        "            \"\",\n",
        "            \"dotnet test $Solution --no-build --nologo\",\n",
        "            \"if ($LASTEXITCODE -ne 0) { throw \\\"Tests failed.\\\" }\",\n",
        "            \"\",\n",
        "            \"Write-Host \\\"Repository workflow checks passed.\\\"\"\n",
        "        });\n",
        "\n",
        "        Console.WriteLine(script);\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Write the validation script to the repo\n",
        "\n",
        "This Python cell persists `eng/validate-workflow.ps1` so the demo repo contains the same local validation action described in the post."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "validate_workflow_ps1 = dedent('''\n",
        "param(\n",
        "    [string]$Solution = \"TeamApp.sln\"\n",
        ")\n",
        "\n",
        "dotnet format $Solution --verify-no-changes\n",
        "if ($LASTEXITCODE -ne 0) { throw \"Formatting check failed.\" }\n",
        "\n",
        "dotnet build $Solution --nologo\n",
        "if ($LASTEXITCODE -ne 0) { throw \"Build failed.\" }\n",
        "\n",
        "dotnet test $Solution --no-build --nologo\n",
        "if ($LASTEXITCODE -ne 0) { throw \"Tests failed.\" }\n",
        "\n",
        "Write-Host \"Repository workflow checks passed.\"\n",
        "''').strip() + '\\n'\n",
        "\n",
        "validate_script_path = repo / 'eng' / 'validate-workflow.ps1'\n",
        "validate_script_path.write_text(validate_workflow_ps1, encoding='utf-8')\n",
        "print(validate_script_path.read_text(encoding='utf-8'))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Build a PR checklist from changed files\n",
        "\n",
        "This example turns changed file paths into a short checklist. It demonstrates how a workflow can produce actionable output instead of generic advice."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "using System.Collections.Generic;\n",
        "using System.Linq;\n",
        "\n",
        "public static class PullRequestChecklistBuilder\n",
        "{\n",
        "    public static IReadOnlyList<string> Build(IEnumerable<string> changedFiles)\n",
        "    {\n",
        "        var files = changedFiles.ToArray();\n",
        "        var items = new List<string> { \"Run dotnet format\", \"Run solution tests\" };\n",
        "\n",
        "        if (files.Any(f => f.Contains(\"Controllers\")))\n",
        "            items.Add(\"Document endpoint changes in README.md\");\n",
        "\n",
        "        if (files.Any(f => f.Contains(\"src/\")))\n",
        "            items.Add(\"Confirm unit tests cover changed behavior\");\n",
        "\n",
        "        return items;\n",
        "    }\n",
        "}\n",
        "\n",
        "public static class Program\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var changedFiles = new[]\n",
        "        {\n",
        "            \"src/Controllers/OrdersController.cs\",\n",
        "            \"src/Services/OrderService.cs\",\n",
        "            \"tests/OrderServiceTests.cs\"\n",
        "        };\n",
        "\n",
        "        var checklist = PullRequestChecklistBuilder.Build(changedFiles);\n",
        "        foreach (var item in checklist)\n",
        "        {\n",
        "            Console.WriteLine($\"- {item}\");\n",
        "        }\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Simulate the request-response sequence\n",
        "\n",
        "The post also shows a sequence where Visual Studio passes a prompt and changed files to the workflow, which then reads repo guidance and returns suggestions. This C# example prints that interaction as a simple trace."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "\n",
        "public static class SequenceSimulation\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var lines = new[]\n",
        "        {\n",
        "            \"Dev -> VS: Prepare this PR\",\n",
        "            \"VS -> Skill: Provide prompt + changed files\",\n",
        "            \"Skill -> Repo: Read TEAM_GUIDANCE.md and solution metadata\",\n",
        "            \"Repo -> Skill: Rules, checklist, conventions\",\n",
        "            \"Skill -> VS: Suggested commands, checklist, code edits\",\n",
        "            \"VS -> Dev: Team-specific workflow guidance\"\n",
        "        };\n",
        "\n",
        "        foreach (var line in lines)\n",
        "        {\n",
        "            Console.WriteLine(line);\n",
        "        }\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Reusable prompt template as a repo asset\n",
        "\n",
        "A reusable prompt pattern helps developers invoke the workflow consistently. This C# example emits the prompt template text that can be stored under `docs/prompt-template.md`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "\n",
        "public static class PromptTemplatePrinter\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var prompt = string.Join(Environment.NewLine, new[]\n",
        "        {\n",
        "            \"# Skill Prompt Template\",\n",
        "            \"\",\n",
        "            \"You are assisting with a C# repository in Visual Studio.\",\n",
        "            \"\",\n",
        "            \"Apply these team rules:\",\n",
        "            \"- Prefer services over controller logic.\",\n",
        "            \"- Recommend dotnet format, build, and test before PR.\",\n",
        "            \"- If endpoints change, remind the developer to update README.md.\",\n",
        "            \"\",\n",
        "            \"Return:\",\n",
        "            \"1. A short checklist\",\n",
        "            \"2. Any suggested commands\",\n",
        "            \"3. Minimal code changes aligned to the rules\"\n",
        "        });\n",
        "\n",
        "        Console.WriteLine(prompt);\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Save the reusable prompt template\n",
        "\n",
        "This Python cell writes the prompt template to the demo repo so it can be referenced alongside the guidance and context files."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "prompt_template = dedent('''\n",
        "# Skill Prompt Template\n",
        "\n",
        "You are assisting with a C# repository in Visual Studio.\n",
        "\n",
        "Apply these team rules:\n",
        "- Prefer services over controller logic.\n",
        "- Recommend `dotnet format`, build, and test before PR.\n",
        "- If endpoints change, remind the developer to update `README.md`.\n",
        "\n",
        "Return:\n",
        "1. A short checklist\n",
        "2. Any suggested commands\n",
        "3. Minimal code changes aligned to the rules\n",
        "''').strip() + '\\n'\n",
        "\n",
        "prompt_template_path = repo / 'docs' / 'prompt-template.md'\n",
        "prompt_template_path.write_text(prompt_template, encoding='utf-8')\n",
        "print(prompt_template_path.read_text(encoding='utf-8'))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Add clarification behavior for missing inputs\n",
        "\n",
        "One of the highest-value conventions in the post is to ask clarifying questions before generating code when required inputs are missing. This C# example validates a request and returns missing details."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "using System;\n",
        "using System.Collections.Generic;\n",
        "\n",
        "public sealed class EndpointRequest\n",
        "{\n",
        "    public string? Route { get; set; }\n",
        "    public string? AuthModel { get; set; }\n",
        "    public string? RepositoryInterface { get; set; }\n",
        "    public string? TestFramework { get; set; }\n",
        "    public string? TargetProject { get; set; }\n",
        "}\n",
        "\n",
        "public static class ClarificationEngine\n",
        "{\n",
        "    public static IReadOnlyList<string> GetMissingInputs(EndpointRequest request)\n",
        "    {\n",
        "        var missing = new List<string>();\n",
        "\n",
        "        if (string.IsNullOrWhiteSpace(request.Route)) missing.Add(\"endpoint route missing\");\n",
        "        if (string.IsNullOrWhiteSpace(request.AuthModel)) missing.Add(\"auth model missing\");\n",
        "        if (string.IsNullOrWhiteSpace(request.RepositoryInterface)) missing.Add(\"repository interface missing\");\n",
        "        if (string.IsNullOrWhiteSpace(request.TestFramework)) missing.Add(\"test framework expectation unclear\");\n",
        "        if (string.IsNullOrWhiteSpace(request.TargetProject)) missing.Add(\"target project not specified\");\n",
        "\n",
        "        return missing;\n",
        "    }\n",
        "}\n",
        "\n",
        "public static class Program\n",
        "{\n",
        "    public static void Main()\n",
        "    {\n",
        "        var request = new EndpointRequest\n",
        "        {\n",
        "            Route = \"/orders\",\n",
        "            AuthModel = null,\n",
        "            RepositoryInterface = \"IOrderRepository\",\n",
        "            TestFramework = null,\n",
        "            TargetProject = \"src/TeamApp.Api\"\n",
        "        };\n",
        "\n",
        "        var missing = ClarificationEngine.GetMissingInputs(request);\n",
        "        foreach (var item in missing)\n",
        "        {\n",
        "            Console.WriteLine($\"Clarify: {item}\");\n",
        "        }\n",
        "    }\n",
        "}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Validate repo assets and inspect the generated layout\n",
        "\n",
        "This cell checks that the expected files exist and prints a compact inventory. It gives you a quick way to verify the bounded workflow assets are present."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "expected_files = [\n",
        "    repo / 'docs' / 'TEAM_GUIDANCE.md',\n",
        "    repo / 'docs' / 'prompt-template.md',\n",
        "    repo / 'eng' / 'agent-skill.json',\n",
        "    repo / 'eng' / 'skill-context.json',\n",
        "    repo / 'eng' / 'validate-workflow.ps1',\n",
        "]\n",
        "\n",
        "status = {str(path.relative_to(repo)): path.exists() for path in expected_files}\n",
        "print(json.dumps(status, indent=2))\n",
        "\n",
        "print('\\nRepo tree:')\n",
        "for path in sorted(repo.rglob('*')):\n",
        "    if path.is_file():\n",
        "        print('-', path.relative_to(repo))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Test realistic prompts and expected workflow outputs\n",
        "\n",
        "The post recommends testing with backlog-shaped prompts rather than toy examples. This cell defines a small set of realistic prompts and the kind of bounded outcome each should produce."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "realistic_prompts = [\n",
        "    {\n",
        "        'prompt': 'Prepare this PR for review and tell me what I missed.',\n",
        "        'expected': ['short checklist', 'recommended commands', 'PR notes']\n",
        "    },\n",
        "    {\n",
        "        'prompt': 'Add a new endpoint for order creation using our service pattern.',\n",
        "        'expected': ['clarifying questions if needed', 'service-oriented code suggestions', 'test reminders']\n",
        "    },\n",
        "    {\n",
        "        'prompt': 'Validate whether these changes meet team conventions before I open the PR.',\n",
        "        'expected': ['convention check summary', 'missing items', 'commands to run']\n",
        "    },\n",
        "    {\n",
        "        'prompt': 'Refactor this controller logic into the service layer.',\n",
        "        'expected': ['minimal code changes', 'service extraction guidance', 'unit test reminder']\n",
        "    }\n",
        "]\n",
        "\n",
        "print(json.dumps(realistic_prompts, indent=2))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Guardrails and ownership record\n",
        "\n",
        "A practical workflow needs boundaries: approved repositories, allowed actions, and a rollback path. This cell creates a lightweight ownership record that can be versioned like any other engineering asset."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "ownership_record = {\n",
        "    'owner': 'Developer Experience Team',\n",
        "    'version': '0.1.0',\n",
        "    'reviewCadence': 'monthly',\n",
        "    'approvedRepositories': ['TeamApp'],\n",
        "    'approvedActions': ['read guidance', 'inspect changed files', 'recommend commands', 'suggest code'],\n",
        "    'rollbackPath': 'Revert guidance/context files in a pull request',\n",
        "    'nonGoals': [\n",
        "        'Do not make architecture decisions without developer input',\n",
        "        'Do not modify deployment files',\n",
        "        'Do not infer security requirements if they are missing',\n",
        "        'Do not perform external system actions without explicit approval'\n",
        "    ]\n",
        "}\n",
        "\n",
        "ownership_path = repo / 'eng' / 'ownership-record.json'\n",
        "ownership_path.write_text(json.dumps(ownership_record, indent=2), encoding='utf-8')\n",
        "print(ownership_path.read_text(encoding='utf-8'))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Summary\n",
        "\n",
        "This notebook encoded a bounded team workflow using repo-backed assets: guidance, structured context, a prompt template, a validation script, and small C# examples for checklist generation and clarification behavior. The emphasis is on consistency, local validation, and explicit guardrails rather than autonomous behavior.\n",
        "\n",
        "## Next Steps\n",
        "\n",
        "1. Pick one workflow to pilot first: PR prep, endpoint scaffolding, validation checks, or refactoring.\n",
        "2. Keep guidance short and authoritative, then version it in pull requests.\n",
        "3. Test with real prompts and failure cases, then fix the asset rather than repeatedly rewriting prompts.\n",
        "4. Keep human approval mandatory for architecture, security-sensitive changes, infrastructure, and production-impacting decisions."
      ]
    }
  ]
}