### 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
19 KiB
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.
Artifact Generation
Cross-cutting rules, step sequence, and assembly protocols for generating local development configuration files from an approved plan.
Reading the Plan
The plan's tables drive all generation:
| Plan Section | What It Drives |
|---|---|
| Services table | Which services get launch.json/tasks.json entries. |
| Emulators table | Which emulator compose services to generate. |
| Orchestrator table | The container runtime (Docker/Podman) and the Compose Command (docker compose / podman compose) to write into every emulator/migration task. |
| Migrations table | Which migration compose services to generate. |
| API Test Collections table | Which API test scripts to generate. |
| Convenience Scripts table | Which convenience scripts to generate. |
Container runtime is a plan value — never hard-code
docker compose. Read the Compose Command cell from the plan's Orchestrator table and use it verbatim for every generated Compose invocation (Start Emulators task, migration task, convenience scripts, validation, teardown). It isdocker composeby default andpodman composewhen the plan selected Podman. The generateddocker-compose.ymlitself is identical for either engine — only the command that drives it changes. In the examples throughout these references,docker composestands in for the plan's Compose Command; substitutepodman composewhen the plan says Podman.
Targeted Resolution
The plan provides high-level intent. For implementation details, perform targeted resolution scans of the workspace:
- Migration details — Scan for migration directory path, existing migration scripts, connection env var names. See migrations.md.
- API endpoints — Parse function definitions or route handlers to get specific endpoint names, methods, routes, auth levels.
- Connection string keys — Check
local.settings.json,.env, or app config for existing key names. - Existing config — Check for existing
.vscode/launch.json,.vscode/tasks.json,docker-compose.ymlto determine merge vs create. - Framework details — For frontend SPAs, detect the specific framework (Vite, Next.js, Angular, CRA) and dev server port from config files.
- TypeScript source maps — For TypeScript services, verify
tsconfig.jsonhas"sourceMap": trueincompilerOptions. Without it, breakpoints in.tsfiles appear as unverified. Seeruntimes/node.md§ Debugger Properties.
Generation Steps
For each service in the plan's Services table (where Generate is checked), generate the following artifacts in order. The plan specifies WHAT to generate; the reference files linked below specify HOW.
| # | Action | Reference |
|---|---|---|
| 1 | Generate docker-compose — For each emulator in the plan's Emulators table, load the emulator reference and assemble the docker-compose service block. If migrations are checked, add healthcheck and migration service. | emulators/, migrations.md |
| 2 | Generate VS Code debug config — Assemble launch.json and tasks.json entries from the project-type and runtime references. For multi-service workspaces, generate compound configuration. |
generate.md § Source Ownership, project-types/, runtimes/, multi-service.md |
| 3 | Generate VS Code workspace config — Assemble .vscode/extensions.json and .vscode/settings.json from project-type and runtime references. Add emulator data directory exclusions. |
generate.md § VS Code Extension Recommendations, generate.md § VS Code Workspace Settings |
| 4 | Configure connection strings — Update local.settings.json, .env, or app config with emulator connection strings. Never overwrite existing values. |
project-types/{type}.md § Connection Strings, emulators/{name}.md § Required App Environment Variables |
| 5 | Generate convenience scripts — For each checked script in the plan's Convenience Scripts table, add to the project's native script runner. | runtimes/{rt}.md § Convenience Scripts |
| 6 | Generate migrations — If the plan's Migrations table has checked rows, do targeted resolution for migration details, then generate the docker-compose migration service. | migrations.md |
| 7 | Generate API test collections — If the plan's API Test Collections table has checked rows, do targeted resolution for endpoints/triggers, then generate test scripts. | api-test-collections.md |
Podman emulator certification. When the plan's container runtime is Podman, each emulator's reference file declares its Podman status under
## Container Runtime Support. Azurite and PostgreSQL are certified. For any emulator not marked Podman-certified, emit a⚠️ LIMITED SUPPORT: Emulator "{name}" is not yet certified for Podmanwarning (per limited-support.md) and generate a best-effort compose service anyway — do not silently swap the runtime back to Docker.
Dependency Availability
⚠️ Do not assume CLI tools or packages are installed in the target project.
Before writing any script or task command that invokes a CLI tool (e.g., rimraf, concurrently, cross-env):
- Check — Verify the tool is already a project dependency.
- Add dependency — Add it as a project dev dependency. This ensures it is version-locked and works consistently across all machines.
- Ask if uncertain — Use
ask_userif the tool is expensive, opinionated, or has multiple alternatives.
Local Credentials
⚠️ Never inline a literal credential into a task or a compose file. Declare local credentials once in a workspace-root
.envand reference them through Compose${VAR}interpolation everywhere else.
| Correct | Do not generate |
|---|---|
Compose ${VAR} interpolation from .env |
A literal credential inlined into a task or compose file |
A concrete credential literal is rewritten by secret-redaction filters, and a masked value that
begins with * is a fatal YAML parse error — YAML reads a leading * as an alias reference, so the
whole compose file stops parsing.
Interpolation only resolves if the variable is actually defined: Compose reads ${...} from .env
or the shell environment, never from a service's own environment: block. Whenever a generated
file references a variable — a compose service, a host task, or a connection string — .env must
declare every variable it needs, or the value silently becomes an empty string.
⛔
.gitignoremust list.envbefore you create it. A credential that reaches a commit is compromised and has to be rotated — deleting it in a later commit leaves it in history, in every clone, and in every fork. Private repositories are no exception. If the project has no.gitignore, or has one that omits.env, fix that first.
See emulators/{name}.md § Required App Environment Variables for the per-emulator variable set.
VS Code Debug & Task Configuration
Assemble .vscode/launch.json and .vscode/tasks.json by combining properties from the detected project type and runtime references. Use the source ownership table below to determine which file provides each property.
Source Ownership
| Concern | Server-side project source | Browser SPA source |
|---|---|---|
Debugger type (node, coreclr) |
runtimes/{rt}.md § Debugger Properties |
project-types/frontend-spa/debug-adapters/{adapter}.md |
| Debug port | runtimes/{rt}.md § Debugger Properties |
N/A (uses dev server URL) |
Request mode (attach / launch) |
project-types/{type}.md § Runtime Wiring |
project-types/frontend-spa/frontend-spa.md § Runtime Wiring |
| Top-level startup task (type, command, problem matcher) | project-types/{type}.md § VS Code Task Configuration |
project-types/frontend-spa/frontend-spa.md § VS Code Task Configuration |
| Build chain tasks (install, clean, watch) | runtimes/{rt}.md § Build Chain |
N/A (dev server handles compilation) |
Runtime-specific launch properties (outFiles, processName) |
runtimes/{rt}.md § Debugger Properties |
N/A |
| Compound configuration | multi-service.md § Compound Debug Configuration | multi-service.md § Compound Debug Configuration |
Working directory (cwd) rules |
generate.md § Working Directory (cwd) Rules |
generate.md § Working Directory (cwd) Rules |
Task runOptions rules |
generate.md § Task runOptions Rules |
generate.md § Task runOptions Rules |
Emulator startup task (Start Emulators) |
runtimes/{rt}.md § Build Chain |
N/A (backend service owns emulators) |
project-types/{type}.md§ VS Code Task Configuration provides concrete task JSON per runtime — use those blocks directly.runtimes/{rt}.md§ Build Chain provides the dependency tasks that the startup task'sdependsOnreferences.
Service ID Derivation
Derive a canonical service ID from the plan's Service Label column: lowercase, kebab-case (e.g., "Functions API" → functions-api, "Web App" → web-app). This ID is used for:
- Task labels (e.g.,
functions-api: func host start) - Launch config naming (use the plan's Launch Config Name column directly)
- Compound config member references
If two services resolve to the same ID, append the project type: payments-api-functions.
⛔ Every generated task label should conform to
{service-id}: {task name}(e.g.,functions-api: func host start,functions-api: dotnet build). Wherever a task label is referenced — generation blocks,dependsOnchains,preLaunchTaskvalues, validation Ready-Signal tables, and validation checklists — it MUST use this{service-id}:form. Instruction files and any examples that show a label without the{service-id}:prefix added are illustrating the latter part of the label; resolve it to the full form before writing or matching.
Task Chain Shape (Server-side only)
Browser-based projects (e.g., Frontend SPA) skip the build chain — the dev server task is the only task. See
project-types/{type}.md§ VS Code Task Configuration.
"{service-id}: {top-level-task}" ← project-type-specific (see project-types/{type}.md)
├── dependsOn: "{service-id}: {watch-task}" ← from runtimes/{rt}.md
│ └── dependsOn: "{service-id}: {clean-task}"
│ └── dependsOn: "{service-id}: {install-task}"
└── dependsOn: "Start Emulators" ← only when emulators are required
Adjust task labels and commands for alternative package managers (
yarn,pnpm,gradle). The key invariant is the chain shape: install → clean → build/watch → top-level task (withStart Emulatorsas a sibling dependency of the top-level task, NOT nested under install). Some runtimes skip steps — use only what applies.
Project Type Path Resolution
Most project types have a single reference file at project-types/{type}.md. Some use a subdirectory:
| Project Type | Reference Path |
|---|---|
functions |
project-types/functions.md |
frontend-spa |
project-types/frontend-spa/frontend-spa.md |
When instructions reference project-types/{type}.md, resolve via this table. If the type is not listed, look for project-types/{type}.md first, then project-types/{type}/{type}.md.
Working Directory (cwd) Rules
⚠️ CRITICAL for multi-service repos. Without correct
cwd, commands likenpm installorfunc host startwill run from the workspace root and fail.
Use the Service Root column from the plan's Services table to determine the cwd for each task.
| Task Scope | cwd Setting |
Example |
|---|---|---|
| Per-service tasks (install, clean, watch, build, top-level) | "options": { "cwd": "${workspaceFolder}/{service-root}" } |
"cwd": "${workspaceFolder}/api" |
| Shared tasks (Start Emulators) | Workspace root (omit cwd — it defaults to workspace root) |
— |
| Single-service repos | Omit cwd — workspace root is the service root |
— |
Task runOptions Rules
Every task in tasks.json must include runOptions with instanceLimit: 1 and instancePolicy: "silent" — install, clean, watch, build, top-level, emulator, and the sequenced compound task from multi-service.md § Compound Debug Configuration. There is no task type this is optional for; if you are writing a "label", you are writing runOptions beside it.
This prevents duplicate task instances and silently skips re-invocations when a task is already running (e.g., from compound + individual preLaunchTask chains). The compound task is the one that needs it most, not least: it is reachable both directly and as a preLaunchTask, so it is the likeliest to be invoked twice.
Start Emulators Task
When the plan includes emulators, generate a shared Start Emulators task. This task is a sibling dependency of each service's top-level startup task (e.g., func host start). Do NOT place Start Emulators as a dependency of build chain tasks like npm install or npm watch — it belongs in the startup task's dependsOn array alongside the build chain prerequisite.
Use the plan's Compose Command for the task command — docker compose up -d by default, or podman compose up -d when the plan's Orchestrator selected Podman.
{
"type": "shell",
"label": "Start Emulators",
"command": "docker compose up -d",
"problemMatcher": [],
"runOptions": { "instanceLimit": 1, "instancePolicy": "silent" }
}
instanceLimit and instancePolicy
Set instanceLimit: 1 and instancePolicy: "silent" on every task. You never want parallel instances of the same build or startup task, and "silent" ensures that duplicate invocations are skipped without prompting the user.
Problem Matchers
Background tasks (isBackground: true) MUST have a real problemMatcher. An empty matcher ("problemMatcher": []) on a background task causes a blocking VS Code dialog ("This task is tracked by a problem matcher"). Look up the correct matcher from the relevant reference file:
- Runtime tasks (build, watch) →
runtimes/{rt}.md§ VS Code Problem Matchers - Project-type tasks (top-level startup) →
project-types/{type}.md§ VS Code Task Configuration - Frontend dev servers →
project-types/frontend-spa/frontend-spa.md§ Framework Lookup Table
For non-background tasks:
| Task Type | Matcher |
|---|---|
Short-lived commands (npm install, npm clean, docker compose up -d) |
"problemMatcher": [] |
Dependency-only tasks (only dependsOn, no command) |
Omit problemMatcher entirely |
Short-lived commands use an empty matcher to suppress matching on tasks that don't produce compiler-style output.
Example
{
"type": "shell",
"label": "npm install",
"command": "npm install",
"runOptions": { "instanceLimit": 1, "instancePolicy": "silent" },
"problemMatcher": []
}
VS Code Extension Recommendations (.vscode/extensions.json)
Aggregate extension recommendations from the detected runtime and project type into .vscode/extensions.json. Each source lists its required extensions in a ## VS Code Extension Recommendations section with an Extension ID | Why Required table.
Assembly Protocol
| Step | Action | Details |
|---|---|---|
| 1. Collect | Gather from runtime | Read extension IDs from runtimes/{rt}.md § VS Code Extension Recommendations |
| 2. Collect | Gather from project type | Read extension IDs from project-types/{type}.md § VS Code Extension Recommendations |
| 3. Deduplicate | Remove duplicates | Each extension ID appears once in the final list |
| 4. Write | Output .vscode/extensions.json |
Contribute to the file — do not replace existing entries |
Output Format
{
"recommendations": [
"{runtime-extension-1}",
"{project-type-extension-1}"
]
}
VS Code Workspace Settings (.vscode/settings.json)
Aggregate workspace settings from the detected runtime, project type, and emulator configuration into .vscode/settings.json. Each source lists its contributed settings in a ## VS Code Workspace Settings section with a Setting | Value | Why table.
Assembly Protocol
| Step | Action | Details |
|---|---|---|
| 1. Collect | Gather from runtime | Read settings from runtimes/{rt}.md § VS Code Workspace Settings |
| 2. Collect | Gather from project type | Read settings from project-types/{type}.md § VS Code Workspace Settings |
| 3. Collect | Gather emulator exclusions | Derive data directory exclusions from docker-compose.yml volumes: mounts |
| 4. Collect | Gather required debug settings | Add the mandatory keys from generate.md § Required Debug Settings |
| 5. Write | Output .vscode/settings.json |
Merge into the file — contribute without replacing existing entries or user customizations |
Required Debug Settings
Always merge these keys into the workspace .vscode/settings.json on every run which is workspace scope only. Preserve any existing entries; if a key is already present, leave its value untouched.
| Setting | Value | Why |
|---|---|---|
debug.onTaskErrors |
"debugAnyway" |
Suppresses VS Code's blocking "task errors" modal on F5, which can appear as a project launching blocker when it's often not. |
{
"debug.onTaskErrors": "debugAnyway"
}
Emulator Data Directory Exclusions
When emulators are configured with workspace bind mounts (e.g. Azurite's ./.azurite:/data), add their data directories to both files.exclude and search.exclude in .vscode/settings.json to reduce workspace noise:
{
"files.exclude": {
"**/.azurite": true
},
"search.exclude": {
"**/.azurite": true
}
}
Derive directory names from the actual bind-mount
volumes:entries indocker-compose.yml(a./.name:/pathhost mount) — do not hardcode. Named volumes (e.g. Postgres'spostgres_data) live inside the container engine, not the workspace, so they need no exclusion. Each emulator's data pattern is defined inemulators/{name}.md.