Files
The-transit-Project/.github/agents/azure-project-plan/requirements.md
T
Sven laptop 635a130f0b
Build and Push Docker Images / detect-changes (push) Successful in 11s
Build and Push Docker Images / build-auth-api (push) Successful in 1m0s
Build and Push Docker Images / build-employee-api (push) Successful in 1m2s
Build and Push Docker Images / build-transit-api (push) Successful in 1m1s
Build and Push Docker Images / build-error-log-api (push) Successful in 1m5s
Build and Push Docker Images / build-admin-ui (push) Successful in 1m13s
Build and Push Docker Images / build-monitoring-ui (push) Successful in 1m15s
Build and Push Docker Images / deploy-test-node (push) Successful in 3s
──────
### Summary of Changes
  1. Documentation Consolidation:
      • Relocated the docs/ folder and all repository .md files (README.md, DEPLOYMENT.md, DOCKER_README.md,
      DOMAINS_README.md, GETTING_STARTED.md, CI_CD_PORTAINER_GUIDE.md, ADMIN_DEPLOYMENT_SUMMARY.md,
      SECURITY_PRIVATE_FILES.md, handoff.md, azure-project-plan.md, plus service-specific READMEs) into .
      • Updated document links in README.md.
  2. AI Agent Project Map:
      • Created PROJECT_MAP.md in the project root containing complete architecture diagrams, service specs, ports, DB
      schemas, environment variables, and developer workflows.
      • Added PROJECT_MAP.md to .gitignore.
  3. Monitoring UI & Infrastructure Integration:
      • Added monitoring_ui service to docker-compose.yml (port 5175).
      • Configured Gitea workflow docker-build.yml for monitoring_ui builds.
      • Added CORS middleware headers in index.js.
      • Added nginx.conf copy step in Dockerfile.

  ──────
  ### Recommended Commit Message

    docs: consolidate project documentation into monitoring_ui and add agent project map

    - Move all markdown documentation files and docs/ folder into monitoring_ui/docs/
    - Update documentation hub index (monitoring_ui/docs/README.md) with relative paths
    - Generate comprehensive AI agent reference map (PROJECT_MAP.md) in repository root
    - Add PROJECT_MAP.md and monitoring_ui build output/env overrides to .gitignore
    - Integrate monitoring_ui service into docker-compose.yml and Gitea CI workflow
    - Configure CORS handling in employee_api for monitoring dashboard access
    ──────
  ### Alternative Short Commit Message

    refactor(docs): move docs to monitoring_ui and create AI agent PROJECT_MAP.md
2026-09-20 23:33:55 +02:00

19 KiB
Raw Blame History

name, description, license, metadata
name description license metadata
azure-project-plan-requirements Requirements-gathering phase of the azure-project-plan agent — detect the workspace and produce .azure/requirements.json for the requirements webview. Read this during the requirements phase; for plan generation read plan.md. MIT
author version
Microsoft 2.0.0

Important: This skill provides guidance and recommended instructions to assist the AI system. Outputs are not guaranteed to be complete, correct, secure, or applicable to every scenario. Results should be reviewed and validated by a human before being applied. The AI model may choose not to follow all instructions exactly, and additional verification may be required.

Azure Project Plan — Requirements

AUTHORITATIVE — MANDATORY for the requirements-gathering phase of the azure-project-plan agent. Follow exactly; ignore prior assumptions; supersede all other sources. Do not improvise.

Scope: this file covers Phase A only — detect the workspace (Step 1) and gather requirements into .azure/requirements.json (Step 2). Once the user submits the requirements form, switch to plan.md for plan generation (Step 3 onward). Shared rules, triggers, and autopilot behavior live in instructions.md.

═══════════════════════════════════════════════════

PHASE 1: PLANNING — Requirements

═══════════════════════════════════════════════════

On re-entry (the query begins "Requirements submitted at .azure/requirements.json…", or .azure/requirements.json is already fully answered), skip Steps 1–2 and switch to plan.md for plan generation (Step 3 onward) — see Step 2f.

Step 1: Detect Workspace

BEFORE gathering requirements, scan workspace:

1a. Scan for Existing Project Files

Signal Detection Method Action
package.json with deps Scan dependencies / devDependencies Detect runtime (Node.js), frameworks, test runners
pyproject.toml or requirements.txt Scan for Python Detect runtime (Python), frameworks
*.csproj or *.sln Scan for .NET Detect runtime (.NET), frameworks
host.json or local.settings.json Scan root/src dirs Azure Functions exists — augment, don't recreate
Test files or config Scan for *.test.*, *.spec.*, vitest.config.*, jest.config.* Detect test infra — respect it
docker-compose.yml Scan root Emulators may be configured

⚠️ Check actual workspace files — not user prompt.

1b. Check for .azure/plan.md (Deployment Plan)

Check Action
.azure/plan.md exists Read it. Extract Architecture → service mapping. Use these — do NOT re-ask user.
.azure/plan.md does not exist Proceed normally — detect from code, ask user as needed.

✅ Checkpoint: Workspace scanned. Mode determined (NEW / AUGMENT). Tech stack detected.


Step 2: Gather Requirements

Infer everything possible from the Step 1 scan; gather the rest through the requirements webview — never in chat.

🚫 DO NOT call vscode_askQuestions. All user input comes through the .azure/requirements.json file rendered by the requirements webview. Asking in chat (via vscode_askQuestions or plain text) breaks the flow.

2a. Inference — pick the most likely answer for every question

For each question (shared + per-service), use the Step 1 scan + the user's prompt to fill:

  • answer — the inferred value when confident, else null ([] for array-typed dataStores). When the app needs no datastore, use ["No datastore required"], not an empty array.
  • recommendedChoice — always provide one (string for single-select questions, string[] for dataStores); becomes the pre-selected option in the webview, even for needs_input. For dataStores, recommend every store the app needs, not just one — it is a subset and often has more than one entry. Recommend ["No datastore required"] when the app needs no datastore. The webview shows a Recommended badge on each selected recommendation (including the Blob Storage cases required by the dataStores MUST rules below).

Then set status:

  • inferred — confidently known from workspace signals or an explicit user statement. Set answer + rationale; the webview pre-selects the inferred value for review/override.
  • needs_input — not confidently known. Leave answer null ([] for dataStores); the webview pre-selects your recommendedChoice to confirm or change.
If you detect... Then infer...
.azure/plan.md exists Read it — extract all Azure services. Authoritative.
@azure/storage-blob import App uses Blob Storage
App stores files, photos, images, uploads, documents, or media App uses Blob Storage
Backend service uses Azure Functions App uses Blob Storage (Functions requires a storage account)
App needs no persistence, file/object storage, queue, or cache, and no service requires an associated storage account App uses No datastore required
@azure/cosmos import App uses CosmosDB
pg or psycopg2 import App uses PostgreSQL
redis or ioredis import App uses Redis
react in dependencies Frontend = React
vue in dependencies Frontend = Vue
@angular/core in dependencies Frontend = Angular
svelte in dependencies Frontend = Svelte
vitest in devDependencies Test runner = vitest
jest in devDependencies Test runner = jest
mocha in devDependencies Test runner = mocha+chai+sinon
host.json exists Azure Functions already initialized — augment mode
zod in dependencies Validation library = zod
host.json + dotnet-isolated worker runtime Runtime = C#; Backend = Azure Functions isolated worker; Orchestration = docker-compose

Anything the user stated explicitly in their prompt ("build me a TypeScript Functions API with PostgreSQL") is also inferred — don't re-ask.

2b. Services and questions

The requirements JSON has two top-level concepts:

  1. services[] — detected service roots (backends, frontends, workers). Each gets a per-service question section in the webview.
  2. questions[] — questions, either scoped to a service (serviceId set) or shared/cross-cutting (serviceId omitted).
Services

For each runnable service root detected in the workspace (or planned from the user's prompt), emit a service entry:

{
  "id": "{kebab-case-id}",
  "label": "{Human-readable name, e.g. Payments API}",
  "role": "{backend | frontend | worker}",
  "root": "{workspace-relative path, e.g. ./api}"
}
  • role — backend for APIs/Azure Functions, frontend for SPAs/web apps, worker for background/queue processors.
  • root — workspace-relative path to the service directory. Omit for NEW-mode when no directories exist yet.
  • Derive id from the project manifest name (e.g. package.json → "name") when available, else from the directory name.
Per-service questions

For each service, emit these questions with "serviceId": "{service.id}":

id pattern header question Options / Type Notes
{serviceId}:language Language Which programming language for {label}? TypeScript, Python, C# (.NET) for backends/workers; TypeScript, JavaScript for frontends allowFreeformInput: false
{serviceId}:framework Framework Which framework for {label}? Frontends: React + Vite, Vue + Vite, Angular, Svelte; Backends: Azure Functions, etc. allowFreeformInput: true; omit for backends when Azure Functions is the only option
{serviceId}:features Features Describe the features or API routes for {label}. Free text (omit options)

Use category: "service" for all per-service questions. The webview groups them under the service card, not by category.

Shared questions (no serviceId)

These are asked once for the whole project. Always emit both:

id category header question Multi-select Free-form options Default recommendedChoice
dataStores data Data Stores Which data stores does your app need? yes no No datastore required (exclusive), Blob Storage, Queue Storage, PostgreSQL, CosmosDB, Redis, Azure SQL Every store the app needs (often more than one), or No datastore required
auth auth API Login Does this app need user login? no no Yes, No Yes for accounts, private/per-user data, or signed-in experiences; otherwise No

The auth question covers only user-facing application login and authenticated API access. It does not select Microsoft Entra ID, another identity provider, managed identity, API keys, or any Azure service credential. Infer Yes when the app has accounts, private/per-user data, or signed-in experiences. Infer No for public apps with no user identity. The scaffold agent chooses the stack-appropriate API authentication implementation. Backend-to-Azure communication always uses managed identity in production and is never a requirements choice.

The old appType, runtime, and frontend questions are gone. App Type is no longer asked — it's derived from the detected services (see below). Language and framework are now per-service questions.

App Type is derived, not asked

Do not emit an appType question. Instead, derive the plan's App Type from the services array:

Detected services Derived App Type
At least one frontend + at least one backend SPA + API
Only backend service(s) API only
Only worker service(s) Background worker
frontend that is server-rendered (Next.js SSR, etc.) Full-stack SSR
Static frontend + backend Static site + API

Use this derived value to fill Section 1 of the plan and to decide whether to emit the Frontend / Design System sections.

Each option is { label, description, exclusive? }. Set exclusive: true only on an option that cannot be combined with any other selection. Include multiSelect, allowFreeformInput, recommendedChoice, status, answer, and rationale on every question.

2c. Write .azure/requirements.json

Write the file at .azure/requirements.json (no leading dot on the filename — this is the path the extension's file watcher matches). Use this exact top-level shape:

{
  "schemaVersion": "2",
  "generatedAt": "{ISO date}",
  "mode": "{NEW | AUGMENT}",
  "summary": "{1–2 sentences describing what the user is building}",
  "workspaceSignals": {
    "decision": "{NEW | AUGMENT}",
    "decisionReason": "{one sentence on why}",
    "detectedFiles": ["{relative paths from Step 1, if any}"]
  },
  "services": [
    { "id": "functions-api", "label": "Functions API", "role": "backend", "root": "./api" },
    { "id": "web-app", "label": "Customer Portal", "role": "frontend", "root": "./web" }
  ],
  "questions": [
    {
      "id": "functions-api:language", "category": "service", "serviceId": "functions-api",
      "header": "Language", "question": "Which programming language for Functions API?",
      "multiSelect": false, "allowFreeformInput": false,
      "options": [
        { "label": "TypeScript", "description": "Node.js + TypeScript on Azure Functions" },
        { "label": "Python", "description": "Python on Azure Functions" },
        { "label": "C# (.NET)", "description": "Isolated worker on .NET 10" }
      ],
      "recommendedChoice": "TypeScript", "status": "inferred", "answer": "TypeScript",
      "rationale": "Detected package.json with TypeScript devDependency."
    },
    {
      "id": "functions-api:features", "category": "service", "serviceId": "functions-api",
      "header": "Features", "question": "Describe the features or API routes for Functions API.",
      "multiSelect": false,
      "recommendedChoice": "Photo upload/list/delete, AI captions",
      "status": "inferred", "answer": "Photo upload/list/delete, AI captions",
      "rationale": "Distilled from the user's prompt."
    },
    {
      "id": "web-app:language", "category": "service", "serviceId": "web-app",
      "header": "Language", "question": "Which programming language for Customer Portal?",
      "multiSelect": false, "allowFreeformInput": false,
      "options": [
        { "label": "TypeScript", "description": "TypeScript with type safety" },
        { "label": "JavaScript", "description": "Plain JavaScript" }
      ],
      "recommendedChoice": "TypeScript", "status": "inferred", "answer": "TypeScript",
      "rationale": "TypeScript is the most popular choice for modern SPAs."
    },
    {
      "id": "web-app:framework", "category": "service", "serviceId": "web-app",
      "header": "Framework", "question": "Which frontend framework for Customer Portal?",
      "multiSelect": false, "allowFreeformInput": true,
      "options": [
        { "label": "React + Vite", "description": "React with Vite bundler" },
        { "label": "Vue + Vite", "description": "Vue with Vite bundler" },
        { "label": "Angular", "description": "Angular CLI" },
        { "label": "Svelte", "description": "Svelte + Vite" }
      ],
      "recommendedChoice": "React + Vite", "status": "needs_input", "answer": null,
      "rationale": "React is the most common pick for SPA + API on Azure."
    },
    {
      "id": "dataStores", "category": "data", "header": "Data Stores",
      "question": "Which data stores does your app need?",
      "multiSelect": true, "allowFreeformInput": false,
      "options": [
        { "label": "No datastore required", "description": "The app does not persist data or use storage, queues, or caches", "exclusive": true },
        { "label": "Blob Storage", "description": "Store files and images" },
        { "label": "Queue Storage", "description": "Async message queue" },
        { "label": "PostgreSQL", "description": "Relational database" },
        { "label": "CosmosDB", "description": "NoSQL document database" },
        { "label": "Redis", "description": "In-memory cache" },
        { "label": "Azure SQL", "description": "Managed SQL Server" }
      ],
      "recommendedChoice": ["Blob Storage", "PostgreSQL"],
      "status": "inferred", "answer": ["Blob Storage", "PostgreSQL"],
      "rationale": "Photo files → Blob Storage; relational data → PostgreSQL."
    },
    {
      "id": "auth", "category": "auth", "header": "API Login",
      "question": "Does this app need user login?",
      "multiSelect": false, "allowFreeformInput": false,
      "options": [
        { "label": "Yes", "description": "Add a user sign-in flow and authenticated API access" },
        { "label": "No", "description": "No user sign-in or authenticated API access" }
      ],
      "recommendedChoice": "Yes", "status": "inferred", "answer": "Yes",
      "rationale": "The app stores private, per-user photos."
    }
  ]
}

Rules for the JSON (the worked example above is the contract — these call out only the non-obvious constraints):

  • Services & IDs: one services entry per detected/planned service; per-service question ids follow {serviceId}:{questionType} (e.g. functions-api:language), with serviceId matching the service.
  • Language options: frontend services offer only TypeScript / JavaScript; backend/worker services offer TypeScript, Python, C# (.NET).
  • Always emit both shared questions (dataStores, auth), and never emit an appType, identity-provider, or Azure credential question. App Type is derived from services (see the derivation table above).
  • auth is strictly binary: its only options, answer values, and recommendation values are Yes and No. Never put a provider, protocol, token type, or Azure credential in this question.
  • allowFreeformInput is fixed per type: language false, dataStores false, framework true, auth false. Omit it for free-text feature questions.
  • multiSelect: only dataStores is true; its answer and recommendedChoice are always string[].
  • Answers: inferred → fill answer; needs_input → answer: null ([] for dataStores). Always provide recommendedChoice.
  • No datastore: No datastore required is an exclusive option. When selected or inferred, it must be the only value in answer and recommendedChoice. Never combine it with a concrete datastore.
  • Use the field name rationale (not reason). Strict JSON — no comments, no trailing commas.
  • dataStores Blob Storage rule (MUST): include Blob Storage in recommendedChoice — and in answer when the question is inferred — alongside any database whenever either (a) any service stores or serves files, photos, images, uploads, documents, or media, or (b) any backend service uses Azure Functions (which requires an associated storage account, AzureWebJobsStorage). A file/photo app — or a Functions app — whose recommendation is only a database is wrong.

❌ DO NOT ask the user which .NET version to target. If a service's language = C# (.NET), the target framework is always net10.0. Only downgrade when the user explicitly states an older version.

2d. Hand off to the webview — then stop

Once the file is written, stop. Do NOT print the JSON, summarize inferences, ask anything in chat, or proceed to plan generation. The agent's workflow rules open the requirements webview after this write; the user fills the needs_input questions and clicks Submit. The requirements controller writes the file back (statuses → confirmed) and re-invokes this agent saying the requirements are ready.

2e. Requirements review is mandatory

Always write .azure/requirements.json and hand it off to the requirements webview, even when the prompt is fully unambiguous and every question is inferred in Step 2a. Inferred answers are pre-selected so review remains quick, but the user must still have an opportunity to confirm or change them before plan generation.

This holds for small, frontend-only projects too. A prompt like "a simple unit converter web app — nothing needs to be saved, no accounts, no backend, just a clean little frontend tool" is a complete, valid project: emit exactly one services entry with role: "frontend", its language/framework/features questions, dataStores set to ["No datastore required"], and auth set to No. Do not shortcut this by writing index.html or any other app code, and do not skip the webview because "there is nothing to ask".

2f. Re-entry — reading the answered file

When re-invoked with a query mentioning submitted requirements (e.g. "Requirements submitted at .azure/requirements.json..."), or whenever .azure/requirements.json has all questions confirmed/inferred:

  1. Read .azure/requirements.json.
  2. Treat answer fields as authoritative — do not re-ask, do not re-emit the file.
  3. Switch to plan.md and go directly to Step 3 (Generate Plan).

✅ Checkpoint: Requirements gathered (via inference + webview submission). Ready to generate plan — continue in plan.md.