Subchapter 8.21
references/subagent-validate.mdMarkdown7 KBView on GitHub
Validate IaC syntax, write scaffold-manifest.json, and generate deploy checklist. Follow the workflow below.
{"skill": "azure-validate"}, {"skill": "azure-deploy"}, {"skill": "azure-prepare"}, or any other skill call. Use the procedures in THIS file only.bicep build / terraform validate), never az deployment sub create.what-if or terraform plan — deploy runs the mandatory what-if with real secret params. Scaffold validates syntax only.| Field | Required |
|---|---|
IaC file paths (all generated .bicep or .tf files) | YES |
| Self-review findings from Steps 6–9 | YES |
prepare-plan.json — services, naming, region, subscriptionId | YES |
prereq-output.json.warnings[] — prereq warnings with fixPhase | YES |
prereq-output.json.healthEndpoint — detected health path (or null) | YES |
| Conformance result JSON (from main-thread Step 10a-conf) | YES |
| Artifact | Location |
|---|---|
scaffold-manifest.json | Session folder |
deploy-result.json skeleton | Session folder |
| Validation result status | Return to caller: Validated or Failed |
| Deploy checklist | .copilot-azure/sessions/{id}/deploy-checklist.md |
Do: Understand the ScaffoldManifest interface (field names, types, required fields) and the validation sequence.
Do:
az bicep build --file infra/main.bicep --stdout > $null (Bicep) or terraform validate (TF). Process output for BCP errors and warnings. Record pass/fail.Do: Verify every managed identity ↔ resource pair in the IaC has a corresponding Microsoft.Authorization/roleAssignments resource with the correct role GUID. Cross-reference with the review findings from Steps 6–9 input.
Skip if no Container Apps in the plan.
For each Container App resource in the generated Bicep:
cpu (must be type string) + memory is one of: 0.25/0.5Gi, 0.5/1Gi, 0.75/1.5Gi, 1/2Gi, 1.25/2.5Gi, 1.5/3Gi, 1.75/3.5Gi, 2/4Gi. FIXABLE: adjust to nearest valid combo (use smallest valid combo for sidecars/companions).secretRef in container env vars must have a matching entry in configuration.secrets[]. Every KV secret URL in secrets[] must reference a Microsoft.KeyVault/vaults/secrets resource that exists in the generated modules. Missing secret resource → FIXABLE: add it to the KV module.prereq-output.json.healthEndpoint is non-null, verify probePath matches it. If null AND any plainEnvVars entry is named BASE or PATH_PREFIX, verify probePath starts with that value (not bare /). If null AND no BASE var: verify the app has a route handler for the probe path (check source entry point for app.get('/') or framework root handler) — bare / on a REST API with only sub-path routes (e.g., /users, /messages) returns 404 and blocks revision activation. FIXABLE: update probePath to a known GET endpoint from the app.FIXABLE errors: fix the Bicep → re-run az bicep build → proceed to Step 3c.
Skip if no App Service or Functions in the plan.
For each App Service / Functions resource in the generated Bicep:
basicPublishingCredentialsPolicies/scm (with allow: true) and basicPublishingCredentialsPolicies/ftp (with allow: false). Missing → FIXABLE: add the child resources per bicep-patterns-security.md § Publishing Credential Lockdown.uniqueString() or a unique suffix (not a hardcoded literal). Hardcoded names cause global collisions. Missing → FIXABLE: wrap name with uniqueString(resourceGroup().id).FIXABLE errors: fix the Bicep → re-run az bicep build → proceed to Step 3c.
The main thread (SKILL.md Step 10a-conf) already ran the conformance script and passed you its JSON. Record it in scaffold-manifest.json.conformance = { passed, failures, source: "script" }. ⛔ Do NOT set validationResult.status: "Validated" while any BLOCK failure is unresolved.
Fallback (only if the caller passed NO result AND infra/main.bicep exists — the gate is Bicep-only, skip for Terraform): run {scaffoldDir}/scripts/scaffold-conformance.ps1 -SessionPath "{sessionPath}" -InfraPath infra (or .sh on bash) yourself, then record with source: "script". Never hand-judge when a shell is available.
Read scaffold-schemas.ts for exact field names.
Do: Write scaffold-manifest.json to the session folder with: sessionId, scaffoldCompletedUtc, iacFormat, targetScope, entryPoint, parametersFile, files[], deployCommand, twoPhaseWiring (if Container Apps), phase2Steps (if applicable), selfReview (from caller input), validationResult (from Steps 2–3). Use the exact field names from scaffold-schemas.ts § ScaffoldManifest.
Read scaffold-healing-rules.md ONLY if validation failed.
Do: Classify errors as FIXABLE or BLOCKING. FIXABLE: auto-fix IaC → re-validate (max 3 attempts before asking user). BLOCKING: surface to user and halt. PLAN_LEVEL_CHANGE: requires re-approval — do NOT auto-fix.
Do: Check that .copilot-azure/sessions/{id}/deploy-checklist.md exists (written by the parallel checklist subagent at scaffold Step 5b). If missing, read deploy-checklist-template.md (opens in a new tab) and write it now as a fallback — fill {placeholders} from prepare-plan.json, delete non-applicable sections. This file survives conversation compaction
Read deploy-schemas.ts (opens in a new tab) — specifically the DeployResult interface.
Do: Create .copilot-azure/sessions/{id}/deploy-result.json conforming to the DeployResult interface. Populate fields from all session artifacts already written (prepare-plan.json, context.json, scaffold-manifest.json, prereq-output.json). Use sensible defaults for fields the deploy phase will fill later. The deploy main agent updates this file in-place at Step 8 with real values.
Do: Return validation status (Validated or Failed) to the caller. Confirm deploy-checklist.md exists. Keep status report ≤500 tokens.